2

While answering this question on Security.SE, I realized that there may be a need for a way to disable AJAX requests from all domains, including the original domain itself. This would be useful if I have a site which hosts user-submitted JS and I don't want that JS to be able to access my site via AJAX on a modern browser (similar to how cross-domain AJAX is prohibited unless set in a header)

Is there any way I can disable same-origin AJAX in PHP or Apache? I'm looking for something similar to the Access-Control-Allow-Origin: * header (set via header() or .htaccess), except that the effect is the opposite -- the browser is told not to allow any AJAX calls to the page.

I know that the end-user can always mess with the headers on their own and allow AJAX. I don't mind that, I want to prevent oblivious visitors from being affected by same-origin AJAX in uploaded code.

Community
  • 1
  • 1
Manishearth
  • 10,990
  • 5
  • 52
  • 73
  • I guess no, because all these headers can be easily edited - it's not correct to trust data from user. – OZ_ Feb 22 '13 at 09:07
  • @OZ_: IIRC, AJAX can't edit headers. I don't mind if the visitor messes with it. I want to prevent oblivious visitors from being affected by AJAX calls. – Manishearth Feb 22 '13 at 09:08
  • [Related](http://stackoverflow.com/questions/3102819/chrome-disable-same-origin-policy) and [related](http://stackoverflow.com/questions/330427/can-i-disable-sop-same-origin-policy-on-any-browser-for-development). Most of what is discussed there seems to hint towards the answer being... no, not without launching the browser with certain operational flags or options... – Lix Feb 22 '13 at 09:09
  • 1
    @Lix: No, that's the opposite of what I want. Those posts are asking for a way to allow cross-domain AJAX. I'm trying to _disallow_ same-domain AJAX. – Manishearth Feb 22 '13 at 09:11
  • 1
    So one user can submit Javascript that will be run on another user's browser? I think AJAX is the least of your security worries... – lonesomeday Feb 22 '13 at 09:18
  • @lonesomeday: Oh, it's not _my_ application. But I'm curious as to what other problems can be caused by submitted JS... (see the security.se post I linked to above, and add an answer to it if you have any additional issues) – Manishearth Feb 22 '13 at 09:20
  • Unless you have set up serverside logic to receive AJAX requests, why would you worry? By default, they are treated like any other request delivering either a site the user could access anyways or a 404. – MildlySerious Feb 22 '13 at 09:29
  • You can [use custom header in XHR](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#setRequestHeader()). Besides the `X_REQUESTED_WITH` header Jan mentioned below, XHR is a normal HTTP request. – Passerby Feb 22 '13 at 09:29
  • @MildlyInteresting: Hmm? You don't need any special serverside logic to receive AJAX. I'm looking for a way to (a) block it via the server side, or (b) make Chrome/etc block a same-origin AJAX request. – Manishearth Feb 22 '13 at 09:40
  • @Passerby: ah, damn. Looks like there isn't any way to do this then. – Manishearth Feb 22 '13 at 09:41

2 Answers2

2

Most JavaScript libraries will set the HTTP_X_REQUESTED_WITH header to xmlhttprequest. So looking for this and blocking such requests is probably the closest you can get to what you want. Otherwise, as you probably know, a XHR request is no different than a "regular" request.

Jan Hančič
  • 49,796
  • 15
  • 87
  • 97
  • So, how would I block this? `if ( $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest' ){die()}`? Aside from that, exactly what do you mean by "most" libraries.. Is there a way to get around this? (IIRC you can't modify headers in AJAX, so I guess that the browser imposes the header on it) – Manishearth Feb 22 '13 at 09:25
  • You can modify headers. See: http://api.jquery.com/jQuery.ajax/ By most I mean that jQuery etc will put that header into any XHR request by default. It's a unwritten standard of sorts ... – Jan Hančič Feb 22 '13 at 09:46
  • @JanHani: ah, I didn't know that :) – Manishearth Feb 22 '13 at 09:47
1

This might not be an exact answer to your question, but you could overwrite the XMLHttpRequest object before inserting the users JS:

window.XMLHttpRequest = false;

// Insert users JS here
MildlySerious
  • 7,578
  • 2
  • 24
  • 29
  • Yeah, I already knew this one. I was wondering if there was a better way to do it. (This won't prevent iframe magic, either, but I guess that no method will) – Manishearth Feb 22 '13 at 09:40
  • It would be hard to create a completely secure environment in this case.. If you don't already do that you should consider not executing the javascript before pressing a button the jsfiddle way. That will propably prevent a lot bad things happening. – MildlySerious Feb 22 '13 at 09:50