GithubHelp home page GithubHelp logo

Comments (13)

EthanHeilman avatar EthanHeilman commented on August 14, 2024 1

@francoismichel If I understand your attack correctly, this was the attack that PKCE was introduced to defeat:

  1. The clients chooses initiating the auth request chooses a value CV and VC=Hash(CV) and initiates the auth request by sending VC to the OpenID Provider (OP),
  2. The user authenticates
  3. The OpenID Provider does the redirect to the redirect URI sending the auth code to the client via the localhost socket,
  4. The client sends the auth code and the CV value to the OpenID Provider which returns the ID Token.

An attacker who intercepts the auth code by listening on the localhost socket can not redeem that auth code for an ID Token because the attacker does not know a value CV such that VC=Hash(CV).

This is the value of enabling PKCE.


There is another known attack here which neither PKCE nor a randomized redirect URI does not fix.

  1. Attacker binds to a localhost port,
  2. Attacker opens browser to initiate auth request,
  3. User clicks I consent (in some IDPs that don't even need to consent if they have already consented for that client-id),
  4. Attacker gets auth code and redeems it for the ID Token

The user looking at a browser window that popped up has no easy way to determine that this was opened by the legitimate service running on localhost. There two mitigations:

  • Use a port numbers lower than 1024 in your redirect URI ACL at the OpenID Provider. This means that an attacker requires root access to bind to a port that will accept by the redirect URI ACL. This also means that SSH3 client needs to setUID root functionality.
  • ACL say three ports in your redirect URIs, then use a daemon to bind to all of these ports and ensure no one can port to them. This approach rests on the ability of the deamon to always be listening on those ports. Not a great solution.
  • Use a cosigner like we do in OpenPubkey

Mobile device flows don't have this problem because app identity is known to the OS and so the iOS can enforce a map of redirect URIs to specific cryptographic identities associated with the candy crush app. There are some other solutions in this space, but using I favor the OpenPubkey cosigner approach.

In general it is very hard to protect secrets like this if an attacker has a programming process on your endpoint that can open ports. That can do so much bad stuff, that provided security against such a threat is diminishing returns.

from ssh3.

septatrix avatar septatrix commented on August 14, 2024 1

I would also like to note that the RFC says to construct these loopback URLs using the numeric literals (127.0.0.1 and [::1] respectively) instead of "localhost".

Another option (which would also be necessary when one wants to implement a mobile client for SSH3) is to use private-use URI schemes like be.francoismichel.ssh3:/oauth2redirect/. This is also possible on desktop OS though it requires a more traditional installation. E.g. on linux a ssh3.desktop file would be required

from ssh3.

septatrix avatar septatrix commented on August 14, 2024 1

@septatrix My two cents:

  1. Using numeric loopbacks seems reasonable. The only reason I like localhost is that is it generic to ipv4 and ipv6. It seems like it wouldn't be hard to just specify two redirect URIs one being the loopback for IPv4 and one being the loopback for IPv6.

In Linux binding to ::1 defaults to dual stack mode, i.e. it also received IPv4 packets

  1. How well supported is native-app OAuth in OIDC on the desktop? I haven't build any systems using it and I don't know if there are any gotchas. I agree on mobile devices private-use schemes is both well supported and a security requirement. Are protocol handlers still used for this?

Not really sure about this TBH

from ssh3.

EthanHeilman avatar EthanHeilman commented on August 14, 2024

I was going to open a ticket but I see there is already an existing ticket.

The Google OP requires a static redirectURI and does not allow wildcards. Google does let you wildcard localhost ports. The redirect URI http://localhost/ will work for all ports.

Google OP configuration

This is the error I get when I use SSH3 oidc with google:
oidc google

What is the security goal?

Is the security goal of adding a random fragment to securely link the request to the OP with the response form the OP? If so OIDC already provides a more secure way of doing this using PKCE (RFC 7636: Proof Key for Code Exchange). The way it works is client creates:

$$CV \gets \{0,1\}^{256}$$

$$VC \gets \mbox{SHA256(CV)}$$

The client then adds VC to the auth request URI. Then to claim the ID Token associated with this request, the client must reveal VC to server. This means that even if an attacker intercepts the original request, the attacker only learns VC not CV. Additionally if the attacker triggers a redirectURI response which is not intended response from the client, when the client-supplies VC, it will break.

It looks like SSH3 supports PKCE, but the default in the SSH3 config is to for PKCE to be false.

doPKCE := flag.Bool("do-pkce", false, "if set perform PKCE challenge-response with oidc")

I don't see a reason why you would ever want PKCE to be false. Is there an OP that doesn't support PKCE?

Port diversity with known ports

In OpenPubkey we support choosing a port from a list of ports. This allows parties to add that list of ports to their redirectURI list if needed and also allows us to fail over if another application is already bound to that port. It might be worth copying this pattern to support OPs that don't wildcard localhost ports.

https://github.com/openpubkey/openpubkey/blob/024d958d6c26e0883c9a9e15cd37a123ce16fd7e/providers/google.go#L406-L414

from ssh3.

septatrix avatar septatrix commented on August 14, 2024

The random port is also problematic for firewalls

from ssh3.

EthanHeilman avatar EthanHeilman commented on August 14, 2024

@almereyda If you want to play around SSH OIDC with a fix redirectURI, I created a PR #144 You can just pull from my branch and use it.

from ssh3.

francoismichel avatar francoismichel commented on August 14, 2024

One reason for using that randomly-generated path was to avoid other programs to hijack the token by sending a fake request to the ssh3 waiting on localhost, causing it to close the socket, and then the attacker could listen on the same port and retrieve the token like that. It seems doable on pretty much any OS.
But maybe am I missing something making such an attack undoable ?

from ssh3.

septatrix avatar septatrix commented on August 14, 2024

Why release the port at all? To be the same redirect URL and work best with reverse proxies and firewalls the port should be static anyhow. So I see no reason why the port should be release after using it?

from ssh3.

EthanHeilman avatar EthanHeilman commented on August 14, 2024

@septatrix Releasing the port makes sense if you are using this as a cli where the cli isn't always running. The alternative is a daemon which starts at OS bootup and always holds that port or a set of ports, but that is a more complex client to build.

from ssh3.

septatrix avatar septatrix commented on August 14, 2024

@septatrix Releasing the port makes sense if you are using this as a cli where the cli isn't always running. The alternative is a daemon which starts at OS bootup and always holds that port or a set of ports, but that is a more complex client to build.

Ah I was under the assumption that the SSH3 server would be the one receiving the token. That seems like the intuitive solution

from ssh3.

francoismichel avatar francoismichel commented on August 14, 2024

Thanks for the discussion.
The attack with an attacker opening a browser window concurrently to SSH3 may not be easy to perform but it makes sense. I wish there was a generic way in OIDC to display some text to the user in the browser window so that it can check the browser window is indeed the right one.
The difference in this scenario however, is that the attacker must either be root or be running with the same rights as the current user in order to be able to show a browser window in its desktop session, while the previous scenario (the one avoidable with PKCE), the attacker just needs to be able to listen on a port.

The reason why PKCE is disabled by default is simply because I couldn't make it to work by the time with that specific version of the oidc module and the google OP, but I may give it another try now. We should probably list the common OPs that support PKCE well and enable it by default.

from ssh3.

francoismichel avatar francoismichel commented on August 14, 2024

Concerning the random URL, I am not strongly against removing it, but we should probably ensure that PKCE is enabled then, and use the random URL if not.

from ssh3.

EthanHeilman avatar EthanHeilman commented on August 14, 2024

@septatrix My two cents:

  1. Using numeric loopbacks seems reasonable. The only reason I like localhost is that is it generic to ipv4 and ipv6. It seems like it wouldn't be hard to just specify two redirect URIs one being the loopback for IPv4 and one being the loopback for IPv6.
  2. How well supported is native-app OAuth in OIDC on the desktop? I haven't build any systems using it and I don't know if there are any gotchas. I agree on mobile devices private-use schemes is both well supported and a security requirement. Are protocol handlers still used for this?

from ssh3.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.