Wargame.kr

Web_550

strcmp




550점대로 넘어왔습니다. strcmp 함수의 취약점을 이용한 문제인것같습니다.



문제에 접속하니 패스워드와 체크하는 버튼이 우릴 기다리고 있습니다.

view-source를 눌러 소스를 확인해봅시다.



POST로 값을 입력받아 password 변수와 비교를 하여 strcmp 함수의 결과로 0을 반환시키면 Flag를 뱉어주네요.

password 변수의 경우 더미값을 이용한 rand()로 생성한 랜덤값이기 때문에 추측하기 어렵습니다.

따라서 정상적인 방법으로는 패스워드를 맞출 수 없습니다.


이렇게 다른 패스워드 값을 넣어준다면  Wrong passwrod.. 메시지를 출력합니다.

구글링을 통해 찾아보니 PHP 5.3+ 버전에서는 strcmp 함수에 string 값이 아닌 Array 값을 입력 해 주었을 때 0을 반환한다고 합니다.

이러한 특성을 이용하여 인증을 우회해봅시다.



burpsuite를 이용하여 POST로 값을 요청해주었습니다.

password 값을 배열로 인식하도록 만들어준 후, 값을 요청해 준 결과 플래그를 뱉어내는 것을 확인 할 수 있습니다.

'Wargame > Wargame.kr' 카테고리의 다른 글

[Wargame.kr] Web_600_tmitter  (0) 2016.05.20
[Wargame.kr] Web_550_type confusion  (0) 2016.05.19
[Wargame.kr] Web_500_md5 password  (0) 2016.05.18
[Wargame.kr] Web_500_md5_compare  (2) 2016.05.18
[Wargame.kr] Web_500_fly me to the moon  (0) 2016.05.17

[H3X0R CTF 2016]

Web_10

cmp



대회 초중반쯤 공개 된 10점짜리 web 문제입니다. 친구들이랑 저녁밥 먹고 다시 들어와 보니 공개 되어 있었죠.. 확인 해 봅시다.


패스워드를 입력하는 text box와 submit 버튼 하나가 있습니다.

여기에 아무 문자나 입력을 하고 submit 해 봅시다.




A를 submit 해 보았더니 2라는 결과값을 뱉어냈습니다.



d를 입력 했을 때는 -33이 나왔습니다.


PHP strcmp() 함수의 반환값의 특성을 이용한 문제인 것 같습니다. 이 문제에서 str1은 flag, str2는 string을 가리키고 있는 것 같습니다.

아스키 코드 상으로 A보다 2만큼 위에 있는 문자는 C입니다. 



C를 입력해주니 15라는 값을 반환 해 주었습니다. C에 이어 다른 글자를 입력 해 주었을 때 위와 같이 양/음수로 나누어 출력을 해 주었습니다.



다른 문자들을 집어 넣어 2번째 문자는 0임을 알 수 있었습니다. 올바른 문자를 입력 했을 때 반환하는 숫자 값이 1씩 줄어드는 것을 보니, 이 값은 남은 string의 길이 같습니다. flag의 총 글자 수는 16인 것을 여기서 알 수 있었습니다.



사실 python으로 스크립트를 작성하여 브포를 돌려볼까도 생각 해 봤지만, 음수도 있고, 반환하는 숫자 값도 일정하지 않아 직접 손으로 브포를 했습니다...

(저 숫자가 남은 글자 수인 것을 알아 낸 타이밍이 4자 이상 찾았을 때라... 귀찮기도 했습니다.)



flag is C0MP4R3_15_900D!



OverTheWire_Wargame Leviathan

[ level3 -> level4 ]


Leviathan3로 접속을 하면 홈 디렉토리에 level3 바이너리가 우릴 기다리고 있습니다. 해당 바이너리는 leviathan4 권한으로 setuid bit가 걸려있기 때문에 이번 레벨은 level3 바이너리로 풀어내면 될 것 같습니다. 한 번 실행 시켜 보도록 하죠.



바이너리를 실행시키면 패스워드를 요구하는데, 패스워드가 틀렸을 때 오류 메시지를 내뱉고 프로그램을 즉시 종료시킵니다.

긴 문자열을 보내도 segmentation fault같은 메시지를 안 내뱉는 것을 보니 BOF 유형은 아닌 것 같아 보입니다. gdb로 분석해보도록 합시다.



main 함수를 disassemble 한 상태입니다. 중간에 보면 printf로 0x804878f에 들어 있는 정보를 출력합니다. 확인 해 보니 해당 문자열은 "Enter the password> " 였습니다. 이 문자열은 우리가 바이너리를 실행시켰을 때 패스워드를 입력받기 직전에 내뱉는 문자열이었습니다. 따라서 그 이후에 진입하년 do_stuff 함수에 패스워드를 입력 및 비교하는 루틴이 들어 있을 것이라고 예상 할 수 있겠습니다.

그렇다면 do_stuff 함수도 분석 해 보도록 합시다.



중간에 보면 strcmp 함수를 호출하는 것을 볼 수 있습니다. 또한, strcmp 이후 if문의 조건을 통해 루틴을 분기시키는 부분이 있네요. strcmp를 통해 패스워드 일치/불일치 여부를 확인 한 후 이 if문에서 프로그램을 종료시킬 지, 다음 루틴으로 넘어갈 지 판별하는 듯 합니다.

또한, 조금 더 아래쪽을 살펴보면 system 함수가 호출되는 것을 확인 할 수 있는데, 위의 mov 명령을 통해 esp에 들어있는 주소의 문자열을 인자로 함수를 실행시킵니다.

strcmp 함수와 system 함수의 인자에는 어떤 값들이 전달되는 지 확인해보도록 합시다.



strcmp 함수의 1, 2번 인자는 우리가 입력한 문자열과 "snlprintf"입니다. 즉, 우리가 입력한 문자열이 snlprintf일 경우 프로그램을 종료시키지 않고 다음 루틴을 실행한다는 뜻이 되겠죠. 그리고 값이 동일할 경우 0x8048760에 들어있는 문자열을 출력 한 후 0x8048774에 들어있는 문자열을 인자로 system 함수를 실행시킵니다. 0x8048760은 "[You've got shell]!", 0x8048774는 "/bin/sh"인 것을 보니, snlprintf를 입력받았을 경우 전자의 문자열을 출력하고 쉘을 띄워주는 프로그램인 것 같습니다. gdb를 종료하고 프로그램을 실행시켜봅시다.



leviathan4로 통하는 패스워드를 깔끔하게 뱉어줍니다.



+ Recent posts