Level8은 admin 계정의 패스워드를 알아내라고 합니다.


Edit 버튼을 누르면 정보가 갱신되며, 이는 곧 update 구문을 이용한 것이라고 생각 할 수 있습니다.


따라서 update [table명] set [attribute1=value1, attribute2=value2, ...]의 형태이기 때문에 single quotation을 추가하여 다른 속성의 값을 중복 변경 할 수 있습니다.


single quotation만을 입력했을 때 나타나는 오류로 보아 update 구문에 적용되는 속성의 순서는 다음과 같습니다.



name, username, email, icq, age 의 순서로 update 되기 때문에 가장 먼저 나타나는 name의 속성의 값을 password로 변경한다면 Admin 계정의 패스워드를 알아낼 수 있습니다.




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

[RedTiger] Level 10  (2) 2017.11.07
[RedTiger] Level 9  (0) 2017.11.06
[RedTiger] Level7  (0) 2017.11.01
[RedTiger] Level6  (0) 2017.11.01
[RedTiger] Level5  (0) 2016.10.19

[Problem]


문제를 살펴보면 벌 한마리가 꿀빨고있다.

여기서 벌을 눌러보면 ../return/good.html로 redirect 되는 것을 확인 할 수 있다. 물론 소스 상에서도 확인 가능하다.



그리고 소스를 확인 해 보면 위와 같은 주석이 달려있다.


[Scenario]

2번째 그림에서 보이는 un과 pw의 헤더 부분인 'BZh91AY&SY'를 검색해보면 bz로 압축된 메시지인 것을 알 수 있는데, python의 bz2 모듈을 이용하여 decompress 해준다.


[Payload]

#coding: utf-8
import bz2

id = 'BZh91AY&SYA\xaf\x82\r\x00\x00\x01\x01\x80\x02\xc0\x02\x00 \x00!\x9ah3M\x07<]\xc9\x14\xe1BA\x06\xbe\x084'

pw = 'BZh91AY&SY\x94$|\x0e\x00\x00\x00\x81\x00\x03$ \x00!\x9ah3M\x13<]\xc9\x14\xe1BBP\x91\xf08'

decompressed_id = bz2.decompress(id)
decompressed_pw = bz2.decompress(pw)
print decompressed_id
print decompressed_pw

id : huge

pw : file




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

[PythonChallenge] Level10  (1) 2017.02.15
[PythonChallenge] Level9  (0) 2017.02.15
[PythonChallenge] Level7  (0) 2017.02.14
[PythonChallenge] Level6  (0) 2016.06.28
[PythonChallenge] Level5  (0) 2016.06.27













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

[Natas] Level10  (0) 2016.10.22
[Natas] Level9  (0) 2016.10.22
[Natas] Level7  (0) 2016.10.22
[Natas] Level6  (0) 2016.10.22
[Natas] Level5  (0) 2016.10.22

SuNiNaTaS

Web Level8




8번째 문제입니다.

얼핏 봐서는 SQLi 문제같지만... 소스코드를 확인 해 보니 아닌 것을 알아챘습니다.




아래 힌트에 패스워드는 0부터 9999까지라고 나와 있기에... 이것은 브루트포싱을 이용한 무작위 대입으로 풀이하는 것이 맞다고 생각했습니다.



그래서 우리들의 영원한 친구 파이썬을 이용하여 브포 코드를 작성했습니다.

Password Incorrect! 문구가 나오지 않을 때까지 돌리는 코드입니다.

그리고 화장실 갔다왔습니다.



패스워드가 7707일때 AuthKey를 뱉어내네요.

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

SuNiNaTaS Web Level10(Prob_23)  (0) 2016.05.10
SuNiNaTaS Web Level9(Prob_22)  (0) 2016.05.09
SuNiNaTaS Web Level7  (0) 2016.05.09
SuNiNaTaS Web Level6  (0) 2016.05.09
SuNiNaTaS Web Level5  (0) 2016.05.09


OverTheWire Narnia 

[ level8 -> level9 ]



오랜만에 풀이하는 OverTheWire 문제입니다. 이전에 하던 Narnia 난이도의 마지막 문제를 풀이했는데요, 간만헤 하는 시스템해킹인지라 감이 떨어졌는지 한 문제 푸는데만 하루가 꼬박 걸렸습니다. 문제 보도록 하죠.




소스입니다. 메인 함수를 확인 해 보니 argv[1]을 func 함수로 보내주네요. func 함수는 blah 포인터 변수에 받아온 argv[i]의 값을 넣어 준 후 20의 크기를 가진 bok이라는 배열을 선언합니다. 그리고 memset 함수를 이용하여 bok의 사이즈(20)만큼 NULL로 초기화를 시켜줍니다. 그 후 가장 중요한 부분입니다. 빨간 네모 박스 쳐져 있는 부분인데, blah[i]가 NULL이 나올 때 까지 bok 배열에 argv[1]의 값을 하나씩 집어 넣어줍니다. 여기서 ret 값을 덮어 씌우는 BOF 취약점이 발생 할 수 있습니다. 

다음은 문제 풀이 할 때 표기했던 내용인데, func 함수를 disassemble 한 어셈블리 코드입니다. 보기 쉽게 주석으로 의미를 적어두었습니다.





참고 삼아서 보면 될 것 같습니다.

다음으로 gdb로 직접 돌려보면서 값을 확인 해 보도록 하겠습니다.



argv[1]의 값으로 A를 총 20개 넣었을 때의 결과입니다. func함수의 어셈블리 코드를 확인 했을 때 ebp-0x20의 위치가 bok 변수의 위치라고 명시 되어 있었으니, continue를 하면서 값을 확인 해 보았습니다.





그리고 총 20번을 돌았을 때의 결과입니다. 20바이트 직후에 나타나는 4바이트는 바로 blah 변수입니다. 어셈블리 코드를 확인 해 보면 ebp-0xc의 위치에 blah가 위치해 있다는 것을 확인 할 수 있는데, 0x20-0xc = 32-12 = 20 입니다. 그래서 20바이트 직후에 blah가 위치해있는데, 이로 인해 생기는 문제는 다음 그림을 통해 확인해보도록 하겠습니다.



위에서 설명했던 문제가 바로 빨간 박스 쳐진 부분입니다. 첫 번째와 두 번째 박스를 확인 해 보면 0xffffd8a2였던 blah 주소 값의 마지막 부분이 0x41(A)로 덮어씌워지는 것을 알 수 있습니다. 그리고 그 다음 루프에서 blah의 값을 참조하기 위해 0xffffd68c의 주소를 확인하는데, 방금 전 루프에서 blah 변수의 주소를 변경하였으므로, 엉뚱한 주소를 참조하게됩니다. 그 결과가 두 번째 네모 박스입니다.

그렇다면 어떤식으로 이러한 문제를 해결해야할까요?

저는 overflow시킬 때 blah 변수의 위치에 해당하는 부분에 blah 변수의 주소 값을 넣어주었습니다. 무슨 말이냐면, blah 변수의 값을 그대로 bok 변수에 저장하기 때문에 blah[21]~blah[24]의 위치에 blah의 주소 값을 그대로 때려박아주는 방법을 선택했습니다.

그럼 방법은 이후에 다시 설명하도록 하고, 빨간 네모 박스 쳐 놓은 부분을 확인 해보겠습니다. 




우리가 overflow를 시키고 있는 이유가 바로 ret 값을 덮어 씌우기 위함이었는데요, 그 ret 값의 위치를 알아야 페이로드를 작성 할 수 있겠죠? 첫 번째 쳐 놓은 박스 부분이 ret로 의심되는 부분입니다. 현재 스택의 구조가 (bok[20], &blah, argc, argv, sfp, ret)라고 생각 할 수 있겠습니다. 그럼 해당하는 값이 ret가 맞는지 확인 하기 위해 메인함수를 disassemble 해 보았는데, func 함수를 호출 한 직후의 위치가 기록 되어 있는 것을 확인 할 수 있습니다. 그러므로 해당 주소는 ret가 맞다고 생각하면 될 것 같습니다. 그리고 두 번째 친 네모 박스는 중간에 argv가 맞는 지 확인하기 위해 가져다 놓았습니다. argv[1]의 자리를 확인 해 보니 잘 안착 해 있네요.




그럼 본격적으로 페이로드를 작성해 보도록 하겠습니다. 페이로드 양식은 아래와 같습니다.


- payload : ./narnia8 "(Dummy 20byte) + (&blah) + (Dummy 12byte) + (system got) + (exit got) + (&argv[2])" "/bin/sh"


위 그림에선 AAAA가 Dummy Code, BBBB가 &blah, CCCC가 system got, 마지막 AAAA가 exit의 got(Dummy가 와도 무방함), DDDD가 &argv[2]입니다.

해당 페이로드를 그대로 때려박아주고 argv[1]과 argv[2]의 주소를 확인 해 보니 각각 0xffffd885, 0xffffd8b6이었습니다. 그리고 덤으로 system 함수와 exit 함수의 주소도 확인하였습니다.


- &argv[1] : 0xffffd885

- &argv[2] : 0xffffd8b6

- system got : 0xf7e63cd0

- exit got : 0xf7e56ec0




우리가 구한 주소들을 페이로드 양식에 때려박아주면 위 그림의 빨간 네모박스와 같은 형태가 나옵니다. 그대로 실행 해 주면 gdb에서 쉘이 떨어지는 것을 확인 할 수 있습니다.

하지만 gdb 환경과 bash의 환경에서는 argv[0]의 값이 다르기 때문에 argv[1]과 argv[2]의 주소가 꼬여버려 페이로드를 그대로 넣어주면 쉘이 떨어지지 않습니다. 따라서 argv[0]의 값을 맞춰주기 위해 실행 할 때 '/'를 추가하여 이름을 늘려주면서 실행시켰습니다.




/를 총 8번 사용하여 실행 시켰을 때 쉘이 떨어졌으며, narnia9의 패스워드를 알아내면서 OverTheWire Narnia 난이도는 끝을 맺도록 하겠습니다.


OverTheWire_Wargame Narnia

[ level7 -> level8 ]





level7의 소스입니다. 이전 레벨에서 볼 수 있었던 snprintf 함수의 취약성을 이용한 FSB와 비슷한 듯 합니다.

차이점으로는 main 함수에서 직접 처리하는 것이 아닌 vuln 함수에서 처리한다는 점 빼곤 없어 보입니다. 아, 또 다른 점으로는 buffer 변수의 결과 값을 출력 해 주지 않는다는 점이 있겠습니다. 자, 그럼 실행하면서 어떤식으로 풀어야 할 지 찾아보도록 하죠.



prtf() = 0x80486e0 (0xffffd64c) 부분을 확인 해 보면 괄호 안에 있는 부분은 ptrf 포인터 변수의 주소이고, 왼쪽의 값은 goodfunction 함수의 주소입니다. 이 값을 hackedfunction의 주소인 0x8048706으로 변경하여 shell을 띄우는 게 이번 레벨의 목표인 것 같습니다.

하지만 이전 레벨과 달리 buffer의 변수를 printf로 출력 해 주지 않기 때문에 얼마나 %x 서식문자를 입력 해 주어야 buffer 변수에 접근 할 수 있는지 알 수가 없습니다. 따라서 gdb를 이용해 스택 값을 확인하여 0xffffd64c의 값의 변화를 직접 확인하는 쪽으로 풀이하였습니다. 노가다죠.



vuln 함수에서 snprintf를 한 직후에 breakpoint를 걸어주고 실행하였습니다. 여기서 FSB를 위해 측정한 거리는 다음과 같습니다.


34542 = 0x8706(34566) - 16 - 8

33046 = 0x10804(67588) - 34542


위와 같이 거리를 구한 후 대입 해 주었으나, gdb 상에서 실행하였기에 파일명이 절대경로로 들어가 argv[0]이 변해서 ptrf의 주소 값이 바뀌었습니다. 그래서 그대로 대입을 해 주었으나, ptrf의 값이 바뀌지 않은 것을 보니 %8x를 한 번 사용했을 때는 buffer 변수에 접근을 못하는 듯 합니다. %8x와 거리 값들을 바꿔주변서 계속 시도하다 보면 아래와 같이 ptrf 포인터의 값이 변하는 부분을 찾을 수 있습니다.



%8x를 총 5번 사용했을 때 buffer 변수에 접근 할 수 있다는 것을 확인 할 수 있는데, 이상한 게 한 가지 있습니다.

예상대로라면 buffer 변수에 접근했을 때 ptrf 포인터의 값은 0x08048706이 되어야 하는데, 0x8706은 정상적으로 overwrite 된 반면 0x0804는 0x083c로 들어가 있는 것을 확인 할 수 있었습니다. 원인은 공부가 부족하여 찾지는 못했습니다. 계산법이 틀린건지, 놓친 부분이 있는 것인지는 잘 모르겠습니다. 혹시 아시는 분이 있다면 댓글로 지적 부탁드립니다. :D

일단 답을 찾아내기 위해... 3c에서 04까지의 거리인 0x38(56)을 빼주고 실행해봅시다.



어떻게든 답은 찾아냈습니다. :D

OverTheWire_Wargame Bandit


[ level8 -> level9 ]




이번 문제는 data.txt 안에 패스워드가 저장되어 있으며, 단 한번 발생한 라인의 텍스트가 패스워드라고 합니다.

결국 이 말은 data.txt 안에는 중복되는 값이 여럿 존재하며, 이를 제거하면 단 하나의 key가 남을 것입니다.


sort와 uniq는 한 번도 사용하지 않았던 명령어라서 구글링을 통해 알아냈습니다. sort는 말 그대로 아스키 순으로 소팅을 해주는 명령어이고, uniq 함수는 중복을 제거해주는 명령어입니다. 그 중에서도 -u 옵션을 넣어주면 중복되는 값을 제거하고 남은 값을 출력해주기 때문에 key값을 바로 도출 해 낼 수 있습니다.

OverTheWire_Wargame Bandit


[ level7 -> level8 ]



이번 문제도 힌트부터 확인하도록 하죠!

이번 레벨의 목표는 data.txt 파일 안에 다음 레벨로 갈 수 있는 패스워드가 저장되어 있다고 합니다.

그러나 'millionth' 라는 단어 옆에 있다고 하네요.

직접 확인해보도록 합시다.


ls -al 명령어로 해당 파일의 크기를 확인 해 보니 4000kb가량 되는 걸 보니... 아마 사전 데이터같은 값들이 저장되어있는 것 같습니다.

이런 다량의 데이터 속에서 원하는 값을 찾아내기 위해서는 grep 명령어를 사용해야하죠. bash에서는 파이프(|)를 사용하여 두 개 이상의 명령어를 동시에 사용 할 수 있습니다.

확실히 말하자면 동시에 실행하는 것은 아니고, 파이프라인 뒤에 있는 명령어를 실행하는데 그 입력값으로 파이프라인 앞에 있는 명령어의 실행 결과를 던져주는거죠.

millionth 뒤에 있는 key값이 바로 우리가 찾고자 하는 키값입니다!

+ Recent posts