<dd id="sga4y"><optgroup id="sga4y"></optgroup></dd>
<nav id="sga4y"><code id="sga4y"></code></nav>
  • <optgroup id="sga4y"></optgroup>

    原文地址:http://drops.wooyun.org/tips/2006

    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,并且在相應的地方設置斷點,

    enter image description here

    圖-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的邏輯中,那么當我們發送攻擊代碼的時候,執行流程將如下:

    enter image description here

    圖-2 \0未觸發異常

    再回到sw_check_uri狀態,此時后面的字符串為.php,而“.”將被為是uri的擴展名的分隔符

    enter image description here

    圖-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
    

    enter image description here

    圖-4文件a.jpg

    enter image description here

    圖-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

    97av