I found out that TOR (/Firefox) is using a weak implementation of a (pseudo)random number generator. On form submission Firefox always sends an unique boundary delimiter together with the POST data. But this unique boundary string isn't so unique as it looks like.
For example, when you send a multipart form request the number is always the first time: 41184676334, 2nd time: 265001916915724, 3th time: 114782935826962, etc..
Try it yourself: build a multipart form and check the POST data:
<form action="/" method="post" enctype="multipart/form-data"> <input type="submit" value="Submit"> </form>
Content-Type: multipart/form-data; boundary=---------------------------41184676334 Content-Length: 63-----------------------------41184676334--
'''1) OS fingerprinting for Windows '''It looks like the implementation between Windows and Linux is different. Windows isn't seeding srand() calls. In this way we're 99% sure that boundary string with 41184676334, 265001916915724, 114782935826962 came from a Windows OS.
'''2) "track" form submissions between websites. '''On website_A I submit a form mulitple times. Now, the owner of website_B is able to read the boundary string and can check how many times a user submitted a form on website_A.
'''3) "track" form interactions on other websites. '''For example, I'm the owner of website_A, and website_B is a photo upload website. If the user goes from website_A to B and later he came back to my website, I'm able to know if the user uploaded a photo on the other website:
- website_A (boundary: 41184676334)
- website_B (??)
- website_A (boundary: 114782935826962)
As you can see only 265001916915724 is missing, so he did one action on the other website.
'''4) Fake boundaries for file uploads '''It is possible to inject fake data in a file and let you browser think that you've uploaded 2 files. In this way it is possible to upload 2 files by uploading only one. Of course it also depends on server side validation, but for the browser this seems to be okay. Example on Bugzilla
Technical analysis: The current implementation of the boundary delimiter in Firefox:
mBoundary.AssignLiteral("---------------------------"); mBoundary.AppendInt(rand()); mBoundary.AppendInt(rand()); mBoundary.AppendInt(rand());
As you can see RAND() is called without seeding this function. Every time you'll (re)start TOR, the browser also resets the seed. Without a good seed the output is of rand is always predictable. At least on Windows, I think Linux has a different implementation of PRNG.
A solution is to seed RAND() with the PID or something else that's not public (like dates or timestamps).
5 years ago there was also a discussion about this topic on Bugzilla: https://bugzilla.mozilla.org/show_bug.cgi?id=461204