问答
发起
提问
文章
攻防
活动
Toggle navigation
首页
(current)
问答
商城
实战攻防技术
漏洞分析与复现
NEW
活动
摸鱼办
搜索
登录
注册
记某系统有趣的文件上传
漏洞分析
本次是一次漏洞复现记录,记录了一个有趣的后台文件上传漏洞,以后遇到类似的拦截可以参考这次的过程绕过。
记某系统有趣的文件上传 =========== 本次是一次漏洞复现记录,记录了一个有趣的后台文件上传漏洞,以后遇到类似的拦截可以参考这次的过程绕过。 站点搭建,根据系统需要,使用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 <?php $file = @$_REQUEST['filename']; $file_contents = @file_get_contents($file); echo "匹配到的文件为:".$file_contents; ``` 在测试代码的同目录下创建六个内容为文件名称的文件。  使用`test.jpg<<<`进行匹配,果然先匹配到了`test.jpg`和`test.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函数,从而产生的特性。这部分函数包括但不限于如下: ```php include() include_once() require() require_once() fopen() copy() file_get_contents() readfile() file_put_contents() mkdir() opendir() readdir() move_uploaded_file() getimagesize() ``` 因时间原因,这次关于特性的学习仅仅只停留在浅显的利用阶段,后续应该要好好看一下这部分的原理,加深理解,才能更好和狡猾的漏洞做斗争。 \-----------------------------我是分割线----------------------------------------------- 关于PHP语言在Windows上特性的参考文章,感兴趣的师傅可以自行深入研究: [PHP源码调试之Windows文件通配符分析](https://xz.aliyun.com/t/2004)
发表于 2023-12-11 15:41:23
阅读 ( 36760 )
分类:
漏洞分析
20 推荐
收藏
7 条评论
Pseudoknot
2023-08-25 10:01
大哥,文章前面的图好像对不上
请先
登录
后评论
fagulas
2023-08-25 18:15
大佬,上传的图片好像有点问题
cloudcoll
回复
fagulas
我也感觉有问题,同一张图上传了好多次。
请先
登录
后评论
c铃儿响叮当
2024-01-04 01:03
TQL
请先
登录
后评论
刀刀
2024-06-22 10:46
TQL
请先
登录
后评论
LOGfggg
2024-06-25 22:53
这个靶机可以分享一下嘛,我想自己本地试试
请先
登录
后评论
秋殇
2024-07-25 15:21
学到了
请先
登录
后评论
请先
登录
后评论
中铁13层打工人
79 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!