Closed Sjord closed 6 days 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.
I attempted to retrieve the history of this requirement, but it doesn't provide much more information:
I propose to delete this requirement.
@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?
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 ?
@set-reminder 5 weeks @tghosth to look at it
⏰ Reminder Monday, January 16, 2023 12:00 AM (GMT+01:00)
@tghosth to look at it
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?
🔔 @tghosth
@tghosth to look at it
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?
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 |
---|
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:
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
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.
Related, potential duplicate requirement: https://github.com/OWASP/ASVS/issues/1522
hi @Sjord, any thoughts on my comment here: https://github.com/OWASP/ASVS/issues/1032#issuecomment-1559095414
No, I don't really have anything to add other than what I already described above.
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.
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"?
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.
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.
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...
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?
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).
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?
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.
Do I missing something here?
Solution a)
Solution b)
How solution a is worse and gives more opportunities to leak credentials?
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.
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?
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 ?
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?
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.
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.
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.
I like it when @tghosth agrees with me almost as much as I enjoy it when @elarlang disagrees with me!
<3
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.
@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.
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
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
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.
@elarlang to review the updated wording.
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.
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.
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.
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?
Agree this is a duplicate
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
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?
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 .
2.10.1:
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.