upload-labs writeup
Posted Nuy0ah
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了upload-labs writeup相关的知识,希望对你有一定的参考价值。
pass-1 js绕过
使用js在本地对文件进行校验
解决方法1:浏览器禁用js可实现绕过
解决方法2:bp抓包
将jpg改为php就可实现绕过
解决方案3:将网页下载下,删除过滤的js,在form提交表单中添加action属性,将其发送给原本应该正常发送的地址(查看请求头的URL)。这种方案可以解决一些判断文件以及提交文件都用js,从而导致无法抓包的问题
pass-2:MIME检验
if (($_FILES[\'upload_file\'][\'type\'] == \'image/jpeg\') || ($_FILES[\'upload_file\'][\'type\'] == \'image/png\') || ($_FILES[\'upload_file\'][\'type\'] == \'image/gif\'))
校验代码判断文件的type类型是否为jpg/png/gif三种格式之一
绕过方法1:先将php后缀改为jpg/png/gif三种其中之一,然后抓包改为php
绕过方法2:直接上传php文件,然后抓包修改数据包中Content-Type类型
pass-3:黑名单绕过
这一关提示
查看校验代码
绕过方法1:双写::\\(D::\\)DATAATA
校验代码只校验一次::$DATA所以可以双写绕过
::\\(DATA是window系统特有文件流,::\\)DATA可以绕过对文件上传的安全检查,image.php::$DATA上传以后在服务器会存储为image.php
绕过方法2:扩展名绕过
使用php5/php4/phtml等扩展名进行绕过
注:扩展名绕过需要在phpsstudy中的http.conf增加
版本太新的phpstudy即使添加了也不能上传成功,建议使用版本较早的版本
pass-4:.htaccess绕过
黑名单限制增加,但没有限制.htaccess
.htaccess 是一个 Apache Web 服务器的配置文件
名字内带有jpg的文件都以php格式解析
先上传.htaccess文件,在上传shell
pass-5 .user.ini绕过
.user.ini是一个配置文件,用于设置PHP运行环境中的各种配置设置。
.user.ini配置 使其自动包含shell.jpg文件到每个PHP文件的开头。
auto_prepend_file=shell.jpg
shell.jpg
<?php phpinfo();?>
先上传.user.ini再上传shell.jpg
pass-6:大小写绕过
校验代码相比之前少了,转换小写,搭建平台window对大小写不敏感
绕过方法1:大小写绕过
绕过方法2:双写::$DATA
pass-7 空格绕过
少了trim函数
直接后面添加空格进行绕过
pass-8 点绕过
没有使用函数deldot,在window中点和空格都是不被允许的
pass-9 ::$DATA绕过
直接::$DATA绕过
pass-10 点空格点绕过
这一关主要针对deldot函数进行绕过,deldot()函数从后向前检测,当检测到末尾的第一个点时会继续它的检测,但是遇到空格会停下来
遇到deldot()函数可以在后缀名后加入". .",这就是点空格点绕过,空格负责将deldot()停止,然后会被trim函数删除,但是会剩下一个点,上传到服务器,点也会被删除
pass-11:双写绕过
代码先创建一个黑名单,然后接收上传文件的后缀名,去除黑名单内的字符,但只进行了一次绕过,所以可以进行双写绕过
pass-12 %00截断
00截断条件:
php版本小于5.3.4
php的magic_quotes_gpc为OFF状态
服务器版本
审计代码
上传路径可控,使用get传参那就可以使用%00截断
pass-13 0x00截断
与12关代码大同小异,唯一不同的就是传递的存储路径由get改为post
get传参会经过编码,post不会,所以使用0x00截断
截断需要在十六进制中将传递的名字后面写为00
或者直接写%00然后对其进行url编码
pass-14 文件包含
getReailFileType函数读取文件前两个字节判断是否为jpg,png,gif其中之一
判断上传文件是否满足要求,满足则随机命名存入文件夹
制作图片马,直接在图片后插入
文件包含漏洞,接收get传入的file参数
访问url:include.php?file=upload/4620230414113629.png
pass-15 getimagesize()+ 文件包含
与十四关大同小异,只是换成getimagesize()来检查文件
getimagesize()函数用于获取图像大小及相关信息,成功返回一个数组,失败则返回 FALSE 并产生一条 E_WARNING 级的错误信息
直接上传图片马,然后访问url:include.php?file=upload/图片命名.jpg
pass-16 exif_imagetype()+文件包含
需要开启php_exif模块,否则会界面无法显示
exif_imagetype()函数:读取一个图像的第一个字节并检查其签名,如果发现恰当的签名返回一个对应的常量,否则返回false。返回值和getimagesize()返回值的数组中的索引2的值是一样的,但本函数快的多。
直接用之前图片马即可
pass-17 二次渲染+文件包含
代码使用imagecreatefromjpeg函数对图片进行渲染
我们可以先上传一个gif图片然后下载渲染过后的gif,二者使用010进行对比,查看有哪些地方是不会被渲染所更改的
然后在不会被渲染的地方添加phpinfo
成功上传
pass-18 条件竞争
根据代码可以看出,先将上传文件放到目录下,然后再进行条件判断,不满足白名单则删除
可以使用burp爆破模块,进行爆破,然后再不断访问上传脚本,只要访问到,就会打断代码删除文件的操作
不断访问
pass-19 条件竞争+apache未知扩展名解析漏洞
本关代码有点小问题,需要修改myupload.php
代码审计可知,跟18关大致类型一致,不过限制更加严格一些,思路是相同的,在文件被上传但还未重命名的时候访问
这是可以上传的后缀名单,这样就可以使用apache未知扩展名解析漏洞,遇到无法解析的后缀就往前挪一个
上传shell.php.7z
burp爆破
不断刷新访问
pass-20 move_uploaded_file()特性利用
代码审计可知先将文件上传然后判断传递的保存名称是否存在黑名单,不存在就将其移动到指定目录
由于代码没有对其进行严格的限制绕过,所以之前的大小写,空格,点,::$DATA均可以实现绕过,但由于之前关卡都考过,所以这肯定不是作者重点
move_uploaded_file()特性,会忽略掉文件末尾的 /.
上传后直接访问即可
pass-21 逻辑数组绕过
代码将上传文件名分割为数组形式然后进行判断
修改为数组形式上传
安全-Pass08之黑名单点绕过(upload-labs)
文章目录
前言
php
即Hypertext Preprocessor
超文本预处理器,多用于web
后端- BUUCTF的upload-labs在线靶场和本地的靶场有点差别,如果用文章的方法没法绕过时,注意看一下源码是否一致
相关介绍
其他介绍
一、题目
php
后端代码
<?php
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$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",".ini");
$file_name = trim($_FILES['upload_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); //首尾去空
if (!in_array($file_ext, $deny_ext)) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH.'/'.$file_name;
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '此文件类型不允许上传!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}
?>
二、WriteUp
[1]. 函数介绍
PHP函数 | 介绍 |
---|---|
file_exists(路径) | 判断指定的文件或目录是否存在,不存在返回true,否则返回false |
in_array(变量,数组) | 如果变量存在于数组就返回true,否则返回false |
isset(变量) | 如果变量存在且值不为null返回true,否则返回false |
move_uploaded_file(文件路径,文件夹路径) | 将文件移动到指定文件夹下 |
strrchr(字符串,字符) | 如果字符存在于字符串时,返回第一次找到的字符至字符串末尾的子串。不存在于字符串时就返回false |
strtolower(字符串) | 将字符串全部转换成小写 |
str_ireplace(字符串1,字符串2,字符串3) | 在字符串3中搜索,如果含有字符串1的子串就替换成字符串2 |
trim(字符串) | 删除字符串前后的空白符,空白符: 空格、制表符(\\t )、换行符(\\n )、回车符(\\r )、空字节符(\\0 )和垂直制表符(\\x0B ) |
[2]. 源码审计
(1). 变量判断
- 对
php
代码进行审计,if语句比较多最好从外往内分析- 第一条
if
语句只是判断了一下提交的post
请求中submit
参数是否被设置且非空
PHP:isset - Manual
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {//第一条if语句
//代码
}
(2). 路径判断
- 第二条语句判断了一下文件上传的路径存不存在,存在的话就执行里面的代码,不存在就给
$msg
设置回显信息- 通过
Seay
审计的全局搜索功能可以找到UPLOAD_PATH
是在config.php
中被定义的
Pass-02\\index.php
的代码中包含了上一级目录下的config.php
然后这个变量就可以在Pass-02\\index.php
中直接使用../
表示访问上一级的目录,所以upload-labs-master\\Pass-02\\index.php
包含的是upload-labs-master\\config.php
- 当
UPLOAD_PATH
变量在upload-labs-master\\Pass-02\\index.php
中被调用时,就会设置上传的父文件夹为upload-labs-master\\upload
$is_upload = false;
$msg = null;
if (xxx) {//第一条if语句
if (file_exists(UPLOAD_PATH)) {//第二条if语句
//代码
}else {//第二条if语句为假
$msg = UPLOAD_PATH.'文件夹不存在,请手工创建!';
}
}
(3). 黑名单
$deny_ext
是一个数组类型,存储了需要被过滤的后缀名
之后会对文件的后缀判断,如果后缀符合其中的一个,文件就会被过滤
".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",".ini"
//代码
if (xxx) {//第一条if语句
if (xxx) {//第二条if语句
$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",".ini");
//代码
}else {//第二条if语句为假
//代码
}
}
(4). 首尾去空
$_FILES['upload_file']['name']
会获取上传文件的名称,如下图的test3.txt
trim($_FILES['upload_file']['name'])
就是删除文件名称首尾
的空白符,然后赋值给变量$file_name
PHP:trim - Manual
//代码
if (xxx) {//第一条if语句
if (xxx) {//第二条if语句
//代码
$file_name = trim($_FILES['upload_file']['name']);
//代码
}else{//第二条if语句为假
//代码
}
}
(5). 获取文件后缀
strrchr($file_name, '.')
会返回小数点和文件后缀组成的子串。
假设文件名为test3.php.jpg
,得到的$file_txt
值就是.jpg
- PHP: strrchr - Manual
//代码
if (xxx) {//第一条if语句
if (xxx) {//第二条if语句
//代码
$file_ext = strrchr($file_name, '.');
//代码
}else{//第二条if语句为假
//代码
}
}
(6). 小写转换
strtolower($file_ext)
就是对得到的字符串进行全小写处理,这样就没法进行文件后缀的大小写绕过了- PHP: strtolower - Manual
//代码
if (xxx) {//第一条if语句
if (xxx) {//第二条if语句
//代码
$file_ext = strtolower($file_ext); //转换为小写
//代码
}else{//第二条if语句为假
//代码
}
}
(7). 置空::$DATA
- 在window的时候如果文件名+
::$DATA
会把::$DATA
之后的数据当成文件流处理,不会检测后缀名
如果文件名为test.php::$DATA.jpg
时,在windows中会删除::$DATA
及之后的内容,则上传window服务器后的文件名为test.php
str_ireplace('::$DATA', '', $file_ext)
将会用空字符来替换变量$file_ext
中的::$DATA
子串,防止了::$DATA
的上传绕过- PHP: str_ireplace - Manual
【文件上传绕过】八、: : $ DATA上传绕过
//代码
if (xxx) {//第一条if语句
if (xxx) {//第二条if语句
//代码
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
//代码
}else{//第二条if语句为假
//代码
}
}
(8). 首尾去空
trim($file_ext)
删除$file_ext
变量首尾的空白符- PHP: trim - Manual
//代码
if (xxx) {//第一条if语句
if (xxx) {//第二条if语句
//代码
$file_ext = trim($file_ext); //收尾去空
//代码
}else{//第二条if语句为假
//代码
}
}
(9). 黑名单过滤
$file_ext
存储的是文件后缀(含有小数点)
数组$deny_ext
的值如下,当文件的后缀不为其中的时,才能进入if语句- PHP: in_array - Manual
".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",".ini"
//代码
if (xxx) {//第一条if语句
if (xxx) {//第二条if语句
//代码
if(!in_array($file_ext, $deny_ext)) {//第三条if语句
//代码
} else {//第三条if语句为假
$msg = '此文件类型上传';
}
}else{//第二条if语句为假
//代码
}
}
(10). 文件存储路径设置
- 在上传文件的时候,文件都会被存储在一个临时的文件夹下
我们不需要知道具体路径,只需要通过tmp_name参数获取路径即可
UPLOAD_PATH
的值为../
,在config.php
文件中定义- PHP: in_array - Manual
//代码
if (xxx) {//第一条if语句
if (xxx) {//第二条if语句
//代码
if (xxx) {//第三条if语句
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH . '/' . $file_name;
//代码
} else {//第三条if语句为假
//代码
}
}else {//第二条if语句为假
//代码
}
}
(11). 移动临时文件
- 剩余的代码仅是用于移动上传的文件,没有对文件进行过滤操作
- PHP: move_uploaded_file - Manual
//代码
if (xxx) {//第一条if语句
if (xxx) {//第二条if语句
//代码
if(xxx) {//第三条if语句
//代码
if (move_uploaded_file($temp_file,$img_path)) {//第四条if语句
$is_upload = true;
} else {//第四条if语句为假
$msg = '上传出错!';
}
} else {//第三条if语句为假
//代码
}
}else{//第二条if语句为假
//代码
}
}
[3]. 点绕过
- 因为php代码中没有删除文件末尾的小数点
.
,所以当一个文件出现多个小数点的时候获取的文件后缀就会出现问题- 假设文件名为
test8.php.
时,获取的文件后缀就是.
而小数点不在黑名单之内,从而绕过黑名单
当文件上传到windows服务器后,会被windows系统自动去掉不符合规则符号后面的内容,从而保留文件名test8.php
复制图片连接并访问
虽然URL末尾含有小数点,但不会影响到php文件的解析
服务器中存储的文件名为
test8.php
使用蚁剑或菜刀进行连接,URL末尾的小数点可有可无
以上是关于upload-labs writeup的主要内容,如果未能解决你的问题,请参考以下文章