ctf-web:关于文件上传漏洞的深入研究

上次我们研究了关于文件上传的漏洞,这次我们研究的内容属于上节课的补充内容,大约是关于文件上传的绕过与防御.
怎么说呢,算是一种锻炼吧.
因为下个月有个awd的比赛,因此最近会经常发一些关于web的内容.
其实我还是挺慌的,因为以前参加的都是ctf线上赛,而且我做的都是逆向这个方面的,然而这次突然来了个web,搞得我有点懵.
web也是最近才开始研究的,所以写的可能不尽人意,希望各位大佬看看就好,不喜勿喷.

一.实验环境

我们这次的实验依然用的是上次的网站和phpstudy.我发在了下面.
1.upload-file.html

<html>
<head>
 <title> 文件上传之解析漏洞~phptitle>
 head>
<body>

<form action="upload.php" method="post"
enctype="multipart/form-data">
<label for="file">Filename:label>
<input type="file" name="file" id="file" /> 
<br />
<input type="submit" name="submit" value="提交" />
form>

body>
html>

2.upload.php



  if ($_FILES["file"]["error"] > 0)
    {
    echo "Return Code: " . $_FILES["file"]["error"] . "
"
; } else { echo "Upload: " . $_FILES["file"]["name"] . "
"
; echo "Type: " . $_FILES["file"]["type"] . "
"
; echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb
"
; echo "Temp file: " . $_FILES["file"]["tmp_name"] . "
"
; 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"]; } } ?>

另外记得在网站目录下新建一个文件夹,名字叫upload.三个文件如图
ctf-web:关于文件上传漏洞的深入研究_第1张图片

运行后如图
ctf-web:关于文件上传漏洞的深入研究_第2张图片
随便上传一个文件
ctf-web:关于文件上传漏洞的深入研究_第3张图片
upload文件夹可看到上传的文件
ctf-web:关于文件上传漏洞的深入研究_第4张图片
好了,基础环境如图搭建完成.
正常的下一步就是使用中国菜刀等软件进行连接,为了节省时间我就不测试了.

二.网站后台上传文件脚本的解析

首先我们先来解析一下这个php脚本.我直接把注释写在下面了,好好看看.
upload.php



  if ($_FILES["file"]["error"] > 0)
    {
    echo "Return Code: " . $_FILES["file"]["error"] . "
"
; } //这个使用了php里面的超全局变量_FILES.首先进行了一个判断,只要出现错误就在屏幕上显示错误代码. else { echo "Upload: " . $_FILES["file"]["name"] . "
"
; echo "Type: " . $_FILES["file"]["type"] . "
"
; echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb
"
; echo "Temp file: " . $_FILES["file"]["tmp_name"] . "
"
; //在屏幕上显示文件的相关信息,比如路径什么的 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"]; //显示文件储存相关位置信息 } } //和上一个if配套,文件在不出错的情况会执行else里面的内容 ?>

根据分析我们可以看出,网站后台对于上传的限制真的是一点都没有,活该被攻破.因此,我们要研究一下,如何进行防御?

三.对于上传文件的过滤

为了防止黑客将恶意代码,如一句话木马,我们就要对上传的文件进行一个过滤.
当然,下面写的都是我第一次认识文件上传的时候产生的一些想法,所以可能比较简陋.大家稍微看看吧.

1.检查文件名称

其实这个是没啥用的,因为正常人是不会直接上传脚本文件,而是会进行一些修改.不过为了预防一些傻子,表面工作还是要做一下的.
所以,我们直接写一个检查文件类型的条件判断即可.



  if ($_FILES["file"]["error"] > 0)
    {
    echo "Return Code: " . $_FILES["file"]["error"] . "
"
; } else { echo "Upload: " . $_FILES["file"]["name"] . "
"
; echo "Type: " . $_FILES["file"]["type"] . "
"
; echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb
"
; echo "Temp file: " . $_FILES["file"]["tmp_name"] . "
"
; if (file_exists("upload/" . $_FILES["file"]["name"])) { echo $_FILES["file"]["name"] . " already exists. "; } //由于我们要对文件进行过滤,因此我们要把代码加在这个地方.多写一个判断条件就行了.假设我们的网站仅仅允许上传图片类型的文件 elseif($_FILES["file"]["type"]!="image/png"&&$_FILES["file"]["type"]!="image/jpeg"&&$_FILES["file"]["type"]!="image/jpg"){ echo "error ! your file type is not image,png,jpeg,jpg."; } else { move_uploaded_file($_FILES["file"]["tmp_name"], "upload/" . $_FILES["file"]["name"]); echo "Stored in: " . "upload/" . $_FILES["file"]["name"]; } } ?>

这个是我添加的代码:

elseif($_FILES["file"]["type"]!="image/png"&&$_FILES["file"]["type"]!="image/jpeg"&&$_FILES["file"]["type"]!="image/jpg"){
      echo "error ! your file type is not image,png,jpeg,jpg.";
    }

我进行了一个额外的对文件类型的判断,当文件类型不是图片的三种特定格式时,就会报错.我们可以进行一下实验,看看现在是否有了一定的安全性.
先实验第一个图片,这个是我随便百度的.
ctf-web:关于文件上传漏洞的深入研究_第5张图片
将这个文件进行上传,发现没有问题,并且在upload文件夹下发现上传的文件.
ctf-web:关于文件上传漏洞的深入研究_第6张图片
ctf-web:关于文件上传漏洞的深入研究_第7张图片
接着,我还是像开始一样直接上传php文件,这次可以看到如图的结果.
ctf-web:关于文件上传漏洞的深入研究_第8张图片

显然我们是成功了.但是,我对文件进行了修改,把后缀改成了.png结尾,结果如图.
ctf-web:关于文件上传漏洞的深入研究_第9张图片
我甚至内容都没变,就改了个后缀,就成功了…说实话,就是用来骗傻子的.所以我们还得想想新的办法.

2.读取文件前某些字节进行判断文件类型

这个方法我就不上截图了,我就进行一个简单的介绍吧.由于我们上一步直接进行了一个修改后缀名就将文件发了上去,所以感觉拿个方法其实没啥用.
因此,我想了一下如果,我们读取文件的某些字节数,然后进行一个判断.
就类似于像我们正常直接打开文件以后,直接看文件,是不是就能看出来是不是恶意代码?
我就不直接写代码了,连接附上.
php如何通过读取前两个字节然后判断文件类型
正如链接中所给的代码一样,我们可以对网站进行修改.
原谅我的懒,这个就当给你们留作一个思考空间了.

3.通过改写随机文件上传路径进行防御

这个也是我的一个构想.刚才百度了一下,也确实有这个方法.
实现的方法就是:
当用户上传了一个文件以后,我们可以使用随机函数创建一个文件夹,然后将文件名也随机进行修改,之后放到这个产生的随机文件夹里.
这样就让用户使用比如中国菜刀之类的软件链接的时候产生了困扰,因为在访问的时候,不知道该访问哪里,自然也就无法进行获取shell.
相信看到这里你们应该已经想到了上面代码其实还有一个比较大的漏洞,就是直接显示了上传以后的文件位置.为了安全期间,应该删除代码里面的显示文件位置的代码.
另外更狠的是,写一个额外的线程,通过计数,每10秒更改一次上传文件的位置,这样就更加有效的进行了防御.

4.禁止此文件执行脚本

这个应该是最有效的方法了.在你的服务器就可以进行设置.
当这个文件连执行权限都没有,那么谈何进行执行呢?

好了,大概就写这么多吧.关于文件上传的漏洞我能想到的暂时就这么多

你可能感兴趣的:(ctf-web,php)