天天看点

网站常见漏洞 -- 文件上传漏洞

任意文件上传漏洞

文件上传漏洞(File Upload Attack)是由于文件上传功能实现代码没有严格限制用户上传的文件后缀以及文件类型,导致允许攻击者向某个可通过 Web 访问的目录上传任意PHP文件,并能够将这些文件传递给 PHP 解释器,就可以在远程服务器上执行任意PHP脚本。

一套web应用程序,一般都会提供文件上传的功能,方便来访者上传一些文件。

 下面是一个简单的文件上传表单 

<form action="upload.php" method="post" enctype="multipart/form-data" name="form1"> 

<input type="file" name="file1" /><br /> 

<input type="submit" value="上传文件" /> 

<input type="hidden" name="MAX_FILE_SIZE" value="1024" /> 

</form> 

php的配置文件php.ini,其中选项upload_max_filesize指定允许上传的文件大小,默认是2M 

$_FILES数组变量 

PHP使用变量$_FILES来上传文件,$_FILES是一个数组。

如果上传test.txt,那么$_FILES数组的内容为: 

$FILES 

Array 

  [file] => Array 

   {

     [name] => test.txt                            //文件名称 

     [type] => text/plain                          //MIME类型 

     [tmp_name] => /tmp/php5D.tmp                   //临时文件 

     [error] => 0                                //错误信息 

     [size] => 536                               //文件大小,单位字节 

   }

}

如果上传文件按钮的name属性值为file 

<input type="file" name="file" /> 

那么使用$_FILES['file']['name']来获得客户端上传文件名称,不包含路径。使用$_FILES['file']['tmp_name']来获得服务端保存上传文件的临时文件路径

存放上传文件的文件夹 

PHP不会直接将上传文件放到网站根目录中,而是保存为一个临时文件,名称就是$_FILES['file']['tmp_name']的值,开发者必须把这个临时文件复制到存放的网站文件夹中。 

$_FILES['file']['tmp_name']的值是由PHP设置的,与文件原始名称不一样,开发者必须使用$_FILES['file']['name']来取得上传文件的原始名称。 

上传文件时的错误信息 $_FILES['file']['error']变量用来保存上传文件时的错误信息,它的值如下:

<a href="http://blog.51cto.com/attachment/201309/235554372.png" target="_blank"></a>

文件上传漏洞 

如果提供给网站访问者上传图片的功能,那必须小心访问者上传的实际可能不是图片,而是可以指定的PHP程序。如果存放图片的目录是一个开放的文件夹,则入侵者就可以远程执行上传的PHP文件来进行攻击。

下面是一个简单的文件上传例子:

&lt;?php 

// 设置上传文件的目录 

$uploaddir = "D:/www/images/"; 

// 检查file是否存在 

if (isset($_FILES['file1'])) 

// 要放在网站目录中的完整路径,包含文件名 

$uploadfile = $uploaddir . $_FILES['file1']['name']; 

// 将服务器存放的路径,移动到真实文件名 move_uploaded_file($_FILES['file1']['tmp_name'], $uploadfile);

?&gt; 

…… 

&lt;form method="post" enctype="multipart/form-data" name="form1"&gt;  

这个例子没有检验文件后缀,可以上传任意文件,很明显的上传漏洞。

利用此漏洞黑客克制自由上床任意的木马文件而导致网站失陷。

漏洞防护措施

解决上面所述问题的一种方法是通过检查上传文件的类型来限制用户的文件上传,如以下代码所示。 

if(isset($_POST["form"])) 

{

if($_FILES['upfile']['type'] == 'image/pjpeg')  //检查文件类型是否为JPEG 

$uploadfile = "upfiles/".$_FILES['upfile']['name'];

//上传后文件所在的文件名和路径 

move_uploaded_file($_FILES['upfile']['tmp_name'], $uploadfile); 

//上传文件 

print_r($_FILES);

die();

else

     die("上传文件的格式不正确!");

?&gt;

上面的代码要求用户上传的文件必须是JPEG类型的图片文件,彻底地避免了终端用户通过上传PHP脚本危害服务器的行为。

文件上传路径变量过滤不严

在许多论坛的用户发帖页面中存在这样的上传Form,如图7-27所示,其网页编程代码为:

  “&lt;form action="user_upfile.asp" ...&gt;

  &lt;input type="hidden" name="filepath" value="UploadFile"&gt;

  &lt;input type="file" name="file"&gt;

  &lt;input type="submit" name="Submit" value="上传" class="login_btn"&gt;

  &lt;/form&gt;”

在其中“filepath”是文件上传路径,由于网页编写者未对该变量进行任何过滤,因此用户可以任意修改该变量值。在网页编程语言中有一个特殊的截止符"\0",该符号的作用是通知网页服务器中止后面

的数据接收。利用该截止符可们可以重新构造filepath,例如正常的上传路径是:

  “http://www.***.com/bbs/uploadface/200409240824.jpg”,

  但是当我们使用“\0”构造filepath为

  “http://www.***.com/newmm.asp\0/200409240824.jpg ”

  这样当服务器接收filepath数据时,检测到newmm.asp后面的\0后理解为filepath的数据就止结束了,这样我们上传的文件就被保存成了:“http://www.***.com/newmm.asp”。

  利用这个上传漏洞就可以任意上传如.ASP的网页木马,然后连接上传的网页即可控制该网站系统。

  提示:可能有读者会想,如果网页服务器在检测验证上传文件的格式时,碰到“/0”就截止,那么不就出现文件上传类型不符的错误了吗?其实在检测验证上传文件的格式时,系统是从filepath的右边向左边读取数据的,因此它首先检测到的是“.jpg”,当然就不会报错了。

最安全的防范办法就是删除上传页面。

     本文转自Tar0 51CTO博客,原文链接:http://blog.51cto.com/tar0cissp/1286799

,如需转载请自行联系原作者