안녕하세요? 허니입니다. SQL Injection 취약점에 대해서 알아보고 대응 방법에 대해 알아보도록 하겠습니다. 사이버 해킹에 대해 공부하시는 학생이나 연구원 분이 계시면 도움이 될 것이라 생각합니다.


대부분의 웹 사이트들은 사용자로부터 입력 받은 값을 이용해 데이터베이스 접근을 위한 SQL-Query를 사용하고 있습니다. 사용자 로그인 과정을 예로 들면, 사용자가 유효한 계정과 패스워드를 입력했는지 확인하기 위해 사용자 계정과 패스워드에 관한 SQL Query문을 사용하게 되며 이때 SQL Injection 기법을 통해서 정상적인 SQL Query를 변조할 수 있도록 조작된 사용자 이름과 패스워드를 보내 정상적인 동작을 방해할 수 있습니다. 이러한 비정상적인 SQL Query를 이용해 다음과 같은 공격이 가능합니다.

 

- 사용자 인증을 비정상적으로 통과 가능
- 데이터베이스에 저장된 데이터를 임의로 열람, 삽입, 수정, 삭제 가능
- 데이터베이스의 시스템 명령을 이용하여 시스템 조작 가능

 

이러한 취약점을 SQL Injection 취약점이라고 하며, DBMS와 연동된 웹 페이지상에 취약점이 존재합니다.

 

 일반적인 대응방법
데이터베이스와 연동이 되는 SQL 쿼리 구문의 모든 파라미터를 필터링하여 사용자의 입력 값이 SQL 쿼리에 직접 입력되지 않도록 수정합니다. 사용자 입력이 SQL injection을 발생시키지 않도록 사용자 입력 시 특수문자(' " / \ ; : Space -- +등)가 포함되어 있는지 검사하여 허용되지 않은 문자열이나 문자가 포함된 경우에는 에러로 처리합니다. SQL 서버의 에러 메시지를 사용자에게 보여주지 않도록 설정한다. 공격자는 리턴 되는 에러 메시지에 대한 분석을 통하여 공격에 성공할 수 있는 SQL Injection 구문을 작성할 수 있습니다. 따라서 SQL 서버의 에러 메시지를 노출하지 않도록 합니다. 웹 애플리케이션이 사용하는 데이터베이스 사용자의 권한을 제한합니다. 가능하면 일반 사용자 권한으로는 모든 system stored procedures에 접근하지 못하도록 하여 웹 애플리케이션의 SQL Injection 취약점을 이용하여 데이터베이스 전체에 대한 제어권을 얻거나 데이터베이스를 운용 중인 서버에 대한 접근이 불가능하도록 합니다.

 

 개발 언어별 대응방법
사용자로부터 입력 받은 변수로 SQL 쿼리 구문을 생성하는 CGI는 입력 받은 변수를 체크하거나 변경하는 로직을 포함하고 있어야 합니다. 입력 받은 변수와 데이터 베이스 필드의 데이터 형을 일치 시켜야 하고, 사용 중인 SQL 구문을 변경시킬 수 있는 특수문자가 포함되어 있는지 체크해야 합니다. 검색 부분과 같이 클라이언트로부터 생성된 SQL 구문을 받는 부분이 있다면 이를 제거해야 합니다.

 

 보안코딩(ASP)

prodId = Request.QueryString("productId")
prodId = replace(prodId, "'", "''")' 특수문자 제거
prodId = replace(prodId, ";", "")
set conn = server.createObject("ADODB.Connection")
set rs = server.createObject("ADODB.Recordset")
query = "select prodName from products where id = " & prodId
conn.Open "Provider=SQLOLEDB; Data Source=(local);
Initial Catalog=productDB; User Id=dbid; Password="
rs.activeConnection = conn
rs.open query
If not rs.eof Then
response.write "제품명" & rs.fields("prodName").value
Else
response.write "제품이 없습니다"
End If

 

 보안코딩( php)

php.ini 설정 변경 / php.ini 설정 중 magic_quotes_gpc 값을 On으로 설정.

; Magic quotes
;

; Magic quotes for incoming GET/POST/Cookie data
magic_quotes_gpc = ON ; Off에서 On으로 변경한다.

; Magic quotes for runtime-generated data, e.g. data from SQL, from exec(), etc.
magic_quotes_runtime = Off

;Use Sybase-style magic quotes (escape ' with " instead of \').
magic_quotes_sybase = Off

 

addslashes() 함수 사용
사용자가 입력하는 값들($_GET, $_POST)을 모두 addslashes() 함수를 이용하여 처리할 수 있도록 함.

addsIshes()
용도 : DB Query와 같이 인용된 부분 앞에 역슬래쉬를 붙여서 반환합니다. 해당문자에는 작은 따옴표, 큰 따옴표, 역슬래쉬, NULL이 있다.
- 적용 가능한 PHP : PHP 3 이상

$query = sprintf("SELECT id,password, username FROM user_table WHERE id='%s';", addslashes($id)); // id변수를 문자형으로 받고, id변수의 특수문자를 일반문자로 변환한다.

// @ 로 php 에러 메시지를 막는다.
$result = @OCIParse($conn, $query);
if (!@OCIExecute($result))
error("SQL 구문 에러");
exit;
@OCIFetchInto($result,&$rows);

 

 보안코딩(JSP)

String sql = "SELECT * FROM user_table" + " WHERE id = ?" + " AND password = ?";
ResultSet rs = null;
PreparedStatement pstmt = null;
try
conn = DBManager.getConnection();
pstmt = conn.prepareStatement(sql);

pstmt.setString(1, request.getParameter("id"));
pstmt.setString(2, request.getParameter("password"));

rs = pstmt.executeQuery();

 

 

+ Recent posts