JWT伪造与SQL注入实战:Web安全攻防解析
1. PCTF解题报告:从JWT伪造到SQL注入的实战复盘
最近参加了一场PCTF网络安全竞赛,遇到了几个典型的安全挑战,涉及JWT伪造、Flask会话劫持和SQL注入等常见漏洞。作为安全从业者,这类比赛不仅能检验技能,更能发现实际开发中容易被忽视的安全隐患。下面我将详细拆解解题过程,这些技术同样适用于企业级安全防护。
2. JWT安全漏洞分析与利用
2.1 JWT基础结构解析
JSON Web Token由三部分组成,通过点号分隔:
- Header:声明令牌类型和签名算法(如HS256、RS256)
- Payload:包含声明(claims)如用户ID、过期时间等
- Signature:对前两部分的签名验证
典型漏洞场景是当服务端使用弱密钥或未验证签名算法时,攻击者可伪造任意身份。比赛中遇到的题目正是使用了默认密钥"secret"的HS256算法。
2.2 实战伪造过程
- 使用jwt.io在线工具解码获取的token
- 修改payload中的admin字段为true
- 用已知密钥重新签名(已知密钥为"secret"时)
- 替换原token发送请求
# Python示例代码 import jwt original_token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiZ3Vlc3QiLCJhZG1pbiI6ZmFsc2V9.7ZJQ7yFZQYw7z3X3j3X3j3X3j3X3j3X3j3X3j3X3j3X3" payload = jwt.decode(original_token, verify=False) payload['admin'] = True new_token = jwt.encode(payload, "secret", algorithm="HS256")关键点:生产环境必须使用强密钥(推荐32字节以上随机字符串)并定期轮换,禁用none算法
3. Flask会话伪造技术剖析
3.1 Flask会话机制安全缺陷
Flask的session cookie使用以下结构:
- 序列化会话数据(默认pickle)
- 使用密钥签名(防止篡改但可读)
- 不加密存储(内容可被解码)
通过flask_session_cookie_manager3工具可解码和伪造:
python3 flask_session_cookie_manager3.py decode -c "<cookie>" -s "weaksecret"3.2 防护方案对比
| 方案 | 优点 | 缺点 |
|---|---|---|
| 强密钥 | 简单有效 | 密钥泄露风险 |
| 会话存储服务端 | 最安全 | 需要额外基础设施 |
| 定期过期 | 限制攻击窗口 | 影响用户体验 |
| 绑定用户指纹 | 防止会话劫持 | 可能产生误判 |
4. SQL注入全链路攻防
4.1 常见注入类型实战
比赛中出现的几种注入场景:
- 布尔盲注:
admin' AND (SELECT SUBSTRING(password,1,1) FROM users WHERE username='admin')='a'--- 时间盲注:
1' UNION SELECT IF(SUBSTRING(database(),1,1)='a',sleep(3),0),2,3--- 报错注入:
1' AND ExtractValue(1, CONCAT(0x5c,(SELECT database())))--4.2 防御方案深度优化
- 参数化查询(以Python为例):
# 错误示范 cursor.execute("SELECT * FROM users WHERE username = '%s'" % username) # 正确做法 cursor.execute("SELECT * FROM users WHERE username = %s", (username,))- ORM安全实践:
- MyBatis严格使用#{}而非${}
- Django ORM避免使用extra()等原生SQL方法
- Laravel的Eloquent禁用raw query
- WAF规则配置示例:
location / { # 拦截常见SQL注入特征 if ($args ~* "union.*select") { return 403; } if ($request_uri ~* "(\'|\")(.*)(drop|alter|truncate)") { return 403; } }5. PHP安全特例分析
5.1 典型漏洞模式
- 动态包含漏洞:
// 危险代码 include($_GET['page'].".php"); // 修复方案 $allowed = ['home','about','contact']; if(in_array($_GET['page'], $allowed)) { include($_GET['page'].".php"); }- 反序列化漏洞:
// 危险操作 unserialize($_COOKIE['data']); // 安全建议 使用json_encode/json_decode替代序列化5.2 ThinkPHP框架加固
针对比赛中遇到的ThinkPHP3.2.3漏洞:
- 及时升级到最新安全版本
- 关闭DEBUG模式
- 过滤输入参数:
I('get.id',0,'intval'); // 强制转换为整数6. 防御体系构建建议
6.1 分层防护策略
| 层级 | 防护措施 | 实施示例 |
|---|---|---|
| 网络层 | WAF配置 | 正则过滤注入特征 |
| 系统层 | 权限最小化 | 数据库账户只读权限 |
| 应用层 | 安全编码 | 参数化查询+输入验证 |
| 数据层 | 加密存储 | 敏感字段AES加密 |
| 监控层 | 日志审计 | SQL语句异常检测 |
6.2 安全开发生命周期
- 设计阶段:
- 威胁建模(STRIDE方法)
- 安全架构评审
- 开发阶段:
- 使用安全编码规范
- 静态代码扫描(SonarQube等)
- 测试阶段:
- 渗透测试(Burp Suite自动化)
- 模糊测试(SQLMap等工具)
- 运维阶段:
- 实时监控(ELK日志分析)
- 应急响应预案
7. CTF实战经验总结
- 信息收集技巧:
- 检查robots.txt和.git目录
- 分析HTTP头(Server/X-Powered-By)
- 尝试常见备份文件(index.php.bak等)
- 工具链优化配置:
# SQLMap高效使用技巧 sqlmap -u "http://target.com?id=1" --batch --smart --level=3 --risk=3 --tamper=space2comment- 调试技巧:
- PHP错误开启:
ini_set('display_errors', 1); error_reporting(E_ALL);- Python Flask调试模式:
app.run(debug=True) # 仅限开发环境在真实业务系统中,建议建立SDL(安全开发生命周期)流程,将安全防护贯穿从需求分析到运维监控的全过程。对于关键业务接口,应当实施二次认证和请求签名机制。我在金融行业实践中发现,结合行为分析的动态防护往往比静态规则更有效,比如检测异常查询模式(短时间内大量分页查询等)。