Oracle Java 인증서 검증 우회 취약점 CVE-2026-91403 영향 버전과 패치 방법

반응형
Oracle Java CVE-2026-91403 상세 정리: 영향 버전과 패치 방법

Oracle Java 인증서 검증 우회 취약점 CVE-2026-91403: 영향 버전과 패치 업데이트 방법

Java 기반 WAS나 업무 솔루션을 운영한다면 OS 패치뿐 아니라 실제 서비스가 사용하는 Java 런타임도 확인해야 합니다. 이번 글에서는 CVE-2026-91403의 원인과 영향 버전, 공식 다운로드 경로, Oracle JDK와 SUSE OpenJDK의 업데이트 방법을 정리합니다.

확인 기준: 2026년 10월 27일. 배포업체의 패치 상태와 다운로드 빌드는 이후 변경될 수 있습니다.

핵심 확인 사항

java -version으로 확인하는 Java가 점검 대상입니다. 다만 WAS의 별도 JDK, 솔루션 내장 JRE, 컨테이너 이미지 내부 Java까지 각각 확인해야 합니다.

1. CVE-2026-91403은 어떤 취약점인가?

이번 문제는 Java의 SSL/TLS 보안 기능인 JSSE(Java Secure Socket Extension)와 관련되어 있습니다. Oracle은 문제가 된 eMudhra 중간 CA 인증서 집합을 신뢰하지 않도록 하는 보안 업데이트를 발표했습니다.

Java 애플리케이션이 HTTPS 서버에 연결할 때는 상대 서버의 인증서를 검사합니다. 이때 신뢰할 수 있는 인증기관에서 이어지는 인증서 체인인지 확인하는데, 문제가 있는 인증서가 계속 신뢰되면 위조된 상대를 정상 서버로 받아들일 위험이 있습니다.

Red Hat은 관련 중간 CA의 취약한 개인키를 악용한 공격자가 임의 호스트 이름의 인증서를 발급하고, 중간자 공격으로 Java 클라이언트를 악성 사이트에 연결시킬 수 있다고 설명합니다.

CVE-2026-91403 개요
구분내용
관련 제품Oracle Java SE, Oracle GraalVM for JDK, Oracle GraalVM Enterprise Edition
관련 구성요소JSSE
Oracle CVSS v3.19.1점
영향기밀성 및 무결성 침해 가능
Oracle 공지일2026년 10월 21일

공식 근거: Oracle 보안 경고 및 영향 제품 목록.

2. 영향을 받는 Java 버전

Oracle 공식 공지에 명시된 버전

Oracle이 명시한 지원 제품의 영향 버전
제품영향 버전
Oracle Java SE 88u511, 8u511-perf
Oracle Java SE 1111.0.33
Oracle Java SE 1717.0.21
Oracle Java SE 2121.0.13
Oracle Java SE 2525.0.5
Oracle Java SE 2727.0.1
Oracle GraalVM for JDK17.0.21, 21.0.13
Oracle GraalVM Enterprise Edition21.3.20

이 표는 Oracle이 공지한 지원 버전 목록입니다. 목록보다 오래된 버전이라고 안전하다는 의미는 아닙니다. Oracle은 이전 릴리스도 영향을 받을 가능성이 있다고 안내합니다.

SUSE Linux Enterprise의 OpenJDK도 대상인가?

대상에 포함됩니다. SUSE 공식 추적 페이지는 SLES 15 SP7의 OpenJDK 8·11·17·21·25 패키지와 IBM Java 8을 영향 대상으로 표시합니다. SLES 16.0의 OpenJDK 17·21·25도 영향 대상으로 기재되어 있습니다.

SUSE 패치 상태 주의

확인 시점의 SUSE 페이지는 전체 상태가 Pending이며, 연결된 SUSE 보안 업데이트 공지가 없습니다. 따라서 이 글에서는 SUSE의 수정 RPM 버전을 확정해서 제시하지 않습니다. 적용 전 공식 페이지에서 해당 서비스팩과 패키지의 최신 상태를 확인해야 합니다.

SUSE 공식 CVE 페이지 및 패키지별 처리 상태 확인

3. 서버에서 실제 사용 중인 Java 확인하기

기본 Java와 RPM 패키지 조회

다음 명령은 조회만 수행합니다. SUSE 서버에서 Java 버전과 설치 경로, 패키지 릴리스를 함께 수집합니다.

# 기본 Java 버전
java -version

# 실제 실행 파일 경로
readlink -f "$(command -v java)"

# Java 공급업체 및 설치 경로
java -XshowSettings:properties -version 2>&1 \
  | grep -E 'java.home|java.vendor|java.version|java.runtime.version'

# 설치된 Java RPM 목록
rpm -qa | grep -Ei 'java|openjdk|jdk|jre'

# 현재 Java 실행 파일을 제공한 RPM
rpm -qf "$(readlink -f "$(command -v java)")"

# Java alternatives 구성
update-alternatives --display java

압축파일로 직접 설치한 Java는 rpm -qf에서 소유 패키지를 찾지 못할 수 있습니다. 또한 배포판은 보안 수정을 기존 버전에 반영할 수 있으므로, 상위 Java 버전 숫자와 RPM 릴리스를 함께 확인해야 합니다.

WildFly나 업무 솔루션이 사용하는 Java 조회

터미널의 Java와 서비스의 Java는 다를 수 있습니다. 먼저 프로세스 목록에서 대상 PID를 확인합니다.

ps -eo pid,user,args | grep '[j]ava'

아래 PID는 예시입니다. 실제 대상 서비스의 PID로 바꿉니다. 다른 계정의 프로세스는 조회 권한이 필요할 수 있습니다.

JAVA_PID=12345

# 실행 중인 Java 바이너리 경로
readlink -f "/proc/${JAVA_PID}/exe"

# 해당 실행 파일의 버전
"/proc/${JAVA_PID}/exe" -version

추가로 WildFly 시작 스크립트의 JAVA_HOME, systemd 서비스의 환경변수, JVM 옵션의 javax.net.ssl.trustStore 설정을 확인합니다. 사용자 지정 신뢰 저장소나 애플리케이션 자체 TLS 구현을 사용하면 별도의 검토가 필요합니다.

4. 패치 다운로드 사이트와 수정 빌드

Oracle의 공식 다운로드 페이지에서는 다음 빌드를 확인할 수 있습니다. 같은 21.0.13이라도 추가 버전이 붙은 수정 빌드를 구분해야 합니다. 다운로드 시점에는 보안 경고와 릴리스 노트를 다시 대조합니다.

확인 시점의 Oracle 다운로드 제공 빌드
계열제공 빌드다운로드
Java 88u511 b33Oracle Java 8
Java 1111.0.33.0.3Oracle Java 11
Java 1717.0.21.0.3Oracle Java 17
Java 2121.0.13.0.3Oracle Java 21
Java 2525.0.5.0.3Oracle Java 다운로드
Java 2727.0.1.0.3Oracle Java 다운로드

Java 8의 빌드 번호와 Java 11 이상의 추가 버전은 Oracle 다운로드 페이지에서 확인할 수 있습니다.

GraalVM은 Oracle JDK 일반 패키지로 대체하지 말고, 보안 공지의 Java SE 패치 안내와 My Oracle Support에서 해당 제품의 수정 패치를 확인합니다.

Oracle JDK는 버전과 사용 목적에 따라 라이선스 조건이 다릅니다. 운영 환경에 적용하기 전에 다운로드 페이지의 사용 조건 및 기존 계약을 확인합니다.

5. Oracle JDK 업데이트 방법: Linux 압축파일 설치 예시

다음은 Linux x64 서버에서 Oracle JDK 21을 압축파일로 설치한 환경의 예시입니다. 경로와 서비스명은 예시이며, 기존 Java 21 계열을 유지하면서 수정 빌드로 교체하는 절차입니다.

① 공식 패키지 다운로드 및 무결성 확인

공식 Java 21 다운로드 화면에서 jdk-21.0.13.0.3_linux-x64_bin.tar.gz와 해당 체크섬 정보를 받습니다. ARM 서버는 ARM64 패키지를 선택합니다.

cd /home/work
sha256sum jdk-21.0.13.0.3_linux-x64_bin.tar.gz

출력된 SHA-256 값이 Oracle 공식 체크섬과 일치하는지 비교합니다.

② 기존 JDK와 서비스 설정 보관

현재 Java 경로, 서비스의 JAVA_HOME, JVM 옵션, 별도로 등록한 사내 CA 인증서를 기록합니다. 기존 설치 디렉터리는 검증이 끝날 때까지 보관합니다.

기존 cacerts 전체를 새 JDK에 덮어쓰면 문제가 있는 신뢰 설정까지 복원할 수 있습니다. 필요한 사내 CA만 승인된 인증서 원본으로 새 저장소에 반영하고 지문을 검증합니다.

③ 새 디렉터리에 압축 해제

sudo mkdir -p /opt/java

sudo tar -xzf /home/work/jdk-21.0.13.0.3_linux-x64_bin.tar.gz \
  -C /opt/java

# 실제 생성된 디렉터리 이름 확인
ls -ld /opt/java/jdk*

확인된 새 JDK 경로의 bin/java -version을 실행합니다. 이어서 실제 서비스 시작 설정의 JAVA_HOME 또는 Java 절대경로를 해당 디렉터리로 변경합니다. 현재 터미널에서만 환경변수를 바꾸면 systemd 서비스에는 반영되지 않을 수 있습니다.

④ 서비스 재시작 및 실제 프로세스 확인

아래 example-was.service는 예시 서비스명입니다. systemd 유닛이나 drop-in을 수정한 경우에만 daemon-reload를 수행합니다.

sudo systemctl daemon-reload
sudo systemctl restart example-was.service
sudo systemctl status example-was.service --no-pager
sudo journalctl -u example-was.service -n 100 --no-pager

새 PID의 /proc/PID/exe를 조회해 수정 JDK로 실행되었는지 확인합니다. Java 파일만 교체하고 기존 프로세스를 계속 실행하면 변경이 반영되지 않을 수 있습니다.

기동 실패 시에는 보관한 서비스 설정과 기존 JDK 경로로 되돌려 복구할 수 있습니다. 이 경우 취약점 조치가 완료된 상태는 아니므로, 원인을 해결하고 수정 빌드를 다시 적용해야 합니다.

6. SUSE Linux Enterprise OpenJDK 업데이트 방법

SUSE RPM으로 설치한 OpenJDK는 SUSE가 제공하는 수정 패키지로 업데이트하는 방식을 우선 검토합니다. Oracle JDK를 설치하는 것은 공급업체 변경까지 포함하므로 기존 SUSE 패키지의 보안 업데이트와 구분해야 합니다.

① 현재 설치 상태와 패치 제공 여부 조회

cat /etc/os-release

rpm -qa | grep -Ei '^java-|^ca-certificates'

sudo zypper refresh

# 해당 CVE를 다루는 패치가 저장소에 있는지 조회
zypper list-patches --cve=CVE-2026-91403

# Java 21 관련 패키지와 저장소 확인
zypper search -si java-21-openjdk

검색 결과가 없다는 이유만으로 안전하다고 판단하면 안 됩니다. 패치 미배포, 저장소 미등록, 내부 미러 동기화 지연 여부를 함께 확인합니다.

② SUSE 수정 패치가 배포된 후 적용

공식 공지에서 해당 서비스팩의 수정 패치가 제공되었고, 등록된 저장소에서도 조회되는 경우에 적용합니다.

# 작업 영향 및 설치 예정 항목 확인
sudo zypper patch --cve=CVE-2026-91403 --dry-run

# 확인된 수정 패치 적용
sudo zypper patch --cve=CVE-2026-91403

위 명령은 수정 패치가 저장소에 등록되어 있을 때 사용하는 절차입니다. 확인 시점의 SUSE 공지는 Pending 상태이므로, 명령 실행만으로 조치 완료를 보장하지 않습니다.

③ 패키지 릴리스와 서비스 재기동 확인

rpm -qa | grep -Ei '^java-|^ca-certificates'
java -version

# Java 21 패키지 변경 이력에서 CVE 확인 보조
rpm -q --changelog java-21-openjdk \
  | grep -i -A 4 -B 4 'CVE-2026-91403'

변경 이력 검색은 보조 수단입니다. 최종 판단은 SUSE 공식 보안 공지의 수정 패키지 릴리스와 실제 설치 릴리스를 비교해서 수행합니다. 이후 해당 Java를 사용하는 WAS와 배치 프로세스를 재시작합니다.

7. 폐쇄망 서버의 업데이트 절차

폐쇄망에서는 외부망에서 수정 패키지를 확보한 뒤 내부로 반입합니다. Oracle 압축파일 방식과 SUSE RPM 방식은 준비물이 다릅니다.

설치 방식별 반입 자료
설치 방식반입 자료확인 사항
Oracle JDK 압축파일수정 JDK, 공식 체크섬, 릴리스 노트CPU 아키텍처, OS 지원, 사용 조건
SUSE OpenJDK RPM수정 RPM과 필요한 의존성, 서명 검증 자료, 보안 공지서비스팩·모듈·아키텍처 일치
컨테이너 이미지수정 Java를 포함한 이미지 또는 빌드 재료최종 이미지의 Java와 신뢰 저장소 상태

SUSE는 공식 CVE 페이지에서 수정 공지와 패키지를 확인하고, 조직의 SUSE 등록 계정 및 승인된 업데이트 저장소를 통해 확보합니다. 서로 다른 서비스팩의 RPM을 섞지 않습니다.

다운로드 단계와 반입 후 단계에서 각각 체크섬을 확인합니다. RPM을 사용하는 경우에는 신뢰할 수 있는 SUSE 서명키를 기준으로 다음과 같이 검증할 수 있습니다.

# Java 수정 RPM만 모아 둔 예시 디렉터리
cd /home/work/java-patch

# 패키지 서명 확인
rpm -K ./*.rpm

# 의존성 해결 및 설치 예정 내역 확인
sudo zypper --no-refresh install --dry-run ./*.rpm

# 검토 후 적용
sudo zypper --no-refresh install ./*.rpm

의존성 오류가 발생하면 필요한 패키지를 추가 확보합니다. 의존성 검사나 서명 검증을 생략하는 방식으로 진행하지 않습니다.

8. 즉시 업데이트하기 어려울 때의 임시 완화

Oracle은 관련 루트 인증서 제거 또는 인증서 폐기 확인 활성화를 대안으로 안내합니다. 루트 제거는 해당 루트에 의존하는 정상 연결에도 영향을 줄 수 있습니다. 배포판별 인증서 별칭과 저장소 관리 방식이 다르므로 아래 예시는 Oracle JDK 11 이상을 대상으로 합니다.

Oracle JDK 신뢰 저장소 백업 및 대상 확인

경로는 예시이며 실제 서비스 JDK로 바꿉니다. cacerts가 심볼릭 링크라면 연결된 실제 파일과 관리 주체부터 확인합니다.

JDK_HOME=/opt/java/example-jdk

readlink -f "$JDK_HOME/lib/security/cacerts"

cp -p "$JDK_HOME/lib/security/cacerts" \
  "$JDK_HOME/lib/security/cacerts.backup-$(date +%Y%m%d%H%M%S)"

"$JDK_HOME/bin/keytool" -list -cacerts

공식 안내에 따른 대상 별칭 제거

대상 인증서와 영향 범위를 검토한 뒤 수행합니다. 비밀번호는 명령행에 직접 적지 않고 프롬프트에서 입력합니다.

"$JDK_HOME/bin/keytool" -delete -cacerts \
  -alias "emsignrootcag1 [jdk]"

"$JDK_HOME/bin/keytool" -delete -cacerts \
  -alias "emsignrootcag2 [jdk]"

"$JDK_HOME/bin/keytool" -delete -cacerts \
  -alias "emsigneccrootcag3 [jdk]"

"$JDK_HOME/bin/keytool" -delete -cacerts \
  -alias "comodoaaaca [jdk]"

처리 후 Java 프로세스를 재시작합니다. JDK 8은 저장소 경로와 명령이 다르므로 Oracle 공식 완화 가이드의 JDK 8 절차를 사용합니다. 사용자 지정 truststore도 별도로 점검해야 합니다.

인증서 폐기 확인 옵션

-Dcom.sun.net.ssl.checkRevocation=true
-Dcom.sun.security.enableCRLDP=true

이 옵션은 실제 애플리케이션의 JVM 시작 옵션에 반영해야 합니다. 폐쇄망에서는 인증서 폐기 정보 조회 경로에 접근할 수 있는지 확인하고, 연결 실패나 지연 여부를 사전에 검증합니다. 옵션 추가만으로 조치가 완료되었다고 판단하지 않습니다.

9. Docker 이미지와 Kubernetes Pod도 별도 조치

호스트 SUSE의 Java를 업데이트해도 컨테이너 내부 Java는 자동으로 바뀌지 않습니다. WildFly 이미지를 빌드할 때 사용한 Java 베이스 이미지나 이미지에 직접 복사한 JDK를 수정해야 합니다.

  1. 기존 이미지 내부의 Java 공급업체와 전체 버전을 확인합니다.
  2. 해당 공급업체가 수정했다고 확인한 베이스 이미지 또는 JDK를 확보합니다.
  3. 기존 cacerts가 COPY나 볼륨 마운트로 다시 들어오는지 확인합니다.
  4. 새 태그로 이미지를 빌드하고 테스트 환경에서 검증합니다.
  5. Harbor 등 내부 레지스트리에 올린 뒤 Deployment의 이미지를 변경합니다.
  6. 교체된 Pod 내부에서 Java 버전과 실제 TLS 통신을 확인합니다.
# 네임스페이스·Pod·컨테이너 이름은 예시
kubectl exec -n example-ns example-pod -c example-was -- java -version

여러 컨테이너를 사용하는 Pod는 Java를 실행하는 컨테이너마다 확인합니다. 베이스 이미지 태그가 같아도 이전 이미지가 캐시될 수 있으므로, 수정 이미지의 digest까지 기록하는 것이 좋습니다.

10. 패치 완료 후 검증 항목

  • 실행 경로: 실제 WAS 프로세스가 새 JDK를 사용하는지 확인
  • 전체 버전: 추가 버전 및 빌드 번호, RPM 릴리스까지 기록
  • 신뢰 저장소: 사용자 지정 truststore와 사내 CA 반영 상태 점검
  • 연계 통신: HTTPS API, TLS 기반 DB·LDAP·메일 등 실제 사용하는 연계 테스트
  • 로그: SSLHandshakeException, PKIX 오류, 인증서 경로 오류 확인
  • 다중 설치: 별도 JRE, 배치용 JDK, 컨테이너 내부 Java 누락 여부 확인

Oracle이 안내하는 CheckCerts.java 점검 프로그램도 보조 수단으로 사용할 수 있습니다. 공식 설명은 JDK 8 이상을 지원한다고 안내합니다. 다만 점검 프로그램의 실행 대상과 실제 애플리케이션의 Java 및 신뢰 저장소가 일치하는지 확인해야 합니다. :chatgpt-content-reference{index="11"}

패치 이후 인증서 오류가 발생하면 서버가 제공하는 인증서 체인과 사용하는 CA를 확인합니다. 인증서 검증을 끄거나 모든 인증서를 허용하는 코드로 해결하면 안 됩니다.

11. 자주 묻는 질문

SUSE Linux Enterprise 15이면 전부 취약한가요?

OS 버전만으로 판단할 수 없습니다. 설치된 Java 패키지와 실제 실행 경로, 신뢰 저장소, 적용 패치를 확인해야 합니다. SUSE 공식 페이지에 SLES 15 SP7의 여러 Java 패키지가 영향 대상으로 기재되어 있으므로 우선 점검 대상에 포함합니다.

Java 21을 사용하면 Java 25로 올려야 하나요?

우선 현재 Java 21 계열에서 해당 취약점이 수정된 빌드를 적용하는 방식을 검토합니다. 메이저 버전 변경은 WildFly와 업무 솔루션의 호환성 검증이 추가로 필요합니다.

웹브라우저를 사용하지 않는 WAS도 점검해야 하나요?

점검해야 합니다. 서버 애플리케이션도 외부 HTTPS API나 TLS 기반 서비스에 연결할 때 Java 인증서 검증 기능을 사용할 수 있습니다.

설치만 하고 재시작하지 않아도 되나요?

조치 완료로 판단하지 않습니다. 관련 프로세스를 재시작하고 실제 새 런타임으로 실행되는지 확인해야 합니다.

공식 참고자료 및 다운로드

반응형