Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
ssh whoami.filippo.io (filippo.io)
240 points by exists on Jan 8, 2023 | hide | past | favorite | 79 comments


To make use of one different key per host, you can use some ssh_config(5) magic[0]:

    IdentityFile ~/.ssh/keys/%h
See also https://try.popho.be/ssh-keys.html , discussed: https://news.ycombinator.com/item?id=32510475

[0] https://man.openbsd.org/ssh_config.5


I learned about this when I encountered a server with an aggressive fail2ban that wouldn't let me log in because I had too many ssh keys. It apparently counted every wrong key as an auth attempt, so it blocked me before my ssh client tried the right key. Since then I've used IdentitiesOnly=yes


Just add the good key to the ssh config file on the client:

IdentityFile ~/.ssh/some.key


Before SSH-ing into untrusted hosts, make sure you understand what SSH agent-forwarding and X11-forwarding are.

Also, maybe don't trust the SSH config defaults on whatever host you're on at the moment. You can explicitly set defaults yourself in your `~/.ssh/config` or similar.


> ... make sure you understand ... SSH agent-forwarding ...

And how to configure your ssh agent to confirm with you on each use. See `-c` in `ssh-add(1)`, and make sure you're using an agent that supports it (GNOME's Seahorse doesn't, gpg-agent does, macOS's ssh-agent doesn't make can be made to via some AppleScript).

Because my ssh agent confirms each key use, I enable agent forwarding on every ssh connection without fear.


>SSH agent-forwarding and X11-forwarding

Are they enabled by default when running SSH?


No, disabled by default


You can turn this behavior off in .ssh/config with

  Host *
    PubkeyAuthentication no
Put that at the bottom of the file, then turn back on for each host:

  Host site.com
    PubkeyAuthentication yes


This doesn't really turn off the behavior. I think you're looking for IdentitiesOnly and IdentityFile, which lets you tell your client to send only the right key per host, rather than sending all of them until it gets a hit.


This seems like bad advice, password auth is less secure than key auth^. And many servers don't accept password-based auth at all.

^password is sent to the server directly; passwords are generally weak and easy to brute force. Pubkeys without a passphrase _can_ be stolen from the local machine, but if an attacker has access to your local machine, you are probably SOL anyway.

edit: as several people have pointed out, this config option does not completely prevent pubkey auth being used (i.e. if configured or overriden on the command line). But if you only use that config by itself, it will disable pubkey authentication for every host.


That's a petty interpretation, it's a big leap reading "don't send your unique identity to strange servers by default" as "never use private keys, always use passwords instead."

Nothing about that config snippet precludes using private keys for known servers.


Well that is how I read it :P I think it would be good to point out that you can add other Host sections to override it.


It’s about preventing identity leakage, not using password. I can’t tell if the post was edited, but it already includes how to override per host.

I value this and I universally disable password auth…on the server :)

E: as listed by others, IdentitiesOnly=yes seems like a better approach?


I have that line in my .ssh/config and I never use password auth.

I explicitly list every server that I want to connect to in the config file, so I know exactly what is going to happen.


You can disable password authentication as well.


Excellent way to also do ssh-agent less key site binding for those who are ssh adding a new key. I would always rather manage a key per host than manage it inside of the ever forgetful agent.


I have been circumventing this issue purely by accident it seems.

I have always had ssh-keygen write out the keys to a custom path like ~/.ssh/keys/$service/$key{,.pub} and configured each host's "identity" manually with the ssh config file.

I never did this for security purposes or anything, I just thought it made more sense than the default behavior.


Today I learned that GitHub keeps a publicly accessible list of all pubkeys linked to each user's account.


Seems questionable on Github's part to have .keys public by default, why not allow people to opt in ex: keybase.io equivalent?

Yes I get that its not sensitive information, but as this demo demonstrates it can fingerprint people who might not be unaware re: this quirk of SSH's coupled with this part of the Github API.


If you are SSH'ing into a server you should expect to get fingerprinted.


If we are going to stretch "fingerprinting" to authentication, then yes, but fingerprinting here has a very specific meaning.

When I SSH into a server, I want to be "fingerprinted" as far as I share, any Device fingerprinting allowed by SSH is a security risk to the client.

https://en.wikipedia.org/wiki/Device_fingerprint


There is a bug difference between being fingerprinted by the server that I am trying to log into and sharing (part of) gbag fingerprint publicly.


You can't even opt out of it as far as I can tell.


Ubuntu Server's installer allows you to import it as the authorized_keys for the new user.


Cloud-init as well. The CLI utility you can use is ssh-import-id.

    ssh-import-id gh:$USERNAME


Which is the tool that Ubuntu uses!


While it's not necessarily feeling great, it's called public for a reason. If anything it should be an incentive to add a passphrase to one's keys.


It can be served up over HTTP too, given the username: https://github.com/${username}.keys

Age (the author's file encryption tool) can make use of this when encrypting a file to send to someone.


Also your PGP key under https://github.com/${username}.gpg


So users can add other users' SSH keys (sourced from GitLab, ....) to their GitHub profile, essentially depriving the actual key owner from using GitHub


But then that opens them up to having their victim commit code to their repos directly, as well.


Not a big deal for an attacker to create a dummy account.


If you need a local & offline first tool to log/track/archive changes from all kind of git repos yourself, from:

* github.com * sourcehut (sr.ht) * gitlab.com * codeberg.org * ...

published ssh keys & changes, to verify (offline) ssh signed commits, verify, encrypt mails, exchchange secure data (age-enc).

You can use this app:

[] https://github.com/paepckehh/gitkeys

If you want your own repos public keys tracked / monitored / archived, just leave a star:

[] https://github.com/paepckehh/keys


> The first is that the SSH protocol provides to the server all public keys the client is willing to produce signatures for, which by default are all the public keys in your ssh-agent and in your ~/.ssh/id_*.

Not sure about other systems, but this isn't the default on Debian. I, at least, start every day by running `ssh-add ~/.ssh/id_whatever_service_I_want_to_auth_to`, because it doesn't do it by itself, and I was too lazy to configure it. For the same reason, the party trick didn't work here, since I haven't had to commit anything today yet ...


I don't know whether this is clever or not. But it ID'd me from my Github account public keys.


I think it's pretty clever, and demonstrates something very powerful about GitHub's position as de facto global code repository: you can get a strong cryptographic identity for (almost) anyone on the service, which you can then sign/encrypt to, verify for, etc.

age (another tool of Filippo's) leverages this to make encrypting to any GitHub user easy[1].

[1]: https://github.com/FiloSottile/age#encrypting-to-a-github-us...


> you can get a strong cryptographic identity for (almost) anyone on the service, which you can then sign/encrypt to, verify for, etc.

I made https://sshign.tcardenas.me/ to take advantage of this. For example: [1]

In the end, it isn't that useful. I only routinely sign digitally to deal with the (Spanish) government, and they provide their own certificates and software to do that.

[1] https://sshign.tcardenas.me/?signer=github.com%2Ftcard&messa...


Sorry, this web UI encourages me to upload private keys? Immediate nope for serious usage. Nice for testing, like jwt.io, though.

The signature verification is handy.


In Hong Kong and France where I pay taxes we seem to only use passwords. Sadly nobody has hacked my tax account and paid them for me :D


As a side note public keys are available on GitHub, e.g. https://github.com/FiloSottile.keys.


I use a different key per host and only send the right key for the host using IdentityFile

  ssh whoami.filippo.io
cannot find any of my keys on Github, even though I have the Github key in my ~/.ssh folder


Can you use this to id people for authentication?

As in if someone pings your server and you get a key that matches their GitHub is it really that person's key or could they be doing it without having the corresponding private key?


Anyone can download the public key and impersonate that person in a scheme like this.


Unless you require them to authenticate using that key (which would obviously require them to have the private key on hand).


What you are describing is the current status quo


Since Github SSH keys are public for every account, wouldn't anyone be able to impersonate you if they know your username, if you haven't set up a passphrase? If yes, it is surprising to me that Github does not make it abundantly clear when you add a key. Until now, I thought the only way an attacker can get my keys is if they break into my computer.

Edit: totally disregard this, absolute brain fog moment


You actually were wrong to disregard this entirely although of course having a public key doesn't allow somebody to trick GitHub into thinking they know your private key -- the trick this whoami server is doing could indeed be fooled that way.

When you call GitHub, after the server proves who it is to the client we get to user authentication, the client says e.g. "I'm tialaramex, and I can prove it, I know tialaramex's private key corresponding to public key 123456, and also private key corresponding to public key 987654". The server looks at the claimed user identity and keys and it can decide it wants to see that proof, for a real SSH server that'll be because it knows those keys are allowed to authenticate for that user (e.g. on a default Linux they're in the user's .ssh/authorized_keys file)

But whoami isn't a real SSH server, it's just looking at the claims, and anybody can make such claims.

If you get my GitHub public key, and you tell whoami "Yeah, I can prove I'm tialaramex, I know the corresponding private key for this public key" the whoami service doesn't actually check you can do that, it just says OK, I guess you're tialaramex.

A more nefarious thing is possible, which I'll mention but it isn't what whoami does. If you run a broadly used SSH server which actually authenticates users, you could scan those public keys against data sets like the one from GitHub, and correlate your users. So e.g. you can see that "Kittens4Ever" on your service is using the same key for that service as "DogsRuleCatsDrool" on GitHub and now you know those are in some sense the "same person". This can't be spoofed because you're actually checking those private key signature proofs, which whoami does not do.

This key correlation is why Security Keys (say a modern Yubikey, or cheaper alternative tokens) mint a brand new random private key for every enrolment. When I enrol the exact same token at Live.com, at GitHub, and at Facebook, the device mints three separate keys which can't be externally correlated, even though I can sign in seamlessly in all three places. So I could authenticate to the Live.com account "HackerNewsNoob" and the GitHub user "DanGFanClub" which says I've followed the site for many years - using literally the same Yubikey to do it - and even though Microsoft owns both services I'd have to give away the connection by some other means (e.g. linking them both on my HN about box, just using my public IP addresses not Tor or VPNs) or there's no practical way they'd be able to connect the dots.


How can someone impersonate you?


They can't, I wasn't thinking properly.


The existence of lesser-known things like this, combined with the defaults of SSH clients, and the rabid promotion of keypair auth instead of passwords, really makes one wonder whether there is some ulterior motive to make it easier to deanonymise and thus track users...


Isn't it spelled filippx now? The 'x' signifies 'no'.


Just for those curious about it:

  $ ssh whoami.filippo.io

      +---------------------------------------------------------------------+
      |                                                                     |
      |             _o/ Hello!                                              |
      |                                                                     |
      |                                                                     |
      |  Did you know that ssh sends all your public keys to any server     |
      |  it tries to authenticate to? You can see yours echoed below.       |
      |                                                                     |
      |  We tried to use them to lookup your GitHub account,                |
      |  but got no match :(                                                |
      |                                                                     |
      |  -- Filippo (https://filippo.io)                                    |
      |                                                                     |
      |                                                                     |
      |  P.S. The source of this server is at                               |
      |  https://github.com/FiloSottile/whoami.filippo.io                   |
      |                                                                     |
      +---------------------------------------------------------------------+
Of course, this happens because the day I learned about the default behavior of SSH (to send all your keys in hope that one works), I went ahead to disable it to stop remote servers from being able to inspect all my keys. I feel this can be abused in a similar way that sites abuse browser information to fingerprint users. So I put this at the bottom of ~/.ssh/config:

  Host *
      IdentitiesOnly yes
And then I explicitly indicate what key to use for each server, either with the "-i" argument, or adding entries above the previous lines:

  Host example.com
      IdentityFile ~/.ssh/example.com.pem
Other commenter mentioned that something similar can be achieved with "PubkeyAuthentication no", but I've been using "IdentitiesOnly yes" for years without issue.


What, if any, are the downsides to this?

Is it just as OP states in article, where you have to interact with the authentication process to provide a key (assuming no key is associated to host as you explain)?


The downside is that if you use a large range of servers, you will have to configure them to tell SSH what identities to use. This can be cumbersome if you ssh by alias (e.g. 'foo' rather than 'foo.yourcompany.com').

If you only SSH into servers you trust (a sensible practice) then the benefit is marginal.


Note that it does accept wildcards so you can do rules for *.mycompany.com

You can also use placeholders for keys, so for example I have a ssh config like:

    Host *.mycompany.com
        # Employer specific yubikey stuff
    
    Host *.mydomain.com
        IdentityFile ~/.ssh/keys/id_primary

    Host *
        IdentitiesOnly yes
        IdentityFile ~/.ssh/keys/%r@%h # uses ~/.ssh/keys/git@github.com for github for example
I originally started doing this because I would have so many keys that servers would reject me for too many authentication attempts, but it also helps make it easy to use distinct keys for distinct purposes and avoiding fingerprinting like this*


Yes that's exactly what I do. I just left it as an "exercise for the reader" to not make the comment too long :)

This kind of stuff is also useful, for example, for AWS machines:

  Host ec2-*.compute-1.amazonaws.com
      # KeepAlive of 50 seconds, because AWS times out after 60:
      # https://aws.amazon.com/blogs/aws/elb-idle-timeout-control/
      ServerAliveInterval 50


Additionally, you can also do:

Host foo foo.example.com some.other.alias


Nice tip about the placeholder, I will steal that. Thanks.


I am more curious what is the upside?

That you trying to SSH into some random server doesn't know that you also use github?


The idea of walking up to a lock and saying “here are all of my keys. Do any unlock you?” is kind of weird and backwards.

But I realize, thinking about it, I was doing that all the time at a previous job where I’d just mash my entire wallet against the keycard reader.

Bonus tangent: join me in playing “Payment Roulette” where you mash your wallet against payment terminals and let your credit and debit cards sort out which is going to pay.


A lot of times the machine would say "Use one card only", won't it? I have a Secrid wallet and I was expecting the aluminium to block the RFID reader except for the 1 card I put in the outer leather pocket, but I still need to open the wallet up and present the dangling card in its sleeve to stop multiple signals...


Blocking radio signals is harder than just adding some aluminium. I'm pretty sure most "RFID blocking" wallets don't actually block RFID reliably.


I’ve seen error messages. But usually my Mastercard wins. I think it might just be faster to electrify.


The analogy isn't the same, the lock could copy the actual key to make a replica in the future.

ssh is only flashing the "name" printed on each key and asking if it should try one of them. (not exactly but it's more equivalent)


Not quite because there is no public/private key analogy. With a physical key there isn’t much security and you are relying on the copying of the key (if someone takes a photo) not happening. There would need to be some sophistication and anyone that sophisticated wouldn’t need to burglarise you. And it is that fact you rely on for a key. It is almost like a credit card PIN


That’s very trusting that there isn’t some race condition on the POS that ends up charging them all.


I’m pretty confident that POS transactions are idempotent. It’s an entire state machine that you’re working through, too, so I doubt it’s capable of performing multiple transactions during the middle of one transaction.


We’ll know we’re in the future when the payment gets split evenly amongst all participants. It’s like paying down a bill with the power of friendship.


  $ ssh whoami.filippo.io
  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  @       WARNING: POSSIBLE DNS SPOOFING DETECTED!          @
  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  The ED25519 host key for whoami.filippo.io has changed
I guess I've tried this before


I think a lot of people in the comments are missing the fact that public keys are by default intended to be public. This is an explicit and intended property of private-public key cryptography. Your public keys are not a security boundary and setting `IdentitiesOnly` in your SSH configuration does not do anything to strengthen your security posture.


[flagged]


> lifts your public keys.

That's why they're called "public".


I have PTSD from trying to explain that public keys are meant to be shared despite the word "key".


That's okay, my PTSD is from people sending their private key when I asked for their public key.


It does highlight a critical difference between "security" and "privacy", though.


It lifts your public keys as much as "git clone git@github.com" does.

They are not stored long-term anywhere, FWIW.


There's no mention of all your public keys being stored on connection, right? It's just comparing public keys it gets sent against what's already public on GitHub


This is like saying there should be a warning for every single website that it lifts your IP address and user agent.


what does "lifted" mean in the context of your public keys (that you published at GitHub if it can tie them to anything?)?


In fairness, many people don't expect github to publish those keys (even if they are public keys)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: