Skip to main content

Server side cross-site scripting

Need

Prevention of server-side cross-site scripting attacks

Context

  • Usage of TypeScript for type-safe JavaScript development
  • Usage of Express for building web applications and handling HTTP requests

Description

Non compliant code

import express from 'express';

const app = express();

app.get('/search', (req, res) => {
const query = req.query.q;
const response = `Search results for: ${query}`;

res.send(response);
});

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

The vulnerability in the given code is a server-side cross-site scripting (XSS) vulnerability. This vulnerability occurs because the code does not properly sanitize the user input before executing it on the server side.

In the code, the server receives a GET request to the '/search' endpoint and extracts the value of the 'q' query parameter using req.query.q. This value is then directly used to construct a response string without any sanitization or validation.

An attacker can exploit this vulnerability by sending a malicious script as the value of the 'q' parameter. For example, if an attacker sends the value <script>alert('XSS')</script>, the server will include this script in the response without any modification. When the response is rendered in the user's browser, the script will be executed, leading to a cross-site scripting attack.

The impact of this vulnerability can be severe. An attacker can use XSS to extract sensitive information from the server, such as session cookies or user credentials. They can also perform actions on the server or on behalf of the server, potentially compromising the server's integrity or performing unauthorized actions.

To mitigate this vulnerability, it is recommended to properly sanitize user input before using it in the response. This can be done by using a library or framework that provides input validation and sanitization functions, or by implementing custom sanitization logic to remove or escape any potentially malicious characters or scripts from the user input.

Steps

  • Validate and sanitize user input before using it in the response
  • Use appropriate encoding or escaping mechanisms to prevent script injection
  • Implement content security policies to restrict the execution of scripts from external sources
  • Regularly update and patch the application framework and dependencies to mitigate known vulnerabilities
  • Implement input validation and output encoding as part of the secure coding practices

Compliant code

import express from 'express';
import { sanitize } from 'sanitize-html';

const app = express();

app.get('/search', (req, res) => {
const query = sanitize(req.query.q);
const response = `Search results for: ${query}`;

res.send(response);
});

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

The fixed code addresses the vulnerability by properly sanitizing user input before executing it on the server side. Here's an explanation of the code:

  1. The code imports the necessary modules, including the 'express' module for creating the server and the 'sanitize-html' module for sanitizing user input.

  2. The code creates an instance of the Express application using the 'express()' function and assigns it to the 'app' variable.

  3. The code defines a route handler for the '/search' endpoint using the 'app.get()' method. This route handler is triggered when a GET request is made to the '/search' URL.

  4. Inside the route handler, the code retrieves the user input from the 'q' query parameter of the request object using 'req.query.q'.

  5. The user input is then passed through the 'sanitize()' function from the 'sanitize-html' module. This function sanitizes the input by removing any potentially harmful HTML or JavaScript code.

  6. The sanitized input is then used to construct a response string that includes the sanitized query.

  7. Finally, the response string is sent back to the client using the 'res.send()' method.

  8. The code starts the server by calling the 'app.listen()' method and specifying the port number (3000 in this case). A console log message is also printed to indicate that the server is running.

By using the 'sanitize-html' module to properly sanitize user input, the fixed code ensures that any potential malicious JavaScript code is removed before it can be executed on the server side. This mitigates the risk of server-side cross-site scripting vulnerabilities.

References