Tags: hash-length-extension unicode 


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!

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"})

infostr = b64decode(res.text.split()[2].split(':')[0]).strip()
sha1 = res.text.split()[2].split(':')[1].strip()

# Bruteforce key length
for i in range(256):
newsign = hashpumpy.hashpump(sha1, infostr, "&admin=True&access_sensitive=True&entrynum=7", i)

# 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]


res = requests.post(url + '/view', data={'id': b64encode(newid), 'integrity': newsha})

if 'Note' in res.text: