目录
- 1. 正文
- 1.1. 文件上传常见验证
- 1.2. 简要上传表单代码分析解释
- 2. 示例-以Uploadlabs为例
- 2.1. pass02
- 2.2. pass-3
- 2.3. pass-4
- 2.4. pass-5
- 2.5. pass-6
- 2.6. pass-7
- 2.7. pass-8
- 2.8. pass-9
- 2.9. pass-10
- 2.10. pass-11
- 2.11. pass-12
- 2.12. pass-13
1. 正文
1.1. 文件上传常见验证
后缀名,类型、文件头等
后缀名:黑名单、白名单(属于直接方法)
黑名单:明确禁止上传的文件后缀。若记录不全,则根据不禁止的全都允许规则,利用其它后缀达到上传,限于个别情况
白名单:明确允许上传的文件后缀。相对于黑名单更安全
文件类型:MIME信息(属于间接方法)
根据数据包中Content-type
获取数据类型MIME (Multipurpose Internet Mail Extensions) 是描述消息内容类型的标准,用来表示文档、文件或字节流的性质和格式
根据HTTP数据包content-type自动判断类型,不可靠,因为可抓包修改
文件头:内容头信息(属于间接方法)
每个文件的根本数据为二进制,拥有相应的文件头,亦可以抓包修改
1.2. 简要上传表单代码分析解释
摘自:PHP $_FILES函数详解
$_FILES数组内容如下:
$_FILES['myFile']['name']
客户端文件的原名称。
$_FILES['myFile']['type']
文件的 MIME 类型,需要浏览器提供该信息的支持,例如"image/gif"。
$_FILES['myFile']['size']
已上传文件的大小,单位为字节。
$_FILES['myFile']['tmp_name']
文件被上传后在服务端储存的临时文件名,一般是系统默认。
$_FILES['myFile']['error']
和该文件上传相关的错误代码
<?phpecho $_FILES['userfile']['name'];echo $_FILES['userfile']['name'];echo $_FILES['userfile']['type'];echo $_FILES['userfile']['size'];echo $_FILES['userfile']['tmp_name'];echo $_FILES['userfile']['error'];
?><form enctype="multipart/form-data" action="" method="POST"><input name="userfile" type="file" /><input type="submit" name="submit" value="upload" />
</form>
表单根据FILES读取的属性值,可做出相应的判断过滤操作
2. 示例-以Uploadlabs为例
大量php函数需要查询
Uploadlabs整与2022年夏季,与迪师傅网课时年代版本排版不同
2.1. pass02
MIME绕过
抓包修改Content-type
2.2. pass-3
$deny_ext = array('.asp','.aspx','.php','.jsp');$file_name = trim($_FILES['upload_file']['name']); // 移除字符串两侧的空白字符或其他预定义字符。$file_name = deldot($file_name);//删除文件名末尾的点$file_ext = strrchr($file_name, '.'); // 搜索 点 在字符串中的位置,并返回从该位置到字符串结尾的所有字符,即后缀$file_ext = strtolower($file_ext); //转换为小写$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA$file_ext = trim($file_ext); //首尾去空
检测文件后缀是否在黑名单中
“https://zhuanlan.zhihu.com/p/57847225”
搭建平台的特性
其他格式执行出其他效果,取决于平台的功能配置
php3
防止平台未开放其他脚本的解析功能,上传文件时最好上传同于搭建网站的脚本语言
2.3. pass-4
.heaccess解析只有apace可用
.htaccess文件(或者"分布式配置文件"),全称是Hypertext Access(超文本入口)。
提供了针对目录改变配置的方法, 即,在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录。
作为用户,所能使用的命令受到限制。管理员可以通过Apache的AllowOverride指令来设置
<!--首先上传文件名为 .heaccess 的文件,文件内容如下-->
<FilesMatch "shana">
Sethandler application/x-httpd-php
</FilesMatch >
意为上传的文件名中含有cimer的,均视为php执行,但需要打开配置文件中的开关
理论如上,焯,为什么我没成功
2.4. pass-5
啊官网上关于.user.ini的介绍
神秘的.user.ini文件
关于php网站可以上传的配置文件: heaccess 、.user.ini。根据黑名单列表,选择上传 ini文件
引发 .user.ini 解析漏洞需要三个前提条件
- 服务器脚本语言为PHP
- 服务器使用CGI/FastCGI模式
- 上传目录下要有可执行的php文件
网站上传根目录存有 readme.php 文件
上传文件
# 对当前文件夹下所有文件头拼接5.jpg 文件
auto_prepend_file=5.jpg
# 对当前文件夹下所有文件尾部拼接5.jpg 文件
auto_append_file=5.jpg
# 以上选一
上传 5.jpg 为脚本代码
访问readme.php ,执行php脚本同时执行拼接上的 5.jpg
2.5. pass-6
# 缺少大小写转化
$file_ext = strtolower($file_ext); //转换为小写
windows文件不区分大小写,即可修改文件后缀大小写突破黑名单
2.6. pass-7
# 缺少首尾去空
$file_ext = trim($file_ext); //首尾去空
windows文件后缀自动去掉末尾空格,即不存在1.txt
数据包中可以添加空格成1.txt
,即文件后缀带有空格部分,但上传成功后操作系统回去除空格
2.7. pass-8
# 缺少过滤文件末尾的点$file_name = deldot($file_name);//删除文件名末尾的点
文件名添加点意为文件类型为php.
,通过黑白名单检索
2.8. pass-9
# 缺少去除::$DATA
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
补充知识:php在window的时候如果文件名+“:: D A T A " 会把 : : DATA"会把:: DATA"会把::DATA之后的数据当成文件流处理,不会检测后缀名,且保持”::$DATA"之前的文件名 他的目的就是不检查后缀名。
2.9. pass-10
过滤函数使用与pass-3一致,pass-03使用白名单,pass-10使用黑名单
$file_name = deldot($file_name);//删除文件名末尾的点
# 该函数定义如下: 即从字符串的尾部开始,从后向前删除点. ,直到该字符串的末尾字符不是. 为止。(来自百度)
从后向前删除点.
,直到该字符串的末尾字符不是.
为止,因此得到的文件后缀应该是空格
2.10. pass-11
# file_name中含有在deny_ext中的后缀替换成空
$file_name = str_ireplace($deny_ext,"", $file_name);
str_ireplace() 函数替换字符串中的一些字符(不区分大小写)
本题过滤文件后缀名中的敏感后缀,过滤分为两种循环过滤和一次过滤
- 循环过滤将持续每次逐字符检索连续的php字符
- 一次过滤只进行一次
pass-11使用str_ireplace() 进行了一次过滤
2.11. pass-12
$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);
# substr() 截取字符串某位置开始后的剩下字符串
# strrpos() 函数查找字符串在另一字符串中最后一次出现的位置。
# 综上因该是获取后缀名
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
# . 为拼接符, 从save_path参数获取存放路径
# img_path 拼凑一个新的文件名
if(move_uploaded_file($temp_file,$img_path)){$is_upload = true;
}
php的一些函数的底层是C语言,而move_uploaded_file就是其中之一,遇到0x00会截断,0x表示16进制,URL中%00解码成16进制就是0x00。
- %00截断:地址上的拦截
- 0x00,文件命名上的截断
由于从save_path参数获取存放路径,因此可以添加截断掉符号。修改数据包中准备存放文件的路径值参数
upload7.php%00/2131254112.jpg
%00 为解码后为 '\0',在字符串中意为字符串结尾符
前提条件需要关闭magic_quotes_gpc以防止对提交参数的转义且php版本<5.3.4
直接访问新名字1.php
2.12. pass-13
同pass-12截断,pass-13截断的存储路径在post提交数据中
get提交会将数据中的url编码自动解码,post并无此过程,因此需要手动解码
目前这一关卡在同迪师傅相同地点
upload-labs通关记录