|
| 1 | +# Cookies |
| 2 | + |
| 3 | + |
| 4 | + |
| 5 | +The scratch website stores a number of cookies in your browser. |
| 6 | +These can be found in the 'Application' or 'Storage' section of your [browser's devtools](https://developer.mozilla.org/en-US/docs/Learn_web_development/Howto/Tools_and_setup/What_are_browser_developer_tools). |
| 7 | +They are officially documented [here](https://mitscratch.freshdesk.com/en/support/solutions/articles/4000219342-cookies-policy) |
| 8 | + |
| 9 | +## scratchsessionsid |
| 10 | + |
| 11 | +The main cookie of significance here is the `scratchsessionsid` cookie, which is used to authenticate requests. |
| 12 | +This means that it is required for many account actions - like posting comments, following users, or viewing your unshared projects. |
| 13 | + |
| 14 | +According to the official cookies documentation, the `scratchsessionsid` cookie takes 2 years to expire, which actually means that many scripts use it as their only authentication method (instead of a username and password) |
| 15 | +The [scratchattach library](https://github.com/TimMcCool/scratchattach/) provides functionality for logging in directly with a session id, or by generating one using your username and password. |
| 16 | + |
| 17 | +### Content |
| 18 | + |
| 19 | +It actually turns out that the `scratchsessionsid` cookie contains information encoded in a urlsafe-base64 zlib-compressed/base62/hash format. |
| 20 | + |
| 21 | +This is [documented in django](https://github.com/django/django/blob/7b32485ee98edf7e8b94ad9c8acdccee562bf216/django/core/signing.py). |
| 22 | + |
| 23 | +[Python implementation of a sessionid decoder](https://github.com/TimMcCool/scratchattach/blob/d52f5ecbcb86a072ea9325cf255811dc2711c08f/scratchattach/site/session.py#L1130-L1156) |
| 24 | + |
| 25 | +There are 3 sections of the cookie, separated by colons. We can name these p1, p2, p3. |
| 26 | + |
| 27 | +#### p1 |
| 28 | + |
| 29 | +This contains most of the data in the session id. It is actually a JSON object, which has been stringified, then zlib-compressed, then urlsafe base64 encoded (with padding removed). |
| 30 | +Do note that this part is actually only zlib compressed if it begins with a `.` symbol. In all cases in scratch so far, it has not been observed, but you may want to keep this in mind. |
| 31 | + |
| 32 | +In python, it can be decoded with `zlib`, `base64`, and `json` like so: `json.loads(zlib.decompress(base64.urlsafe_b64decode(p1+"==")))` |
| 33 | + |
| 34 | +Output (partially redacted): |
| 35 | +`{'username': 'faretek0', 'token': '<some hash>:<some other hash>', 'login-ip': '123.45.678.910', '_auth_user_id': '160388196', 'django_timezone': 'America/New_York', '_auth_user_hash': '<a hash value>', 'testcookie': 'worked', '_auth_user_backend': 'authentication.backends.ReplicationBackend'}` |
| 36 | + |
| 37 | +You would notice that this contains certain information (your IP) which you likely do not want to be public. |
| 38 | +It could be considered more dangerous to have a leaked session-id compared to a leaked password, from a privacy standpoint - although there are other concerns here, like the fact that that one can view an email address of an account given the username and password. |
| 39 | + |
| 40 | +#### p2 |
| 41 | + |
| 42 | +This is a [base62-encoded](https://github.com/TimMcCool/scratchattach/blob/d52f5ecbcb86a072ea9325cf255811dc2711c08f/scratchattach/utils/commons.py#L256-L263) unix timestamp of the login time. |
| 43 | +To convert this to a python datetime object, use `datetime.fromtimestamp`. |
| 44 | + |
| 45 | +### p3 |
| 46 | + |
| 47 | +This is probably some authentication hash of some kind. |
0 commit comments