Apache RCE 취약점 Log4Shell (CVE-2021-44228)과 대응방안

냥린이·2021년 12월 11일
1

취약점 개요

2021년 11월 24일 Alibaba cloud 보안팀이 보고한 취약점 때문에 요며칠 난리도 아니다.

해당 취약점은 CVE-2021-44228, Log4Shell로 Apache software foundation에서 개발한 Java 로깅 프레임워크(프로그램을 작성하는 도중 로그를 남기기 위해 사용되는 자바 기반 로깅 유틸리티) Log4j 2의 log4j-core 모듈에서 발생하며, CVSS에서 가장 높은 심각도인 10점을 받았다.

제보는 11월에 되었지만 본격적으로 유명세를 떨치게 된 건 2021년 12월 10일 마인크래프트의 통신 서버를 제작하는 PapaerMC에서 해당 취약점을 이용한 대규모 해킹 시도를 발견하고 긴급 공지를 하게 되면서다.

이후 전세계적으로 관련 뉴스가 쏟아졌고 이를 인식한 KISA는 2021년 12월 11일에 대응 가이드를 배포했다.

오픈 소스인 Log4j 라이브러리를 쓰는 자바 웹 서버가 아주 많기 때문에 파급력이 상당할 것이고, 보안에 크게 관심 없는 일반 개발자들도 빠르게 조치를 하고 있는 것 같다. (slf4j 기본 로깅 모듈과 logback을 쓰는 경우에도 log4j에 종속된 모듈이 있다면 찾아서 조치하는 것이 좋다.)

취약점 상세

Log4j 2에 포함된 Recursive Analysis Functions과 Lookups, 즉 임의의 위치에서 log4j 구성에 값을 추가하는 기능을 악용한 것이다.

Log4j 2의 Lightweight Directory Access Protocol (LDAP)
Secure LDAP (LDAPS), Remote Method Invocation (RMI), Domain Name Service (DNS) 서비스를 지원하는 JNDI(Java Naming and Directory Interface)을 통해 페이로드를 응답으로 보낼 시 RCE가 가능하다. (프로토콜은 Log4j.allowedJndiProtocols 속성에서 추가로 지정할 수도 있다.)

JNDI 인젝션은 대충 이런 식이다. 이 역시 깃헙에서 각종 PoC를 확인할 수 있다.

public static void main(String[] args) throws Exception{
    InitialContext ctx = new InitialContext();
    ctx.lookup("rmi://127.0.0.1/fgf4fp");
}

LDAP를 사용하는 경우 log4j2.allowedCdapHosts 속성에 나열된 호스트 또는 ip 주소와 로컬 호스트 이름 또는 ip 주소에 대한 참조가 지원된다. 이 LDAP 프로토콜을 이용해서 대규모 공격이 시도되고 있다. 지금까지 발견된 페이로드는 코인 마이닝, 스캐닝 등 다양하다.

Minecraft의 경우 채팅 메세지를 통해 취약점이 사용되었는데, 채팅을 통해 보내진 페이로드가 로그에 저장되었기 때문이다. 해킹 시연의 장이 되어버린 마인크래프트 이것이 이 취약점의 가장 무서운 점인데, 응용 프로그램에서 사용자 입력값을 받는 곳이 매우 많으며, 로깅 시스템은 오류 정보와 광범위한 이벤트를 일상적으로 계속 기록하기 때문에 취약점 활용도가 무궁무진하기 때문이다.

인기(?)에 힘 입어 다양한 PoC는 계속 추가되고 있다. Log4Shell PoC 더 알아보기

취약한 버전 및 제품

해당 취약점은 Apache Struts2, Apache Solr, Apache Druid, Apache Flink, Apache Spark, Apache Tomcat에서 발생 가능하며 2.2.0부터 2.14.1 버전 모두 취약하다.

취약할 수 있는 상용 제품 및 서비스는 현재까지 알려진 바로 Minecraft, Steam, Apple iCloud, Tencent, Twitter, Baidu, Didi, Cloudfare, Amazon, Tesla, ElasticSearch, Ghidra 이다. 실시간으로 확인하고자 하면 취약 서비스 목록 를 참고하면 된다.

대응 방안

JNDI lookup을 비활성화 하는 것이 핵심이다.
패치된 최신 버전으로 업데이트하거나, 용이치 않으면 직접 찾아가 조치를 해주어야 한다.
버전 별 조치 사항은 아래와 같다.

1. Java 8 사용 시

12월 10에 배포한 Apache Log4j 2.15.0으로 버전으로 업데이트
(12월 6일자 릴리즈는 불완전한 버전이다)

다만 Java 8을 사용하므로 Java 버전 업데이트가 필요할 수 있다

21.12.15 추가
PatternLayout nolookups 속성 추가의 Bypass 기법이 발견되었다고 한다. log4j 2 버전 2.16.0 으로 업데이트를 추천한다.

2. log4j 2.10.0 버전 이상 사용 시

Set log4j.formatMsgNoLookups or Dlog4j.formatMsgNoLookups to true

java 실행 인자에 nolookup을 활성화 하는 시스템 속성을 추가한다

java -Dlog4j2.formatMsgNoLookups=true -jar myapp.jar

main 메소드에서 System.setProperty를 추가해도 된다
Tomcat 등 서블릿 컨테이너 기반 서버는 각 컨테이너에 인자를 넣어야 할 수 있다

3. log4j 2.7.0 버전 이상 사용 시

Use %m{nolookups} in the PatternLayout configuration

설정 파일에서 로그 패턴에 nolookups을 추가해준다

PatterLayout %m -> %m{nolookups}

21.12.15 추가 Bypass 기법이 발견되었다고 한다. log4j 2 버전 2.16.0 으로 업데이트를 추천한다.

4. log4j 2.0.0 버전 이상 사용 시

Remove JdniLookup and JdniManager classes from log4j-core.jar

log4j-core.jar에 있는 JdniLoopkup과 JdniManager 클래스를 삭제한다

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

추가

log4j는 3-4명의 컨트리뷰터가 무상으로 제작한 라이브러리라고 한다.
이번 취약점이 발생한 jndi lookup plugin은 2013년 7월에 추가된 것으로
제작자는 한국인으로 국내 Y대 출신의 K씨로 파악된다. (apache issue log4j-313)
고의가 아니었음이 분명하고 개인 컨트리뷰터에게 비난이 가해지는 일이 없었으면 한다.

개인적인 감상을 추가하자면, 여러 이유 때문에 결국 개발자를 업으로 삼겠다고 다짐했고
며칠 전까지 보안 공부하는 주변 지인들에게 개발을 고려해보라고 말하고 다녔지만..
그동안 해왔던 보안 공부도 손 놓지 말아야겠다고 새롭게 다짐하는 계기가 됐다.

진정한 보안 내재화는 보안팀만 열심히 해서 되는 게 아니다.
개발자 개개인이 책임감을 가질 필요가 분명히 있다.

profile
홀로서기 기록장

0개의 댓글