I've asked this on Stack Overflow because it is related to a programming problem (how to mititgate vulnerabilities in code) but I do have some broader questions, and a lack of understanding about how to mitigate the vulnerability. Please note the update section below where I have put in place the mitigations in these linked questions here and here.
I've run a pen test tool (Burp) against my node(express)/angular application and it identified a reflected XSS vulnerability specifically when attempting a
GET request for static assets (noticeably vulnerabilities were not found for any of the requests being made when a user interacts with the application).
The issue detail is:
The vulnerability was tested by passing an arbitrary url parameter to the request like so:
The response 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
You can see that I have CSP in place (using Helmet to implement) and other protections against exploits. The app is served over https, but no user auth is required. CSP restricts requests from the app's domain and google analytics.
The pen test report advises validating input (I am, but surely that would make requests including data sent by a user unsafe if I wasn't?), and encoding html which angular does by default, plus GET request urls are being escaped (see update below).
I'm really struggling to find a solution to preventing or mitigating this for those requests for static assets:
- Should I whitelist all requests for my application under csp?
- Can I even do this, or will it only whitelist domains?
- Can/should all responses from node/express to requests for static assets be encoded in some way (see update on url escaping below)?
- Or that GET request param can somehow be evaluated in my application code?
Escaping of the url is already in place so:
Cannot GET /images/?<script>alert(hello)</script>
I've also put express-sanitized in place on top of this.
However, if I curl the original test the request param is still reflected back.
curl 'http://mydomain/images/?41b68(a)184a9=1' Cannot GET /images/?41b68(a)184a9=1
Which you would expect because html is not being inserted into the url.
The responses to GET requests for static assets are all handled by
app.use(express.static('static-dir')) so the query is passed into this.
express.static is based on serve-static which depends on parseurl.