Log4j 란?
Apache에서 만든 로깅용 자바기반의 오픈소스 라이브러리이다. 디버깅용이나 로그 적재에 주로사용한다.
Log for java라는 뜻을 줄여서 Log4j 라고 하며 Jakarta-project에서 Java를 위한 프로젝트 중 하나이다.
간단히 말해 로그를 출력하기 위한 라이브러리이다.
log4j 가 없어도 로그는 출력할 수 있지만 각 소스마다 sysout을 이용해 로그를 출력한다면 디버깅 로그가 필요 없을 경우에는 모두 추적하여 삭제하는 번거러움이 있고 sysout은 호출하면 할 수록 성능이 저하된다.
(궁금한 경우 루프문을 작성하여 sysout을 계속 출력해 보면 알 수 있다.)
취약점
최근 log4j에 대한 취약점으로 큰 이슈가 발생하였다. JNDI Injection 취약점을 이용하여 서버에서 악성 코드를 실행할 수 있다. 아래와 같은 위험이 있다고 한다.
- 대상 컴퓨터(서버)의 모든 권한 취득 가능
- 비밀번호 없이 내부망 접근 가능
- 악성 프로그램(랜섬웨어 등) 실행 가능
- 기업의 중요한 자료 삭제 등
취약점 조치
버전 업그레이드를 위해 공홈에서 사용중인 JDK 버전에 맞는 라이브러리를 다운로드 받는다.
https://logging.apache.org/log4j/2.x/download.html#
파일을 다운로드 받은 후 압축파일의 내용을 보면 필요한 파일보다 더 많은 파일이 있다.
지금 우리가 수행할 작업은 1.x 버전에서 2.x 버전으로 변경하는 작업이므로 해당 작업을 중점으로 설명하겠다.
( log4j2-2.x.x 버전 업그레이드는 라이브러리만 교체하면 되는것으로 알고 있음)
<라이브러리 교체>
프로젝트의 상황에 따라 일부 라이브러리는 차이가 있을 수 있다.
(예를 들면 remix / jdbc가 붙은 log4j 관련 라이브러리)
그러나 버전 업그레이드에 반드시 필요한 파일은 3개가 있으며 slf4j를 사용하는 경우 1개의 교체해야하는 파일이 있다.
log4j-core-2.x.x.jar | log4j-api-2.x.x.jar | log4j-web-2.x.x.jar | log4j-slf4j-impl-2.x.x.jar |
추가 | Slf4j 사용시 추가 ( 교체 : slf4j-log4j12-1.x.x.jar) |
기존 프로젝트에 삭제되어야하는 라이브러리는 다음과 같다.
- log4j-1.x.x.jar
- slf4j-log4j12-1.x.x.jar (slf4j를 사용하지 않는 경우에는 해당 파일이 없을 수 있으나 대부분의 프로젝트에는 있다.)
추가되어야 하는 라이브러리
- log4j-core-2.x.x.jar
- log4j-api-2.x.x.jar
- log4j-web-2.x.x.jar
- log4j-slf4j-impl-2.x.x.jar / log4j2-2.x.x용 바인딩 파일 (slf4j를 사용하지 않는 경우 제외)
slf4j를 사용하며 기존에 존재하는 라이브러리 중 유지해야하는 라이브러리
- slf4j-api-1.x.x.jar / 기존 소스에서 API를 사용하고 있으므로 삭제하지 않음
<설정 변경 : WEB.XML>
log4j2.xml 경로설정 - log4j-2.x 버전에서는 web.xml에서 경로나 파일명을 명시하지 않으면 기본값으로 classpath: 경로에서 log4j2-test.xml 또는 log4j2.xml 파일을 찾는다고 한다. (log4j 에서도 동일했던 것 같은데..)
하지만 명확하게 하기 위해 별도의 설정을 하도록한다.
<!-- 대상파일 web.xml -->
<!-- AS-IS : 변경 전-->
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:/log4j.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<!-- To-be : 변경 후-->
<context-param>
<param-name>log4jConfiguration</param-name>
<param-value>classpath:/log4j2.xml</param-value>
</context-param>
<listener>
<listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class>
</listener>
web.xml에 해당 코드가 없는경우 추가하도록 한다.
경험으로는 spring 3.1 버전에서는 해당 코드가 없는 프로젝트가 있었으며 spring 3.2 이후부터는 해당 코드가 있었다.
<설정 변경 : LOG4J2.XML>
log4j2.xml 파일에 대한 작성법은 여기서 다루지 않도록 한다.
관련링크 : https://logging.apache.org/log4j/2.x/manual/configuration.html
사용중인 설정파일의 내용은 아래와 같다.
<!-- 신규작성 파일 : log4j2.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="DEBUG">
<Properties>
<Property name="logNm">log_pattern_Layout</Property>
<Property name="layoutPattern">[%d{ISO8601}][%5p] [%c{4}]: %m%n</Property>
</Properties>
<Appenders>
<Console name="console" target="SYSTEM_OUT">
<PatternLayout pattern="${layoutPattern}" />
</Console>
<RollingRandomAccessFile
name="rolling_log"
fileName="./logs/file.log"
filePattern="./logs/pjt/pjt-%d{yyyy-MM-dd_HH}_%i.log"
immediateFlush="false"
append="true"
ignoreExceptions="false">
<PatternLayout pattern="${layoutPattern}" />
<Policies>
<!-- 30MB 용량이 초과시 DefaultRolloverStrategy 정책만큼 넘버링 -->
<SizeBasedTriggeringPolicy size="30 MB" />
<!-- 일별 로그 파일 생성-->
<TimeBasedTriggeringPolicy interval="1" modulate="true" />
</Policies>
<!-- 롤링 파일 1000개 까지 생성 -->
<DefaultRolloverStrategy max="1000" />
</RollingRandomAccessFile>
<Async name="async_log" includeLocation="true">
<AppenderRef ref="rolling_log" />
</Async>
</Appenders>
<Loggers>
<!-- 스프링 프레임워크에서 찍는건 level을 info로 설정 -->
<logger name="org.springframework" level="info" additivity="false" >
<AppenderRef ref="console" />
<AppenderRef ref="async_log" />
</logger>
<Logger name="jdbc.connection" level="info" additivity="false">
<AppenderRef ref="async_log" />
</Logger>
<Logger name="jdbc.audit" level="error" additivity="false">
<AppenderRef ref="async_log" />
</Logger>
<Logger name="jdbc.resultset" level="error" additivity="false">
<AppenderRef ref="async_log" />
</Logger>
<Logger name="jdbc.resultsettable" level="error" additivity="false">
<AppenderRef ref="async_log" />
</Logger>
<Logger name="jdbc.sqltiming" level="error" additivity="false">
<AppenderRef ref="async_log" />
</Logger>
<Logger name="com.ibatis" level="error" additivity="false">
<AppenderRef ref="async_log" />
</Logger>
<Logger name="java.sql" level="error" additivity="false">
<AppenderRef ref="async_log" />
</Logger>
<Logger name="com.kpmg.kr" level="error" additivity="false">
<AppenderRef ref="async_log" />
</Logger>
<Root level="debug">
<AppenderRef ref="async_log" />
<AppenderRef ref="console" />
</Root>
</Loggers>
</Configuration>
<설정 변경 : JAVA CODE내 사용>
slf4j를 사용했다면 과거 1.X 버전을 사용할때랑 동일하므로 변경할 내용이 없으나. 사용하지 않는 다면 아래 예제를 참조하여 수정하도록 한다.( 보통은 slf4j를 상당수 사용하기 때문에 ....)
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
// logger name이 현재 클래스 경로인 것을 찾는다.
private static Logger logger = LogManager.getLogger(this.getClass());
prvate static void write(String s){
logger.info(s);
}
작업을 완료하고 콘솔(예를 들면 이클립스)에서 Was 기동시 붉은색 로그가 아닌 검정색 로그가 주르륵 올라간다면 적용이 완료되었다고 볼 수 있다.
설정오류(설정에 오류는 있으나 컴파일 오류가 안나는 상태)의 경우 Was 기동시 붉은색 로그만 나타나게 된다면
즉, 스프링 관련 로그같은 별도의 검정색 텍스트가 보이지 않는다면 설정이 잘못되었다고 볼 수 있다.
<오류 발생 Case>
모두 적용을 완료한 후 톰켓 기준 WAS 기동시 에러메세지가 나타나는 경우가 있다.
org.apache.tomcat.util.bcel.classfile.ClassFormatException: Invalid byte tag in constant pool: 19
해당 현상은 톰켓 버그로 이 문제가 해결된 버전은 Tomcat을 사용함으로써 해결이 가능하다.
- Tomcat 9.0.x : 9.0.0.M18 이후
- Tomcat 8.5.x : 8.5.12 이상
- Tomcat 8.0.x : 8.0.42 이상
- Tomcat 7.0.x : 7.0.76 이상
해당내용 관련 StackOverflow
'Development > Java' 카테고리의 다른 글
[Spring Boot] application.properties 값 가져오기 (1) | 2024.05.29 |
---|---|
pom.xml sample (0) | 2024.05.03 |
logback 취약점에 따른 취약점 조치 (0) | 2021.12.20 |
log4j 2.x 버전 다운로드 (0) | 2021.12.14 |
[log4j] org.quartz.core.QuartzSchedulerThread 로그가 보기 싫을때 (0) | 2021.05.27 |