成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

如何通過CVE-2015-7547(GLIBC getaddrinfo)漏洞繞過ASLR

安全 漏洞
在這項研究中,我們使用了Linux創建進程時的特性來繞過ASLR。這種技術同時也可以用于其他內存損壞漏洞的利用。因此,用戶應始終嘗試通過及時部署軟件修補程序和更新來保護服務器。以保證我們在潛在威脅行動者行動前領先一步。

0x01 前言

2016年2月16日,Google披露了一個重要的緩沖區溢出漏洞,該漏洞在GLIBC庫中的getaddrinfo函數中觸發。同時他們還提供了一份PoC。基于此,在本文中,我們將展示如何通過CVE-2015-7547繞過ASLR。

0x02 漏洞描述

getaddrinfo()函數的作用是通過查詢DNS服務將主機名和服務解析為addrinfo結構體。

在getaddrinfo()函數實現中,使用了alloca()函數(在堆棧上分配緩沖區)對DNS進行響應。開始的時候,該函數首先分配一段棧空間用于DNS響應, 如果響應時間過長,它將重新分配一個堆緩沖區用于響應。但由于更新代碼將緩沖區為新分配的堆緩沖區后,舊的堆棧緩沖區未及時釋放,仍舊再使用。 這個懸空指針便造成了一個經典的緩沖區溢出。

ASLR? ASLR!

在上述情況下,可以通過這個漏洞覆蓋getaddrinfo()函數的返回地址,但是我們應該將返回地址覆蓋到哪里呢?在啟用ASLR的系統中,模塊地址是隨機的。因此,攻擊者不能將攻擊流地址設置為預先設定的地址。

fork()

fork()是Linux中創建新進程的方法。一個典型的fork使用方法如下圖所示:

fork出的子進程和父進程使用的相同的指令段,他們只有pid不相同,而pid是fork函數返回給子進程的。和windows下的代碼復用的區別在于,這里意味著子進程與其父進程共享許多特性--具有相同的寄存器狀態,堆棧和內存布局。

0x03 程序流程示例

考慮一個服務器應用程序,其運行模式如下:

1. 客戶端遠程連接到應用程序。

2. 應用程序自己fork一個子進程用于響應客戶端請求

3. 在處理客戶端請求的過程中,子進程使用"getaddrinfo()"函數解析主機名。 同時,它向其DNS服務器發送DNS請求。

4. DNS服務器對DNS請求做出一個合法響應。

5. 子進程啟動與已被解析的主機的連接。

每次主進程進行響應處理時,它都會自己fork一個子進程。根據前面的描述,這意味著所有子進程將共享相同的內存布局--包括加載模塊的地址。 這種場景對于許多服務(例如HTTP代理,電子郵件服務器或DNS服務器)是非常常見的。

0x04 攻擊流程示例

在實施攻擊的過程中,我們假設攻擊者具有能夠響應受害者的任意DNS請求的能力。實現這種情形完全可以通過ARP欺騙、DNS欺騙完成。攻擊場景如下圖:

1. 一個攻擊者構造一個請求發送給受害服務器

2. 為了響應攻擊者的請求,受害服務器的守護進程fork出一個子進程

3. 子進程處理請求時,發起一個DNS請求

4. 攻擊者回復一個惡意的DNS響應,該響應將子進程的返回地址覆蓋,在這里,我們將其設置未0x12121212

5. 攻擊者獲得子進程用connect()函數發起的TCP回連

如果0x12121212確實是getaddrinfo()的正確返回地址,那么該進程將正常運行,并通過connect()發起tcp連接。

如果不是這種情況,并且攻擊者將返回地址寫為其他任何地址,則應用程序將由于內存段錯誤或執行無效的指令而崩潰。

這種方式可以作為判斷一個地址是否為getaddrinfo()的返回地址的一種方法,原因在于如果地址正確,那么一個TCP連接將會成功建立。由于模塊的基址在不同的子進程中是沒有隨機化(前面提到的公用內存布局),于是這個地址在所有的子進程中可以通用。一個攻擊者可以使用這種方式去遍歷每一個可能的地址,知道正確建立TCP連接而獲得正確的地址。

然而,采用這種方式進行基址定位需要猜解2的64次方的數量的地址,這并沒有太大的現實意義。

逐字節的逼近

不過,攻擊者可以每次只覆蓋一個字節。 例如,假設getaddrinfo的返回地址為0x00007fff01020304:

我們首先只覆蓋getaddrinfo()函數的返回地址最低有效位(LSB)的一字節。這里用0x00進行覆蓋。由于在假設中getaddrinfo()的返回地址為0x00007fff01020304,將最低位覆蓋為0x00,那么這里返回地址就會變為0x00007fff01020300,由于該地址是非法地址,函數返回后程序就會崩潰。于是我們繼續重復上述操作,并且每次重復是LSB只加1(即第一次0x00,第二次0x01,第三次0x02,...),當我們將LSB增加到0x04時,getaddrinfo函數的返回地址為正確的返回地址0x00007fff01020304,此時程序不會崩潰,建立tcp連接。于是最低位的值便確定了。

接下來,我們重復上述整個操作,通過覆蓋返回地址的兩個字節(0x04 0x00)來枚舉下一個字節,我們將返回地址的第一個字節設置為剛剛猜解出來的正確字節(0x04),于是我們只需要采取相同辦法猜解第二個字節即可。猜解成功的標志和第一個字節一樣,建立正確的連接。

接下來是第三個字節,第四個字節。。。

通過這種逐字節逼近的方法,我們最多只需要進行8*2^8次(每個字節最多2^8次猜解,總共8字節)嘗試便可以得到正確的返回地址,這種方式在幾秒內便可得到結果。

0x05 查找可利用的應用程序

http://codesearch.debian.net是一個包含超過18,000 Debian包的索引的網站。我們通過該網站查找所有調用 fork()和getaddrinfo()函數的應用程序(這些程序都是有可能進行利用的),發現超過1300個潛在的可利用的應用程序。 然后,進一步的我們需要檢查每個應用程序的源代碼,檢查其流程是否適合我們的需要。

0x06 Tinyproxy

Tinyproxy是Linux下一個小型的http代理軟件,通過審計,發現該應用程序的執行流程符合上述分析的執行流程。當它在響應HTTP連接請求時,會fork出一個子進程,然后調用getaddrinfo()函數來檢索所請求的網站的IP地址。 然后使用connect()函數連接該主機獲取網站內容。

1. 堆棧任意指針泄露

在下面的代碼塊中我們遇到了第一崩潰點:

rbx寄存器首先被覆蓋,然后執行"mov BYTE PTR [rbx],sil"指令,該指令可釋放對rbx指向的地址的指針。 rbx原先是指向棧上的,也就是說,如果我們采用逐字節逼近的方法,枚舉其值使得該程序在堆棧上泄漏一個地址。

下圖(output of /proc/PID/maps)顯示了堆棧的邊界。 正如圖中所示,它的初始大小總是大于0x1000字節。

寄存器rbx指向的地址必須是可寫的,否則會引發分段錯誤導致程序崩潰。然而它的缺陷在于,無論在哪個地址寫入“sil”值,只要它是可寫地址,程序流將正確地繼續,這意味著對于rbx的低12位設置什么值根本無關緊要,因為由于堆棧的緣故它總是可讀可寫的。

所以我們只要在堆棧范圍內泄露了任意一個指針。當我們必須精確定位時,堆棧變量指向的地址并不會對程序流產生什么影響。

2. 泄露棧基址

由于應用程序的流程總是相同的,所以棧的大小總是相同的。 這意味著我們可以依賴于棧基址到這些變量,結構體和緩沖區的偏移量進行定位。而且在這樣的情況下,我們往往依賴于這樣的常量偏移。所以首先應該得到棧基址。

由于我們已經得到一個在棧空間內的地址,所以泄露棧基址比枚舉任意地址更簡單。而且我們知道它擁有兩個屬性,一是棧基址與頁面邊界(0x1000)對齊,二是棧基址將是棧后面的第一個不可讀的地址。

讓我們假設堆棧基址在0x00007fffed008000。我們利用已經泄漏的任意堆棧地址,并將其對齊到頁邊界得到一個新的對齊地址,例如0x00007fffed000140對齊到0x00007fffed000000。然后,我們枚舉堆棧基址,從這個對齊的地址開始進行覆蓋,并在每次嘗試之后遞增0x1000(頁大小)。在我們發送請求之后,等待一段時間,并檢查服務器是否嘗試連接到我們解析的IP。如果是,這意味著我們還沒有達到堆棧基地。如果發生超時,說明服務器發生崩潰,我們達到了目標,獲得了堆棧基址。

3. 堆棧偏移

在從getaddrinfo返回之前,程序會執行以下檢查:

注意以紅色突出顯示的塊。如果我們到達它并且傳遞一個無效的堆指針作為參數,應用程序崩潰,因為它試圖釋放(free()函數)一個無效的堆塊。如果要繞過這個free()函數,r14和rdi必須相等。 r14指向原來的__alloca()函數堆棧緩沖區。 由于堆棧基址先前泄漏,并且__alloca()緩沖區與堆棧基址的偏移量應該是常量,因此我們不應該遇到任何問題。 然而,我們發現偏移在每次運行時略有不同。 為什么?

這涉及到內核代碼對ASLR的處理問題,如下linux內核代碼所示:

  1. /arch/x86/kernel/process.c 

觀察上述內核代碼,可以看到,如果ASLR被啟用,每次堆棧分配時SP(堆棧指針)將減少一個隨機數。這意味著在每次不同的運行時,在rsp和堆棧之間將存在一個隨機增量。

幸運的是,這個增量非常小。我們可以輕松地枚舉這個隨機偏移。

看看上面的IDA代碼片段,我們可以發現,如果rdi等于r14,程序將不會運行到釋放rdi的那個分支。 因此,我們可以使用我們之前得到的堆棧基址,結合預先計算(即,如果該值于棧基址對齊程序將返回0),然后嘗試所有其他2^9種可能性,便可得到此增量。

4. 泄漏LIBC模塊地址

這部分的實現是超級簡單的,因為我們可以使用前面提到的技術(byte-by-byte approach 逐字節逼近)來枚舉返回地址的每個字節從而得到它。

5. 代碼執行

剩下要做的就是構造一個ROP鏈,這是非常容易和直接。我們知道system()函數在libc的基址偏移的某個確定的位置,所以我們只需設置它的參數,并使用ROP調用它。

0x07 結論

在這項研究中,我們使用了Linux創建進程時的特性來繞過ASLR。這種技術同時也可以用于其他內存損壞漏洞的利用。因此,用戶應始終嘗試通過及時部署軟件修補程序和更新來保護服務器。以保證我們在潛在威脅行動者行動前領先一步。

責任編輯:武曉燕 來源: paloaltonetworks.com
相關推薦

2015-01-29 11:47:35

2020-09-22 12:07:13

攻擊

2021-10-29 11:52:16

谷歌漏洞TPM

2025-03-28 07:15:00

漏洞網絡攻擊網絡安全

2015-09-18 09:33:03

2015-07-13 09:18:20

2015-01-23 16:57:09

2015-06-03 10:21:44

漏洞溢出漏洞9patch

2015-02-04 11:20:28

2021-02-07 14:39:22

Falco漏洞安全工具

2023-11-20 11:24:24

2022-06-14 09:00:21

漏洞補丁

2015-05-13 19:30:21

2021-01-29 10:29:17

漏洞中間人攻擊網絡攻擊

2021-10-08 15:53:26

漏洞PoC漏洞攝像頭

2015-01-29 09:15:57

2021-06-17 11:05:46

漏洞Linux發行版Polkit auth

2021-02-09 10:31:04

漏洞webWordPress F

2009-12-18 13:31:18

Cisco路由器配置口

2021-11-02 11:55:07

macOS macOS Monte漏洞
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久伦理电影 | 男女免费视频网站 | 国产欧美一区二区精品久导航 | 在线视频成人 | 男女视频在线观看网站 | 国产一区二区三区视频免费观看 | 蜜臀久久| 狠狠爱一区二区三区 | 在线观看国产视频 | 亚洲午夜精品 | 亚洲天堂成人在线视频 | 在线视频91 | 日韩免费一级 | 国产伦精品| 国产一级淫片免费视频 | 亚洲日本免费 | 国产久| 国产精品99999 | 91麻豆精品一区二区三区 | 久久亚洲综合 | 久久精品国产久精国产 | 国产一区免费视频 | 看av片网站 | 亚洲啊v | 国产精品日本一区二区不卡视频 | 久久久久国产精品一区二区 | 色黄网站 | 亚洲视频免费一区 | 精品国产一区二区在线 | 一区二区三区在线播放 | 成人高清视频在线观看 | 91精品久久久久久久99 | 国产欧美在线一区二区 | 波多野结衣av中文字幕 | 国产精品99久久久久久久vr | 91在线免费视频 | av在线播放国产 | 亚洲午夜av久久乱码 | av夜夜操 | 一级一级毛片免费看 | 精品乱子伦一区二区三区 |