log4j는 그 동안에도 이슈가 종종 있었는데 이번 보안 취약점은 심각한 보안 결함이라고 한다.
현재(2021.12.9 ~ 2021.12.13) 사건이 이슈화 되었고 나는 이것을 빠르게 해결하기 위해 log4j 를 Logback으로 변경했다.
Log4j 란?
개발자는 여러 이유로 프로그램에 로그를 기록한다.
이것은 오류를 체크하는 로그일 수도 있고, 단순히 모니터링을 위한 로그일 수도 있다.
Log4j는 이러한 프로그램에 로그를 기록할 수 있도록 도와주는 라이브러리이다.
보안 취약점 원인
이 보안 취약점은 JNDI와 LDAP를 이용한다.
JNDI : JAVA 프로그램이 디렉토리를 통해 데이터(JAVA 객체)를 찾을 수 있도록 하는 서비스
LDAP : 분산 디렉터리 서비스에서 사용자, 시스템, 네트워크, 서비스, 앱 등의 정보를 공유하기 위한 오픈 프로토콜
JNDI의 인터페이스 중 하나가 LDAP이다.
그러므로 JAVA로 실행되는 프로그램은 [JNDI + LDAP] 로 데이터(JAVA 객체)를 찾을 수 있다.
이것을 Log4j 에서는 ${prefix:name} 라는 문법으로 JAVA 객체를 볼 수 있다.
해커는 로그가 기록되는 곳을 찾아 이 문법을 활용해 취약점을 이용할 수 있다.
대응 방안
대응 방안은 나무위키를 첨부했다. (Log4j 보안 취약점 사태 - 나무위키)
가장 안전한 방법은 log4j 를 2.15.0 이상으로 올리는 것이다. 하지만 이 방법은 Java 8이 필요하다. 2.12.1 버전 Java 7을 지원하는 마지막 버전이므로, 2.13.0 이상 버전을 사용중이라면 판올림에는 문제가 없다.
log4j 2.10.0 이상 사용 시 다음의 방법 중 한 가지 이상의 방법을 사용한다.
Java 실행 인자(Arguments) 에 시스템 속성을 추가한다.-Dlog4j2.formatMsgNoLookups=true
Java 실행 계정의 환경 변수 혹은 시스템 변수로LOG4J\_FORMAT\_MSG\_NO\_LOOKUPS=true
를 설정한다.log4j 2.7.0 이상 사용 시 log4j 설정(log4j.xml 등)에 PatternLayout 속성에 있는 %m 부분을 %m{nolookups} 으로 교체한다.
log4j 상기버전 미만일 경우 가장 어려운 상황으로, JndiLookup 클래스와 JndiManager 클래스를 읽지 못하도록 조치해야 한다.
log4j-core.jar 를 직접 빌드하거나, 자바 프로젝트에 패키지명까지 맞춰가면서 dummy화 시켜야 한다.
이 방법은 위에 링크한 KISA 인터넷 보호나라에서 쉽게 대응할 수 있는 방안을 제공하니까 반드시 열람하도록 한다.log4j 외에 다른 로깅 모듈(logback)로의 교체를 검토한다.
나는 대응 방안 중 마지막 방법, 다른 로깅 모듈을 사용하는 것으로 결정했다.
logback 으로 교체한 이유는 log4j 는 종종 보안 이슈가 있었고 log4j 보다 우월한 점이 많기에 교체를 결정했다.
logback 교체 방법
dependency 추가
dependencies {
compile group: 'ch.qos.logback', name: 'logback-classic', version: '1.3.0-alpha5'
compile group: 'ch.qos.logback', name: 'logback-core', version: '1.3.0-alpha5'
compile group: 'org.slf4j', name: 'slf4j-api', version: '2.0.0-alpha1'
}
logback 의 기반은 slf4j 이므로 slf4j 도 함께 추가해야 한다.
logback.xml 추가 (spring boot 를 사용한다면 logback-spring.xml)
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
<property name="directory" value="c:/javaLog"/>
<appender name="ROLLING"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${directory}/programname.log</file>
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${directory}/programname-%d{yyyy-MM-dd}.%i.log
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<Pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n
</Pattern>
</encoder>
</appender>
<appender name="STDOUT"
class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n
</Pattern>
</layout>
</appender>
<root level="trace">
<appender-ref ref="ROLLING" />
<appender-ref ref="STDOUT" />
</root>
</configuration>
파일은 classpath(잘 모르겠다면 아마 resources일 것이다)에 추가하면 된다.
ROLLING 은 파일을 남기기 위해 추가했고 STDOUT 은 로그를 찍어보기 위해서 추가했다.
directory 에 로그를 저장하고자 하는 경로를 지정
하면 된다. (만약 경로를 만들어도 로그 파일 생성이 안 된다면 쓰기 권한을 부여해보자)
기존에 로그를 사용하던 것처럼 마지막 <root level="?">
로 로그 수준을 정할 수 있다.

아래부터 높은 레벨이다 (ERROR > WARN > INFO > DEBUG > TRACE)
설정한 레벨 이상의 로그를 출력한다.
ex) INFO 설정 시 INFO, WARN, ERROR 로그가 출력된다.
- JAVA 소스에 직접 추가해야 하는 경우
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static Logger logger = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
logger.trace("trace");
logger.debug("debug");
logger.info("info");
logger.warn("warn");
logger.error("error");
}
}
logback.groovy? logback-test.xml? logback.xml?
아마 정상적으로 실행하고 로그를 찾아보면 logback.groovy 와 logback-test.xml 은 찾지 못했고 logback.xml 은 찾았다는 기록이 나올 것이다. 오류가 아니다.
[logback.groovy > logback-test.xml > logback.xml]
이 순서로 높은 우선순위를 가진다.
logback은 위 설정파일을 순서대로 검색하며 우선순위가 높은 설정파일을 찾으면 하위 설정 파일은 검색하지 않는다.
단순히 로컬에서 logback-text.xml 을 만들어 임시로 확인할 수도 있고 별도로 개발서버에만 추가하는 설정을 통해 로그를 다르게 추가할 수도 있다.
특정 조건마다 로그를 다르게 작성하고 싶다면 [org.codehaus.janino]
를 활용하면 된다. 분기문을 통해 유연한 로깅 코드를 개발할 수 있다.
logback 매뉴얼
Chapter 1: Introduction (qos.ch)
URL 이동하여 우측의 [Chapter Index]
참고하여 자세한 설명을 확인할 수 있다.
logback 에 대해서 자세히 알아볼 수 있는 블로그를 참조한다.
주말 사이에 심각한 보안 이슈가 있었는데 log4j 를 업데이트해서 해결한 사람도 많을 것이다.
그러나 log4j는 보안 이슈도 종종 나오고 logback 의 이점이 많으므로 이 기회에 바꾸길 잘했다고 생각한다.
'Programming > Java' 카테고리의 다른 글
Java: 윈도우 명령어 사용하기 / Window Command (0) | 2022.05.11 |
---|---|
JAVA 버전 변경이 안 되는 경우 (환경변수를 바꿔도 안 될 때) (4) | 2021.12.15 |
JAVA/자바 :: 설치 및 환경변수 설정 (0) | 2021.12.12 |