Uploadlabs wp
师傅们好!这是我最近打uploadlabs时写的wp,肯定有错误和疏忽的地方,如果师傅们看到了错误或者概念不清的地方,请师傅们不要吝啬自己的批评和建议,我会认真去改去弄懂那些错误的地方!再次感谢各位师傅们!
该靶场纯用来学习文件上传,跳过了很多解题步骤,比如测试它是那种绕过方式等等,一般直接研究该绕过产生的原因和使用方法
网上的答案很少有对源码进行细致分析,特别是越到后面越没有分析,让人很容易摸不着头脑,所以本wp最重要的异地就是关于源码防御代码的分析(当然CTF不会给你源码,必须一个一个试)
通关经验总结(直接使用版):
用来总结文件上传漏洞的一些基本方法和思想,便于自己以后使用
1.看是前端绕过还是后端绕过,如果是前端直接抓包改完发进去就行
2.抓包修改我们实体请求部分的content-type部分,有些题目会检测
黑名单绕过:
1.php3 php4 php5等后缀的绕过
2.htaccess文件间接绕过
3.PhP等大小写绕过(没有全部转小写的绕过)
4.后缀没有去空格,导致他的对后缀名的提取多提取了一个空字符,黑名单找不到,绕过了
5.首尾不去点,哥们直接1.php. 加个·的绕过 或者 . . (点空格点)的绕过,适用于删点和删空格顺序弄反的情况
6.::$DATAwindows系统漏洞
7.pphphp 删除php等敏感后缀 我们直接这么构造去绕过
白名单绕过:
1.GET方法直接1.php%00.jpg在我们的储存路径中注释掉后面的部分
POST方法直接二进制改找到我们自己给的一个中间变量 a.phpa.jpg php后面的a用二进制改成00就行或者我们直接选定中间变量然后右键URL变一下码就行
2.文件头的检测,我们要用到杂项里面用的多的010editor 来修改我们的文件头 比如GIF89a 建议是用gif格式来传shell ,gif问题小一点
3.用文件包含来解析我们的php代码 但要注意绕过
4.二重绕过建议前10行的二进制绕过 但可以用010editor找一下修改过后的图片有哪些部分不同,再在那个里面插入我们的php代码就行,然后用我们的文件包含来
条件竞争
真遇到了看题目具体是怎么操作的,然后再用burpsuite爆破就行
有些关卡的因为phpstudy版本过高的原因,导致我们的题目最终一步,例如将配置.htaccess将我们的.jpg文件
转换为php文件解析,又或者是配置apache使它能够解析php3 php4 php5文件,这些操作网上经过调整后仍有bug(页面直接下载图片,甚至不会加载页面等等),大部分网上的办法都试过了,甚至学到一些新的东西,但最后结果还是不行,索性最后一步结果如果验证phpinfo();得不到结果,但是前面该学的知识和思路都领悟了,后面的验证无法进行也是没办法。但不影响做题,这类题目的解题步骤最后一步的得到phpinfo();的测试回显做不到,但解题思路依然会不漏 ,突出一个过程比结果重要
(这个时候还不会用docker)
Pass-1

首先看题,直接让我们传个webshell 再看看源码,是前端的一个防御模式。

这里我有两种方法,首先看第一种
1.抓包改的方法


先用文本文件写一下脚本,这里用的eval函数是将里面的字符串内容当作php代码去执行的函数
出来之后把文件名后缀改为jpg,用来绕过前端的检测

找到文件,先别急着上传,还要等着抓包的

我们找到火狐的设置,在常规那一栏的最下方网络配置,改成这样的代理配置,当然burpsuite的配置也和这个一样,不然抓不到

把抓包的开关打开

点击上传后我们可以看到请求报文,这个时候其实已经绕过前端了,之后发过去的包就是直接给后端了,然后又是传的文件,要想我们的shell能够实现,必须要还要将文件后缀改为php 这样才能使webshell里面的代码执行

修改完之后再点击上面的intercept is on,把他变为off状态来发包

这个时候算是成功一半了,我们点击图片,看我们的shell被放在哪了

新建标签打开图像

应该算是成功了,传个phpinfo();看看

成功了
2.直接禁用或者修改javascript的方法

在火狐游览器中F12,然后点击调试器,到右边设置中,点击禁用javascript
这种方法其实不是很推荐,有些靶场或者实战中如果禁用了javascript的话我们的页面将无法正常显示了
然后步骤与1相同,就不过多赘述了,重点是下面的总计
4.注意事项以及防御思路和代码解析提取绕过经验
可能我们点击新链接进入图片时会直接在pass1这个路径下打开,有些题目是找不到的,把前面的pass1去掉试试就行,这个题就是要去掉前面的pass1那个路径
看看防御手段,仔细学习以下
function checkFile() {
//这一步的var是为了看客户端有没有上传文件
var file = document.getElementsByName('upload_file')[0].value;
if (file == null || file == "")
{
alert("请选择要上传的文件!");
return false;
}
//定义允许上传的文件类型
var allow_ext = ".jpg|.png|.gif";
//提取上传文件的类型
var ext_name = file.substring(file.lastIndexOf("."));
//判断上传文件类型是否允许上传
if (allow_ext.indexOf(ext_name + "|") == -1) {
var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name;alert(errMsg);
return false;
}
}
这里要补充几个脚本语言方法和php里面的函数
1.document.getElementsByName
其实看名字就能看出来,就是统计表单中选择了某一个name选项的数量,比如有两个name=upload_file 选择了,这里我们的document.getElementsByName返回的对象中就肯定有2
1.返回值有统计的元素个数 用下列方法查找:num = document.getElementsByName("animal").length;
2.返回值有所有name为animal的元素(也就是返回整个input标签中的所有属性,可以直接调用出来看的) 用下列方法查找:elements = document.getElementsByName("fname");
接下来就可以这么查找了 elements[0].type elements[0].checked 这样去查找了,相当于返回了所有name=满足要求的input 标签,包括里面的属性,将它们一个一个都化为了nodelist,相当于一个列表,或者说是结构(c语言中的结构类似)然后可以一个一个查找属性值
2.file.substring与file.lastIndexOf结合使用提取文件末标判断是否为图片文件
这是两个javascript的方法
file.substring就是提取它传值的两个数之间的字符串,如果只有一个数,则从那一位数下标开始一直提取到最后
然后是file.lastIndexOf('')就是找到最后方法传值内的那个字符的下标
结合使用就是file.substring(file.lastIndexOf(".")); 查找最后一次出现'.'的地方,然后从那个地方开始提取字符串一直提到最后 这不就是提取文件上传类型嘛 很容易理解
3.整体的攻击逻辑
因为它只是在前端写的脚本语言,完全没有防御我们的抓包操作,我们只需要提前将webshell写入文本文档,然后修改后缀上传,就可以绕过这个前端的检测,后端就随便入侵了。
Pass-2
1.解题与Pass-1一样步骤也能绕过
跟第一题是一样的,我们这边还是写一句木马<?php @eval($_GET['a']); ?>
上几个步骤与Pass-1中是一样的,我们还是抓个包
由于我们传的还是jpg文件,直接绕过了,但是有几个函数我们还是要学习以下,并且分析一下他的防御代码
2.Pass-2的独特用法
我们直接传一个php的文件,这里传php4是为了验证下面Pass-3的问题,很烦
抓一下包
我们发现请求包下面限定文件传输的格式中是application/octet-steam 这个字段会有什么作用呢,说人话就是会把我们的实体文件请求直接拦下来,因为它也不知道是什么 无法解析
这里我们改成image/jpeg、image/png、image/gif
这里三种组合的任意一种都能是我们的请求能够过去
过去之后直接传值 a=phpinfo();就行
或者蚁剑连一下也是可以的
注意事项,防御思路,补充知识
$is_upload = false;
$msg = null;
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.'文件夹不存在,请手工创建!';}
}
1.防御与攻击思路
现在看来只有当我们的传入文件的类型是jpeg png gif的时候才能算是进入 那跟我们第一题是一样的,它主要是为了检测我们的传入的文件的后缀是否符合他的要求,我怀疑它这个检验代码还是存在于前端,不然我们的后面抓包修改后的php后缀是过不了的
1.FILE[][]方法
$_FILES["file"]["name"] - 上传文件的名称
$_FILES["file"]["type"] - 上传文件的类型
$_FILES["file"]["size"] - 上传文件的大小,以字节计
$_FILES["file"]["tmp_name"] - 存储在服务器的文件的临时副本的名称
$_FILES["file"]["error"] - 由文件上传导致的错误代码
这些都是php中的文件函数,能够对我们客户端传入的文件进行操作
2.move_uploaded_file(file,newloc) 函数
该函数用一句话概括就是将指定文件移动到新地方
有两个变量 1.file即是我们需要移动的文件 2.newloc就是我们移动到的新位置
当然如果移动成功,那么就会返回值true 如果出现任何差错,比如说文件找不到,文件路径出错等等,都会返回flase
Pass-3(本人出bug关,设置了之后虽然可以解析,但是解析到直接下载图片,页面直接显示为blank)
1.解题步骤
F12查看后发现这不是前端的检测,是后端检测,抓包直接改后缀是没办法的
在我们直接传了个12.phpshell后被告知我们不允许传这些后缀的文件,一般这类都是shell的后缀格式,被纳入了黑名单,那其实除了这些我们还有很多漏网之鱼的shell后缀可以使用 php3 php4 php5 都是可以使用的
那这里我们选择php5后缀的文件进行绕过
这是我们的文本内容,改一下后缀格式
上传成功了,我们直接右键新建页面打开这个图片,找到图片的所在位置
由于配置apache后,添加了php5后缀的解析后虽然能够正常解析,但是还是存在跳转到这个页面直接下载这个文件,其他什么都做不了的情况,无法做出最后一步的验证
2.防御与攻击思路以及补充函数和方法
这是防御的代码
1.函数与方法的补充
trim()方法
传入的变量是一个字符串,用于删除字符串头尾部的空字符,然后返回这个经过处理的字符串
dedot()方法
删除给定字符串的末尾的点,从末尾开始,如果遇到的第一个字符不是'.' 就直接完成,如果遇到'.' 就会一直删除'.' ,只要碰到非'.'的字符串就不会删除了
Strrchr()函数
这居然是一个C函数,有两个参数值 (string,char)第一个是字符串,第二个是字符,作用是从这个字符串中寻找最后一次出现char的地方,返回值是一个字符串,即我们这个char出现后的所有字符串部分,包括char
str_ireplace()函数
有三个参数值(str1,str2,str3) 该函数的意思是将str3中的所有str2字符子串全部替换为str1
1.防御与攻击思路
我们一行代码一行代码的来解析,前面的is_upload msg变量申明,用于后续判断
接下来的最开始的第一个if判断我们是否点击了提交,点击了进入下一个if判断
第二个if判断里面是file函数,即判断我们的文件是否上传成功了,如果成功了就进入if语句内进行一些赋值操作
下面才是重头戏,它首先是对我们的文件名进行清除空字符,然后删除我们文件名后的,假如还有的点全部删除,然后再开始找清除完多余'.'的最后一个'.',然后读取它后面的字符串,即找我们的后缀名
最后再是根据它指定的黑名单进行筛查
看上去逻辑是很容易的,而且确实绕过也很简单
如果设置的黑名单不够多的话我们是很容易可以绕过的
Pass-4
如果是自己线下做题,一个一个后缀去试试,如果大部分都不可以,就要考虑考虑.htaccess直接配置一下了
1.知识补充
.htaccess是什么呢,我们每次用小皮选定文件夹,是不是发现都会多出这样两个文件
这个就是apache的配置文件 作用如下:URL重写、自定义错误页面、MIME类型配置以及访问权限控制等。主要体现在伪静态的应用、图片防盗链、自定义404错误页面、阻止/允许特定IP/IP段、目录浏览与主页、禁止访问指定文件类型、文件密码保护等
我们也可以直接构造这个文件,让它帮我们把所有我们传的文件后缀全部识别为php
这里要做一个笔记,就是一般的话如果涉及.htaccess 文件的绕过,要写哪些木马
<FilesMatch "xxx"> SetHandler application/x-httpd-php </FilesMatch>
这是比较常用的一个,就是将我们指定的文件名的文件全部解析为php文件来看待 "xxx"里面的内容就是我们指定的文件名了,也就是我们在植入完.htaccess文件后下一个想要传入的webshell的名字
解题步骤
1.首先写个.htaccess文件名的脚本,用来为我们后续的上传绕过做准备
内容如下
然后再看我们指定的4.jpg的内容
直接打印phpinfo();用来验证
结果就不演示了,因为最后结果不能显示
Pass-5
1.信息收集与分析
按照基本的文件上传题来做,肯定是要各种方法都要试一遍,前端后端的防御。这一题也是给我们拓展了一个思路就是大小写绕过
点开提示(这样其实不好,但是第一次写uploadlabs的目的就是为了去学习文件上传漏洞,能够尽量多的去吸收,节约时间,可以去做题网站上再去按部就班,这里还是一个重学习的目的)
发现我们的.htaccess都被禁用了,php3 php4 什么的更是不行,但是我们却看到了大小写的区别,突然想起Pass-3里的防御代码,给你全部无论大小写都强制转换为小写,做到这才明白为什么要这么去做。
2.解题步骤
上面的分析中已经指明了,我们这里可以看看黑名单了缺了啥,PHP这种纯大写没有被禁用,那我们试试纯大写,用burpsuite改一下文件名后缀就行
还是直接传我们的phpinfo();进去,就不设置密码了啥的
改一下文件名,再看看其他信息,允许的内容是image/jpeg的格式,传jpg没问题的,这里抓包改一下后缀为PHP
右键链接到新页面查看我们的文件被储存在哪了就行
这边防御代码也稍微分析一下
跟第3题的差不多一样的,少个全部转化为小写的过程而已
Pass-6
本题也是相当于给我们提供一种思路吧,是一种优先级很高的思路,感觉也是一种优先级很高的思路,就是文件后缀加空格的绕过
1.解题步骤
直接看源码,或者直接看提示都比较快能够看到解题思路,如果是平时去做题网站做题的话还是要将前面的思路全都试一遍的,然后才能确定它的绕过类型是什么
1.还是上传直接写phpinfo();

2.
burp抓一下包


改成php ' 空字符'绕过,放包,点击新页面打开看看

成功了
2.防御思路与攻击思路

其实前面几个题的思路都大差不差,最终的方面是防御代码对我们文件名的处理,前面几道题也无非就是在

这个区域内增增删删,而我们现阶段的绕过,也算是可以依据这个处理思路来
与我们Pass-4 Pass-3的防御思路差不多,最多就是穷举所有可能会拿来绕过的文件后缀,然后前后删空字符,强制改大小写的之类,这就是没有前后删空字符的绕过
Pass-7

1.解题步骤和防御思路
第7关看上去有点哈人,所有的解析都被禁用了

源码其实和前面差不多,然后就是找它有哪些操作是漏了的,第7关缺了个去除文件末尾'.'的操作,我们也是按照这个思路来

还是传我们的phpyinfo();的源码
用burp抓一下包改一下后缀

加一个'.'的绕过

也是成功绕过,防御思路和攻击思路其实与上面几个差不多,就是看有哪些检测手段是缺了的
其实点的绕过也是根据windows特性来的,自动过滤了文件末尾的点,也就是我们服务器创建新文件的,我们的4.php.直接变成了4.php 这样就能成功给我们的shell提供环境
Pass-8

我们这里发现缺了::$DATA的检测,大小写 收尾去空的操作都是有的
1.知识补充
那么我们这里要补充一点知识 就是::$DATA是什么?
当我们传入文件名末尾有::$DATA的文件时,windows会自动将它检测为数据流,并不是说直接不进入这个if判断里面进行检测了,只是我们绕过了这个判断之后,服务器创建文件夹的时候,会自动省略::$DATA 然后我们传入的.php::$DATA文件名的文件就直接变成了.php,shell环境还是创建成功了的
所以要明确::$DATA是在哪一步起作用,并不是连这个if判断都绕过了,它只是我们在绕过之后,服务器系统创建文件的时候起的作用,以及还能帮助我们绕过黑名单的穷举
2.解题步骤
1.

直接传我们的shell,用burp抓一下抓包
进去后就应该显示phpinfo(); 我这里环境没配好,显示403了,就不演示了
Pass-9
1.解题思路和防御思路
我们看源码和提示,应该是把前面的后缀都给禁止了,但是的防御代码的对字符串后缀的处理有少许变化,就是它先取出我们后缀中的所有点,然后再开始删空格,而且只有一次检测,就一次if的处理,那我们可以这样设置文件
4.php改成 4.php. .(注意两点之间是有一次空格的)
这样处理过后我们的可以自己推一下,它首先将最后一个.去除了,然后遇到不是·了,开始转大小写,取出::$DATA字符串,最后开始取出空字符,使其变成了4.php.在文件也是可以正常做shell的
Pass-10
1.知识复习以及分析
我们首先来分析一下这道题,看看源码和提示 它会将这些字符串从你的文件名中全部删除,这个功能是怎么实现的呢?我们看这个函数
之前讲过这个函数的具体作用,估计这个函数就是这道题的考点了,我们回忆一下这个函数实现,首先从字符串的开头开始找我们指定删除的字符串,比如说我们要删除'php'这个字符串,我们传上去的字符串是'pphphp',它会先一个一个对应,如果出现了php这三个字符连在一起出现的情况,就直接删除,我们的p’php‘hp中间的php被删除了,首尾的php就又连起来了,又能够组成了解析的php文件了
2.解题步骤
用4.php先预备传入,再抓一下包
修改文件名后放包
点击新链接打开图片后验证,成功绕过
上面10个题目都是黑名单的绕过,但是平时基本上不会给你设置黑名单穷举,很难用的到,做做签到题学学思路还是挺不错的
Pass-11
1.知识点补充以及漏洞产生的原理
首先我们要补充一个知识点 关于%00截断的一些补充
这其实一个系统函数,系统是由汇编或者C写成的,所以当里面的字符串遇到\0就会把它读成一个字符串的结束符号,后面的内容就不会去解析了,这一步的应用在最后我们传入jpg文件绕过白名单检测后创建文件时,文件名会变成我们想要的.php形式
我们先来分析一下源码,看到这行代码和我们抓包的内容
$sava_path这个变量应该就是我们传入文件的存放地址了,再看看burpsuite里面抓到的包的内容,应该是要存到一个upload的文件夹里面,当然还要经过我们下面这个变量的处理方式,将他加密之后和我们处理过后的文件名连起来,才能最终成为我们文件存放地址
如果我们不做修改,文件存放的文件地址直接就是upload/???.jpg了,就没用,还是没有shell环境,这个时候我们可以在burp里面修改一下,做一个00截断
2.解题步骤
修改前
修改后
这样我们传入的文件名就变成了4.php,即使我们传输的时候对它本身的 jpg格式没做任何的处理,但是我们创立的文件却是我们想要的名字。
本题需要php5.30以下的版本,还要把魔术标点的功能去掉,才能在最后出现phpinfo();的结果,就不演示了
Pass-12
12题的防御代码是跟11的防御代码是一样的,只是11的提交方式是GET方法,而12题的方法是POST方法,而我们的POST方法提交的东西是不会经过URL的编码的,直接看作是字符串,所以我们的%00是不会被认为是/0的,这时候可以有如下方法进行操作
还是传我们的4.jpg,抓包来改一些东西
找到我们的POST方法提交的地方,还是跟我们的GET方法一样的方式,给个文件名
这个4.php后面随便加个什么字符都是可以的,主要是作为一个媒介给我们二进制修改
再来到我们的HEX界面
找到对应的+,在16进制中表现为2b,我们把它改成00 之后就变成了\0,就到达了同样的效果
还有另一种方法
选定我们在4.php后面加的%00后,右键打开这几个选项就可以进行URL的编码了,效果也是一样的
Pass-13
这题涉及到文件包含的漏洞利用,要结合使用,由于本人只有文件上传的知识,所以对于文件包含的问题可能讲的不是很好。
1.解题步骤
1
我们首先来看一下题目要求和提示,
它说只检测图标内容的开头两个字节,这里我们拿GIF举例子,我随便在网上找一个GIF图片然后用010editor打开看看gif文件的结构
可以看到,前两个字节是GIF8a,加半个字节,不过无伤大雅,我们依然可以根据这个原理来构造我们的木马
2.
这里建议用记事本打开,用notepad打开好像有问题,不知道是编码形式还是什么,notepad去编辑总是解析不出来
写完之后上传,但是现在躺在upload文件夹里面的还是我们的.gif格式的图片,那我们怎么去拿它当shell呢?
这里要用文件包含的漏洞,本靶场已经帮我们上传了一个文件包含的解析页面,能够帮助我们去解析我们的webshell,就是读取它的php内容,该文件如下
如何使用呢? 我们在这个页面中通过get方式来传值,传入我们的刚刚写进的木马的文件名
3.
复制一下,在我们的include.php界面里通过get方式传值

成功绕过,主要是涉及到文件包含的内容,以及一些常用文件的文件头的内容,涉及的知识比较多。
2.防御思路和攻击思路
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;
}
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$temp_file = $_FILES['upload_file']['tmp_name'];
$file_type = getReailFileType($temp_file);
if($file_type == 'unknown'){
$msg = "文件未知,上传失败!";
}else{
$img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").".".$file_type;
if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true;
} else {
$msg = "上传出错!";
}
}
}
这里的防御代码用的是白名单,而且要进入我们的文件内容去检查我们的文件头部分,所以想要直接传php文件进去还是很难的。这个时候就要想到文件包含的操作,把我们的shell环境提取出来,文件包含的意思不是我们的shell被我们的启动页面包含着,而是通过我们的启动页面去启动我们的shell环境

真正的包含关系是在我们的URL中体现出来的,那么如何传入我们的这个include.php文件呢?
,这里有一个很鸡贼的方法,我们可以通过上几个靶场来上传这个include文件,当然具体的方法等到文件包含漏洞时再详细学习
Pass-14-getimagesize()
1.知识补充
本题的主要绕过点是getimagesize()函数,那我怀疑就是检测一下图片文件的文件头来判断它是否是图片文件,这个本人在杂项的学习中遇到过,可以到本人的杂项笔记中详细了解
getimagesize()函数和我想的一样,就是检测文件的文件头来判断它是不是该文件
那么我们的绕过方法还是一样的,在shell文件前面加绕过判断的字符段
2.解题步骤
我们拿010edior打开看一下

之前做杂项留的png图片,前面文件头的前两个字符用来判断文件类型,我们把其他内容全部删除,然后直接在后面接上我们的webshell的内容就行
上传这个文件,再按照我们Pass13的思路用文件包含漏洞来访问我们的这个文件,将它的php代码解析出来。

Pass-15—exif_imagetype()
1.知识补充
exif_imagetype()函数 作用是用来检测我们的指定文件的前面第一个字节来判断它的文件类型
那其实呢和我们 13 14的绕过方法其实是差不多的,而且这个只检测你文件头的第一个字节,绕过更加容易。步骤也是一样的,用010editor打开我们的webshell

前面的png判断的文件头不要改,后面的webshell部分可以写自己想写的内容,这里只是来验证一下phpinfo()看绕过是否成功
当然也要用到文件包含的漏洞
这里我们就不做演示了,步骤与13 14相同
Pass16-二重渲染
本题个人感觉难度挺高的,如果事先不知道这种渲染的规则和规律,很难做的出来
但本靶场的讲解是用来学习新东西的,如果实在不知道绕过点的利用,可以先学知识再来解题
1.知识补充
二次渲染是什么?
在我们上传文件后,网站会对图片进行二次处理(格式、尺寸要求等),服务器会把里面的内容进行替换更新,处理完成后,根据我们原有的图片生成一个新的图片并放到网站对应的标签进行显示。
而我们如何去利用二次渲染的漏洞呢?
二次渲染过后我们的渲染过后的图片和原来的图片是有一些地方是没有变化的,渲染过程那一部分是不会变得,那我们的利用这个漏洞的关键就是找到那个没有变的地方在哪,这个时候也要去看我们的图片的二进制的形式才能看出哪里不同,010editor太好用了,下面是010editor比较的结果,它能比较两个文件的二进制形式的差异,而且能直接标出哪些相同,哪些不同,那么我们就在这几个相同的区域内写自己的木马就行

那我们试试在这个区域内写webshell,还是写phpinfo()直接来验证
保存后将我们的这个文件上传一下,按照上面的文件包含的顺序进行操作得到验证,绕过成功

Pass-17(条件竞争)

直接要我们代码审计了,那我们就看看源码吧

整体结构就是if语句的嵌套
1.
那我们看第一个if语句的判断,判断我们是否点了提交按钮,点了就直接进我们的if语句的内容
2.
1号if的内容是首先定义了一个ext_arr的列表,然后用file_name储存我们的文件名,又用temp_file来储存我们的临时文件名
最后再联合使用substr和strrpos来寻找我们的文件名的最后一个'.'的位置到我们文件结尾,就是我们的文件后缀名,file_ext这个变量存起来
upload_file用来储存我们的文件的地址,也就是存入我们的文件的路径
3.
进入二号if查看,开始移动我们的文件,移动到upload_file指定的文件路径下
然后再进入三号if,看看我们的后缀是不是这几个白名单的内容,如果是的话就让我们进入三号if的内容,将文件名随机化储存起来
4.分析漏洞
对于我们文件后缀名的绕过,是file_ext这个变量,它的处理方式是找到我们最后一个.的位置然后将后面的所有字符串作为我们的文件名后缀
好吧,我的分析思路完全错了,这一题要利用的漏洞是条件竞争。条件竞争的一个比较明显的标志就是后端php对上传的文件的处理顺序不当,它是先将文件存入文件夹,然后再对其进行判断,看它是否符合允许上传的条件,如果符合就还是不动它,不符合才把它删除。在我们上传入文件到后端进行文件检测这一段时间内,是可以进行重复发包然后截获的,这个瞬间的时间就导致我们的webshell被写入后台文件了,但是还没有进行判定它是否符合我们允许传输的条件,如果我们在这个时候,访问了这个尚未被处理的文件,那我们就可以执行我们上传的webshell从而达到目的
那么具体操作是什么呢?
首先我们先抓一个上传我们shell的请求,下面是我上传的5.phpshell的内容


右键点击将他送入我们的intruder页面
payload的位置清除

然后这样设置
然后再截断一个我们访问upload/shell.php(我上传shell的php执行代码的一个结果,就是写一个shell.php的shell)
设置还是一样设置,先开我们的shell请求的攻击
然后再开我们的上传shell的攻击,如果在我们的本地文件夹下看见了我们的shell.php文件就说明成功
Pass-18
源码很长
<?php
include '../config.php';
include '../head.php';
include '../menu.php';
$is_upload = false;
$msg = null;
if (isset($_POST['submit']))
{
require_once("./myupload.php");
$imgFileName =time();
$u = new MyUpload($_FILES['upload_file']['name'], $_FILES['upload_file']['tmp_name'], $_FILES['upload_file']['size'],$imgFileName);
$status_code = $u->upload(UPLOAD_PATH);
switch ($status_code) {
case 1:
$is_upload = true;
$img_path = $u->cls_upload_dir . $u->cls_file_rename_to;
break;
case 2:
$msg = '文件已经被上传,但没有重命名。';
break;
case -1:
$msg = '这个文件不能上传到服务器的临时文件存储目录。';
break;
case -2:
$msg = '上传失败,上传目录不可写。';
break;
case -3:
$msg = '上传失败,无法上传该类型文件。';
break;
case -4:
$msg = '上传失败,上传的文件过大。';
break;
case -5:
$msg = '上传失败,服务器已经存在相同名称文件。';
break;
case -6:
$msg = '文件无法上传,文件不能复制到目标目录。';
break;
default:
$msg = '未知错误!';
break;
}
}
?>
<div id="upload_panel">
<ol>
<li>
<h3>任务</h3>
<p>上传一个<code>webshell</code>到服务器。</p>
</li>
<li>
<h3>上传区</h3>
<form enctype="multipart/form-data" method="post">
<p>请选择要上传的图片:<p>
<input class="input_file" type="file" name="upload_file"/>
<input class="button" type="submit" name="submit" value="上传"/>
</form>
<div id="msg">
<?php
if($msg != null){
echo "提示:".$msg;
}
?>
</div>
<div id="img">
<?php
if($is_upload){
echo '<img src="'.$img_path.'" width="250px" />';
}
?>
</div>
</li>
<?php
if($_GET['action'] == "show_code"){
include 'show_code.php';
}
?>
</ol>
</div>
<?php
include '../footer.php';
?>
Pass-19
$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 = $_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 . '文件夹不存在,请手工创建!';}
}
1.知识补充
pathinfo()函数
pathinfo()函数的返回值是一个数组,这个数组包含的信息是这个文件的路径的一些基本信息
他有两个参数 pathinfo(path(检查的路径),process_sections(想要返回的信息))
1.path就是我们传入的文件这个路径
2.process_sections就是我们的文件的路径信息的一个细分,用来控制我们想要返回的路径信息
PATHINFO_DIRNAME - 只返回 dirname(我们文件的目录)
PATHINFO_DIRNAME - 只返回 basename(文件名称)
PATHINFO_EXTENSION - 只返回 extension(文件的后缀名)
2.解题思路
1.找到绕过点
那我们这个题目的防御代码中的使用是这样的pathinfo($file_name,PATHINFO_EXTENSION)
就表示他返回我们文件路径的最后一个,文件的后缀名,也就是检测我们的后缀名
拿到我们的后缀名之后就开始黑名单检测
经过检测之后就会写入我们的upload文件夹中
那我们的绕过就是要绕过这个文件后缀名的条件
再想想我们的文件名的写入是我们直接上传的文件的文件后缀,还是我们本题savename里面的文件后缀名?
看题之后发现是我们savename自己提交的一个文件后缀名
2.绕过具体操作
我们可以直接传入.php文件了,因为他检测是我们的savename,也就是我们自己定义的那个文件名
可以按照如下操作来
上传的文件的后缀名其实无所谓
我们看保存名称
a.phpa.jpg jpg是为了绕过检测,而php后面的a是为了我们能够再burpsuite里面方便我们二进制形式改为%00从而绕过(post提交,所以要二进制改)
这样去修改,再发包出去,进入我们的webshell的页面就能看到了绕过成功了
Pass-20
本题感觉网上的讲解都过于形式化,没有理解其本质,就是来一句数组绕过就完事了,很没意思
(在给了你代码的前提下)看懂代码,才能知道哪里有漏洞 本题的漏洞就是三个if语句里面的判断条件造成的
1.源码分析 找绕过点
分为两个部分,A部分:用来判断我们的文件MIME的类型,抓包改一下type就行
然后A部分的else用来判断我们的自己上传的save_name是否为空,如果为空就直接那我们的文件的名字作为filename,如果不为空还是按我们自己上传的savename来命名
然后再把我们的这个file改为数组的形式,好检验
B部分:首先将我们的后缀名提取出来储存到我们的ext变量中
再将我们的ext与我们的白名单进行比较,如果通过就让我们进行储存操作
后面的就不用看了,就没有进行判断操作了
2.根据绕过点一个一个绕过
下面我们将根据我们的请求包来一个一个绕过
1.首先是我们的第一个绕过点,我们的第一个if语句的绕过
这个很简单,我们直接在抓包操作中关于我们的upload_file那一栏的content-type实体字段修改为题目源码允许的类型就行
2.第二if语句的绕过
它首先做了个判断,判断我们的save_name有没有值提交,如果有,那么我们的$file变量就赋值为save_name
没有就用我们的提交的文件的文件名
很明显,自己提交一个显然更容易控制来绕过,但是这里要注意一个细节

它会判断我们的file是否为数组,这里的转file为数组极为重要,而且直接关系到本题的解答,如果能理解这一步就很好做了。为此我们先不急,来看下面的判断操作
这是我们源码里面唯二判断我们能不能正常上传的操作了,也是最后一个,绕过它就很好做了
它的判断条件是判断我们的ext变量是不是这个allowsuffix列组里面的值,而ext是由我们的file来决定的,而我们的file是一个数组,而且它是我们flie数组的最后一个元素
那我们直接先来解决这个
直接复制一个关于save_name的实体部分,然后将我们的save_name数组(为什么是save_name?在我们赋值file变量的时候进行了一个操作,可以往回看看)的最后一个元素随便指定一个符合条件的元素就行,这一步我们也成功绕过
那么,第三个绕过,也很容易了
第三个绕过是关系到我们shell文件存到文件夹里面命名的问题了
他将我们file数组变量的第一个变量作为了我们的文件名
那我们直接将第一个变量设置为我们想要的文件名即可,但是要注意注释掉后面的内容
就是这一部分要注释掉,所以
这样子命名即可
至此,三层绕过已全部完毕,直接发包等待结果,顺便附上请求包的所有内容便于查看
然后就报错了,好吧。。。。php版本必须低于5.3才能用那个注释,我这个环境是7开头的,所以不行,答案出不来