Skip to main content

Power Cookie picoCTF 2022 Solution

The page decides admin status from a single cookie value, so flip it from guest to admin and reload.

Published: July 20, 2023Updated: August 25, 2026

Description

The site sets an isAdmin cookie to 0 when you continue as guest. Flip it to 1 and reload /check.php to see the flag.

Web

Click “Continue as guest” to set the cookie or create it manually in DevTools.

Open the browser’s storage view, change isAdmin from 0 to 1.

Refresh /check.php; the server now treats you as admin and prints the flag.

Solution

Want to try it yourself first?

The guided walkthrough reveals hints one step at a time.

Walk me through it
  1. Step 1Inspect the JavaScript
    Observation
    The site offers a continue-as-guest button and the description mentions an isAdmin cookie. Read the page source, or DevTools, to confirm the cookie's name and starting value before tampering with it.
    The main page shows the onclick handler that creates isAdmin=0, so you know which cookie name to modify.
    What didn't work first

    Tried: Opening the Elements panel in DevTools to find the cookie name.

    The Elements panel shows the live DOM, not cookie storage and not JavaScript source. Cookies live under the Application tab in Chrome or Storage in Firefox. Read the handlers in the Sources panel, or from View Page Source.

    Tried: Searching the page source for 'flag' or 'admin' text directly.

    The flag is not in the HTML source; the server only returns it once the cookie passes the authorization check. What the source gives you is the cookie's name and starting value, so you know what to change.

    Learn more

    HTTP cookies are small key-value strings that browsers store and automatically send with every request to the matching domain. Servers use them for session management, user preferences, and authentication state. Because cookies live in the browser, users have full read and write access to them via DevTools or JavaScript.

    In this challenge, the developer made a classic mistake: trusting a client-controlled value (isAdmin=0) for an authorization decision. The server should never rely on data from the client alone to determine privilege levels. Any value the client sends can be forged.

    To inspect cookies in Chrome or Firefox, open DevTools (F12), go to the Application tab (Chrome) or Storage tab (Firefox), and expand the Cookies section. You can double-click any value to edit it directly.

    Cookies can also be manipulated via JavaScript in the browser console. Running document.cookie = "isAdmin=1" creates or overwrites the cookie immediately without needing the Application tab. This technique is useful when the DevTools storage panel is cumbersome or when you need to set multiple cookies quickly during a competition. However, cookies marked with the HttpOnly flag cannot be accessed this way - they are invisible to JavaScript and must be edited through the DevTools storage panel directly.

    For command-line-based testing, curl allows you to specify custom cookies with -b "isAdmin=1" and inspect the full HTTP response without a browser. This is faster for scripted testing and lets you see raw response headers that browsers sometimes obscure. The combination of browser DevTools for initial exploration and curl for precise, repeatable requests is a standard web testing workflow.

  2. Step 2Toggle the cookie
    Observation
    The onclick handler sets isAdmin to 0. That is a simple truthy check on the server, so flipping the value to 1 should unlock the privileged response.
    Edit the cookie value (or create a new isAdmin=1 cookie) and revisit /check.php to read the flag.
    What didn't work first

    Tried: Typing document.cookie = 'isAdmin=1' in the browser console and then reloading the same index page instead of /check.php.

    The cookie change takes effect immediately, but the flag is only returned by /check.php - not the main landing page. After setting the cookie, you must navigate to /check.php (or reload it if already there) to see the server's privileged response.

    Tried: Deleting the isAdmin cookie entirely instead of changing its value to 1.

    With no cookie at all, the server has no isAdmin signal and falls back to treating you as a guest, so no flag. It checks for the value 1 specifically, which means the cookie has to be present and set, not missing.

    Learn more

    Cookie tampering is one of the simplest web attack techniques. Because browsers freely expose cookie storage to the user, any client-side authorization check is trivially bypassed. Proper implementations use signed sessions - the server cryptographically signs the session data so any modification is detected.

    Secure cookie practices include: setting the HttpOnly flag to prevent JavaScript access, the Secure flag to enforce HTTPS-only transmission, and SameSite=Strict to prevent cross-site request forgery. However, none of these prevent a user from modifying their own cookie value in DevTools.

    The real fix is server-side session validation: store the admin flag in a server-side session keyed by a random, unpredictable session token. The token itself is useless without the server's session data, so tampering with the cookie value achieves nothing.

    Many modern frameworks handle this correctly by default. Express.js (Node) uses express-session with a server-side store; Django stores session data in the database and sends only a signed session key; PHP's built-in sessions write data to the server filesystem. The pattern is always the same: the cookie holds a random identifier, and all sensitive state lives server-side under that key.

    JWT (JSON Web Tokens) are a related technology that encodes claims (including roles and permissions) directly in the token - but crucially, tokens are signed with a secret key. Any tampering with the payload invalidates the signature, so the server can detect and reject modified tokens. However, JWTs have their own pitfalls: the alg: none attack, weak signing keys, and improper signature verification have all been sources of real vulnerabilities. Cookie-based authentication is not inherently weaker than JWTs - both require careful implementation.

Interactive tools
  • Flask Session DecoderDecode Flask / itsdangerous session cookies. Splits payload, decompresses zlib, parses JSON, and verifies the HMAC signature when given the secret.

Flag

Reveal flag

picoCTF{gr4d3_A_c00k13_65fd1...}

Cookie tampering is a common beginner attack; always validate privilege server side.

Key takeaway

Authorization has to be decided server-side, from state the server controls, never from a value the client supplies. Cookies are fully user-editable, so a privilege flag stored in one lets any visitor elevate their own access without a password. Keep session state on the server behind an unpredictable token: the cookie carries only that opaque token, and the server looks up what role it represents.

Related reading

Tools used in this challenge

Where to go next