Tags: hash-length-extension unicode
Rating:
There are two endpoints in this challenge: `/new` and `/view`. We have to become admin to get the flag back from the server.
with `/new` we can create a note. We have to provide an author and the note content. The server signs our parameters using the SHA1 algorithm, and later in `/view` checks that the signature we provided is the same. The server also adds `admin=False, access_sensitive=False, entrynum=783` as default to our parameters before signing.
To get the flag, these parameters must be set as the following: `admin=True&access_sensitive=False&entrynum=7`
It looks like we can use a hash length extension attack to add some extra parameters at the end, and overwrite admin, access_sensitive and entrynum.
I used hashpumpy to solve this. I extended the id string with `&admin=True&access_sensitive=True&entrynum=7` and set `integrity` to the new sha1 string generated by hashpumpy. One problem I had for a long time is that the server raised exceptions because we send in raw bytes that it cannot utf8 decode. Encoding the string using `unicode-escape` did the trick!
script:
```python
import hashpumpy
import requests
from urllib.parse import quote
from base64 import b64encode, b64decode
url = 'http://crypto.chal.csaw.io:5003'
res = requests.post(url + '/new', data={"author": "zup", "note": "cool"})
print(res.text)
infostr = b64decode(res.text.split()[2].split(':')[0]).strip()
sha1 = res.text.split()[2].split(':')[1].strip()
print(sha1)
print(infostr)
# Bruteforce key length
for i in range(256):
newsign = hashpumpy.hashpump(sha1, infostr, "&admin=True&access_sensitive=True&entrynum=7", i)
print(newsign)
# We need to use unicode-escape because the server prints our extended string and will fail because of invalid utf8 characters
newid = newsign[1].decode('unicode-escape').encode('unicode-escape')
newsha = newsign[0]
print(newid)
print(newsha)
res = requests.post(url + '/view', data={'id': b64encode(newid), 'integrity': newsha})
print(res.text)
if 'Note' in res.text:
break
```