[Security] Log4j 0-day vulnerability( Log4Shell 취약점)

sania Ka·2021년 12월 11일
3
post-thumbnail

CVE-2021-45105 내용 일부 추가 : 2021/12/20
CVE-2021-45046 내용 일부 추가2 : 2021/12/17
CVE-2021-45046 내용 일부 추가 : 2021/12/16
NVD Metrics / 영향 받는 서비스 추가 : 2021/12/15
화이트 리스트 추가 : 2021/12/12
코드 추가(1차) : 2021/12/12
최초 작성 : 2021/12/11

CVE-2021-44228

Log4j 공식 문서

CVE-2021-44228: Apache Log4j2 JNDI features do not protect against attacker controlled LDAP and other JNDI related endpoints.

Severity: Critical

Base CVSS Score: 10.0 CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
NVD Metrics

Versions Affected: all versions from 2.0-beta9 to 2.14.1

지난 2021년 12월 9일 Apache Log4j에서 발견된 원격 코드 실행(RCE) 취약점이다.
마인크래프트 보안 취약점으로 알려져 있다.

Message lookup substitution이 활성화 되어있고, 공격자가 로그 메세지 혹은 메세지의 파라미터를 제어 할 수 있는 경우, 어떠한 인증절차 없이 LDAP 서버에 로드되어있는 임의의 코드를 실행 할 수 있는 취약점이다.

현재 Log4Shell 이라는 별명이 붙어있다.

신규 취약점인 CVE-2021-45046에 관한 내용은 이 글을 참고하길 바란다.


원인

Log4j의 클래스들중에서 이번에 문제가 된 부분은 StrSubstitutor와 StrLookup 부분이다.

JNDI Message lookup이 log4j에서 기본으로 실행된다는게 문제점이다.

간단히 설명하면, 별다른 보호기능 없이 JNDI를 통해 로거가 명령어를 실행하고 외부 서버에 접속을 시도한다. 이를 통해, 삽입된 코드를 실행하거나, 내부의 데이터를 노출하거나, 원격지의 코드를 실행하게 된다.


취약점 테스트

이 테스트는 취약점이 존재하는 Log4j 2.14.0 버전을 사용했다.

취약점 확인

테스트에 사용하는 Logger code


간단히 로그를 출력하는 코드이지만, 이 코드는 실제로 loopup을 시행한다. 실행 결과는 아래와 같다. 물론 실제로는 존재하지 않는 도메인으로 테스트를 진행하였기에, connection timeout이 발생한다.

실행 이후 콜스택 로그

콜스택을 추적해보면, Logger -> Loggerconfig -> Appender -> Layout -> StrSubstitutor -> JndiLookup 으로 이어지는 것을 확인 할 수 있다.
여기서 주목해야 하는 점은, 개발자는 JndiLookup에 관련된 그 어떠한 코드도 작성하지 않았다는 것이다. 이 코드를 응용한다면, 아래와 같은 취약점 공격이 가능해진다.

실제 위험성이 존재하는 코드

WAS가 동작하며, 해당 WAS에서 Log4j 2.14.0 버전을 사용한다고 가정하겠다.

테스트에 사용하는 Logger code 1


정말 간단하게, get 요청으로 들어온 request의 queryString을 logger를 통해 출력하는 코드를 작성했다.

공격 코드 1


간단하게 로컬에 ldap 더미서버를 만들고, 해당 서버에 접속을 시도하도록 작성하였다.

출력 1


모든 요청에 대한 수신처리와 코드 적재등을 하지 않았기에, 에러가 발생하지만, 실제 ldap 서버에 접속을 시도하는 것을 확인 할 수 있다.


테스트에 사용하는 Logger code 2


이번에는 QueryString이 아닌, UserAgent에 대해 log를 찍어보았다.

공격코드 2


마찬가지로 UserAgent에 공격 코드를 삽입했다.

결과 2


의도한대로 실행되는 것을 확인 할 수 있다.

정리

request에 포함 할 수 있는 데이터에 대해 별다른 처리를 하지 않고, 바로 로그를 출력하면 해당 코드는 언제든지 공격에 이용 될 수 있다. 공격에는 ldap 말고도, jndi를 통해 호출이 가능한 dns, RMI등을 사용 할 수도 있다.


영향

Log4j 2.0-beta9 부터 2.14.1을 사용하는 모든 프로젝트에 잠재적 취약점이 존재한다.

RCE이기 때문에 사실상 해당 취약점이 존재하는 컴퓨터에서 무슨짓이든지 가능하다.
단적인 예시로는, 취약점이 존재하는 Log4j를 사용하는 프로젝트들은 별도의 처리를 하지 않았다면, 언제든지 crash가 가능하며, 환경 변수등으로 관리하는 DB password 등을 탈취당할 수도 있다.

log4j를 사용하는 프로젝트들은 무수히 많기 때문에, java 기반으로 돌아가는 대부분의 서비스들이 영향을 받는다고 볼 수 있다.

가장 유명한 예는 마인크래프트가 있는데, 1.7부터 1.18 버전 사이의 모든 Release에 취약점이 존재한다.
특정 문자열로 이루어진 채팅을 멀티 서버에서 치는 경우, 단순하게는 멀티서버를 종료시킬 수 있고, 서버 컴퓨터의 정보를 탈취하는 등의 공격 또한 가능하다.

극적인 예로는 마인크래프트 멀티서버로 둠을 돌릴수 있다고 한다...

해당 문제를 해결한 1.18.1을 빠르게 배포하였지만, 그 이전의 릴리즈들은 여전히 보안 취약점이 존재한다. 물론 보안 패치를 공개하긴 했지만, 이를 적용하지 않은 서버들은 여전히 보안 취약점에 노출되어 있는 것이다.

또한 전자정부 프레임워크에서도 해당 취약점이 존재하니, 전자정부 프레임워크 3.0~4.0 버전을 사용하는 개발자들은 즉시 보안 패치를 하는 것이 좋겠다.

그 외에도 영향을 받는 서비스에는 Cloudflare, iCloud, Steam, Tencent QQ 및 Twitter 등이 있다.

보안 취약점을 확인하여 해결된 서비스 들은 링크에서 확인 할 수 있다.


해결방법

사용하는 Log4j를 2.15.0 이상의 버전으로 업데이트 한다.
다만, Log4j 2.15.0 이상을 사용하기 위해서는 jdk8 이상의 버전이 필요하므로, 업데이트 하기 어려운 상황이라면, log4j의 버전별로 조치 방법이 다르다.

The safest thing to do is to upgrade Log4j to a safe version, or remove the JndiLookup class from the log4j-core jar.

2.15.0이 완벽하게 패치 된 버전이 아니어서 추가 취약점이 발견되었다. 따라서 2.16.0 이상의 버전을 사용하기를 권고한다.
2.16.0도 마찬가지로, jdk8 이상의 버전이 필요하므로, 각 버전에 맞춰 업데이트 하기 바란다.

또 신규 취약점이 나와서 2.17.0으로 업데이트 하기를 권장한다.

log4j.version >= 2.17.0

현재 최신버전으로, 이 글에서 소개한 CVE-2021-44228 뿐만 아니라, 신규 취약점인 CVE-2021-45046, CVE-2021-45105도 패치된 버전이다

log4j.version == 2.16.0

현재 최신버전으로, 이 글에서 소개한 CVE-2021-44228 뿐만 아니라, 신규 취약점인 CVE-2021-45046도 패치된 버전이다.
CVE-2021-45105이 추가로 발견되었다.

log4j.version == 2.15.0

Log4j 2.15.0 부터 message lookup substitution의 기본값이 비활성화로 되어있기 때문에 특별히 조치할것은 없다.
2.15.0 버전에도 신규 취약점인 CVE-2021-45046이 존재하기 때문에, 버전을 2.16.0으로 올리기를 권고한다.

log4j.version >= 2.10

시스템 설정 log4j2.formatMsgNoLookups 또는 환경변수 LOG4J_FORMAT_MSG_NO_LOOKUPStrue로 설정한다.

Other insufficient mitigation measures are: setting system property log4j2.formatMsgNoLookups or environment variable LOG4J_FORMAT_MSG_NO_LOOKUPS to true for releases >= 2.10

그러나, 이 방법은 불완전하다. 말 그대로 임시 방편이며, 2.12.2 버전으로 업데이트 하는 것을 권장한다. 또는, 2.0-beta9 의 방법을 따라서 아예 클래스 파일을 제거하기 바란다.

log4j.version >= 2.0-beta9

JndiLookup 클래스를 zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class 명령어를 통해 class path에서 제거한다.

마인크래프트 서버

1.18

1.18.1로 업그레이드 한다.
불가능 하다면, JVM argument에 -Dlog4j2.formatMsgNoLookups=true를 추가한다.

1.17

JVM argument에 -Dlog4j2.formatMsgNoLookups=true를 추가한다.

1.12-1.16.5

파일을 받아 서버파일이 존재하는 디렉터리(폴더)에 두고, JVM 인수에
-Dlog4j.configurationFile=log4j2_112-116.xml
를 추가한다.

1.7-1.11.2

파일을 받아 서버파일이 존재하는 디렉터리(폴더)에 두고, JVM 인수에
-Dlog4j.configurationFile=log4j2_17-111.xml
를 추가한다.

1.7 이하

신경 안써도 된다.

참고문서

https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-44228
https://nvd.nist.gov/vuln/detail/CVE-2021-44228
https://logging.apache.org/log4j/2.x/security.html
https://blog.cloudflare.com/actual-cve-2021-44228-payloads-captured-in-the-wild/
https://oracle.com/security-alerts/alert-cve-2021-44228.html
https://issues.apache.org/jira/browse/LOG4J2-3201
https://www.minecraft.net/en-us/article/important-message--security-vulnerability-java-edition
https://github.com/apache/logging-log4j2/pull/608
https://en.wikipedia.org/wiki/Log4j#Log4Shell_vulnerability
https://en.wikipedia.org/wiki/Arbitrary_code_execution
https://www.xda-developers.com/log4j-security-vulnerability-minecraft-apple/


0개의 댓글