안녕하세요. 오늘은 webhacking 18번 문제를 풀어보겠습니다.

홈페이지로 들어가 webhacking 18번을 눌러주세요.


sql injection 문제이군요. 밑에 보시면 index.phps가 있습니다. phps가 php source 의 약자인것은 전부 아시지요? 한번 눌러 봅시다.

소스를 차례대로 분석해 봅시다.

일단 첫줄을 보시면 no를 get형식으로 입력받아야 소스가 실행되는 것을 알 수 있습니다.

그리고 eregi를 사용해 no를 입력받았을 때 no값에 

공백,/,\(,\),\t,|,&,union,select,from,0x 이러한 값들이 있을 경우 exit에 의해 함수가 실행이 되지 않고 종료된다는 것을 알 수 잇습니다.

그다음은 mysql함수를 사용하여 id가 guest이고 입력받은 no값과 일치하는 id를 검색하여 q라는 변수에 저장하는 것을 알 수 있습니다.

그렇다면 no가 무엇일까요?


개발자 도구를 이용해 확인을 하시면 문제의 입력칸의 이름이 no인것을 확인할 수 있습니다. 그리고 from method가 get으로 설정되있는 것을 보아 get형식으로 입력받는 다는 것을 알 수 있습니다.

위에 나온 sql함수와 php함수는 블로그항목에 게시되어 있으므로 자세히 알고 싶으시면 참고하시기 바랍니다.

그다음 소스를 봅시다.

if($q[0]=="guest") echo ("hi guest"); 
if(
$q[0]=="admin"

@solve(); 
echo (
"hi admin!"); 

q[0]가 게스트이면 hi guest를 출력하고 admin이면 문제가 해결된다고 나와 있습니다.

일단 테이블을 예상해봅시다.

id                                 no

admin                            ?

guest                             ?

대충 이렇게 되겠군요. 

그런데 우리는 no값을 모릅니다. 그래서 일단 무차별대입으로 한번 숫자를 입력해보겠습니다.

1을 입력하니 hi guest가 나오는 것을 볼 수 있습니다. 즉 id가 guest이고 no값이 1인 id를 검색했는데 guest가 나왔다는 것이지요.

테이블을 고쳐봅시다.

id                                 no

guest                             1

admin                            ?

만약 id가 guest하고 admin밖에 없다면 admin의 no값은 2일 확률이 큽니다. admin을 뽑아내봅시다. 

$q=@mysql_fetch_array(mysql_query("select id from challenge18_table where id='guest' and no=$_GET[no]")); 

여기 위의 소스를 보시면 조건에 id가 guest 이고.... 라고 되어 있습니다. 우리는 admin을 뽑아내야 하는데 id가 guest이면 no값이 얼마든 뽑아낼수가 없습니다.  그래서 이 조건을 무효화 시켜줄 필요가 있습니다. no값에 0 or no=2을 넣어 봅시다.

$q=@mysql_fetch_array(mysql_query("select id from challenge18_table where id='guest' and no=0 or no=2")); 

이렇게 되면 id가 guest이고 no값이 0인 id를 찾거나 no값이 2인 id를 찾으라는 뜻이됩니다. 왜 이렇게 되냐면 sql연산은 and>or순이기 때문에

(id='guest' and no=0) or no=2 이렇게 되기 때문이지요.

admin의 no값이 2라는 가정하에 정답은 0 or no=2가 될 수 있겠군요.

단 eregi에 의해 no값에 공백이 있으면 함수를 종료하기 때문에 공백을 우회해줄 필요가 있습니다. 공백을 우회하는 방법으로는 /를 이용한 주석이나 \t, \n 등이 있습니다.하지만 /와 \t는 eregi에 의해서 막힘으로 \n을 써봅시다.

그런데 \n을 직접 폼에 입력하여 전송하면 \따로 n따로 url 인코딩이 되어버립니다. 그래서 \n을 같이 인코딩한 %0a라는 값을 직접 주소창에 적어주셔야 합니다.

get방식으로 입력받기 때문에 주소창에서 적어주실 수 있습니다.

단 적기전에 ?를 붙여주시고 no값을 넣어주시면 됩니다.

즉 주소창에 no=0%0aor%0ano=2를 입력해봅시다. 

admin의 no값이 2가 맞은 모양입니다. 문제가 해결되었군요.

아 참고로 저는 no=2%0aor%0ano=2를 입력해서 문제를 해결했습니다.

앞의 no값은 어차피 거짓으로 만들기 위한거기 때문에 1을 제외한 그 어떤 값을 넣어줘도 문제가 해결됩니다. 

다만 1을 넣으면 앞의 조건도 참이 되버리기 때문에 guest와 admin이 둘다 불러오게 됩니다. q[0]이기 때문에 먼저 받아온 guest부터 저장이 되어버리기 때문에 문제를 해결 할 수 없습니다. 만약 소스에 q[1]이라고 되어있었다면 얘기는 달라졌겠군요.

암튼 이것으로 문제해결을 마치겠습니다.


'Webhacking' 카테고리의 다른 글

webhacking 15번 문제  (0) 2015.10.12
webhacking - 26번 문제  (0) 2015.10.02
webhacking - 60번 문제  (0) 2015.09.25
webhacking - 20번 문제  (0) 2015.09.25
webhacking - 42번 문제  (0) 2015.09.18
Posted by englishmath
,

안녕하세요. 오늘은 basic rce level 16 문제를 풀어보겠습니다.

홈페이지로 들어가 basic rce level 16을 눌러주세요.

또 시리얼이군요. 파일을 받아 봅시다.


이름을 입력하라는군요.

뭐 당연한 결과지요. 올리디버그로 열어 봅시다.

파일을 열고 재생버튼을 누른 다음 텍스트를 찾아봅시다.

Wrong password 라는 문자열이 보이는군요. 한번 들어가 봅시다.

Good 이라는 성공문자열과 Wrong 이라는 실패문자열이 있습니다. 그리고 그 위쪽에 CMP 비교구문이 있는 것을 알 수 있습니다.

EAX와 DWORD PTR SS:[EBP-3C]를 비교한다는 군요. DWORD PTR SS:[EBP-3C]는 메모리주소[EBP-3C]에 저장된 값을 의미합니다. EBP값에서 3C를 뺀 메모리주소에 저장된 값이라는 뜻입니다. 그리고 앞에 DWORD는 4byte를 의미합니다. 

그리고 밑에는 조건점프인 jnz가 있습니다. 비교함수의 두 변수값이 다를 경우 점프하지요. 지금 점프하는 주소를 보시면 실패문자열이 있는 주소입니다. 그렇기 때문에 jmz에서 점프하지 않아야 성공할 수 있습니다.

즉 EAX와 DWORD PTR SS:[EBP-3C]이 같으면 성공할 수 있습니다.

그러기 위해선 EAX와 EBP값이 뭔지를 알아낼 필요가 있습니다. CMP부분에 브레이크를 걸고 프로그램을 실행시켜 봅시다.

엔터를 쳐주시면 브레이크부분에 걸리게 됩니다.

EAX가 5인걸로 보아 패스워드 인 것 같습니다. Name은 문제에서 정해준 CodeEngn이므로 굳이 찾지 않아도 됩니다.

EBP값이 28FF48이군요. 여기에서 3C를 빼야 합니다. 16진수 계산하기 귀찮으니 그냥 계산기 씁시다.

계산기를 실행시킨 후 보기 - 프로그래머용 을 클릭하여 16진수를 계산합시다.

16진수 이므로 Hex로 바꿔주신 후 계산을 해주시면 28FF0C가 나오네요.

즉 메모리주소 28FF0C에 있는 값의 4byte를 EAX와 비교하겠네요. EAX와 같아야 성공문자열이 나오고 EAX는 메모리주소 28FF0C에 있는 값의 4byte이니 메모리주소 28FF0C에 있는 값의 4byte가 이번 문제의 정답이 되겠군요. 얼릉 메모리주소를 확인해봅시다. 아래와 같이 들어갑시다.

메모리 주소로 들어가셔서 뒤져보시면 아까 계산한 28FF0C주소를 찾으실 수 있습니다.

값은 97 0D C6 E4 C4 10 35 00 이네요. basic rce level 15에서 설명했듯이 메모리 주소는 리틀엔디언 방식으로 읽어주셔야 합니다. 즉

00 35 10 C4 E4 C6 0D 97 입니다. DWORD이므로 4byte를 들고 오면 E4C60D97이 됩니다.

즉 EAX값이 E4C60D97이 되어야 합니다. 그런데 밑의 실행결과를 보시면

패스워드에 10을 줬을 경우

EAX는 A가 되버립니다. 즉 EAX가 E4C60D97이 될려면 E4C60D97의 십진수 값을 입력해 주셔야 합니다.

설마 계산기 버려두고 힘들게 계산하지는 않겠죠?

E4C60D97을 입력 후 10진수로 바꿔주시면 3838184855가 나옵니다. 한번 확인해 봅시다.

맞다는군요. 인증하러 갑시다.

인증~

네 이것으로 문제풀이를 마치겠습니다.





'codeengn' 카테고리의 다른 글

codeengn - basic rce level 20  (0) 2015.10.02
codeengn - basic rce level 19  (0) 2015.10.02
codeengn - basic rce level 18  (0) 2015.09.25
codeengn - basic rce level 17  (0) 2015.09.25
codeengn - basic rce level 15  (0) 2015.08.18
Posted by englishmath
,

안녕하세요. 오늘은 basic rce level 18 문제를 풀어보겠습니다.

홈페이지로 들어가 basic rce level 18을 눌러주세요.

Name이 CodeEngn일때 시리얼을 구하는 문제네요. 파일을 받아봅시다.

흠 이름과 시리얼을 적는 부분이 나오네요.

올리디버그로 열어 봅시다. 재생버튼을 누른 후 텍스트를 확인해 봅시다.

성공과 실패 문자열이 보입니다. 들어가 봅시다.

 

JE를 이용해 성공문자열쪽으로 점프하는군요. JE는 비교함수에서 쓰이는 두 변수의 값이 같을 때 점프 합니다. 그런데? 늘 보던 비교함수 CMP가 없습니다. 그럼 뭐가 비교함수인걸까요?

위쪽의 박스친 곳을 보시면 lstrcmpi라는 함수가 있습니다. lstrcmpi는 문자열을 비교해주는 함수입니다. 즉 이 두값이 같아야 JE에서 인식을 하여 성공문자열로 점프합니다.

그런데 뭐와 뭘 비교하는지가 안나와있군요. 그래서 프로그램을 실행시켜 대입을 해보겠습니다. 실행 전 확인을 위해 비교함수 밑쪽에 브레이크를 걸어주세요.

check를 눌러주세요.

확인을 하면 두 변수에 값이 나와있는 것을 확인하실 수 있습니다.

하나는 06162370056B6AC0구요. 하나는 1로 나오는군요. 즉 시리얼은 string1 에 저장된다는 것을 알 수 있습니다. 그렇다면 Name은 위의 06162370056B6AC0이겠군요. 두 변수의 값을 같게 해줘야 하므로 시리얼을 06162370056B6AC0로 바꿔줘봅시다.

성공문자열이 뜨는 것을 볼 수 있습니다. 아무래도 이시리얼이 정답인 것 같군요.

인증하러 가봅시다.

 인증~

다음 문제가 뜨는 걸로 보아 정답인 것 같습니다.

네 이것으로 문제풀이를 마치겠습니다.

 


 


 


'codeengn' 카테고리의 다른 글

codeengn - basic rce level 19  (0) 2015.10.02
codeengn - basic rce level 16  (0) 2015.10.02
codeengn - basic rce level 17  (0) 2015.09.25
codeengn - basic rce level 15  (0) 2015.08.18
codeengn - basic rce level 14  (0) 2015.08.18
Posted by englishmath
,