Tutorial: A webapp vulnerable to XSS


In this tutorial we’re going to cover the following topics:

  • Creating Nodejs routes
  • Creating a Handlebars templates
  • Writing a webpage vulnerable to XSS exploit

Nodejs Router:

I’m going to introduce you to Routers, instead of explaining (probably in later post), I’ll just show you by example. To start we’ll need to add a new route in our ‘app.js’ file:

new route to http://<your ip addresss>/xss
  • ‘app.use’ :: this will bind a route – ‘/xss’ – the the middleware layer that we want to use, i.e. ‘xss.js’
  • Easier explanation :: anytime a user visits the ‘/xss’ route in our web application, e.g., it tells the server to execute the functions defined in the ‘./xss.js’
  • We have to define a new file names ‘xss.js’ in the same directory as the app.js file. Note, if we instead defined the middleware as ‘./public/xss.js’, then we have the have folder named public in the same directory as the ‘app.js’ file, and within that ‘public’ folder, we would need to define ‘xss.js’

Define ‘xss.js’

Create and open a file named ‘xss.js’ in the same directory as ‘app.js’

touch xss.js 

If we listed all of the contents in the current directory (ls -al), it should like the following:

Open up the ‘xss.js’ in an text editor:

vim xss.js

Screenshot of the skeleton code:

skeleton code of ‘xss.js’ file

I’m going to try and explain what’s going on here and hope this makes sense.

Recall in the ‘/wagmi’ route, anytime this endpoint is visited it executes a function that defined inline:

visting /wagmi executes an inline function

The ‘/xss’ route also needs a handler/function that is executed. In this instance we’re ‘importing’ – through the use of ‘require’ – the functions from the ‘xss.js’ file. Because we’re importing the function, then the ‘xss.js’ file must export a function, which it does. Notice the use of ‘module.exports’:

xss.js returns the handler/function that will be called for ‘/xss’ route

Hopefully, this explains what’s going. If not, just hit the “I believe button’ and copy the code. Moving on we have to define what handler will be doing when the ‘/xss’ route is visited.

We define that as so:

Note, do not get confused with ‘/’, root, endpoint. This is not defining the route for, it’s defining the handler for the http://127.0.01/xss/

Recall that in the ‘app.js’ file it’s redirecting all traffic to the ‘/xss’ endpoint to the ‘xss.js’ file. Using ‘/’ means we are using the root ‘/xss’ endpoint. In the ‘xss.js’ file, if we instead use ‘/subdirectory’, instead of ‘/’, we would be defining the route for

Quick description of what’s going on inside the handler:

  • we initialize variable ‘context’ which will be a dictionary
  • we set dictionary key name ‘text’, i.e. context.text’ to value in query parameter ‘text’.
  • we send a response back to the client that visited the ‘/xss’ endpoint.
    • we use our templating engine – ‘handlebars’ – to create the html page
    • we pass the context variable for ‘handlebars’ templating engine to use.

We have to tell our web app to use the handlebars templating engine. Let’s do that now.

Handlebars Template Engine

In the ‘app.js’ we have to configure our web app to use the handlebars templating engine:

add the highlighted lines of code into you app.js file
  • We are importing (i.e. require) the handlebars package
  • We are telling handlebars the default html script to be included in all of our html pages
  • We are setting the web app template engine to handlebars

Recall the directory structure in the first tutorial:

Directory structure of our web application

This is a standard layout when using the ‘handlebars’ template engine. It’s important specifically to have the ‘views’ and the ‘view/layouts’ directories.

In the ‘layouts’ directory, is where we define the ‘main.handlebars’ template, this will be included in every html page our web app responds with.

The ‘views’ directory will have the specific handlebars/html templates for our routes. We do this because, presumable, we’ll have different html for different endpoint, we don’t want the same html for all of our webpages, that would be boring.

Screenshot of my main.handlebars template:

html code inside ‘main.handlebars’

<!doctype html>
<title>My Page</title>
        <!--bootstrap setup -->
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <script src=""></script>
        <link rel="stylesheet" href="" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
        <link rel="stylesheet" href="" integrity="sha384-AYmEC3Yw5cVb3ZcuHtOA93w35dYTsvhLPVnYs9eStHfGJvOvKxVfELGroGkvsg+p" crossorigin="anonymous"/>
        <script src=""></script>

        <script src=""></script>
        <script src=""></script>


In my main, I include the sources for bootstrap and jQuery. This is where you ideally put styling sources that you want rendered for all of your pages. This is a benefit of using templating engine – you minimize the amount of code that is repeated. You need this because I’m using bootstrap styling.

We now need to define the index.handlebars file, the file that is rendered when someone visits the ‘/xss’ route.

Creating an XSS vulnerable Webpage

In the ‘xss.handlebars’ file write the following code:

<h1>Cross Site Scripting Test</h1>
  <div class="container">
          <form action="/xss" method="get">
                  <div class="form-group">
                          <label for="text">Input Text Here:</label>
                          <textarea class="form-control" name="text"></textarea>

                  <button type="submit" class="btn btn-primary">Submit</button>
          {{#if text}}

The important parts:

  • We creating a form element
    • The form element has a textarea/text box, where the user can provide input
    • The textarea/text box has a ‘name’ attribute of ‘text’, this is equivalent to a variable. When the types in input and submits, the user’s input is set to the ‘name’ variable
    • when submitted it performs a ‘GET’ request to our ‘/xss’ route
  • Notice the Block of code defined between {{#if text}} … {{/if}}, handlebars supports if statements.
    • If the handlebars engine is passed a variable named ‘text’ it will generate that into the html
    • {{text}} (double brackets) will escape special characters
    • {{{text}}} (triple brackets) will not escape, it will generate the exact string that the user inputs into the form.

Save the file.

Testing the web application

At this point we should be ready start up our web applications.

Navigate out of your ‘views’ folder where you edited the ‘index.handlebars’ page and into the directory where your ‘app.js’ file is. The contents of your current directly should like so:

Startup the web application:

node app.js

Open up a Google Chrome browser and browse to

Insert the following into the text box:


Click ‘Submit’. You should’ve receive a text box popup stating “wagmi”:

text box pop up with

Congratulations! You not only completed fully function web application, you wrote one that was vulnerable to XSS.

Vulnerable Piece of Code

unescaped user input

The culprit that results in an XSS vulnerability is the use of triple brackets in the handlebars templating engine. Handlebars will render the user input exactly as written, there is not escaping/sanitization of user input.

A quick fix would be to use the double brackets to render variable passed into the handlebars template, this would escape special characters.

Another option could be to perform user input sanitization in our middleware. I’ll leave this to you to research what node packages are available to sanitize user inputs.

Anyway, I hope you found this tutorial enlightening. In the next few tutorials, I want to go over how to connect your web application to a Database and introduce sql injections.



Print Friendly, PDF & Email

Leave a Reply

Your email address will not be published. Required fields are marked *