一個HTTP請求,把網站打裂開了

程式碼熬夜敲 發表於 2021-10-16

大家好,我是周杰倫,今天給大家看一段神奇的程式碼。

利用這幾行神奇的程式碼,居然能把網站打崩潰,這是怎麼一回事呢?

就是下面這個函式,根據傳進來的開始和結束位置,讀取檔案資料:

char* Read(int fd, int start, int end) {
    unsigned int length = end - start + 1;
    if (length > 1024)
        return NULL;

    return ReadFile(fd, start, end);
}

函式中最大隻支援一次讀取1024個位元組,所以增加了一個判斷邏輯。

現在請大家思考一下,這個函式有沒有什麼問題?

---思---

---考---

---5---

---秒---

---鍾---

來思考一下,假設我像這樣來呼叫這個函式:

Read(0, 0, 4294967295);

會發生什麼事呢?

你可能已經注意到了,這裡傳了一個很特殊的引數過去,這個數乍一看很大,遠遠超過了1024,按理說會通不過函式內部的檢查對吧?

但事情不是這麼簡單,這個特殊的數字——4294967295,是32位無符號整數所能表示的最大範圍。

但是請注意Read這個函式的引數,startend都是int型變數,把4294967295傳遞給end的時候,會被當作有符號的整數解析,也就是 -1 !

現在來看Read函式中計算長度的這行程式碼:

unsigned int length = end - start + 1;

計算結果就是-1 - 0 + 1 = 0!

length的結果會是0!

很自然逃過了下面對長度的檢查:

if (length > 1024)
    return NULL;

上面這段程式碼不只是一個假想的模型,實際上,它曾經真實存在過!

它的漏洞編號是:CVE-2015-1635

這是一個微軟的網際網路伺服器IIS中的一個漏洞,更要命的是,這個漏洞位於IIS處理HTTP請求的HTTP.sys驅動程式中。

你知道的,驅動程式是執行在作業系統核心之中,一旦核心驅動執行出現異常,那後果,輕則藍屏崩潰,重則直接被攻擊者遠端執行程式碼,控制伺服器!

在HTTP 1.1版本的協議中,可以通過請求頭中的Range欄位,請求或上傳指定資源的部分內容,比如像這樣:

GET /bg-upper.png HTTP/1.1
User-Agent: curl/7.35.0
Host: 127.0.0.1:8180
Accept: */*
Range: bytes=0-10

其中的Range欄位格式如下:

Range: bytes=start-end

微軟的IIS為了提高效能,將HTTP協議的解析放在了核心驅動HTTP.sys中實現。

而其中對range欄位的處理,就存在我們文章開頭的那個邏輯錯誤,不同的是,我們上面的那個示例是一個32位整數的版本,而IIS這個真實的漏洞是64位整數產生的問題,但原理是一樣的。

通過向存在漏洞的IIS伺服器傳送對應的HTTP請求,即可將目標伺服器打藍屏,實現DOS——拒絕服務攻擊。

這種攻擊方式就是——整數溢位攻擊。

接下來,我們們在搭建一個環境來驗證一下。

在虛擬機器中搭建一個IIS7的Web伺服器:

在這裡插入圖片描述

64位無符號整數能表示的最大數是:18446744073709551615,通過向伺服器傳送包含range引數的請求,有很大可能會導致伺服器藍屏。

使用神器metasploit來利用這個漏洞發起攻擊:

在這裡插入圖片描述

現在來看,伺服器已經掛了:

在這裡插入圖片描述

為什麼是很大可能,而不是一定藍屏呢,如何實現穩定把伺服器打藍屏呢?這就需要進一步瞭解這個漏洞更詳細的情況。

實際上這個漏洞原理比文章開頭的那個邏輯要更復雜一些,這裡只是做了一個簡單入門介紹,關於這個漏洞的更詳細情況,大家可以看一下360大神MJ0011當年寫的一篇技術分析(PS:有點硬核,想要看懂得反覆多看幾次):

《MS15-034/CVE-2015-1635 HTTP遠端程式碼執行漏洞分析》

https://blogs.360.cn/post/cve...