一、信息收集阶段
初始目标仅有一个登录页面,未发现关联子站、多余开放端口,子目录扫描也未获取有效信息。

Wappalyzer插件识别信息有限,仅能确认网站开发语言为PHP。

二、初步漏洞探测
首先尝试弱口令攻击,但常见组合均告失效。观察到登录请求中用户名与密码为明文传输,但存在登录次数限制机制。测试确认了admin用户真实存在。
随后针对前台的SQL注入漏洞进行探测,使用Burp Suite配合xss sql插件进行多轮测试,未发现可利用的注入点。

根据请求与返回包特征,推测网站基于ThinkPHP框架二次开发。尝试相关历史EXP均未成功。

发现网站注册功能处于开启状态,尝试注册账户以测试文件上传、越权等漏洞。

上传普通图片成功,但尝试上传PHP木马时全部失败。经过多种上传绕过方式Fuzz测试,确认网站采用了白名单机制,仅允许指定扩展名的文件上传。

后续又定位到头像上传及用户资料更新功能点,但测试后未发现可利用漏洞。

三、关键突破点分析
测试陷入僵局时,一个请求包中的Headers引起了注意,其包含JWT(JSON Web Token)。

解码后发现info字段被加密,结合特征推测为AES加密。

此时回想起信息收集阶段可借助findsomething插件。查看后收获关键信息:

发现了多个GitHub及Gitee项目链接。访问后获得了重要线索,测试出现转机,并印证了网站基于ThinkPHP6开发的推测。


随后将后端代码克隆至本地,进入代码审计环节以寻找漏洞。
四、代码审计与密钥获取
首先从JWT相关代码入手。通过搜索定位关键代码:


代码显示,JWT的密钥key需从环境变量env中获取。进一步定位到生成令牌的关键函数,该函数通过JWT工具类生成新令牌,并添加两个自定义声明:加密后的info与终端信息terminal,最后按OAuth2.0规范添加"bearer "前缀。
接着分析$info的加密过程,定位到str_encipher()函数:

在refreshToken方法中,先通过json_encode($info)将数据转为JSON字符串,再调用str_encipher函数进行加密,传入的密钥为config('app.aes_token_key')。
str_encipher函数逻辑为:若传入的$key为空,则默认使用config('app.aes_chat_key');此处明确传入了aes_token_key,故使用该密钥。由于$encode = true,最终调用\utils\Aes::encrypt方法进行AES加密。
查看\utils\Aes类相关代码,确认其encrypt方法实现简单,基于AES-128-ECB模式。

最后一步是获取缺失的JWT_SECRET和aes_token_key。首先查阅项目README及example.env文件。


在example.env中发现了默认密钥。首先验证JWT_SECRET。

验证成功。接着使用相同密钥解密AES加密的info字段。

成功获取原始信息,整个过程行云流水。随后尝试修改userid、role、account等字段值,并使用相同密钥重新进行AES加密。
为节省篇幅,此处直接展示最终构造的payload:

将加密结果替换原JWT中的info字段,在确认令牌有效期后,使用相同的JWT_SECRET重新生成JWT。

五、漏洞利用与登录
回到登录页面,使用之前注册的账号登录,并通过BurpSuite拦截登录请求包。

将请求包中data[authToken]的值替换为新生成的JWT,放行请求。登录成功,进入后台管理界面。


六、后台功能验证
后台确认文件上传功能确实采用了白名单机制。

系统内存在大量受害者记录。



记录显示,许多受害者在被威胁后因未交钱,其相关信息被群发。

