RPC authentication based on ec (pubkey) #6604

pull jonasschnelli wants to merge 1 commits into bitcoin:master from jonasschnelli:2015/08/rpc_pubkey_auth changing 3 files +92 −7
  1. jonasschnelli commented at 9:08 AM on August 31, 2015: contributor

    This would add asymmetric pubkey authentication for the RPC server (while still supporting http basic authentication).

    Each RPCJSON HTTP requests will be signed (URI+BODY) with a provided private key (bitcoin-cli -rpcprivatekey or custom implementation with own ec stack). The signature will be verified over a pre-shared pubkey (-rpcpubkey in bitcoin.conf). HTTP Base authentication will be disabled if -rpcpubkey is set.

    One might think that adding better(different) authentication is useless because we don't encourage people to expose the RPC server to the public anyways. I think as long as the RPC server supports authentication, there should be a stronger authentication as then plaintextish http basic auth.

    if this gets conceptual acceptance, i'll add tests and documentation

  2. jonasschnelli force-pushed on Aug 31, 2015
  3. jonasschnelli force-pushed on Aug 31, 2015
  4. laanwj added the label RPC on Aug 31, 2015
  5. laanwj commented at 9:32 AM on August 31, 2015: member

    Nice work.

    However I wonder in which cases does this provide more security than just rpcuser+rpcpassword or using a generated cookie?

    The usual argument for public/private key authentication (in e.g. ssh) is that it allows using a single private key to authenticate to multiple servers, without the servers possessing enough information to authenticate to other servers. But I'm not convinced this is a very likely use-case with bitcoinds.

    What this does not protect against is MiTM: as no Message Authentication Code is used, the authentication token can be passed on while the command could be completely replaced. Edit: Oh! I misread, you thought of this by signing the entire request. I think replay attacks are still possible though.

    Also: not sure how wise it is to get into cryptographic protocol design here. One point with dropping SSL is to clearly put responsibility for any kind of advanced RPC authentication/encryption on the user (hence my recommendation in the release notes to use stunnel, which can handle certificate pubkey based auth).

  6. jonasschnelli commented at 9:43 AM on August 31, 2015: contributor

    @laanwj: Made the same thoughts. I see use-cases in landscapes where bitcoind and the RPC client app do not lay on the same machine and sharing the secrets (even if the network is trusted) is unwanted.

    Right, it does not prevent from MiTM. It could be achieved easily by including a only increasing nonce in the request/signature. But this would break sharing the same user (we only support one) between different client without sharing the current nonce height between client apps.

  7. jonasschnelli commented at 9:53 AM on August 31, 2015: contributor

    But right. I'm also not sure if this would make sense to have in master. I just have the feeling that users will expose the RPC auth to the public (even if they add a reverse proxy).

  8. dcousens commented at 12:23 PM on August 31, 2015: contributor

    Personally, [weak] concept NACK. I'd prefer the master RPC to be kept as simple as possible.

    I see use-cases in landscapes where bitcoind and the RPC client app do not lay on the same machine and sharing the secrets (even if the network is trusted) is unwanted.

    Is that common though?

    ... users will expose the RPC auth to the public ...

    This is my concern too.

  9. jgarzik commented at 1:18 PM on August 31, 2015: contributor

    +1 for better auth. I've always wanted better auth.

    +1 for auth that does not require sending a password over the wire (even if we recommend localhost etc.)

    My idea was to add something standards supported - HTTP-Digest authentication with an already-specified digest, rather than inventing my own.

    That said, this work is obviously better than Basic auth.

  10. laanwj commented at 1:49 PM on August 31, 2015: member

    I agree with @dcousens that we should keep RPC as simple as possible. Also: Adding any advanced authentication features makes it easier for users to expose RPC more widely. If you want to argue for that we should also keep SSL support, as without SSL "digest authentication" adds only very little, e.g. it's vulnerable to MiTM attacks (it's also based on MD5 which is basically broken...).

  11. jgarzik commented at 1:58 PM on August 31, 2015: contributor

    As simple as possible is removing RPC authentication. If the argument is complexity and "you shouldn't do that" then remove all RPC auth and let the connection layer handle it.

    Otherwise merging a better option is obviously an improvement over choosing to keep a poor and insecure auth method.

  12. jonasschnelli commented at 2:14 PM on August 31, 2015: contributor

    Even if one uses stunnel (or a different encryption layer), i think storing a plaintext password in a config file on the remote system (where bitcoind is running) is not a way that i personally would support for a security critical application like bitcoind.

    On modern operating systems with high adjustable permission systems i think a pub key based auth. can make sense.

    Maybe we keep this PR laying around and see how the RPC server evolves and think about it later. Maybe its also useful for someone customizing bitcoind for his personal needs.

  13. laanwj commented at 2:17 PM on August 31, 2015: member

    Insecure in what use case? What is your attack scenario?

    Just saying "more secure" as if you need to check some checkboxes isn't useful, and will just cause people to make false assumptions. If it involves merging some horrible complex beast like HTTP digest authentication, it could in practice make things less secure by exposing bugs in little-tested/reviewed code paths.

  14. laanwj commented at 2:19 PM on August 31, 2015: member

    i think storing a plaintext password in a config file on the remote system (where bitcoind is running) is not a way that i personally would support for a security critical application like bitcoind.

    But the private key is password-equivalent. Stealing it gives exactly the same permissions as stealing the password would. Again: what is the attack scenario you're trying to protect against?

  15. jonasschnelli commented at 2:27 PM on August 31, 2015: contributor

    But the private key is password-equivalent. Stealing it gives exactly the same permissions as stealing the password would. Again: what is the attack scenario you're trying to protect against?

    Right. This is why i don't want to store the private key on the system that is running bitcoind (bitcoin.conf). What i want there is a public key verifying my authorization.

    An attack scenario could be a linux system where an attacker gains read access to bitcoin.conf (it's very likely that some users not using the right permission mode for bitcoin.conf). An attacker than could ban and whitelist serval nodes or do other evil things. This would work from any users without special rights on a multiuser operating system like linux. It more realistic that a VPS operator or different attacker can get read access to bitcoin.conf than compromising your whole system. The first would be even hard to detect.

  16. laanwj commented at 2:34 PM on August 31, 2015: member

    Sure - public key authentication would prevent an attacker breaching the bitcoind node from getting the password (private key) from bitcoin.conf. But if the attacker already has access to the system running bitcoind, it's only one step toward stealing the wallet.dat, or manipulating/observing bitcoind directly in memory, bypassing RPC auth.

    Edit: I do like the "server has different credentials than the client" idea though. Could be powerful, especially with multiple clients w/ different pubkeys. This is better than digest auth. I think this is better posed as a flexibility improvement: if you have N servers and M clients you just need to add those M pubkeys to every server. And one can remove clients without having to change the codes on every other client. This would require M*N shared secrets otherwise.

  17. dcousens commented at 4:54 PM on August 31, 2015: contributor

    Right. This is why i don't want to store the private key on the system that is running bitcoind (bitcoin.conf). What i want there is a public key verifying my authorization.

    At which point, if an attacker compromises the bitcoind system, the threat model means he won't be able to get the clients private key. But, meh? Assuming the client private key is only used for this bitcoind instance, what point is there in that? It is no different to breaching the rpcpassword directly?

    Plus, a whole new technology stack might be required for the client.

  18. jgarzik commented at 5:16 PM on August 31, 2015: contributor

    I think "new technology stack" is a bit over-stated. Should be well within the reach of existing codebases while not breaking the rest.

  19. gmaxwell commented at 8:28 AM on September 6, 2015: contributor

    I think using something custom here breaks most of the advantage of using http+json rpc in the first place. I think it's unlikely many callers would implement support for the custom thing. If we had a whole custom RPC protocol it would be a different answer (and in that case I'd argue that it should be using a SPAKE protocol of some kind-- as those can get us mutual authentication to boot).

    Supporting plain digest auth, lame as it is, would likely deliver more aggregate value. (plus doesn't give us a totally novel protocol that needs cryptanalysis.)

  20. jonasschnelli commented at 11:15 AM on September 6, 2015: contributor

    This PRs authentication methode is not new and has been widely deployed over Bitpay/Copay (https://github.com/bitpay/bitauth). But right. It's a new implementation and it would require some crypoanalysis.

    If I'm right, using auth digest would mean we would encourage people to use a auth scheme that is based on broken md5.

    I would recommend to drop auth fully or try to achieve a modern form of authentication that is not based on plain text password transmission or md5 hashing.

  21. jgarzik commented at 3:12 PM on September 6, 2015: contributor

    Here is an analysis of MD5 and Digest auth. https://en.wikipedia.org/wiki/Digest_access_authentication#Impact_of_MD5_security_on_digest_authentication

    Though it's not HMAC, Digest auth includes multiple MD5 rounds and even allows the possibility for some implementations to store the first hash, rather than the cleartext password. That does appear to be applicable to us -- perhaps a tiny 20-line CLI util could generate a password hash for placing into bitcoin.conf.

    In general I agree w/ @gmaxwell I do note that this would likely require importing MD5 down the road as OpenSSL use is eliminated. Moving the server over to libevent and removing SSL was another big step in that direction, incidentally...

  22. RPC: ecdsa pubkey auth 4116cb385e
  23. jonasschnelli force-pushed on Sep 6, 2015
  24. gmaxwell commented at 9:43 PM on September 6, 2015: contributor

    @jonasschnelli There is nothing currently known to be broken about MD5 in this application. For the digest authentication to be broken, assuming strong credentials, it would require an efficient second pre-image attack against MD5 and none is known to exist (nor, AFAIK, theorized to be likely to be found anytime soon). The existing attacks against MD5 are structured collision attacks. The only complaint anyone should make about digest auth is that it has no resistance at all to a MITM, and as such it's awful limited in what it protects against.

    If the credentials are weak (e.g. user picked passwords) then both http digest auth and the bitauth scheme are both insecure as they are not zero-knowledge (an observer can attempt to brute force the secret offline), and neither have an effective KDF (to make the brute forcing of a weak key somewhat more computationally infeasible). (As far as including MD5 for this, well thats trivial at least).

    There is a proposal for digest auth improvements, which will likely be widely deployed: https://tools.ietf.org/id/draft-ietf-httpauth-digest-19.txt which might be of interest.

  25. gmaxwell commented at 9:47 PM on September 6, 2015: contributor

    Separately, I've analyzed this proposal somewhat and now feel comfortable NAKing this particular construction and implementation: It's appears trivially vulnerable to replay, e.g. you send send me 1 BTC and I observe your sendtoaddress RPC call, then I connect and continually replay it until you are out of coins.

    [And I find it a little hard to imagine a practical example where plain auth with a random cookie would be insecure but that kind of replay would be tolerable. ... maybe a situation where the exposed connections only performs information gathering RPCs that you wouldn't mind just anyone performing?]

    Interestingly, the bitauth page claims to include a nonce to prevent replay-- but I see no evidence of that in your implementation. (Then again, it also makes claims like "The cryptography in Bitcoin is rock solid and is securing billions of dollars worth of bitcoins.", as seemingly its main security claim, which is a serious red-flag.)

    The bitauth readme claims "The server verifies that the signature is valid and that it matches the identity (the public key). It then computes the SIN from the public key, and sees whether that SIN has access to the requested resource. The nonce is checked to make sure it is higher than the previously used nonce." ---- that is a stateful protocol, and making it secure requires that there be no more than one server (and that the server refrain from certain scaling and HA approaches without using a consensus protocol); likewise multiple clients with the same key would lock each other out. I also can't find any evidence of the bitauth code actually implementing that either... e.g. the example client and server seem to have no infrastructure to persist a counter; though I know nothing about reviewing JS code and perhaps that is magicked away someplace.

    While even with that vulnerability it's true that an improvement over plain-text, but I think it doesn't make sense to adopt a narrow, not widely compatible protocol with such simple violations of expected security-- especially on top of the poor performance of it. And it certainly wouldn't be enough for us to stop recommending people use the https as: It's not an improvement over that..

    I'm concerned that this protocol may have a turn-the-client-into-a-TX-signing-oracle attack in some contexts; the specific construction makes it somewhat hard to be sure that no such attack exists. E.g. I get a client to make a request which happens to be identical to a masked bitcoin transaction that I want the client to sign, spending coins associated with the clients pubkey (as users eagerly reuse these keys even if we ask them not to). The only resistance I see to this attack is just the challenge in comping up with a plausible string that is both a json request that a client could be talked into producing and a transaction. For our own client this might be impossible, but it's hard to reason about all possible functioning client software. There might be a trivial reason this doesn't apply however.

    I do support being stronger here but we are hamstrung somewhat by compatibility requirements inherent in an RPC interface; and we should not go half way and deliver something that might look secure under all reasonable attack models but actually be weak under many of them.

  26. jonasschnelli commented at 3:54 AM on September 7, 2015: contributor

    Right. I has no replay attack prevention (like a upcounting nonce within the signature). That would be required for production.

    Fair enough. I see the points and they make also sense for me. Will see how complicated auth digest would be to implementation.

  27. jonasschnelli closed this on Sep 7, 2015

  28. MarcoFalke locked this on Sep 8, 2021

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-13 15:15 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me