RPC: Avoid cleartext passwords by default #1986

Closed
wants to merge 2 commits into
from

Projects

None yet

6 participants

@jgarzik
Member
jgarzik commented Nov 5, 2012

Although in theory RPC API access should be locked down, there are
occasions where cleartext passwords have been used anyway.

HTTP Basic authentication remains, but a new default "Bitcoin" HTTP
Authorization header is used. HTTP Digest authentication was considered
initially, but that may require additional HTTP round-trips. The standard
HMAC-SHA256 algorithm pair was chosen instead, with some additional stirring
factors (random nonce, time).

The HTTP server will accept Basic or Bitcoin authentication now.

The HTTP client will attempt Bitcoin authentication, and fall back to
Basic if that fails.

@laanwj
Member
laanwj commented Nov 5, 2012

I agree this is useful, even with encrypted transport over SSL it's a safe precaution to not use cleartext passwords.

It's a pity though that we need to invent our own authentication scheme for this, but it looks like you evaluated the other options already.

One question: taking a quick look at the code I don't see any challenge response code in there. How well does this withstand replay attacks? Does it check the embedded date/time?

@gavinandresen gavinandresen commented on the diff Nov 5, 2012
src/bitcoinrpc.cpp
+static bool HTTPAuthBitcoin(string& strAuth, string& strRequest)
+{
+ // Format: Bitcoin SP $Username SP $Timestamp SP $Nonce SP $HMAC_hash (hex)
+
+ vector<string> vWords;
+ boost::split(vWords, strAuth, boost::is_any_of(" "));
+ if (vWords.size() != 5)
+ return false;
+
+ // parse args
+ if (vWords[0] != "Bitcoin")
+ return false;
+ string strUser = vWords[1];
+ if (strUser != mapArgs["-rpcuser"])
+ return false;
+ string strDate = vWords[2];
@gavinandresen
gavinandresen Nov 5, 2012 Bitcoin member

What is the format of strDate? And shouldn't there be a check here to make sure strDate is reasonably close to the current time, to prevent replay attacks?

@jgarzik
jgarzik Nov 5, 2012 Bitcoin member
  1. Format: Unix time (number of seconds since epoch)

  2. Yes, there should be a check. See main pull req discussion, querying the best time window.

@jgarzik
Member
jgarzik commented Nov 5, 2012

Your basic impression is sound. HTTP Digest was the preferred solution, but that introduces an additional round-trip to obtain a server nonce value, mitigating replay attacks.

Lacking that round trip to gain additional protection, the best one can do is make sure the embedded time is within a certain window. Currently there are no time checks, because I wanted to get some feedback as to best time window.

The server could demand that the HTTP request time be +/- five (5) minutes of its own system clock... or one hour? Which one takes into account broken clients etc. the best? What is a good time window?

The smaller the window, the more secure.

@jgarzik
Member
jgarzik commented Nov 5, 2012

Just added a commit to clamp the timestamp to +/- 60 seconds.

However, it is still open for discussion, because this is a usability issue: users with a drifting clock will get an unfriendly, vague "not authorized" error message. The window should be as small as possible... while still being wide enough to avoid most users hitting this issue.

(of course, I think all users should be running or sync'ing with NTP, but that's an unrealistic opinion.....)

@gmaxwell
Member
gmaxwell commented Nov 5, 2012

So why not use digest auth instead of something custom (and fragile) and solve the latency concerns by persisting the connection where you're concerned with that. The session bring up tear down has more of those nasty round trips in any case.

@jgarzik
Member
jgarzik commented Nov 5, 2012

"custom and fragile" is oversold, considering this is intentionally highly similar to Amazon S3's HMAC authentication scheme. S3 must even deal with the same issue: picking a time window encompassing average client clock drift, without shutting out too many. I think they chose 5 minutes.

@gavinandresen
Member

RE: times: default should be 'as secure as possible.' Users should sync their clocks (but an if (fDebug) printf("rpc timestamp out of sync...") would be nice to make it easier to debug but not open up non -debug usage to flood-of-bad-authorization DoS attack).

RE: custom and fragile:

This seems less fragile than the old, maybe-soon-to-be-broken, MD5-based HTTP digest authorization. Jeff: any reason this is highly similar to Amazon's scheme and not exactly the same?

@gmaxwell
Member
gmaxwell commented Nov 5, 2012

I'm just concerned that we're solving things that weren't obvious a problem with novel cryptographic authentication protocols. Even with authentication it is still unacceptable to run RPC across an insecure network because an active attacker can just intercept and replace RPC calls (not to mention sniffing the content)... and without connection persistence anything latency sensitive will still suffer. And this will insert really confusing failure modes. I don't normally expect my client's clock to have to be in the right timezone.

@gavinandresen
Member

The DKIM RFC 6376 : http://www.ietf.org/rfc/rfc6376.txt ... also seems very similar. It uses an explicit expiration time, which seems like the right thing to do.

It is overly complicated for this (e.g. we don't need multiple signature algorithms, don't need to specify which headers are part of the signature hash, etc), but I always like adopting or adapting an existing standard that experts have blessed instead of inventing our own.

@luke-jr
Member
luke-jr commented Nov 13, 2012

Needs rebase

Jeff Garzik added some commits Nov 5, 2012
Jeff Garzik RPC: Avoid cleartext passwords by default
Although in theory RPC API access should be locked down, there are
occasions where cleartext passwords have been used anyway.

HTTP Basic authentication remains, but a new default "Bitcoin" HTTP
Authorization header is used.  HTTP Digest authentication was considered
initially, but that may require additional HTTP round-trips.  The standard
HMAC-SHA256 algorithm pair was chosen instead, with some additional stirring
factors (random nonce, time).

The HTTP server will accept Basic or Bitcoin authentication now.

The HTTP client will attempt Bitcoin authentication, and fall back to
Basic if that fails.
a4305bf
Jeff Garzik RPC: clamp HTTP auth timestamp to +/- 60 seconds 010cc65
@jgarzik
Member
jgarzik commented Nov 16, 2012

Rebased. Still need to address valid @gavinandresen etc. comments.

@BitcoinPullTester

Automatic sanity-testing: PASSED, see http://jenkins.bluematt.me/pull-tester/010cc65142f83b1045bc21b64cfe7cb46b8eff78 for binaries and test log.

@jgarzik
Member
jgarzik commented May 30, 2013

Closing. Will reopen with closer integration with Amazon S3 spec, as per comments.

@jgarzik jgarzik closed this May 30, 2013
@luke-jr
Member
luke-jr commented Aug 19, 2013

Found a bug. The initial request sends "Connection: close" header, but then if the server requests Basic auth instead, it sends the retry over the same socket (which is now closed).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment