作者:
百度安全中心
·
2014/05/19 11:12
0x00 背景
Nginx歷史上曾出現過多次解析漏洞,比如80sec發現的解析漏洞,以及字尾名後直接新增%00截斷導致程式碼執行的解析漏洞。
但是在2013年底,nginx再次爆出漏洞(CVE-2013-4547),此漏洞可導致目錄跨越及程式碼執行,其影響版本為:nginx 0.8.41 – 1.5.6,範圍較廣。
為了更深入的瞭解漏洞產生的原因,筆者根據官方補丁(http://nginx.org/download/patch.2013.space.txt),對此漏洞進行了進一步的分析,
0x01 漏洞朔源
1.從官方補丁可以看出nginx在ngx_http_parse_request_line函式處做了程式碼patch,下載nginx原始碼,定位其補丁檔案為ngx_http_parse.c,函式ngx_http_parse_request_line中,分別位於程式碼段:
由此可定位本次漏洞需要分析的點,啟用gdb除錯,將break點設定為ngx_http_parse_request_line,
並且watch變數state和p,因為此函式為狀態機,state為狀態值,p為指標所指文志,這將是漏洞觸發的關鍵點。
除錯過程中需要跟蹤nginx的worker子程式,所以需要設定setfollow-fork-mode child,並且在相應的地方設定斷點,
圖-1 跟進子程式
2.分別傳送正常和攻擊語句進行測試:
正常語句:
http://127.0.0.1/a.jpg
攻擊語句:
http://127.0.0.1/a.jpg(非編碼空格)\0.php
使用正常語句一直s或n跟蹤,會發現在對url的解析過程中,當路徑中存在’.’或url存在’\0’會有如下處理:
#!cpp
case sw_check_uri:
……
case '.':
r->complex_uri = 1; //此作為flag會判斷使用ngx_http_parse_complex_uri方法,對路徑修復
state = sw_uri;
break;
casesw_check_uri:
……
case '\0': //當遇到\0是,將會判斷為非法字元
return NGX_HTTP_PARSE_INVALID_REQUEST;
但是在檢查uri中有空格則會進入到sw_check_uri_http_09
的邏輯中,那麼當我們傳送攻擊程式碼的時候,執行流程將如下:
圖-2 \0未觸發異常
再回到sw_check_uri
狀態,此時後面的字串為.php,而“.”將被為是uri的副檔名的分隔符
圖-3 取字尾名錯誤
最終導致nginx認為此次請求的字尾名為php,透過配置,會傳給fastcgi進行處理,而fastcgi在查詢檔案的時候被\0截斷,最終取到”a.jpg(非編碼空格)”檔案(注:Linux下php-fpm預設限制的字尾名為php,如未取消限制,訪問將出現access denied。測試想要檢視執行結果,需修改php-fpm.conf中的security.limit_extensions為空,即允許任意字尾名檔案作為php解析。)
跨越
location /protected / {deny all;}
的規則的原理與此類似,均為狀態機中判斷出現混亂,從導致而可以跨越到protected目錄中,訪問預設不可訪問到的檔案。
由此可知,常規利用中如果想觸發程式碼執行,條件為可上傳帶空格的檔案到伺服器,並且伺服器儲存的時候也需要保留空格,而大多數情況下,web應用在處理上傳檔案時,都會將檔案重新命名,透過應用自身新增字尾,或者對字尾名去掉特殊字元後,做型別判斷。
以上因素都導致此漏洞被認為是雞肋漏洞,難以利用,而被人們所忽略。
0x02 windows下的RCE
此問題在windows的攻擊場景中,則從小汽車變身為變形金剛。
首先,我們瞭解一下windows讀取檔案時的特點,即檔案系統api建立檔名或查詢檔名時,預設會去掉檔名後的空格,再執行操作,參見示例程式碼,目錄下放置a.txt不帶空格:
#!cpp
#include "stdafx.h"
#include<windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hFile =CreateFile(L"a.txt ",GENERIC_WRITE|GENERIC_READ, 0, //注意a.txt後有一個空格
NULL,
OPEN_EXISTING, // 開啟存在的檔案
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile ==INVALID_HANDLE_VALUE)
{
printf("openfailed!");
}
else
{
printf("fileopened");
}
CloseHandle(hFile);
return 0;
}
透過此程式碼可知道,即使我們傳入引數是”a.txt ”帶空格,最後訪問到卻確是”a.txt”不帶空格
此時的攻擊過程為:
1.上傳任意檔案(不需要帶空格檔案),
2.http://127.0.0.1/a.jpg(非編碼空格)\0.php
圖-4檔案a.jpg
圖-5漏洞利用
成功將a.jpg檔案當作php程式碼執行,達到了攻擊成功的目的。
透過windows的此特性,使CVE-2013-4547在windows+nginx的環境中的危害無限擴大,即在windows下,只要普通使用者能上傳檔案,則可利用本次漏洞,導致程式碼執行,並進一步入侵伺服器。
並且在普通站長中使用windows做為作業系統的數量甚廣,CVE-2013-4547在windows的場景下將進行華麗的變身。
from:http://sec.baidu.com/index.php?research/detail/id/19
本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!