![]() |
| Ethical Hacking |
🛡️ Ethical Hacking — Day 19
XSS Deep Dive: Reflection, DOM Analysis & Secure Testing
⚠️ LEARNING PURPOSE ONLY: Today's tutorial is strictly for educational and defensive cybersecurity learning. Perform every practical exercise only against your local OWASP Juice Shop lab, applications you own, or systems for which you have explicit authorization. Never test XSS against public websites or other users without permission.
Welcome to Day 19.
On Day 18, we learned the fundamentals of Cross-Site Scripting (XSS). Today we'll go deeper into how to analyze an input, find where it is reflected, understand its context, and determine whether the application is safely encoding it.
The goal is not to memorize XSS payloads.
The goal is to understand:
INPUT
↓
HTTP REQUEST
↓
APPLICATION
↓
HTML / DOM
↓
BROWSER🎯 Day 19 Learning Objectives
Today you'll learn:
Reflection points
Input tracing
HTML contexts
Attribute contexts
JavaScript contexts
DOM XSS
Sources and sinks
Browser Developer Tools
Burp HTTP History
Burp Repeater
Response comparison
Safe XSS validation
Output encoding
HTML sanitization
CSP
Secure JavaScript
Laravel XSS prevention
Spring Boot/Thymeleaf XSS prevention
React XSS prevention
Linux practical commands
Windows PowerShell practical commands
macOS practical commands
Writing an XSS finding
1. XSS Review
The basic vulnerability is:
Untrusted Data
↓
Unsafe HTML/JavaScript Context
↓
Browser
↓
Unexpected InterpretationThe secure model is:
Untrusted Data
↓
Context-Aware Encoding
↓
Safe HTML/DOM
↓
Browser2. What Is a Reflection Point?
A reflection point is a place where your supplied input appears again in the application's response or DOM.
For example, you submit:
XSS-DAY19and the page displays:
Search results for XSS-DAY19Your input has been reflected.
The next question is much more important:
Where exactly was it reflected?
3. Reflection Doesn't Mean Vulnerability
Suppose:
Input:
<test>The application returns:
<test>The browser displays:
<test>but treats it as text.
Therefore:
Reflected input
≠
XSSYou need to determine whether the browser interprets the data as executable content.
4. Reflection Contexts
Your input may appear inside:
HTML text
<div>USER_INPUT</div>Attribute
<input value="USER_INPUT">JavaScript
<script>
const x = "USER_INPUT";
</script>URL
<a href="USER_INPUT">Link</a>CSS
<div style="...USER_INPUT...">Each context has different security requirements.
5. Why Context Matters
This is a critical concept:
HTML encoding
≠
JavaScript encoding
≠
URL encoding
≠
CSS encodingYou cannot safely solve every XSS problem with:
"Just escape the input."The correct defense depends on where the data is inserted.
6. Start Your Lab
Linux
docker psWindows PowerShell
docker psmacOS
docker psVerify Juice Shop:
Linux/macOS
curl -I http://127.0.0.1:3000Windows
curl.exe -I http://127.0.0.1:30007. Open Juice Shop
Open:
http://127.0.0.1:3000Then start:
Burp Suite
↓
Proxy
↓
Open BrowserKeep your scope limited to:
127.0.0.1:30008. Find an Input
Look for a feature that accepts text.
Examples:
Search
Feedback
Reviews
Comments
Profile fieldsEnter a harmless unique marker:
XSS-DAY19-TESTThe unique marker makes it easier to find in Burp and Developer Tools.
9. Capture the Request
Go to:
Proxy
↓
HTTP historyFind the request containing:
XSS-DAY19-TESTRecord:
Method:
Endpoint:
Parameter:
Input:For example:
GET
/rest/...
q=XSS-DAY19-TESTYour actual Juice Shop version may use a different endpoint.
10. Send to Repeater
Right-click:
Send to RepeaterThen:
Repeater
↓
SendThis gives you a repeatable baseline.
11. Baseline Table
Create:
| Input | Status | Length | Reflection |
|---|---|---|---|
XSS-DAY19-TEST | ___ | ___ | Yes/No |
hello | ___ | ___ | Yes/No |
12345 | ___ | ___ | Yes/No |
Now we know how the application normally handles input.
12. Test Special Characters
Inside your local lab, test:
<test>and:
"test"and:
'test'and:
&testThese are diagnostic inputs, not destructive payloads.
Record what happens.
13. Inspect the Response
In Burp Repeater, look for your marker.
Search for:
XSS-DAY19-TESTThen inspect the surrounding content.
For example:
<div>
XSS-DAY19-TEST
</div>This is an HTML text context.
14. Attribute Reflection
You might instead find:
<input value="XSS-DAY19-TEST">Now your input is inside an HTML attribute.
The security requirements are different.
You need appropriate attribute-context handling.
15. Encoded Reflection
You might see:
<test>instead of:
<test>That's generally a good sign when the intended context is plain HTML text.
The browser renders:
<test>as visible text rather than interpreting it as an HTML element.
16. Browser Developer Tools
Now use your browser.
Open:
Developer Tools
↓
ElementsSearch for:
XSS-DAY19-TESTFind exactly where it appears.
Ask:
Is it HTML text?
An attribute?
A script?
A DOM-generated element?17. DOM Inspection
Suppose the server response doesn't contain your input, but the browser displays it.
This can be a clue that JavaScript is processing the value.
Flow:
URL
↓
JavaScript
↓
DOM
↓
PageThis is where DOM XSS analysis becomes important.
18. Sources and Sinks
A very useful XSS concept is:
Source → Sink
A source is where untrusted data enters JavaScript.
Examples:
location.search
location.hash
document.URL
document.referrerA sink is where that data can become interpreted as HTML or code.
Examples include:
element.innerHTML
element.outerHTML
document.write()
insertAdjacentHTML()The important question is:
Can untrusted data flow from a source to a dangerous sink without safe handling?
19. DOM XSS Example
Consider:
const value = location.hash.substring(1);
document.getElementById("output").innerHTML = value;Flow:
URL Hash
↓
location.hash
↓
value
↓
innerHTML
↓
DOMThis is a security pattern that deserves review.
20. Safer Version
If the intention is to display plain text:
const value = location.hash.substring(1);
document.getElementById("output").textContent = value;Now:
Input
↓
textContent
↓
Textrather than:
Input
↓
innerHTML
↓
HTML interpretation21. Why innerHTML Is Dangerous
innerHTML tells the browser:
"Interpret this string as HTML."
That may be perfectly legitimate when the HTML is fully trusted.
But if the content comes from an attacker-controlled source:
Untrusted Data
↓
innerHTML
↓
HTML Parseryou have a potential XSS problem.
22. Why textContent Is Safer
textContent tells the browser:
"Treat this as text."
So:
<test>remains:
<test>rather than being interpreted as an HTML element.
For displaying plain text, this is usually the correct choice.
23. Search JavaScript Source
In Developer Tools:
SourcesSearch for:
innerHTMLThen:
document.writeThen:
insertAdjacentHTMLThen:
outerHTMLYou're looking for:
User-controlled source
↓
Dangerous sink24. Important: Dangerous Sink ≠ Vulnerability
Finding:
innerHTML = ...doesn't automatically mean XSS.
For example:
element.innerHTML = "<b>Hello</b>";might use completely trusted static HTML.
You need to trace:
Where does the value come from?25. Source → Processing → Sink
Use this model:
SOURCE
↓
Untrusted Input
↓
Processing / Validation
↓
Encoding / Sanitization
↓
SINK
↓
BrowserA vulnerability may exist if:
SOURCE
↓
Untrusted Data
↓
Dangerous Sinkwithout appropriate protection.
26. Reflected XSS Analysis
Reflected:
Request
↓
Server
↓
Response
↓
BrowserExample:
/search?q=TESTServer:
Search results for TESTThe input is immediately reflected.
27. Stored XSS Analysis
Stored:
Request
↓
Server
↓
Storage
↓
Later request
↓
Response
↓
BrowserThis can affect other users.
For your lab, use only:
Your test account
Your test data
Your local database28. DOM XSS Analysis
DOM-based:
URL / Browser Input
↓
Client JavaScript
↓
DOM Sink
↓
BrowserThe server may not be involved at all.
29. Compare the Three
| Type | Stored? | Server Response Required? | Main Location |
|---|---|---|---|
| Reflected | Usually no | Yes | Server response |
| Stored | Yes | Usually | Server + browser |
| DOM | Not necessarily | Not necessarily | Client JavaScript |
30. HTML Encoding
For HTML text contexts, special characters are generally encoded.
For example:
< → <
> → >
& → &
" → "After encoding:
<test>the browser displays:
<test>as text.
31. Context-Aware Encoding
Remember:
HTML Text
↓
HTML Encoding
HTML Attribute
↓
Attribute Encoding
JavaScript
↓
JavaScript-safe handling
URL
↓
URL validation/encodingDon't use one encoding function everywhere.
32. Output Encoding vs Input Filtering
This is an important distinction.
Input filtering
Input
↓
Remove certain charactersOutput encoding
Input
↓
Store safely
↓
Encode for the output context
↓
BrowserFor XSS prevention, context-appropriate output encoding is generally the more reliable principle.
33. Why Blacklists Fail
A weak defense might say:
Remove:
<script>But XSS isn't simply:
<script>There are many HTML, DOM, JavaScript and browser contexts.
Therefore:
Don't build XSS protection around a blacklist of a few strings.
Use proper context-aware encoding and safe APIs.
34. Sanitization
Sometimes an application genuinely needs to allow users to enter HTML.
For example:
Rich text editor
Blog editor
Formatted commentsIn such cases, simply escaping all HTML may not be appropriate.
Instead, use a well-designed HTML sanitization mechanism that removes dangerous constructs while preserving allowed formatting.
35. Encoding vs Sanitization
Encoding
Turns data into safe text for a particular output context.
<test>
↓
<test>Sanitization
Removes or transforms unsafe HTML while preserving selected safe HTML.
Use the appropriate technique for the actual requirement.
36. Content Security Policy
Check your local response headers:
Linux/macOS
curl -I http://127.0.0.1:3000Windows
curl.exe -I http://127.0.0.1:3000Look for:
Content-Security-Policy37. CSP Is Defense in Depth
Think:
Output Encoding
+
Safe DOM APIs
+
CSP
+
Secure CookiesCSP can reduce the impact of some XSS attacks, but:
CSP should not be your primary XSS defense.
38. Cookie Security
Check whether sensitive cookies use:
HttpOnly
Secure
SameSiteRemember:
HttpOnly → JavaScript cannot directly read that cookie
Secure → Cookie sent over HTTPS
SameSite → Controls certain cross-site cookie behaviorThese are useful security controls but don't replace XSS prevention.
39. Laravel XSS Review
Generally escaped
{{ $name }}Raw HTML
{!! $name !!}Be extremely careful with raw output.
Use it only when the HTML is trusted or has been properly sanitized for the intended context.
40. React XSS Review
Normal React rendering:
<div>{userInput}</div>is designed to escape text.
Be cautious with:
dangerouslySetInnerHTMLbecause it intentionally inserts raw HTML.
Whenever you see it:
Find source
↓
Is HTML trusted?
↓
If not:
sanitize appropriately41. Spring Boot / Thymeleaf
Prefer normal escaped template output.
Be cautious with mechanisms that intentionally output raw HTML.
The general principle:
Untrusted data
↓
Escaped output
↓
HTML42. JavaScript Secure Coding
Risky for untrusted content
element.innerHTML = userInput;Better for plain text
element.textContent = userInput;Also review carefully
document.write(userInput);element.insertAdjacentHTML("beforeend", userInput);43. Linux Practical Exercise
Find your local application:
docker psCheck response:
curl -I http://127.0.0.1:3000Download HTML:
curl -s http://127.0.0.1:3000/ > juice.htmlSearch for CSP:
grep -i "content-security-policy" juice.htmlSearch for a test marker if you have a captured response:
grep -n "XSS-DAY19-TEST" juice.html44. Windows Practical Exercise
docker psCheck:
curl.exe -I http://127.0.0.1:3000Save HTML:
curl.exe -s http://127.0.0.1:3000/ -o juice.htmlSearch:
Select-String -Path juice.html -Pattern "XSS-DAY19-TEST"45. macOS Practical Exercise
docker psCheck:
curl -I http://127.0.0.1:3000Save:
curl -s http://127.0.0.1:3000/ > juice.htmlSearch:
grep -n "XSS-DAY19-TEST" juice.html46. Burp Repeater Workflow
Use this workflow:
1. Capture request
↓
2. Send to Repeater
↓
3. Send original request
↓
4. Record baseline
↓
5. Modify ONE parameter
↓
6. Send
↓
7. Compare
↓
8. Inspect reflection context
↓
9. DocumentDon't change five things at once.
47. Why Change One Thing?
Suppose you change:
Parameter A
Parameter B
Header
Cookie
Pathat the same time.
Then the response changes.
Which change caused it?
You don't know.
Professional testing uses:
One variable
↓
One observation
↓
Clear conclusion48. XSS Finding Example
Suppose your authorized lab test discovers:
Parameter:
q
Input:
<test>
Response:
Input reflected without HTML encoding
Context:
HTML
Result:
Browser interprets markupYour report could say:
Potential reflected XSS: The
qparameter is reflected into an HTML context without appropriate output encoding. The application should contextually encode untrusted output before rendering it.
49. Don't Overstate Findings
Avoid writing:
"The entire website is vulnerable."
Instead specify:
Endpoint:
Parameter:
Context:
Behavior:
Impact:
Evidence:
Recommendation:Good security reports are precise.
50. XSS Impact
Potential impact depends on the application.
It can include:
Unauthorized actions
Account-related abuse
Phishing within trusted pages
UI manipulation
Sensitive data exposure
Session-related abuse
Attacks against privileged usersImpact should be evaluated based on the actual application and affected user privileges.
51. Day 19 Main Lab
Mission: Trace an Input
Choose one local Juice Shop input.
Step 1
Enter:
XSS-DAY19-TESTStep 2
Capture it with Burp.
Step 3
Send to Repeater.
Step 4
Establish baseline.
Step 5
Search for the marker in the response.
Step 6
Inspect the browser DOM.
Step 7
Determine:
Server reflection?
DOM reflection?
Stored?Step 8
Determine context:
HTML
Attribute
JavaScript
URL
DOMStep 9
Test harmless special characters:
<test>
"test"
'test'
&testStep 10
Document the behavior.
📊 Day 19 Lab Report
╔══════════════════════════════════════╗
║ DAY 19 XSS REPORT ║
╚══════════════════════════════════════╝
Target:
127.0.0.1:3000
Feature:
____________________________
Endpoint:
____________________________
Method:
____________________________
Parameter:
____________________________
Test Marker:
XSS-DAY19-TEST
Reflected in HTTP response?
Yes / No
Present in DOM?
Yes / No
Stored?
Yes / No / Unknown
Context:
HTML / Attribute / JS / URL / DOM
Special Character Behavior:
____________________________
Encoding Observed:
____________________________
Potential XSS:
Yes / No / Unclear
Evidence:
____________________________
Recommended Fix:
____________________________🧠 Day 19 Assignment
Answer these questions:
What is a reflection point?
Does reflected input automatically mean XSS?
What is an HTML context?
What is an attribute context?
Why does context matter for XSS prevention?
What is a DOM source?
What is a DOM sink?
Why can
innerHTMLbe dangerous?Why is
textContentsafer for plain text?What is stored XSS?
What is reflected XSS?
What is DOM-based XSS?
What is output encoding?
What is HTML sanitization?
Why is removing
<script>not sufficient?What does CSP do?
What does
HttpOnlydo?Why is
dangerouslySetInnerHTMLworth reviewing?Why should raw HTML output in Laravel be treated carefully?
Why should you change only one parameter during controlled testing?
🏆 Day 19 Challenge
Create a Source → Sink Map.
Example:
SOURCE
location.hash
│
▼
JavaScript variable
│
▼
Processing
│
▼
innerHTML
│
▼
DOM
│
▼
BrowserThen create the secure version:
SOURCE
location.hash
│
▼
JavaScript variable
│
▼
textContent
│
▼
Plain Text
│
▼
Browser🔐 Day 19 Golden Rule
Remember:
The most important XSS question isn't "What payload should I use?" It is "Where does untrusted data go, and how does the browser interpret it?"
Use this mental model:
SOURCE
↓
UNTRUSTED DATA
↓
PROCESSING
↓
OUTPUT CONTEXT
↓
ENCODING / SANITIZATION
↓
BROWSERAnd always keep:
DATA ≠ CODE✅ Day 19 Summary
Today you learned:
Reflection points
Reflected XSS
Stored XSS
DOM XSS
HTML contexts
Attribute contexts
JavaScript contexts
Sources
Sinks
innerHTMLtextContentOutput encoding
Sanitization
CSP
Secure cookies
Burp Repeater
Browser Developer Tools
Laravel
React
Spring Boot/Thymeleaf
Linux
Windows
macOS
XSS reporting
🔑 Most Important Lesson
Trace untrusted data from its source to its final browser context. Then use the correct encoding, sanitization, or safe DOM API for that context.
🔜 Day 20 — XSS Practical Lab & Defense
Next we'll consolidate XSS with a more structured local lab:
Reflected XSS analysis
Stored XSS analysis
DOM XSS source/sink tracing
Burp Suite
Browser DevTools
Safe validation methodology
XSS severity and impact
Secure Laravel code
Secure Spring Boot code
Secure JavaScript
CSP
XSS reporting
Linux, Windows and macOS practical sessions
⚠️ LEARNING PURPOSE ONLY: All exercises remain limited to your local/authorized lab. Never test public websites or other people's accounts without explicit authorization.

No comments:
Post a Comment