DOM-based XSS

A DOM-based XSS is possible because an adversary-controlled inputs affect a so-called sensitive function. Examples of such functions are like: eval, innerHTML, setAttribute, and document.write.

Let us look at an example below. It is refactoring of our previous welcome application.

Here is the server side code:

const express = require('express');
const path = require("path");

let app = express();

// Function to handle the root path
app.get('/', async function(req, res) {

    let username = req.query.username;


    // Return the articles to the rendering engine
    res.sendFile(path.join(__dirname, "main.html"));
});

let server = app.listen(8080, function() {
    console.log('Server is listening on port 8080')
});

Here is the client-side code (note that for simplification, we ignored all other HTML parts):

<script>
var pos = document.URL.indexOf("username=") + 9; 
document.write("hello! " + decodeURIComponent(document.URL.substring(pos,document.URL.length))); 
</script>

Normally, we use the following URL to visit the page:

http://localhost:8080/?username=cao

However, if an adversary crafts an input like below, they can execute arbitrary scripts.

http://localhost:8080/?username=<script>alert(1)</script>

Note that there are many ways to craft XSS payload. Please find the following useful resources: XSS Cheat Sheet.