# Cookies Hacking
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - πŸŽ™οΈ Twitch πŸŽ™οΈ - πŸŽ₯ Youtube πŸŽ₯ * Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access to the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)! * Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family) * Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) * **Join the** [**πŸ’¬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.** * **Share your hacking tricks by submitting PRs to the** [**hacktricks repo**](https://github.com/carlospolop/hacktricks) **and** [**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud).
Find vulnerabilities that matter most so you can fix them faster. Intruder tracks your attack surface, runs proactive threat scans, finds issues across your whole tech stack, from APIs to web apps and cloud systems. [**Try it for free**](https://www.intruder.io/?utm\_source=referral\&utm\_campaign=hacktricks) today. {% embed url="https://www.intruder.io/?utm_campaign=hacktricks&utm_source=referral" %} *** ## Cookies Attributes ### Expires & Max-Age * `Expires` sets an expiry date for when a cookie gets deleted * `Max-age` sets the time in seconds for when a cookie will be deleted **(use this, it’s no longer 2009)** ### **Domain** The `Domain` attribute specifies **which hosts can receive a cookie**. If unspecified, the attribute **defaults** to the **same host** that set the cookie, _**excluding subdomains**_. **If `Domain` is** **specified**, then **subdomains are always included**. Therefore, specifying `Domain` is less restrictive than omitting it. However, it can be helpful when subdomains need to share information about a user. For example, if you set `Domain=mozilla.org`, cookies are available on subdomains like `developer.mozilla.org`. But if you don't, the cookie won't be sent to subdomains. If a **subdomain** `sub.example.com` **sets a cookie** with _domain_ attribute of **`.example.com`**, it will be **sent** on requests to the **parent domain.** ### **Path** The `Path` attribute indicates a **URL path that must exist in the requested URL to send the `Cookie` header**. The `%x2F` ("/") character is considered a directory separator, and subdirectories match as well. #### Order When 2 cookies have the **same name** the one that is sent is: * The one with the **longest path** matching the URL path * The **newest** one if both have the same path ### SameSite This will indicate to the browser if the **cookie** can be sent **from other domains**. It has 3 possible values: * **Strict**: The cookie will not be sent along with a request by third party websites. * **Lax**: The cookie will be sent along with the GET request initiated by third party websites. * **None**: The cookie is sent from any third party domain | **Request Type** | **Example Code** | **Cookies Sent When** | | ---------------- | ---------------------------------- | --------------------- | | Link | \\ | NotSet\*, Lax, None | | Prerender | \ | NotSet\*, Lax, None | | Form GET | \
| NotSet\*, Lax, None | | Form POST | \ | NotSet\*, None | | iframe | \ | NotSet\*, None | | AJAX | $.get("...") | NotSet\*, None | | Image | \ | NetSet\*, None | Table from [Invicti](https://www.netsparker.com/blog/web-security/same-site-cookie-attribute-prevent-cross-site-request-forgery/) and slightly modified.\ A cookie with _**SameSite**_ attribute will **mitigate CSRF attacks** where a logged session is needed. **\*Notice that from Chrome80 (feb/2019) the default behaviour of a cookie without a cookie samesite** **attribute will be lax** ([https://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/](https://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/)).\ Notice that temporary, after applying this change, the **cookies without a SameSite** **policy** in Chrome will be **treated as None** during the **first 2 minutes and then as Lax for top-level cross-site POST request.** ## Cookies Flags ### HttpOnly This avoids the **client** to access the cookie (Via **Javascript** for example: `document.cookie`) #### **Bypasses** * If the page is **sending the cookies as the response** of a requests (for example in a **PHPinfo** page), it's possible to abuse the XSS to send a request to this page and **steal the cookies** from the response (check an example in [https://hackcommander.github.io/pentesting-article-1/)](https://hackcommander.github.io/pentesting-article-1/) * This could be Bypassed with **TRACE** **HTTP** requests as the response from the server (if this HTTP method is available) will reflect the cookies sent. This technique is called **Cross-Site Tracking**. * This technique is avoided by **modern browsers by not permitting sending a TRACE** request from JS. However, some bypasses to this have been found in specific software like sending `\r\nTRACE` instead of `TRACE` to IE6.0 SP2. * Another way is the exploitation of zero/day vulnerabilities of the browsers. * It's possible to **overwrite HttpOnly cookies** by performing a Cookie Jar overflow attack: {% content-ref url="cookie-jar-overflow.md" %} [cookie-jar-overflow.md](cookie-jar-overflow.md) {% endcontent-ref %} * It's possible to use [**Cookie Smuggling**](./#cookie-smuggling) attack to exfiltrate these cookies ### Secure The request will **only** send the cookie in an HTTP request only if the request is transmitted over a secure channel (typically **HTTPS**). ## Cookies Prefixes **`__Secure-` prefix**: must be set with the `secure` flag from a secure page (HTTPS). **`__Host-` prefix**: must be set with the `secure` flag, must be from a secure page (HTTPS), must not have a domain specified (and therefore, are not sent to subdomains), and the path must be `/`. `__Host-` prefixed cookies cannot be sent to superdomains (cookies from subdomains to domains) or subdomains (cookies from domains to subdomains), so, if you want to isolate your application cookies, prefixing everything with `__Host-` is not a bad idea. ## Cookies Attacks If you find some kind of custom cookie containing sensitive data (sessionID, username, emails, etc.) you should definitely try to exploit it ### Decoding the cookie If the **cookie** is using some **Base encoding** (like Base64) or similar you may be able to **decode it**, **change** the **content** and **impersonate** arbitrary users. ### Session Hijacking Steal a cookie and use it to impersonate the user inside an application ### Session fixation The attacker gets a cookie from a web page and sends a link to the victim to **login using the very same cookie**. If the cookie is not changed when a user logs in, this could be useful because the attacker could be able to impersonate the user through a cookie. If you found an **XSS in a subdomain** or you **control a subdomain**, read: {% content-ref url="cookie-tossing.md" %} [cookie-tossing.md](cookie-tossing.md) {% endcontent-ref %} ### Session donation The attacker sends his own session to the victim. The victim will see that he is already logged in and will suppose that he is inside his account but **the actions will be performed inside the attacker's account**. If you found an **XSS in a subdomain** or you **control a subdomain**, read: {% content-ref url="cookie-tossing.md" %} [cookie-tossing.md](cookie-tossing.md) {% endcontent-ref %} ### [JWT Cookie](../hacking-jwt-json-web-tokens.md) Click on the previous link to access a page explaining possible flaws in JWT. ### Empty Cookie Browsers allow a cookie with an empty name ```js document.cookie = "a=v1" document.cookie = "=test value;" // empty name document.cookie = "b=v2" ``` This results in the sent cookie header: ``` a=v1; test value; b=v2; ``` More interestingly, if you have a vector that somehow lets you **set the empty cookie**, you can **control any other cookie**: ```js function setCookie(name, value) { document.cookie = `${name}=${value}`; } setCookie("", "a=b"); // this sets the empty cookie to a=b ``` Although internally in the browser, this is set as the empty named cookie, it will result in the **sent cookie header:** ``` a=b; ``` Meaning, every webserver will parse it as the cookie `a` being set to the value `b`. ### Chrome Bug - document.cookie corruption If a unicode surrogate codepoint is in a set cookie, `document.cookie` will be permanently corrupted and return an empty string. ```js document.cookie // "a=b;" document.cookie = "\ud800=meep"; document.cookie // "" ``` ### Cookie Smuggling Several webservers, including Java webservers Jetty, TomCat, Undertow, and the Python web framework Zope, as well as Python web servers/frameworks like cherrypy, web.py, aiohttp server, bottle, and webob, are found to **incorrectly parse cookie strings** due to leftover support for RFC2965, an outdated cookie quoting mechanism that uses RFC2616 for a quoted-string definition. Specifically, **these servers continue reading a cookie string when they encounter a double-quoted (dquoted) cookie value, even if a semicolon is encountered**. This is problematic because **semicolons are supposed to separate key-value** pairs in the cookie string. For instance, if a **browser sends three cookies, RENDER\_TEXT, JSESSIONID,** and **ASDF:** ```basic RENDER_TEXT="hello world; JSESSIONID=13371337; ASDF=end"; ``` these servers interpret them as part of a **single cookie value** rather than three separate cookies. This leads to a security risk: if an attacker gains cross-site scripting (XSS) access, they can use this bug to **exfiltrate sensitive cookies like HttpOnly cookies**. ### Cookie Injection Many webservers, including Java's Undertow, Python's Zope, and those using Python's stdlib http.cookie.SimpleCookie and http.cookie.BaseCookie, have been found to **incorrectly parse cookies, using wrong delimiters to start the next cookie name/value pair**. This allows an attacker to **spoof multiple cookies while only controlling one cookie value**. In **Undertow's** case, it begins parsing the next cookie immediately after the **end of a quoted** cookie value, without waiting for a semicolon: ```bash LANGUAGE="en-us" CSRF_TOKEN="SPOOFED_VALUE" ``` **Zope** start parsing the next cookie on a **comma**: ```bash LANGUAGE=en-us,CSRF_TOKEN=SPOOFED_VALUE ``` And **Python's SimpleCookie** and **BaseCookie** immediately start parsing the next cookie on a **space** character: ``` LANGUAGE=en-us CSRF_TOKEN=SPOOFED_VALUE ``` As a result, servers such as **cherrypy**, **web.py**, **aiohttp** server, **bottle**, and **webob** (Pyramid, TurboGears) are all vulnerable to this type of attack. This issue presents significant **security implications**. For instance, if a web application uses **cookie-based CSRF protection**, an attacker can **inject** a spoofed **CSRF-token cookie** to bypass this protection. Additionally, the last duplicate cookie name in Python's http.cookie packages overrides any previous ones, making this type of attack especially easy. Furthermore, the **spoofing** of **`__Secure-`** and **`__Host-`** cookies can be abused in an insecure context. Also, in a configuration where cookies are passed onto a backend server, **cookie injection could lead to authorization bypasses** if the backend server is susceptible to spoofing but the frontend server is not. ### Extra Vulnerable Cookies Checks #### **Basic checks** * The **cookie** is the **same** every time you **login**. * Log out and try to use the same cookie. * Try to log in with 2 devices (or browsers) to the same account using the same cookie. * Check if the cookie has any information in it and try to modify it * Try to create several accounts with almost the same username and check if you can see similarities. * Check the "**remember me**" option if it exists to see how it works. If it exists and could be vulnerable, always use the cookie of **remember me** without any other cookie. * Check if the previous cookie works even after you change the password. #### **Advanced cookies attacks** If the cookie remains the same (or almost) when you log in, this probably means that the cookie is related to some field of your account (probably the username). Then you can: * Try to create a lot of **accounts** with usernames very **similar** and try to **guess** how the algorithm is working. * Try to **bruteforce the username**. If the cookie saves only as an authentication method for your username, then you can create an account with username "**Bmin**" and **bruteforce** every single **bit** of your cookie because one of the cookies that you will try will the one belonging to "**admin**". * Try **Padding** **Oracle** (you can decrypt the content of the cookie). Use **padbuster**. **Padding Oracle - Padbuster examples** ```bash padbuster # When cookies and regular Base64 padbuster http://web.com/index.php u7bvLewln6PJPSAbMb5pFfnCHSEd6olf 8 -cookies auth=u7bvLewln6PJPSAbMb5pFfnCHSEd6olf # If Base64 urlsafe or hex-lowercase or hex-uppercase --encoding parameter is needed, for example: padBuster http://web.com/home.jsp?UID=7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6 7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6 8 -encoding 2 ``` Padbuster will make several attempts and will ask you which condition is the error condition (the one that is not valid). Then it will start decrypting the cookie (it may take several minutes) If the attack has been successfully performed, then you could try to encrypt a string of your choice. For example, if you would want to **encrypt** **user=administrator** ``` padbuster http://web.com/index.php 1dMjA5hfXh0jenxJQ0iW6QXKkzAGIWsiDAKV3UwJPT2lBP+zAD0D0w== 8 -cookies thecookie=1dMjA5hfXh0jenxJQ0iW6QXKkzAGIWsiDAKV3UwJPT2lBP+zAD0D0w== -plaintext user=administrator ``` This execution will give you the cookie correctly encrypted and encoded with the string **user=administrator** inside. **CBC-MAC** Maybe a cookie could have some value and could be signed using CBC. Then, the integrity of the value is the signature created by using CBC with the same value. As it is recommended to use as IV a null vector, this type of integrity checking could be vulnerable. **The attack** 1. Get the signature of username **administ** = **t** 2. Get the signature of username **rator\x00\x00\x00 XOR t** = **t'** 3. Set in the cookie the value **administrator+t'** (**t'** will be a valid signature of **(rator\x00\x00\x00 XOR t) XOR t** = **rator\x00\x00\x00** **ECB** If the cookie is encrypted using ECB it could be vulnerable.\ When you log in the cookie that you receive has to be always the same. **How to detect and attack:** Create 2 users with almost the same data (username, password, email, etc.) and try to discover some pattern inside the given cookie Create a user called for example "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" and check if there is any pattern in the cookie (as ECB encrypts with the same key every block, the same encrypted bytes could appear if the username is encrypted). There should be a pattern (with the size of a used block). So, knowing how are a bunch of "a" encrypted you can create a username: "a"\*(size of the block)+"admin". Then, you could delete the encrypted pattern of a block of "a" from the cookie. And you will have the cookie of the username "admin". ## References * [https://blog.ankursundara.com/cookie-bugs/](https://blog.ankursundara.com/cookie-bugs/)
Find vulnerabilities that matter most so you can fix them faster. Intruder tracks your attack surface, runs proactive threat scans, finds issues across your whole tech stack, from APIs to web apps and cloud systems. [**Try it for free**](https://www.intruder.io/?utm\_source=referral\&utm\_campaign=hacktricks) today. {% embed url="https://www.intruder.io/?utm_campaign=hacktricks&utm_source=referral" %}
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - πŸŽ™οΈ Twitch πŸŽ™οΈ - πŸŽ₯ Youtube πŸŽ₯ * Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access to the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)! * Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family) * Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) * **Join the** [**πŸ’¬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.** * **Share your hacking tricks by submitting PRs to the** [**hacktricks repo**](https://github.com/carlospolop/hacktricks) **and** [**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud).