So it’s clear that the ‘hash’ parameter must be an hex-encoded sha-1.
To summarize: we need to provide constrained username and password and unconstrained hash, such that the “signature” is valid.
The problem is that we don’t know salt and pepper, which are the secrets for the signature: in fact this is a “baby HMAC”.
But if we look at the first lines of the source code, we see that we are provided with:
length of both salt and pepper;
MD5(salt);
SHA1(pepper).
Having MD5(salt) is equal to having a signature made with the salt for an empty message, and the same holds for SHA1(pepper).
Making some research about attacks against cryptographic hash functions, we found that what we were looking for was an hash length extension attack.
We found an implementation, along with a detailed explanation, here.
Exploit
In these cases it’s useful to modify the challenge source code to make some local tests first.
We modify the first lines like that:
At this point, we play a little bit with hash_extender from command line to see how it works, and to check if we can forge valid signatures, with some known secrets.
After that we write an exploit which can work both locally and remotely:
the first call to hash_extender is to generate a valid MD5 signature with the username; we take from the output the generated signature and the generated username, which contains a certain number of bytes used to perform the attack and the actual username that we desired to append;
the second call to hash_extender is to generate the final SHA1 signature, which must contain the password and the MD5 signature hex-encoded; from the output we take the generated signature and password.
In both cases, the ‘data’ (-d) parameter is empty because we have the hashes of salt and pepper, which are like signatures for empty messages, like we said before.