CVE-2013-4547 Nginx解析漏洞深入利用及分析

wyzsk發表於2020-08-19
作者: 百度安全中心 · 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,並且在相應的地方設定斷點,

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

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章