Skip to main content

Stored cross-site scripting (XSS)

Need

Prevention of persistent cross-site scripting attacks

Context

  • Usage of TypeScript for type-checking and compiling JavaScript code
  • Usage of Express for building web applications and APIs

Description

Non compliant code

import express from 'express';

const app = express();

app.use(express.urlencoded({ extended: true }));

app.post('/submit', (req, res) => {
const userInput = req.body.userInput;
// Vulnerable code: storing user input without proper sanitization
// This allows an attacker to inject malicious JavaScript code
// into the application fields and compromise user sessions
saveUserInput(userInput);

res.send('User input saved successfully!');
});

function saveUserInput(input: string) {
// Code to save user input to the database
// ...
}

app.listen(3000, () => {
console.log('Server is running on port 3000');
});

The vulnerability in the given code is a stored cross-site scripting (XSS) vulnerability.

In the code, the application receives user input through a POST request to the '/submit' endpoint. The user input is stored in the userInput variable without any proper sanitization or validation. This means that any malicious JavaScript code entered by the user will be stored as-is in the application's database.

This vulnerability allows an attacker to inject and persistently store malicious JavaScript code in the application fields. When other users access the application and retrieve this stored data, the malicious code will be executed in their browsers, potentially compromising their sessions or allowing the distribution of malicious software.

To mitigate this vulnerability, it is recommended to filter the information received and sent by the application using white lists. This means validating and sanitizing user input to ensure it does not contain any malicious code before storing it in the database.

Steps

  • Implement proper input validation and sanitization to filter out any potentially malicious code.
  • Use a white list approach to only allow specific characters or patterns in the user input.
  • Encode any user input before storing it in the database to prevent the execution of malicious code.
  • Consider using a web application firewall (WAF) to provide an additional layer of protection against XSS attacks.
  • Regularly update and patch the application and its dependencies to ensure any known vulnerabilities are addressed.

Compliant code

import express from 'express';
import xss from 'xss';

const app = express();

app.use(express.urlencoded({ extended: true }));

app.post('/submit', (req, res) => {
const userInput = xss(req.body.userInput);
saveUserInput(userInput);

res.send('User input saved successfully!');
});

function saveUserInput(input: string) {
// Code to save user input to the database
// ...
}

app.listen(3000, () => {
console.log('Server is running on port 3000');
});

The fixed code addresses the vulnerability of stored cross-site scripting (XSS) by implementing input filtering using a library called xss.

  1. The code imports the necessary modules, including express for creating the server and xss for input filtering.

  2. The express server is created and configured to parse URL-encoded data using the express.urlencoded middleware. This allows the server to handle form submissions.

  3. The app.post route is defined to handle the submission of user input. Inside the route handler, the user input is retrieved from req.body.userInput and passed through the xss function from the xss library. This function sanitizes the input, removing any potentially malicious JavaScript code.

  4. The sanitized user input is then passed to the saveUserInput function, which is responsible for saving the input to the database. This function is not shown in the code snippet but should include proper validation and sanitization measures to prevent other types of vulnerabilities.

  5. Finally, the server listens on port 3000 for incoming requests.

By using the xss library to sanitize the user input, the code ensures that any potentially malicious JavaScript code is removed, preventing the stored XSS vulnerability. This approach follows the recommendation of filtering the information received and sent by the application using white lists.

References