知足常乐

知足常乐

常见的开源项目未授权漏洞修复方案

2022-05-06

过完年很长时间没有写博客了,因为很忙,真的很忙😥
水一篇吧,刚好这几天在修复漏洞工单。

MongoDB 未授权访问漏洞

复现

使用nmap对目标机器扫描
image-1651132879139
无任何保护措施,直接IP连接,成功。
image-1651133397070

修复

创建admin用户
image-1651131556506


修改配置文件
linux机器一般在 /etc/mongodb.conf
2.6版本之前
image-1651131839643
2.6版本之后
image-1651131895293
重启mongo服务

systemctl restart mongodb

创建完admin用户 我们就可以用admin来创建我们所适用数据库的管理员了


我们登录数据库

> use admin
switched to db admin
> db.auth("admin","******")
1
use TestDB
switched to db TestDB
> db.createUser(
... {
... user:"dbadmin",
... pwd:"******",
... roles:["dbAdmin","dbOwner","userAdmin"]
... }
... )
Successfully added user: {
        "user" : "dbadmin",
        "roles" : [
                "dbAdmin",
                "dbOwner",
                "userAdmin"

这样,我们就可以用dbadmin来操作数据库了。

复测

我们再次用nmap来测试漏洞,可以看到已经获取不到server的信息了
image-1651132760774
我们再来看用驱动连接 可以看到,已经无法查询出来信息了
这里为什么会连接成功是因为mongo默认是连接到test库的,之后需要db.Auth来认证才可以切换数据库
image-1651133463813
我们写上密码再来连接 可以看到成功获取到数据库的信息
image-1651135467977

mongo的各种角色权限可以参考文末的链接。


ElasticSearch未授权访问漏洞

复现

直接请求目标主机的9200端口,请求索引列表API,可以直接get到所有索引的数据,同样道理直接请求DELETE接口很可能会对业务造成很大的危害。
image

修复

进行身份认证
我查了一下,我们的线上es版本是5.6.2,很老的版本了,es7以后好像是内置认证模块的。
5.6.x版本的话就需要x-pack插件的帮助了。


安装对应版本的x-pack插件

为了方便测试,我在windows安装了一个5.6.2版本的es

D:\elasticsearch-5.6.2\bin>elasticsearch-plugin install https://artifacts.elastic.co/downloads/packs/x-pack/x-pack-5.6.2.zip

进入/bin目录下,执行plugin命令安装对应版本的x-pack插件。
之后一直输入 y 即可

Continue with installation? [y/N]y
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@        WARNING: plugin forks a native controller        @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
This plugin launches a native controller that is not subject to the Java
security manager nor to system call filters.

Continue with installation? [y/N]y
-> Installed x-pack

D:\elasticsearch-5.6.2\bin>

在这里多插一句,如果网速比较慢不能在线安装,通常会把插件的zip包下到本地离线安装,但是要注意一个特别坑的地方,就是插件zip的位置一定要保证在es的根目录
大概这个样子

\bin
\config
\...
\plugins
x-pack.zip

然后在根目录执行安装命令 大概是这种格式
./bin/elasticsearch-plugin install file:///usr/local/elasticsearch-5.6.2/x-pack-5.6.2.zip

修改配置文件

我们找到\config\elasticsearch.yml 文件,添加下边几行

xpack.security.enabled: true   
http.cors.enabled: true
http.cors.allow-origin: '*'
http.cors.allow-headers: Authorization,X-Requested-With,Content-Length,Content-Type

重启服务
现在重新访问就会让输入账号密码了
image-1651739347598

默认的超级用户名和密码:

用户名:elastic
密码:changeme

输入密码确认就可以正常显示数据了。
我们打开f12查看请求
image-1651739824815

可以看到多了一个Authorization 请求头
image-1651739869671

base64解码就可以看到是我们刚刚输入的账密


修改密码
在es启动的情况下,替换掉 your_passwd 字段,然后请求这个接口。

curl -XPUT -u elastic:changeme 'http://localhost:9200/_xpack/security/user/elastic/_password' -d '{ "password" : "your_passwd" }'

image-1651741169248

再次进行登录即可

Java服务调用
这块可以参考文末的springboot集成带认证的ES,每个人具体的环境不太一样,我们的项目用的es版本比较老,用的还是TransportClient客户端 简单贴一下代码吧。非java代码,我们的是kt开发的。

	//这里setting新增了xpack.security.user
	if (!xpackPassWord.isNullOrBlank()){
            builder.put("xpack.security.user", "elastic:$xpackPassWord")
        }

        val settings = builder.build()
        val ips = ip!!.split(",".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()

        val client = if (plugin != null) {
            PreBuiltTransportClient(settings, plugin)
        } else {
            //PreBuiltTransportClient(settings)
            //这里换成了XPackTransportClient
            PreBuiltXPackTransportClient(settings)
        }
        for (ipAddress in ips) {
            client.addTransportAddress(InetSocketTransportAddress(InetAddress.getByName(ipAddress), port!!))
        }
        return client

复测

image-1651755792051
到这里就完全解决了。

Zookeeper未授权访问漏洞

复现

为了测试方便,我在本地安装了与目标环境一模一样的3.4.9版本的zk。

[zk: localhost:2181(CONNECTED) 12] ls /
[hello, zookeeper]
[zk: localhost:2181(CONNECTED) 13] getAcl /
'world,'anyone
: cdrwa
[zk: localhost:2181(CONNECTED) 14]

我们用zkCli连接到本地服务端之后,看下 / 下的Acl,发现权限是 ‘world’的。

Zookeeper对权限的控制是节点级别的,而且不继承,即对父节点设置权限,其子节点不继承父节点的权限。
Zookeeper提供了几种认证方式
world:有个单一的ID,anyone,表示任何人。
auth:不使用任何ID,表示任何通过验证的用户(是通过ZK验证的用户?连接到此ZK服务器的用户?)。
digest:使用 用户名:密码 字符串生成MD5哈希值作为ACL标识符ID。权限的验证通过直接发送用户名密码字符串的方式完成,
ip:使用客户端主机ip地址作为一个ACL标识符,ACL表达式是以 addr/bits 这种格式表示的。ZK服务器会将addr的前bits位与客户端地址的前bits位来进行匹配验证权限。

这里我们可以看到 world时候代表任何人都可以访问操作的。

修复

在这里我们选择zk的Acl限制指定的IP访问操作
setAcl [znode] ip:[ip]:[acl]
这里千万要注意不要写错,不然就无法再连接上来回退acl配置了

[zk: localhost:2181(CONNECTED) 23] getAcl /
'world,'anyone
: cdrwa
[zk: localhost:2181(CONNECTED) 24] setAcl / ip:10.94.xx.xx:cdrwa

对应的acl表达式可以参考文末具体的介绍

有权限的客户端操作
image-1651819546980
无权限的客户端操作
image-1651819566347
可以看到没有权限的IP无法对znode进行操作

怎么回退
如果不小心设置错了权限,那么我们需要用有权限的客户端重新对znode进行授权

 setAcl / world:anyone:cdrwa

我们用没权限的机器再次操作
image-1651819688541

这种方式应该是最简单的了。不过要注意下setAcl只能对当前znode进行授权,子node不继承权限,
也就是说 对 ‘/’ 节点授权,/dubbo 不受到权限影响。

文末参考