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.
Since Nmap is far more efficient at scanning large scale networks than ipmiping this method is only used if Nmap says that a hosts has UDP 623 open.
For better or worse this port is often blocked, so much of the time other methods are more likely to find out obliquely whether or not IPMI is running.
Ports are weighted by their indicative ability and whether or not Nmap finds them open, filtered, or in other states.
Nmap also can show the banners of services connected to. I use regular expressions to hunt for targets - for instance the strings "iLO" and "DRAC" are good indicators that a system might be running HP's Integrated Lights Out service, or iLO.
Note: Currently I do NOT use the broadcast ping method (a very quick way to zip through the subnet you're residing in); I simply don't have any data on the effectiveness on this; while very fast when it works I didn't feel like it allowed for the control and reliability of arbitrary scans. Two out of three of my systems (Dell and HP) responded to an RMCP ping. None responded to a broadcast ping by idiscover (ipmiutil discover.) All did, however, respond to my Python audit tool below.
Unfortunately (of course!) the spectre of communications and networks comes into play - nmap gives a bunch of different reasons as to why a port is open or not (open, closed, filtered, etc.) Yet another table has a set of weights that gives more points to an open port than to a "open|filtered" (as Nmap might say) hit. Interpreting nmap and weighting is a bit on the frustrating side, but c'est la vie.
Take all the weights, add up all the points and you have an IPMI certainty level. I've found in ad hoc testing that 15 points or more are strong indicators that the system is running IPMI.
Currently I have various thresholds (no, possibly, probably, yes.) In tests - without having known access to any other servers than my own - it seems to work reasonably well. That is, the things that I think are suspicious and my basic thought model above does indeed bubble certain servers to the top and leaves random hosts alone. There are some real problems with false positives, tho - many firewalls seem to imply to nmap that there's something on any port (I've thought of tossing in a rare port or two (if you listen to something like port 1 & 31313, for instance, you're probably not *really* listening to it!)
But this isn't meant to be the last word on the topic. It should be fairly simple to get some decent data on IPMI banners, my guess is that it'd be by far the best way to rapidly scan large amounts of systems.
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.
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.# 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
./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.)
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".
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.
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|
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.# 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