flawopen.com/Incidents/log4shell-jndi-injection-december-2021
Log4Shell (CVE-2021-44228): 원인과 해결
CVE-2021-44228은 로그 데이터가 Log4j 2 조회와 JNDI 클래스 로딩을 유발하게 했습니다. Log4j를 업데이트하고 포함된 사본도 찾으세요.[1], [2], [4]
방문객이 한 말을 받아 적는 것만이 일인 직원이 있는 사무실을 떠올려 보세요. 누군가, 방문객이 특정 문구를 말하면 직원이 받아 적기를 멈추고 문구에 나온 주소로 가서 낯선 사람에게서 봉인된 봉투를 받아 그 안의 지시를 따른다는 것을 알아냅니다. 직원은 받아 적기만 하면 되는 사람이었는데 말이죠.[1]
핵심 개념 및 용어
메시지 룩업- 로그를 쓸 때 메시지 안의 ${...} 식을 값으로 바꿔 주던 Log4j 2 기능입니다. 2.15.0 이전에는 설정된 패턴뿐 아니라 메시지 안의 데이터에도 적용되었습니다.[1]
JNDI- Java Naming and Directory Interface. LDAP 같은 디렉터리 서비스에서 객체를 찾는 API입니다. 원격 서버로의 JNDI 룩업은 JVM이 불러올 클래스를 돌려줄 수 있었습니다.[1]
식 인젝션(CWE-917)- 신뢰할 수 없는 데이터가 식 평가기에 도달해, 데이터로 넘긴 텍스트가 명령으로 실행되는 것입니다.[1]
전이 의존성- 다른 라이브러리가 필요로 한다는 이유만으로 애플리케이션에 들어온 라이브러리입니다. Log4Shell 노출의 상당수는 아무도 목록에 올리지 않은 Log4j 사본에서 비롯되었습니다.[4]
프레임워크 매핑
- 이 가이드에서 설명하는 약점의 CWE 참조: CWE-20 CWE-502 CWE-917
- D3-OTF 아웃바운드 트래픽 필터링 — 이 가이드의 아웃바운드 네트워크 제한은 서비스 또는 호스트가 접근할 수 있는 대상을 줄입니다.
- CISA KEV — 추가일 2021-12-10 — CVE-2021-44228
사고 타임라인
Alibaba Cloud Security의 천자오쥔이 Apache에 결함을 비공개로 제보합니다.[1]
CISA가 긴급 지시 22-02를 발령해 미국 연방 기관에 Log4j를 찾아 완화하도록 요구합니다.[3]
Log4j 2.17.1이 CVE-2021-44832를 수정합니다. 2.15.0 이후 나온 세 CVE(CVE-2021-45046, CVE-2021-45105 포함) 중 마지막입니다.[1]
단계별 공격 실행 흐름
공격자의 텍스트가 로그 호출에 닿는다
애플리케이션이 기록하는 사용자 이름, 헤더, 검색어 같은 어떤 값이든 공격자가 고른 룩업 식을 담을 수 있습니다.[1]
소스 코드 비교: 취약한 구현 vs 보안 패치
설명용 Maven 설정입니다. log4j-bom을 가져오면 다른 라이브러리가 끌어온 사본까지 포함해 모든 Log4j 모듈이 하나의 최신 버전으로 해석됩니다. 이어서 enforcer 규칙이 2.17.1보다 오래된 log4j-core가 전이적으로라도 남아 있으면 빌드를 실패시키므로, 새 의존성이 취약한 코드를 몰래 다시 들여올 수 없습니다. 진짜 수정은 업그레이드이며, 애플리케이션 서버에서 외부로 나가는 LDAP와 RMI를 막은 것은 패치가 늦은 곳에서도 악용을 끊어 낸 심층 방어였습니다.
<!-- pom.xml: a direct dependency pinned to a vulnerable release -->
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.14.1</version>
</dependency>
</dependencies>
<!-- Nothing stops another library from pulling in an older log4j-core transitively. -->
<!-- pom.xml: one version for every Log4j module, and a build that fails on old ones -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-bom</artifactId>
<version>2.24.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.5.0</version>
<executions>
<execution>
<id>ban-vulnerable-log4j</id>
<goals><goal>enforce</goal></goals>
<configuration>
<rules>
<bannedDependencies>
<searchTransitive>true</searchTransitive>
<excludes>
<exclude>org.apache.logging.log4j:log4j-core:[2.0-beta9,2.17.1)</exclude>
</excludes>
</bannedDependencies>
</rules>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
엔지니어링 및 시스템 보안 강화 체크리스트
- ✓log4j-core를 2.17.1 이상(Java 7은 2.12.4, Java 6은 2.3.2)으로 올리고, 의존성 트리 어디서든 더 오래된 버전이 해석되는 빌드는 실패시킵니다.[1]
- ✓빌드마다 SBOM을 만들어 산출물과 함께 보관해, 앞으로 나올 공지를 몇 분 안에 영향받는 서비스와 연결할 수 있게 합니다.[4], [3]
- ✓소스 저장소뿐 아니라 배포된 산출물도 스캔합니다. 많은 제품에서 shaded 또는 번들된 JAR가 의존성 목록에서 Log4j를 숨겼습니다.[4]
- ✓애플리케이션 서버의 외부 통신을 기본 차단합니다. 악용에는 임의 호스트로 나가는 LDAP, RMI, DNS가 필요했습니다.[4], [3]
- ✓구조적 결함이 수정된 뒤에도 후속 CVE를 예상하고, 벤더의 수정이 자리 잡을 때까지 사고를 닫지 않습니다.[1]