9

I am building a REST API to store security sensitive data for both my client and third-party partners.

Each request is validated using an HMAC of certain data which is keyed on a temporary key assigned for a short duration after the user is logged in. Of course everything runs over TLS. Every request gets logged, along with the keys to any data returned, as well as the keys to any data that would have been returned if the request were not blocked for some reason.

If the data is not present, or if the data at a location may be read by a particular user, but not updated, or if the update request is malformed, should the server return a meaningful error message, or not?

  1. If the user does not have permissions to perform an action, a 401 or 403 response should be returned, indicating that the request failed due to lack of permissions to perform the action. Other response codes may be used in the case where the data is malformed, or the expected data types do not match (sending a string to an int field, etc.). Basically, follow good REST/HTTP practices and log everything, but don't provide any information to the user beyond a basic hint as to what went wrong.

  2. Never give anyone any information, in case it could be used against the system in some way. Only ever return a 500 error, with no description of any kind. There is some level of disagreement as whether or not to even return a 404, or if an empty response or 500 error should be returned instead. If a third-party developer is encountering these responses, and doesn't understand why, they must contact our company, have someone look into the logs and explain how to make the requests properly.

Does anyone have "from the trenches" experience as to which methodology makes the most sense? Of particular concern is how to balance security with usability and support requests.

3 Answers 3

4

Short version:

Be informative enough to support legitimate users of your application, but no more than that.

Long version:

First of all, there is no single answer for this, because it depends upon the context of the application. If you're releasing an open-source API for your product to allow people to write clients, then you want to lean in the direction of providing useful feedback so they can debug their code and write useful error handlers. If you're releasing closed-source client software to interact with your closed-source server, then you can be a little more restrictive, because you're only impacting yourself.

Second of all, the RESTful model implies in part that you're going to return HTTP codes with semantic meaning (e.g., 404 for "Not Found", not just 500 for everything). Of course, REST is just a way of doing things, so it's not like the REST auditor will rap your knuckles if you don't, but if you're using a model, you should consider that it has reasons for being designed as it is.

Third of all, the most important security focus you can have is on the content of error messages, not the signifier. Returning a 404, 403, 405, 502, or 503 is good as it helps the endpoint determine - roughly - what went wrong. Returning a stack trace from your Tomcat server, on the other hand, is way over the line - and it's probably the default, so be careful!

Finally, my experience "from the trenches" was as I've described: return the right HTTP error code, but don't wax poetic about it, "503" says "Service unavailable" and that's it. For things that are not HTTP-level issues, we return a 200 with a short application-layer error code. Codes are numeric, and can be found in the API, and so do provide "an attacker" with some information - here they had the wrong password, here they had too many concurrent connections, here they had "objectionable content". Yes, that's providing an attacker a way to map the system. The value of having a system that can be debugged by and for legitimate users outweighed the security benefit gained by obfuscating errors with a generic return value. For example, I'm willing to bet a smart attacker could differentiate between authentication error and WAF violation by paying close attention to the round trip latency, so I'm not losing all that much by giving it to him in an error code.

1
  • This is more or less the way that I have handled things in the past. My experience is that using the proper status codes and generic responses (and no more) has a lot more benefit than obscuring everything. A system can be both transparent and secure. Anyone can look up how async encryption works, but it isn't generally worth the time to try to break it. Most of the arguments against this approach have come from team members with very little web experience, who generally don't understand what HTTP codes are for.
    – drz
    Commented Jul 18, 2013 at 14:09
2

I would avoid error 401 as it triggers the browser to show an HTTP Authentication login box. This is annoying and confuses your users.

Other than that, return any error code you want, just bear in mind that certain clients will do certain things given your response code.

For example, a 500 or 403 may prevent your response from being indexed by search engines, while a 200 may not. The error code itself doesn't really disclose anything security-wise. Anything in the 4xx range says "the client did something wrong" while anything in the 5xx range says "the server did something wrong".

1

In case of a restful service I'd combine both of the options. But I'd just return 401 or 403 (do not distinguish between them) and simply make a generic error for 404 and 500, I'd use 200 instead with a custom message rather than 404 or 500.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .