구글로 가봅시다.



/s3cr3t




users.txt


'Wargame > Natas:OverTheWire' 카테고리의 다른 글

[Natas] Level5  (0) 2016.10.22
[Natas] Level4  (0) 2016.10.22
[Natas] Level2  (0) 2016.10.22
[Natas] Level1  (0) 2016.10.22
[Natas] Level0  (0) 2016.10.22

PythonChallenge

Level3



힌트를 봅시다.

하나의 소문자 주위에 3개의 큰 보디가드들이 양 옆에 있다고 합니다.

사진을 확인 해 보니 대문자*3, 소문자, 대문자*3의 형태를 띠고 있는 것이라고 볼 수 있겠네요.

소스를 확인해봅시다.



위와 같이 문자열이 주석처리 되어있네요.

레벨2와 마찬가지로 스크립트를 돌려봐야겠습니다.



input.txt에 위의 문자열을 박아주었습니다.

text에 저장한 후, 정규표현식을 이용하여 정확히 대문자*3, 소문자, 대문자*3의 형태를 가지고 있는 소문자만 추려내보았습니다.



linkedlist라는 문자열이 나왔습니다!


이번에는 html이 아니라 php네요.



[*] FLAG : linkedlist.php


'Wargame > PythonChallenge' 카테고리의 다른 글

[PythonChallenge] Level5  (0) 2016.06.27
[PythonChallenge] Level4  (0) 2016.06.27
[PythonChallenge] Level2  (0) 2016.06.27
[PythonChallenge] Level1  (0) 2016.06.27
[PythonChallenge] Level0  (0) 2016.06.27

SuNiNaTaS

Web Level3




3번째 문제입니다. 아무것도 주지 않고 공지사항 게시판에 글을 쓰라고 하네요.



소스를 확인 해 보니 역시 이곳에도 아무 힌트도 주어지지 않았습니다.

그렇다면 남은것은 써니나타스 웹페이지 자체의 공지사항에 글을 쓰라는 말이 되겠네요.



공지사항 게시판에는 Write 버튼이 없기 때문에 Q&A(FreeBoard)에서 글쓰기를 하여 해당 URL을 확인하였습니다.

http://suninatas.com/board/write.asp?page=1&divi=Free

위와 같은 형식으로 나와있는데, 공지사항의 경우 ~/list.asp?divi=notice 의 형태입니다.

그렇다면 여기서 divi=notice로 바꿔주면 NoticeBoard에 글을 쓸 수 있는 페이지가 나올 듯 합니다.


역시나, 해당 페이지가 나타났고 아무 내용이나 입력 후 Submit을 했더니 Authkey를 뱉어냈습니다.

'Wargame > SuNiNaTaS' 카테고리의 다른 글

SuNiNaTaS Web Level6  (0) 2016.05.09
SuNiNaTaS Web Level5  (0) 2016.05.09
SuNiNaTaS Web Level4  (3) 2016.05.07
SuNiNaTas Web Level2  (0) 2016.05.06
SuNiNaTas Web Level1  (0) 2016.05.06
OverTheWire_Wargame Narnia

[ level3 -> level4 ]




Level3의 문제입니다.

R/W 권한과 READ ONLY의 권한으로 파일을 각각 하나씩 open 해줍니다.

output 하는 경로의 경우 "/dev/null"로 고정이 되어있네요. input의 경우에는 사용자에게 직접 입력을 받습니다. 이 때, 입력은 argv[1]로 받으며 strcpy 함수를 이용하기 때문에 길이 제한이 없습니다. 따라서 이 때 BOF가 발생하게 되는데, ofile은 값을 지정해줬음에도 불구하고 ifile보다 먼저 선언되었기 때문에 ifile에서 32바이트를 넘어가는 길이의 입력을 받을 경우 ofile의 값에도 영향을 미치게 됩니다.

이러한 스택의 특성을 이용하여 level4로 갈 수 있는 패스워드를 따 보도록 합시다.

일단 ifile의 경우 overflow를 시키면 ofile의 값을 덮어씌우게 되는데, 이럴 경우 ofile의 포인터는 overflow 된 ifile의 중간에 위치하게 됩니다. 따라서 아래와 같은 payload를 사용하면 두 개의 파일에 따로따로 접근 할 수 있게 됩니다.




ifle과 ofile을 이어 붙인 그림입니다.

입력을 받을 수 있는 argv[1]에는 ///////////////////tmp/fstr3am_/tmp/fstr3am_/a 를 넣어줍니다.

그럼 첫 번째 fstr3am_ 이후의 위치가 원래 ofile의 시작 포인터입니다. 따라서 ofile을 끄집어 낼 경우 /tmp/fstr3am_/a가 딸려나오게 됩니다.

그리고 ifile을 꺼낼 경우 원래 ifile의 길이인 24byte를 초과했기 때문에 ofile의 마지막인 a 이후에 나오는 NULL Byte까지 인식을 하여 /tmp/fstr3am_/tmp/fstr3am_/a이 ifile의 전체 경로가 됩니다.

그렇다면 /tmp/fstr3am_/tmp/fstr3am_/ 의 경로에 /etc/narnia_pass/narnia4의 symbolic link를 걸어준 a라는 이름의 파일을 생성해주고, /tmp/fstr3am_/ 의 경로에 비어있는 a라는 파일을 하나 만들어주면 /tmp/fstr3am_/a에 level4로 통하는 패스워드가 복사 될 것입니다.



위와 같이 a라는 파일을 두 개 만들어줍니다.



그리고 위에서 설명했던 payload대로 입력을 해 주면 패스워드가 출력됩니다.

OverTheWire_Wargame Narnia

[ level2 -> level3 ]



이번 문제는 기본적인 BOF 문제입니다. strcpy 함수로 buf 변수에 argv[1]의 값을 넣어주는데, 인자 길이를 제한하지 않기 때문에 BOF 취약점이 존재합니다.

이를 이용하여 스택에서 쉘코드를 실행시키는 형태로 풀이하도록 하겠습니다.



먼저 스택의 크기를 가늠하기 위해 4바이트씩 늘려 가며 A를 출력해줍니다.

140바이트를 출력했을 때 segmentation fault가 터지는 것으로 보아 buffer 128byte + dummy 8byte + sfp 4byte + ret 4byte 의 구조를 띄고 있는 것 같습니다.

ret 값에 들어갈 리턴 값의 위치를 구하기 위해 gdb로 스택을 살펴보도록 하겠습니다.



main 함수의 strcpy 부분에 breapoint를 걸고, argv[1]의 위치를 찾아봅니다.

140개의 A를 지나 return address(BBBB) 뒤의 0x90이 있는 지점을 찾아 그 중 한 곳의 주소를 집어줍니다.

이렇게 특정 스택 주소를 집어주는 이유는 여러 번 실행한 결과 랜덤 스택이 적용되어있지 않기 때문에 0x90중 한 곳에만 return 시켜준다면 뒤에 있는 쉘코드가 실행 될 것입니다.


payload : ./narnia2 A*140 + 0xffffd872 + 0x90*100 + 25byte shellcode



짜잔!

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로 통하는 패스워드를 깔끔하게 뱉어줍니다.



OverTheWire_Wargame Leviathan

[ level2 -> level3 ]




레벨2에는 printfile이라는 바이너리가 자리 잡고 있습니다. 레벨1과 마찬가지로 setuid bit가 걸려있기 때문에 이 파일을 이용해서 레벨3로의 패스워드를 알아 내야 할 것입니다.

gdb로 한번 까 보도록 하겠습니다.



먼저 main을 disassemble 한 상태입니다.

위쪽은 파라미터 갯수 검증하는 부분이고, 빨간 체크박스부터 살펴보면 access 함수를 호출하는 것을 알 수 있습니다.

access 함수의 원형을 살펴보죠.

int access(const char *pathname, int mode);

2가지 인자를 받는데, 경로를 포인터로 받고 mode 또한 숫자 또는 상수로 받습니다.


R_OK(0x01)

 읽기 권한 여부

 W_OK(0x02)

 쓰기 권한 여부

 X_OK(0x03)

 실행 권한 여부

 F_OK(0x04)

 파일 존재 여부


함수 호출 규약에 따라 먼저 들어간 0x04가 mode, eax가 *pathname이 되겠군요.

스택에서 한번 어떤 값이 들어가는 지 살펴보도록 하겠습니다.



eax에 들어가는 값을 따라가 보니 argv[1]에 우리가 넣어줬던 파일 경로의 값이 들어갑니다.

그렇다면 여기서 호출하는 access 함수의 목적은 파일이 존재하는지 존재하지 않는지의 여부를 파악하고, 만약 존재하지 않을 경우 프로그램을 종료시키는 것이 될 것입니다.

사실 여기서 바로 /etc/leviathan_pass/leviathan3 로 넣어주면 깔끔하지 않느냐?

라는 질문이 있을 수도 있는데, 이유는 모르겠지만 그렇게 넣어주면 파일 미존재로 인해 프로그램이 종료되었습니다. 뭔가 다른 장치를 해 놓은 듯 합니다.

혹시 아시는 분이 계시면 댓글 부탁드립니다.


자, 그럼 이제 access 함수 이후에 어떤 행동을 하는지 더 살펴보도록 하죠.



access 함수 이후에 snprintf 함수를 호출하는데, sprintf와 동일하지만 버퍼의 길이를 제한하여 넣어준다는 차이가 있습니다.

이 함수는 대충 이런 모양이 될 것 같습니다.


snprintf(buffer, 0x1ff, "/bin/cat %s", argv[1]);


우리가 넣어 준 파일 경로 앞에 /bin/cat을 넣어주고 buffer 변수에 넣는거죠.

그리고 마지막엔 system함수의 인자로 buffer을 넣어줘서 결국 "/bin/cat 파일"을 실행하는 것입니다.

자, 여기까지 이해를 했다면 어떤식으로 문제를 풀어야 할 지 감이 오지 않나요?



/tmp/ 경로에 fstr3am_2라는 디렉토리를 만들어주고, 그 곳에 ".bashrc;sh"라는 이름의 파일을 하나 던져줍니다.

세미콜론 앞에 오는 문자열은 어떤 문자가 오던 간에 상관은 없습니다.

이렇게 한 이유는 access 함수를 우회하기 위해 실제로 존재하는 파일을 생성해주는것이고, 파일명을 /bin/cat에 붙여주기 때문에 결과적으로 버퍼에 들어가는 문자열은 아래와 같이 될 것입니다.


"/bin/cat .bashrc;sh"


이 프로그램에서는 실행을 위해 system 함수를 이용하기 때문에 system("/bin/cat .bashrc;sh") 라는 명령어가 완성이 되는군요.

결과적으로 /bin/cat .bashrc, sh 두 가지의 명령어가 따로 실행이 되는것입니다.



깔끔하게 쉘을 떨어뜨렸습니다. 권한이 leviathan3로 정상적으로 상승된 것을 확인하고, leviathan3의 패스워드를 뱉어내도록 합시다.

OverTheWire_Wargame Bandit


[ level3 -> level4 ]



Level3에 들어오면 inhere라는 이름의 디렉터리가 존재합니다. 들어가고 싶게 생기지 않았나요? 들어가줍시다.

ls 명령어로 확인했을 때 아무것도 나타나지 않는데, 우리의 촉은 숨김파일이 있다! 라고 말해주죠.

ls -al 명령어로 확인 해 보니 hidden이라는 숨김파일이 존재합니다.

해당 파일을 cat 명령어로 보면 다음 level로의 key 값을 찾아낼 수 있습니다.

OverTheWire_Wargame Bandit


[ level2 -> level3 ]



Level2에 접속하면 홈 디렉터리에 'spaces in this filename'이라는 파일이 있습니다.

현재 이 파일밖에 없기 때문에 cat * 을 입력하면 와일드카드로 모든 파일명에 해당하는 것을 읽으라는 명령이므로, 당연히 key값이 보여집니다.

다른 방법으로는 cat s 까지 입력 후 tab을 눌러주면 자동 완성이 되므로, 이를 이용하여 출력 할 수도 있습니다.

+ Recent posts