27

I am creating an API strcutured web application and in this application we have different layers which are doing their own job.

First layer is Validation layer which validate user input and if it passes the validation we move that to second layer (which is Access Control layer ) otherwise return the error message

Second layer is Access Control which checks if user has permission to perform the task it wants to perform, If user has permission it moves the request to next layer otherwise return error message

Third Layer is Controller Layer where we have the logic of application

My question is that is that ok to have validation layer before access control ? What if user are trying to perform a task which user doesn't have permission to and we are sending back validation error message ? User would be sending requests to an endpoint and talking with validation layer and once it passes the validation only then he would see the message You can't access this!

It feels strange to me so is it fine like this or what could be my other options in infrastructure this?

Muhammad
  • 399
  • 3
  • 7
  • 10
    It's also worth mentioning that validations often must reach out to the database to do their job, or a file store. If you do this before checking for access control violations, you essentially allow attackers to DDoS your database or file system by throwing massive amounts of traffic at that particular URL. – Greg Burghardt May 04 '18 at 11:54
  • In my case the same goes for Access Control Middleware, it checks a resource and see if the type of resource is accessible by user, if it's accessible I allow access otherwise don't – Muhammad May 04 '18 at 13:49
  • That's true. During a DDoS that layer will still hit your data store. With running that layer first you won't hit your data store for validations AND access control - you'll just hit it for access control. It reduces the size of the tsunami, but doesn't prevent it from hitting the beach. It gives you or your server team a fighting chance to respond to an attack before the whole system becomes bogged down. – Greg Burghardt May 04 '18 at 14:24
  • 6
    From a practical standpoint, access control should come before validation anyway - how are you going to validate the correctness of a user's request if they can't access the request in the first place? – Zibbobz May 04 '18 at 14:31
  • @Zibbobz validation is simple like checking if user is sending correct schema, like the parameter which should be integer is integer or something else – Muhammad May 05 '18 at 12:29
  • @GregBurghardt actually no data can be accessed from an unknown person, so if same user send data simultaneously we can counter that by rate limiting them or blocking the account altogether, so I don't think the protected data is simply open to ddos, let me know if I am wrong, thanks – Muhammad May 05 '18 at 12:31
  • @Muhammad My point is that, in a secure system, if a user doesn't have the permission to perform an action, then they shouldn't be able to *get* to that action in the first place. And even if they can somehow, you should *still* be checking whether they should have access as the first step - it should never come *after* validation. – Zibbobz May 07 '18 at 15:45

6 Answers6

59

It depends on whether knowing the validity of some input for a task that you aren't permitted to do is a security leak. If it is, you really should to do it the other way round.

The only safe response to an unauthorised user is "access denied". If sometimes the response is "bad request" and other times "access denied", you are sending information to an unauthorised user.

As an example, you could have a check in the validation of the "delete document" task that the named document exists. Someone with no permissions would be able to discern whether something exists by attempting to delete it, and comparing which error they receive back. A particularly determined attacker could enumerate all document names (under a certain length), to see which exists.

Caleth
  • 10,519
  • 2
  • 23
  • 35
  • 7
    +1, absolutely. If your data are in any way personally identifiable or sensitive in any other way, then security implications are much, much more serious than usability implications. – Kilian Foth May 04 '18 at 12:36
  • 4
    @caleth actually it wouldn't let you know if a certain document is in the system or not, this type of information only be given when you reach the controller layer. Validation just check the schema, it doesn't access the database - only access control & deeper layers do the database access. Also, access control layer only shows you same stuff while a resource exist or not. The only compromising thing is the schema which I am thinking if is ok or not – Muhammad May 04 '18 at 13:55
  • @Caleth Could you elaborate on your last comment? I don't see how that's the case given OPs comment. Seems in any case the only information being sent back is unprivileged information if the schema is publicly documented. – Rotem May 04 '18 at 14:20
  • 12
    @Rotem It's essentially impossible to determine in advance what information an attacker could take advantage of. Just because you haven't *found* a way to learn something you shouldn't, doesn't mean there isn't such a way. As an extreme example, there might not be any vulnerability *now*, but in the future somebody might add a check to the validation layer that *does* leak information because they didn't know it wasn't protected. – Kamil Drakari May 04 '18 at 14:25
  • 5
    @KamilDrakari that's not an extreme example, that's a perfectly reasonable example. Put another way - if you do validation before access control, any time a developer wants to add a validation step, they have to make a decision on whether that validation exposes anything sensitive. The chance of every dev getting that call right seems tiny. – mfsiega May 04 '18 at 16:53
  • I ended up with a model kind of like this one, but with one amusing exception. The delete command only operates on the id of the document, so trying to enumerate names is impossible. The enumerate function filters out stuff the user can't see so calling the enum function gets back an empty list. – Joshua May 05 '18 at 03:17
  • There's essentially no reason to do validation before access control and many reasons not to. Can you explain I'd you have a reason for designing g it this way? – Sandy Chapman May 05 '18 at 23:12
  • @SandyChapman the thing is, depending on what parameter I am getting the Access Control may or may not decline the request, for example: An endpoint `http://example.org/api/v2/documents?type=discarded` fetch the document by type but this type `discarded` may not be accessible depending on the user role. So in this example we would have to check if type is given in the right format and in the expected values – Muhammad May 06 '18 at 07:49
25

Well, there are multiple types of validation:

  1. Cheap basic sanity-checking, which verifies that the request is not obviously malformed.

    This is typically at least partially duplicated client-side, to avoid futile round-trips.

    Anyway, it should be done before access-control to make things easier and less error-prone, as it doesn't risk any information-leak.

  2. More expensive validation which still does not depend on any protected application-data.

    If there is such extra-validation, it might be after access-control not to avoid leaking data, but to hinder DOS-attacks.
    Sometimes simply executing the request does some of that validation implicitly at reduced or no cost, so it might be left out here.

    If all the validation of the first step is duplicated, it might make sense to duplicate parts of this client-side too.

  3. Additional validation depending on the protected application-data.

    Doing it before access-control obviously risks information-leaks. Thus, first do access-control.

Deduplicator
  • 8,591
  • 5
  • 31
  • 50
  • 3
    It would be ideal to perform access control at a policy enforcement point in your infrastructure even before reaching your API. A basic static set of validation (Ex: OpenAPI ) would be first, followed by deeper business validation. Even some static validation could potentially have impact on the availability of your app- ex [ReDOS](https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS) attacks. – felickz May 04 '18 at 15:34
  • @felickz: Yes, DOS attacks are a valid reason to defer validation until after authorization. It's a balance-act. Anyway, I split my first point to properly take that into account. – Deduplicator May 04 '18 at 15:54
  • Doing expensive validation before access control also risks leaking information due to timing attacks. If your system takes shorter or longer depending on the resource, then the attacker can infer aspects of the resource being requested. – Lie Ryan May 05 '18 at 03:50
  • @LieRyan: Which is the reason all the validation which is potentially before access-control does not depend on protected application data at all. – Deduplicator May 05 '18 at 08:37
14

There must be some validation before access control. Let's say SO's API has an endpoint "edit answer", then whether the user can edit a particular answer can depend on the answer (below a certain reputation, a user can only edit his own answers). So the "answer ID" parameter being well-formed must be verified before the access control layer comes into play; possibly also that the answer exists.

OTOH, as Caleth and Greg mention, putting more extensive validation before access control is a potential security risk.

So the hard rules are

  1. You must not disclose any information through validation that the user is not supposed to be otherwise able to find out.
  2. You must validate data before access control can use it to the extent that access control needs it.

Following both these rules may mean that you have to have some validation before and some after access control.

Sebastian Redl
  • 14,950
  • 7
  • 54
  • 51
  • 4
    This is the realistic answer. If its simple, straight input data structure validation, then there must be no qualms putting it first. It even protects Access control layer from specially designed inputs/packets. The validation that actually entails secure information leak or guessing, must be placed after access checks. – S.D. May 04 '18 at 15:30
  • That assumes answers are public. I dare saying a lot of API's will not even show you the data withou authentication. – TomTom May 05 '18 at 18:02
6

In addition to the possible frustration of receiving an 'access denied' after validating input; also keep in mind that the Validation layer, unless it is a very simple one, can always need information from the Controller. Keeping this in mind, I believe positioning Validation behind Access Control, closer to Controller makes more sense.

simurg
  • 322
  • 1
  • 4
2

That depends on what you mean by validation layer - if by that you just mean checking the syntax of the request, that's safe and something you have to do anyway. If your 'validation' uses any information that an unprivileged user does not have access to, it is no longer safe.

You definitely should have a sanity checker before attempting access control, but you should take care to communicate very clearly to all maintainers (current and future) that this part must not use privileged information; Any such checks should be done in a separate validation step after authentication.

As a sanity check for the sanity checker, it should not actually have any code dependencies on any part of your code lower down the pipeline and should be separable into its own package that should be publicly publishable without any problems (other than possible legal issues). If you can't do that, your 'validation layer' is doing too much (or your codebase is a mess).

Cubic
  • 301
  • 2
  • 10
1

No. It is not ok.

If you have a bug in your validation layer it might bypass the security layer.

Its a common mistake to consider security as part of business requirements. "only users with the role sales, should be able to see the quarterly figures" seems like a business rule.

But if you want to be secure, you have to read such a rule as "only users in the sales role, should be able to run code on this endpoint" You have make sure your server always returns "access denied" before it gets to any kind of code you have written or files on the server.

Ewan
  • 70,664
  • 5
  • 76
  • 161