首页 值得一看 🔍️

0x00 引言

JWT(JSON Web Tokens)是一个应用层消息保护开放标准RFC 7519,规定了一种Token实现方式,以JSON为格式。它在近年来被广泛应用于各种认证机制中,但也存在被误用的风险及由此产生的安全问题。

0X01 JWT

RFC 7519将JWT定义为一种紧凑且自包含的方式,用于在各方之间作为JSON对象安全地传输信息。此信息可以验证和信任,因为它是经过数字签名的。JWT可以使用秘密(使用HMAC算法)或使用RSA的公钥/私钥对进行签名。

在互联网领域中,JWT适用领域非常普遍,其主要使用场景有:

JWT本质上是一个字符串,分为三个部分:

Header: 存放Token类型和加密的方法
Payload: 包含一些用户身份信息.
Signature: 签名是将前面的Header,Payload信息以及一个密钥组合起来并使用Header中的算法进行加密

头部(Header)

头部用于描述关于该JWT的最基本的信息,例如其类型以及签名所用的算法等。这也可以被表示成一个JSON对象。

{
"typ": "JWT",
"alg": "HS256"
}

在头部指明了签名算法是HS256算法。

当然头部也要进行BASE64编码,编码后的字符串如下:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

载荷(Payload)

{ "iss": "admin",
  "iat": 1416794566,
  "exp": 1558333419,
  "aud": "www.example.com",
  "sub": "admin@example.com",
  "GivenName": "admin",
  "Surname": "root",
  "Email": "aroot@example.com",
  "Role": [ "Manager", "Project Administrator" ]
}

iss: 该JWT的签发者,是否使用是可选的;
sub: 该JWT所面向的用户,是否使用是可选的;
aud: 接收该JWT的一方,是否使用是可选的;
exp(expires): 什么时候过期,这里是一个Unix时间戳,是否使用是可选的;
iat(issued at): 在什么时候签发的(UNIX时间),是否使用是可选的;
其他还有:
nbf (Not Before):如果当前时间在nbf里的时间之前,则Token不被接受;一般都会留一些余地,比如几分钟;是否使用是可选的;

除此之外,payload中还可以包含更多有关该Token使用者的身份信息。

将上面的JSON对象进行base64编码可以得到下面的字符串。这个字符串我们将它称作JWT的Payload(载荷)。

eyJpc3MiOiJhZG1pbiIsImlhdCI6MTQxNjc5NDU2NiwiZXhwIjoxNTU4MzMzNDE5LCJhdWQiOiJ3d3cuZXhhbXBsZS5jb20iLCJzdWIiOiJhZG1pbkBleGFtcGxlLmNvbSIsIkdpdmVuTmFtZSI6ImFkbWluIiwiU3VybmFtZSI6InJvb3QiLCJFbWFpbCI6ImFyb290QGV4YW1wbGUuY29tIiwiUm19sZSI6WyJNYW5hZ2VyIiwiUHJvamVjdCBBZG1pbmlzdHJhdG9yIl19

签名(Signature)

将上面的两个编码后的字符串都用句号.连接在一起(头部在前),就形成了:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTQxNjc5NDU2NiwiZXhwIjoxNTU4MzMzNDE5LCJhdWQiOiJ3d3cuZXhhbXBsZS5jb20iLCJzdWIiOiJhZG1pbkBleGFtcGxlLmNvbSIsIkdpdmVuTmFtZSI6ImFkbWluIiwiU3VybmFtZSI6InJvb3QiLCJFbWFpbCI6ImFyb290QGV4YW1wbGUuY29tIiwiUm19sZSI6WyJNYW5hZ2VyIiwiUHJvamVjdCBBZG1pbmlzdHJhdG9yIl19

最后,我们将上面拼接完的字符串用HS256算法进行加密。在加密的时候,我们还需要提供一个密钥(secret)。如果我们用test作为密钥的话,那么就可以得到我们加密后的内容:

qmjRJ4WqDSunPEixLePXNGxotrhZCjxGFpHWl_EjNXg

最后将这一部分签名也拼接在被签名的字符串后面,我们就得到了完整的JWT,它可以作为Token放在下文所述的三个位置中的任何一个。

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTQxNjc5NDU2NiwiZXhwIjoxNTU4MzMzNDE5LCJhdWQiOiJ3d3cuZXhhbXBsZS5jb20iLCJzdWIiOiJhZG1pbkBleGFtcGxlLmNvbSIsIkdpdmVuTmFtZSI6ImFkbWluIiwiU3VybmFtZSI6InJvb3QiLCJFbWFpbCI6ImFyb290QGV4YW1wbGUuY29tIiwiUm19sZSI6WyJNYW5hZ2VyIiwiUHJvamVjdCBBZG1pbmlzdHJhdG9yIl19.qmjRJ4WqDSunPEixLePXNGxotrhZCjxGFpHWl_EjNXg

即为

base64(header).base64(payload).HMACSHA256(base64UrlEncode(header)+"."+base64UrlEncode(payload),secret)

0X02 其他概念介绍

1.Token Auth

在计算机科学中Token的含义十分广泛,而在Web安全中,我们通常所说的Token就是一次会话中验证身份和获取信息的凭证,典型代表有OAuth中的Access Token。会话Token是对客户端进行请求的令牌,本质上是由服务端生成的一串字符串,当第一次登录后,服务器会生成一个Token,并且将其返回给客户端,在之后的操作中,会话无需验证用户名和密码,客户端只需带上这个Token,就可请求数据。

Token的类型可分为两种:

  1. bearer. 包含一个简单的Token字符串.
GET /resource/1 HTTP/1.1
Host: example.com
Authorization: Bearer mF_9.B5f-4.1JqM
  1. mac. 由消息授权码(Message Authentication Code)和Token组成.
GET /resource/1 HTTP/1.1
Host: example.com
Authorization: MAC id="h480djs93hd8",
                   nonce="274312:dj83hs9s",
               mac="kDZvddkndxvhGRXZhvuDjEhGeE="

使用Token的认证请求的方式有三种

  1. 放在请求头
  2. 放在请求体
  3. 放在URI

客户端可以选择一种来实现,但是不能同时使用多种。同样的,开发者也可使用不同的值来作为Token,常见的方法有用设备号/设备mac地址作为Token、用session值作为Token等。

2.JOSE

JOSE 是一种旨在提供在各方之间安全传递声明(claims)的方法的规范集,其中设计的技术均与JWT相关,主要有以下几个部分构成:

JWS-JSON Web签名,针对JWT格式进行数字签名的操作规范
JWE-JSON Web加密,针对JSON数据进行加密的操作规范
JWK-JSON Web密钥,用于JSON对象描述加密密钥、纪要及的数据结构和表示方式
JWA-JSON Web算法,用于JWS或JWE所使用的数字签名或加密算法列表
JWT-JSON Web令牌,描述以JSON对象在通信交互过程中使用的,一种可以签名或加密的标准数据格式

以上五者的关系如下图所示。

image

3.JWKS

JSON Web密钥集(The JSON Web Key Set,JWKS)是一组密钥,其中包含公钥,用于验证授权服务器发布并使用RSA或ECDSA算法签名的任何JSON Web令牌(JWT)。

0x03 漏洞利用角度

1.利用角度综述

对于常用身份认证机制,通用的漏洞挖掘角度包括:

是否存在敏感信息泄露
存在鉴权不充分而产生的劫持
是否存在伪造
是否可以被爆破
………

2. JWT 常见漏洞存在位置

而对于JWT来说,它所面临的安全问题则更加棘手。这是因为JWT是一种非常复杂的机制,如上文所述,其包含JWT、JWS、JWE、JWK、多种密码算法、两种不同的编码方式(或者说序列化)、压缩、可能采用不止一种签名、对多个收件人的加密——这其中无论哪一个微小的环节出问题,都会导致漏洞的产生。

(1)Header部分

是否支持修改算法为none/对称加密算法
是否可以删除签名
插入错误信息
kid字段是否有SQL注入/命令注入/目录遍历
jwk元素是否可信
是否强制使用白名单上的加密算法

(2)Payload部分

其中是否存在敏感信息检查过期策略,比如 exp, iat

(3)Signature部分

检查是否强制检查签名
密钥是否可以爆破(如HMAC)
是否可以通过其他方式拿到密钥
采用了自身存在脆弱性的算法(如ECDH-ES)
签名方法之间是否存在冲突

(4)其他

重放
通过匹配校验的时间做时间攻击
修改算法非对称算法为对称算法(如修改RS256为HS256)
弱密钥破解
不安全的配置所导致的敏感信息泄露(如在报错信息中泄露签名)

0x04 漏洞利用工具

笔者在此仅列举一部分工具,其余大同小异的工具不再赘述。

1. 解码jwt

https://jwt.io/

image

2.破解及漏洞利用

jwt_tool

image

查看帮助说明:

python3 jwt\_tool.py -h
usage: jwt_tool.py [-h] [-b] [-t TARGETURL] [-rc COOKIES] [-rh HEADERS] [-pd POSTDATA] [-cv CANARYVALUE] [-np] [-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
  jwt                   the JWT to tinker with (no need to specify if in header/cookies)
  #要处理的的JWT(当在标头/cookie中时,无需指定)
optional arguments:
#可选参数
  -h, --help            show this help message and exit
  #显示帮助信息并且推出
  -b, --bare            return TOKENS ONLY
  #只返回TOKEN
  -t TARGETURL, --targeturl TARGETURL
                        URL to send HTTP request to with new JWT
                        #包含新JWT向目标URL发送HTTP请求
  -rc COOKIES, --cookies COOKIES
                        request cookies to send with the forged HTTP request
                         #向目标URL发送构造的HTTP请求cookie
  -rh HEADERS, --headers HEADERS
                        request headers to send with the forged HTTP request (can be used multiple times for additional headers)
                        #与伪造HTTP请求一起发送的请求头(可多次用于其他头)
  -pd POSTDATA, --postdata POSTDATA
                        text string that contains all the data to be sent in a POST request
                        #包含POST请求中要发送的所有数据的文本字符串
  -cv CANARYVALUE, --canaryvalue CANARYVALUE
                        text string that appears in response for valid token (e.g. "Welcome, ticarpi")
                        #响应有效令牌出现的文本字符串(例如“Welcome,ticarpi”)
  -np, --noproxy        disable proxy for current request (change in jwtconf.ini if permanent)
                       #禁用当前请求的代理(如果永久更改jwtconf.ini)
  -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)
                        #欺骗JWKS(使用-ju指定JWKS URL,或在jwtconf.ini中设置以自动执行此攻击)
                        k = key confusion (specify public key with -pk)
                        #密钥混淆(使用-pk指定公钥)
                        i = inject inline JWKS
                        #注入内联JWKS
  -ju JWKSURL, --jwksurl JWKSURL
                        URL location where you can host a spoofed JWKS
                        #URL位置,您可以在其中托管伪造的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
                        #篡改JWT内容
                        (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)
                        #HMAC-SHA令牌的破解密钥
  -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)
                        #用于破解的密钥文件(使用“kid”攻击签名时)
  -V, --verify          verify the RSA signature against a Public Key
                        (specify -pk/-jw)
                        #根据公钥验证RSA签名
  -pk PUBKEY, --pubkey PUBKEY
                        Public Key for Asymmetric crypto
                        #非对称密码体制的公钥
  -jw JWKSFILE, --jwksfile JWKSFILE
                        JSON Web Key Store for Asymmetric crypto
                        #用于非对称加密的JSON Web密钥存储
  -Q QUERY, --query QUERY
                        Query a token ID against the logfile to see the details of that request
                        #根据日志文件查询令牌ID以查看该请求的详细信息
                        e.g. -Q jwttool_46820e62fe25c10a3f5498e426a9f03a
  -v, --verbose         When parsing and printing, produce (slightly more) verbose output.
                        #在解析和打印时,生成(稍微多一些)详细的输出。

例如:使用JWT_TOOL进行漏洞检测

python3 jwt\_tool.py [jwt] -X a

image

含义:显示存在”alg”:”none”,更改Headers 中”alg”为none,Payload中”admin”为true.也就是说,通过把算法置空,篡改身份来达到越权的目的。

JSON Web Token Attacker-JOSEPH

特性:

识别和标记
JWS/JWE编辑器
(半)自动攻击
Bleichenbacher MMA
密钥混淆(aka算法替换)
签名排除
Base64url 编/解码器
新攻击的易扩展性

image

JSON Web Tokens-JWT4B(burp插件)

特性:

自动识别
JWT编辑器
JWTs重签名
签名检查
自动攻击可用,如“Alg无”和“CVE-2018-0114”
有效性检查并支持有效负载中的“expires”、“not before”、“issued at”字段
cookie传输JWTs中安全标志的自动测试

image

jwt-hack

jwtXploiter

0X04 靶场演示

我们在这里使用的靶场为webgoat。

使用docker一键式安装运行

 docker run -it -p 127.0.0.1:80:8888 -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 -e TZ=Europe/Amsterdam webgoat/goatandwolf:v8.2.1

或pull image下来之后再

 docker run -p 8080:8080 -t webgoat/webgoat-8.0

启动镜像后,访问 http://[IP]:[端口]/WebGoat/login 即可进入webgoat靶场

image

Tips-使用正则表达在代理工具的历史中搜索JWT特征语句:

ey[A-Za-z0-9_-]*\.[A-Za-z0-9._-]*         //网址安全的JWT版本
ey[A-Za-z0-9_\/+-]*\.[A-Za-z0-9._\/+-]*   //所有JWT版本(可能误报)

此处选择了Task4作为例子讲解jwt漏洞的利用。在这个题目中,我们需要更改令牌,并通过更改令牌成为管理员用户,一旦成为管理员,就能够重置投票。

image

先随便登陆一个账号。
image

我们可以看到Reset votes是旁边这个选项,但只有管理员才能使用。

我们先获取一个当前用户的token。

image

试着解码一下:

image

image

使用jwt_tools的“-T”参数进行调试,生成新JWT.

image

验证一下:

image

使用该jwt提交题目,成功取得了管理员权限,完成赛题。

image



文章评论

未显示?请点击刷新