“js验证”
根据源码我们可以看到本题是要绕过js验证,我们先将上传的文件格式从.php改为.jpg
文件上传后,在burp中将文件格式改回为原来的.php
就可以打开我们上传的文件了
或者可以直接打开about:config在设置中直接禁用js
根据源代码我们可以看到本题是要验证Content-type
所以文件上传之后,在burp中将Content-type改为代码中限制的形式如’image/jpeg’
就可以打开我们上传的文件了
改为
上传成功。
知识点:
根据源代码我们可以看到黑名单里不允许上传.asp、.aspx、.php、.jsp
但是是可以上传.phtml、.phps、.php5、.pht
文件上传后,在burp中将文件格式改为.php5
这里有上传路径,通过打开上传路径我们就可以看到文件内容了
根据源代码我们可以看到黑名单中拒绝了大部分有问题的后缀上传
但是可以上传.htaccess文件
我们构造.htaccess文件:AddType application/x-httpd-php //所有文件都会被当成php文件来解析
这里是要把文件名全部去掉,只留下.htaccess后缀
根据源代码,我们可以看到基本上都过滤了,但是我们还可以通过利用ini配置文件来进行绕过。
先上传一个以auto_prepend_file=1.jpg为内容的.user.ini文件,然后再上传一个内容为php的一句话的脚本,命名为1.jpg,.user.ini文件里的意思是:所有的php文件都自动包含1.jpg文件。.user.ini相当于一个用户自定义的php.ini。
文件上传成功。
根据源代码我们可以看到,相比较于之前的,过滤了htaccess,但是对于后缀名没有进行统一转换为大小写了。所以我们可以通过将后缀名进行大小写绕过。
将文件名称由1.php改为1.Php即可上传成功。
上传成功。
根据源代码,我们可以看到没有对后缀进行首位去空处理,所以我们在文件后缀中加入空格进行绕过
上传成功
“加点绕过/windows解析漏洞”
根据源代码,我们可以看到没有进行去‘.‘处理即没有删除文件末尾的点,所以我们可以在文件末尾进行加点绕过
根据代码我们可以看到,代码中没有进行去除字符串:: D A T A 处 理 , 所 以 我 们 可 以 通 过 加 字 符 串 : : DATA处理,所以我们可以通过加字符串:: DATA处理,所以我们可以通过加字符串::DATA的方式,使其不检查后缀名。
改为
上传成功
知识点:
在php+windows的情况下:如果文件名+":: D A T A " 会 把 : : DATA"会把:: DATA"会把::DATA之后的数据当成文件流处理,不会检测后缀名.且保持"::$DATA"之前的文件名。
只能是Windows系统,并且只能是php文件。
“点+空格+点绕过”
根据代码我们可以看到这里进行了去点、去字符串、去空、转换为小写等操作
但是我们可以看到这里去点、去空的操作都只进行了一次,并且是先进行去点操作之后进行去空操作。我们在文件后缀中加入“点+空格+点”,只过滤了最后的点和空格,还有一个点没有进行删除,这就使得本题又转化为Pass-08问题
上传成功
根据源码可以看到,str_ireplace()函数替换$file_name中的字符串即替换上述文件后缀名为空,但是只执行一次,所以我们可以进行双写绕过
改为
知识点:
str_ireplace() 函数替换字符串中的一些字符(不区分大小写)。
语法:str_ireplace(find,replace,string,count)
根据源码,我们可以看到 i m g p a t h 是 直 接 将 后 缀 名 img_path是直接将后缀名 imgpath是直接将后缀名file_ext进行拼接。我们可以在中间加入php后缀,再用%00进行截断,那么就可以将文件当作是php文件进行解析。
$_GET[‘save_path’]的意思是需要请求参数save_path。使用GET方法,我们可以拦截下包之后更改save_path的值,使用%00将后缀名.jpg截断,以此来运行php文件。
也可以直接在前端直接对参数save_path修改为.php+%00截断的格式
根据源代码我们可以看到,我们可以看到 i m g p a t h 是 直 接 将 后 缀 名 img_path是直接将后缀名 imgpath是直接将后缀名file_ext进行拼接。因为POST请求不会像GET请求那样对%00进行自动解码,且POST请求是以二进制流的方式发送文件,所以我们可以在二进制中进行修改。
这里的“+”只是一个记号,我们需要在二进制中找到“+”的二进制码2b,将其改为00
上传成功
知识点:
POST请求不会像GET请求那样对%00进行自动解码,且POST请求是以二进制流的方式发送文件,所以我们可以直接在二进制中进行修改。
“图片马绕过”
根据源码我们可以知道,这是通过读文件的前2个字节判断文件类型,因此直接上传图片马即可。
制作图片马: copy 1.jpg/b + 1.php/a 2.jpg //生成的2.jpg即为图片马
但是直接访问图片并不能把图片当做PHP解析,我们还需要利用文件包含漏洞
其中file为图片所在位置
文件上传成功。
知识点:
这段代码的意思是读取上传文件的前两个字节内容,unpack解码后,使用intval转换为十进制,默认为十进制,根据转换后的结果判断图片类型。“rb”代表着读取二进制文件。
根据源代码,我们可以知道这是通过使用getimagesize()来检查是否为图片文件
上传图片马进行绕过
同Pass-14
文件上传成功
知识点:
根据源代码,我们可以知道这是读取一个图像的第一个字节并检查其签名。
所以我们通过上传图片马进行绕过
同Pass-14
文件上传成功
知识点:
我们还需要修改php.ini中的配置,将;extension=php_exif.dll前面的;去掉,然后保存重启。
“二次渲染绕过”
根据源代码,我们可以知道需要先判断后缀与MIME类型是否符合要求,符合后生成新图像,生成新图像成功后就根据系统时间给文件命名,如果失败就unlink删除。之后再通过imagecreatefromjpeg()函数同原图像资源创建新图像(二次渲染)。
具体可以参考 二次渲染绕过。
知识点:
1.basename(string $path [,string $suffix]) //返回路径中的文件名部分
2.imagecreatefromjpeg(string $filename)
imagecreatefrompng(string $filename)
imagecreatefromgif(string $filename) //由文件或URL创建一个新图像,内容不对则失败返回false,成功后返回图像资源
3.srand([int $seed ]) //用seed播下随机数发生器种子
4.strval(mixed $var) //返回字符串类型的var
5.imagejpeg(resource $image [,string $filename [,int $quality]])//从image图像以filename为文件名创建一个JPEG图像
imagepng(resource $image [,string $filename]) //从 image 图像以filename为文件名创建一个PNG图像或文件
imagegif(resource $image [,string $filename]) //从 image 图像以filename为文件名创建一个GIF图像或文件
“条件竞争”
根据源代码,我们可以知道这里先将文件上传到服务器,然后判断文件后缀是否在白名单里,如果在则重命名,否则删除。所以我们可以上传1.php只需要在它删除之前访问即可。
可以利用burp的intruder模块不断上传,然后我们不断的访问刷新该地址即可
调高线程,访问比较
Upload文件夹上传成功1.php
知识点:
根据源代码可以知道这里也是先进行保存然后再重命名,所以也存在条件竞争问题。
Apache会将“.php.7z”当作“.php”来进行解析,我们可以看到“.php.7z”在本题的白名单中,所以我们需要上传一个.php.7z文件,然后再利用条件竞争漏洞进行多线程不断的发送 “ .php.7z”的文件。
上传成功。
根据源代码,我们可以看到move_uploaded_file()函数中的img_path是由post参数save_name控制的,所以我们可以通过%00截断进行绕过。
同Pass-13
上传成功
也可以通过大小写绕过,因为在源代码中我们可以看到黑名单中全是小写。
上传成功
还可以通过move_uploaded_file()的性质,忽略掉文件末尾的/.进行绕过。
上传成功
知识点:
根据源代码,我们可以知道此处服务器端先是检查了MIME类型,然后判断save_name参数是否为空,为空就把文件本来名称赋值给 f i l e , 否 则 就 是 将 s a v e n a m e 参 数 的 值 赋 给 它 。 紧 接 着 判 断 file,否则就是将save_name参数的值赋给它。紧接着判断 file,否则就是将savename参数的值赋给它。紧接着判断file是否是数组。如果不是数组则将其拆成数组,然后数组最后一个的值(end函数就是取数组最后一个的值)同白名单做比较,符合jpg、png、gif中的一种就允许上传了。
在允许上传之后还要把数组的值拼接在一起对文件进行重命名。所以我们可以构造save_name[0]=1.php/ save_name[1]置为空 save_name[2]=jpg(一个白名单的合法后缀)。这样的话,reset($file)取的是数组的第一个元素即1.php/,然后接了一个’.'符号,之后又将数组最后一个元素内容拼接到一起。虽然数组最后一个值是jpg,但是当我们只设置了两个数组元素的时候,数组的元素个数就只有两个了。因此拼接是空的,所以最后得到的文件名就是1.php/.。又因为move_uploaded_file()函数会忽略掉文件末尾的/.,所以我们上传到服务器的文件还是被重命名为了php后缀。
上传成功。