BugForge — 2026.03.30

Cheesy Does It: SQL Injection Authentication Bypass

BugForge SQL Injection medium

Overview

  • Platform: BugForge
  • Vulnerability: SQL Injection (Authentication Bypass), Client-Side Price Manipulation
  • Key Technique: Classic SQLi on login username field — string concatenation in SQL query allows OR 1=1 tautology to bypass authentication and return admin session
  • Result: Full authentication bypass as admin (id:1), flag captured from login response

Objective

Find and exploit vulnerabilities in a pizza ordering web application (same app as prior weeks, new instance).

Initial Access

# Target Application
URL: https://lab-1774911155697-8ep208.labs-app.bugforge.io

# Auth details
Registered user: standard registration
Auth mechanism: JWT HS256 (payload: {id, username, iat})
Admin access obtained via SQLi bypass

Key Findings

  1. SQL Injection on Login (CWE-89: Improper Neutralization of Special Elements used in an SQL Command) — The username parameter in POST /api/login is interpolated directly into a SQL query via string concatenation. Injecting admin' OR 1=1-- bypasses authentication entirely and returns a valid admin session with the flag.

  2. Client-Side Price Manipulation (CWE-602: Client-Side Enforcement of Server-Side Security) — Server trusts client-supplied unit_price and total_price in POST /api/orders. Also trusts client-supplied amount in POST /api/payment/process. Accepted $0 and negative values.


Attack Chain Visualization

┌──────────────┐     ┌───────────────────────────┐     ┌──────────────┐
│  Register    │     │ Extract API routes from   │     │  Test SQLi   │
│  account,    │────>│ JS bundle recon           │────>│  on /api/    │
│  map surface │     │ (main.db402bda.js)        │     │  login       │
└──────────────┘     └───────────────────────────┘     └──────┬───────┘
                                                              │
                                                              v
                                              ┌───────────────────────────┐
                                              │  POST /api/login          │
                                              │  {"username":             │
                                              │   "admin' OR 1=1--",      │
                                              │   "password":"x"}         │
                                              └─────────────┬─────────────┘
                                                            │
                                                            v
                                              ┌───────────────────────────┐
                                              │  Server returns:          │
                                              │  - Admin JWT (id:1)       │
                                              │  - role: admin            │
                                              │  - FLAG in success field  │
                                              └───────────────────────────┘

Application Architecture

Component Path Description
Frontend React SPA (main.db402bda.js) Material UI pizza ordering interface
Backend Express/Node.js REST API, JWT auth
Database SQLite (assumed, sequential IDs) User and order storage
Auth JWT HS256 Token has {id, username, iat} — no role claim, role is DB-side

Exploitation Path

Step 1: Reconnaissance — Map the API Surface

Registered an account and captured traffic to enumerate all API endpoints. Additionally extracted routes from the bundled JavaScript file (main.db402bda.js).

Key endpoints discovered:

  • POST /api/register — User registration
  • POST /api/login — Authentication
  • GET /api/verify-token — Token validation
  • PUT /api/profile — Profile updates
  • POST /api/orders — Order creation (accepts client-supplied prices)
  • POST /api/payment/validate / POST /api/payment/process — Payment flow
  • GET /api/admin/* — Admin endpoints (stats, users, orders)
  • GET /api/menu/* — Menu data (pizzas, bases, sauces, toppings)

Key observations:

  • JWT contains {id, username, iat} with no role — role stored server-side only
  • Admin endpoints return 403 for regular users (properly enforced)
  • Price calculation is entirely client-side with server trusting submitted values

Step 2: Test Admin Escalation Paths (Dead Ends)

Tested several privilege escalation approaches before finding the SQLi:

Mass assignment — Attempted adding role, is_admin, admin, userRole fields to both POST /api/register and PUT /api/profile. All extra fields silently ignored.

JWT manipulation — Tested none algorithm (returned “Invalid token”). Brute-forced 10 common secrets — all returned 403. JWT secret never cracked.

NoSQL injection — Tested $gt operator on login — returned 400.

Double-quote SQLi — Tested admin" OR 1=1-- — returned 400 Invalid credentials (query uses single quotes).

Step 3: SQL Injection on Login

Tested single-quote based SQL injection on the username field:

POST /api/login HTTP/1.1
Host: lab-1774911155697-8ep208.labs-app.bugforge.io
Content-Type: application/json

{"username":"admin' OR 1=1--","password":"x"}

The server concatenates the username directly into the SQL query (e.g., SELECT * FROM users WHERE username='<input>' AND password='...'). The injected payload transforms the query into:

SELECT * FROM users WHERE username='admin' OR 1=1--' AND password='x'

The OR 1=1 tautology causes the query to return all rows. The first row is the admin user (id:1), so the server issues a valid admin JWT and returns the flag in the success response field.

Step 4: Flag Captured

The login response included:

  • Valid admin JWT (id:1, username:admin)
  • User object with role: admin
  • Flag in the success field
bug{tNcu9Rw6Y7ou89Z4TX3OqYzAmrPcz5rv}

Step 5: Price Manipulation (Bonus Finding)

Also confirmed the server has no server-side price validation:

POST /api/orders HTTP/1.1
Authorization: Bearer <jwt>
Content-Type: application/json

{"items":[{"pizza_id":1,"base_id":1,"sauce_id":1,"toppings":[1],
  "unit_price":0,"quantity":1}],"total_price":0,
  "delivery_address":"123 Free St","phone":"555-0000"}

Accepted with unit_price: 0 and total_price: 0. Also accepted negative values. Payment processing endpoint (POST /api/payment/process) similarly accepted amount: 0 and amount: -100.


Flag / Objective Achieved

bug{tNcu9Rw6Y7ou89Z4TX3OqYzAmrPcz5rv}

Obtained from the login response after SQLi authentication bypass as admin.


Key Learnings

  • Always test SQLi on login forms — Even in 2026, string concatenation in authentication queries exists. Login forms are high-value SQLi targets because successful injection yields immediate session access, not just data leakage.
  • Single vs. double quote matters — Double-quote injection returned a generic 400, while single-quote injection worked. This indicates the SQL query wraps the value in single quotes. Testing both quote types is essential.
  • Inconsistent security posture is a signal — This application uses parameterized queries on the orders endpoint but string concatenation on login. When you find one well-protected endpoint, don’t assume all endpoints are equally hardened.

Failed Approaches

Approach Result Why It Failed
Mass assignment (role=admin) on register/profile Fields silently ignored Server only accepts known profile fields
JWT none algorithm “Invalid token” Server validates algorithm header
JWT secret brute force (10 common secrets) All returned 403 Secret is not a common/weak value
NoSQL injection ($gt operator) 400 Bad Request Backend uses SQL, not MongoDB
Double-quote SQLi on login 400 Invalid credentials SQL query uses single-quote string delimiters
Price manipulation for flag trigger Orders accepted but no flag Price bugs are incidental, flag tied to auth bypass
IDOR on /api/orders/:id Only own orders (1-5), order 6 = 404 No other user orders exist to access

Tools Used

Tool Purpose
Caido HTTP interception and request editing (Session 49)
Browser DevTools JS bundle analysis for API route extraction

Remediation

1. SQL Injection on Login (CVSS: 9.8 - Critical)

Issue: The login query concatenates user-supplied username directly into the SQL string, allowing injection of arbitrary SQL. CWE Reference: CWE-89 - Improper Neutralization of Special Elements used in an SQL Command (‘SQL Injection’)

// BEFORE (Vulnerable)
app.post('/api/login', async (req, res) => {
  const { username, password } = req.body;
  const query = `SELECT * FROM users WHERE username='${username}' AND password='${password}'`;
  const user = await db.get(query);
  // ...
});

// AFTER (Secure)
app.post('/api/login', async (req, res) => {
  const { username, password } = req.body;
  const user = await db.get(
    'SELECT * FROM users WHERE username = ? AND password = ?',
    [username, password]
  );
  // ...
});

Additional hardening: Use bcrypt or argon2 for password hashing instead of storing/comparing plaintext passwords. Parameterized queries eliminate the injection vector entirely.

2. Client-Side Price Manipulation (CVSS: 8.1 - High)

Issue: Server trusts client-supplied unit_price and total_price in order creation. Payment processing also trusts client-supplied amount. CWE Reference: CWE-602 - Client-Side Enforcement of Server-Side Security

// BEFORE (Vulnerable)
app.post('/api/orders', authenticate, async (req, res) => {
  const { items, total_price } = req.body;
  await db.createOrder({ user_id: req.user.id, items, total_price });
});

// AFTER (Secure)
app.post('/api/orders', authenticate, async (req, res) => {
  const { items, delivery_address, phone } = req.body;
  const pricedItems = await Promise.all(items.map(async (item) => {
    const base = await db.getBase(item.base_id);
    const sauce = await db.getSauce(item.sauce_id);
    const toppings = await db.getToppings(item.toppings);
    const unit_price = calculatePrice(base, sauce, toppings, item.size);
    return { ...item, unit_price };
  }));
  const total_price = pricedItems.reduce(
    (sum, i) => sum + i.unit_price * i.quantity, 0
  );
  await db.createOrder({ user_id: req.user.id, items: pricedItems, total_price });
});

OWASP Top 10 Coverage

  • A03:2021 - Injection — SQL injection on login endpoint via string concatenation
  • A04:2021 - Insecure Design — Client-side price enforcement with no server-side validation

References


Tags: #sqli #authentication-bypass #price-manipulation #injection #bugforge #api-security Document Version: 1.0 Last Updated: 2026-03-30

#authentication-bypass #price-manipulation #login-bypass