
Log4j CVE-2021-44228 취약점에 대한 범용 해결 방법
이 프로젝트는 log4j CVE-2021-44228 취약점에 대한 일반적인 대응 방안을 제공합니다. 이는 단기적으로 프로젝트를 재빌드하거나 log4j-core jar 파일을 패치할 대안이 없을 때 사용할 수 있습니다.
이 아이디어는 매우 간단합니다. Java 런타임의 '-Xbootclasspath/a' 옵션을 사용하여 클래스 로더가 'JndiLookup' 클래스의 '빈' 버전을 로드하도록 강제하는 것입니다.
따라서 전체 대응 방안은 이 단일 클래스 'org.apache.logging.log4j.core.lookup.JndiLookup.java'로만 구성되며 다른 종속성은 없습니다.
편의를 위해 Maven을 통해 컴파일하고 jar로 묶을 수 있는 pom.xml도 제공되지만, 선호하는 JDK를 사용하여 'javac' 및 'jar' 명령어로 동일한 작업을 간단히 수행할 수도 있습니다.
이 'JndiLookup' 클래스의 빈 버전은 원래 log4j2 구현과 호환되지 않을 수 있습니다. 특정 클래스 로딩 상황에서 실패할 수 있기 때문입니다.
대응 방안을 적용하면 다음과 같은 메시지가 표시됩니다:
"WARN JNDI lookup class is not available because this JRE does not support JNDI.
JNDI string lookups will not be available, continuing configuration.
Ignoring java.lang.ClassCastException: class org.apache.logging.log4j.core.lookup.JndiLookup"
그럼에도 불구하고 Log4j2는 아무 문제 없이 계속 작동하며, JNDI 조회를 사용하지 않을 뿐입니다. 이렇게 하여 JNDI 조회가 비활성화되었습니다!
클래스를 컴파일하고 jar 파일을 생성한 후에는 Java 명령어의 시작 부분에 '-Xbootclasspath/a:<대응 방안 jar 파일 위치>' 옵션을 추가하고 jar 파일을 배치한 디렉터리를 지정하면 됩니다(예: log4j-workaround-1.0-SNAPSHOT.jar). 이를 수행하는 방법에 대한 예제는 개념 증명 섹션을 참조하세요.
이 대응 방안을 적용할 Java 명령어는 무엇이든 실행할 수 있습니다(WebLogic, Tomcat, Spring으로 빌드된 fat jar 등).
대응 방안에만 관심이 있고 실제로 작동하는지 확인하는 방법에는 관심이 없다면 다음 내용은 무시해도 됩니다.
접근 방식을 검증하기 위해 'POC' 폴더를 추가했으며, 여기에는 또 다른 Maven 프로젝트가 들어 있습니다. 단위 테스트를 사용하는 대신 fat jar의 명시적 명령줄 실행이나 제가 검증한 Tomcat과 같은 컨테이너 실행을 사용하는 프로덕션 설정에 가깝게 유지하고 싶었습니다.
개념 증명에는 두 개의 클래스가 있습니다. 'POC.java'는 명령줄에서 대응 방안을 테스트하고, 'POCServlet.java'는 애플리케이션 서버에서 동일한 것을 테스트합니다.
두 시나리오 모두 '${jndi:ldap://localhost/test}'를 로그하려고 시도합니다. 이로 인해 대응 방안이 적용되지 않으면 log4j가 로컬 호스트의 LDAP에 연결을 시도하고 연결이 거부되어 실패합니다.
명령줄 POC를 실행하려면(Maven에서 빌드한 후):
'target\log4j-workaround-1.0-SNAPSHOT\WEB-INF' 디렉터리로 이동하여 다음을 실행합니다(Windows 명령줄인 경우):
java -Xbootclasspath/a:..\..\..\..\target\log4j-workaround-1.0-SNAPSHOT.jar -classpath classes;lib\* com.github.grimch.log4j_workaround.poc.POC
Tomcat으로 POC를 실행하려면:
왜 '-Xbootclasspath'를 전혀 사용하지 않고 대응 방안 jar를 '일반' 클래스패스의 첫 번째 항목으로 넣지 않는가?
글쎄요, 일부 컨테이너는 배포된 애플리케이션 아카이브의 jar 파일이 시스템 클래스패스의 동일한 파일보다 우선하도록 클래스 로딩에 영향을 줄 수 있습니다. 반면 부트스트랩 클래스패스에 있는 것은 다른 모든 것보다 우선합니다.
그러나 동일한 기능(예: WebLogic의 'prefer-application-packages')을 사용하지 않는다는 것이 확실하다면 '-classpath' 대안을 선택할 수도 있습니다.