A researcher recently reported an issue in a site about using script on a 3rd party site to discover if a user is an admin.

Here's the scenario:

  • Main site is target.example
  • Attacker site is evil.example
  • target.example has SSL and HSTS and redirects all http traffic to https using a 301 redirect
  • the session cookie on target.example is httponly and "secure"
  • evil.example has javascript that loads javascript src from target.example/admin/utility and using success/error of loading that html page can execute attack javascript

Example javascript that would be on evil.example:

<script type="text/javascript" 
onload="alert('Hello, Admin')"
onerror="alert('Ok, you are not the admin')" 

This technique leverages the fact that the site returns a 403 instead of a 200 on admin pages. The suggestion was to return a 200 error on admin pages for logged out users instead of returning the 403 error.

The risk presented by returning a 403 or 404 is that the attacker will only send attacks for users they know are admins. This would let the attacker fingerprint the site or attempt to exploit it and the only "noise" in the logs would be higher than normal number of 403 errors in the error log which might not raise suspicion as much as other kinds of activity might.

The question: Does it actually add practical security benefit to return a 200? Is this a thing that many sites do?

  • What business has an admin only local document accessing third party hosted resources without a "benign location" local intermediary in the first place? Try to minimize dependency on external resources, and for the rest, use an intermediary locally hosted redirector / proxy (sometimes also called anonymizers) that will intercept any external requests, request them on behalf of your admin client, and send them back to the request originating client using a local path. There's plenty of reusable resources that will do this for you that can be found online, and your problem will disappear.
    – TildalWave
    Jul 23 '13 at 21:40


I would not return a 200 OK unless you want to tell web-clients that there is a resource available at the requested URI and that it is accessible (eg: to be indexed by search engines). Especially, I would never return a 200 OK for protected areas as long as the requesting client has not authorized.


Let me try to provide you with a bit of insight on the HTTP status codes you mentioned:

200 OK 

Tells bots (and geeks) that the URI request is valid and the target resource (html page, css file, ZIP download, whatever) exists and is being returned together with that header.

What happens: requesting client gets told that resource exists and is available. It can and will get indexed by bots like search engines.

403 Forbidden

Tells bots (and geeks) that the URI request is invalid as the client requesting the data does not have appropriate authorization to request that resource.

What happens: requesting client gets told that resource exists but that he's not authorized to fetch it. It's like slamming the door on someone's nose while saying "you aren't allowed to do that" because authentication is required. Benign bots and search engines will respect that and treat this 403 Forbidden almost the same as if it were a 404 Not Found. They will not retry to visit the URI unless they have good reason to revisit the URI. Example: when checking new links pointing to that URI.

404 Not Found

Tells bots (and geeks) that the URI request is invalid as the URI that is used does not point to existing data on the server.

What happens: requesting client gets told that resource does not exist. It's like saying "nothing here, don't try again". Benign bots and search engines will not retry to visit the URI unless they have good reason to revisit the URI. Example: when checking new links pointing to that URI.

From a security standpoint…

You should always return the correct header matching the situation. Besides the obvious protocol reasons, let me give you a simple example why correct headers are needed: Imagine someone malicious trying to hack your site. If you always return a 200 OK you will have a hard time filtering the good from the bad requests. But if you - for example - notice a series of 403 Forbidden in your server logs, it's easy to nail down the timestamp, IP, and User Agent... which helps you filter and/or block such client requests.

  • 2
    Yes, I'm familiar with response code purposes ;) The last paragraph is solid advice. Thanks for it.
    – greggles
    Jul 22 '13 at 15:48
  • 1
    @greggles Thanks for the positive feedback! As for the status-code info: I couldn't read your knowledge level from your question, so I provided that info just in case. After all, there's always that next person reading this stuff that who knows if he/she knows status codes like we do. ;) Hope I didn't step on any toes by going in too detailed?
    – e-sushi
    Jul 22 '13 at 16:01
  • 3
    No problem at all. Your very appropriate use of headers let me skim to the part I cared about ;)
    – greggles
    Jul 22 '13 at 19:50

When a user tries to access an "admin" page, his browser will sure get an HTTP response code (200, 403...) but it will also obtain a page which will sure be distinct depending on whether the user is "an admin" or "not an admin". The Javascript which triggers the loading can look at the code but also at the page. Masquerading the 403 as a 200 will impair only the stupidest of attackers, who do not really care -- that is, precisely the least worrisome of attackers.

You may note that when a user reaches a site which requires authentication, that site will often redirect the user to a "login page". That is, the site does not send a 401 response (which would be what HTTP prescribes), but instead a 200 response for a page which just happens to contain some text for human consumption, the text saying "You must log in". This is not, and has never been, a security feature; sites to that because the popup windows that browser display when faced with a 401 are just plain ugly.

Your case of "403 vs 200" is just the same: you don't want to do it for security reasons (because it will not bring any security worth talking about) but you may want to do it for aesthetic reasons (e.g. to smoothly redirect unauthorized users to a good-looking "non-admin" page).

  • 2
    You said "The Javascript which triggers the loading can look at the code but also at the page." but I thought the Same Origin Policy prevents the javascript from looking at the page. Can you expand on how the script could read the page?
    – greggles
    Jul 22 '13 at 15:55
  • You are right, in this context the SOP will try to block the actual reading, but may leak the error code (or at least the fact that there was an error). There is indeed a slight information leak that way. I don't find it very serious, though. This deserves some extra thinking time.
    – Tom Leek
    Jul 22 '13 at 16:56

IMHO this only creates a very small hurdle for anyone attacking the site to bypass. Does that mean you also fake the content when the login is invalid? Create an entire honeypot for all invalid logins?

Most invalid logins are not caused by terrorists trying to bring about the end of civillization as we know it - usually it's just the caps lock button. Hence you do need to tell users that the authenticaton information they've provided was not successful.

If the authentication response is intended to be machine readable then there's even more reason for making it simple and unambiguous (but I may be inferring too much from your use of Javascript).

will only send attacks for users they know are admins

...then again perhaps not. This, combined with the javascript code makes me think there's something a bit fishy in the security model here.

There are lots of things you should be doing to secure authentication transitions, but I think deliberately faking the HTTP response code in reply to invalid credentials in an effort to deter attackers is counter-productive.

(Faking the response code in reply to a request already believed to be an attack is a different story).

  • 2
    I think you've misunderstood the scenario (and/or I explained it poorly). There's no credentials involved. It's about javascript on a 3rd party site that can detect whether a user's browser has an active session on the site that is authenticated as an admin.
    – greggles
    Jul 22 '13 at 15:47
  • Sorry - should have read it more carefully. Perhaps not setting the secure and httponly flags on authentication cookies isn't a good idea? (it's still relatively trivial to scan the HTML content for, e.g., "invalid")
    – symcbean
    Jul 22 '13 at 22:57
  • 2
    I think the same origin policy would prevent scanning the html content. I'm not sure I follow the double-negative in your comment about secure and httponly flags on cookies. Can you elaborate on that?
    – greggles
    Jul 23 '13 at 18:32
  • While httponly cookies are still sent with Ajax requests, your example above is predicated on the secure flag not being set on the cookies, and the detection of an authenticated state on a non-SSL URL: not best practice for securing a site. If the URL had been httpS://www.target.example/admin/utility then the point would have been moot.
    – symcbean
    Jul 23 '13 at 20:08
  • 2
    I just updated the question - cookies on the site are httponly and secure and the site uses ssl and hsts. I can't really say what the "right" behavior is, but I can say that in my testing that this attack (disclosing information) still works in Chrome and Firefox latest.
    – greggles
    Jul 23 '13 at 21:24

If this is an issue, then you can implement CORS Access Control header, rejecting/fake requests that comes with an Origin that is not from a trusted domain.

CORS-header aware browsers will send an Origin header when making a cross-origin request, giving the server a chance to reject/fake the request. If your site administrators are using a browser that can make CORS-request but are not CORS-header aware, then they really should consider switching to a more secure browser.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.