RavenDB 4.0 Unsung heroesThe design of the security error flow
This is again a feature that very few people will even notice exist, but a lot of time, effort and thinking went into building. How should RavenDB handle a case when a user make a request that it is not authorize to make. In particular, we need to consider the case of a user pointing the browser to a server or database that they aren’t authorized to see or without having the x509 certificate properly registered.
To understand the problem we need to figure out what the default experience will be like, and if we require a client certificate to connect to RavenDB, and the client does not provide it, by default the response is some variation of just closing the TCP connection. That result in the client getting an error that looks like this:
TCP connection closed unexpectedly
That is not conductive for a good error experience and will typically cause a user to spend a lot of time trying to figure out what the network problem is, while everything is working just fine, the server just doesn’t want to talk to the user.
The problem is that at the TLS level, there isn’t really a good way to give back some meaningful error. We are too low level, all we can do is just terminate the connection.
Instead of doing that, RavenDB will accept the connection, regardless of whatever it has a valid certificate (or even any certificate) and pass the connection to one level up in the chain. At that point, we can check whatever the certificate is valid and if it isn’t (or if it doesn’t have the permissions to do what we want it to do we can use the protocol’s own mechanism to report errors.
With HTTP, that means we can return a 403 error to the user, including an explanation on why we rejected the connection (no certificate, expired certificate, certificate doesn’t have the right permissions, etc). This make things much easier when you need to troubleshoot permissions issues.
More posts in "RavenDB 4.0 Unsung heroes" series:
- (30 Oct 2017) automatic conflict resolution
- (05 Oct 2017) The design of the security error flow
- (03 Oct 2017) The indexing threads
- (02 Oct 2017) Indexing related data
- (29 Sep 2017) Map/reduce
- (22 Sep 2017) Field compression
Comments
yep, but can this behavior help some malevolent user trying to hack the system?
Oren, I think I'd agree with Diego here - at least make it an admin setting so by default it just gives a 403 and you have to turn on the detailed error reporting.
to be clearer: I'm not questioning the technical decision, but simply the fact to returning info to the user. simply logging this error server-side, or activate this behavior to a specific admin setting as paul suggests, looks more "safe" to me.
How could a 403 Forbidden response help a malicious user? What are they going to do with the information that a client certificate is required, that it is expired, or that it doesn't have permissions? It's no different than a regulat API respond with 401 if the authorization header is missing/incorrect and 403 if it doesn't have permissions.
@mircea "including an explanation on why we rejected the connection (no certificate, expired certificate, certificate doesn’t have the right permissions, etc"
@Diego Guidi, if should never be a security issue to return operational messages to a user. Also security through obscurity is not security at all.
@pop of course, but often when you log to an account with wrong user or password, error message don't specify of password or username is wrong. just an example.
@Diego Guidi, When you use a wrong password it doesn't say "Connection Error" either. You should not return specifics which might be considered information disclosure but general information which contains the least amount of data possible but is still not ambiguous for operational purposes.
I think Ayende's idea is great. Errors have to be understandable without knowing arcane details about the technology used. If you want to disclose nothing, that's fine - but do not expect that anybody uses your technology without pointing a gun to his head. Secure systems have to be easy to use - boing unable to understand that is at the core of slow SSL / PGP etc. adoption
@pop +1 for that least amount of data possible but is still not ambiguous for security: http status code should be enough. my2cents.
@hds of course, but a client that made requests is are a different beast that "user" trying to configure a db accessibile from external clients. simply, different users needs different information.
I also think it should be a config setting.
Because if I were debugging this I would think that the connection went OK (because it returned a 403), so the certificate and the rest of the chain are ok. So I would get stuck on thinking that RavenDB has some kind of its own certificate information which is incorrect (because the x.509 was accepted so they can't be talking about that one).
So the message has to make it absolutely clear that it is talking about which certificate it is talking about (specifically the one it just accepted as correct) and even then it should be a config setting because in our internal guidelines we for example skip any connection troubles if a user gets a 403 then it is not a connection issue but an application issue.
I started answering to the comments, but this turn out to be big enough to be its own post. It will show up on Friday, but in the meantime you can read it here: https://ayende.com/blog/180129/security-analysis-on-error-reporting?key=d341bd7d34e54a60870ca2ff9cc4dff3
Comment preview