Restrict sending custom request headers to allowed hosts

Problem

DAST sends user configured custom request headers with every request, regardless of the host. This can cause the following issues:

  • A request that was previously a simple CORS request becomes a preflighted request
  • Scans are slower due to the extra preflighted HTTP request (one per external resource request)
  • If the external host rejects the preflight request due to the additional header, it's likely the user's scan will fail (missing JavaScript, CSS, etc)
  • If the external host accepts the preflight request despite the additional header, the the request header is sent to the external host. This can be a security issue, depending on what was configured in the request headers.

This only affects requests made by a browser.

Proposal

Limit custom request headers to only be sent on DAST_BROWSER_ALLOWED_HOSTS. This is a breaking change.

This applies to the CI/CD variables DAST_REQUEST_HEADERS_BASE64, DAST_REQUEST_HEADER and DAST_REQUEST_HEADERS.

Proof that tokens may be leaked

The following redacted log was taken from a customer scan:

2022-10-06T05:30:16.000 TRC CHROM event received  {"method":"Network.requestWillBeSent","params":
{"requestId":"240.6","loaderId":"4E1105698FC8652047FB127FDC470C3B","documentURL":"<redacted>","request":
{"url":"https://use.fontawesome.com/releases/v6.2.0/css/all.css","method":"GET","headers":{"Authorization":"Bearer <secret-token>",...

Reference

From customer issue, see internal Slack thread.

Example

A user has a target website, that loads bootstrap JavaScript from an external CDN. A simple CORS request is made, to get the JavaScript. This is a GET HTTP request, where the response is status 200, the resource body contains the JavaScript and there is a Access-Control-Allow-Origin response header.

Page source Network requests
<html>
<body>
Hello world!

<script>
  let host = "maxcdn.bootstrapcdn.com"
  let url = "https://" + host + "/bootstrap/3.3.7/js/bootstrap.min.js"
  fetch(url)
</script>
</body>
</html>

Suppose the user adds a custom authorization token header, DAST_REQUEST_HEADERS: "Authorization: Bearer secret.token". The following network requests show that an extra request is made, a preflight CORS request. In this case, maxcdn.bootstrapcdn.com rejects the preflight request, therefore the JavaScript is unable to load.

Page source Network requests
<html>
<body>
Hello world!

<script>
  let host = "maxcdn.bootstrapcdn.com"
  let url = "https://" + host + "/bootstrap/3.3.7/js/bootstrap.min.js"
  fetch(url, {headers: {"Authorization": "Bearer secret.token"}})
</script>
</body>
</html>

Implementation plan

Edited by Philip Cunningham