分析两段php的文件上传源码,尝试进行后缀黑/白名单的上传绕过。
这段源码来自uploads-labs靶场第21关。
![php源码分析案例 | 文件上传绕过 php源码分析案例 | 文件上传绕过]()
首先将上传的文件名以符号 . 为分隔符打散为数组,取数组的最后一个元素为后缀名,白名单检测后,实际的文件名为[数组的首个元素.数组的总长度-1位置的元素]。
想要绕过白名单上传,很明显需要使end($file)和$file[count($file)-1]指向不同的内容,end($file)是合法的后缀用于骗过白名单,而$file[count($file)-1]是实际上传的后缀。
简单的看,这两个都是指代数组的最后一个元素。那什么特殊情况才能使他们不同呢。源码中有这么一句:
也就是说,其实我们可以直接把文件名用数组的形式传进去,这样代码就不会自作主张的用符号 . 来进行分隔了。
这样看end($file)就等于jpg,而$file[count($file) - 1],实际变成了$file[1],我们上传的数组并没有给$file[1]赋值,也就是空的。
于是最后的filename就变成了up.php/. ,接下来进入move_uploaded_file函数。
move_uploaded_file函数的作用是检查某个文件是否是由php的http post机制上传,如果是,则同时将其移动到一个新的位置。通常用于检查并将php上传时产生的临时文件移动到上传目录下,实际达到上传的效果。
但是move_uploaded_file函数有一个特性,会忽略文件名末尾的/. ,估计是函数把/.当作路径来看待了,即
move_uploaded_file("/tmp/7ED.tmp","/www/uploads/up.php/.")
以此可以达到在上传文件名中使用数组和/.绕过白名单的效果。
单独面对move_uploaded_file函数使用/.也可以达到绕过黑名单上传的效果。
如果本案例最后没有move_uploaded_file函数,也可以利用windows的特性:【文件名末尾的.和空格会被自动删除】来进行绕过。
![php源码分析案例 | 文件上传绕过 php源码分析案例 | 文件上传绕过]()
首先将上传的文件名以符号 . 为分隔符打散为数组,然后array_pop在这里的作用是取数组最后一个元素,在前面拼接上一串md5和符号 . 即是最后实际上传的文件名。
我们上传的文件名既要避免触发后缀黑名单,又要在生成$newfile时补充上可用的后缀名。
面对这种情况,我当时在不清楚源码的情况下通过fuzz上传了up.php../php成功绕过,后面发现php在处理$_FILES['upload_file']['name']时,会忽略/符号以及它前面的内容,所以实际上传的文件名就是php
这个文件名没有后缀名,自然绕过了后缀黑名单,然后在array_pop(explode('.',$filename))又被获取到作为了新文件的后缀名,最后实际上传的文件名变成了一串md5.php,成功绕过后缀黑名单。
至于为什么0x01章节中文件名里可以使用/符号,是因为0x01章节的源码是取$_POST['save_name']的值作为文件名而非$_FILES['upload_file']['name']。
学习分析一串代码,也许取得的乐趣和成就感不如学一个新工具、新手法。但这是脚本小子进阶的必经之路。共勉~
喵,点个赞再走吧~
原文始发于微信公众号(小黑的安全笔记):php源码分析案例 | 文件上传绕过
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
点赞
https://cn-sec.com/archives/867129.html
复制链接
复制链接
-
左青龙
- 微信扫一扫
-
-
右白虎
- 微信扫一扫
-
评论