盡最大可能分析上傳源碼及漏洞利用方式

0x00 簡單源碼分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?php
if ((( $_FILES [ "file" ][ "type" ] == "image/gif" )       //檢測Content-type值
|| ( $_FILES [ "file" ][ "type" ] == "image/jpeg" )
|| ( $_FILES [ "file" ][ "type" ] == "image/pjpeg" ))
&& ( $_FILES [ "file" ][ "size" ] < 20000))              //檢測文件大小
   {
   $ext = end ( explode ( '.' , $_FILES [ "file" ][ "name" ]));  //獲取最後「.」的後綴
   if ( $ext === 'php' )                          //檢測是否爲php後綴
     {
     exit ( 'error' );
     }
   if ( $_FILES [ "file" ][ "error" ] > 0)           //返回上傳錯誤碼
     {
     echo "Return Code: " . $_FILES [ "file" ][ "error" ] . "<br />" ;
     }
   else                                                  //返回上傳成功信息
     {
     echo "Upload: " . $_FILES [ "file" ][ "name" ] . "<br />" ;
     echo "Type: " . $_FILES [ "file" ][ "type" ] . "<br />" ;
     echo "Size: " . ( $_FILES [ "file" ][ "size" ] / 1024) . " Kb<br />" ;
     echo "Temp file: " . $_FILES [ "file" ][ "tmp_name" ] . "<br />" ;
 
     if ( file_exists ( "upload/" . $_FILES [ "file" ][ "name" ]))  //檢測文件是否存在
       {
       echo $_FILES [ "file" ][ "name" ] . " already exists. " ;
       }
     else                          //將上傳的臨時文件轉移到指定存放文件夾
       {
       move_uploaded_file( $_FILES [ "file" ][ "tmp_name" ],
       "upload/" . $_FILES [ "file" ][ "name" ]);
       echo "Stored in: " . "upload/" . $_FILES [ "file" ][ "name" ];
       }
     }
   }
else
   {
   echo "Invalid file" ;              //返回無效文件的錯誤信息
   }
?>

0x01 詳細分析過程

1) 直接使用用戶上傳文件名,沒有過濾特殊字符,存在漏洞php

1
2
3
4
5
6
7
8
9
10
11
12
if ((( $_FILES [ "file" ][ "type" ] == "image/gif" )            //文件類型檢測
|| ( $_FILES [ "file" ][ "type" ] == "image/jpeg" )
|| ( $_FILES [ "file" ][ "type" ] == "image/pjpeg" ))
&& ( $_FILES [ "file" ][ "size" ] < 20000))
   {
   $ext = end ( explode ( '.' , $_FILES [ "file" ][ "name" ]));  //文件後綴檢測
   if ( $ext === 'php' ){
     
     exit ( 'error' );
   }
 
       ......                                      //省略了中間的一些代碼

如下代碼的做用是,將上傳到臨時文件夾的文件移到upload的目錄下html

1
2
3
4
5
6
else                                            
  {
  move_uploaded_file( $_FILES [ "file" ][ "tmp_name" ],
  "upload/" . $_FILES [ "file" ][ "name" ]);
  echo "Stored in: " . "upload/" . $_FILES [ "file" ][ "name" ];
  }

1.1分析:web

從以上代碼能夠看出,能夠上傳圖片文件,對文件拓展名檢測是經過end(explode(‘.’,$_FILES[「file」][「name」]))函數實現(在這裏先不說文件類型驗證的問題)explode(‘.’,$_FILES[「file」][「name」])用來把上傳的文件名做爲字符串,以.(點)來分割字符串來生成數組,而end()函數則是將數組內部指針指向最後一個元素,並返回該元素的值,例如,當上傳x.php文件時,最終就會獲取到php。shell

而對於$_FILES裏面獲取變量,是直接來自http request請求,它跟普通獲取其它get,post變量同樣。 好比在post上傳時,咱們能夠經過抓包來截獲(經常使用神器burpsuite)這一過程,因爲在上傳的檢測中沒有對文件名進行檢測和過濾及處理,所以,咱們能夠將name構造一個特殊文件名,而後,再將post數據提交,就能夠達到上傳繞過對文件擴展名的檢測。apache

1.2利用:數組

好比咱們能夠在本地上將一個php文件命名爲x.php.jpg在上傳文件時,抓包post,將filename修改成x.php\0.jpg再提交post數據,那麼在保存咱們修改後的文件時,\0後面的全部字符將(如.jpg)被自動截斷,最終生成咱們想要目標文件格式(如本例的x.php),以致於能夠上傳任意惡意的php腳本。從網上獲得說明Php4的版本能夠利用這個漏洞,php5版本以上會自動過濾掉’」/0」,另外不少asp,jsp也存在此類截斷上傳的漏洞。安全

2)文件類型驗證不嚴格,存在漏洞服務器

1
2
3
4
5
6
7
8
9
10
<?php
if ((( $_FILES [ "file" ][ "type" ] == "image/gif" )
|| ( $_FILES [ "file" ][ "type" ] == "image/jpeg" )
|| ( $_FILES [ "file" ][ "type" ] == "image/pjpeg" ))
&& ( $_FILES [ "file" ][ "size" ] < 20000))
   {
   $ext = end ( explode ( '.' , $_FILES [ "file" ][ "name" ]));
   if ( $ext === 'php' ){  
     exit ( 'error' );
   }

2.1分析:app

從代碼能夠看出是經過讀取文件的type直接來作文件類型的判斷,一樣咱們能夠經過抓取post數據,將Content-type值修改成容許上傳的MIME類型,在這裏有image/gif等三種,從而繞過對文件type的檢查,雖然以後代碼對文件擴展名進行了檢測(那兩個個函數對文件擴展名檢測的大慨過程就是判斷文件名最後」.」的最後字符,example.php.bak最終獲得是bak),並判斷是不是php後綴名。jsp

2.2利用:

1.若是沒有對apache默認支持解析文件方式進行修改時(即apache解析漏洞,不少網站管理員因爲安全意識薄弱或其餘狀況每每沒有修改),那麼在繞過對type的檢測以後,最簡單的利用方式就是咱們能夠直接上傳一個惡意的名爲x.php.ext,這裏的ext能夠是多種,只要不是php和apache能夠解析其餘擴展名(如txt後綴)就能夠,那麼按照apache默認從右往左直到遇到可支持解析的文件的解析方式,那麼就會把x.php.ext當成x.php來解析。

2.在繞過對文件type檢查以後,咱們還能夠將本地的x.php文件修改成x.php1,x.php3,x.php4或者x.php5再上傳,默認的apache服務器將會解析爲php。

3)使用php的全等於來判斷是否爲php文件類型,存在漏洞

1
2
3
4
$ext = end ( explode ( '.' , $_FILES [ "file" ][ "name" ]));
if ( $ext === 'php' ){    
     exit ( 'error' );
   }

3.1分析:

咱們知道在php語法中全等於」===」的做用是先判斷等號左右兩邊的數據類型是否同樣,再判斷等號兩邊的值是否相等,若是都相等返回true,否者返回false。

3.2利用:

在明白全等於」===」的判斷原理以後,咱們就能夠進行利用了,仍是以本地的x.php舉例,咱們能夠將x.php修改成Php, x.PHp, PHP...在繞過對type的檢測以後再上傳,以上傳的x.PHP來分析,首先上傳截獲到的是PHP後綴,此時$ext=PHP,再將進行下一步的驗證,$ext和php都是相同的數據類型,可是在驗證它們值時卻不相等,從而繞過上傳。

而默認的web應用程序都是默認將Php,x.PHp,PHP...解析爲php執行。

4)對上傳文件內容沒有作檢測,存在漏洞

4.1分析:

從upload.php源代碼分析來看,在整個過程沒有對上傳文件內容進行檢測,過濾和處理,能夠經過上傳圖片木馬或其餘方式來到達惡意上傳的目的。

4.2利用:

1.若是的網站是用Nginx的Web應用程序且版本 <8.03,那咱們就能夠利用Nginx默認開啓Fast-CGI而形成的畸形解析漏洞,如下是具體利用方式說明。在默認Fast-CGI開啓情況下,咱們能夠上傳一個名爲x.jpg,其內容爲

1
<?PHP fputs ( fopen ( 'shell.php' , 'w' ), '<?php eval($_POST[cmd])?>' );?>

的文件,以後咱們再訪問x.jpg/.php這個網站路徑,在這個目錄下就會生成一句話木馬shell.php。

2.若是的網站是用Nginx的Web應用程序且版本在(0.5.,0.6.,0.7,0.8<=0.7.65<=0.8.37)其中,那咱們還能夠利用Nginx空字節代碼執行漏洞來達到上傳任意惡意代碼並執行。具體利用方法是:將x.jpg圖片中嵌入PHP代碼而後經過訪問x.jpg%00.php來執行其中的惡意代碼。

3.若是網站的Apache Web應用程序中.htaccess可被執行且可被上傳,那能夠嘗試在.htaccess中寫入:
<FilesMatch "example.jpg"> SetHandler application/x-httpd-php 
這段代碼的意思就是將把目錄下的全部後綴爲jpg的文件當作可執行的php腳本進行解析並執行。所以,咱們能夠上傳一個x.jpg的木馬, 這樣x.jpg就可解析爲php文件。

轉載請註明來自4ido10n's Blog文章《盡最大可能分析上傳源碼及漏洞利用方式》

相關文章
相關標籤/搜索