Semantic API Fuzzing
Beyond Random Bytes
Traditional API fuzzing sends random bytes and mutated payloads. This finds crashes but rarely finds logic bugs. Semantic fuzzing uses AI to generate payloads that are structurally valid but test boundary conditions in the business logic.
The difference is intent. Random fuzzing asks "what happens if I send garbage?" Semantic fuzzing asks "what happens if I send something that looks valid but exploits a specific vulnerability class?"
Fuzzing Technique Comparison
| Technique | Example Payload | What It Finds |
|---|---|---|
| Random fuzzing | { "name": "x\x00\xff\xfe" } |
Buffer overflows, encoding errors |
| Schema-aware fuzzing | { "name": "", "price": -0.01 } |
Validation bypasses |
| Semantic fuzzing (AI) | { "name": "'; DROP TABLE products;--", "price": 0.001, "category": "electronics\nclothing" } |
Injection, logic errors, edge cases |
| Context-aware fuzzing (AI) | { "name": "Test Product", "price": 99999999.99, "quantity": 2147483647 } |
Integer overflow, precision errors |
AI Fuzzing Categories
Category 1: SQL Injection Payloads
AI generates injection strings tailored to the field context:
[
{"name": "'; SELECT * FROM users; --", "price": 10},
{"name": "1 OR 1=1", "price": 10},
{"name": "admin'--", "price": 10},
{"name": "1; DROP TABLE products", "price": 10},
{"name": "' UNION SELECT password FROM users WHERE '1'='1", "price": 10}
]
Category 2: XSS Payloads
[
{"name": "<script>alert('xss')</script>", "price": 10},
{"name": "<img src=x onerror=alert(1)>", "price": 10},
{"name": "javascript:alert(1)", "price": 10},
{"name": "{{7*7}}", "price": 10},
{"name": "${7*7}", "price": 10}
]
Category 3: Boundary Values
[
{"name": "", "price": 0},
{"name": "A", "price": 0.01},
{"name": "A".repeat(200), "price": 99999999.99},
{"name": "A".repeat(201), "price": -0.01},
{"name": "A".repeat(10000), "price": 1e308}
]
Category 4: Type Confusion
[
{"name": 12345, "price": "not a number"},
{"name": true, "price": false},
{"name": null, "price": null},
{"name": ["array"], "price": {"object": true}},
{"name": "", "price": ""}
]
Category 5: Unicode Edge Cases
[
{"name": "Test\u200BProduct", "price": 10},
{"name": "Test\u202EProduct", "price": 10},
{"name": "Test\u0000Product", "price": 10},
{"name": "\uD800\uDC00", "price": 10},
{"name": "Test\u200B\u200B\u200B", "price": 10}
]
\u200B= zero-width space (invisible character in display)\u202E= right-to-left override (can reverse text display)\u0000= null byte (can truncate strings in C-based systems)
Category 6: Business Logic
[
{"name": "Widget", "price": 0.001, "quantity": -1},
{"name": "Widget", "price": 0, "discount_percent": 101},
{"name": "Widget", "price": 10, "quantity": 2147483647},
{"name": "Widget", "price": 10, "ship_date": "1970-01-01"},
{"name": "Widget", "price": 10, "ship_date": "9999-12-31"}
]
Category 7: Authorization Bypass (IDOR)
[
{"product_id": "other-users-product-id"},
{"user_id": "admin-user-id"},
{"order_id": "../../../etc/passwd"},
{"id": "0"},
{"id": "-1"}
]
Anomaly Detection
After sending fuzz payloads, you need to detect which responses indicate vulnerabilities:
def detect_anomaly(response, payload_info) -> str | None:
"""Detect if the response indicates a potential vulnerability."""
# 500 errors on any input = server-side failure (unhandled exception)
if response.status_code >= 500:
return f"Server error ({response.status_code}) on {payload_info['category']} payload"
# Reflection of injected content in response (XSS indicator)
if payload_info["category"] == "XSS":
if "<script>" in response.text or "onerror=" in response.text:
return "XSS reflection detected in response"
# SQL error messages in response (information disclosure)
sql_indicators = ["syntax error", "mysql", "postgresql", "sqlite",
"ORA-", "unterminated", "unexpected end"]
if any(indicator in response.text.lower() for indicator in sql_indicators):
return "Possible SQL error disclosure in response"
# Stack traces in response (information disclosure)
if "Traceback" in response.text or "at Object." in response.text:
return "Stack trace leaked in response body"
# Unexpected success on malicious input
if response.status_code == 200 and payload_info["category"] == "SQL_INJECTION":
return "SQL injection payload accepted without error -- verify data integrity"
# Sensitive data in error response
sensitive_patterns = ["password", "secret", "api_key", "token", "credentials"]
if any(p in response.text.lower() for p in sensitive_patterns):
return "Potentially sensitive data in error response"
return None
Fuzz Campaign Results
{
"campaign_id": "fuzz-2026-02-09-001",
"endpoint": "POST /api/v2/products",
"total_payloads": 50,
"anomalies_found": 3,
"findings": [
{
"severity": "HIGH",
"category": "SQL_INJECTION",
"payload": {"name": "'; SELECT * FROM users; --", "price": 10},
"response_status": 500,
"anomaly": "Server error on SQL_INJECTION payload -- possible unparameterized query"
},
{
"severity": "MEDIUM",
"category": "BOUNDARY",
"payload": {"name": "A", "price": 99999999999.99},
"response_status": 200,
"anomaly": "Price stored as 100000000000.0 -- precision loss on extreme values"
},
{
"severity": "LOW",
"category": "UNICODE",
"payload": {"name": "Test\u200BProduct", "price": 10},
"response_status": 200,
"anomaly": "Zero-width space accepted in product name -- may cause display issues"
}
]
}
Severity Classification
| Severity | Criteria | Example |
|---|---|---|
| CRITICAL | Remote code execution, data breach | Command injection succeeds |
| HIGH | SQL injection, auth bypass, data corruption | 500 error on SQL payload |
| MEDIUM | Information disclosure, precision loss | Stack trace in response |
| LOW | Display issues, minor validation bypass | Unicode accepted in name |
| INFO | Behavioral observation, no direct impact | Rate limit not enforced |
Key Takeaway
Semantic fuzzing combines AI's understanding of vulnerability patterns with systematic endpoint testing. Unlike random fuzzing, it generates payloads that are structurally plausible but designed to trigger specific vulnerability classes. The anomaly detection layer automatically flags responses that indicate potential issues, reducing the manual triage burden.