본문 바로가기
시큐어코딩/JAVA

[시큐어코딩]Java에서 부적절한 인증서 유효성 검증 – 보안 연결의 허점을 막는 시큐어코딩 방법

by ICT리더 리치 2025. 4. 16.
반응형

HTTPS 연결이 되어 있다고 해서 모든 것이 안전할까요? 인증서를 '검증하지 않는' 코드 한 줄이, 전체 통신을 공격자에게 넘겨줄 수 있습니다.

안녕하세요, Java 기반의 웹 보안 및 Spring Boot 시큐어코딩에 관심이 많은 여러분. 오늘은 HTTPS 통신에서 자주 발생하는 심각한 실수 중 하나인 부적절한 인증서 유효성 검증 문제를 다뤄보려 합니다. 특히 Java 환경에서는 개발자들이 RestTemplate, HttpClient 등을 사용할 때, 인증서 검증을 생략하는 실수를 무심코 저지르기 쉽습니다. 오늘 포스팅에서는 Spring Boot 환경에서 잘못된 구현 사례부터, 안전한 구현 방식까지 실무 중심으로 정리해 드리겠습니다.

1. 인증서 유효성 검증이란 무엇인가?

인증서 유효성 검증이란 HTTPS 통신 시 서버가 제시한 SSL/TLS 인증서가 신뢰 가능한 기관(CA)에 의해 발급되었는지, 만료되지 않았는지, 올바른 도메인에 대응되는지 등을 확인하는 과정을 말합니다.

이 검증 과정을 거쳐야 사용자의 기기는 "이 서버는 안전하다"고 판단하고 통신을 시작합니다. 즉, 이 검증이 없으면

가짜 서버와도 무차별 통신

이 가능해집니다.

보안의 중요성을 강조하며 제스처를 취하는 20대 한국 여성 전문 강사
부적절한 인증서 사용을 단호하게 거부하는 보안담당자 모습

2. 개발자가 자주 저지르는 잘못된 코드

인증서 검증이 실패했을 때, 연결을 무조건 허용하도록 처리하는 아래와 같은 코드가 대표적인 보안 취약점입니다. 이는 테스트 환경에서 시작해 실서비스에 반영되는 경우가 많습니다.


import javax.net.ssl.*;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;

// ❌ 모든 인증서를 무조건 신뢰하는 매우 위험한 코드
TrustManager[] trustAllCerts = new TrustManager[]{
    new X509TrustManager() {
        public X509Certificate[] getAcceptedIssuers() { return null; }
        public void checkClientTrusted(X509Certificate[] certs, String authType) {}
        public void checkServerTrusted(X509Certificate[] certs, String authType) {}
    }
};

SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

⚠️ 이 코드는 테스트 목적으로 사용하더라도 실제 배포 환경에 포함되면 모든 인증서를 신뢰하게 되며, MITM 공격에 완전히 노출됩니다.


import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
import java.time.Duration;

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
    return builder
        .setConnectTimeout(Duration.ofSeconds(5))
        .setReadTimeout(Duration.ofSeconds(5))
        .build(); // ✅ 기본 TrustManager 사용 (CA 검증 포함)
}

✅ 이 방식은 JVM의 기본 인증서 저장소를 이용해 CA 체인을 자동 검증하므로, 별도 설정 없이도 안전한 HTTPS 통신이 가능합니다.

3. 왜 위험한가 – 공격자의 개입 시나리오

공격자는 사용자의 네트워크 중간에 위치해 가짜 인증서를 전달합니다. 인증서 검증을 생략한 앱이나 서버는 이 가짜 인증서를 신뢰하게 되며, 모든 HTTPS 통신이 공격자에게 노출됩니다.

  • 비밀번호, 토큰, 개인 정보 등이 중간자에게 실시간 탈취됨
  • 공격자는 자신이 진짜 서버인 것처럼 통신을 주고받음
  • 피해자는 HTTPS 연결이라 안심하며 계속 통신을 이어감

✅ 요약: 인증서 검증을 우회하는 행위는, 사용자의 보안 장치를 직접 해제하는 것과 같습니다.

4. 중간자(MITM) 공격 실제 흐름

중간자 공격(Man-in-the-Middle)은 사용자와 서버 사이에 공격자가 끼어들어 모든 데이터를 가로채거나 조작하는 공격입니다. 인증서 유효성 검증이 비활성화된 시스템에서는 이 공격이 매우 쉽게 성립합니다.

아래는 일반적인 MITM 시나리오입니다.

  1. 1️⃣ 사용자가 공용 Wi-Fi(카페 등)에 접속
  2. 2️⃣ 공격자가 위조된 인증서를 가진 프록시 서버로 응답
  3. 3️⃣ 앱이 인증서를 검증하지 않음 → 연결 허용
  4. 4️⃣ 모든 API 통신 데이터가 공격자의 프록시를 통해 유출

💡 HTTPS를 사용하더라도, 인증서를 제대로 검증하지 않으면 평문 통신과 다름 없습니다.

5. 안전한 시큐어코딩 패턴

Java 11과 Spring Boot 기반의 애플리케이션에서는 기본적으로 JVM의 신뢰할 수 있는 루트 인증서 저장소를 통해 SSL 인증서 유효성 검사가 자동으로 수행됩니다. 다만, 아래의 패턴을 통해 시큐어코딩을 강화할 수 있습니다.

  • RestTemplate, WebClient 등에서 SSLContext를 직접 설정하지 않는다
  • 테스트 환경에서도 인증서 우회 코드(TrustManager 무력화)는 절대 금지
  • 자체 인증서 사용 시 JDK cacerts에 등록하거나 -Djavax.net.ssl.trustStore 지정
  • @Profile("test") 조건을 이용해 테스트용 인증서 설정을 분리 관리

⚠️ 커스텀 TrustManager를 구현할 경우, 반드시 서버 인증서의 fingerprint(지문) 또는 CN(DNS 이름)을 명시적으로 검증해야 합니다.

6. 실제 기업에서 발생한 사고 사례

2018년, 한 유명 금융 앱이 인증서 검증 우회 코드를 포함한 채 배포되면서 화제가 되었습니다. 공격자가 단순한 MITM 프록시만으로 사용자 정보를 탈취할 수 있었고, 이후 해당 기업은 긴급 패치를 진행했습니다.

또한 2022년, 모 스타트업의 IoT 기기에서 인증서 유효성 검증을 생략한 채 업데이트 서버와 통신하여, 공격자가 펌웨어를 조작할 수 있는 상황이 발생했습니다. 이는 보안 부서가 아닌 일반 개발자의 실수였으며, 시큐어코딩의 중요성이 다시 한 번 부각되었습니다.

📌 인증서 검증 생략은 단순한 "편의 코드"가 아니라, 기업 전체를 위험에 빠뜨릴 수 있는 보안 리스크입니다.

7. 자주 묻는 질문 (FAQ)

Q 테스트 환경에서는 인증서 검증을 꺼도 괜찮지 않나요?

절대 권장되지 않습니다. 테스트 환경에서 우회 코드를 사용하면 해당 코드가 운영에 반영될 위험이 크며, 보안 기준이 흐려집니다. 모든 환경에서 인증서 유효성 검증은 필수입니다.

Q 인증서 검증을 유지하면서 테스트하는 방법은 없나요?

자체 서명 인증서(self-signed cert)를 사용하고, 이를 테스트 기기나 로컬 CA에 사전 설치하면 검증을 우회하지 않아도 됩니다. 보안은 유지하면서도 테스트 환경을 구성할 수 있습니다.

Q 앱에서 TrustManager를 재정의해야 할 경우, 안전하게 구현하려면?

커스텀 TrustManager를 쓸 경우 허용할 인증서의 fingerprint를 화이트리스트로 등록하고, 반드시 도메인 매칭 검사를 수동으로 수행해야 합니다. 오직 지정된 서버만 통신하도록 제한해야 합니다.

Q 앱 보안 진단에서 인증서 검증 우회가 어떻게 발견되나요?

보안 진단 도구가 MITM 프록시(예: Burp Suite)로 앱 통신을 가로채고, 위조된 인증서를 응답합니다. 이때 앱이 경고 없이 통신을 계속하면 '인증서 유효성 검증 미흡' 항목으로 탐지됩니다.

인증서 유효성 검증은 HTTPS 보안 통신의 마지막 방어선입니다. 실무에서는 단순한 실수처럼 보일 수 있지만, 그 한 줄이 전체 시스템의 보안성을 무너뜨릴 수 있습니다. 오늘 소개한 코드 패턴과 공격 시나리오를 숙지하고, 모든 프로젝트에서 철저한 검증 로직을 구현해 보세요. 작은 습관이 안전한 개발 문화를 만듭니다. 🔐

반응형