[어설픈] webhacking.kr 21번 문제풀이

2019. 4. 14. 22:26Web Hacking/Webhacking.kr


안녕하세요!

오늘은 webhacking.kr에서

250점 문제인

21번 문제를 풀어보도록 하겠습니다!


문제에 들어가니 아래와 같이 나오네요!

대문에 크게 

BLIND SQL INJECTION


이라고 광고하고 있네요

뭐 제가 밑에 박스에 값을 넣고

제출 버튼을 누르면

Result에 결과가 뜨겠죠?


BLIND SQL INJECTION = 서버에 요청을 보내어,

 서버의 참/거짓 값을 토대로 값을 알아내는 INJECTION 입니다!

기존에 sql injection과 달리 한번에 BAAM!하고 

결과가 나오지 않아요 ㅠㅠ




그래서 뭐 일단은 뭐라도 좋으니

a를 입력해 보았습니다!


그랬더니 결과창에

False 

"응응 너 틀림 ㅋ"

이라고 뜨네요..?!


근데 신기하게 id랑 pw parameter도 있나보네요!

그리고 위에 url 결과창이 뜨니 

당연히 get방식이겠죠?



근데 sql 문제 풀 때 보면,

no는 number를 항상 칭하는 그런

parameter였기 때문에

알파벳이 아닌 숫자를 넣어보기로 했습니다!


그래서 no=1을

넣었더니 아래와 같이 true가 뜨네요!

뭐지? id랑 pw에 아무값도 안줬는데 왜 참이 뜨는거야....?!?!?!?!



일단은 그냥 계속 쭉 다른 숫자 값들을

크기 순서대로 넣어봤습니다!


no=2를 넣고 실행을 하니!

아래와 같이 또 true가 뜨네요!




근데 아무리 봐도 

여기서 no는 number가 들어가는 곳이 맞기 때문에!

( sql injection 할 때 no parameter에는 ' 나 "가 들어가지 않았음)


그래서 싱글쿼터 우회를 안하고 

그대로 query를 inject 해봤습니다!


no=2 and length(id)>10 #(뒷 부분 주석처리 됨)


그랬더니 이건 False라고 뜨네요!

no=2인 놈의 id길이는 10보다 작거나 같다!


흠...

no=1과 no=2 둘 중 하나에

저희가 원하는 값이 담겨 있을지도?!


제가 일일이 부등호랑 직접 노가다로 대입해서 찾았습니다!

no=2 일때 그 아이디의 길이는 5이다!


혹시나 해서 no=1일때 아이디 길이도 확인해보니!

아이디 길이가 5네요!


이후에 제가 length(id)대신

length(pw)으로 pw길이도 확인해봤는데!

아래의 표와 같았습니다!



그럼   no     id     pw 

          1    5자리   5자리

          2   5자리  19자리


근데 아무래도 5 자리는 금방할 거 같으니까

19 자리 비밀번호부터 구해봅시다!


"그럼 뭐 저 짓을 계속 할꺼냐?"

"날 샐꺼냐?"


당연히 python으로 풀어야죠!


코드가 좀 난해하게 보여도 그렇게 어렵지 않습니다!

혹시 몰라서 주석까지 적어놨습니다!


웹 해킹할 때 쓰이는 python library는 request입니다!

그래서 import requests라고 일단 선언합니다!

(= request 라이브러리 쓸 꺼야!)


그 다음에 answer라는 변수를 선언합니다!

주석에 적었듯이, 정답을 적을 공간입니다!

일단은 아무것도 없으니 빈칸으로 해놔야 겠죠?

그래서 ""이렇게 더블쿼터를 붙여놨습니다(=빈칸)


그리고 for문을 돌립니다!

형식은 for 변수 in range( 숫자, 숫자): 입니다!

c 언어에서 for문과 거의 유사합니다!


다만 여기서 range가 좀 다릅니다!

제가 밑에 적은 코드를 보시면 range(1,20)이라고 적혀있는데

여기서는 1~20이 아니라!

1~19까지입니다!


왜냐면 비밀번호가 19자리이기 때문에

각 자리마다 맞는 값을 찾아야 하기에!


근데 여기서 for 문을 한번 더 돕니다!

첫 번째 for문은 비밀번호 자리 수 만큼 도는 것이고!

두 번째 for문은 각 자리가 무슨 값인지 확인하기 위해서

브루트포싱하는거죠!


예를 들자면 1번째 글자 a니? b니? c니? d니? e니? f니? .... (찾을 때 까지)

그러다가 첫 번째 글자 찾으면

두 번째 글자로 넘어가서 다시

a니? b니? c니? d니? e니? f니? ... (찾을 때 까지)

그렇게 19번을 하는 거에요! 


어 range에 숫자가 다른데요? 

왜 range(97,127)에요?


왜냐하면 알파벳 소문자 a가 97부터라서 그래요!

그럼 대문자랑 나머지 문자는요....?


원래는 그런 문자들도 추가했었는데요!

앞에 뽑히는 3,4 글자 보니까 다 소문자길래

그냥 ascii 값 97 (=a)부터 

검색하기로 했습니다!


url변수에는 저희가 어디 url로 보낼껀지 적으면 되요!

그래서 url에 있는 webhacking.kr 주소 긁어 오시구요!

그 뒤에 parameter 부분부터는 

substring 함수는 단어를 자를 수 있는 함수입니다!


substr( 무엇을 자를꺼냐, 어디서 부터 자를꺼냐, 몇 글자 자를꺼냐)

그래서 아래를 보시면 

substr(pw,%d,1)라고 했으니


"pw를 %d 번째 부터 1글자 잘라라!"

실제론 pw를 1번째 부터 1글자 잘라라! 

        pw를 2번째 부터 1글자 잘라라!

`````

pw를 19번째부터 1글자 잘라라!


이렇게 되겠죠?

한 마디로 각 글자를 추출 하는 거에요!

그래서 추출한 글자를 ascii 값으로 바꿔줄꺼에요!


ascii(문자열) => 문자열을  ascii 표에 해당하는 숫자로 변환시켜줌

그래서 그 값을 %d 와 비교한다는거는

97부터 127사이의 ascii 값과 

ascii(substring( ))값을 비교한다는 거에요!

그리고 뒷 부분은 뭐 필요없으니 #를 달아서 주석처리를 합니다!

그리고 url 뒤에 적은 %( i , j )는

각각 %d %d에 순서대로 들어갑니다!


이거랑 똑같다고 보시면 됩니다!

c언어에서 printf("this is number %d",num)

<num변수에는 1이 들어가 있다고 가정>


그 다음에는 간단합니다!

cookies 변수에는 웹사이트에 저희가 어떤 사용자인지

알려주기 위해 쿠키 값을 적습니다!

형식은 다음과 같습니다!

cookies={' 쿠키이름 ': ' 쿠키 값 '}


여기까지 하면 저희가 request할 모든 것들을 세팅했기 때문에!

보내야합니다!


그때 이제 requests에 점을 찍고

method를 정합니다!

request.post인지 request.get인지!


여기서는 get이니

request.get( )!

그리고 get으로 보낼 때 같이 보낼 값들을 적습니다!


get방식으로 어떤 url에 보낼건데?

쿠키는 뭔데?


|  |

request.get(url,cookies=cookies)


이렇게 request를 보내면 서버에서 응답이 오겠죠?

True다 아니면 False다

그걸 알기 위해서 res라는 변수에 해당 정보를 담습니다!


그리고 이 응답 값을 text형식으로 바꿉니다!

res => res.text

왜 바꾸냐고요? True인지 False인지 단어 찾아야 하니까요!


그래서 res.text.find('True')

참인 단어를 찾았다!

(단어를 못 찾으면 -1을 반환하는데, -1이 아니니 단어를 찾았다고 조건 준 거에요!)


우리가 원하던 글자니 저장해야겠죠?

answer 변수에?


answer = answer + chr( j )

chr 함수에 대해서는 주석에 적어놓았듯이!

ascii 숫자를 입력하면 그 표에 해당하는 문자로 바꿔주는 함수입니다!

그리고 확인하고 싶어서 그 글자 출력해주고요!

break을 걸어서 루프를 탈출하고 

다음 글자 찾으러 갑니다!


 만약에 -1이 반환 되어서 못 찾으면

 현재 숫자 출력하고

계속 j in range for문 돌리세요!


그리고 for문이 다 돌려지면

here is the answer! 라고 출력하고!

answer에 담겨진 값을 출력합니다!


그러면 아래와 같이 

blindsqlinjectionkk라고 나옵니다!




이걸 이제 authentication 페이지가서

인증해주시면

아래와 같이 클리어 메세지가 뜹니다!


고생하셨습니다!