Critical Bug in Codeforces: Broken AES encryption results in 403 Forbidden Error. (Solution)

Revision en6, by prophet_, 2020-07-14 12:23:51

After investigating an issue resulting in a 403 error when trying to access codeforces as described in this blog: https://codeforces.com/blog/entry/80065

I believe I have found the issue and the solution.

Codeforces uses a "slow aes" decryption function to require users to perform a non-trivial amount of computational work before they can access the site, presumably to protect against malicious users spamming the server. A parameter is given based on the user's IP address and the user must decrypt using this to generate a RCPC token in order to access the site.

Those experiencing the 403 error likely are victims of a bug that causes the last 2 characters (last byte in binary) to be deleted. You can confirm this by checking your RCPC token in your cookies. This token should be 32 characters, but is only 30 if you experience this bug.

The aes javascript implementation is from here: https://codeforces.com/aes.min.js

I believe the issue is with the function "unpadBytesOut". In the image below I am logging the "bytesOut" variable, which stores the final token, before and after this function.

                console.log("BEFORE" ,bytesOut.toString(), bytesOut.length);
                this.unpadBytesOut(bytesOut);
                console.log("AFTER" ,bytesOut.toString(), bytesOut.length);

Console Log

As you can see, in this particular case, the last byte has been deleted by this function. I have found that around 8% of randomly generated aes parameters (the one based on your ip) has this issue.

If you are having this issue, download the javascript and run it locally, after removing the line calling this function. I am also happy to generate the token for anyone who has difficulty doing it themselves. If you send me your response from codeforces.com without redirects and I can send you the corrected token. If you're on linux or max for example, you can send me the response to the command "curl codeforces.com". Note that this token won't compromise the security of your account as I believe it is purely to protect again a DDOS by verifying the IPs.

I hope MikeMirzayanov can get this fixed as soon as possible.

UPD: I believe the issue has now been resolved. The aes.min.js has been updated with an additional conditional in the previously broken unpadBytesOut function. Below is a diff of the new change:

Diff

UPD: I have written an ad hoc script that may serve as a potential foundation for fixing various cf tools broken by this. You can find more about this here: https://codeforces.com/blog/entry/80135

History

 
 
 
 
Revisions
 
 
  Rev. Lang. By When Δ Comment
en6 English prophet_ 2020-07-14 12:23:51 198
en5 English prophet_ 2020-07-14 09:44:35 279 UPD: The issue has been fixed!
en4 English prophet_ 2020-07-14 00:35:41 16
en3 English prophet_ 2020-07-13 07:33:44 3 Tiny change: 'our ip) have this issu' -> 'our ip) has this issu'
en2 English prophet_ 2020-07-13 06:59:20 220
en1 English prophet_ 2020-07-13 06:54:17 2209 Initial revision (published)