原理:应用程序中存在上传功能,但是对上传文件没有经过合法性校验或者检验函数存在缺陷,导致攻击者可以上传木马文件到服务器application/octet-stream
pass-01:(前端js+抓包)
上传php文件页面提示不允许上传(前端JS过滤),
查看源码发现允许上传的文件类型 ,可通过禁用JavaScript,抓包,修改js代码进行过滤
1、页面F12打开设置,勾选禁用js
上传成功
2、选择允许上传格式的文件进行上传抓包,在抓包软件中进行修改后缀名
放包后查看上传成功
pass-02: (抓包)
通过查看源代码发现允许上传的文件格式.png.jpeg.gif)
选择通过抓包修改文件后缀进行上传
上传成功
pass-03:(等价扩展名)
查看源代码,发现不允许上传php此类文件,进行抓包修改尝试
提示不允许上传php文件
因为代码限制全部转换为大小写,放弃使用大小写绕过,采用php1-5等多种扩展名进行尝试
发现可以上传成功,但浏览器无法解析,解决方法:更换低版本php,在php.in配置文件后加入php5等。
语言 | 等价扩展名 |
asp | asa, cer, cdx |
aspx | ashx, asmx, ascx |
php | php2 php3 php4 phps phtml.htm.html.pht |
jsp | jspx jspf |
pass-04:(.htaccess)
查看源代码发现过滤了各种后缀,且转换大小写
.htaccess文件上传(Hypertext Access超文本入口),也被称为分布式配置文件,提供针对目录改变配置的方法,在一个特定文档目录中放置一个包含一个或多个指令的文件,以作用于此目录及其所有子目录。.htaccess可以帮我们实现包括:文件夹密码保护、用户自动重定向、自定义错误页面、改变你的文件扩展名、封禁特定IP地址的用户、只允许特定IP地址的用户、禁止目录列表,以及使用其他文件作为index文件等一些功能。
通过编辑 .htaccess文件内容为:
SetHandler application/x-httpd-php //把文件当成php的代码来解析
上传后将一句话木马重命名为15.jpg进行上传,查看后发现发生内部错误
修改PHP study配置文件,其他选项菜单--打开配置文件--httpd.conf,重启PHP study。
将将文件内的none改为all
还是不行。。。。。。。。。。
方法二:
抓包后修改后缀添加 .空格.也可以
pass-05:(点空格点绕过)
没有循环验证,也就是说这些收尾去空,删除末尾的点,去除字符串::$DATA,转换为小写这些东西只是验证了一次。所以我们的绕过思路就很简单,在数据包中把后缀名改为.php. .验证过程,首先他发现有一个点,这时会把他去掉,又发现有一个空格,也会把它去掉,我们这时还有一个点,也就是.php. 由于他只是验证一次,所以不会在去掉我们的点,这时就可以上传成功,也可以解析成功
查看解析文件,上传成功
pass-06:(大小写绕过)
查看源码,发现过滤了后缀名和.htaccess文件,但没有过滤大小写
进行后缀名大小写进行尝试,发现上传成功
pass-07:(空格绕过)
查看源码发现没有对空格进行过滤
抓包后修改后缀,进行上传成功
查看浏览器解析
pass-08: (点点绕过)
源码示例:
抓包修改(此处为两个 .)
解析成功
pass-09: (::$DATA)
查看源代码,没有去除 ::$DATA ,抓包后在php后缀后直接添加,
进行抓包修改后缀,上传成功,提示禁止访问
删除php后缀::$DATA,成功解析
pass-10:(点切割后缀名)
源码如下
抓包修改后缀名,这里使用的是用 . 去分割后缀名
文件上传成功,但无法解析,打开页面自动下载脚本文件
pass-11:(双写绕过)
查看源码,使用::$DATA,发现上传成功,但在解析时发现php后缀被注释掉了
打开源码发现将符合的字符串替换为空,这里选择采用双写绕过
抓包后进行修改文件后缀名,这里使用1.pphphp(注:不要与被注释的一致)
解析为
pass-12:(GET-%00截断)
查看源代码,十二关设置了白名单
漏洞利用条件
截断条件:php版本小于5.3.4,php的magic_quotes_gpc为OFF状态
1、php版本小于5.3.4
2、php的magic_quotes_gpc为OFF状态(php.ini配置文件,默认on修改为off)没找到!旧版小P有
白名单判断,但$img_path是直接拼接,因此可以利用%00截断绕过。
这里应该选择选择php文件进行上传截断,
进行抓包,在路径中添加1.php%00进行截断,并修改上传的文件后缀为白名单中(这里的文件名要与上传的文件图片名一致)
修改Content-Type:image/jpeg,可以上传图片jpg文件,显示上传成功,复制右侧文件路径,如果直接放包,在地址栏12.php后的东西删掉即可。
解析成功
pass-13: (POST-%00截断)
基本操作与上个类似,只是需要对%00进行URL编码(%00 截断在 GET 中被 url 解码之后是空字符,
但是在 POST 中 %00 不会被 url 解码,)
url编码:
上传成功,复制文件路径进行查看
上传成功
pass-14: (图片马)
(注!!!!!:此处php版本改为5.4.45)
getimagesize()函数将测定任何GIF,JPG,PNG,SWF,SWC,PSD,TIFF,BMP,IFF,JP2,JPX,JB2,JPC,XBM 或 WBMP 图像文件的大小并返回图像的尺寸以及文件类型及图片高度与宽度。函数成功返回的就是一个数组,失败则返回 FALSE 并产生一条 E_WARNING 级的错误信息。
图片马制作:
创建一个txt文件,内容一句话木马:
在随便选找一个图片文件,打开cmd进行图片马制作:
copy 做木马的图片/b + 一句话木马文件(php/txts后缀) 生成的图片名.jpg
(原图)
(做好的图片马)
浏览上传,成功后复制图片链接,点击文件包含漏洞进行查看
输入图片地址(注意要加 ?file=文件所在路径)
pass-15:(图片马)
getimagesize函数,这个函数的意思是:会对目标文件的16进制去进行一个读取,去读取头几个字符串是不是符合图片的要求的
所以这关还是用和14关一样的方法,生成带有php代码的图片上传,配合包含漏洞拿下此关。
pass-16:(打开php_exif)
第16关同14,15关思路一样,操作一样。但是需要打开php_exif
exif_imagetype() 读取一个图像的第一个字节并检查其签名。
本函数可用来避免调用其它 exif 函数用到了不支持的文件类型上或和 $_SERVER['HTTP_ACCEPT'] 结合使用来检查浏览器是否可以显示某个指定的图像。
然后直接上传图片马,打开查看
pass-17:(二次渲染)
第十七关主要是把二次渲染绕过 imagecreatefromjpeg()函数
二次渲染是由Gif文件或 URL 创建一个新图象。成功则返回一图像标识符/图像资源,失败则返回false,导致图片马的数据丢失,上传图片马失败。
这里推荐使用gif格式文件进行测试
(原图)
进行图片马制作,然后进行上传,上传后下载下来使用WinHex进行图片对比,查看没有被修改的地方(尽量多的地方)然后输入一句话木马(此处已修改完!!!原来一样)
将修改好的保存后上传改后的gif文件,查看解析
注意输入的语句,正常打开是乱码,因为输入的是一句话木马不是探针文件,F12打开Hackbar
勾选Post data 输入探针语句,php版本页面显示
pass-18:(条件竞争)
我们看代码他是先将图片上传上去,才开始进行判断后缀名、二次渲染。如果我们在上传上去的一瞬间访问这个文件,那他就不能对这个文件删除、二次渲染。这就相当于我们打开了一个文件,然后再去删除这个文件,就会提示这个文件在另一程序中打开无法删除。
从源码来看的话,服务器先是将文件后缀跟白名单做了对比,然后检查了文件大小以及文件是否已经存在。从源码来看,服务器先是将上传的文件保存下来,然后将文件的后缀名同白名单对比,如果是jpg、png、gif中的一种,就将文件进行重命名。如果不符合的话,unlink()函数就会删除该文件。所以我们可以上传1.php只需要在它删除之前访问即可,这个也就叫做条件竞争上传绕过。
直接上传php文件进行抓包,将抓包发送到Intruder
进入后选择positions,点击clear,
然后进行修改
进一步设置线程
然后点击发包,打开另一个浏览器访问上传文件的所在路径(你不会找不到吧),不停的刷新,直到访问到
方法二:
1、创建x.php文件 内容为:
');?>
2、上传x,php,并抓包
3、右击转发到 intruder
4、点击第二个标签 Positions 点击右侧 clear$按钮
5、点击第三个标签Payloads 打开列表 Payload type 选择 null payloads
5点击第四个标签Options 修改线程数Number of threads 为20
6、然后点击 start attack 开始 无限上传
7、执行.py文件来判断是否上传成功
import requestsurl = "http://127.0.0.1/upload/upload/x.php"#这里的IP地址为目标IP,路径为上传文件的准确路径,#否则上传不成功,这里的ma.php是上面的木马文件while True: html = requests.get(url) #获取请求的URL地址 if html.status_code == 200: #代码200代表上传成功 print("OK") #成功后显示OK break else: print("NO") #不成功显示ON
8、在执行 start attack时同时执行.py文件进行判断
9、.py·文件运行后 显示OK 后表示可能会上传成功 ,打开文件夹upload 如果真的上传成功文件则会生成一个shell.php 然后输入目标文件地址 成功访问到php网页
pass-19:(条件竞争)
第十九关的上传路径有点问题,不是上传到了upload里面,建议修改一下,进入第十九关,找到myupload.php文件,如图所示修改。 然后重启就可以了。
这关是检查了后缀名,然后上传,然后在进行二次渲染。这时我们只能上传图片马,而且得配合解析漏洞进行通关
如果觉得麻烦可以写一个python代码,进行跑脚本
import requests
url="http://127.0.0.1/upload/upload/2.gif"
while True:
html = requests.get(url)
if('Warning' not in str(html.text)):
print('ok')
break
这里的2.gif为上传的图片马,需要在文件包含漏洞里进行查看
pass-20:(%00截断或/.)
方法一:(注:修改版本低于5.3)
move_uploaded_file()函数中的img_path是由post参数save_name控制的,可以在save_name利用%00截断(注意php版本低于5.3)。
查看解析
方法二:
move_uploaded_file()有这么一个特性,会忽略掉文件末尾的 /.
所以我们把他修改为如图所示
pass-21:(数组绕过验证)
查看源码
大概意思为
检查上传路径是否存在,检查content_type是否合法
判断post方法传递的$file是否为空
判断$file不是数组,则用explode将%$file在.处分割成数组
判断最后的一个数组是否在白名单中
将数组中的第一个数组和最后一个数组连接起来
上传文件
explode(separator,string[,limit]) 函数,把字符串打散成数组。
end(array)函数,输出数组中的当前元素和最后一个元素的值。
reset(array)函数,把数组的内部指针指向第一个元素,并返回这个元素的值
count(array)函数,计算数组中的单元数目,或对象中的属性个数
首先准备一张图片马或者php一句话木马,上传后用bp拦截
我们可以尝试这样绕过:
1、先修改content_type构造为白名单中的值
2、修改post的参数为数组类型,save_name[0]为" upload-20.php ", save_name[2]为" png|jpg|gif "
因为上面的代码会先判断最后一个数组元素是否在白名单中,我们索引[2]为"png|jpg|gif"
正好可以绕过,而后面会将数组第一位和$file[count($file) - 1]进行拼接
因为我们的save_name[1]为空,即$file[1]为空,所以拼接后文件名就会变成upload-20.php
上传成功,访问图片地址,查看解析
来源地址:https://blog.csdn.net/weixin_64713446/article/details/127010892