Some tools and thoughts.

I wrote some software to explore IPMI; here are some of results. I thought I'd do the usual detect, get data, and audit sort of cycle. Each of these turned out to be fairly interesting problem on its own.

Password Cracking

Here's a little Perl program that tries to guess an account on a remote BMC, extract its hash, and then try to crack its (HMAC hashed) password. I wrote up a little bit on this for the curious. Heavily commented, it may provide some utility.

Detection

Well, if you can talk to UDP port 623, it's pretty simple to find out if a remote system is running IPMI. Unless you're inside a data center, however, most folks block UDP. And even if they don't... UDP scanning is about as slow as can be imagined. So I'm currently using two basic methods, leveraging the venerable Nmap and ipmiping (from the FreeIPMI Gnu tools.) The easiest thing to do is:

Here are four pieces of Perl to implement the above; one scans, one interprets, and the other two are used for weighting. It's a research tool or a proof of concept, not a production scanner, but it does produce some reasonable output.

REQUIRED: Nmap version 6.

ipmi_scan.pl - basic IPMI scanner, uses Nmap and, if available, ipmitool
ipmi_scan man page - man page for above
post_ipmi_scan.pl - parses the output of above, spits out some weighted results
j_vendor.pl - Some basic vendor data... which use which ports?
j_weights.pl - Some basic vendor weights for above

iscan.tar.gz - Gzip'd tar of the above 4 Usage is pretty simple, if a bit quirky. Should be run as root. Verbose (-v) for lots of output.

   # standard run:
      ./ipmi_scan.pl -A -v -O yes  192.168.0.0/24
   # fast
      ./ipmi_scan.pl -tcp -v 192.168.0.0/24
   # kitchen sink
      ./ipmi_scan.pl -A -v -O high 192.168.0.0/24
   
The scan will create a pair of result files that correspond to the target names (slashes are converted to underscores.) Simply run the post-processor on them; tossing through reverse numeric sort puts them in a more interesting order. Anything over 10 I'd call suspicious, where > 20 is pretty certain to be running IPMI. In this case I used the terse flag (-t) to cut the output to the bare minimum.
   ./post_ipmi_scan.pl -t 192.168.0.0_24|sort -rn
   96.3 192.168.0.69
   16.25 192.168.0.46
   10.8 192.168.0.23
   7.33 192.168.0.202
   5.4 192.168.0.189
   5.4 192.168.0.179
   1.7 192.168.0.9
   1.23 192.168.0.1
   1.1 192.168.0.8
   0.9 192.168.0.251
   0.63 192.168.0.55
   0.43 silent/192.168.0.250
   0.2 pi.fish2.com/192.168.0.14
   0.2 fierce.fish2.com/192.168.0.6
   0.2 192.168.0.88
   0.01 192.168.0.16
   

In the above results the top 3 systems are actually running IPMI, but only the HP told Nmap that UDP port 623 was open - my Dell and Supermicro returned the more ambiguous "open|filtered" response, which is quite commonly a false alarm, bleah. Perhaps it's better just to suck it up and do the IPMI ping in parallel with the scanner (or write an NSE to do it correctly in Nmap.)

Audit

Two programs here, one is a simple Python remote prober (starting to hate Perl, let me tell you) and a second that uses utilities from FreeIPMI to grab credentialed configuration data.

A small python program (>50% inline comments, 2.5k gzip'd) that sends a single packet to a BMC and mulls over the response. What can you do with only a single packet, one might ask? 10+ different security tests for IPMI, for starters. Well, for starters and for enders, it's only a packet :) Requires python, a BMC and an open path to UDP port 623 to work. Usage is simply "ipmi-get-auth.py target".

ipmi-get-auth.py / A very small description

Here's a couple of small python programs that - using FreeIPMI tools - (a) sucks in the basic IPMI/BMC configuration of a server and (b) does a lil' security check on the results.

ITAR (a small IPMI/BMC audit program) /

Because I... well, no good reason, actually. One is in python3 and the other in python2. I guess I'm testing your readiness. The programs are pretty heavily commented, especially ipmifreely.py, so check that for more details on what's going on. Requires simplejson and ConfigParser, maybe some more.

YOU MUST have FreeIPMI installed, which, as of this writing, kills off Mac and Windows chances at sucking down a cool JSON file from a server. And you really, really should have a recent version. Don't say I didn't warn you. But life goes on.

The data aquisition is done via a python program (I-check.py) that requires valid credentials to get data. It converts the results to JSON, which in turn may be checked by the audit tool (ipmifreely.py.) There is a sample policy in "IPMI-policy.ini", where I put some values for testing.

I-check.py - grabs IPMI configuration data
ipmifreely.py - parses the output of above, spits out some results
IPMI-policy.ini - IPMI policy file

Sample use:

   # this grabs the configuration stuff; here I'm using it on an HP iLO 3 server
   # the output is redirected to a file
   $ ./ipmifreely.py -v -u admin -p admin 192.168.0.46 > hp.json
   # This takes the JSON file and looks for issues
   $ ./I-check.py drac.json
   ./I-check.py hp.json 
   Host:    192.168.0.46
   [bmc-config]   Serial_Channel Non_Volatile_Enable_Pef_Alerting = No
   [bmc-config]   Serial_Channel Volatile_Enable_Pef_Alerting  = No
   [bmc-config]   Serial_Channel Volatile_Enable_Per_Message_Auth = No
   [bmc-config]   Serial_Channel Non_Volatile_Enable_Per_Message_Auth   = No
   [bmc-config]   Lan_Conf_Security_Keys  K_G   = 0x0000000000000000000000000000000000000000
   [bmc-config]   SOL_Conf Force_SOL_Payload_Authentication = No
   [bmc-config]   SOL_Conf Force_SOL_Payload_Encryption  = No
   [bmc-config]   Lan_Conf_Auth  Callback_Enable_Auth_Type_None   = Yes
   [bmc-config]   Lan_Conf_Auth  Operator_Enable_Auth_Type_None   = Yes
   [bmc-config]   Lan_Conf_Auth  OEM_Enable_Auth_Type_None  = Yes
   [bmc-config]   Lan_Conf_Auth  Admin_Enable_Auth_Type_None   = Yes
   [bmc-config]   Lan_Conf_Auth  User_Enable_Auth_Type_None = Yes
   [bmc-config]   Rmcpplus_Conf_Privilege Maximum_Privilege_Cipher_Suite_Id_1 = OEM_Proprietary
   [bmc-config]   Rmcpplus_Conf_Privilege Maximum_Privilege_Cipher_Suite_Id_0 = OEM_Proprietary
   [bmc-config]   Rmcpplus_Conf_Privilege Maximum_Privilege_Cipher_Suite_Id_2 = OEM_Proprietary
   [pef-config]   Community_String  Community_String  = public
   [pef-config]   PEF_Conf Enable_PEF_Event_Messages  = No
   
You might check out some IPMI Security Best Practices for more on what to check what I consider to be good things to do, security-wise.