Introduction
I participated in the Hack.LU CTF again this year with, just like in 2013, but now together with the great Team HacknamStyle from KU Leuven. We ended up 24th of 220 active teams by solving the CthCoin challenge (20 solves), among others:
CthCoin (Category: Crypto/Web)
Cthulhu awakens and all worshippers will be rewarded greatly! A new Cryptocurrency was created, and Cthulhu generous gives away free coins. Can you break it, but be careful do not provoke him.
First Impressions
One can register an account on the website, and receives 65 CthCoins for free. However, the flag, which is for sale in the shop, costs 120 coins:
A first simple attempt to use free CthCoins from another user hacknam1_ failed, yielding an error message indicating that we are not the owner of this CthCoin and thus are not allowed to spend it. Re-using our own spent CthCoins also yielded an error message. Attempting to modify other values in the JSON array yielded similar errors:
Then we found the first clue in robots.txt: endpoint /debugcoins. This showed a page with hashes. Upon viewing the source, it became apparent these were MD5 hashes, and there was some useful additional info in HTML comments at the bottom:
This information confirmed what we already thought: the system is based on ECDSA, and the signature is calculated over all logical fields of a CthCoin. The MD5 is calculated on all these fields also, as well as the SIG field which is correctly being validated when attempting to purchase something.
As ECDSA is known to be vulnerable to nonce reuse attacks, the Public Key was the same for all generated CthCoins from different users and the nonce seemed awfully small (6 digits), we initially investigated whether we could create enough accounts with free CthCoins to generate a collision. Given the birthday paradox, this seemed plausible and would have yielded the private key for us to create arbitrary CthCoins for ourselves. However, upon investigation, it seemed that not only the “NC” parameter was used as nonce, but also the “TS”, as prepending a zero to the “TS” field also yielded a malformed nonce error:
From hereon, we focused on bypassing the duplicate check instead. The /debugcoins page hinted on the fact that an MD5 hash comparison was being used to perform the duplicate check, which implied that modifying one character of any of the fields would be sufficient to bypass it. This reminded me of a vulnerability in Samsung found earlier by the great Matthew Bryant (Mandatory). So we started appending and prepending zeroes and spaces, replacing characters by their encoded equivalents, all to no avail:
However, finally we thought of changing the case of letters. This didn’t work with the Public Key (PK), but it did with the Signature (SIG) field! We successfully bypassed the check and could now re-use our 50 CthCoins two times again to purchase the flag:
Conclusion
Although a bit deceptive (Category Crypto?), this was definitely a fun challenge. Lessons learned: Properly validate your input, and never modify your data after validating it. Always throw an error when incoming data is not considered valid.