记某系统有趣的文件上传

admin 2024年5月13日01:27:17评论8 views字数 2802阅读9分20秒阅读模式
本次是一次漏洞复现记录,记录了一个有趣的后台文件上传漏洞,以后遇到类似的拦截可以参考这次的过程绕过。

本次是一次漏洞复现记录,记录了一个有趣的后台文件上传漏洞,以后遇到类似的拦截可以参考这次的过程绕过。
站点搭建,根据系统需要,使用phpstudy即可在windows上成功搭建

记某系统有趣的文件上传

0x01黑盒问路

使用默认口令进入后台,先对网站的上传功能进行黑盒测试,左侧栏中找到图库管理,正常点击上传按钮,弹出文件上传对话框。

记某系统有趣的文件上传

选择文件,使用一张测试图片,文件名随便写,反正之后要在数据包里修改。

记某系统有趣的文件上传

点击提交后,进行抓包,记一下上传路径,方便之后去看源码。

记某系统有趣的文件上传

修改文件名为test.php并发送数据包,从可以看到返回包的路径,文件名称被添加.jpg

记某系统有趣的文件上传

此时需要根据上传路径,看源码中的上传逻辑,寻找突破点。

0x02上传但没完全上传

/Admin/SEMCMS_Upfile.php

记某系统有趣的文件上传

从源码中可以看到,文件类型校验是从此处的filename获得,并截取了.后面的文件后缀

记某系统有趣的文件上传

之后使用正则对截取的后缀进行匹配,感觉这块可能存在问题。

记某系统有趣的文件上传

于是构造filename为test.jpg.php,进行测试发现,因为使用了end()函数,导致jpg没有被取到,未能绕过正则校验。

记某系统有趣的文件上传

提醒了允许上传的白名单,他人还蛮好的。

记某系统有趣的文件上传

继续看到下面的代码,发现原来是对POST传上去wname强行拼接了刚刚$filename的后缀。难怪之前直接上传后,返回的文件名多了个后缀。

记某系统有趣的文件上传

还有令人在意的是这个test_input()函数,跟进看一下,发现是个实现去除空格、去除反斜杠、对html字符进行实体编码功能的。

记某系统有趣的文件上传

最后就是熟悉的move_uploaded_file()函数写入文件,新的文件名就是刚刚拼接起来的$newname

记某系统有趣的文件上传

整理一下思路,目前的状况就是preg_match()没办法直接绕过,只能从其中正则匹配的jpg|jpeg|gif|png|doc|xls|pdf|rar|zip|bmp|ico这些后缀中选择,并添加到我们可控的文件名后面,让原本可执行的文件变成图片。这种简单粗暴的添加方式还是可以被绕过的。
秘密藏在windows文件命名规则中:

记某系统有趣的文件上传

在windows环境中,当创建的文件名中存在:时,文件名会被截断并生成空文件。以本系统为例,构造数据包,只需要控制$wname为test.php:,其他参数都符合上传要求即可。

记某系统有趣的文件上传

访问返回的路径,果然发现通过该方式成功上传php文件,但是内容并没有被写入,感觉比较鸡肋。

记某系统有趣的文件上传

0x03注入灵魂

之前也有碰到过类似的,虽然利用该windows系统中特有的方式上传php文件,但是无法写入信息,只能无奈放弃的情况。
根据偶然间看到的漏洞poc,师傅还利用了PHP语言在Windows上的一些奇妙特性<<再次进行上传,给第一次传上去的php写入内容,注入了灵魂。
与之前测试构造的数据包不太一样,poc中需要控制$wname为test.jpg.php:,其他参数都符合上传要求就行。
上传时,文件拼接后完整的名称为test.jpg.php:.jpg;创建文件时会生成test.jpg.php空文件。

记某系统有趣的文件上传

记某系统有趣的文件上传

记某系统有趣的文件上传

再次发送数据包,控制$wname为test,$filename为test.jpg<<
这里就需要提一下PHP语言在windows上的特性:

  • 大于号>相等于通配符问号?
  • 小于号<<相当于通配符星号*
  • 双引号"相等于字符.

根据描述,上传时,文件拼接后完整的名称为test.jpg<<,应该会匹配为test.jpg.php

记某系统有趣的文件上传

记某系统有趣的文件上传

但和预想的不同,并没有任何内容被写入php文件中。

记某系统有趣的文件上传

虽大佬诚不欺人,但最好还是编写代码验证一下,找找出问题的原因。因为该特性是PHP在windows下存在的,因此与具体的函数无关,推测在读文件的时候应该同样存在等效的通配符匹配效果,于是编写如下代码文件读取代码进行测试。

<?php
$file = @$_REQUEST['filename'];
$file_contents = @file_get_contents($file);
echo "匹配到的文件为:".$file_contents;

在测试代码的同目录下创建六个内容为文件名称的文件。

记某系统有趣的文件上传

使用test.jpg<<<进行匹配,果然先匹配到了test.jpgtest.jpg.jpg,从而导致给php文件写入失败。
<<效果测试:
需要注意单个<无法正常匹配到结果,只有连着使用两个或两个以上<才有通配符*的效果。

记某系统有趣的文件上传

删除test.jpg再次使用相同的参数请求,匹配到test.jpg.aaa

记某系统有趣的文件上传

删除test.jpg.aaa再次使用相同的参数请求,匹配到test.jpg.jpg

记某系统有趣的文件上传

删除test.jpg.jpg文件后再次使用test.jpg<<<进行匹配,成功获得.php文件

记某系统有趣的文件上传

对其他符号同样进行测试
>效果测试:
单独>可以匹配零个或一个字符,效果类似于通配符?,缺失多少拼接多少>就可以匹配到对应的文件。

记某系统有趣的文件上传

但经过测试无法代替文件名中的字符.使用

记某系统有趣的文件上传

"效果测试:
符号"可以匹配到字符.

记某系统有趣的文件上传

通过上述的测试,发现原来内容被写入到同目录下第一次测试时上传的test.jpg.jpg文件中=.=!
发现问题,就好解决,重新利用payload,更换文件名为test123上传即可。这次就没手贱放包了。

记某系统有趣的文件上传

创建空php文件test123.jpg.php

记某系统有趣的文件上传

写入内容

记某系统有趣的文件上传

成功执行

记某系统有趣的文件上传

根据上述匹配方式,尝试构造并测试其他poc
还是以给test123.jpg.php写入php代码为例,除了可以使用test123.jpg<<,具有相同效果的poc为:
test123.jpg">>p

记某系统有趣的文件上传

记某系统有趣的文件上传

test123.jpg"php

记某系统有趣的文件上传

记某系统有趣的文件上传

0x04后记

考虑到该特性是否与php版本有关,特意测试了在php5、php7以及php8中的利用,读写文件均可以成功。
从网上找到的文章解释来看,是因为在windows下,PHP中的部分函数会调用支持上述字符作为通配符的底层Windows API函数,从而产生的特性。这部分函数包括但不限于如下:

include()
include_once()
require()
require_once()
fopen()
copy()
file_get_contents()
readfile()
file_put_contents()
mkdir()
opendir()
readdir()
move_uploaded_file()
getimagesize()

因时间原因,这次关于特性的学习仅仅只停留在浅显的利用阶段,后续应该要好好看一下这部分的原理,加深理解,才能更好和狡猾的漏洞做斗争。

文章来源:奇安信攻防社区

https://forum.butian.net/share/2399

黑白之道发布、转载的文章中所涉及的技术、思路和工具仅供以安全为目的的学习交流使用,任何人不得将其用于非法用途及盈利等目的,否则后果自行承担!

如侵权请私聊我们删文

END

记某系统有趣的文件上传

原文始发于微信公众号(黑白之道):记某系统有趣的文件上传

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年5月13日01:27:17
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   记某系统有趣的文件上传https://cn-sec.com/archives/2073304.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息