user 파라미터(integer)를 입력받아 Username과 Email을 출력해준다.


?user[]=1과 같이 입력해주면 mysql_real_escape_string() 함수를 사용하는 것을 확인 할 수 있다. 따라서 single quotation과 같은 특수문자는 사용이 불가하다.


하지만 integer 기반 쿼리이기 때문에 single quotation 없이 SQLi가 가능하며, union select 구문을 사용할 수 있다.


또한 like와 parentheses 등 주요 기능이 필터링 되어 있다.


union을 사용하다 보면 2번째 컬럼에서 username의 이름을 넣어주면 쿼리가 정상 동작하는 것을 알 수 있다.


여기서 username 컬럼에 deddlef를 hex encoding 하여 보내줘도 동일한 결과가 출력되는 것을 알 수 있으며, deddlef'는 에러가, deddlef'#는 에러가 발생하지 않는 것을 확인 할 수 있었다.


여기서 출력되는 쿼리의 결과에서 username 부분을 새로운 쿼리에 넣어 실행, 결과를 출력하는 것이라 예상 할 수 있으며 exploit code를 hex encoding 하여 보내주면 패스워드를 얻어낼 수 있다.

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

[RedTiger] Level8  (0) 2017.11.01
[RedTiger] Level7  (0) 2017.11.01
[RedTiger] Level5  (0) 2016.10.19
[RedTiger] Level4  (0) 2016.10.19
[RedTiger] Level3  (0) 2016.10.19











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

[Natas] Level8  (0) 2016.10.22
[Natas] Level7  (0) 2016.10.22
[Natas] Level5  (0) 2016.10.22
[Natas] Level4  (0) 2016.10.22
[Natas] Level3  (0) 2016.10.22

PythonChallenge

Level6





바지가 나왔습니다.

소스를 확인해보죠.



상단에 <-- zip 이라는 주석이 달려있습니다.



channel.zip으로 접속을 해보니 해당 파일이 다운로드 되었습니다.

압축 해제를 해 보니 숫자로 이루어진 다수의 txt파일과 readme.txt가 있었습니다.



90052부터 시작을 하며, zip 내부에 답이 있다고 합니다.

90052.txt에는 Next nothing is 94191 라는 문구가 적혀있었으며, 다음은 94191.txt ... 의 규칙으로 따라가면 될 것 같습니다.



그래서 스크립트를 작성해보았습니다.



그랬더니 마지막인 46145.txt에서 comments를 모으라는 메시지를 뱉어냅니다.

여기서 말하는 comment는 zip으로 압축 할 때 comment를 추가 할 수 있는데, 그 때의 comment라는 것을 한참 고민 하다 알아냈습니다.



그래서 python 모듈 중 하나인 zipfile을 이용하여 comment를 출력해보았습니다.



HOCKEY라는 모양의 알파벳이 나타났습니다.




그러나 들어가보니 이것은 공기 안에 있다고 합니다. 문자들을 잘 살펴보라네요.

스크립트 결과를 자세히 보면 O X Y G E N의 알파벳이 HOCKEY라는 모양을 이루고 있는 것을 알 수 있습니다.

Oxygen은 산소로, 공기에 있는게 맞네요!


[*] FLAG : oxygen.html


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

[PythonChallenge] Level8  (0) 2017.02.15
[PythonChallenge] Level7  (0) 2017.02.14
[PythonChallenge] Level5  (0) 2016.06.27
[PythonChallenge] Level4  (0) 2016.06.27
[PythonChallenge] Level3  (0) 2016.06.27

SuNiNaTaS

Web Level6




6번째 문제입니다. Hint와 reference 글을 읽어보면 README 글을 열람하라는 내용과, 인코딩 및 디코딩을 지원해주는 http://tools.web-max.ca/encode_decode.php 웹페이지 URL이 적혀있습니다. README 글을 클릭 해 보면 아래와 같은 창이 나타납니다.



파란 글씨로 SQL Query가 써져있는데, Single Quotation을 이용한 SQL Injection을 통해 간단하게 인증을 우회 할 수 있을 것 같았습니다.

그래서 위 그림과 같이 query를 날려주었습니다.(1' or 1=1#과 같은 쿼리를 날려 줄 수도 있지만, =과 # 필터링으로 인해 like와 --을 사용했습니다.)




Congratulation!!

Auth_key를 뱉어내길래 이 키로 바로 Auth 메뉴에 넣어줬더니 계속 틀린 값이라고 합니다... reference 글에 나타나있는 대로 뭔가 인코딩이 필요할 것 같아 base64, sha1, md5 등 인코딩을 해서도 날려봤지만 역시 인증이 되지 않았습니다.

한참 고민하던 중, 몇 번 다시 돌려보니 위 팝업창이 뜬 이후 http://suninatas.com/Part_one/web06/view.asp?idx=3&num=3&passcode=wkdrnlwnd 이라는 URL로 요청을 때리는데, 접근 거부 팝업이 뜨는 것을 확인했습니다.

그래서 한 단계가 더 있는 것을 깨닫고, 쿠키를 확인 해 봤더니 쿠키 중 auth_key라는 값이 있었습니다.

이 곳에 우리가 찾아낸 key값을 집어 넣는 듯 합니다.



이 auth_key 값을 suninatastopofworld!로 넣어주었더니 그래도 안되길래... base64, sha1, md5 등 인코딩을 하다 보니 md5 hash 값을 넣어 주었을 때 해당 글이 읽혔습니다.



저는 크롬 확장프로그램 중 하나인 EditThisCookie 툴을 이용하여 쿠키를 변조 해 주었습니다.



접근 거부가 뜨던 웹페이지가 정상적으로 접속이 되고, KeyFinding^^라는 본문 내용을 담고 있는 페이지가 나왔습니다.



소스를 확인 해 보니, 시작 부분에 KEY_HINT가 Rome's First Emperor 라고 주어져있습니다.

찾아보니 로마의 첫 번째 황제는 아우구스투스였습니다.



구글링을 통해 아우구스투스의 라틴 이름을 Auth 메뉴에 박아주니 인증 되는 것을 확인하였습니다.



이번 문제는 게싱이 많이 포함되어 있는 문제였습니다. 힌트가 없었다면 풀이하기 많이 어려웠을 것 같습니다...

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

SuNiNaTaS Web Level8  (0) 2016.05.09
SuNiNaTaS Web Level7  (0) 2016.05.09
SuNiNaTaS Web Level5  (0) 2016.05.09
SuNiNaTaS Web Level4  (3) 2016.05.07
SuNiNaTaS Web Level3  (0) 2016.05.06
OverTheWire_Wargame Narnia

[ level6 -> level7 ]


Level7입니다. Narnia도 끝이 다가오네요.

코드를 보면 처음에 fp라는 이름의 int형 포인터에 puts함수의 주소를 넣어줍니다.

이는 곧 fp를 함수포인터로 사용한다는 의미가 되겠네요. 인자는 puts와 동일한 (char *)형입니다.

그리고 환경변수와 argv[3] 이후의 값들을 모두 제거하네요.

다음으로 취약점이 발생하는 strcpy문이 2번 호출됩니다. b1와 b2에 argv[1]와 argv[2]를 덮어씌워주는데, b2가 b1보다 나중에 선언되기 때문에 b1이 high address가 되겠네요. 따라서 b2에서 buffer를 overflow 시키게 된다면 b1의 값에도 영향을 미칠 것입니다.

그리고 esp의 값을 0xff000000과 and 시켜 결국 fp의 값이 스택 영역일 경우 프로그램을 종료시킵니다. 이는 스택에 쉘코드를 직접 넣어 실행 시킬 경우를 막아놓은 장치인듯 합니다.

마지막으로 b1을 인자로 fp(puts) 함수를 호출시킵니다.

대충 감이 오지 않나요? 일단 한번 실행을 해 보겠습니다.



b1과 b2의 값을 변경시켜가면서 출력을 해 봤더니 b1의 값이 8바이트 이상 입력 될 시 segmentation fault가 나타나는 것을 확인 할 수 있습니다.

b2의 값은 overflow 시켰을 때 16바이트를 입력하면 segmentation fault가 일어나는 것으로 보아, b1과 b2 사이에 dummy byte는 따로 없는 것 같습니다.

그렇다면 여기서 생각 할 수 있는 것은 b1[8]의 상위 스택에 바로 sfp, ret가 있거나 다른 경우의 수가 있다는 것입니다.

하지만 이 코드의 경우 gdb로 분석 해봤을 때 exit(1)로 끝나는 코드이기 때문에 leave;ret이 없는 것으로 보아 첫 번째 경우는 제외하였습니다.

그럼 두 번째 경우를 알아봐야 하는데, gdb를 통해 알아보도록 하겠습니다.



main 함수를 disassemble 한 상태입니다. 코드의 처음 부분에서 지역변수를 위해 0x30만큼 esp를 확보 해 준 이후 곧바로 esp+0x28의 값에 0x80483f0를 넣어줍니다.

????? 왜죠? 분명 선언은 b1, b2, fp, i 순으로 했는데...

아직 시스템에 대한 공부가 부족해서 정확하게 이해는 하지 못했습니다. 정황상으로는 선언과는 별개로 값을 직접 입력 해 줄 때에는 순서와 상관 없이 직접 입력 해 준 변수가 가장 상위의 스택에 쌓이는 듯 합니다.

아, 그리고 0x80483f0의 값은 puts@plt의 주소입니다. 결국 i, b2, b1, fp 의 순서로 스택이 나열되어 있다는 뜻이 되겠습니다.

그림에는 따로 나와있지 않지만 b1의 주소는 esp+0x20, b2의 주소는 esp+0x18입니다.

드디어 두 번째 경우의 수를 찾아냈습니다.

제가 생각하지 못했던 스택 시스템에 따라 b1 이후에 fp가 저장되어 있기 때문에 b1에 8byte를 입력했을 경우 fp에 NULL이 입력되어 마지막에 fp를 호출 할 때 segmentation fault가 나타났던 것입니다.

그렇다면 puts가 저장 되어 있는 fp에 system 함수의 주소를 꽂아주고, b1에는 b2를 이용해 /bin/sh를 넣어준다면 system("/bin/sh")라는 완벽한 결과가 나타나겠습니다.

자, 갑시다!



address of system : 0xf7e63cd0



system 함수가 정상적으로 실행되는 것을 확인 할 수 있습니다.

b2에 값을 더 추가하여 b1에 /bin/sh를 넣어주도록 합시다.


payload :

./narnia6 'A'*8 + 0xf7e63cd0 + 'B'*8 + '/bin/sh'




짜잔! 깔끔하게 쉘을 얻어냈습니다.


OverTheWire_Wargame Narnia

[ level5 -> level6 ]




자, level5입니다. 문제를 까 보니 i와 buffer 변수가 선언 되어 있으며, i 변수를 500으로 바꾸면 쉘을 띄워주겠다고 합니다.

buffer 변수는 [buffer의 크기-1]의 위치에 NULL을 집어넣기 때문에 overflow는 시키기 어려울 것 같습니다.

그래서 구글링을 잘 해보니 snprintf에 FSB가 존재한다고 합니다. snprintf는 출력 할 때 printf처럼 표준 출력을 사용하지 않고 문자열 자체로 출력하기 때문에 %x와 같은 서식문자도 buffer에 집어 넣을 수 있는 것입니다.

FTZ 이후로 기억 속에서 잊혀져 가던 FSB를 문서를 다시 보면서 어렴풋이 되찾았습니다.

차근차근 실행 해 가면서 보도록 하죠.



먼저 buffer 변수에 문자열을 집어 넣어봤습니다.

버퍼의 총 길이와 입력한 argv[1]의 값을 출력 해 주고, i의 값과 i의 주소를 뱉어냅니다.



여기서 argv[1]에 %x를 입력 해 줍니다.

그러면 snprintf에 의해 %x 문자열 자체가 buffer에 넘어가게 되고, 이를 printf에서 그대로 인자로 전달 해 줘서 %x에 해당하는 인자값을 출력해줍니다.



그럼, AAAA를 인자로 전달하고(printf의 첫 번째 인자) %x를 연달아 쓰면서 해당 인자 값이 몇 번째에 출력 되는 지 확인 해 보았습니다.

%x를 총 5번 사용했을 때 AAAA에 해당하는 값이 출력이 되었습니다.

그럼 이 위치를 이용해 FSB를 시도 해 보도록 하죠.

payload는 아래와 같습니다.


payload :

./narnia5 AAAA+[i의 주소]+%8x%8x%8x%8x+%460c%n


여기서 %460c를 입력 해 준 이유는 앞에 나온 'AAAA'와 i의 주소, %8x의 4번 출력으로 인해 8byte * 5 = 40byte이기 때문에 500에서 40을 빼서 460이 된 것입니다.

또한, i의 주소 앞에 'AAAA'를 붙여주는 이유는 %n이라는 서식문자 자체가 esp+4의 위치(다음 스택)에 있는 주소의 값을 수정해 주기 때문입니다.

그럼 계속 실행 해 보도록 하죠.



앞서 나온 buffer의 크기가 늘어났기 때문에 i의 위치가 변동되었습니다.

0xffffd6dc -> 0xffffd6cc로 바꿔주도록 하죠.



짜잔! key값을 얻어냈습니다.






References

- Format String Bug(HackerLogin 서정현 선배님)

- Format String Attacks(Tim Newsham)

OverTheWire_Wargame Leviathan

[ level6 -> level7 ]



이번 레벨에도 어김없이 setuid bit가 걸려 있는 바이너리가 버티고 있습니다. 실행을 해 보니 사용 방법을 친절하게 알려줍니다. 사용법대로 입력 해 보니, 값이 틀렸다고 오류 메시지를 출력해주고 프로그램을 종료시킵니다. 아마 지금까지의 leviathan 문제를 풀어본 결과 gdb로 까보면 바로 답이 있을 것 같습니다.



자, 일단 main 함수를 disassemble 한 상태입니다. 맨 처음 esp+0x1c에 0x1bd3을 집어 넣어주네요. 이게 답인듯 합니다. 0x1bd3 = 7123

그리고 바로 아래에서 argc가 2가 아닐 경우 오류 메시지(사용법)를 출력하고 프로그램을 종료시키네요.

그 다음 입력받은 값을 int형으로 바꿔주는 atoi 함수를 호출하고, 그 값과 [esp+0x1c](0x1bd3)을 비교하고, 값이 다를 경우 오류 메시지(Wrong)를 출력하고 프로그램을 종료시키네요.

만약 옳은 패스워드를 입력 했을 경우에는 system 함수를 호출하여 쉘을 띄워주는 것 같습니다.



상수 값을 확인해보니 /bin/sh으로, system 함수는 쉘을 떨어뜨려주는 것으로 확인이 되었습니다.

그럼 우리가 확인한 0x1bd3(7123)을 프로그램으로 집어 넣어줍시다.



깔끔하게 쉘이 떨어졌고, 패스워드를 출력 해줍니다.

OverTheWire_Wargame Leviathan

[ level5 -> level6 ]




자, 벌써 level5입니다. 홈 디렉토리를 확인하니 leviathan5라는 바이너리가 딱 버티고 있습니다.

권한을 확인 해 보니 이번에도 setuid bit가 걸려있네요. leviathan6 권한으로 실행이 되나봅니다. 파일을 실행 해 보니 "Cannot find /tmp/file.log"라는 오류 메시지를 내뱉고 프로그램을 종료시킵니다. 어떤 이유인지 확인하기 위해 gdb로 까보도록 하죠.



main 함수를 disassemble 한 상태입니다. 맨 처음에 fopen으로 파일 하나를 오픈 한 후, 해당 파일이 없으면 오류메시지를 내뱉고 프로그램을 종료시킵니다.

만약 파일이 있을 경우에는 fgetc와 feof 함수를 이용해 파일의 끝까지 이동하면서 한 바이트씩 읽어가며, 도중 putchar을 이용해 읽었던 값을 출력해줍니다.

그리고 eof에 도달하면 반복을 종료하고, getuid, setuid 함수를 이용해 현재 함수의 uid를 얻어와 setuid시키며 0x8048722에 들어있는 문자열을 인자로 unlink합니다.

fopen 할 때 인자로 전달하는 값 중 첫 번째 인자와 unlink 할 때 전달하는 인자가 동일합니다. 즉, fopen 하는 파일은 이 프로그램을 실행시키고 끝까지 실행됨과 동시에 삭제가 된다는 소리가 되겠네요.

상수 값을 분석해 본 결과, fopen의 두 번째 인자는 "r", 첫 번째 인자는 "/tmp/file.log"였습니다. 따라서 /tmp/file.log 파일을 읽어서 fgetc로 한 글자씩 저장하고, 출력하는 행위를 eof를 만날 때 까지 한다는 소리가 되겠네요.

그렇다면 /etc/leviathan_pass/leviathan6를 /tmp/file.log에 심볼릭 링크하여 leviathan5 프로그램을 실행시키면 해결 될 것 같습니다.



leviathan6로 통하는 패스워드를 아름답게 내뱉어주네요.

OverTheWire_Wargame Bandit


[ level6 -> level7 ]


자, 벌써 6레벨까지 도달했습니다. 힌트부터 확인하도록 하죠.



이번 레벨의 목표는 서버 어딘가에 저장되어있는 다음 단계로의 패스워드를 찾으라는 것입니다.

bandit7의 유저권한, bandit6의 그룹권한, 그리고 33byte의 크기를 가지고 있다는 것을 알려주고 있네요.

이전 레벨과 동일하게 find 명령어로 한방에 찾아주도록 합시다.



짜잔.

OverTheWire_Wargame Bandit


[ level5 -> level6 ]



자, 이번 문제는 힌트를 한번 참고해서 풀어보도록 하죠.

이번 레벨의 목표는 inhere 디렉토리 안에 1033바이트의 읽을 수 있는 non-exec 파일이 있다고 합니다.

직접 확인해보도록 하죠.


inhere 디렉토리 아래에는 여러개의 디렉토리가 또 존재하고 있으며, 이 디렉토리 아래에는 여러개의 파일이 더 존재합니다. 그러나 우리는 찾고자 하는 파일이 1033바이트인 것을 이미 알고 있기 때문에 find 명령어로 size 옵션을 지정해주어 1033바이트인 파일만 추려냈습니다.

그러면 key값을 바로 확인 할 수 있습니다.

+ Recent posts