不少次聽到人說apache的「解析漏洞」了,正好今天又有人問,那就簡單科普一下這個「解析漏洞」是何物。php
先來看測試過程和結果的對比吧。html
結果一web
首先,我安裝了apache 2.x版本,同時以module方式使apache與php結合,測試發現確實存在這樣的解析漏洞。shell
結果二apache
而後,我將apache與php的結合方式修改成fastcgi方式,測試發現爆500錯誤,不存在這樣的解析漏洞。瀏覽器
錯誤提示:服務器
1Bad file descriptor: mod_fcgid: don't know how to spawn child process: f4ck.php.xapp
意思就是不知道該如何解析這個文件。測試
結果出來了,那麼對於影響範圍這塊,在目前全部的apache版本中均存在此問題,但只適用於以module方式解析php的apache,使用fastcgi方式解析php的apache不受影響,使用cgi方式解析php的apache是否影響未測試。網站
下面來簡單分享一下測試過程當中我發現的一點經驗。
先來看一下apache的主配置文件httpd.conf,搜索「DefaultType」,就能夠看到這麼一段註釋和默認配置:
# # DefaultType: the default MIME type the server will use for a document # if it cannot otherwise determine one, such as from filename extensions. # If your server contains mostly text or HTML documents, "text/plain" is # a good value. If most of your content is binary, such as applications # or images, you may want to use "application/octet-stream" instead to # keep browsers from trying to display binary files as though they are # text. #10DefaultType text/plain
DefaultType存在的意義是告訴apache該如何處理未知擴展名的文件,好比f4ck.xxx這樣的文件,擴展名是xxx,這確定不是一個正常的網頁或腳本文件,這個參數就是告訴apache該怎麼處理這種未知擴展名的文件。
參數DefaultType的默認值是「text/plain」,也就是遇到未知擴展名的文件,就把它看成普通的txt文本或html文件來處理。
測試一
好比我將如下代碼保存爲f4ck.xxx:
1F4ckTeam apache test
訪問它,按照默認的apache配置,這個文件是會被瀏覽器顯示出來具體效果的:
這是對於文件內容爲HTML代碼的未知擴展名文件來講,文件中的HTML代碼會被瀏覽器執行。
測試二
那麼,對於文件內容爲php代碼的未知擴展名文件來講,這些php代碼會被解析嗎?
來看測試結果:
能夠看到,這裏包含php代碼的未知擴展名的文件被看成txt文檔處理了。
可是,若是將文件名改成f4ck.php.xxx,那麼就會被以module方式運行php的apache解析,爲何?
由於Apache認爲一個文件能夠擁有多個擴展名,哪怕沒有文件名,也能夠擁有多個擴展名。Apache認爲應該從右到左開始判斷解析方法的。若是最右側的擴展名爲不可識別的,就繼續往左判斷,直到判斷到文件名爲止。
官方解釋見:http://httpd.apache.org/docs/current/mod/directive-dict.html,搜索「extension」便可看到。
摘錄官方解釋:
extension
In general, this is the part of the filename which follows the last dot. However, Apache recognizes multiple filename extensions, so if a filename contains more than one dot, each dot-separated part of the filename following the first dot is an extension. For example, the filename file.html.en contains two extensions: .html and .en. For Apache directives, you may specify extensions with or without the leading dot. In addition, extensions are not case sensitive.
那麼,對於「測試一」和「測試二」來講,apache發現這個文件的擴展名是未知的,那麼它會先看在擴展名以前是否有其餘的可識別的擴展名,可是該 案例中的完整文件名爲「f4ck.xxxx」,在擴展名「xxxx」以前沒有其餘的可識別擴展名了,因此apache就按照httpd.conf中參數 DefaultType的值來決定該文件的處理方式,即做爲txt文檔處理。
一樣的,對於「結果一」和「結果二」來講,也是按照這樣的方式來逐步肯定未知擴展名文件的解析方式,首先apache發現這個文件的擴展名是未知 的,那麼它會先看在擴展名以前是否有其餘的可識別的擴展名,在該案例中的完整文件名爲「f4ck.php.x」,那麼apache就發如今未知擴展名 「x」以前有一個可識別的擴展名是「php」,那麼apache就會認爲這是一個php文件,就會把這個文件按照解析php文件的方式來解析。
說到這裏,就不得不提一下,apache對於擴展名的定義都是寫在conf/mime.types文件中的,看一下圖:
文件mime.types定義了apache處理不一樣擴展名文件的方法,文件httpd.conf中參數DefaultType的值定義了apache處理未知擴展名文件的方法。
另外,文件httpd.conf中語句塊「」中能夠用「AddType」語句來定義apache解析不一樣擴展名文件的方法。
處理和解析是徹底不一樣的概念,這就好像對於apache+php結合的網站來講,apache是應用服務器,php是中間件,apache只負責接 收/響應HTTP請求,php卻負責.php文件的解釋執行。Php將.php文件解釋執行完畢後,將生成的HTML代碼發送給apache,再由 apache將HTML代碼發送給客戶端。
另外說一下,擴展名rar並無在文件mime.types中出現,因此若是遇到能夠上傳rar文件且與php的結合方式爲module方式的apache,則能夠直接上傳相似「f4ck.php.rar」的文件來得到webshell。
解決方案一
在httpd.conf或httpd-vhosts.conf中加入如下語句,從而禁止文件名格式爲*.php.*的訪問權限:
<FilesMatch ".(php.|php3.|php4.|php5.)"> Order Deny,Allow Deny from all </FilesMatch>
解決方案二
若是須要保留文件名,能夠修改程序源代碼,替換上傳文件名中的「.」爲「_」:
$filename = str_replace('.', '_', $filename);
若是不須要保留文件名,能夠修改程序源代碼,將上傳文件名重命名爲時間戳+隨機數的格式。
總結:網上說的「低版本的apache存在未知擴展名解析漏洞」的說法是錯誤的,正確的說法應該是使用module模式與php結合的全部版本 apache存在未知擴展名解析漏洞,使用fastcig模式與php結合的全部版本apache不存在此漏洞。而且,想利用此漏洞必須保證文件擴展名中 至少帶有一個「.php」,不然將默認被做爲txt/html文檔處理。