IORegistryIterator競爭條件漏洞分析與利用
Author:[email protected]
0x00 簡介
CVE-2015-7084是由於IORegistryIterator沒有考慮使用者態多執行緒同時呼叫的情況,引起Race Condition,可導致任意程式碼執行。漏洞存在於XNU版本3248.20.55之前的核心上,即Mac OS X 10.11.2、iOS 9.2、watchOS 2.1、tvOS 9.1之前的系統版本上。官方修復公告https://support.apple.com/en-us/HT205637。
0x01 漏洞背景
IORegistryIterator是用於XNU核心中用於遍歷訪問IO Registry Entry的一個類。在XNU版本3248.20.55之前的核心上,即Mac OS X 10.11.2、iOS 9.2、watchOS 2.1、tvOS 9.1之前的系統版本上,在操作IORegistryIterator時缺少鎖機制,使用者態程式透過多執行緒呼叫引起Race Condition,最終可實現任意程式碼執行。這個漏洞是由Google Project Zero的Ian Beer報告,CVE編號CVE-2015-7084。
0x02 漏洞分析
Ian Beer在https://code.google.com/p/google-security-research/issues/detail?id=598中給出了漏洞的說明,以及一份導致Double Free的PoC程式碼。
is_io_registry_iterator_exit_entry
是IORegistryIteratorExitEntry對應的核心介面,會呼叫IORegistryIterator::exitEntry函式。
#!cpp
/* Routine io_registry_iterator_exit */
kern_return_t is_io_registry_iterator_exit_entry(
io_object_t iterator )
{
bool didIt;
CHECK( IORegistryIterator, iterator, iter );
didIt = iter->exitEntry();
return( didIt ? kIOReturnSuccess : kIOReturnNoDevice );
}
.
#!cpp
bool IORegistryIterator::exitEntry( void )
{
IORegCursor * gone;
…
if( where != &start) {
gone = where; // Race Condition
where = gone->next;
IOFree( gone, sizeof(IORegCursor)); // gone可能被釋放兩次
return( true);
} else
return( false);
…
}
但是由於缺乏鎖的保護,透過多執行緒呼叫IORegistryIteratorExitEntry,導致gone指向的記憶體區域被釋放兩次,引起崩潰。示意圖如下:
0x03 漏洞利用
由於Double Free不易利用,Pangu Team在其部落格文章http://blog.pangu.io/race_condition_bug_92/中提出了另外一種思路,可以穩定地利用Race Condition實現任意程式碼執行。下面將對這種思路進行具體的分析,在已知Kernel Slide的情況下,在Mac OS X 10.11上實現提權。
1. 攻擊流程
透過觀察操作IORegistryIterator的函式enterEntry,發現其包含向單向連結串列插入節點的操作,如下:
#!cpp
void IORegistryIterator::enterEntry( const IORegistryPlane * enterPlane )
{
IORegCursor * prev;
prev = where;
where = (IORegCursor *) IOMalloc( sizeof(IORegCursor));
assert( where);
if( where) {
where->iter = 0;
where->next = prev; //在連結串列頭部插入新的where節點,where->next指向舊where
where->current = prev->current;
plane = enterPlane;
}
}
而IORegistryIterator::exitEntry中,包含移除單向連結串列頭部節點的操作,並且釋放移除的節點記憶體。
#!cpp
bool IORegistryIterator::exitEntry( void )
{
IORegCursor * gone;
…
if( where != &start) {
gone = where;
where = gone->next; //從連結串列頭部移除當前where節點
IOFree( gone, sizeof(IORegCursor)); //釋放移除的節點記憶體區域
return( true);
} else
return( false);
…
}
在兩個執行緒中分別呼叫IORegistryIteratorEnterEntry和IORegistryIteratorExitEntry,在特定的執行序列下,可能導致enterEntry在執行where->next = prev;時,prev指向的where區域已經被exitEntry的IOFree釋放,就會導致where->next指向被釋放的記憶體。
那麼,當第二次呼叫exitEntry時,就會使得where指向被釋放的記憶體,這塊記憶體透過Heap Spray可以控制其中的內容。
#!cpp
bool IORegistryIterator::exitEntry( void )
{
…
if( where != &start) {
gone = where; //where->next已指向被釋放的區域
where = gone->next; //where指向被釋放的區域
}
…
}
最後,第三次呼叫exitEntry時,where->iter可控,透過對映使用者空間記憶體iter物件虛表,可實現任意程式碼執行。
#!cpp
bool IORegistryIterator::exitEntry( void )
{
…
if( where->iter) { // where->iter可控
where->iter->release(); //可透過構造虛表,執行任意程式碼
where->iter = 0;
}
…
}
攻擊流程示意圖如下:
2. Heap Spray
關於這個漏洞利用的關鍵是要控制where指向的被釋放的記憶體區域的內容。where是IORegCursor指標,由IOMalloc申請,位於kalloc.32 zone中。
#!cpp
struct IORegCursor {
IORegCursor * next;
IORegistryEntry * current;
OSIterator * iter;
};
當第二次exitEntry被呼叫後,where指向的記憶體區域在kalloc.32的freelist連結串列中。我們可以透過heap spray kalloc.32,使得位於freelist中的記憶體重新被填充為我們控制的資料,實現控制where->iter的目的。heap spray的方法就是透過結合io_service_open_extended
以及OSData,Pangu Team在其POC 2015的議題《Hacking from iOS8 to iOS9》中提到了這種heap spray的方法。
透過構造特定的XML資料,包含data標籤,那麼透過io_service_open_extended
建立任意UserClient,在OSUnserializeXML中反序列化data資料時,就可以透過OSData佔用記憶體,實現任意zone的heap spray。
#!cpp
object_t *
buildData(parser_state_t *state, object_t *o)
{
OSData *data;
if (o->size) {
data = OSData::withBytes(o->data, o->size);
} else {
data = OSData::withCapacity(0);
}
if (o->idref >= 0) rememberObject(state, o->idref, data);
if (o->size) free(o->data);
o->data = 0;
o->object = data;
return o;
};
3. 任意程式碼執行
在使用者空間對映兩塊記憶體空間,分別放置構造的iter物件以及構造的虛表。將XML中的data的第三個QWORD欄位設定為構造的iter物件指標,並進行heap spray。透過heap spray成功控制where指向的記憶體區域內容後,where->iter可控,最終呼叫where->iter->release()時就會呼叫我們構造的虛表中的函式,實現任意程式碼執行。在已知Kernel Slide的情況下,在10.10.5以及10.11上都成功實現提權,10.10.5如下:
0x04 官方修復
在10.11.2的XNU原始碼中,蘋果官方進行了修復。新新增了一個IOUserIterator,用於封裝IORegistryIterator,對reset操作等加鎖,也在enterEntry和exitEntry時加鎖,防止多執行緒呼叫引起的Race Condition。
#!cpp
/* Routine io_registry_iterator_enter */
kern_return_t is_io_registry_iterator_enter_entry(
io_object_t iterator )
{
CHECKLOCKED( IORegistryIterator, iterator, iter );
IOLockLock(oIter->lock);
iter->enterEntry();
IOLockUnlock(oIter->lock);
return( kIOReturnSuccess );
}
/* Routine io_registry_iterator_exit */
kern_return_t is_io_registry_iterator_exit_entry(
io_object_t iterator )
{
bool didIt;
CHECKLOCKED( IORegistryIterator, iterator, iter );
IOLockLock(oIter->lock);
didIt = iter->exitEntry();
IOLockUnlock(oIter->lock);
return( didIt ? kIOReturnSuccess : kIOReturnNoDevice );
}
0x05 References
- https://code.google.com/p/google-security-research/issues/detail?id=598
- http://blog.pangu.io/race_condition_bug_92/
- http://blog.pangu.io/wp-content/uploads/2015/11/POC2015_RUXCON2015.pdf
相關文章
- 競爭條件入門2024-08-18
- 條件競爭利用初體驗---2019-0ctf-zero_task2019-06-06
- [SEEDLab]競態條件漏洞(Race Condition Vulnerability)2021-06-19
- 淺談併發的資料競爭(可見性)與競態條件(原子性)2018-09-23
- 解決多執行緒競爭條件——臨界區2024-04-23執行緒
- 企業競爭情報蒐集與分析2023-02-20
- BlueKeep 漏洞利用分析2019-09-20
- CRLF Injection漏洞的利用與例項分析2020-08-19
- 聊天機器人ChatGPT在Go程式中找到競爭條件並修復2022-12-03機器人ChatGPTGo
- Linux 併發與競爭2024-06-14Linux
- 如何利用親和圖提高企業競爭力?2023-10-16
- “印度北上廣”:競爭與追逐2020-03-11
- cve-2014-0569 漏洞利用分析2020-08-19
- Concurrency(三:競態條件和臨界區)2019-03-11
- 充電樁規模競爭格局分析2020-07-09
- 兒童服飾行業競爭分析2022-06-18行業
- 轉載:利用大資料創造競爭優勢2019-03-09大資料
- 谷歌與ChatGPT展開直接競爭2023-02-09谷歌ChatGPT
- 電商公司如何利用IP代理獲取競爭優勢?2022-03-01
- 憑什麼打敗競爭對手?基於資料、基於分析的商業競爭2019-03-14
- 條件概率與全概率公式2019-03-21公式
- (CVE-2019-5786) 漏洞原理分析及利用2020-07-01
- CVE-2014-4113漏洞利用過程分析2020-08-19
- 永恆之藍漏洞利用機制分析2020-08-03
- 【C進階】22、條件編譯分析2021-12-25編譯
- 優質投資的特徵與競爭力2020-05-30特徵
- Linux 併發與競爭實驗學習2024-06-15Linux
- doxygen 宏定義/宏編譯/條件編譯/預處理/預編譯 不處理、忽略條件、分析所有條件、滿足所有條件的方法2024-03-05編譯
- CVE-2015-1538漏洞利用中的Shellcode分析2020-08-19
- Python條件語句與迴圈2019-05-12Python
- python條件判斷與迴圈2021-09-09Python
- 大資料分析競爭對手的重要性2022-12-01大資料
- 推薦演算法是今日頭條的核心競爭力嗎?2018-09-23演算法
- 漏洞利用與卡巴斯基的對抗之路2020-08-19
- CVE-2014-0038核心漏洞原理與本地提權利用程式碼實現分析2020-08-19
- 社交遊戲玩法設計—競爭與對抗2023-02-28遊戲
- 在由價格競爭向產品競爭、服務競爭等領域延伸的過程中2022-03-17
- ruoyi漏洞利用2024-07-02