DAST vs SAST: Complementary Approaches
While SAST analyzes source code without execution, DAST tests the running application from an attacker's perspective:
| Aspect | SAST (Static) | DAST (Dynamic) |
|---|---|---|
| Testing Phase | Development (before runtime) | Staging/Production (runtime) |
| Access Required | Source code | Running application URL |
| Finds | Code patterns, potential bugs | Actual exploitable vulnerabilities |
| False Positives | Higher (context missing) | Lower (validates exploitability) |
| Coverage | All code paths | Only accessible endpoints |
Use SAST during development to catch issues early, then DAST in staging to validate the deployed application. Together they provide comprehensive coverage.
Choosing a DAST Tool
Popular DAST tools for different use cases:
OWASP ZAP (Recommended)
Pros: Free, open-source, extensive features, CI/CD friendly
Cons: Steeper learning curve, requires configuration
Best for: Teams wanting full control and customization
Burp Suite (Professional)
Pros: Powerful scanning, excellent UI, active community
Cons: Expensive ($399/year), manual focus
Best for: Security professionals doing manual testing
Nuclei
Pros: Fast, template-based, easy CI/CD integration
Cons: Limited crawling, requires template management
Best for: Known vulnerability scanning at scale
Setting Up OWASP ZAP
Installation
# Pull the latest ZAP Docker image
docker pull owasp/zap2docker-stable
# Run interactive ZAP with WebSwing UI
docker run -u zap -p 8080:8080 -p 8090:8090 \
-i owasp/zap2docker-stable zap-webswing.sh
Baseline Scan
Start with a quick baseline scan to identify low-hanging fruit:
# Basic scan (5-10 minutes)
docker run --rm \
-v $(pwd):/zap/wrk/:rw \
owasp/zap2docker-stable zap-baseline.py \
-t https://staging.yourdomain.com \
-r zap-baseline-report.html \
-J zap-baseline-report.json
# With authentication (context file)
docker run --rm \
-v $(pwd):/zap/wrk/:rw \
owasp/zap2docker-stable zap-baseline.py \
-t https://staging.yourdomain.com \
-n /zap/wrk/context.context \
-U testuser \
-r report.html
Full Scan
Comprehensive scan with active vulnerability testing (30-60+ minutes):
docker run --rm \
-v $(pwd):/zap/wrk/:rw \
owasp/zap2docker-stable zap-full-scan.py \
-t https://staging.yourdomain.com \
-r zap-full-report.html \
-J zap-full-report.json \
-x zap-full-report.xml
Authentication Strategies
Method 1: Form-Based Authentication
Create a ZAP context file for web applications with login forms:
{
"context": {
"name": "Staging Environment",
"urls": ["https://staging.yourdomain.com.*"],
"auth": {
"type": "form",
"loginUrl": "https://staging.yourdomain.com/login",
"loginRequestData": "username={%username%}&password={%password%}",
"usernameParameter": "username",
"passwordParameter": "password",
"loggedInIndicator": "\\QLogout\\E",
"loggedOutIndicator": "\\Q
Method 2: API Token Authentication
For REST APIs with bearer tokens:
// Authentication script (JavaScript)
function authenticate(helper, paramsValues, credentials) {
var msg = helper.prepareMessage();
msg.setRequestHeader("Authorization: Bearer " + paramsValues.get("token"));
helper.sendAndReceive(msg);
return msg;
}
function getRequiredParamsNames() {
return ["token"];
}
function getOptionalParamsNames() {
return [];
}
Method 3: Session Cookies
Reuse authenticated session cookies:
# Get session cookie manually or via script
curl -c cookies.txt -X POST https://staging.yourdomain.com/login \
-d "username=test@example.com&password=TestPassword123!"
# Run ZAP with cookies
docker run --rm \
-v $(pwd):/zap/wrk/:rw \
owasp/zap2docker-stable zap-baseline.py \
-t https://staging.yourdomain.com \
--hook=/zap/wrk/cookie-script.py
Scope Management
Include/Exclude Rules
Prevent scanning sensitive or third-party endpoints:
# Exclude admin panels from active scans
https://staging.yourdomain.com/admin/.*
# Exclude third-party integrations
https://staging.yourdomain.com/webhooks/stripe/.*
# Exclude logout (prevents session termination)
https://staging.yourdomain.com/logout
# Exclude heavy operations
https://staging.yourdomain.com/api/reports/generate.*
robots.txt Compliance
Respect robots.txt to avoid scanning disallowed paths:
docker run --rm \
-v $(pwd):/zap/wrk/:rw \
owasp/zap2docker-stable zap-baseline.py \
-t https://staging.yourdomain.com \
--config spider.parseRobotsTxt=true
CI/CD Integration
GitHub Actions Workflow
name: DAST Scan
on:
schedule:
# Run every night at 2 AM UTC
- cron: '0 2 * * *'
workflow_dispatch: # Manual trigger
jobs:
zap-scan:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Wait for deployment
run: |
# Ensure staging is ready
for i in {1..10}; do
if curl -f -s https://staging.yourdomain.com/health; then
echo "✅ Staging is ready"
exit 0
fi
echo "⏳ Waiting for staging..."
sleep 10
done
exit 1
- name: Run ZAP Baseline Scan
uses: zaproxy/action-baseline@v0.7.0
with:
target: 'https://staging.yourdomain.com'
rules_file_name: '.zap/rules.tsv'
cmd_options: '-a -j' # AJAX spider, JSON report
- name: Upload ZAP Report
uses: actions/upload-artifact@v3
if: always()
with:
name: zap-scan-report
path: report_html.html
- name: Check for High/Critical Issues
run: |
HIGH_COUNT=$(jq '[.site[].alerts[] | select(.riskcode >= "2")] | length' report_json.json)
if [ "$HIGH_COUNT" -gt "0" ]; then
echo "❌ Found $HIGH_COUNT high/critical vulnerabilities!"
exit 1
fi
Custom Rules Configuration
Create .zap/rules.tsv to customize alerting thresholds:
# Format: rule_id threshold [IGNORE, WARN, FAIL]
10021 IGNORE # X-Content-Type-Options header (handled by CDN)
10020 WARN # X-Frame-Options (non-critical for API)
10038 FAIL # Content Security Policy missing
90022 FAIL # Application Error Disclosure
40012 FAIL # Cross Site Scripting (Reflected)
40014 FAIL # Cross Site Scripting (Persistent)
Interpreting Results
Risk Levels
| Level | Description | Action |
|---|---|---|
| High | Directly exploitable (SQLi, XSS, Auth bypass) | Fix immediately, block deployment |
| Medium | Requires conditions (CSRF, session issues) | Fix in current sprint |
| Low | Informational leaks, missing headers | Backlog, fix when convenient |
| Informational | Best practices, no direct risk | Consider for hardening |
Common False Positives
- X-Frame-Options on APIs: Not needed for non-browser endpoints
- Cookie without SameSite: May be intentional for OAuth flows
- SQL injection in base64: Often a decoding artifact, verify manually
- XSS in JSON responses: Safe if Content-Type is application/json
Advanced Techniques
AJAX Spider
For single-page applications (React, Vue, Angular):
docker run --rm \
-v $(pwd):/zap/wrk/:rw \
owasp/zap2docker-stable zap-baseline.py \
-t https://staging.yourdomain.com \
-a # Enable AJAX spider
--config spider.maxDuration=10 \
--config ajaxSpider.clickElemsOnce=true
API Scanning with OpenAPI Spec
Import OpenAPI/Swagger spec for comprehensive API coverage:
docker run --rm \
-v $(pwd):/zap/wrk/:rw \
owasp/zap2docker-stable zap-api-scan.py \
-t https://staging.yourdomain.com/api/swagger.json \
-f openapi \
-r api-scan-report.html
Authenticated API Testing
# Generate API token
TOKEN=$(curl -X POST https://staging.yourdomain.com/api/auth \
-d '{"username":"test@example.com","password":"TestPassword123!"}' \
| jq -r '.token')
# Run ZAP with token in headers
docker run --rm \
-v $(pwd):/zap/wrk/:rw \
-e "TOKEN=$TOKEN" \
owasp/zap2docker-stable zap-api-scan.py \
-t https://staging.yourdomain.com/api/swagger.json \
-f openapi \
--config replacer.full_list(0).description=auth \
--config replacer.full_list(0).enabled=true \
--config replacer.full_list(0).matchtype=REQ_HEADER \
--config replacer.full_list(0).matchstr=Authorization \
--config replacer.full_list(0).replacement="Bearer $TOKEN"
Performance Optimization
Parallel Scanning
Split scans by route prefix for faster execution:
# Scan /api routes
docker run --rm -v $(pwd):/zap/wrk/:rw \
owasp/zap2docker-stable zap-baseline.py \
-t https://staging.yourdomain.com/api \
-r api-report.html &
# Scan /admin routes
docker run --rm -v $(pwd):/zap/wrk/:rw \
owasp/zap2docker-stable zap-baseline.py \
-t https://staging.yourdomain.com/admin \
-r admin-report.html &
wait # Wait for both to finish
Scan Scheduling
- Baseline scans: Every deployment (5-10 min)
- Full scans: Nightly or weekly (30-60 min)
- API scans: On API spec changes (10-20 min)
Best Practices Checklist
Troubleshooting
Scans Timing Out
- Increase timeout:
--config connection.timeoutInSecs=300 - Reduce spider depth:
--config spider.maxDepth=3 - Disable heavy scans: Add
-config scanner.strength=LOW
Authentication Failing
- Verify logged-in indicator regex matches actual response
- Check if CSRF tokens are required (use ZAP anti-CSRF token handling)
- Use network inspection (browser DevTools) to capture exact login request
- Try session cookie injection instead of form-based auth
Too Many False Positives
- Use
rules.tsvto IGNORE specific rule IDs for your context - Add regex patterns to exclude endpoints from active scanning
- Start with
-config scanner.attackStrength=LOW
Next Steps
You're now equipped to implement DAST scanning! Continue your security journey:
- Add SAST scanning for comprehensive coverage
- Implement dependency scanning with Trivy
- Try our interactive demo to see security scanning in action
- Contact us for managed DAST services
ElevatedIQ offers automated DAST scanning with custom authentication scripts, false positive filtering, and 24/7 monitoring. Get in touch to secure your running applications.