问答
发起
提问
文章
攻防
活动
Toggle navigation
首页
(current)
问答
商城
实战攻防技术
漏洞分析与复现
NEW
活动
摸鱼办
搜索
登录
注册
记某系统有趣的文件上传
漏洞分析
本次是一次漏洞复现记录,记录了一个有趣的后台文件上传漏洞,以后遇到类似的拦截可以参考这次的过程绕过。
记某系统有趣的文件上传 =========== 本次是一次漏洞复现记录,记录了一个有趣的后台文件上传漏洞,以后遇到类似的拦截可以参考这次的过程绕过。 站点搭建,根据系统需要,使用phpstudy即可在windows上成功搭建 ![image.png](https://shs3.b.qianxin.com/butian_public/f755911596aa3eb7e85963596374f0aa77c5706ccd603.jpg) ### 0x01黑盒问路 使用默认口令进入后台,先对网站的上传功能进行黑盒测试,左侧栏中找到图库管理,正常点击上传按钮,弹出文件上传对话框。 ![image.png](https://shs3.b.qianxin.com/butian_public/f70134282ab52c36ddc97ec7affe87eb6c3857f04b7ff.jpg) 选择文件,使用一张测试图片,文件名随便写,反正之后要在数据包里修改。 ![image.png](https://shs3.b.qianxin.com/butian_public/f7110220f3e063b81bf69693531711f6ff41364da9ca0.jpg) 点击提交后,进行抓包,记一下上传路径,方便之后去看源码。 ![image-20231207163738868](https://shs3.b.qianxin.com/butian_public/f8231033b4c39711f19bfdad61c3aa9e634cc69121f8a.jpg) 修改文件名为`test.php`并发送数据包,从可以看到返回包的路径,文件名称被添加`.jpg` ![image.png](https://shs3.b.qianxin.com/butian_public/f158496956b2d42bc4783a26fd146a0b755307737a0ba.jpg) 此时需要根据上传路径,看源码中的上传逻辑,寻找突破点。 ### 0x02上传但没完全上传 /Admin/SEMCMS\_Upfile.php ![image.png](https://shs3.b.qianxin.com/butian_public/f955668f4ea6f7927666a784eb5fcb66f5b9dc04533a1.jpg) 从源码中可以看到,文件类型校验是从此处的`filename`获得,并截取了`.`后面的文件后缀。 ![image.png](https://shs3.b.qianxin.com/butian_public/f7580287557ff8ebb673eb6574759dfef0794e9acc05f.jpg) 之后使用正则对截取的后缀进行匹配,感觉这块可能存在问题。 ![image.png](https://shs3.b.qianxin.com/butian_public/f955907d4cdded5fd5fe6d50b4454dc7ccec222c0264b.jpg) 于是构造filename为`test.jpg.php`,进行测试发现,因为使用了end()函数,导致`jpg`没有被取到,未能绕过正则校验。![image.png](https://shs3.b.qianxin.com/butian_public/f6051922a9117d80f97d553be7a8b387cc30c3eb1e1a7.jpg) 提醒了允许上传的白名单,他人还蛮好的。 ![image.png](https://shs3.b.qianxin.com/butian_public/f3814152ef8a6bfa04c15c4b286cfddfc8fce77e29bd3.jpg) 继续看到下面的代码,发现原来是对POST传上去`wname`强行拼接了刚刚`$filename`的后缀。难怪之前直接上传后,返回的文件名多了个后缀。 ![image.png](https://shs3.b.qianxin.com/butian_public/f673322366f873be2cb0152c7d92cce28fbf0767d8d29.jpg) 还有令人在意的是这个test\_input()函数,跟进看一下,发现是个实现去除空格、去除反斜杠、对html字符进行实体编码功能的。 ![image.png](https://shs3.b.qianxin.com/butian_public/f7327644b814154a2fe591fcd5c1229b8ef4f72b78210.jpg) 最后就是熟悉的move\_uploaded\_file()函数写入文件,新的文件名就是刚刚拼接起来的`$newname` ![image.png](https://shs3.b.qianxin.com/butian_public/f74374234833ef54fe029cb33d931fa7aad456202aac1.jpg) 整理一下思路,目前的状况就是preg\_match()没办法直接绕过,只能从其中正则匹配的`jpg|jpeg|gif|png|doc|xls|pdf|rar|zip|bmp|ico`这些后缀中选择,并添加到我们**可控的文件名**后面,让原本可执行的文件变成图片。这种简单粗暴的添加方式还是可以被绕过的。 秘密藏在windows文件命名规则中: ![image.png](https://shs3.b.qianxin.com/butian_public/f173884d7f5a62d6f96c0f9a7dc76a57269ad3a09d7d4.jpg) 在windows环境中,当创建的文件名中存在`:`时,文件名会被截断并生成空文件。以本系统为例,构造数据包,只需要控制$wname为`test.php:`,其他参数都符合上传要求即可。 ![image.png](https://shs3.b.qianxin.com/butian_public/f985614acf51d04d0588772d3e9e3f9a7e60439908c69.jpg) 访问返回的路径,果然发现通过该方式成功上传php文件,但是内容并没有被写入,感觉比较鸡肋。 ![image.png](https://shs3.b.qianxin.com/butian_public/f594639eab9a2f91d0ae882fc2e58fa8025a20f4abd25.jpg) ![image.png](https://shs3.b.qianxin.com/butian_public/f3027325573ffd845d85977c7d7e672a0020910a0d570.jpg) ### 0x03注入灵魂 之前也有碰到过类似的,虽然利用该windows系统中特有的方式上传php文件,但是无法写入信息,只能无奈放弃的情况。 根据偶然间看到的漏洞poc,师傅还利用了PHP语言在Windows上的一些奇妙特性`<<`再次进行上传,给第一次传上去的php写入内容,注入了灵魂。 与之前测试构造的数据包不太一样,poc中需要控制$wname为`test.jpg.php:`,其他参数都符合上传要求就行。 上传时,文件拼接后完整的名称为`test.jpg.php:.jpg`;创建文件时会生成`test.jpg.php`空文件。 ![image.png](https://shs3.b.qianxin.com/butian_public/f100851b4779be9d921eb79655c4b3e63eee824700b58.jpg) ![image.png](https://shs3.b.qianxin.com/butian_public/f3311431b49eef71ba1243bbbda119ad2f5fa14d5da64.jpg) ![image.png](https://shs3.b.qianxin.com/butian_public/f514754fbd6f153a15070fc7f3d6596ec1086be90bee6.jpg) 再次发送数据包,控制$wname为`test`,$filename为`test.jpg<<` 这里就需要提一下PHP语言在windows上的特性: - 大于号`>`相等于**通配符**问号`?` - 小于号`<<`相当于**通配符**星号`*` - 双引号`"`相等于**字符**点`.` 根据描述,上传时,文件拼接后完整的名称为`test.jpg<<`,应该会匹配为`test.jpg.php` ![image.png](https://shs3.b.qianxin.com/butian_public/f871533c9bd7f4ebae32750fa5880400d6e7b7e719212.jpg) ![image.png](https://shs3.b.qianxin.com/butian_public/f7361099208cbbf303e6f08f0789edfc9950a70eea51c.jpg) 但和预想的不同,并没有任何内容被写入php文件中。 ![image.png](https://shs3.b.qianxin.com/butian_public/f2301516fe0396f1f8b354832cc3c2cfc04c6984a47cf.jpg) 虽大佬诚不欺人,但最好还是编写代码验证一下,找找出问题的原因。因为该特性是PHP在windows下存在的,因此与具体的函数无关,推测在读文件的时候应该同样存在等效的通配符匹配效果,于是编写如下代码文件读取代码进行测试。 ```php <?php $file = @$_REQUEST['filename']; $file_contents = @file_get_contents($file); echo "匹配到的文件为:".$file_contents; ``` 在测试代码的同目录下创建六个内容为文件名称的文件。 ![image.png](https://shs3.b.qianxin.com/butian_public/f889754c5baa69cc91a956ad568671c32c32b31f852ff.jpg) 使用`test.jpg<<<`进行匹配,果然先匹配到了`test.jpg`和`test.jpg.jpg`,从而导致给php文件写入失败。 `<<`效果测试: 需要注意单个`<`无法正常匹配到结果,只有连着使用两个或两个以上`<`才有通配符`*`的效果。 ![image.png](https://shs3.b.qianxin.com/butian_public/f373953aacdc027816eaa78f26c2ad223b75669187357.jpg) 删除`test.jpg`再次使用相同的参数请求,匹配到`test.jpg.aaa` ![image.png](https://shs3.b.qianxin.com/butian_public/f104827401dd172471fc9e5b8e9cae9f2593db6aa1f03.jpg) 删除`test.jpg.aaa`再次使用相同的参数请求,匹配到`test.jpg.jpg` ![image.png](https://shs3.b.qianxin.com/butian_public/f930612e2773a4eeb47de53eb9a0ac733279511a06587.jpg) 删除`test.jpg.jpg`文件后再次使用`test.jpg<<<`进行匹配,成功获得`.php`文件 ![image.png](https://shs3.b.qianxin.com/butian_public/f362991565189a5c68a1f9b0cd936791a2fc7e7fcfcb9.jpg) **对其他符号同样进行测试** `>`效果测试: 单独`>`可以匹配零个或一个字符,效果类似于通配符`?`,缺失多少拼接多少`>`就可以匹配到对应的文件。 ![image.png](https://shs3.b.qianxin.com/butian_public/f923532329bbd3f1885f4b1af5cb4abd1fd5f3925f398.jpg) 但经过测试无法代替文件名中的字符`.`使用 ![image.png](https://shs3.b.qianxin.com/butian_public/f365513505026e43d4c8d93ab6b90f889853aa44665c1.jpg) `"`效果测试: 符号`"`可以匹配到字符`.`。 ![image.png](https://shs3.b.qianxin.com/butian_public/f541020bcd6a20ac5cd2b883a16e95e059a3c6180f8e3.jpg) 通过上述的测试,发现原来内容被写入到同目录下第一次测试时上传的`test.jpg.jpg`文件中=.=! 发现问题,就好解决,重新利用payload,更换文件名为test123上传即可。这次就没手贱放包了。 ![image.png](https://shs3.b.qianxin.com/butian_public/f859833f2a10a2b7b72b22dfbb0a645de712d903388c4.jpg) 创建空php文件`test123.jpg.php` ![image.png](https://shs3.b.qianxin.com/butian_public/f421458eb6990763ea056fcd8669483289c25eb7fcda9.jpg) 写入内容 ![image.png](https://shs3.b.qianxin.com/butian_public/f4694673d9b7d4906cc3c4cebe8e69814037010bf20a0.jpg) 成功执行 ![image.png](https://shs3.b.qianxin.com/butian_public/f190097ab5b0b3d4daa3483ab38e3c0301c4c2f0257d4.jpg) **根据上述匹配方式,尝试构造并测试其他poc** 还是以给test123.jpg.php写入php代码为例,除了可以使用`test123.jpg<<`,具有相同效果的poc为: `test123.jpg\">>p` ![image.png](https://shs3.b.qianxin.com/butian_public/f9539507b0a6e03aa17cb5801f8b47f6a8d6dccf3e6a0.jpg) ![image.png](https://shs3.b.qianxin.com/butian_public/f17754806fccfaf988e97c5aef02a67935e96cc3bef27.jpg) `test123.jpg\"php` ![image.png](https://shs3.b.qianxin.com/butian_public/f463530047eb6a7b2e0295e9e39e0abcd77e4ef4a3100.jpg) ![image.png](https://shs3.b.qianxin.com/butian_public/f8878598b541619e0b2ef70527e02c5cd9ce9995e8834.jpg) ### 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
阅读 ( 35540 )
分类:
漏洞分析
19 推荐
收藏
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层打工人
72 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!