logo

Insecure or unset HTTP headers - X-Frame Options - Typescript


Need

Implementation of secure and properly configured HTTP headers


Context

  1. Usage of TypeScript for statically typed JavaScript development
  2. Usage of Express for building web applications and APIs

Description

Insecure Code Example

import express from 'express';

const app = express();

app.get('/', (req, res) => {
  res.setHeader('X-Frame-Options', 'ALLOW-FROM https://malicious-website.com');
  res.send('Hello World!');
});

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

The vulnerability in the provided TypeScript code is related to the insecure or unset HTTP header, specifically the X-Frame-Options header. In the code, the X-Frame-Options header is set to allow framing from a specific domain, 'https://malicious-website.com'. This header is intended to protect against clickjacking attacks by specifying which domains are allowed to embed the application in an iframe. However, in this case, the header is set to allow framing from a potentially malicious website. This vulnerability can be exploited by an attacker who controls the malicious-website.com domain. They can embed the application in an iframe on their website and potentially trick users into performing unintended actions or disclosing sensitive information. To mitigate this vulnerability, it is recommended to disable the X-Frame-Options header from the server responses. Additionally, it is advised to define the frame_ancestors policy in the Content Security Policy (CSP) header. The frame_ancestors policy allows you to specify which domains are allowed to embed the application in an iframe, providing a more secure alternative to the deprecated X-Frame-Options header.

Steps

  1. Remove the line that sets the X-Frame-Options header in the server response
  2. Add the Content-Security-Policy header with the frame-ancestors directive to specify the allowed frame ancestors
  3. Set the frame-ancestors directive to 'none' if the application should not be embedded in any frames, or specify the allowed origins if the application should be embedded in specific frames

Secure Code Example

import express from 'express';

const app = express();

app.use((req, res, next) => {
  res.setHeader('Content-Security-Policy', "frame-ancestors 'none'");
  next();
});

app.get('/', (req, res) => {
  res.send('Hello World!');
});

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

The fixed code is written in TypeScript using the Express framework. It addresses the vulnerability related to insecure or unset HTTP headers by implementing the Content Security Policy (CSP) header with the frame-ancestors policy. In the code, we import the Express module and create an instance of the application using the `express()` function. The `app.use()` middleware function is used to set the `Content-Security-Policy` header on all server responses. The value of the header is set to `frame-ancestors 'none'`, which means that the application should not be embedded in any frames or iframes. The `app.get()` function defines a route for the root URL ("/") and sends the response "Hello World!". Finally, the `app.listen()` function starts the server on port 3000 and logs a message to the console. By setting the `Content-Security-Policy` header with the `frame-ancestors` policy to `'none'`, the fixed code ensures that the application cannot be embedded in any frames, thereby preventing clickjacking attacks.


References

  • 152 - Insecure or unset HTTP headers - X-Frame Options

  • Last updated

    2023/09/18