Dynamic DAST & Attack Simulations
OWASP ZAP & API Fuzzing β Day 3
Execute automated OWASP ZAP baseline scans in Docker, simulate REST endpoint fuzzing attacks, and audit HTTP security headers against vulnerable-store-api.
Static analysis alone cannot detect runtime configuration issues, such as missing response headers, cross-origin misconfigurations, or server-level parameter reflection. In this lab, you will runOWASP ZAP against the live running vulnerable-store-api container and execute automated attack fuzzing.
The official reference codebase for Day 3 is hosted in the repository. Clone the repository and navigate to day-3-dast-zap-fuzzing to run the working solution.
git clone https://github.com/letstrnsfrm-ai/security-compliance-roadmap.git
cd security-compliance-roadmap/day-3-dast-zap-fuzzingStart Live Target API with Endpoints to Attack
Add product search and checkout routes to server.js and run the service locally on port 3001.
// Add to server.js
app.get('/api/products/search', (req, res) => {
const query = req.query.q || '';
// Intentionally reflects query without encoding & missing security headers
res.send(`<h1>Search Results for: ${query}</h1><p>0 items found.</p>`);
});
app.get('/api/health', (req, res) => {
res.json({ status: 'ok', uptime: process.uptime() });
});node server.js
# Output: Store API running on port 3001Execute OWASP ZAP Baseline Container Scan
Run OWASP ZAP via Docker to spider endpoints and audit for missing security headers, clickjacking defenses, and cross-site scripting indicators.
WARN-NEW: Content Security Policy (CSP) Header Not Set [10038] x 2
WARN-NEW: Missing Anti-clickjacking Header (X-Frame-Options) [10020] x 2
WARN-NEW: X-Content-Type-Options Header Missing [10021] x 2
WARN-NEW: Strict-Transport-Security (HSTS) Header Not Set [10035] x 2Simulate Parameter Fuzzing & Payload Injections
Direct an automated curl fuzzing script to inject XSS and SQLi boundary payloads into the search route and assert response behaviors.
#!/usr/bin/env node
const http = require('http');
const payloads = [
"<script>alert('xss')</script>",
"' OR '1'='1",
"../../../../etc/passwd",
"%00%27%22",
];
async function testPayload(payload) {
return new Promise((resolve) => {
const url = `http://localhost:3001/api/products/search?q=${encodeURIComponent(payload)}`;
http.get(url, (res) => {
let data = '';
res.on('data', chunk => data += chunk);
res.on('end', () => {
const reflectsRawPayload = data.includes(payload);
resolve({ payload, status: res.statusCode, reflectsRawPayload });
});
});
});
}
async function runFuzzSuite() {
console.log('β‘ Running Automated DAST Endpoint Fuzzer...');
let flawsFound = 0;
for (const p of payloads) {
const result = await testPayload(p);
if (result.reflectsRawPayload) {
console.error(`π¨ DAST VULNERABILITY: Raw payload reflected unescaped! [${p}]`);
flawsFound++;
}
}
if (flawsFound > 0) {
console.error(`\nβ Fuzzing Failed: ${flawsFound} unencoded injections detected.`);
process.exit(1);
}
console.log('β
Fuzzing Passed: All inputs properly encoded or rejected.');
}
runFuzzSuite();node scripts/fuzz-test.js
# Output: π¨ DAST VULNERABILITY: Raw payload reflected unescaped! [<script>alert('xss')</script>]Harden HTTP Headers & Secure Response Encoding
Install Helmet middleware to inject critical HTTP headers and sanitize reflected HTML output to pass both ZAP and fuzz testing.
// npm install helmet
const helmet = require('helmet');
// Enable standard security headers: CSP, HSTS, X-Frame-Options, noSniff
app.use(helmet());
// Secure Search Route with HTML entities encoding
app.get('/api/products/search', (req, res) => {
const query = String(req.query.q || '')
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"');
res.send(`<h1>Search Results for: ${query}</h1><p>0 items found.</p>`);
});node scripts/fuzz-test.js
# Output:
# β‘ Running Automated DAST Endpoint Fuzzer...
# β
Fuzzing Passed: All inputs properly encoded or rejected.- Understood Dynamic Application Security Testing (DAST) principles and when black-box scanning is necessary.
- Spun up an automated OWASP ZAP baseline scan in Docker against vulnerable-store-api.
- Identified missing HTTP response headers (CSP, HSTS, X-Frame-Options, X-Content-Type-Options).
- Wrote a dynamic payload fuzzer script (scripts/fuzz-test.js) and hardened the API using helmet middleware and output sanitization.
π§ Knowledge Check
What is the primary difference between passive DAST scanning and active DAST scanning?