1

I need to provide security requirements for public API keys that will be generated by a web application and then used in automation scripts by clients.

The scripts will be run on the endpoints several times a day via a cronjob.

The risk of a key exposure is very high since whoever steals these scripts, will be able to execute OS commands remotely on the client domains.

I need to prevent this kind of theft risk while keeping the UX as simple as possible.

For now, I've prepared the following requirements:

  1. The key will be generated by the web application, after logging in to the application.
  2. IP addresses will be paired with the key so that only the IP that generated the key can use the key.
  3. The key will inherit the permissions on the endpoint of the user who generated it.
  4. The user will select the set of authorised actions allowed by the key- e.g. running actions, downloading reports, etc.
  5. The keys will be strings with 40 random alphanumeric and special characters in size. (minimal size, could be longer than that) or GUIDs.
  6. The API will have a request rate limiting.
  7. Users should be guided not to hardcode the key in the scripts. The scripts should receive them as a parameter from the user.
  8. The keys will be revoked automatically after 30 days.
  9. Admins will be able to revoke the keys manually.
  10. The key will NOT be transferred as a part of the URL, only in a header or the request body.

What do you think about these recommendations?

8
  • "Users should be guided not to hardcode the key in the scripts. " -- why/how could they be used in a script and receive the key as a parameter?
    – schroeder
    Aug 31, 2021 at 13:27
  • -- why/how could they be used in a script and receive the key as a parameter - the scripts will use the key as a user input to prevent it from being hardcoded, that will be a recommendation / security warning for clients
    – uvzz
    Aug 31, 2021 at 13:50
  • Still confused. Where are the scripts generated? Where are they run? What is running the API for which there will be a key?
    – schroeder
    Aug 31, 2021 at 13:52
  • I still have no clear idea of what is happening. The endpoint connects to the API and does something, or the API connects to the endpoint and requests something? What is the role of the web interface? It's only for management, or it triggers execution?
    – ThoriumBR
    Aug 31, 2021 at 13:56
  • clients will create scripts and run them on their servers, the API is used to communicate with a backend server that will run commands on domain workstations
    – uvzz
    Aug 31, 2021 at 14:08

1 Answer 1

1

Those 10 points are not making much sense from a API design or security perspective. Many mixed concepts and no clear definition of what keys 'are'.

What is the intent of these "public API keys"?

Are they;

  1. Intended to identify a user
  2. Used by application logic to decide what methods/data a user can access (ACL)
  3. Is presenting the 'API key' going to admit a requester and process the request (Authentication)
  4. Will there be some other method of identity, other method of ACL, other Authentication, and the 'key' is just a resultant token as a result of these to be used to show they were performed (Authorization)
  5. Similar to (4) Is a key designed to apply a type of usage quota or rate limiting? (but not for identity/acl/authn/authz). e.g. AWS API Gateway use a usage quota and it is represented using an API Key, but the api key is only ever used as a way to control rate limiting and quota, nothing else. this is a good practice becasue it means the usage plan can be managed without effecting identity or auth.

Figure out the purpose of the 'key'.

Check out OWASP cheatsheet series (which I am a maintainer of) for guidance on each element, start with Authn and then Authz before tackling things like rate limiting or the REST assessment guide

NB1 Authn

From experience performing penetration tests myself, the best way to be secure for an API is to avoid at all costs sending secrets in any request. What that means is never actually send the API key ever if possible, and if it is sent try to make sure it is sent 1-time and then once the user has the secret all subsequent requests do not send it at all but instead they use the secret to derive a HMAC that proves they have the secret (but not actually send the secret to the server). The server can verify the request with the HMAC because it too has the secret stored and can reproduce the same HMAC as the client did, but the secret was never sent in the requests.

Something called a JWT uses HMAC but it also requires a complex implementation of things like OAuth2 or OIDC (built on top of OAuth2) that can be very complex to design (and mostly always leave more security holes than they address in my personal experience), so my advice is avoid complexity, use HMAC first and mature from there if needed.

NB2 Authz

This should be performed separate from authn when a sensitive request is made (think a bank transfer to a account you never sent money too before and the bank asks you to do a one-time code, that is 'Authz'). When a user is already authenticated, do not simply let them do anything they try to do, let them do many things that are not sensitive, but as soon as a critical or sensitive request is made you should treat that as a elevation of privledge request that requires authz. If you never apply this, you never actually apply authz in your app! this is the case for 99% of code out there, none use authz and that is why OWASP Top 10 number 1 is broken access controls - so please consider adding Authz because it is the biggest risk, and most forgotten by developers

NB3 Identity

The identity of a user should not be part of the api key, so when an api key is rotated the identity is not changed. doing audits is usually not possible if you do not actually think about how identity is implemented as a first class concept.

NB4 quotas and rate limiting

Common for an API, but should not be tightly coupled to any user/account. Think about quota and rate limiting regardless of identity (because attackers are anyone/everyone). When some users require additional rates/quotas then build the system to support extending the default limitiation in special cases for these special users. but the secure default rates/quotas should always be there regardless of identity.

Summary of-sorts

If you have no Authn yet, consider a method of identity first, then you can try to 'prove' that identity using authn. If you have a solid foundation of an identity and you have thought about Authn, make sure that any 'secret' is communicated to the user no more than 1 time, and the user sends the secret exactly 0 times (so a HMAC or HMAC based solution is perfect for API Authn). A simple user UUID in a header can be identity, or something more sophisticated, as long as the secret is not in the requests the 'identity' will be used to lookup the secret on the server-side and will have to reproduce the HMAC and match the user's resultant HMAC they sent you for the identity+authn combination to validate, so the UUID is fine for this purpose and can be exposed because without the secret it is useless (there are some cases this is not safe and if that is your case dear reader, you already know)

Once you have identity and Authn sorted, please consider adding Authz where privileged requests are attempted. If an authenticated user is able to do anything at all once authenticated, you really do not have any access controls in place, you just have a authentication mechanism and no controls for access to one resource versus access to another that the user is allowed to access, and if one is sensitive and the others are not, allowing them to do it 1 hour / 1 day / 1 week / 1 month after authenticating, you really can't have any assurance the authorised user was performing that sensitive action can you? So let users who are authenticated do as many activities they wish to do that are not sensitive, and for things that matter most make sure you add Authz challenge-response mechanisms to protect them.

Finally; rate-limiting can be very very helpful and not noticable by 'normal users', for example you can rate limit to 1-request-per-second and that can save you from DoS and large bills but a user may never notice if a typical activity is never more than 1r/s. You chose the right 'expected' limits for your users, and don't let the unexpected occur because you protected it up front. If your user needs to break away from the typical usage quotas try to add something like the AWS Usage Plan API Key system on top of the default limitations built into your API.

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.