9

XSS & Single-Page Apps

I'm researching on web security, and have seen that token based authentication is good for CSRF prevention, distributed system architectures and processing performance.

But another problem is XSS. Not specifically talking about the injection itself, but the libraries. With single-page apps developers normally include hundreds of different modules into their code, which could later on execute maliciously when the app is in production.

Patching XMLHttpRequest

So I had the idea to patch the XMLHttpRequest property and take control of the original "native code" function, preventing third-party code from making ajax requests.

(function () {
  // my code
  let XHR = window.XMLHttpRequest
  window.XMLHttpRequest = null
})()

// load third-party code after...

I tested this in the console with facebook and youtube... all their ajax loaded content stop working.

Malicious Example

An example of uncaught malicious behavior is code that only executes in production by checking if the window.location is something like "app.x.com" so the developer doesn't realize of the ajax requests during development.

Patching the XMLHttpRequest property would prevent this, and taking into consideration that all other mesures were taken to prevent XSS (sanitization), this would close the final gap and let you take control of network requests, preventing malicious code from stealing the auth tokens.

Final Doubt

Are there any caveats to this approach? (security-wise)

Hadrian
  • 193
  • 4

2 Answers2

8

Are there any caveats to this approach? (security-wise)

Yeah, it's not very thorough, you can get a new instance of the constructor from a new window object instead:

XMLHttpRequest = null;

var iframe = document.createElement('iframe');
iframe.style.display = 'none'; // optional
document.body.appendChild(iframe);
var XHR = iframe.contentWindow.XMLHttpRequest;
console.log(new XHR());

You would have to overwrite a lot more things to ensure a XMLHttpRequest cannot be accessed, that's just 1 way to do this.

For XSS protection, just use a Content Security Policy and only use trusted libraries from trusted sources.

Alexander O'Mara
  • 8,774
  • 6
  • 34
  • 38
2

Even if this would work and you could block JavaScript from performing XMLHttpRequests - which as shown by @Alexander is not the case (ActiveXObject would be another alternative) - it doesn't really limit the dangers of XSS.

An attacker still has a number of possibilities:

  • Defacement
  • Phishing: For example, add a login form, which sends the entered data to an attacker controlled server
  • Extracting Data: While an attacker cannot send acquired data via XMLHttpRequest, they can force a redirect via meta tag refresh and send the data that way.
  • CSRF: The token can be acquired as described above, then a form can be created and submitted via JavaScript.
  • Network Requests: The form example from above is also how any network requests can be performed without using XMLHttpRequests.

There really is no good way to prevent all of these points (at the very least, you would need to prevent any changes to the DOM, which I don't think is possible).

You need to trust the third party JavaScript libraries that you use.

If you do not trust the vendor, you need to reproduce the functionality yourself.

tim
  • 29,018
  • 7
  • 95
  • 119