tarickb / sasl-xoauth2

SASL plugin for XOAUTH2
Other
72 stars 20 forks source link

"secret" arguments to `sasl-xoauth2-tool` on the command line are world-readable #57

Closed dkg closed 1 year ago

dkg commented 1 year ago

sasl-xoauth2-tool get-token can take an argument --client-secret. This is troubling, since on many systems, command line arguments are world-readable.

I see a couple ways around this:

Once an alternate approach is available, if the "client secret" really does need to be secret, it's probably a good idea to explicitly deprecate the existing --client-secret argument to this command.

tarickb commented 1 year ago

Just to clarify (and my apologies if you know this already) -- the client secret is used to authenticate the application, not the user. It's much less sensitive than the OAuth2 access or refresh tokens.

Other OAuth2 tools don't bother hiding the client secret either. I'm not sure it's worth the effort to do anything about this for sasl-xoauth2.

dkg commented 1 year ago

right, i do understand that generally.

But i confess i'm not confident in my understanding of how this actually plays out in the XOAUTH2 ecosystem -- why would any verifier trust a bearer token to "authenticate" the application? surely the application's "client secret" can be copied from the source code, or extracted from the binary, and then reused by arbitrary other applications.

If the verifier (gmail?) actually cares that this is a particular client application, as opposed to a particular client for a specific user, then what would the verifier do if they knew that the "client secret" was being leaked? Would they terminate all access for any user of the client secret in question? or of the client id?

if instead this is just supposed to help the verifier distinguish between different clients for a specific user (that is, that any application using this protocol would dynamically generate a client secret for the user in question, so that, say, i could distinguish between the authorization for Thunderbird on my Windows laptop and Thunderbird on my Windows desktop), then why would this value be named "client secret" and why would it differ from the "client id"?

If there really is no risk of leakage, then perhaps this command-line argument concern can be addressed by documentation in sasl-xoauth2-tool's manpage. But if any verifier would freak out about a client secret leaking by default, could we have some way that a user who cares about actually keeping the client secret a secret can avoid leaking it on the command line?

tarickb commented 1 year ago

Indeed, the client secret can be copied from source (though generally open-source applications shouldn't ship client IDs and secrets in their code) or extracted from binaries. Google's OAuth2 docs seem to suggest that in this case it's not treated as a secret: "The process results in a client ID and, in some cases, a client secret, which you embed in the source code of your application. (In this context, the client secret is obviously not treated as a secret.)"

The (separate, locked-down) OAuth2 refresh and access tokens control access to a specific user's account. The risk of a client secret leaking is that someone else could impersonate the application and craft a URL requesting a token from the OAuth2 provider (Google or Microsoft). The application name that would show up in the resulting "do you want to allow this app access to your data?"-type screen would then be the name corresponding to the "stolen" client ID/secret.

Anyway it's easy enough to prompt the user for a secret if they don't specify one, so I'll just do that.

dkg commented 1 year ago

thanks for the fix and for the explanation, @tarickb!

This solves the interactive use case, but doesn't address the situation where this program is run directly in a non-interactive session (e.g. during a configuration-management deployment). in that case, the "client secret" still does leak to the process table, but as you say it's probably not a secret at that point.

tarickb commented 1 year ago

There's not really a way to use this non-interactively though. The script sets up an HTTP server and waits for the user to visit the URL it produces, which then redirects to a localhost URL, which then lets the script finish generating a token. I guess you could automate this somehow but I can't imagine why anyone would want to do that.