ipmi, risk, security, tech

Remotely Access Live Supermicro Firmware+

TLDR; a vendor supported/supplied utility allows download of live BMC1 firmware/configuration on (at least) some SuperMicro BMCs. It’s hard to tell who might be affected, but the utility used was written by ATEN Technology, ASRock ASPEED, and others all seem to be connected in various ways in not only SuperMicro firmware but the rest of the BMC world, and it’s not clear to me what other vendors might have this feature (sic) as well (QEMU lists many vendors using Aspeed BMCs that potentially could have something similar.)

I’ve only tested this on a couple of systems – a Supermicro X11SSZ-QF and a Supermicro X10-based virtual BMC (this firmware was run under QEMU (release notes claim to support their X10DRU-I+, X10DRT-P, X10DRG-H, X10DRW-I, X10DRI-T4+, X10DDW-I, X10DRFR, X10DRI-T, X10DRFF, X10DRFR-T, X10DRD, X10DRD-L motherboards.) That said, I’d say evidence strongly suggests this extends to other versions, as nearly identical strings2 are hardcoded in /lib/libipmi.so that show the dd command dumping firmware to the same location. This is at least true for Supermicro servers in their X10, X11, X12, and X13 families; it’s been around for some time and presumably still is. Feel free to send me intel on test results of other systems, and update as appropriate.

The downloaded firmware includes the base OS, web pages/programs, BMC configuration, most files, and the kernel. Yes, you can change the firmware remotely by any number of methods, but here an attacker can see exactly what is going on on the BMC. Compromising the BMC becomes much easier if you can observe what the exact system is doing. Consider: would you want a potential attacker to be able to see your server/app configurations, password files, SSH keys, etcetera? It’s a dangerous thing, even if it’s not a bug but a feature. But hey, they didn’t ask me.

I think it’s especially interesting because it’s not simply being able to get the firmware of a BMC server, but it does so via valid IPMI by leveraging the OEM commands (the specification details how vendors can extend the protocol to allow vendor-specific commands/functionality3.) In the past I’ve heard rumors of various features from BMC vendors, such as capturing and freezing RAM, generating SMIs, etc., but these are all hidden from public view… how much do you trust your server vendor?) Ironically I’d actually seen this utility many years ago, but could never get it to work, apparently because I didn’t have the right hardware.

Details


ATEN Technology has a freely downloadable tool – AlUpdate4 that can do a variety of operations to a local or remote BMCs; here’s what I used in tests –

$ ./AlUpdate -h 192.168.0.24 -u ADMIN -p ADMIN -i lan -r y -d over-lan.img

Under the hood (each item representing packet(s) sent/received) it has 4 stages –

  1. authenticate to BMC and set communication parameters
  2. get ready to send
  3. send a I’m-ready-when-you-are-command
  4. let me have it!

The first step is the setup request via a RMCP+ Open Session request via UDP on port 623, the standard IPMI port. I only mentioned it because while it could request any of a number encryption and data integrity algorithms, they instead shut off data integrity and confidentiality by using the 0x00 algorithms for both, meaning that all of this all sent in the clear with no protection.

Authentication Algorithm RAKP-HMAC-SHA1
Integrity Algorithm(s) None
Confidentiality Algorithm(s) None

After the connection is established, the AlUpdate tool sends three OEM IPMI commands in sequence –

  • 0x1d
  • 0x1e
  • 0x1f

The first command packet is sent and receives a command was successful response.

direction NetFN IPMI command response code
to BMC 0x3e 0x1d n/a
from BMC 0x3e 0x1d 0x00

The basic structure of each command is the same – here’s the full UDP payload of the first packet –

    06001200000000000000070020f8e881001d62

Or in tshark format –

    
        Version: 0x06
        Reserved: 0x00
        Sequence: 0xff
        Type: Normal RMCP, Class: IPMI
            ...0 0111 = Class: IPMI (0x07)
            0... .... = Message Type: Normal RMCP (0x0)
    IPMI v2.0+ Session Wrapper, session ID 0x360
        Authentication Type: RMCP+ (0x06)
        Payload type: IPMI Message (0x00), not encrypted, not authenticated
            0... .... = Encryption: Payload is unencrypted
            .0.. .... = Authenticated: Payload is unauthenticated
            ..00 0000 = Payload Type: IPMI Message (0x00)
        Session ID: 0x00000360
        Session Sequence Number: 0x00000000
        Message Length: 7
    Intelligent Platform Management Bus
        Target Address: 0x20
        Target LUN: 0x00, NetFN: OEM Request (0x3e)
            NetFn: OEM Request (0x3e)
            .... ..00 = Target LUN: 0x0
        Header Checksum: 0xe8 (correct)
        Source Address: 0x81
        Source LUN: 0x00, SeqNo: 0x00
            .... ..00 = Source LUN: 0x0
            0000 00.. = Sequence Number: 0x00
        Command: Unknown command (0x1d)
        Data checksum: 0x62 (correct)

Behind the scenes the BMC starts packing up the firmware on the BMC – if you’re on the BMC (perhaps more on that on a follow-up), running the ps command shows –

PID USER VSZ STAT COMMAND
[...]
1312 root 2784 S sh -c /bin/restore_file.sh 0
1313 root 2784 S {restore_file.sh} /bin/sh /bin/restore_file.sh 0
1345 root 3112 S tar -zcvf /tmp/save_config.tar.gz ./preserve_config
1346 root 2920 R gzip -f
[...]

What is it doing? MTD is the Memory Technology Device subsystem and is used for storage backed by flash memory of various sorts (like NAND, NOR, etc); this shows the BMC extracting the firmware from its flash storage via dd to get ready to send.

The “/proc/mtd” psuedo file shows some details on the various MTD devices, including mtd5:

$ cat /proc/mtd
dev: size erasesize name
mtd0: 00100000 00010000 "bootloader"
mtd1: 00300000 00010000 "nvram"
mtd2: 01000000 00010000 "rootFS"
mtd3: 00300000 00010000 "kernel"
mtd4: 00840000 00010000 "webpage"
mtd5: 01fc0000 00010000 "all_part"
mtd6: 00010000 00010000 "uboot_env"

That “all_part” means basically the entire system – from it you can extract (via binwalk or whatever methods you’d like) the base OS, plus the web components, kernel, configuration details, etc. When the BMC boots up it mounts the root file system and then /nv and /web… here’s the kernel command line and the mount commands –

    console=ttyS1,115200 root=/dev/mtdblock2 rootfstype=cramfs noinitrd rw mem=79M
    mount -t jffs2 /dev/mtdblock1 /nv
    mount -t cramfs /dev/mtdblock4 /web

Every time a “0x1d” IPMI command is sent the “dd” is triggered again… (not in parallel, it kills off any previous)… and the lil’ BMC really struggles during that time. (Makes me wonder if repeated hammering of the disk might cause problems….)

The BMC itself runs Linux version 2.6.28.9 on a CPU: ARM926EJ-S

$ uname -a
Linux (none) 2.6.28.9 #1 Mon Aug 10 14:12:03 CST 2015 armv5tejl GNU/Linux
$ cat /proc/cpuinfo
Processor : ARM926EJ-S rev 5 (v5l)
BogoMIPS : 191.69
Features : swp half thumb fastmult edsp java
CPU implementer : 0x41
CPU architecture: 5TEJ
CPU variant : 0x0
CPU part : 0x926
CPU revision : 5

Hardware : ASPEED-AST2300
Revision : 0000
Serial : 0000000000000000

The “dd if=/dev/mtdblock5 of=/tmp/dump_flash” bit is hardcoded in /lib/libipmi.so, and is executed via the /bin/ipmi_lan persistent daemon, which listens to UDP port 623 (IPMI’s default listening port.)

Next, AlUpdate waits about 50 seconds to send the second packet (command 0x1e.) Until the firmware is completely saved to disk the BMC will respond with a successful command completion code plus a 0x00 data field. The tool continues to query every 4-5 seconds until the BMC sends a 0x01 in the data field followed by 0x200000 (0x0200000) – the latter corresponding exactly to the size of the BMC firmware (33,554,432 in base 10.)

The request packet –

    0600760a000001000000070020f8e881001e61

And the final response packet –

    06002923be84070000000f0081fc8320001e0001020000000000bf

After seeing that response 0x1f IPMI commands are sent and repeated until the entire flash is sent over. This takes about XXX minutes in total. The request packets are the same old thing –

    0600760a000007000000070020f8e881001f60

While the response packets cram in 57 bytes per UDP packet (55 data bytes after the command and the checksum is taken into account.)

    06002923be840d000000410081fc8320001f0000ae17ee57504ba6a3a879a8dbb1b1d9c68a6252d1cb26de9049037a501fe781f78073c010e0c6fc32208e7abb00e8c03cb0e975f4bb0061dc

The whole exchange takes about 800,000 packets back and forth. After a successful transfer or if nothing happens for about 10m after the initial mtd dump, the image file will be removed from /tmp on the BMC.

Download BMC conf separately?

Oddly, using the -c flag to get just the configuration (e.g. ./AlUpdate -c -d backup.bin -i kcs -r y as per the usage output didn’t work. Checking the packet flow and what’s going on the BMC it seems to start fine, but then something goes awry… perhaps someone else can let me know how it should work.

Quick Test

You don’t strictly need the AlUpdate tool to test this… if you send a single authenticated packet via your IPMI tool o’ choice, such as –

    ipmi-raw --driver-type=LAN_2_0 -h 10.0.0.1 -u ADMIN -p ADMIN 0 3e 1d

or

    ipmitool -U ADMIN -P ADMIN -H 10.0.0.1 raw 0x3e 0x1d

On susceptible systems it’ll start the dump to /tmp/ on the BMC, and presumably throw an error (but who knows on various systems; other OEMs might use it for different purposes, since it’s up to them to define) if it doesn’t recognize the command.

Denouement


In the grand IPMI scheme of things, just another issue, I suppose; it’s already dangerous enough with all the other problems! Still, that someone could vacuum out such information from you BMCs seems at least casually alarming. Certainly if an adversary was able to do this it’s probably game over.

Others might claim that if they had your credentials or admin access to your BMC it’s pretty much over anyway, since you can upload new firmware or change the configuration anyway.

There is a substantial difference, however, between blindly overwriting existing data and being able to view and change existing data. And since the basic configuration and password of your BMCs is shared through multiple vendors, it means that even if your other BMCs aren’t Supermicro, such disclosure puts them at additional risk as well.

And if an adversary was able to install a backdoor into existing firmware (as I did to gain shell access to my own BMC to determine what was going on behind the scenes) by examining the configuration details of your BMC, that’s substantially more difficult to detect than someone actually changing the BMC carte blanche. Even if you don’t detect backdoors or changes to BMC configuration (which can be quite tricky), one might well notice a change in firmware version.

YMMV.

Be well and be safe.

Footnotes


  1. The BMC is an embedded computer that has lived on the motherboard of Intel-based servers for the last 25+ years. It is responsible for out-of-band monitoring and management of servers via Intel’s IPMI protocol and goes under such rebranded names as iLO, iDRAC, etc. I’ve written a fair bit about such things, and there’s lots of additional information available online.
  2. E.g. – in BMC_X13AST2600-ROT20-D301MS_20231005_01.01.20_STDsp.zip you can see (unpacked with binwalk or other tools) –
    dd if=/dev/mtdblock4 of=/tmp/dump_flash^@/tmp/dump_flash^@SlaveTask:at_b_DumpFlashComplete = 0x%x
    

    In BMC_X12AST2500-3201MS_20231006_01.03.03_STDsp.zip
    it shows –

        dd if=/dev/mtdblock5 of=/tmp/dump_flash^@SlaveTask:at_b_DumpFlashComplete = 0x%x

  3. The IPMI spec has two different ways to specify OEM commands (FYI, OpenBMC has a nice writeup on all this.) The first is by specifying an OEM NetFn code (from the IPMI spec 2.0, “Table 5-1, Network Function Codes”) –

    0x2E/0x2F – OEM/Group OEM/Non-IPMI group Requests and Response. The first three data bytes of requests and responses under this network function explicitly identify the OEM or non-IPMI group that specifies the command functionality. While the OEM or non-IPMI group defines the functional semantics for the cmd and remaining data fields, the cmd field is required to hold the same value in requests and responses for a given operation in order to be supported under the IPMI message handling and transport mechanisms. When this network function is used, the IANA Enterprise Number for the defining body occupies the first three data bytes in a request, and the first three data bytes following the completion code position in a response.

    Or 0x30-0x3F. This is for Controller-specific OEM/Groups.Vendor specific (16 Network Functions [8 pairs]). The Manufacturer ID associated with the controller implementing the command identifies the vendor or group that specifies the command functionality. While the vendor defines the functional semantics for the cmd and data fields, the cmd field is required to hold the same value in requests and responses for a given operation in order for the messages to be supported under the IPMI message handling and transport mechanisms.

    The second is via the Bridge NetFn (0x02), which reserves commands in the range C0-FE for OEMs.

  4. I got mine via – https://download.asrock.com/TSD/socflash_linux.zip, under https://www.asrockrack.com/support/faq.asp?id=61.

    The zip file has DOS, Windows, and Linux versions of the command. When executing it with no arguments it gives the usage –

    # ./AlUpdate
    *****************************************************************************
    * ATEN Technology, Inc.                                                     *
    *****************************************************************************
    * FUNCTION   :  IPMI FIRMWARE UPDATE UTILITY                                *
    * VERSION    :  2.08                                                        *
    * BUILD DATE :  Oct  9 2018                                                 *
    * USAGE      :                                                              *
    *             (1)Update FIRMWARE : AlUpdate -f filename.bin [OPTION]        *
    *             (2)Dump FIRMWARE   : AlUpdate -d filename                     *
    *             (3)Restore CONFIG  : AlUpdate -c -f filename.bin              *
    *             (4)Backup CONFIG   : AlUpdate -c -d filename.bin              *
    *****************************************************************************
    * OPTION                                                                    *
    *   -i the IPMI channel, currently, kcs and lan are supported               *
    * LAN channel specific arguments                                            *
    *   -h remote BMC address and RMCP+ port, (default port is 623)             *
    *   -u IPMI user name                                                       *
    *   -p IPMI password correlated to IPMI user name                           *
    *   -r Preserve Configuration (default is Preserve)                         *
    *      n:No Preserve, reset to factory default settings                     *
    *      y:Preserve, keep all of the settings                                 *
    *   -c IPMI configuration backup/restore                                    *
    *      -f [restore.bin] Restore configurations                              *
    *      -d [backup.bin] Backup configurations                                *
    *****************************************************************************
    * EXAMPLE                                                                   *
    *   we like to upgrade firmware through KCS channel                         *
    *   AlUpdate -f fwuperade.bin -i kcs -r y                                   *
    *   AlUpdate -d fwdump.bin -i kcs -r y                                      *
    *                                                                           *
    *   we like to restore/backup IPMI config through KCS channel               *
    *   AlUpdate -c -f restore.bin -i kcs -r y                                  *
    *   AlUpdate -c -d backup.bin -i kcs -r y                                   *
    *                                                                           *
    *   we like to upgrade firmware through LAN channel with                    *
    *   - BMC IP address 10.11.12.13 port 623                                   *
    *   - IPMI username is usr                                                  *
    *   - Password for alice is pwd                                             *
    *   - Preserve Configuration                                                *
    *   AlUpdate -f fw.bin -i lan -h 10.11.12.13 623 -u usr -p pwd -r y         *
    *   AlUpdate -d fwdump.bin -i lan -h 10.11.12.13 623 -u usr -p pwd -r y     *
    *                                                                           *
    *   we like to restore/backup IPMI config through LAN channel with          *
    *   - BMC IP address 10.11.12.13 port 623                                   *
    *   - IPMI username is usr                                                  *
    *   - Password for alice is pwd                                             *
    *   - Preserve Configuration                                                *
    *   AlUpdate -c -f fw.bin -i lan -h 10.11.12.13 623 -u usr -p pwd           *
    *   AlUpdate -c -d fwdump.bin -i lan -h 10.11.12.13 623 -u usr -p pwd       *
    *****************************************************************************