Question

OK, probably best to give an example here of what I mean.

Imagine a web based forum system, where the user authentication is done by some external method, which the system is aware of.

Now, say for example, a user enters the URL for a thread that they do not have access to. For this should I return a 403 (Forbidden), letting the user know that they should try another authentication method, or a 404, not letting them know that there is something there to access.

Assuming I return a 403, should I also return a 403 when they access a URL for a topic that doesn't exist yet?

Edit: the example above was more of an example that something IRL.

Another Example, say I expose something like

/adminnotes/user

if there are Administrator notes about the user. Now, returning a 403 would let the user know that there is something there being said about them. A 404 would say nothing.

But, if I were to return a 403 - I could return it for adminnotes/* - which would resolve that issue.

Edit 2: Another example. Soft deleted Questions here return a 404. Yet, with the right authentication and access, you can still see them (I'd presume)

Was it helpful?

Solution

Above everything else, comply with HTTP spec. Returning 403 in place of 404 is not a good thing. Returning 404 in place of 403 probably is ok (or not a big blunder), but I would just let the software tell the truth. If user only knows the ID of a topic, it's not much anyway. And he could try timing attacks to determine whether this topic exists.

OTHER TIPS

I would go for a 307 redirect to NoSuchPageOrNoPermissions.html where you nicely tell the user they either mistyped the url or don't have permissions.

This will not break compliance and not send out the incorrect message.

If you are very paranoid you could put in a random wait before returning the redirect so time analysis would be harder.

As for all the people here asking why protect directories try these examples

1. User Name

Imagine we are an ISP we give each user a webpage at www.isp.example/home/USERNAME and email address of USERNAME@isp.example. If an attacker does a dictionary attack sending requests to www.isp.example/home/[Random] and can tell if that is a valid user name we now can generate a list of valid email address to sell to bad people.

2. What Folder

Bob is running for office he has an account with the poster and uses his site to store personal information. But he has secured it by making it private folder his public pages are at: www.example.com/Bob and his secret folder is www.example.com/Bob/IceCream he has marked this as private so any one requesting gets 403. however www.example.com/Bob/Cake returns a 404 as Bobs secret is icecream not cake.

Alice the reporter does a dictionary attack on Bobs site trying

  • www.example.com/Bob/Cake - 404
  • www.example.com/Bob/Donuts - 404
  • www.example.com/Bob/Lollies - 404
  • www.example.com/Bob/IceCream - 403

Now Alice knows Bobs secrets and can discredit him as an ice cream eater.

I think you should send 307 (Temporary Redirect) for requests for "/adminnotes/user" to redirect unprivileged clients to "/adminnotes/". So the client makes a request for "/adminnotes/", therefore you can send back 403, because it is forbidden.

This way your application stays HTTP compliant, and unprivileged users won't learn much about protected data.

What "privacy" is protected by hiding from users the existence of a particular thread?

I'd say that returning either 403 or 404 on a thread they cannot access is OK. Returning 403 on a thread that does not exist is a bad idea.

No website in the world does what you are suggesting, so by this example we see that it is probably best to follow the standard and return 404 when the resource does not exist and 403 when it is forbidden.

I don't see why you worry about privacy issue from the URL. In the case of stackoverflow, you can put any text after the QuestionID number. For example, Return "correct" error code, or protect privacy? still comes back to this question.

Don't forget that a 404 can also technically be revealing information. For example, you could tell who didn't have adminnotes. Depending on the circumstances, this could be just as bad as indicating that the resource did exist.

In my opinion, errors should not lie. If you give a 404, it should always be the case that the resource does not exist.

If you're dealing with sensitive information, then you can always say that the user doesn't have permission for the resource. This doesn't necessarily require that the resource exists. A client may not have permission to even know if the resource exists. Therefore you would need to provide a permission denied error for any combination of /adminnotes/.

That said, the official spec seems to disagree, here's what the official rfc says about the errors at http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html:

10.4.4 403 Forbidden The server understood the request, but is refusing to fulfill it. Authorization will not help and the request SHOULD NOT be repeated. If the request method was not HEAD and the server wishes to make public why the request has not been fulfilled, it SHOULD describe the reason for the refusal in the entity. If the server does not wish to make this information available to the client, the status code 404 (Not Found) can be used instead.

10.4.5 404 Not Found The server has not found anything matching the Request-URI. No indication is given of whether the condition is temporary or permanent. The 410 (Gone) status code SHOULD be used if the server knows, through some internally configurable mechanism, that an old resource is permanently unavailable and has no forwarding address. This status code is commonly used when the server does not wish to reveal exactly why the request has been refused, or when no other response is applicable.

I'm no expert, but I think it's crappy to give a "not found", when a resource may exist. I'd prefer a "forbidden", without a guarantee that the resource exists, implying that you would need to authenticate somehow in order to find out.

Lets say you did return a "page not found" error when you detect that the user does not have the correct access rights. A malicious person with the intent of hacking will soon figure out that you would return this in place of the access denied.

But the real users who mistype a url or use a wrong login etc would be confused and it would take no end of explanations and release notes to explain your position to the customers, TAC etc. In exchange for what ?

The intention is good, but i'm afraid this policy you propose might not work out the way you wanted it to.

My suggestion is to:

  1. If Not Exists_Thread then return 404
  2. If Not User_Can_Access_to_this_Thread then return 403
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top