背景
还是之前的一个小项目,部署在专网中,等保在做了一次漏扫后,说是有个高危漏洞要求整改。打开漏洞扫描报告后,总体网络风险级别为:比较危险: nacos未授权访问漏洞
,漏洞详细信息如下:
Nacos
未授权访问!?这还了得??
我们知道, Nacos
结合了注册中心与配置中心,本身在进入后台管理页面时也有一个认证(当然,我们的 Nacos
部署在专网中,并修改了默认密码),这让我们误以为后续的服务注册、配置读取与更新也是开启认证的。显然这就是自以为是的想法,这就是光顾着使用技术,而没有相对深入研究导致的安全事故。其实,官方文档中明确说明: Nacos
服务端默认是不需要登录的,这样会导致配置中心对外直接暴露。
试想一下,你的服务注册、配置读取与更新接口竟然是暴露的,没有任何认证拦截的;尤其是配置中心,通过 URL
可以直接访问到完整的配置信息,甚至包括各种服务的密码信息等,就问怕不怕。。
Nacos官方文档列出了以下服务发现与配置管理的接口:
- 服务注册
curl -X POST 'http://127.0.0.1:8848/nacos/v1/ns/instance?serviceName=nacos.naming.serviceName&ip=20.18.7.10&port=8080'
- 服务发现
curl -X GET 'http://127.0.0.1:8848/nacos/v1/ns/instance/list?serviceName=nacos.naming.serviceName'
- 发布配置
curl -X POST "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test&content=HelloWorld"
- 获取配置
curl -X GET "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test"
漏洞验证
在进行整改即开启 Nacos
认证之前,我想先尝试验证一下,是不是确实存在未授权的访问。就拿获取配置的接口为例,通过 curl
获取或者直接浏览器访问: http://nacosIP:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test
。
这里我不放结果了,确实可以直接访问到。。啥也不说了,安全第一,开始整改~~
安全整改
开启认证
在 Nacos
的配置文件 application.properties
中,开启认证(将nacos.core.auth.enabled
的值从false
改为true
)。
nacos.core.auth.enabled=true
Note:鉴权开关是修改之后立马生效的,不需要重启 Nacos
服务。
验证漏洞
通过 curl
获取或者再次浏览器访问: http://nacosIP:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test
,发现接口403了,真棒。
其中,主要的错误信息是:unknown user!
com.alibaba.nacos.api.exception.NacosException: Request nacos server failed:
at com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy.requestToServer(NamingGrpcClientProxy.java:279) ~[nacos-client-2.0.3.jar:na]
at com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy.queryInstancesOfService(NamingGrpcClientProxy.java:169) ~[nacos-client-2.0.3.jar:na]
at com.alibaba.nacos.client.naming.remote.NamingClientProxyDelegate.queryInstancesOfService(NamingClientProxyDelegate.java:111) ~[nacos-client-2.0.3.jar:na]
at com.alibaba.nacos.client.naming.core.ServiceInfoUpdateService$UpdateTask.run(ServiceInfoUpdateService.java:182) ~[nacos-client-2.0.3.jar:na]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_333]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_333]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_333]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [na:1.8.0_333]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_333]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_333]
at java.lang.Thread.run(Thread.java:750) [na:1.8.0_333]
Caused by: com.alibaba.nacos.api.exception.NacosException: unknown user!
at com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy.requestToServer(NamingGrpcClientProxy.java:271) ~[nacos-client-2.0.3.jar:na]
... 10 common frames omitted
获取Token
获取 Token
是 POST
接口,这里通过 curl
携带用户名、密码来实现: curl -X POST '127.0.0.1:8848/nacos/v1/auth/login' -d 'username=nacos&password=nacos'
JWT
长这种样子的 Token
很是面熟呀,显然,这正是 JWT
(JSON Web Token),我们顺手到 jwt.io
网站上解析下 Token
中包含哪些内容。
携带令牌获取配置
携带令牌获取配置,成功。
客户端配置
在所有的微服务客户端(但凡要注册至注册中心的服务都需要配置。我这里相关的服务有:网关服务、系统服务、认证服务、MinIO对象存储服务、WebSocket消息推送服务、定时任务服务、系统监控服务等)的配置文件 bootstrap.yml
中添加以下配置:
spring.cloud.nacos.username=your-username
spring.cloud.nacos.password=your-password
Note:
- 看上去上面整改写了这好几个步骤,实际进行整改时,直接操作:开启认证与客户端配置两步即可。
- 这里的整改是直接开启了认证功能,如果需要更细粒度的权限控制,可参考官方文档添加用户、角色、分配权限。
Reference
- https://nacos.io/zh-cn/docs/auth.html
If you have any questions or any bugs are found, please feel free to contact me.
Your comments and suggestions are welcome!