flawopen.com/Teardowns/cve-2020-0022-android-bluetooth-hci-heap-overflow
CVE-2020-0022 源代码级技术深度解析与系统加固工程指南:深入剖析漏洞触发条件、攻击利用链条与加固补丁的具体实现。
通俗原理解析:Imagine a post office that accepts letters in numbered pieces (Part 1 of 2, Part 2 of 2). An attacker sends Part 1 stating 'the whole letter is 50 words'. The clerk prepares a tiny envelope. Then the attacker sends Part 2 containing 5,000 words! The clerk shoves the words in, bursting the envelope and scattering private documents all over the floor.
Fluoride Bluetooth StackHCI (Host Controller Interface)L2CAP (Logical Link Control and Adaptation Protocol)Heap Buffer Overflow根本原因在于开源系统中未经验证的边界参数,导致状态不同步并绕过安全控制。
技术利用机制与执行路径分析:The attacker broadcasts crafted ACL packets toward a nearby Android device.
技术利用机制与执行路径分析:The attacker sends an initial L2CAP packet claiming a small total packet length.
技术利用机制与执行路径分析:The attacker sends a second fragment with an unexpected payload size exceeding the allocation.
技术利用机制与执行路径分析:The reassembly loop overwrites adjacent heap chunks, executing code inside the Bluetooth daemon.
// VULNERABLE: system/bt/stack/l2cap/l2c_main.cc
void l2c_rcv_acl_data(BT_HDR *p_msg) {
tL2C_LCB *p_lcb = l2cu_find_lcb_by_handle(handle);
// ROOT CAUSE:
// Does not verify that accumulated fragment lengths stay within allocated buffer!
uint8_t *p_dest = p_lcb->p_rx_msg->data + p_lcb->p_rx_msg->offset;
// Copies fragment without boundary checking!
memcpy(p_dest, p_msg->data, p_msg->len);
p_lcb->p_rx_msg->offset += p_msg->len;
}
// SECURE: system/bt/stack/l2cap/l2c_main.cc patch
void l2c_rcv_acl_data(BT_HDR *p_msg) {
tL2C_LCB *p_lcb = l2cu_find_lcb_by_handle(handle);
// 1. Calculate remaining capacity in allocated reassembly buffer
size_t remaining_capacity = p_lcb->p_rx_msg->total_len - p_lcb->p_rx_msg->offset;
// 2. Reject fragment if incoming length exceeds remaining capacity
if (p_msg->len > remaining_capacity) {
L2CAP_TRACE_ERROR("L2CAP packet overflow: len %d exceeds remaining %zu",
p_msg->len, remaining_capacity);
osi_free(p_lcb->p_rx_msg);
p_lcb->p_rx_msg = nullptr;
return; // Abort cleanly
}
uint8_t *p_dest = p_lcb->p_rx_msg->data + p_lcb->p_rx_msg->offset;
memcpy(p_dest, p_msg->data, p_msg->len);
p_lcb->p_rx_msg->offset += p_msg->len;
}
total_len - offset) before copying reassembled network packet fragments。