OWASP / ASVS

Application Security Verification Standard
Creative Commons Attribution Share Alike 4.0 International
2.74k stars 668 forks source link

2.10.1 Verify that intra-service secrets do not rely on unchanging credentials such as passwords, API keys #1032

Closed Sjord closed 6 days ago

Sjord commented 3 years ago

2.10.1:

Verify that intra-service secrets do not rely on unchanging credentials such as passwords, API keys or shared accounts with privileged access.

What does this mean? How should you authenticate to other services? My application currently authenticates to the database server using username and password, and uses API keys to access several API's. Is that in violation of this requirement?

What is the proper way to do manage intra-service secrets? Can we rephrase this to a positive requirement instead of a negative requirement?

What does it mean for a secret to rely on credentials? When are credentials unchanging?

What was the original purpose of this requirement?

See also https://github.com/OWASP/ASVS/issues/763.

jmanico commented 3 years ago

I think the general suggestion here is that

OAuth2 tokens + mTLS > mTLS alone > API Keys > Passwords for API access

Or in short, API keys in general are weak API access methods.

But for sure this requirement as-is is over-reaching.

Sjord commented 3 years ago

I attempted to retrieve the history of this requirement, but it doesn't provide much more information:

Sjord commented 2 years ago

I propose to delete this requirement.

wet-certitude commented 2 years ago

@jmanico I would consider the private key of an mTLS connection "unchanging" as well. I see that the private key, unlike a password/token is not transmitted - at least that is one interpretation, but one that after much thought, I could not figure out based the current stipulation alone.

Since it's been over a year since this was reported and no one was able to figure out what exactly this means, no one is going to miss this stipulation if we simply remove it?

settantasette commented 2 years ago

I do not think deleting this requirement is the right way to go, rather I would re-phrase it to bring in some clarity. I understand @jmanico's point, but at the moment the way control point is presented is very confusing. Verify that intra-service secrets do not rely on unchanging credentials such as passwords, API keys or shared accounts with privileged access. Does it mean that secrets should not use passwords etc. whatsoever ? Or if for example passwords are rotated daily then its acceptable ? Since its not "unchanging credential" anymore. Then question comes what is acceptable rate of rotation of credentials ?

tghosth commented 1 year ago

@set-reminder 5 weeks @tghosth to look at it

octo-reminder[bot] commented 1 year ago

Reminder Monday, January 16, 2023 12:00 AM (GMT+01:00)

@tghosth to look at it

tghosth commented 1 year ago

I agree this requirement is unclear and it is not clear what it was based on to begin with.

Given the topic of this section, I would suggest simplifying to:

Verify that service authentication uses either mTLS or a credential which is unique to that service and rotatable. Where supported, temporary session tokens should be generated and used instead of sending the credential on each connection.

Thoughts/opinions?

octo-reminder[bot] commented 1 year ago

🔔 @tghosth

@tghosth to look at it

Sjord commented 1 year ago

Verify that service authentication uses either ...

I think we should have a requirement that requires authentication between services.

either mTLS or a credential

I think other methods of authentication are also acceptable. Although "a credential" can of course mean a certificate or a JWT or anything.

which is unique to that service and rotatable

This should perhaps be moved to a more general requirement. All the secrets that the application uses itself should be unique, rotatable, non-default (2.10.2), etc.

Where supported

This is a pretty big escape hatch, if the developing party is developing both services that communicate with each other. They can choose to not support this.

temporary session tokens should be generated and used instead of sending the credential on each connection.

I don't understand this. Why would this be better?

sseelmann commented 1 year ago

Doesn't the current 2.10.1 contradict with 2.10.4 which defines how such "internal secrets" (if that's meant by "intra-service secrets") should be managed:

2.10.4 [GRAMMAR] Verify passwords, integrations with databases and third-party systems, seeds and internal secrets, and API keys are managed securely and not included in the source code or stored within source code repositories. Such storage should resist offline attacks. The use of a secure software key store (L1), hardware TPM, or an HSM (L3) is recommended for password storage.   798  

PS: and isn't 2.10.4 overlapping with 6.4.1? But that would be a separate issue to discuss.

6.4.1 [MODIFIED] Verify that a secrets management solution such as a key vault is used to securely create, store, control access to and destroy secrets such as service account or 3rd party application credentials. (C8)   798
tghosth commented 1 year ago

Adding some additional context:

History:

# Description L1 L2 L3 CWE NIST §
2.10.1 Verify that intra-service secrets do not rely on unchanging credentials such as passwords, API keys or shared accounts with privileged access. 287
2.10.1 Verify that intra-service secrets do not rely on unchanging credentials such as passwords, API keys or shared accounts with privileged access. OS assisted HSM 287 5.1.1.1
2.10.1 Verify that intra-service secrets do not rely on unchanging passwords, such as API keys or shared accounts with privileged access. OS assisted HSM 287 5.1.1.1
2.10.1 Verify that integration secrets do not rely on unchanging passwords, such as API keys or shared privileged accounts. OS assisted HSM 287 5.1.1.1
2.11.1 Verify that integration secrets do not rely on unchanging passwords, such as API keys or shared privileged accounts. Software OS assisted HSM 5.1.1.1
2.11.1 Integration secrets SHOULD NOT rely on unchanging passwords, such as API keys or shared privileged accounts. Software OS assisted HSM 5.1.1.1
2.11.1 Integration secrets SHOULD NOT rely on unchanging passwords, such as API keys or shared privileged accounts. If passwords are required, the credential should not be a default account and stored with sufficient protection to prevent offline recovery attacks, including local system access. Software OS assisted HSM 5.1.1.1
2.21 Integration secrets SHOULD NOT rely on unchanging memorized secrets, such as API keys or shared privileged accounts. If memorized secrets are required, the credential should not be a default account, and stored with sufficient protection to prevent offline recovery attacks, including local system access. Software OS assisted HSM 5.1.1.1
2.21 Integration memorized secrets SHOULD NOT rely on unchanging memorized secrets, such as API keys or shared privileged accounts. If memorized secrets are required, the credential should not be a default account, and stored with sufficient protection to prevent offline recovery attacks, including local system access. Software OS assisted HSM 4.0 5.1.1.1

From Andrew's deck: image

tghosth commented 1 year ago

PS: and isn't 2.10.4 overlapping with 6.4.1? But that would be a separate issue to discuss.

6.4.1 [MODIFIED] Verify that a secrets management solution such as a key vault is used to securely create, store, control access > to and destroy secrets such as service account or 3rd party application credentials. (C8)   798

@sseelmann please can you open a separate issue to discuss if one does not already exist

tghosth commented 1 year ago

Verify that service authentication uses either ...

I think we should have a requirement that requires authentication between services.

You mean an extra requirement "before" this one that just requires intro-service authentication?

either mTLS or a credential

I think other methods of authentication are also acceptable. Although "a credential" can of course mean a certificate or a JWT or anything.

What other methods of authentication? "Credential" is pretty flexible wording...

which is unique to that service and rotatable

This should perhaps be moved to a more general requirement. All the secrets that the application uses itself should be unique, rotatable, non-default (2.10.2), etc.

Yeah, I hear that... It's like a catch-all requirement

Where supported

This is a pretty big escape hatch, if the developing party is developing both services that communicate with each other. They can choose to not support this.

I think they would need to demonstrate why that cannot be supported...

temporary session tokens should be generated and used instead of sending the credential on each connection.

I don't understand this. Why would this be better?

Temp session tokens are better than sending a credential each time. This is how OAuth2/OpenID service to service authentication is supposed to work.

@Sjord do you think you could propose alternative wording.

elarlang commented 1 year ago

Related, potential duplicate requirement: https://github.com/OWASP/ASVS/issues/1522

tghosth commented 1 year ago

hi @Sjord, any thoughts on my comment here: https://github.com/OWASP/ASVS/issues/1032#issuecomment-1559095414

Sjord commented 1 year ago

No, I don't really have anything to add other than what I already described above.

tghosth commented 1 year ago

Ok so @Sjord @elarlang what do you think about this:

Verify that service authentication uses either mTLS or a credential (such as an API key or password) which is unique to that service and rotatable. If a credential is being used, temporary session tokens should be generated and used instead of sending the credential on each connection.

elarlang commented 1 year ago

Temp session tokens are better than sending a credential each time. This is how OAuth2/OpenID service to service authentication is supposed to work.

If an application uses authentication for every request does it make "not valid"? Maybe "can be" instead of "should be"?

tghosth commented 1 year ago

Maybe:

Verify that service authentication uses either mTLS or a credential (such as an API key or password) which is unique to that service and rotatable. If a credential is being used, temporary session tokens should be generated and used instead of sending the credential on each connection unless there is a good reason why this is not possible.

elarlang commented 1 year ago

As a developer I want to ask - what is the good reason why I need to use sessions in this situation?

I think we need to be clear with that.

tghosth commented 1 year ago

So my preferred wording would be

Verify that service authentication uses either mTLS or a credential (such as an API key or password) which is unique to that service and rotatable. If a credential is being used, temporary session tokens should be generated and used instead of sending the credential on each connection unless there is not supported by the 3rd party.

But @Sjord was worried this was too easy to get out of...

elarlang commented 1 year ago

I re-read entire communication here... and it did not help.

I think we need to make clear wording - is the requirement for the application which providing the machine-to-machine service or the one who is using it.

If it is for using, then how much there is for the application to say, how the communication should be done - it just can use whatever way it is provided. Or should we have requirement to set some limitation here?

I don't see the reason, why you need to have creating a session overhead for every situation. It makes sense when you have multiple requests to handle with the same client over short period of time. But if it's some data sync once per day and it's done with one request, do I really need to have this session overhead?

tghosth commented 1 year ago

I re-read entire communication here... and it did not help.

I think we need to make clear wording - is the requirement for the application which providing the machine-to-machine service or the one who is using it.

If it is for using, then how much there is for the application to say, how the communication should be done - it just can use whatever way it is provided. Or should we have requirement to set some limitation here?

OK so I see your point about making this clearer. What do you think about the following reword/split?

I don't see the reason, why you need to have creating a session overhead for every situation. It makes sense when you have multiple requests to handle with the same client over short period of time. But if it's some data sync once per day and it's done with one request, do I really need to have this session overhead?

I see your point but I think that is leading practice for service to service authentication, e.g. using OIDC and we should mandate it in particular for service developers (rather than service consumers).

elarlang commented 1 year ago

The wording is nice and clear to separate consuming and providing a service.

If a credential is being used, temporary session tokens should be generated and used instead of the consumer sending the credential on each connection.

how it increases the risk if it is not done that way?

jmanico commented 1 year ago

The wording is nice and clear to separate consuming and providing a service.

If a credential is being used, temporary session tokens should be generated and used instead of the consumer sending the credential on each connection.

how it increases the risk if it is not done that way?

More chance of credential exposure.

elarlang commented 1 year ago

Do I missing something here?

Solution a)

  1. A makes request to service B, request also contains credentials
  2. B validates credentials (authentication) and gives response

Solution b)

  1. A makes authentication request to service B - sending credentials
  2. B validates credentials (authentication) and gives back session token
  3. A makes request to service B, request also contains session token
  4. B validates session token and gives back response

How solution a is worse and gives more opportunities to leak credentials?

tghosth commented 1 year ago

You are correct if this is just one communication. However, if there will be multiple communications between A and B then this makes a difference.

elarlang commented 1 year ago

You are correct if this is just one communication. However, if there will be multiple communications between A and B then this makes a difference.

... and this was exactly what I pointed out here: https://github.com/OWASP/ASVS/issues/1032#issuecomment-1723691604

I don't see the reason, why you need to have creating a session overhead for every situation. It makes sense when you have multiple requests to handle with the same client over short period of time. But if it's some data sync once per day and it's done with one request, do I really need to have this session overhead?

tghosth commented 1 year ago

Ok so we could do this but I am not sure it is ideal:

Verify that for a service designed to be consumed by other services, authentication uses either mTLS or a credential (such as an API key or password) which is unique to that service and rotatable. If a credential is being used and interaction with the service involves more than one connection per session, temporary session tokens should be generated and used instead of the consumer sending the credential on each connection.

Verify that consumers of a service are configured to use the most secure authentication option provided by the service being consumed.

Thoughts @elarlang ?

elarlang commented 1 year ago

Now the points are kind of covered but it makes the requirement text awful.

Back to the point. The reason for the change is "avoid leaking credentials". Credentials are changed between parties anyway, now there is question - how often those are changed. In a bit longer time-window, if an attacker reach to accesses to steal machine-to-machine session tokens, an attacker can also steal credentials. So I can not see any huge benefits for it and my question is - is this finetuning actually level 2 material or it should be separate requirement for level 3?

Sjord commented 1 year ago

You are correct if this is just one communication. However, if there will be multiple communications between A and B then this makes a difference.

I disagree. This assumes that the chance that credentials are intercepted scales linearly with the number of times it is communicated. That there is some probability per message that it gets intercepted. I think this is incorrect. I think a TLS connection is almost perfectly secure. When it isn't secure, an attacker can probably decrypt all traffic and just wait around for credentials. They can probably distinguish the credentials exchange from other messages by size alone, and can choose to decrypt the correct message.

jmanico commented 1 year ago

Agree with @Sjord - for three reasons:

1) When you use credentials per messsage, you are using them frequently, and if stolen they have persistent attack value. If a token is stolen, it's only useful for the length of the token life, which is usually a LOT LESS than the credential lifetime.

2) Tokens can be scoped to only provide the permissions necessary for the task at hand. Credentials, on the other hand, are all-or-nothing. If they're compromised, the attacker has the keys to the kingdom.

3) Revocation: If a token is compromised, you can easily revoke it without affecting other services or users. With credentials, you'd have to change the password, update it everywhere it's used, and potentially force a password reset for all users.

tghosth commented 1 year ago

Back to the point. The reason for the change is "avoid leaking credentials". Credentials are changed between parties anyway, now there is question - how often those are changed. In a bit longer time-window, if an attacker reach to accesses to steal machine-to-machine session tokens, an attacker can also steal credentials. So I can not see any huge benefits for it and my question is - is this finetuning actually level 2 material or it should be separate requirement for level 3?

I think that service to service credentials are always going to be a headache to change and so that should be avoided wherever possible. I also agree with the points from @jmanico and @Sjord.

I accept that service to service is theoretically less exposed but we want to set out leading practice which in this case is to have a session mechanism.

In terms of the messy requirements, I guess we could do the following:

Verify that for a service designed to be consumed by other services, authentication uses either mTLS or a credential (such as an API key or password) which is unique to that service and rotatable Verify that if a credential is being used for a service and interaction with the service involves more than one connection per session, temporary session tokens should be generated and used instead of the consumer sending the credential on each connection. Verify that consumers of a service are configured to use the most secure authentication option provided by the service being consumed.

jmanico commented 1 year ago

I like it when @tghosth agrees with me almost as much as I enjoy it when @elarlang disagrees with me!

<3

Sjord commented 1 year ago

I see your point but I think that is leading practice for service to service authentication, e.g. using OIDC and we should mandate it in particular for service developers (rather than service consumers).

I accept that service to service is theoretically less exposed but we want to set out leading practice which in this case is to have a session mechanism.

@tghosth What do you mean by "leading practice"? Why is a session mechanism a leading practice?

I think that each of us imagines a different kind of service, and that contributes to miscommunication. I think of a web application and its database server. Others seem to think of different web applications talking to each other, or even a public web API. Which kind of service you are thinking about is important for the ease of credential rotation, whether is supports sessions or OIDC, and the relative risk between session tokens and other credentials. I wouldn't want OIDC for my database server, changing the credentials is easy, and session tokens wouldn't improve security significantly if I sent the credentials anyway on each page load.

tghosth commented 1 year ago

@Sjord I take your point but bear in mind that having short lived credentials for databases is in fact possible, see this example here: https://developer.hashicorp.com/vault/docs/secrets/databases

You could also use certificate auth with a database.

So whilst I accept that not all service to service connections are the same, I still think that expecting a more modern authentication mechanism is not unreasonable.

tghosth commented 9 months ago

So we have 3 proposed requirements intended to replace 2.10.1

Verify that for a service designed to be consumed by other services, authentication uses either mTLS or a credential (such as an API key or password) which is unique to that service and rotatable.

I think this is highly sensible and should be added.

Verify that if a credential is being used for a service and interaction with the service involves more than one connection per session, temporary session tokens should be generated and used instead of the consumer sending the credential on each connection.

I am starting to feel like this is a little too complex...

Verify that consumers of a service are configured to use the most secure authentication option provided by the service being consumed.

If we skip the next one, maybe we can make do with this one instead.

Thoughts @Sjord @elarlang

Otherwise my next step is to open a PR

elarlang commented 9 months ago
tghosth commented 9 months ago

Verify that for a service designed to be consumed by other services, authentication uses either mTLS or a credential (such as an API key or password) which is unique to that service and for which a plan exists (ideally automated) to rotate the credential.

I think this is highly sensible and should be added.

how do you define and verify a "rotatable" password?

Do you think this is clearer?


Verify that if a credential is being used for a service and interaction with the service involves more than one connection per session, temporary session tokens are generated and used instead of the consumer sending the credential on each connection.

I am starting to feel like this is a little too complex...

"Should" sounds like a recommendation, not a requirement

To be clear, I think maybe we should just not include this one at all. I got rid of "should" anyway.


Verify that consumers of a service are configured to use the most secure authentication option provided by the service being consumed.

If we skip the next one, maybe we can make do with this one instead.

not actionable for me. What is the "most secure option"?

This is one of those situations where the app owner doesn't control the service but they control how they use the service. As such, I don't know what the most secure mechanism is in each case, it may be that the service only supports a static API key. We can't stop them using the service but if it supports an API key and alternatively mTLS, we can say use the more secure mechanism (mTLS).

Do you think we should define a hierarchy of preference such as mTLS > ephermeral credential >credentials + session token > fixed credentials? @elarlang


tghosth commented 9 months ago

Updated wording for discussion:

Req1:

Verify that for a service designed to be consumed by other services, authentication uses either mTLS or offers a session mechanism to avoid use of fixed credentials each time.

Req2:

Get in the bin

Req3:

Verify that consumers of a service are configured to use an authentication option which is more secure than fixed credentials (such as mTLS, temporary or ephemeral credentials, or fixed credentials plus a session mechanism) where this option is provided by the service being consumed.

Make it L3.

tghosth commented 9 months ago

@elarlang to review the updated wording.

Sjord commented 9 months ago

which is more secure than fixed credentials (such as mTLS, temporary or ephemeral credentials, or fixed credentials plus a session mechanism)

I think requiring something to be "more secure than" already requires security knowledge. It explains security in terms of itself.

Also, I know something about security and I still don't understand why a session mechanism is more secure than fixed credentials.

jmanico commented 9 months ago

Also, I know something about security and I still don't understand why a session mechanism is more secure than fixed credentials.

session theft ends when that session goes idle or gets logged out of, and events that require re-authentication are a good blocked when I popped your session but dont have your creds.

credential theft is usually full account compromise forever

Both are nasty, but credential theft is way worse. Especially when no MFA is in play.

tghosth commented 9 months ago

which is more secure than fixed credentials (such as mTLS, temporary or ephemeral credentials, or fixed credentials plus a session mechanism)

I think requiring something to be "more secure than" already requires security knowledge. It explains security in terms of itself.

Also, I know something about security and I still don't understand why a session mechanism is more secure than fixed credentials.

Whilst it is less concerning for service to service components, fixed credentials are still more exposed than a session mechanism.

tghosth commented 9 months ago

In #1858, @jmanico noted:

I suggest we change "user accounts" to "service accounts" based on the context of this requirement.

# Description L1 L2 L3 CWE
1.2.2 [MODIFIED] Verify that communications between back-end application components, including APIs, middleware and data layers, are authenticated and use individual user accounts. (C3) 306

And @elarlang noted:

As it is implementation requirement, it should be moved away from V1 category.

But what exact attack scenario or weakness does the requirement address?

Not all services require authentication.

What is accepted authentication? Basic auth vs some application logic for auth vs certificate...

Personally, I think this feels like duplication with the modified requirements I drafted above https://github.com/OWASP/ASVS/issues/1032#issuecomment-1933951547 which are based on 2.10.1 so I would be tempted to remove it altogether.

What do people think?

jmanico commented 9 months ago

Agree this is a duplicate

tghosth commented 9 months ago

Ok so current proposal is as my comment here: https://github.com/OWASP/ASVS/issues/1032#issuecomment-1933951547

plus, remove requirement 1.2.2 https://github.com/OWASP/ASVS/issues/1032#issuecomment-1934432104

Sjord commented 9 months ago

I think fixed API keys are fine. GitHub, GitLab, and AWS apparently think API keys are fine. I asked several times why a session mechanism would be more secure than API keys. I received some responses to this, but I am still not convinced. Arguments against API keys given above feel pretty handwavy to me. The proposal of @tghosth assumes that it is very clear that some things are "more secure than" fixed credentials, but this is not clear to me.

This doesn't feel ready for a PR to me. My main problem is not that we disagree, but that I don't understand the motivation to disallow API keys. I think other users of the ASVS would have an even harder time understanding it.

when I popped your session but dont have your creds

What is an attack scenario where an attacker can access the session token but not the credentials that started that session?

tghosth commented 8 months ago

What is an attack scenario where an attacker can access the session token but not the credentials that started that session?

Fixed credentials are used on every single API request whereas with a session mechanism the credential on an individual request is shorter lived. If an attacker gets access to an individual request, (log files, fluke interception, etc) they don't get access to the fixed credentials.

APIs which support OIDC would support this requirement as the client will generally go through the OIDC process to authenticate and then use an access token.

I do accept that this seems to be a less popular approach. It looks like AWS does this with STS. On the other hand, even Github seems to use some sort of fixed credentials for their API.

We currently have two proposed requirements to replace the existing one:

Aimed at service creators:

Verify that for a service designed to be consumed by other services, authentication uses either mTLS or offers a session mechanism to avoid use of fixed credentials each time.

Aimed at service consumers (L3 proposed):

Verify that consumers of a service are configured to use an authentication option which is more secure than fixed credentials (such as mTLS, temporary or ephemeral credentials, or fixed credentials plus a session mechanism) where this option is provided by the service being consumed.

I think in both cases, they explain what is considered more secure so I guess the question is whether you have a problem with one or both and how we can bridge that gap @Sjord .