我正在参加「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的检测。
案例
案例一
下面是一个简单案例,首先进入网页然后抓包:
我们对其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
得到密码为aaab,于是我们便可以修改JWT里面user为admin:
实战
这里给大家带来一个题目方便大家更加深入了解该漏洞,进入网站后是以下界面:
需要我们购买按钮后提示我们账户余额不足,可能存在逻辑漏洞,于是我们继续分析一下。尝试修改发包里面的内容:
可以看到存在一个admin验证的操作,仔细想一下,因为要验证所以我们的请求包里一定有验证信息,包中的JWT表示的正是身份,因为需要密码,所以使用上面提到的软件进行爆破:最后得到密码为:
1Kun
我们就可以修改我们想要的内容了,具体参考下图:
我们抓包后修改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的格式进行构造从而实行绕过的操作,也是网站中经常会出现的漏洞,会照成严重的后果,我们要学习该漏洞的原理来推进防护措施,喜欢本文的小伙伴希望可以一键三连支持一下。