目录

upload-labs Pass01 to 12

写在前面:windows部署和Linux部署的部分题目顺序不一致,下面以windows部署结果为例

Pass01-前端后缀检查

前端检查文件后缀

判断方法

./pass01-check.png
开发者工具network标签页
使用开发者工具,通过检查network标签页是否有流量产生即可判断是否是本地前端检查

绕过

方法1:关闭js

前提是关闭后不对网页其他功能构成影响

./pass01-chrome.png
chrome开发者工具设置关闭js

./pass01-firefox.png
firefox开发者工具设置关闭js

方法2:burpsuite修改数据包

  1. 将写好的脚本ant.php修改为ant.jpg
  2. 开启burpsuite proxy,上传,然后拦截到数据包
  3. 这时候上传ant.jpg已经绕过本地前端检查
  4. 将拦截到的ant.jpg修改为ant.php即可

./pass01-burpsuite.png
burpsuite修改上传的文件后缀为php,Content-Type不变

Pass02-mime检查/文件名00截断

服务器检查Content-type

  1. 测试是否前端js检查-结果:否
  2. 开始测试是否存在00截断或者修改Content-type检查

方法1:00截断

要求PHP<5.3.29,而且GPC关闭
拓展:00截断和%00的区别 参考

  1. 准备上传文件,修改ant.php名为ant.php.jpeg
  2. 开启burpsuite proxy拦截流量
  3. burpsuite专职hex标签页,找到ant.php.jpeg位置,将.jpeg的’.‘的十六进制2e修改为00
  4. burpsuite forward数据包即可

./pass02-00.png
00截断绕过

方法2:burpsuite修改Content-type

  1. 正常上传ant.php
  2. burpsuite将拦截到的数据包的application/x-php修改为image/jpeg
  3. forward

./pass02-burpsuite.png
修改Content-type为image/jpeg

Pass03-不完整的黑名单

不安全的黑名单
大小写后缀做了处理 - 无法通过大小写绕过
黑名单虽然没有htaccess限制,但是上传的文件被重命名 - 无法使用.htaccess绕过

  1. 尝试使用其他后缀赖绕过,例如ant.php5
  2. 但是需要修改apache配置,让服务器将php3当成php处理
  3. 注意文件被重命名,需要访问重命名之后的地址

httpd.conf需要增加配置 AddType application/x-httpd-php .php3

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
$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); //收尾去空

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 = '上传出错!';
    }
} 

Pass04-htaccess绕过

.htaccess绕过

./pass04-ext.png
黑名单没有.htaccess和.user.ini

  1. 黑名单限制没有.htaccess,而且文件没有重命名
  2. 上传.htaccess,将ant.jpg设置为php
  3. 再上传ant.jpg

.htaccess文件内容

1
2
3
4
#.htaccess内容
<FilesMatch "ant.jpg">
    SetHandler application/x-httpd-php
</FilesMatch>

Pass05-后缀大小写绕过

服务器没有处理大小写,使用大小写绕过即可
文件被重命名

./pass05-case.png
大小写后缀绕过

Pass06-后缀空格绕过

后缀加空格绕过后缀检查
注意这题的题目提示与源码提示不一致
Linux环境无法复现

  1. 添加空格绕过即可

./pass06-ext.png
题目提示

1
2
3
4
5
6
7
8
// 源码可以看出没有去除文件名或者后缀的前后空字符,这个在windows下会造成绕过
// linux复现不成功
$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");
$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

./pass06-without%2520.png
不带%20可以访问
./pass06-with%2520.png
带%20也可以访问

这里也无法利用apache的多后缀解析漏洞,例如上传一个ant.php.xxx时,服务器只保留了后缀.xxx,ant.php都被当成是文件名替换掉了,所以网页返回的是一个.xxx的路径

所以,凡是遇到只保留后缀的,基本都无法使用多后缀解析漏洞

1
2
3
4
$img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;
if (move_uploaded_file($temp_file,$img_path)) {
    $is_upload = true;
}

Pass07-apache多后缀解析漏洞

文件没有被重命名
.htaccess和.user.ini 不能上传

  1. 测试apache多后缀解析漏洞

./pass07-burpsuite.png
添加.xxx后缀

./pass07-apache.png
apache多后缀解析漏洞

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
$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");
$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 = '上传出错!';
    }
} 

Pass08-windows::$DATA绕过

只能在windows下复现
增加::$DATA,让服务器认为后面是数据流,不去检验后缀

./pass08-data.png
::$DATA绕过

1
2
3
4
5
6
7
// 没有去除::$DATA
$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");
$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); //首尾去空

Pass09-apache多后缀解析漏洞

文件没有被重命名
.htaccess 不能上传
.user.ini可以上传,但是upload文件夹没有可执行的php文件,无法触发

尝试apache多后缀漏洞,通过。同Pass07

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
$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");
$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 = '上传出错!';
    }
}

Pass10-复写

构造复写后缀绕过即可

./pass10-repeat.png
复写后缀

Pass11-上传路径可控+白名单

文件被重命名
存在白名单限制,无法使用00截断,00截断会导致后缀校验不通过
上传路径save_path可控制,尝试%00截断路径

./pass11-burpsuite.png
通过%00截断路径

./pass11-00.png
路径%00截断

原理

  1. 漏洞位置move_uploaded_file,通常用来移动上传的文件
  2. 如果路径产生%00截断,就会产生漏洞并可被重命名
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
$ext_arr = array('jpg','png','gif');
$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);
if(in_array($file_ext,$ext_arr)){
    $temp_file = $_FILES['upload_file']['tmp_name'];
    $img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
    // 关键位置,将文件移到save_path的时候,遇到%00发生截断,而且由于截断后的路径是../upload/ant.php,相当于重命名为ant.php
    if(move_uploaded_file($temp_file,$img_path)){
        $is_upload = true;
    } else {
        $msg = '上传出错!';
    }
}

Pass12-请求体内的上传路径可控

与pass11雷士,只是路径位于请求体内
注意请求体内的数据

  1. 路径截断
  2. 与pass11不同,pass11的阶段发生在url上,url上的%00(url编码)其实对应编码前数据NUL
  3. post请求体实现路径截断也应该填入NUL,不应该是%00
  4. 所以这里可以先填入%00,然后选择url-decode还原

./pass12-body.png
注意请求体内的数据