File under... et tu, IPMI 2.0 specification?
Leaky hashes in the RAKP Protocol
The short version: the RAKP protocol in the IPMI specification allows anyone to use IPMI commands to grab a HMAC IPMI password hash that can be cracked offline. Longer explanation follows. Here's a little Perl program that implements it.
I guess you can file this in the ... "well, I don't think there are enough problems with IPMI with this new spec... what else can we do to sabatoge its security?"
Prior to IPMI 2.0 the IPMI specs would encapsulate IP packets using the Remote Management Control Protocol (RMCP.) For 2.0 I can only surmise that they wanted to continue avoid sending the password over the network (at least, most, or some of the time, depending on options), so they introduce RMCP+, which offers "enhanced authentication" and extends IPMI over IP.
Thus RAKP - the RMCP+ Authenticated Key-Exchange Protocol - was born. According to the specification (page 161):
RAKP-HMAC-SHA1 uses pre-shared symmetric keys and HMAC-based integrity algorithms to mutually authenticate a remote console to a given managed system and to generate pair-wise unique symmetric keying material that can be used with a number of integrity and confidentiality algorithms to provide protection for RMCP messages.
That sounds pretty good - so how does this work? As an illustration as to its underpinnings, an easy way to trigger RAKP is to use ipmitool like below (the "chassis identify" in the example simply asks the BMC to say what it's identify interval is) - you might note that the password given ("fluffy-wuffy") is invalid, but it doesn't matter, as we're just starting up RAKP, we're not interested in finishing it, and ipmitool requires some password, even if it's wrong:
This command kicks off a back-n-forth sequence with a remote BMC; for instance, on my iMac, it looks like this:
sequence # | Client sends | BMC responds with |
---|---|---|
1 | get channel auth request | |
2 | get channel auth response | |
3 | RMCP+ open session request | |
4 | open session response | |
5 | RAKP message 1 | |
6 | RAKP message 2 |
I show only two of the four RAKP steps to a successful negotation; this is because all we need is the RAKP message 2 contents. RAKP was designed thinking that the BMC and the client share a secret - the password - and that the client can validate the HMAC and see if it's the right server they're talking to. For better or worse it also gives an attacker all they need to crack the password. And in message 2 the BMC sends our target HMAC.
Looking at the output of ipmitool you'll eventually see a few lines that look something like this:
[...] rakp2 mac input buffer (63 bytes) a4 a3 a2 a0 4c 7f fb df ee a4 a3 96 b1 d0 7e 27 cd ef 32 ae 66 cf 87 b9 aa 3e 97 ed 5d 39 77 4b bc 8a c5 a9 e2 da 1d d9 35 30 30 31 4d 53 00 00 00 00 00 00 00 00 00 00 14 05 41 44 4d 49 4e [...]The input buffer is most of what is used to calculate the HMAC. In order, these bytes are the session IDs of the remote console (4) and managed system (4), the remote console's random number (16), the managed system's random number (16), the managed system's GUID (16), the priv level (1), the length of the user name (1), and finally the user name itself.
The HMAC is created with that buffer and the password - or password guess - which may be compared with the key exchange auth code that the BMC has also sent you in your exchange:
[...] Key exchange auth code [sha1] : 0xede8ec3caeb235dbad1210ef985b1b19cdb40496 [...]At this point you're left with a very easy way to crack a password. Simply take the input buffer above along with a password guess, create a HMAC - defined in RFC 2104 and is implemented as a library in most popular scripting languages - and compare it to what the BMC sent. If they match, you've guessed right.
To be fair to engage in RAKP-ness you do need a valid IPMI account name on the remote system, but requests via RAKP 2 are also kind enough to tell you if an account is valid or not (and, remember, vendors always have default accounts, and frequently they're not removable.)
I did a quick, unscientific scan of a bit over 1000 hosts that would talk to me on the Internet, and a bit over 5% of them had vendor default passwords enabled. Another 5-10% of accounts were easily crackable with a modest sized dictionary. None of that is very surprising, of course, but being able to grab password hashes from a system is unforgivable. I might do some further looking around; presumably others might as well.
On the plus side, no one else can disable this feature either, as it's part of the IPMI specification, so the playing field is level.
Even more so now... keep those BMCs behind firewalls, and block frickin' UDP port 623!
Postcript. FYI, it turns out that a little delay between requests can help with some systems that have a hamster-driven BMC. I put a delay option (-D) in my little perl program - a delay of 3 ("-D 3") seems to work well.
Special thanks to out to Jarrod B Johnson (