Hacker News new | past | comments | ask | show | jobs | submit login
Auditing GitHub users’ SSH key quality (benjojo.co.uk)
490 points by benjojo12 on June 2, 2015 | hide | past | favorite | 177 comments



Maybe GitHub themselves should just stop accepting keys of a certain length. For example <2048 RSA keys (and <256 ECDSA keys). They could also check against the Debian set.

As the article says, GitHub could be being proactive rather than reactive here. They don't "have" to, but they could.


GitHub now, after reporting this to them do not allow keys below 1023 to be added, and all keys that had been smaller than that, have been removed and owners of those keys got a email like screenshot on the top of the post


According to a 2009 blog post[1]:

> Thanks to our new servers, known bad keys[2] from Debian and Ubuntu are now blacklisted. We estimate that about 1000 keys in our database were impacted by this. If you get authentication errors using keys that worked a day ago, please double-check that they are not on our blacklist. If they are, you should ensure your software is updated and generate new keys. We’ve got a guide to help you out with this.

[1] https://github.com/blog/500-state-of-the-hub-rackspace-day-0

[2] https://github.com/blog/63-ssh-keys-generated-on-debian-ubun...


Woah, this new article says a lot of weak-Debian keys were found. Does this mean Github had a regression in their blacklisting since 2009? Or maybe they didn't blacklist enough originally?


Actually the facts are not incompatible here. There are two questions: Are weak Debian keys accepted in the web app? Are weak Debian keys accepted by their SSH.

The answers were yes and no. It's the same for most systems right now. You can put a weak Debian key in authorised keys, but you won't be able to login anyway.


Or the list used contained keys that weren't actually weak debian keys?


Seeing a key with substring of "Tyr" as the username and that substring of my key matching scared me a bit.

If you want to check how many bits your key is, use

ssh-keygen -l -f ~/.ssh/your_key.pub

(It wasn't mine, while it is an older key, mine is larger than 768 thankfully)

Edit: look at timdorr's example for a better visual.


Most people will want to run this verbatim:

  ssh-keygen -l -f ~/.ssh/id_rsa.pub
You'll get an output like so:

  ⚡~ $ ssh-keygen -l -f ~/.ssh/id_rsa.pub
  2048 f6:2d:94:54:c0:96:18:64:24:fb:c2:ad:ed:6a:1d:68  timdorr@Pixelicious.local (RSA)


There's probably a better way of doing it, but this should check all your public keys if you use more than one, assuming they're in ~/.ssh

  for file in $(ls ~/.ssh/*.pub); do ssh-keygen -lf $file; done


Not better, but could also be written as:

  find ~/.ssh -name '*.pub' | xargs ssh-keygen -lf
Here's a simple bash function to check all your GitHub keys:

  function check_github_keys {
    username=$1
    i=0
    curl -sw "\n" "https://github.com/${username}.keys" | while IFS="\n" read -r line ; do
      tmp=`mktemp -t githubkey`;
      echo "$line" > $tmp
      res=$(ssh-keygen -lf $tmp)
      rm $tmp
      ((i=i+1))
      echo "${username}.keys:${i}  ${res/ $tmp/}"
    done
  }
Invoke as:

  check_github_keys <username>
I'm sure there's a better way to write that one though!


Your initial "find" version would be better if it used print0 because it would avoid failing on files with spaces in their names:

find ~/.ssh -name '*.pub' -print0 | xargs -0 ssh-keygen -lf


This of course can be rewritten as find ~/.ssh -name \*.pub -exec ssh-keygen -lf {} \;


If you use ssh-agent, you can do:

    ssh-add -l
to list all your registered keys.


    4096 63:f2:23:00:c9:0d:07:3b:6d:ad:4d:a9:98:32:f5:25  ***@*** (RSA)
Am I good?


Your key is 4096 bits, you're good.


True, this will be default if you don't namespace your keys and use ssh config files like I do, I should have just said that.


how much safe are we, with a 2048 bits key?

is this something we should be upgrading (like to 4096) in the near future?


Not much point in upgrading from 2048 bit RSA to 4096 bit RSA. Instead, you should plan to upgrade to ed25519 keys when your client and servers support them - faster and better security than RSA.


Of course that is an "if" one should carefully think about -- e.g. it is OK if all you are using is OpenSSH at version 6.5 or later. (That can be a problem with many older boxes). But other than that, last I checked only SSH.NET and tinyssh supported ed25519 keys. Shameless plug for some more data on this: http://ssh-comparison.quendi.de/comparison.html (yeah, that page could be a lot better -- pull requests are welcome)


Does anybody have a good (and easy!) guide how to do that on my Mac or Linux machine (client and server) ?


If you have experience with RSA key pairs, using ed25519 key pairs is easy. To generate a key pair just run: ssh-keygen -t ed25519

As with RSA, this command generates a public and private key file. Put the public key in the authorized_keys file on the server side.

You'll need OpenSSH 6.4 on both the server and the client side. If you have an older version, I would not recommend upgrading outside of your operating system's normal upgrade channel because then you'll be responsible for security updates. Instead I would wait until your operating system has it.


It amounts to doing this:

  $ ssh-keygen -t ed25519
As usual, on the server, you do something like

  $ cat generated-key.pub >> ~you/.ssh/authorized_keys
EDIT: sibling post was quicker off the bat. Oh well, that'll teach me to not refresh a tab :p


2048 is fine for the foreseeable future; it's the same key length used for most SSL certificates (including CAs!). Your next key upgrade should probably be to another key type entirely, most likely ED25519.


I don't have a qualified answer but given he says it would take 24 minutes to crack a 256bit key and 3 days to do a 512bit, I would extrapolate (given exponentially difficulty as you add more bits) to roughly:

- 180x per doubling bit size would be - 512 doubled twice, would mean 3 days * 180 * 180 = 97,200 days

I think you're safe.


That's not how the math works.

First, 2048 bits is not 512 bits doubled twice, but rather doubled 1536 times (512 doubled twice would be 514). If this were a symmetric cipher, you could stop here and conclude that a 2048 bit key was 2^1536 times stronger than a 512 bit key.

However, RSA has diminishing returns on security as you increase the key length. The strength is determined by the complexity of the GNFS, the fastest known way of breaking RSA[1]. That tells us that breaking 256-bit RSA takes ~2^46 operations, 512-bit RSA takes ~2^63, 2048-bit RSA takes ~2^116, and 4096-bit RSA takes ~2^156. 2^116 is a lot of operations - they say the amount of energy required to break that would be nearly enough to boil all the water on earth.

[1] http://crypto.stackexchange.com/questions/8687/security-stre...


> they say the amount of energy required to break that would be nearly enough to boil all the water on earth.

Not wanting to be alarmist, but what you're saying is that someone breaking my ssh key (which is 2048 bits) is the end of the world...


great answer!


On his/her admittedly subpar machine. Keep in mind that this will vary wildly for different hardware.


i had the same moment of panic and ended up removing old keys and regenerating my keys that are in use. i wish i'd seen this comment beforehand -_-


How does one even go about getting a 256-bit key? You have to do it on purpose somehow, or it has to be seriously old, in which case you're likely aware somehow that that's a terrible idea.

Is there outdated ssh keygen software out there that still generates sub-768 keys?


I'm pretty sure the first 256 bit key listed in his output is/was mine.

It was a key generated and used as a test (years ago). It has never been used to access my Github account. Also, my account is pretty bare as it is.

To be safe, though, I have now removed the key.


> I'm pretty sure the first 256 bit key listed in his output is/was mine.

Post the private key to prove it!


All that will prove is that someone was willing to burn less than a half an hour of CPU time.


256 bits is a perfectly respectable length for an ECDSA key, so I'm guessing people tried to generate those and accidentally created RSA keys instead.


No, ssh-keygen won't create that small RSA keys. It is a limitation that's been around since long before OpenSSH (although I believe it used to be 512, the limit now seems to be 768).


To be honest, I have no idea. I had hack about to get Go's crypto/rsa package to give me a key that size, I really would love to know what can make these keys


And where do the odd numbers come from? 1023 bits? 799 bits??


So this one is kinda fun.

IIRC PuTTYGen had a bug in it for a very long time that you would ask for a 1024 key, and it would subtract a bit off it. You can see the same with 2047 keys in the data that I will be publishing on the next post.


Some people use slightly odd key-sizes on purpose, in the hope of buying a little extra time in case something like the Debian OpenSSL bug happens again.


Same kind of people who write 1338 instead of 1337, for the lulz


They may have been assuming that appropriate key lengths for AES would work for SSH keys as well.


Perhaps someone is on an obscure platform whose only SSH key generator is subpar.

Or perhaps someone has a system that generates keys automatically, and it was poorly configured.


I vaguely remember that 10 or 15 years ago I've seen obscure ssh client for relatively obscure platform that could not handle RSA keys that were longer than some X, with X being something like 640.

Even then, generating such key with OpenSSH was not something one could do by accident.


At least Github were "kind" enough to strip the comments from the public keys they publish without permission. I would've been even more upset if they were leaking things like username@workdomain....


> from the public keys they publish without permission

Public Keys are supposed to be public. It's OK not to know that, but blaming Github for doing crypto right is not really clever...

If you don't want your public key to be traced back to you, generate a new pair just for github.


blaming Github for doing crypto right

So github is doing crypto right by unnecessarily exposing data that is _only_ relevant to a) the user and b) his personal access to his repos?

By this logic, why not make crypto even better and add something like github.com/user.address, github.com/user.mail or github.com/user.phone?


your analogy is very flawed.

public keys are essentially opaque tokens that do nothing more than ensuring that a counterpart of a connection is whoever you think is associated with the public key. The key itself does not convey that information. It conveys no information at all beyond its cryptographic properties.

Turning a key into anything else (e.g. through re-use, publishing it elsewhere in association with other data) is not an intrinsic property of the key.

On the other hand personal data such as an address cannot be easily replaced like a key, immediately ties it to a person and does not provide any cryptographic properties at all.

TL;DR: pubkey is not private data, user.address is not crypto


The analogy isn't flawed, it's a question of the benefit for the person who's key/info it is, in this case github users. We generally don't have anything to gain from our keys being made public (address, phone number, etc...). It's also a generally accepted faux pas to share someone else's public key for them. Quoted from another comment[1] (quoted from email for the practical paranoid)...

You can send someone else’s public key to an old-style keyserver. Although you might think this would be a favor, it’s actually extremely rude. The public key owner might have reasons for not using a keyserver and might prefer to distribute his public key via some other method—or he might not want to publicize the key at all beyond a small group of people.

Never publicize someone else’s key for them!

Admittedly, it's a risk we should be aware of. But regardless of whether it's rude or not, it doesn't seem to be what people expect. What's worse though is that whether it's malicious or not; user trust is practically impossible to get back after it's gone.

[1] https://news.ycombinator.com/item?id=9648351


But the keys are public...


That's my point. They shouldn't be. I never gave Github permission to publish my keys. The "public" part in the key is merely there to distinguish it from the "private"-part ("never share this with anyone"). It should signify "share this with people whose machine you want to access", not "share this with the whole world".

From a healthy paranoid point of view: you don't share your public key unless you have to. Sure, there are no known attacks on strong RSA keys today, but that doesn't mean there will never be. Why take that risk with, literally, thousands of keys and people's security? It's rude at the very least.

Of course, you should never use your Github keys for anything else, but that's beside the point entirely.

As for the comments: key comments are useful but often contain information that can identify a person (e-mail address, username@machine etc). Publishing that would have been even worse.


> Why take that risk with, literally, thousands of keys and people's security?

I would say it encourages scrutiny. The assumption of public keys is that they are public, if any part of your security architecture relies on a public key being private then it would seem flawed, flaws that should be exposed.

And if them being public induces extra paranoia, such as using separate keys only for github then all the better.

Sunlight is the best disinfectant.


Exactly.

These keys are not less secure for being published, but moreso. At least now the public can determine whether or not we trust these keys and any edits made with them as opposed to weaknesses in their security going abused without notice.


This is about being able to connect keys to individuals and then searching The Stash for more links that then build a graph.

But it's just metadata, isn't it..


If you use a key exclusively for github servers then there's no graph-building.

something like the following in ~/.ssh/config

Host *.github.com

IdentitiesOnly yes

IdentityFile ~/.ssh/hostboundkeys/github_ed25519


Here's what I do:

    # IdentityFile magic, should be placed at very end of file
    Host *
    IdentityFile ~/.ssh/keys/id_ecdsa_%r@%h
    IdentityFile ~/.ssh/keys/id_rsa_%r@%h
    IdentityFile ~/.ssh/keys/id_ecdsa_ANY@%h
    IdentityFile ~/.ssh/keys/id_rsa_ANY@%h
    IdentityFile ~/.ssh/keys/id_ecdsa_%r@ANY
    IdentityFile ~/.ssh/keys/id_rsa_%r@ANY
    IdentityFile ~/.ssh/keys/id_ecdsa_ANY@ANY
    IdentityFile ~/.ssh/keys/id_rsa_ANY@ANY
Will look for user@host, ANY@host, user@ANY, then ANY@ANY keys. You can add ed25519 to this.


This looks pretty neat -- however, do you use passphrases for your keys, and if so, how do you manage them? Only 2 obvious solutions spring immediately to mind - use the same (or none) pass for each key, or have a unique one per-key and some sort of separate password database with a master password.

At least, I can't imagine memorising enough unique passphrases for all the user/host combinations I currently have.

I'm hoping there's some clever built-in or easily added (like keychain/agent) way to secure individual keys on the filesystem without excess complexity when using them.


The IdentifyFile directives actually work with ssh-agent - it will try the keys listed there first, using them via the agent if they're loaded. I use the same passphrase on all keys and load them into my agent all at once (when loading, the last passphrase you entered will be tried to decrypt each key).

Normally, the problem with having many keys in the agent is that a server you're logging into will boot you after supplying too many keys it doesn't accept, but this fixes that.


This is the answer right here. Also it's wise to use different keys for different services, for the same reasons that you'd use different passwords.


When I share a password between two services, they get the plaintext password when I authenticate, so the first one can impersonate me in front of the second one. How does this apply to keys?


If you have one key, and use it for N services, compromising your key compromises N accounts. If you use one key per service, compromising a key only compromises one account.


If you have your N private keys all stored on the same device (such as side-by-side in your ~/.ssh/keys directory, as in ryan-c's example upthread), under what scenario would just one of those keys get compromised?

You only need one private key per device to be secure. The benefit of using separate keys per service is privacy - it prevents the various service providers from colluding to determine that you're a user of all the services (but if you're not careful you're probably leaking other information to them that would let them learn this anyways).


If you're not using passphrases on your keys, then yes they are locally wide open, much like a passwords.txt strategy for passwords. If you do passphrase them, the attacker now needs N passphrases. Perhaps you notice the keylogger before all passphrases get logged? There are probably more scenarios where N keys is strictly better than one, but that's the first that comes to mind.

I agree with the privacy aspect, it's that's the same point that the8472 made.


"perhaps you don't use password manager and you notice the keylogger halfway through" is a pretty unlikely scenario to motivate me to use a bunch of unique passphrases.

It's not "strictly better" when it hurts your ability to use and memorize strong passes.

Usability is part of security.


And unlike passwords the extra overhead of maintaining multiple keys is virtually frictionless.


> if any part of your security architecture relies on a public key being private then it would seem flawed

What about your privacy architecture? Can the public key be derived from a packet capture of SSH? My quick session with Wireshark and layman's protocol/crypto understanding says probably not. But it seems possible that while the crypto may be designed such that the public key may be public without endangering the cryptography, there are still privacy reasons (being able to identify people by unique public key) to not share it any more widely than it needs to be.

For example, it seems like I have read that PGP public keys can be read in the clear, which allows metadata graphs to be built by passive interceptors. Maybe SSH doesn't have that issue though.


Actually, it looks like the public key can be derived from a packet capture of SSH. See https://tools.ietf.org/html/rfc4252#section-7


AIUI A SSH session first performs a DH key exchange and authenticates the server. Only over that already-encrypted session will the client offer its public keys.

That means the public key will not be leaked to outside observers. Combine with server-specific keys to avoid potential "try logging into my server" social engineering.

This means only the server will ever learn your public key, but it has to know that already anyway.

So publishing your public key does not leak any privacy bits.


You're right, my bad.


I think that packet is encrypted, though -- at least, it looks like that in Wireshark to me. I see key exchange packets and the following ones seem to become encrypted, before I have given ssh-agent the approval to use my key. I am mostly going off of what Wireshark's protocol decoders tell me, though, so I could be wrong.


You're right, I was wrong. Sorry!


Assuming for a moment that this problem exists: That wouldn't change anything about my argument. If privacy is part of the threat model then privacy shouldn't be conditional on the public key being kept secret.

By publishing the key you expose the flaw in that setup.


FWIW I'm surprised you got downvoted, and it wasn't me. Is privacy part of the threat model? The closest thing I could find is http://iacr.org/archive/asiacrypt2001/22480568.pdf , "Key-Privacy in Public-Key Encryption" (2001), where they conclude most RSA encryption schemes are not anonymous.

If that applies to SSH, I see no problem in asking for "public key secrecy" as a requirement/option in a layer above the crypto.


>Sunlight

Did your dad ever come into your room and throw open the curtains to get you to get your lazy ass out of bed?

Today you know he was probably right, but how did you feel about it when it was happening? Probably not very good.


I'm sorry, but you misunderstand what a public key is if you merely think of "public" as a way to distinguish between private.

If your security model relies on public keys not being publicly known, then your security model can't reasonably be expected to work or be honored by GitHub.

Considering a public key as a "shared secret", as you're claiming it is, moves beyond "healthy paranoid" and into just "paranoid".


There might be other reasons not to want these public keys to be published. For example, suppose there is an anonymous developer on a controversial project (maybe one that litigious companies don't want to exist?) who has chosen to have two GitHub accounts, one with the developer's legal name and one with a pseudonym.

If the developer is using the same key with both accounts, GitHub knows about the connection between them, but the larger public doesn't -- until the keys are published.

Another possible source of risk that would relate more to publishing the comment fields (which GitHub apparently chose not to do) is letting an attacker know which client devices to try to steal or compromise in order to get access to a developer's account. (Not a cryptographic attack at all!) It might still be possible to make some guesses about this if you know, for instance, that a developer bought a new laptop in a given week and then added a new key and either did or did not deactivate the old one.

Public keys that are used for confidential communications from the public or for signing publicly-released data probably ought to be distributed widely. But public keys that are used to authenticate to a service also reveal nonpublic facts about the number and activation and deactivation of devices that are used to access that service. If someone is crawling these records and noticing the timing of changes, it may help for planning attacks -- again, noncryptographic ones.


GitHub actually won't let you use the same pubkey in two places, but I get what you're trying to say.

I'll reiterate - you should assume your public key (and any comment on your public key) is already public information, even if GitHub hasn't published your pub key. Anything else is not good security practice.

As far as I can tell, this is not a concern to anyone in crypto -- revealing public keys, that is. Obviously if you're a crypto expert reading this and disagreeing, feel free to chime in, but as far as I know, there are zero concrete crypto reasons to obfuscate a public key.

It's your fault if you put private information in a public key's comment field.


I agree with you on the cryptographic point: you shouldn't (have to) expect to get cryptographic security from the secrecy of a public key, regardless of how the public key is used. My point is that there could be other reasons not to publish it, even though it's not a source of cryptographic vulnerability.

It seems to me that in crypto there are plenty of fields where the protocol designer would say "this value is nonconfidential" or "this value is not required to be kept secret" -- reasoning from the protocol's internal cryptographic security goals -- where publishing the value still has other adverse consequences. For instance, TLS session tickets per RFC 5077: "since the ticket is encrypted and the attacker does not know the secret key, a stolen ticket does not help an attacker resume a session".

But the protocol's internal security goals aren't always the only relevant security goals, and in the session tickets example, there is also a privacy sensitivity about disclosing them in some contexts because they can be used to show that a particular party was responsible for a particular TLS sessions (like if you were using Tor to access a web site but then posted the session tickets under your own name because RFC 5077 says that they don't need to be kept secret).

I think that's precisely what's happened here. If you read SSH protocol specs, they will say that public keys never need to be kept secret -- from the point of the SSH protocol's security goals. That's great, and it's a fair point. Users can still have other perfectly reasonable security reasons to request that people not publish them in particular circumstances!


> Users can still have other perfectly reasonable security reasons to request that people not publish them in particular circumstances!

Yes, but nobody has shown any compelling reasons in relation to pubkeys used for github.

And even if there were some potential small benefit it would have also be weighted against the benefit of having the whole population of pubkeys available for security research.

The OP article clearly exposes problematic practices that might have otherwise gone unnoticed.


> Users can still have other perfectly reasonable security reasons to request that people not publish them in particular circumstances!

I feel your argument relies on these actually existing -- so what are these reasons?


Let me quote from "PGP & GPG -- EMAIL FOR THE PRACTICAL PARANOID":

You can send someone else’s public key to an old-style keyserver. Although you might think this would be a favor, it’s actually extremely rude. The public key owner might have reasons for not using a keyserver and might prefer to distribute his public key via some other method—or he might not want to publicize the key at all beyond a small group of people.

Never publicize someone else’s key for them!

Now, if your reply reiterates your argument that public keys are public because it's in the name, duh, then I can't help..


It's about building a comprehensive security model -- the author of what you quoted would be wrong if he suggests public keys should be considered, at any time, by anyone, to be anything less than public.

Any security model that relies on a public key not being known is a bad security model.

How "rude" an activity is only matters when you're dealing with people who care if you think they're being "rude", and in PKI that's not possible because your public key must be given to untrusted parties.

What's more relevant is the attack surface you present by exposing your public key. Since your security model already assumes they have it through other means, you've given your attacker no new information.

Hiding your public key is textbook "security through obscurity".

Edit: I tweeted the author of the quote you gave (Michael W. Lucas, @mwlauthor) about the above article, I'll try and get him to chime in on our discussion if I can.


What's more relevant is the attack surface you present by exposing your public key. Since your security model already assumes they have it through other means, you've given your attacker no new information.

Unless you're assuming they don't have it via other means. If I have a keypair I only use for GitHub, and GitHub didn't publish pubkeys as they do, then it is a fairly safe assumption that an attacker does not have my public key. Not something to build an entire cryptosystem around, but still a fairly safe assumption.

But I do agree when you say, "Any security model that relies on a public key not being known is a bad security model". It's the difference between "rely" and "this (weak) assumption contributes positively to overall security".

Let's look at a scenario. Say I:

1. use a particular keypair just for GitHub, and nothing else.

2. had generated this key on Debian during the period when it was brokenly generating easily-factorable keys with low entropy.

If GitHub did not publish public keys, then I could then reasonably expect that I was safe for the life of that key. Yes, upon finding out about the vulnerability, I'd immediately revoke and generate a new key, but there were people who unknowingly had vulnerable keys up there for a very long time, and they could have been compromised for a long time, without their knowledge.

Again, no, you can't rely on the public key being private, but publishing it can have some bad side-effects when something unforeseen comes up, and not publishing it can offer you some greater protection than publishing it, even if it's a small amount.

Having said that, I actually don't disagree with GitHub's decision to publish public keys as they do. So: shrug.


If GitHub did not publish public keys, then I could then reasonably expect that I was safe for the life of that key.

I don't think so, because of the way GitHub's SSH access works - you don't need to know the account associated with a given key to try and authenticate with that key, so trying all 32k "Debian keys" of each size and seeing which ones let you in is quite feasible.


Very good point, though I'd assume that GitHub has rate-limits in place that would catch people trying to brute-force accounts. Still, though, even with that, you're right that your safety margin drops a bit.


> Unless you're assuming they don't have it via other means.

Never, ever assume this of your public key.

The solution to the Debian bug is to use a keypair not generated by the bugged Debian build, not "continue to use the bugged keypair".


Never, ever assume this of your public key.

Why? I mean, I'm not saying it's an absolute 100% certain assumption that any particular public key is secret. I'm saying it's a reasonable assumption that will likely be correct in many cases. Not something to base your faith of a cryptosystem on, of course, but it's a reasonable assumption in many circumstances that can have a positive impact on the actual security of your accounts. The public key I use for my own machines is very unlikely to be known by anyone else, because it's only used on machines I have full and sole control over. Sure, that's not absolute proof (maybe one of my servers has been compromised and I don't know about it), but it's a reasonable assumption.

The solution to the Debian bug is to use a keypair not generated by the bugged Debian build, not "continue to use the bugged keypair".

Duh. If you actually read what I wrote, you'd see I agree with that. I'm talking about the fact that people were using broken keypairs for long time, and didn't know, because the vulnerability hadn't been found and disclosed yet. You won't generate a new keypair if you don't know there's something wrong with the one you have.

My point is that if an attacker knew about the vulnerability a long time before it was fixed and publicly disclosed, GitHub publishing public keys gives that attacker a nice corpus of keys they can check to see if they're vulnerable, and can make use of that information (since the attacker knows that any bad key is known to be used for a particular GH account).

If GH did not publish public keys, all users would have been safe from that particular attack vector. Sure, there are other avenues where an attacker could get ahold of some of those same public keys, but it's probably a vanishingly small percentage of them.


> If the developer is using the same key with both accounts

They shouldn't be doing that, though. Each public key should be tied to one identity. (You might have many keys to one identity, but not vice versa.)


GitHub also won't allow you to do that.


If the crypto you use is sound/strong there is no reason-not-to/risk in making the public key known to everyone and his dog. If the crypto is not sound then the solution is not to hide the public key (security by obscurity style), it is to use better crypto.


If the crypto/implementation turns out to be unsound, first you have to 1. learn that the flaw exists, and then 2. take steps to remedy the situation. That's a window of opportunity where "obscurity" can potentially buy you time. On the other hand, if you assume your public keys are widely known and distributed, you're more likely to drop everything and take care of step 2 ASAP. So maybe it's a wash...


Or at least give each user the option and default it to unshared. I don't see why they'd default to sharing everyone's.


So is the writing on a postcard; doesn't mean you want it published.


I agree, this is rude and as far as I remember, it's not mentioned anywhere in the key upload interface.

It's equivalent to uploading someones PGP key to a keyserver without his or her permission.


I hoped my key wasn't effectively public by using it with github, but I honestly tend to assume the worst whenever I use a service like it.


Now you can also test several attacks on them, compare them to a larger database to see if you have common divisors, check for low primes, check for bad primes (fermat factorization)...


Yup, this is what I will be trying next.


Oh and check for low private keys as well, I did that before here's the code: http://cryptologie.net/article/265/small-rsa-private-key-pro...


It would be interesting to see, what's the public key that's used by the largest number of accounts? I wonder if some people, instead of generating their own, use a public/private pair they downloaded from the internet somewhere, not realizing the vulnerability.


I don't think github allows you to use the same key for different accounts. Maybe it's the way they identify the user who is pushing over ssh?


Correct!


I don't think that would happen since you would not find such a result googling for "how to get a pgp key".

Makes me want to do a parody webpage explaining how to setup PGP by just copy/pasting one


Maybe it doesn't happen directly but through downloading some preconfigured Linux VM with the private/public key already set up.


It's quite possible it doesn't happen, but it's also a trivial SQL command to find out..


I'd also suggest looking at the rsa public exponents. PuTTY and OpenSSH (at least used to) use their own values when generating keys, so you can somewhat reliably identify which keys were generated by these tools


It could be interesting to try to match those keys to the ones generated by Debian during the OpenSSH vulnerability [1] period.

[1] http://jblevins.org/log/ssh-vulnkey


That was one of the things that was checked in this post


Oups! Sorry, my bad. I only skimmed through the article very quickly.


But there was no source on the problem, thanks for the link!


Do you have any (anonymized) stats for the largest key sizes you encountered? I ask as the owner of a comically-large key.


Rachel talked about Github and public keys a while ago (saw on HN): https://rachelbythebay.com/w/2013/04/07/ssh/



It would be far more effective to add a "log in with Facebook/Twitter/GitHub" button and oAuth than mess with SSH keys, surely?


Especially the guy with commit access to PyCrypto should reconsider his position in the project..


Kudos to Github for not charging him with "Unauthorized Access of a Computer"


Given their customer base, that sort of response would have kicked off a shit-storm. ISTM that any "responsible disclosure" ought to at least rate a T-shirt. (If GH don't want to pony up the T-shirt, that's fine, but they can't send customer notifications before the researcher publishes.)


I'm not saying that I didnt get anything for it what so ever, The peer of mine did manage to send over some swag as a thanks, I now have http://i.imgur.com/d2f7mcD.png on my work desk :)


> (If GH don't want to pony up the T-shirt, that's fine, but they can't send customer notifications before the researcher publishes.)

In my uneducated opinion, that seems like a really good way to judge whether something qualifies as worthy of a bug bounty etc.


Sure, but as I understand it, he doesn't/didn't need to actually try it on github's servers. If he put the public keys in question into the authorized_keys list of a second account on his personal system, he can locally verify that the brute forced private key is correct. I think the wording agrees with this:

> <snip> and then a few more minutes to transform those back into a SSH key that I could log into systems with.


> List public keys for a user - Lists the verified public keys for a user. This is accessible by anyone.

Hardly 'kudos' for them; the API to list public keys is listed by GitHub as 'accessible by anyone' in the documentation, it would be difficult to construe what they did as 'unauthorized' because of that.


To be wildly pedantic, GitHub wouldn't charge him with anything, the DoJ would, regardless of what GitHub does/doesn't do.


that https://github.com/anybody.keys feature, how on earth did OP find this?


Its a documented feature [1].

[1]: https://developer.github.com/v3/users/keys/


I've heard of it before, the same is available in their API too:

https://developer.github.com/v3/users/keys/#list-public-keys...


In the mean time, Bitbucket still doesn't accept ECDSA keys:

https://bitbucket.org/site/master/issue/4222/no-support-for-...


What is the easiest way to manage SSH keys?

I can't remember where half of mine have been saved. I should really revoke everything and start again, as I use it for accessing my VPS too.

How do you revoke all keys on Ubuntu and OS X?


There is no concept of revoking ssh keys, so you have to remove them from the ~/.ssh/authorized_keys file on every server you have access to, and delete the public keys at every service you've uploaded them to.

For a revoking mechanism to be possible you would need a trusted third party (like a certificate authority) to verify the keys for each and every connection you make.


For managing large infrastructure, it's possible with semi-recent openSSH (5.4+ I think?) to validate and revoke keys[1] by signing them with a different key which the server (or client) trusts.

[1] http://www.lorier.net/docs/ssh-ca


> 210 | ssh-ed25519 AAAAC

Does this mean GitHub finally supports Ed25519?


I've been using an Ed25519 key on github for about 6 months now.


As someone who's put an ed25519 key on github... I'm not actually sure (didn't verify). I also still have compatibility keys there, I merely installed it so that, opportunistically, it could be used when supported.


I'd be interested in the script used to scrape the GitHub public key endpoint? I assume it just throttled back to stay under the GitHub API rate limit?


I still use a 1024-bit DSA key I generated ~10 years ago. How bad is that? Should I replace it with a 2048-bit RSA key?


> We go on to consider Diffie-Hellman with 768- and 1024-bit groups. A small number of fixed or standardized groups are in use by millions of TLS, SSH, and VPN servers. Perform- ing precomputations on a few of these groups would allow a passive eavesdropper to decrypt a large fraction of Internet traffic. In the 1024-bit case, we estimate that such com- putations are plausible given nation-state resources, and a close reading of published NSA leaks shows that the agency’s attacks on VPNs are consistent with having achieved such a break. We conclude that moving to stronger key exchange methods should be a priority for the Internet community.

From: https://weakdh.org/imperfect-forward-secrecy.pdf


Yes


Good article. Very detailed and thoughtful!


Pitting two well-known security principles (or at least watered-down versions) against each other: "security by obscurity is evil" and "defense in depth". Which trumps here? Should the public keys be printed in every phone book, just because it says "public" in the name? Or should they be kept semi-secret, since publishing them could lead to them being factored offline?


Defense in depth doesn't conflict with "security by obscurity is evil": Defense in depth is that I keep my private key secured with a passphrase, on an encrypted volume, and that I take measures to protect against applications having access to it unless they require it. It's the layer of physical security where I don't leave my laptop where it's easily accessed, and everything else that goes into securing a workstation.

Defense in depth recommends having multiple layers of security, such that a breach of a single layer doesn't constitute a full breach. There's no requirement (and in fact I'd argue there's no solid recommendation) for including obscurity as one or more of the layers.


The parent may not have used the best terminology, but the point still stands: your "defense in depth" example utterly fails to protect your private key if your public key is widely-available and easily-factorable.

If I didn't have my public key on GitHub, it's unlikely that even that could fall into an attacker's hands. Not that I would rely on that assumption, but it would reduce my attack surface.


If you think there's a chance that public RSA (lets not even get started on ed25519) keys of reasonable size are easily-factorable, there's a lot of groups out there who'd love to make you rich or lock you up.


> If you think there's a chance that public RSA (lets not even get started on ed25519) keys of reasonable size are easily-factorable, there's a lot of groups out there who'd love to make you rich or lock you up.

I think that's more accurate if you replace "think" with "can actually practically demonstrate".


What if, in 10 years, 1024-bit keys are factorable in <10 days on commodity hardware? I could call that a "breach of a single layer." If 1024-bit keys have been widely publicized, it turns into a "full breach", because the defenses weren't deep enough. If the keys had not been publicized, then the entire 1024-bit key space has to be iterated online in order to find weak keys.

Now, of course the user can take some responsibility for not upgrading their key in 10 years, etc.

I don't see why it's, like, some moral obligation to invite factoring attacks just because of the name of the key and knee-jerk hatred for "obscurity."

Put another way, it makes sense to avoid pure obscurity when adding it takes extra work. In this case, GitHub is going out of their way to add theoretical weakness, but apparently we must do it, because security bible!


So, all the "it's called a public key for a reason!" people: when are you going to submit a patch for OpenSSH allowing unauthenticated users to query arbitrary users' public keys, and maybe a list of users while you're at it? You vehemently support one particular operator of an SSH server doing it, citing good security practice, so why not do it everywhere?

Edit: to be fair, there is the difference that GitHub has already added it and probably didn't have to write C code to do it. So maybe this feature should be requested for things like, say, cPanel, and users' $HOME/.ssh/authorized_keys should be world-readable by default. Still, maybe it's worth doing in OpenSSH so everyone can get the huge benefits of this currently only enjoyed by GitHub's users.


This is a very grave error. If this caused damage to open source projects then I could see a class action suit against GitHub.

1. Duty of care - should never have accepted keys provably weak.

2. Poorly communicated that username.keys was available, thus many users may have thought their keys weren't at risk.

3. No countermeasures from crawlers mass collecting keys. (Not they they should even need to do this - they should just have done #1 in the first place!)

This isn't a game man, GitHub hosts a ton of the world's open source code and they're supposed to be experts in cryptography and security. Russian mobsters, NATO spooks, bitcoin drug cartels, and even high school script kiddies are all constantly trying shit and it impacts us all not just the people with weak keys. If python core gets backdoored I get backdoored, no matter how careful I am with the software I install.


Instead of downvoting, let's educate people a bit more:

1. Picking a small key is all on the user. It's like choosing the single letter 'a' as a password. If you want to do so why not?

2. The key you give to github is a "public" key. It is made to be public so this should be irrelevant.

3. There is 'almost' no known countermeasures against mass crawls of public keys. Look at the recent attacks: https://blog.hboeck.de/archives/872-About-the-supposed-facto...

What they could do: check against databases of public keys to see if your key is weakened by such attacks.


I strongly disagree with #2. Your public key should NOT be public, especially without your explicit consent. Specifically because, at least theoretically, it could be used to derive your private key. From a parandoid point of view that's just Bad.

This is one of the reasons why should use different key pairs for different purposes.


I strongly disagree with you. So do many, many people who upload their public PGP keys to keyservers. The whole point is that anybody, anywhere can have my public key without knowing my private key. If you can derive the private key from your public key, then you have a really bad keypair (by algorithm or by keysize).


Yes, but communication is the whole point of PGP. I didn't upload my PGP key to a keyserver, I uploaded SSH keys to GitHub so that I could check out my own code--code which is in a private repo.

I can't think of any reason that my SSH keys should be publicly avaiable. GitHub offers private repos so I can't understand why keys are all public by default.


It is because there is absolutely no reason they shouldn't be public. You can generate as many ssh key as you want and if they are long enough they are secure.


> Specifically because, at least theoretically, it could be used to derive your private key.

What theory? I'm unaware of a current working theory that could be used to derive a private key from a public key of sufficient complexity.


Well, maybe when some of these keys were made, they were sufficiently complex, but now they're not. Revealing those public keys has potentially given attackers months/years to try to factor them offline. If the public keys were not known, Github would have a chance (and hopefully does) of rate-limiting brute-force attacks. Heck, even if Github is doing nothing to help against brute-forcing, just hiding public keys might make the bandwidth costs more infeasible than the cost of factoring a known public key.


They're insecure whether or not GitHub makes them viewable. All you get by not publishing your public key is a false sense of security.

This is textbook security through obscurity, and is considered ill-advised by the security community.


But in real-world terms, some users are less likely to be compromised if GitHub hadn't published them. In that light, I don't think it's advisable for GitHub to go out of their way to publish them without the user's knowledge.

I think the "security through obscurity" principle ought to, if it doesn't already include this, say that added measures or core design principles should not be based on obscurity. This should not mean that all obscurity must be removed. In this case, GitHub have added anti-obscurity, and the defense is mainly dogmatic mis-application of the principle IMO.


> But in real-world terms, some users are less likely to be compromised if GitHub hadn't published them.

This is not true.


Can you read my reply to your "sibling" comment, especially regarding 512-bit keys? I want to know if I have a factual misunderstanding. Or maybe we disagree on probability or something.


The solution to "my key is easily factorable" is not "hide the key", it's "get a new key".

Factually you haven't said anything I know to be wrong.


I agree, with the (silly?) distinction that it's not "hiding" like a secret key, it's just "not showing to the whole world" because they never had a good reason in the first place IMO. Had they not published them, it would address the privacy concerns some of us have, and happen to band-aid over the easily factorable keys too. I guess I'll agree that's not really a legitimate reason to make them "hide" them now... it's mainly my preference for avoiding metadata leakage. I shouldn't have focused so much on factoring.

Just in case anyone is still reading, some rough analogies: Would you publish intermediate state data from a hashing or signing process? Would you publish your users' password hashes (even w/ scrypt and robust character set+length requirements)? Would you re-use Bitcoin addresses that have spent before?[1] Would you add a feature to an SSH server to return users' public keys to anyone on the internet? Would you have GPG auto-publish new keys to keyservers? I see these as not usually fatal, but not smart or necessary things, somewhat similar to this.

[1] One of the justifications for address rotation in Bitcoin is that once the address has spent, its 512-bit ECDSA public key is known, rather than just a RIPEMD160(SHA256()) hash of the public key. Absurd paranoia, lack of understanding crypto, or defense in depth?


if they are "compromised" then the whole security of internet is.


Oh, the whole internet is using 512-bit RSA keys, like some GitHub users were? (And I did say "some" before, not "all" or "whole internet".) My point is that the 512-bit users would not have been targetable if nobody knew their keys were 512 bits long. And with bandwidth constraints, their keys would probably not have been bruteforceable either. Due to GitHub publishing their keys, they were targetable, potentially for months, plenty of time to factor.

I guess the response to that will be something about how they don't "deserve" protection because they used weak keys, and while I would resent that sentiment, I can't really argue against the idea.

To sum up, GitHub is doing something cryptographically unnecessary for this use case, that potentially harms confidentiality and anonymity for some users, and the arguments in favor seem to be: 1) A few users find it marginally useful, 2) It doesn't break the actual crypto if the users do it right, 3) Obscurity is taboo, 4) The name is "public key". I'll grant my position is weak, but so are those arguments. Their primary strength is dogma. Which, I don't know, maybe drilling crypto basics does have a net benefit even if they're not applicable to every situation.


> My point is that the 512-bit users would not have been targetable if nobody knew their keys were 512 bits long

This is wishful thinking. A Man In The Middle Attack would have worked on him.


MITM SSH to get the public key and factor it? My understanding from other discussions in this thread is that the publickey authentication protocol is encrypted with the server's host key. Are you relying on the user ignoring key mismatch errors, or targeting them on the first connection and relying on them not checking the key fingerprint? Or something else entirely? I'd like to learn if there's something I haven't thought about here.


It's not because you had more time that you will be able to crack a 1024bits RSA public key.


Are you talking about how factoring will take more time than anyone has available, or something?


can you suggest a better name for it then?


I think you are talking about private keys.


Edit:

In response to your #1:

Picking a password is all on the user too. But magically GitHub is competent enough to stop users from picking the password "ilovecake". Most users of GitHub are not security professionals. Just like most people opening a bank account are not bank vault security professionals.

Original:

They are downvoting me because they love / work at GitHub or don't understand how critical software security is. If you think about the physical life equivalent here (say a bank leaving keys out in the open for safe deposit boxes) there is no way to rationalize it. But all of a sudden it's our favorite social coding startup we can't actually call them out on a huge security fuck up. If this were Microsoft we'd be laughing.


> But magically GitHub is competent enough to stop users from picking the password "ilovecake"

That is definitely a good thing, but github wouldn't be responsible if they didn't do that and people chose weak passwords.

> If you think about the physical life equivalent here (say a bank leaving keys out in the open for safe deposit boxes) there is no way to rationalize it

No, it would be like a bank not actively looking for deposit box keys that customers may have dropped.

btw, I 100% think github should protect users from weak keys, I'm just disagreeing that they could somehow be sued for it


I think it is more like a bank making a diagram of the lock used on each customer's safety deposit box and posting that up on the internet.

I don't see any good reason to put everyone's public key out in the open. Is there any possible way that hiding the keys would hurt github's profits?


That is a truly awful analogy.

The entire point of PKI is that the public key is meant to be public. The impact on your security if a properly-created public key gets out is absolutely nil. I don't see any reason to hide them, save for an irrational belief that only comes from not knowing how the math works.


Noted upthread: there are some noncryptographic threats about revealing the identity of anonymous users, and conceivably giving people information about which devices to steal in order to impersonate that developer. (The second is mitigated a bit by stripping the comments, but is still conceivably a source of information.)


How is a public key revealing your identity? You can generate as many pair as you want. If you want your identity on github to be masked just generate a key specifically for github


This is all fine and well if you know that github exposes your keys. Which, at least wheb I added my keys, was not mentioned in a big, red button in the key dialog. Maybe I trusted GH too much by not creating a separate key pair for them. But information about me is being leaked without my knowledge, and that's wrong.


Yes, I for one didn't know that GitHub did this. If I had had a pseudonymous account that I trusted GitHub to protect, it would have exposed my identity because I wouldn't have realized it was important to make separate SSH keys.

Edit: Elsewhere commenters say GitHub wouldn't have allowed this for a different policy reason, so this problem couldn't actually come to pass.


Shrug, I didn't know github did this till I read this thread, but I feel neither insecure nor compelled to change anything in response to the news.


It's not called a "public" key for nothing.


I would trust a bank who published their lock diagrams (or at least provided them to me on request) more than one that shrouded their security in secrecy. If I can look at the bank's diagrams I can verify that the lock has no obvious weaknesses, I can show the diagrams to my friends and through analysis we can determine if the lock seems secure enough for my needs. If the workings of the bank's vault are opaque to me the bank could easily be locking my safety deposit box with a twist-tie as a cost cutting measure.


GitHub allowed users to host critical code behind keys that were trivial for bad actors to compromise.

End of story. They should have blocked those keys. They didn't. The majority of the modern open source software movement is centred around a company that couldn't be bothered to lock down the cryptographic keys that protect millions of people from intrusion.

And when I point this out I get downvoted. Completely contrary to the HN guidelines of what deserves a downvote. If people disagree with me that it is gross negligence (which I still 100% view that it is) then they are more than able to voice that, but I'm not some new user shooting their mouth off or saying a dumb inane thing. I'm legitimately concerned about how seriously Github takes software security.


Nice try Sourceforge. ;) You should complain with those core commiters.




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

Search: