文件上传之闯关
https://github.com/c0ny1/upload-labs
黑名单
第一关 修改html代码

# 游览器F12 删除 onsubmit 提交校验的语句,绕过前端限制 ,上传成功,shell拿到。

第二关 修改游览器的content-type的类型 绕过mime包检查

#后台代码判断 依据content-type 的文件类型,不符合的文件类型,不通过
# if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif'))
#
修改游览器content-type 的文件类型,欺骗后端的逻辑认证。
第三关 上传特殊可解析后缀
黑名单: 不允许文件类型的文件上传。php asp py
白名单: 只允许某一种或者几种文件的上传 比如 mime类型 TXT tar jpg等等
不论白名单或者黑名单,如何绕过?都是绕过检测的手段。
黑名单的绕过就是 保证上传到文件和限制文件的类型不同,同时又能让web服务器的命令解释器解析执行。
(比如 一个webshell.php变形123.php3 ,同时 命令解释器还可以执行123.php3)
白名单的绕过就是 保证上传到文件和限制文件的类型相同,同时又能让web服务器的命令解释器解析执行。
(比如 一个webshell.png变形123.png ,同时 命令解释器还可以执行123.png)
web服务环境:
windows iis
windows apache
windows nginx
linux apache or nginx
本pass禁止上传.asp|.aspx|.php|.jsp后缀文件!
明显一个黑名单的限制。
# php的配置可以识别 后缀名加数字的文件,比如 xx.php3 ,直接修改文件的后缀名,能绕过黑名单的限制



当前php的配置文件,无法解析php43,当成了静态文件返回了游览器。
如何修改php参数,让解释器执行这个php3这个文件,
# php的某一些低版本的解释器是具有可以解释php3这个中文件的设置。
php动态修改配置文件
第四关一个黑名单的限制 windows的iis特性 解析漏洞绕过。
提 示
关闭
本pass禁止上传.php|.php5|.php4|.php3|.php2|php1|.html|.htm|.phtml|.pHp|.pHp5|.pHp4|.pHp3|.pHp2|pHp1|.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后缀文件!
根据提示 代码把php asp 一些低版本的漏洞,过滤掉了。
针对黑名单,常见的就是 图片挂马
windows 上的iis服务解析漏洞
会自动把文件中的特殊字符 ; 分号后面的内容丢弃。文件系统接收到文件后会过滤文件名,
webshell.php 加上 ;.jpg 组合成一个jpg格式的文件 ,上传到服务器上后,变成 webshell.php;.jpg ----> webshell.php

我使用了另外一个 iis asp的环境模拟上传后的情况,查看webshell.asp;.jpg iis服务可以执行webshll.asp文件

windows+ php的特性
会自动把文件中的特殊字符 : 分号后面的内容丢弃。文件系统接收到文件后会过滤文件名,
webshell.php 加上 :.jpg 组合成一个jpg格式的文件 ,上传到服务器上后,变成 webshell.php;.jpg ----> webshell.php


证明: 使用windows 特殊符号不能应用于文件命名,使用:成功跳过逻辑代码。
但是文件创建了,PHP代码没有追加进去。
使用特殊的追加内容符号,把内容追加进去
123.< 123.<<< 123.>>> 123.>><
实验一下
测试使用.>>> 能够追加进去内容
正常访问到 webshell


第五关 windows 特性对大小写不敏感
不严谨的说法 就是在windows系统上 1.PHP 1.PHp 1.Php 1.php 是同一个文件
那么黑名单的状态不一定都能包含所有的文件的变形
所以上传 一个 大小写的文件 绕过黑名单 是可行。
实验
# 游览器是可以获取到webshell 的


第六关 利用windows特性 文件命名 特性绕过
后台代码对于来源文件名,统一改成小写后上传
使用windows 的文件命名特性 1.php . 混淆后缀名,让后台代码提取的后缀名是空值,
# windows文件系统写入文件的时候因为不允许空格 点的存在,会自动把1.php . ---变形成--》 1.php
实验正常 获取到正常的weshell

web.php::$DATA --特殊文件数据流
过黑名单 -- 利用文件命名的特殊性。
第七关 都是使用 点空格,或者空格点,混淆后缀名称,绕过黑名单
ubuntu 镜像下载
http://mirrors.aliyun.com/ubuntu-cdimage/releases/22.04/release
kali 镜像下载
https://mirrors.aliyun.com/kali-images/kali-2022.2/
rocky linux
https://rockylinux.org/download
历史版本下载
https://archive.kernel.org/
第八关 特殊文件数据流
web.php::$DATA --特殊文件数据流
过黑名单 -- 利用文件命名的特殊性。
成功上传 绕过

第九关 点 空格 点 windows特性,后缀混淆
第十关 后台代码针对文件名称的后缀过滤机制
后台代码删除后缀名 的机制是 正则的匹配, 全部匹配成功后,删除匹配的
1.phpphpphpphp 针对字符的完全匹配删除,不存在匹配一次的就不匹配了
1.phphpp ---- > 把php 分段隔开,完全匹配不上即可

对于文件名和后缀都在匹配的规则下

白名单
第十一关 url数据包头 %00截断
PHP软件版本要低5.3.4一下,magic_quotes_gpc 关闭,才能实现这个漏洞-- 一般老网站才有这种漏洞

# 不严谨的说法 可以这么理解
在上传目录中不光可以利用windows 文件的命名的特性
也可以使用windows 目录命名的特性
比如在拼接文件目录的时候,http://127.0.0.1/user/abc.txt%00
在网络传输协议中,能够使用的特殊符号是因为游览器使用的url编码格式
windows文件系统的命名规则中没有和url编码 不兼容,所以就会存在目录和文件命名 不一样的现象出现。
比如目录拼接 123%00 这个字符串,操作系统命名目录时或者文件时,会自丢弃%00
# 严谨的说法
'''
%00截断 是使用在网络传输中的,网络传输使用使用ascll表进行编码的
在ascll编码中 %00 在编码中是0 的意思,而ascll表又把零 作为特殊字符保留,,作为字符串的结束含义,所以在url中出现%00 时,就代表url已经全部读取完毕了,所以称为00截断
0x00 是linux中的截断
/00 也是一种截断
'''
问题: post http://127.0.0.1/user/123.php%00
实验完全成功
# POST 请求的路径中有在最后一个/ 后,就是文件名称+%00截断,没有该文件,会被新建,所携带的数据会被追加到该文件中。

第十二关 url 数据体 16进制00 截断
在 POST请求中, url 的请求头中没有具体的文件名,那么就一定在数据体中,针对请求体的修改让数据进行截断。达到上传到目的。
看图一 数据体中包含 form表单的 包含文件名称
单纯的修改请求体数据没有用,因为url 发送要进行编码,所以好的做法是进行16进制编码进行修改

请求体中找到手动写入一个文件名称,空一个空格,为填入隔断符,创造条件

观察 16进制 编码定位 空格,

20 这个位置就是空格,更改为 16进制的 00截断

空格已经被替换了

上传成功!shell 正常访问

此关开始组合手法上传
第十三 十四 十五关 上传文件内容检查 -- getinmagesize exif_imagetype 函数
随着对文件的校验的等级不断升级,单纯的对文件的类型判断满足不了,需求更新手段
对于文件来说,每一种类型的文件 通常的内容开头的值是不变的,比如
图片开头值是xxxx ,那么后台代码decode 文件开头的数据, 对比是否一致确实是图片类型,才予以放行。
还有的做法是 把文件全部解码以后,对文件所有的内容进行扫描关键字,匹配,然后才放行。
'''
JPEG (jpg), 文件头:FFD8FF
PNG (png), 文件头:89504E47
GIF (gif), 文件头:47494638 GIF89a
TIFF (tif), 文件头:49492A00
Windows Bitmap ( bmp),文件头:424D
CAD (dwg), 文件头:41433130
Adobe Photoshop (psd), 文件头:38425053
Rich Text Format (rtf), 文件头:7B5C727466
XML (xml), 文件头:3C3F786D6C
HTML (html), 文件头:68746D6C3E
Email [thorough only] (eml), 文件头:44656C69766572792D646174653A
Outlook Express (dbx), 文件头:CFAD12FEC5FD746F
Outlook (pst), 文件头:2142444E
MS Word/Excel (xls.or.doc), 文件头:D0CF11E0
MS Access (mdb), 文件头:5374616E64617264204A
WordPerfect (wpd), 文件头:FF575043
Adobe Acrobat (pdf), 文件头:255044462D312E
Quicken (qdf), 文件头:AC9EBD8F
Windows Password (pwl), 文件头:E3828596
ZIP Archive (zip), 文件头:504B0304
RAR Archive (rar), 文件头:52617221
Wave (wav), 文件头:57415645
AVI (avi), 文件头:41564920
Real Audio (ram), 文件头:2E7261FD
Real Media (rm), 文件头:2E524D46
MPEG (mpg), 文件头:000001BA
MPEG (mpg), 文件头:000001B3
Quicktime (mov), 文件头:6D6F6F76
Windows Media (asf), 文件头:3026B2758E66CF11
MIDI (mid), 文件头:4D546864
'''
# 破解这种手段的方式,就是图片 + 木马整合成一个文件,进行把木马的字符串和图片的字符串进行交融杂糅,既让文件能够显示,又能绕过后台的检测机制,木马又能正常使用
具体的方式
#1、粗暴做法, 把木马的代码追加到文件的最后,躲避文件头的检测
使用 copy /b 1.png/b muma.php/b 000.png 以二进制的方式整合成一个png文件 ,然后在结合利用 文件命名或者url编码 或者请求截断的方式,把后缀名更改成php
比如 123.php.jpg ----- 上传到服务端是123.php
逆向思维讲: 解释在 webshell.php木马中添加 图片属性的标志字符串,变形成 webshell.php.jpg 混淆服务端的检测,通过截断方式上传到服务端为webshell.php
#2、使用工具注入一句话木马 只是混淆服务端的检测的升级手段 ,无论怎么变形,该文件必须能被php解释器执行。
使用工具把把木马程序随机的 注入到图片文件中的任意位置,躲避检查,提高上传成功的几率
此关 要求能上传即可 过关,
function 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;
}
# 分析一下代码 getReailFileType函数 提取文件的2字节和自己的类型库做对比,作为新建文件的类型
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$temp_file = $_FILES['upload_file']['tmp_name'];
$file_type = getReailFileType($temp_file);
if($file_type == 'unknown'){
$msg = "文件未知,上传失败!";
}else{
$img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").".".$file_type;
if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true;
} else {
$msg = "上传出错!";
}
}
}
# 把上传的文件读到临时文件中,以上传目录/ 10-99随机数--时间. func抓的内容的类型 。
'''
如何获取webshell
因为文件的数据没有被改变,只是文件的后缀名被改了
要想办法 让php 识别gif文件就是 php 文件就能到达shell
'''
第十六关 二次渲染
梳理一下文件上传的流程防范流程
1、前端页面对文件进行限制 代码删除
2、post 请求中 截断 请求头 请求体
3、利用系统文件命名特性,软件命名特性 ,游览器编码特性,使文件落地到系统中发生变形
以上方式都被防御后,针对内容变异
4、 注入标准文件头,绕过类型检测
5、文件内容的检测
针对文件内容进行二次渲染
大白话就是 把一句话木马或者其他代码 通过各种方式,各种编码注入到文件的不同位置去,
,
比如 使用 100个图片,分别注入一句话,哪个能够欺骗绕过,那么这个图片就代表注入成功 -- 笨方法
第十七关 文件上传的时间竞争
根据网站的规模不断的壮大,从原本的单机架构,到集群架构演变,CDN,负载均衡,反向代理,缓存系统,读写分离,MHA主从数据库等。
在为了追求效率的情况下,越来越多的文件上传对于代码检测的压力越来越大,相对的文件检测不再是实时性,变成异步检测 ,
具体的做法是 后台代码会文件做一个简单的检查,放到临时目录中,然后再去做内容检查,如果检查到恶意代码的话就会被删除。
'''
所以上传文件的数量和访问文件的时间 与 后台查杀代码,做一个时间的赛跑
上传文件的并发量足够的大,使检查代码的队列处于满载状态,就能做到,
使用测试器 并发发包
使用测试器 并发请求访问的文件内容就 是创建一个木马文件,创建的文件逻辑代码不会检查,所以就能够是使用shell
'''

第十八关 重命名竞争
apache 低版本对于 文件解析的漏洞
当一个文件 test.php.7z 时,他的判断逻辑是从右到左的,7z不认识,那就跳过,检查到php时,认识,那么就会把 这个文件当做 php文件进行解析。
所以这个shell 能够使用。



第十九关 二进制 00 截断
抓包, 文件名 00截断

第二十关 代码审计相关 (不会,保留!)
htacess文件
在上述渗透过程中,一般过白名单的方式,基本都是利用 系统 、软件的命名规则使 文件的后缀名变成 php
那么有没有方式让 iis nginx apache 自动认为不同后缀的文件都当成php文件来解析那
ok 那就是htaccess文件 (分布式配置文件) 能够让apache 识别不同后缀的文件当做 php文件解析 ,跟 7z文件有这异曲同工之妙。
.htaccess
'''
<FilesMatch "">
setHandler application/x-httpd-php
</FilesMatch>
'''

浙公网安备 33010602011771号