I was watching someone play Cookie Clicker and when they reloaded the tab, they still had all their save data. I’d never played Cookie Clicker before so I assumed it must be using cookies to retain that data, but when I loaded a Cookie Clicker tab on my browser, Firefox reported no cookies beyond the consent to store advertising cookies (Thanks for blocking trackers, Firefox).

[image lost]

So, what does Cookie Clicker use to store data? Browsers can store data in a few ways.

Cache storage is for storing responses to network queries. When a query is made, it’s stored as a request/response pair, and when that same query is to be made again, if it matches any cached queries, the browser can save on network usage by taking a cached response. Since Cookie Clicker is pretty much a local app once you load the page, this is probably not how it works.

Cookies are values passed and passed back in HTTP requests with the Set-Cookie header. They can either be for the duration of a session (i.e. deleted when the browser is closed) or persistent (expiring at a set time). Cookies must expire as per RFC 2965. Since we don’t want our Cookie Clicker cookie count expiring, this is probably a bad idea.

Indexed DB storage is storage of key:value pairs in a browser database. Webapps can interface with a created Indexed DB to retrieve this data. It could work for Cookie Clicker, but it’d be pretty complicated.

Local Storage is also storage of key:value pairs but doesn’t require the same code steps of spinning up a database and is generally much less complicated. This could also work for Cookie Clicker.

Session Storage is the same as local storage, except it has the same drawback of cookies in that it must eventually expire. This would not work for Cookie Clicker.

Our most likely candidate based on these types of storage is Local Storage. Opening the Local Storage tab shows us 2 values: CookieClickerGame and CookieClickerLang.

CookieClickerGame looks interesting. If we didn’t know what that was, we could feed it into Cyberchef magic, but most webapps store this kind of data as base64, so we’ll skip this step and feed it into a decoder directly.

And it appears that Cookie Clicker saves data as a base64 encoded semicolon, comma, and pipe delimited list. Probably a little jankier than it could have been if it used an Indexed DB, but it works and I’m not going to take the time to rewrite it. Anyway, now that we have this, if we know that we have exactly 42 cookies, with very little effort, we can change every instance of 42 to a very large number, re-encode the list, and feed it back into Firefox’s Local Storage.

PS. No XSS on bakery name. The characters are stored in the save file but sanitized in the UI.

Sources:

https://betterprogramming.pub/the-different-types-of-browser-storage-82b918cb3cf8

https://www.geeksforgeeks.org/how-to-set-up-a-cookie-that-never-expires-in-javascript/

http://www.faqs.org/rfcs/rfc2965.html

https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB

And of course,

https://orteil.dashnet.org/cookieclicker/