Preventing reflected XSS attacks in static asset requests in node/express

After conducting a penetration test using the Burp tool on my node(express)/angular application, I discovered a reflected XSS vulnerability. This vulnerability was specifically identified when making a GET request for static assets (no other vulnerabilities were found during user interactions with the application).

The issue description is as follows:

An arbitrary URL parameter's name is inserted into a JavaScript expression without any quotation marks. The payload 41b68(a)184a9=1 was submitted through this URL parameter and echoed back unmodified in the application's response.

This behavior indicates the ability to inject JavaScript commands into the document. Although an attempt to exploit this vulnerability was unsuccessful, manual examination of the application's behavior is recommended to identify any unusual input validation or obstacles.

To test the vulnerability, an arbitrary URL parameter was passed in the following format:

GET /images/?41b68(a)184a9=1

The response received was:

HTTP/1.1 404 Not Found
X-Content-Security-Policy: connect-src 'self'; default-src 'self'; font-src 'self'; frame-src; img-src 'self' *.google-analytics.com; media-src; object-src; script-src 'self' 'unsafe-eval' *.google-analytics.com; style-src 'self' 'unsafe-inline'
X-XSS-Protection: 1; mode=block
X-Frame-Options: DENY
Strict-Transport-Security: max-age=10886400; includeSubDomains; preload
X-Download-Options: noopen
X-Content-Type-Options: nosniff
Content-Type: text/html; charset=utf-8
Content-Length: 52
Date: Wed, 08 Oct 2015 10:46:43 GMT
Connection: close

Cannot GET /images/?41b68(a)184a9=1

The application has implemented Content Security Policy (CSP) via Helmet, ensuring protection against exploits. While the app uses HTTPS, it does not require user authentication. CSP restricts requests to the app's domain and Google Analytics.

The pen test report suggests validating input (which is already being done), encoding HTML (handled by Angular by default), and evaluating the behavior of static asset requests within Node/Express.

Exploring solutions to prevent or mitigate this issue for static asset requests:

  • Should all application requests be whitelisted under CSP?
  • Can domains be whitelisted instead of individual requests?
  • Should responses to static asset requests be encoded in some manner?
  • Could the vulnerability lie in the code handling static asset responses?
  • Is there a possibility of the GET request parameter being evaluated in the application code?

Update

Initial investigations point towards escaping data in URL parameter values and sanitizing input in URLs as part of mitigation strategies. Escaping of the URL is already in place:

curl 'http://mydomain/images/?<script>alert('hello')</script>'

Resulting in:

Cannot GET /images/?&lt;script&gt;alert(hello)&lt;/script&gt;

Addition of express-sanitized has also been implemented for further security measures.

However, testing the original scenario still reflects the request parameter back:

curl 'http://mydomain/images/?41b68(a)184a9=1'
Cannot GET /images/?41b68(a)184a9=1

This behavior can be attributed to the absence of HTML insertion in the URL.

All responses to static asset GET requests are handled through

app.use(express.static('static-dir'))
, which processes the query accordingly. express.static utilizes dependencies like serve-static and parseurl.

Answer №1

The issue arises from the response generated by Express for invalid GET requests, which typically looks like:

Cannot GET /pathname/?yourQueryString

This response may be suitable in many cases, including serving static assets. However, there are situations where only requests for specific static assets should be considered valid, such as:

GET /pathname/your-file.jpg

In my scenario and possibly for others, a custom 404 handler is in place to handle these instances:

var data = {
    status: 404,
    message: 'Not Found',
    description: description,
    url: req.url
}; 

This custom handling is implemented for invalid template requests in app.js using:

app.use('/template-path/*', function(req, res, next) {
    custom404.send404(req, res);
});

To address requests to static folders explicitly, I have now included dedicated handlers:

app.use('/static-path/*', function(req, res, next) {
        custom404.send404(req, res);
});

If needed, an additional step could involve removing request query parameters before returning the 404 response:

var data = {
    status: 404,
    message: 'Not Found',
    description: description,
    url: url.parse(req.url).pathname // requires var url = require('url')
};

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The POST method in Node JS request-promises does not properly handle string inputs

When I am trying to establish a connection between my node.js module and another server, I utilize the 'request-promise' library. My implementation for posting data looks like this: rp.({ method: 'POST', headers:{ 'Conte ...

Update JSON data in ng-blur event using AngularJS

Could you offer some guidance on how to push the content from a text box into JSON when I click outside of the box? Below is the code for my text box: <input type="text" name="treatmentCost" class="form-control" ng-model="addTemplate" /> And here i ...

Tips for efficient navigation through posts when they are loaded via a JSON file

Check out my Plnkr demo: http://plnkr.co/edit/brWn6r4UvLnNY5gcFF2X?p=preview Let's say I have a JSON file: { "info": { "test1": "test", "teste2": "test" }, "posts": [ { "name": "lorem ipsum", "content": "sit a ...

Filter the ng-repeat list dynamically by triggering ng-click event

I am currently developing an application on that requires users to be able to filter a list of credit cards by clicking on filters located on the interface, such as filtering for only Amex cards or cards with no fees. Although I have successfully bound t ...

Storing data in a TypeBuffer and then retrieving it from a file can lead to surprising outcomes

Upon executing the following code: var list = new Uint32Array(16); for (var i=0; i<16; ++i) list[i] = i; fs.writeFileSync("list", new Uint8Array(list).buffer); console.log([].slice.call(new Uint32Array(fs.readFileSync("list")))); We anticipate the out ...

I'm building an angular website and considering using Ionic to develop the corresponding mobile apps. Can you recommend the simplest approach for this integration?

I have developed a responsive website using Angular 4 with Lumen serving as the Rest API. The website functions smoothly on both desktop and mobile browsers, but I now intend to venture into developing mobile applications. What would be the most straightf ...

Tips for adding an array to an array of objects with AngularJs

I'm facing an issue with the array structure in my code. Here's what I currently have: $scope.arrayList=[{FirstName:"",LastName:""}]; $scope.Address=[{address:"",PhoneNumber:""}]; What I want to achieve is to push the $scope.Address array into ...

Issues with ng-repeat causing the Angular Editable table to malfunction

<table class="table table-bordered"> <tbody> <tr ng-repeat="playerOrTeam in template.editableTable track by $index"> <td style="text-align: center;" ng-repeat="playerOrTeamCat in playerOrTeam track by $index"> ...

Using middleware in Express to handle GET requests

Can the request object sent to any route be accessed globally in Express, without having to explicitly access it in a .get method or similar? ...

nvd3 - multiBarHorizontalChart - total exceeds 100%

I am currently using angular-nvd3 and I am facing an issue with presenting horizontal bars that display both count and percentage. The problem arises when the sum of the percentages exceeds 100%, resulting in a total of 101%. Here's an example for ref ...

Converting JSON DateTime objects to local time in JQuery without considering timezones

I am struggling with parsing a JSON DateTime object using moment.js. Despite trying various methods recommended on Stackoverflow, nothing seems to work in my case. In my application, I save DateTime values in UTC format and when displaying them, I need to ...

How can I include already installed packages in the 'dependencies' and 'devDependencies' sections of my package.json file after deleting the original package.json?

Contemplating the multitude of packages I added to my Project using npm, I inadvertently deleted my package.json file while tidying up. To remedy this, I executed the command nmp init to generate a new package.json file. The resulting package.json file a ...

What steps do I need to follow in order to utilize Express Generator to create a node skeleton with an HTML view

Is there a way to create a skeleton for Node.js using Express generator with an HTML view engine? For example, we typically do npm install -g express-generator express -v pug but it seems we cannot create a skeleton for express -v html ...

Leveraging functions in a Node.js module

I am struggling with using a function inside a Node.js module. I have implemented a custom sorting function to sort an array of objects based on the value of a specific property. exports.getResult = function(cards) { cards.sort(sortByField('suit& ...

Disable location prompt feature when using AngularJS with Maps API

For my web application, I developed a feature that includes a map with custom markers using Angular loops: <map data-ng-model="mymap" zoom="4" center="[38.50, -95.00]" style="heigth:375px"> <div ng-repeat="item in list"> <marker pos ...

I'm encountering an issue where the database table in Postgres is not updating correctly while working with Node

Currently, I am working on a CRUD application where I can successfully read and delete data from the database table. However, I have encountered an issue when trying to update specific data for a particular route. Every time I attempt to update the data in ...

What is the best way to send two mongoose find queries to the correct GET route?

I am facing an issue with my app where I have two separate routes using app.get to render "/" and fetch data from two different MongoDB collections using mongoose find{} methods. I also have corresponding post routes that redirect the data entered in forms ...

Tips for setting up a React TypeScript project with custom folder paths, such as being able to access components with `@components/` included

I'm looking to streamline the relative url imports for my React TypeScript project. Instead of using something messy like ../../../contexts/AuthContext, I want to simplify it to just @contexts/AuthContexts. I attempted to update my tsconfig.json with ...

Strategies for capturing a 404 error in an Express router

Trying to capture the 404 page not found error in an express router. Using a simple example : const express = require('express'); const app = express(); const router = express.Router(); // ROUTER MID BEFORE router.use((req, res, next) => { ...

Node.js sessions cookies are not being generated properly as req.cookies['connect.sid'] is not being created, and req.sessionID is changing every time the page is refreshed

In my setup, I am working with express 4.13.3 and express-session 1.11.3. Below is the session configuration I have implemented: app.use( session({/*store: new redis_store,*/name: 'connect.sid', secret: 'azerty is qwerty', resave: fals ...