Nginx歷史上曾出現過多次解析漏洞,比如80sec發現的解析漏洞,以及后綴名后直接添加%00截斷導致代碼執行的解析漏洞。
但是在2013年底,nginx再次爆出漏洞(CVE-2013-4547),此漏洞可導致目錄跨越及代碼執行,其影響版本為:nginx 0.8.41 – 1.5.6,范圍較廣。
為了更深入的了解漏洞產生的原因,筆者根據官方補丁(http://nginx.org/download/patch.2013.space.txt),對此漏洞進行了進一步的分析,
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應用在處理上傳文件時,都會將文件重命名,通過應用自身添加后綴,或者對后綴名去掉特殊字符后,做類型判斷。
以上因素都導致此漏洞被認為是雞肋漏洞,難以利用,而被人們所忽略。
此問題在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