설명
TLS 연결에서 모든 인증서를 신뢰하거나 모든 호스트명을 허용하면 중간자 공격(MITM)에 취약해집니다. X509TrustManager의 검증 메서드를 비워 두거나 HostnameVerifier가 항상 true를 반환하면 서버 인증이 사실상 제거됩니다.
잠재적 영향
- 공격자가 위조 인증서를 사용해 TLS 연결을 가로챌 수 있습니다.
- 민감한 데이터, 세션 토큰, API 요청/응답이 도청 또는 변조될 수 있습니다.
- 테스트용 우회 설정이 운영 환경까지 유입되면 전체 통신 보안이 무력화될 수 있습니다.
해결 방법
- 기본 신뢰 저장소와 기본
HostnameVerifier를 사용하고, 특정 환경에서만 예외를 두지 않습니다. - 테스트용 self-signed 인증서가 필요하면 별도 trust store를 구성합니다.
- 모든 인증서 또는 모든 호스트명을 허용하는 커스텀 verifier, trust manager를 사용하지 않습니다.
예시
변경 전
java
import javax.net.ssl.HttpsURLConnection;
public class UnsafeHostnameVerifier {
void configure(HttpsURLConnection conn) {
conn.setHostnameVerifier((hostname, session) -> true);
}
}
변경 후
java
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
public class SafeTlsVerifier {
void configure(HttpsURLConnection conn) {
HostnameVerifier verifier = HttpsURLConnection.getDefaultHostnameVerifier();
conn.setHostnameVerifier(verifier);
}
}
설명:
- 변경 전: 호스트명이 무엇이든 항상
true를 반환하므로 서버 인증서의 대상 검증이 완전히 무력화됩니다. - 변경 후: 기본 hostname verifier를 사용해 TLS 라이브러리의 정상 검증 흐름을 유지합니다.
다른 검증 우회 설정
new X509TrustManager() { ... }에서checkClientTrusted,checkServerTrusted를 비워 두면 해당 인증서의 신뢰 검증을 건너뜁니다.- 이름 있는
class AlwaysTrueVerifier implements HostnameVerifier든 익명new HostnameVerifier() { ... return true; }든 항상 허용하는 구현은 호스트명 검증을 우회합니다. - Kotlin의
HostnameVerifier { _, _ -> true }도 같은 위험이 있습니다.object : HostnameVerifier { ... }나object : X509TrustManager { ... }로 구현할 때도 실제 검증을 수행해야 합니다.