[SQL Injection]데이터 유형 검사

데이터 유형 검사  

 


데이터 타입 검사가 무엇을 의미하는지 SQL 쿼리 관점에서 분류할 수 있습니다 . 



구분 

내용

데이터 값

파라미터의 매개변수 값이 SQL 쿼리에서 숫자,문자,날짜형등의 데이터로 사용되는 경우

스키마 객체

파라미터 매개변수 값이 SQL 쿼리에서 테이블 및 칼럼 등의 객체명으로 사용되는 경우 

SQL 쿼리문

SQL Query 구문을 파라미터의 매개변수 값으로 전송하여 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  = (int)$_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 인젝션 취약점 제거가 가능합니다 . 

해당 파라미터는 개발 단계 부터 타입을 명시적으로 숫자형이라고 선언되어 있는게 더 자연스럽지만 PHP는 변수를 선언할 때 타입 지정이 불가능 합니다 . 

다른 언어는 타입 선언이 필수 이기 때문에 이와 같이 숫자형 타입에서 SQL 인젝션 은 발생 하지 않습니다 . 



문자형

문자형 데이터는 숫자가 아닌 문자가 포함되어 있습니다 .
SQL 쿼리는 여기에 추가적으로 문자열 데이터 표기법에 대해서 알아야합니다 .
표기법을 보면 문자열 데이터는 싱글 쿼터를 쌍으로 감싸서 표현합니다. 
즉 파라미터 입력값이 SQL 쿼리문에 주입될때 싱글쿼터로 인해서 SQL 인젝션이 가능합니다. 
문자열 타입에서 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  = addslashes($_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);
?>








공격 구문을 주입 하면 테이블의 컬럼 명만 출력되고 DB 의 에러메세지는 출력되지 않습니다 . 

다른 키워드를 주입해도 SQL 인젝션 공격은 불가합니다 . 

이런 경우는 쿼리 굼ㄴ에서 싱글 쿼터 삽입 가능 여부가 공격의 핵심이 되기 때문에 싱글 쿼터 주입을 차단 하면 복잡한 필터링 설정 없이 취약점 해결이 가능합니다 .


그러나 PHP 환경에서는 Addslashes 함수등을 사용하여 싱글쿼터를 이스케이프처리 하였을 때 MBCS(Multi Byte Character Set) 변환이 있어서는 안됩니다 . 






추가한 구문
$_empname = mb_convert_encoding($_empname, 'utf-8', 'euc-kr');

cnrkgks rnansdms $_emp의 값 euc-kr을 utf-8로 변환하겠다는 뜻입니다. 

다음과같이 멀티바이트로 변환할 경우 싱글쿼터 주입이 가능한 문제가 발생합니다 . 

empinfo_name.php?empname=%BF'










예상치 못한 상황으로 php 및 MySQL이 연동된 환경에서 발생하는 취약점입니다 . 
 

구분

내용

SBCS

모든 캐릭터를 1byte로

DBCS

1byte로 표기가 불가한 문자를 2byte로

MBCS

1byte 문자표기에는 1byte로 표기(SBCS)

2byte 문자표기에는 2byte로 표기(DBCS)

Unicode

모든 캐릭터를 2byte로 표기 


이 방식이  PHP에서는 Addslashes함수를 거치면서 싱글쿼터에 백슬래시가 추가됩니다 . 
그러나 특정언어에서는 2바이트 문자열 중에 백슬래시와 합쳐서 하나의 문자가 될수 있습니다 . 
















MBCS 인코딩 후 addslashes 적용 
$_empname  = $_GET['empname'];
$_empname = mb_convert_encoding($_empname, 'utf-8', 'euc-kr');
$_empname = addslashes($_empname);

다시 동일 공격 구문을 테스트 해도 멀티 바이트 인코딩 이슈가 발생하지 않습니다 . 

댓글