About the content
📌 This post includes a simple XSS prevention method on the javascript(express) server side.
Basics
XSS(Cross-site scripting) is most common vulnerability on the web applications. Most of the web applications have field like user input, login form, search etc. so the attackers can put the malicious javascript code in these input fields. Many information like user sessions can be stolen by proper input. There are some various of XSS like Reflected XSS, DOM XSS and Stored XSS,
Anyways I am not going into deep detail about XSS so I guess you have sufficient knowledge so far.
Code
Now it is time to show how to prevent on express API. Firstly the basic project should be created. The next we are going to create a vulnerable API structure using Nodejs(Express.js) and get the input from static login form file.
You can follow the instructions below to create API easily.
Open the terminal and run the followings.
start the project
npm init -y
create a folder that will contain static files like html.
mkdir static
cd static
touch login.html
Go back to root directory and create a server file.
touch server.js
Install required packages.
npm install express body-parser
Time to configure and run out the API server in server.js.
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const app = express();
app.use(bodyParser.urlencoded({ extended: false }));
Get the login page while server is run
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, '/static/login.html'));
});
Create post request to get user information and run the server.
app.post('/login', (req, res) => {
res.status(200).send(
"<div>" + req.body.username + " logged in!</div>"
);
});
const PORT = '3000';
app.listen(PORT, () => {
console.log(`listen on port: ${PORT}`);
});
Create the login form in login.html.
<!DOCTYPE html>
<html>
<head>
<title>Example Login Form</title>
</head>
<body>
<form action="/login" method="post">
<!-- user input-->
Username:<br />
<input
type="text"
name="username"
placeholder="Username"
required
/><br /><br />
Password:<br />
<input
type="password"
name="password"
placeholder="Password"
required
/><br /><br />
<!-- submit button -->
<input type="submit" value="login" />
</form>
</body>
</html>
Run the server on terminal.
node server
👉 Checkout the localhost:3000 on the browser and get to the login page like following.
If you get the same everything is well so far ! 👍
Enter username and password without any payload, server also returns username on the success page.
Go back to login page and enter one of XSS payloads from following as username and also you can find more yourself.
You are going to get an alert notification like this so the main thing is how to prevent it.
Prevention Methods
Direct use of res.send() or res.write() might cause some problem like above.
Alternatively, use res.render() instead however they are not the same methods. Sometimes you might need to use res.send() or res.write() methods therefore need to sanitize method.
Let's write a sanitizer over String class! Move on the bottom of server.js and define the function below.
function onChangeString() {
String.prototype.escape = function() {
var tagsToReplace = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
};
return this.replace(/[&<>"]/g, function(tag) {
return tagsToReplace[tag] || tag;
});
};
}
Call the function like onChangeString() after package definitions and rewrite the post method using custom escape method that defined over String class.
app.post('/login', (req, res) => {
res.status(200).send(
"<div>" + (req.body.username).escape() + " logged in!</div>" // prevent xss using String class based escape method
);
});
Check again on the browser and so you will see the payload as a string on the response.
Use of escape method detects some special entities from the string type user input. The main idea behind sanitization is escaping the some special characters like '<', '>', '"' or many of them.
To check the entire project please visit my Github account.
Thank you for reading.
Have a nice day!
Top comments (0)