
HashiCorp Vault KMS에서 confluent-kafka의 TLS 인증서 검증 비활성화
심각도: 높음, CVSS 3.1 7.4
벡터 (v3.1): CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N
영향받는 버전: confluent-kafka >= 2.8.0, <= 2.14.2
수정된 버전: 2.15.0
CWE: CWE-295 (부적절한 인증서 검증)
구성 요소: confluent_kafka/schema_registry/rules/encryption/hcvault/hcvault_client.py
보고자: Rahul Karne
CNA: VulnCheck
confluent-kafka의 HashiCorp Vault KMS 클라이언트는 hvac.Client를 생성할 때 verify=False를 하드코딩하여, Schema Registry 필드 암호화 규칙을 통해 이루어지는 Vault HTTPS 연결에 대한 TLS 인증서 검증을 비활성화합니다.
취약한 코드는 다음 위치에 있습니다:
confluent_kafka/schema_registry/rules/encryption/hcvault/hcvault_client.py
영향받는 클라이언트는 다음과 같이 초기화됩니다:
self._client = hvac.Client(
url=vault_url,
token=token,
namespace=ns,
verify=False
)
verify=False가 무조건 적용되므로, 클라이언트는 자체 서명되거나 공격자가 제어하는 인증서를 포함한 신뢰할 수 없는 TLS 인증서를 수용합니다.
애플리케이션의 Vault 트래픽을 가로채거나 리디렉션할 수 있는 네트워크 위치의 공격자는 Vault 서버를 사칭하고, Vault 인증 자격 증명을 탈취하며, 위조된 Vault/KMS 응답을 반환할 수 있습니다.
영향받는 HCVault 통합은 Vault 토큰, 네임스페이스, AppRole 자격 증명에 대한 구성을 노출하지만, 영향받는 버전에서는 인증서 검증을 복원할 수 있는 지원되는 CA 번들 구성이나 이에 상응하는 메커니즘을 제공하지 않습니다.
애플리케이션과 HashiCorp Vault 사이에 네트워크 중간자(man-in-the-middle) 위치를 확보한 공격자는 다음을 수행할 수 있습니다:
X-Vault-Tokenrole_idsecret_id이는 Vault 기반 KMS 워크플로로 보호되는 데이터의 기밀성과 무결성을 손상시킬 수 있습니다.
confluent-kafka는 Apache Kafka용 공식 Confluent Python 클라이언트입니다.
이 취약점은 특히 다음을 사용하는 배포에 영향을 미칩니다:
Schema Registry encryption rules
↓
HCVault KMS integration
↓
hcvault:// key URI
따라서 영향받는 대상은 모든 confluent-kafka 사용자보다 좁습니다.
그러나 영향받는 기능은 이러한 배포가 암호화 키 관리 및 필드 수준 암호화를 위해 HashiCorp Vault에 의존하기 때문에 보안에 민감합니다.
HcVaultKmsClient.__init__()는 hcvault:// 키 URI를 파싱하고, Vault 기본 URL을 결정하며, hvac.Client를 생성합니다.
2.14.2를 포함한 영향받는 버전에서 관련 코드는 다음과 같습니다:
self._client = hvac.Client(
url=vault_url,
token=token,
namespace=ns,
verify=False
)
if role_id and secret_id and self._client is not None:
self._client.auth.approle.login(
role_id=role_id,
secret_id=secret_id
)
hvac 라이브러리는 궁극적으로 Python requests TLS 스택에 의존합니다.
다음 설정은:
verify=False
클라이언트가 원격 서버의 TLS 인증서를 검증하지 않도록 지시합니다.
결과적으로 일반적으로 거부되어야 할 인증서가 수용될 수 있으며, 여기에는 다음이 포함됩니다:
이는 지원되는 두 가지 인증 경로 모두에 영향을 미칩니다.
토큰 인증이 사용되면 Vault 토큰이 다음을 통해 전송됩니다:
X-Vault-Token
HTTP 헤더입니다.
공격자가 Vault 엔드포인트를 성공적으로 사칭하면, 공격자가 제어하는 서버가 이 토큰을 수신할 수 있습니다.
AppRole 인증이 사용되면 클라이언트는 다음을 전송합니다:
role_id
secret_id
다음으로:
/v1/auth/approle/login
따라서 성공적인 MITM은 두 AppRole 자격 증명을 모두 탈취할 수 있습니다.
영향받는 HCVault 드라이버는 다음을 포함한 구성을 읽습니다:
token.id
namespace
approle.role.id
approle.secret.id
그리고 관련 VAULT_* 환경 변수도 읽습니다.
그러나 영향받는 버전은 운영자가 다음을 수행할 수 있게 하는 구성을 노출하지 않습니다:
결과적으로 영향받는 통합을 사용하는 애플리케이션은 일반적인 패키지 구성을 통해 TLS 검증을 복원할 수 없습니다.
이 패키지는 안전한 기본값에 의존하는 대신 TLS 서버 인증서 검증을 명시적으로 비활성화합니다.
취약한 구성은 사실상 다음과 같습니다:
hvac.Client(..., verify=False)
다음이 아니라:
hvac.Client(..., verify=True)
또는 단순히:
hvac.Client(...)
여기서 검증은 기본적으로 활성화됩니다.
인증서 검증을 비활성화하면 TLS 연결에서 서버 인증이 제거됩니다.
연결은 암호화된 상태로 유지되지만, 클라이언트는 자신이 합법적인 Vault 서버와 통신하고 있는지 판단할 수 있는 신뢰할 수 있는 메커니즘이 없습니다.
이는 네트워크 중간자 공격에 필요한 조건을 만들어냅니다.
성공적인 악용에는 다음이 필요합니다:
애플리케이션이 영향받는 버전의 confluent-kafka를 사용합니다:
2.8.0부터 2.14.2까지.애플리케이션이 HCVault KMS 통합과 함께 Schema Registry 암호화 규칙을 사용합니다.
구성된 KMS 키가 다음을 사용합니다:
hcvault://
스킴.
가능한 예시는 다음과 같습니다:
필요한 MITM 위치가 확보되면 애플리케이션 수준의 권한이나 피해자 상호작용은 필요하지 않습니다.
poc_confluent_kafka.py는 로컬에 압축 해제된 confluent-kafka 2.14.2 wheel을 대상으로 이 문제를 시연합니다.
PoC는 다음을 사용합니다:
HcVaultKmsClient 구현.개념 증명은 다섯 가지 모드를 포함합니다.
| 모드 | 설명 |
|---|---|
cert | 로컬 모의 Vault를 위한 자체 서명 인증서와 키를 생성합니다. |
server | https://localhost:8443에서 모의 HTTPS Vault를 시작하고 수신된 요청을 표시합니다. |
control | verify=True를 사용한 보안 제어; 자체 서명 인증서를 CERTIFICATE_VERIFY_FAILED로 거부해야 합니다. |
token | 취약한 HcVaultKmsClient를 로드하고 신뢰할 수 없는 인증서를 수용함을 시연합니다. |
approle | 취약한 AppRole 인증 경로를 실행하고 role_id와 secret_id의 노출을 시연합니다. |
PoC 의존성을 설치합니다:
pip install hvac cryptography
압축 해제된 취약한 wheel을 PoC 옆에 배치합니다:
confluent_kafka-2.14.2-cp310-cp310-win_amd64/
└── confluent_kafka/
└── schema_registry/
└── ...
PoC는 압축 해제된 2.14.2 패키지에서 HcVaultKmsClient를 직접 임포트합니다.
tink와 같은 관련 없는 의존성을 스텁 처리하여, 완전한 Kafka 또는 KMS 환경 없이도 취약한 Vault 클라이언트 구성을 테스트할 수 있게 합니다.
두 개의 터미널을 사용합니다.
python poc_confluent_kafka.py server
모의 HTTPS Vault는 다음에서 수신 대기합니다:
https://localhost:8443
자체 서명 인증서를 사용합니다.
먼저 적절한 인증서 검증이 자체 서명 서버를 거부하는지 시연합니다:
python poc_confluent_kafka.py control
예상 결과:
EXPECTED TLS failure: CERTIFICATE_VERIFY_FAILED
-> verify=True correctly rejected the self-signed cert
실행:
python poc_confluent_kafka.py token
취약한 HcVaultKmsClient는 서버가 신뢰할 수 없는 인증서를 제시함에도 불구하고 연결합니다.
모의 서버는 Vault 토큰을 관찰할 수 있습니다:
GET /v1/auth/token/lookup-self
X-Vault-Token: CNA-DEMO-VAULT-TOKEN
X-Vault-Namespace: cna-demo-namespace
실행:
python poc_confluent_kafka.py approle
모의 Vault는 다음을 수신합니다:
POST /v1/auth/approle/login
{"role_id": "CNA-DEMO-ROLE-ID", "secret_id": "CNA-DEMO-SECRET-ID"}
보안 control 모드와 취약한 token / approle 모드 사이의 대비는 이 동작이 테스트 환경이 아니라 하드코딩된 다음으로 인해 발생함을 보여줍니다:
verify=False
기본적인 보안 수정은 hvac가 인증서 검증을 수행하도록 허용하는 것입니다:
hvac.Client(
url=vault_url,
token=token,
namespace=ns
)
TLS 검증은 기본적으로 활성화되므로, 이를 명시적으로 비활성화할 필요가 없습니다.
견고한 구현은 다음을 수행해야 합니다:
기본적으로 TLS 인증서 검증을 활성화합니다.
구성 가능한 CA 번들을 지원합니다, 예를 들어:
ssl.ca.location
VAULT_CACERT
상호 TLS를 사용하는 환경을 위한 클라이언트 인증서를 지원합니다.
비어 있거나 거짓인 구성 값이 인증서 검증을 조용히 비활성화하지 못하도록 방지합니다.
자체 서명 및 기타 신뢰할 수 없는 인증서가 기본적으로 거부되는지 확인하는 회귀 테스트를 추가합니다.
이 취약점은 다음에서 수정되었습니다:
confluent-kafka 2.15.0
영향받는 버전은 다음과 같습니다:
2.8.0
through
2.14.2
2.15.0에서는 Vault 클라이언트 동작이 변경되어 TLS 검증이 기본적으로 활성화됩니다.
업데이트된 구현은 또한 다음을 포함한 TLS 관련 구성을 도입합니다:
ssl.ca.location
VAULT_CACERT
ssl.certificate.location
ssl.key.location
이를 통해 사설 PKI 인프라를 사용하는 배포가 인증서 검증을 비활성화하지 않고도 신뢰할 수 있는 CA 및 클라이언트 인증서 구성을 제공할 수 있습니다.
이 취약점의 점수는 다음과 같습니다:
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N
CVSS 3.1 점수: 7.4 — 높음
AV:N — 네트워크
취약한 Vault 통신은 네트워크 연결을 통해 발생합니다.
AC:H — 높은 공격 복잡도
공격자는 네트워크 MITM 위치를 확보하거나 Vault 연결을 리디렉션해야 합니다.
이는 중요한 전제 조건이며, 취약점이 심각(Critical)이 아닌 높음(High)으로 평가된 이유입니다.
PR:N — 권한 불필요
공격자는 영향받는 애플리케이션 내에서 권한이 필요하지 않습니다.
UI:N — 사용자 상호작용 불필요
공격자가 필요한 네트워크 위치를 확보한 후에는 사용자 상호작용이 필요하지 않습니다.
S:U — 범위 변경 없음
영향은 영향받는 애플리케이션과 그 Vault 상호작용의 보안 권한 내에 머뭅니다.
C:H — 높은 기밀성 영향
Vault 토큰 또는 AppRole 자격 증명이 공격자에게 노출될 수 있습니다.
I:H — 높은 무결성 영향