본문 바로가기

1. Web hacking (웹 해킹)/2) 개념 정리

[2020.05.19] Dreamhack 개념정리 - 5강 Server-side Advanced - SQLInjection

https://dreamhack.io/

 

해커들의 놀이터, DreamHack

해킹과 보안에 대한 공부를 하고 싶은 학생, 안전한 코드를 작성하고 싶은 개발자, 보안 지식과 실력을 업그레이드 시키고 싶은 보안 전문가까지 함께 공부하고 연습하며 지식을 나누고 실력 향

dreamhack.io

1. SQL Injection Advanced

이번 강의에서는 MySQL과 SQLite를 중점적으로 다루며, 그 외에도 SQL Server(MSSQL), Oracle, PostgreSQL에 대해서도 다룬다.

SQL Injection 공격기법, SQL DML 구문에 대한 이해, Exploit Technique 에 대해서 알아보자.

2. SQL Injection 공격 기법

Logic

논리 연산을 이용한 공격 방법이다.

대표적인 논리 연산자로는 and 연산과 or 연산이 있다.

and 연산은 모든 조건이 참인 경우에만 결과가 참이 된다.

or 연산은 하나의 조건이라도 참이 되는 경우 결과는 참이 된다.

Union

SELECT 구문의 Union 절을 이용한 공격 방법이다. Union 절은 다수의 SELECT 구문의 결과를 결합시키는 행위를 수행한다.

사용 예시

이를 통해 원하는 다른 테이블에 접근하거나 원하는 쿼리 결과 데이터를 생성하여 어플리케이션에서 처리되는 데이터를 조작할 수 있다.

데이터베이스 조회 쿼리의 결과가 어플리케이션에 출력되는 경우 사용하기 유용한 공격 기법이다.

Union 절 사용 시 특정 조건이 만족되어야 한다.

- 이전 SELECT 구문과 UNION SELECT 구문의 결과 칼럼의 수가 같아야 한다.

- 특정 DBMS에서 사용 시 이전 칼럼과 UNION SELECT 구문의 칼럼의 타입이 같아야 한다.

Subquery

서브 쿼리는 하나의 쿼리 내에 또 다른 쿼리를 사용하는 것을 의미한다.

- 서브 쿼리를 사용하기 위해서는 (Sub Query)와 같이 괄호를 통해 선언할 수 있다.

- 서브 쿼리에서는 SELECT 구문만 사용할 수 있다.

 

 

Error Based

에러 베이스는 사용자가 임의적으로 에러를 발생시켜 정보를 획득하는 공격기법이다.

위 코드는 debug 모드가 설정되어 있으며, 사용자의 입력 데이터가 SQL 쿼리에 직접적으로 사용되어 SQL Injection 취약점이 발생하는 것을 알 수 있다.

하지만 SQL 쿼리 결과의 유무만 판단하며, 결과는 직접적으로 출력되고 있진 않다.

debug 모드가 설정되어 있기 때문에 SQL 쿼리 문에서 에러가 발생한다면 아래 그림과 같이 발생한 원인에 대한 에러 메시지가 노출되는 것을 확인할 수 있다.

 

admin'을 입력하여 Syntax Erro가 발생했다는 의미의 에러이다.

위와 같이 쿼리 결과가 직접적으로 출력되지 않으며 에러 메시지가 노출되는 경우 에러 메시지를 통해 주요 정보를 노출시키는 방법들이 존재한다.

해당 방법들을 사용하여 Error Based SQL Injection을 성공적으로 활용하기 위해서는 Syntax Error와 같이 DBMS에서 해당 쿼리가 실행되기 전에 검증 가능한 에러가 아닌, Runtime 중에 발생하는 에러가 필요하다.

 

Blind

Blind SQL Injection은 데이터베이스 조회 후 결과를 직접적으로 확인할 수 없는 경우 사용될 수 있는 공격기법이다.

DBMS의 함수 또는 연산 과정 등을 이용해 데이터베이스 내에 존재하는 데이터와 사용자 입력을 비교하며, 특정한 조건 발생 시 특별한 응답을 발생시켜 해당 비교에 대한 검증을 수행한다.

마치 up-down 게임을 하듯 공격한다는 설명

Blind SQL Injection을 수행하기 위해서는 다음 조건이 만족되어야 한다.

- 데이터를 비교해 참/거짓 구분

- 참/거짓의 결과에 따른 특별한 응답 생성

(참/거짓의 결과에 따른 특별한 응답을 생성하는 방법들은 Application Logic에서 다룬다)

데이터를 비교하여 참/거짓을 구분하는 구문으로 If Statements를 많이 사용한다.

사용 예시 ↓

 

 

Application Logic

데이터베이스의 결과를 받은 어플리케이션에서 결과 값에 따라 다른 행위를 수행하게 되는 점을 이용해 참과 거짓을 구분하는 방법이다.

아래 코드는 username에 의해 SQL Injection이 발생하며, 데이터베이스의 결과인 username이 admin인 경우에는 사용자에게 "True"가 반환되고, 아닌 경우에는 "False"가 반환된다.

 

 

데이터베이스에 아래와 같이 데이터가 있는 경우를 가정하고 설명하도록 하겠다.

 

*UNION 구문을 이용해 "admin" 반환

데이터베이스에서 반환된 결과가 "admin"인 경우 사용자에게 "True"가 반환되며, 아닌 경우에는 "False"가 반환되는 것을 확인할 수 있다.

 

* IF Statments 및 비교 구문 추가

substr은 첫번째 인자의 문자열을 두번째인자의 index부터 세번째 인자의 길이만큼 반환하는 함수이다.

즉, substr(password,1,1) 실행시 "admin"의 패스워트 첫번째 문자열인 "P"가 반환되며, 사용자는 각 문자열을 입력하며 비교한다.

사용자 입력 문자 중 "P" 문자 입력 시 조건이 참이되며, 사용자에게 "True"가 출력된다. 이를 통새 사용자는 password의 첫번째 문자열이 "P"임을 알 수 있다.

 

위와 같은 방법으로 index를 변경하며 password 전체를 획득할 수 있다.

Time Based

Time Based Blind SQL Injection은 시간 지연을 이용해 참/거짓 여부를 판단한다.

시간지연은 DBMS에서 제공하는 함수를 이용하거나, 무거운 연산과정을 발생시켜 쿼리 처리 시간을 지연시키는 heavy query 등으로 발생시킬 수 있다.

* 사용 예시

If Statements의 조건이 참이 되는 경우 sleep함수가 실행되어 1초의 시간이 지연되었으며, 조건이 거짓이 되면 시가니 지연이 발생하지 않은 것을 확인할 수 있다.

Error Based Blind

Error Based Blind SQL Injectino은 임의적으로 에러 발생을 일으켜 참/거짓을 판단하는 공격기법이다.

예시

MySQL에서 처리할 수 있는 DOUBLE 타입의 최대 값을 넘겨 에러를 발생시키는 연산을 이용한 방법이다.

위와 같이 에러가 발생하면 HTTP Reponse Status number 또는 어플리케이션의 응답의 차이를 통해 에러 발생을 확인하고 참/거짓 여부를 판단하면 된다.

 

 

Short-circuit evaluation

로직 연산의 원리를 이용한 방법이다.

AND 연산은 A식과 B식이 있을 때 모두 참이 되어야 결과가 참이된다.

이때, A가 거짓이라면 B는 연산을 하지 않아도 결과가 거짓이라는 것을 알 수 있다.

그렇기 때문에 실제로 B식을 수행하지 않는 것을 의미한다.

위와 같은 원리로 OR 연산에서도 A가 참이라면 B 식의 결과없이도 결과는 참이되기 때문에 B식이 수행되지 않는다.

이를 통해 데이터를 비교해 참/거짓 구분 로직을 대체할 수도 있다.

 

Blind SQL Injection Tip

- Binary Search (이진 탐색 알고리즘)

1. 범위 내의 중간 값을 지정하고 값을 비교한다. 0~100 사이의 범위라면 50을 지정하고 찾고자 하는 값과 비교한다.

2. 지정한 값이 찾고자 하는 값과 비교하고 범위를 조절한다. 50보다 크다면 범위를 51~100으로 조절한다. 50보다 작으면 범위를 0~49으로 조절한다.

3. 위 과정을 반복하여 특정한 값을 찾는다.

- bit 연산

ASCII는 7개의 비트를 통해 하나의 문자를 나타낸다. 이 원리를 적용하여 바이트를 비트로 변환하면 7번의 요청을 통해 한 바이트를 획득할 수 있다.

비트는 1과 0으로 이루어져있기 때문에 1에 대해 요청해서 거짓이 나오면 0이라는 것을 알 수 있다.

위와 같이 MySQL에서는 bin 함수를 통해 int형을 bit형태로 변경할 수 있다.

위와 같이 7번의 요청을 통해 binary 값이 1000001, 즉"A"라는 것을 알 수 있다.

 

 

 

3. SQL DML 구문에 대한 이해

SQL DML

SQL DML (Data Manipulation Language)은 데이터베이스에서 데이터를 조회하거나, 추가/삭제/수정을 수행하는 구문이다.

SELECT

데이터를 조회하는 구문이다.

SELECT 문자열을 시작으로 조회의 결과로 사용될 표현식 또는 칼럼들에 대해 정의한다.

FROM 절에서는 데이터를 조회하기 위한 테이블의 이름을 입력한다.

WHERE 절에서는 해당 테이블 내에 조회하는 데이터의 조건을 설정한다.

ORDER BY 절은 쿼리의 결과 값들을 원하는 컬럼을 기준으로 정렬한다.

LIMIT 절은 쿼리의 결과로 출력될 row의 개수 또는 Offset을 지정한다.

INSERT

데이터를 추가하기 위한 구문이다.

INSERT 문자열을 시작으로 INSERT 구문이 시작하며, 데이터가 추가될 테이블을 정의한다.

VALUE[S] 절에서는 추가될 데이터의 값을 입력한다.

INSERT 구문에서는 추가될 데이터의 값들이 입력되는 VALUE[S] 절에서 주로 SQL Injection이 발생하게 된다.

*INSER 구문 사용 예시

, 를 통해 여러 데이터를 한번에 추가할 수도 있다.

서브 쿼리를 통해 다른 테이블에 존재하는 데이터를 가진 row를 추가하여 데이터를 획득할 수도 있다.

UPDATE

데이터를 수정하는 구문이다.

UPDATE 문자열을 시작으로 수정을 요청할 테이블을 정의한다.

SET 절에서는 수정할 컬럼과 수정될 데이터를 정의한다.

WHERE 절을 통해 수정할 row를 지정한다.

DELETE

데이터를 삭제하는 구문이다.

DELETE FROM 문자열을 시작으로 삭제할 데이터가 존재하는 테이블을 정의한다.

WHERE 절을 통해 삭제할 데이터의 row를 지정한다.

DELETE 구문에서는 삭제될 row를 지정하는 WHERE 절이 사용자의 데이터로 주로 사용된다.

4. Exploit Technique

SQL Injection Exploit Technique

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

- 정보 탈취 (기밀성 침해)

- 정보 수정/삭제 (부결성 침해

* Blackbox 점검 중 SQL Inejction 취약점을 발견하고 공격의 목적을 달성하기까지의 과정

1. SQL Injection 취약점 발견

- HTTP Responsw Status Code를 통해 오류가 발생하는지 확인

- DBMS의 오류 메시지를 통해 취약점 가능성 확인

- 웹 애플리케이션에서 변조된 SQL구문이 실행된 데이터가 반환되는지 확인

2. 구문 예측/ DBMs 정보 획득

- 사용자의 입력 데이터를 처리하는 구문을 예측한다.

ex. 로그인 로직 처리되는 곳에서 SELECT 구문의 WHERE 절에서 사용자의 입력데이터를 처리한다. 또한, 회원 가입 로직이라면 새로운 데이터를 추가하기 위해 INSERT 구문의 VALUES 절에서 사용자의 입력데이터를 처리할 것이다.

- DBMS의 정보를 획득하여 Exploit 작성을 위한 정보를획득한다.

3. Exploit 작성

- 사용할 공격 기법을 선정한다. 데이터베이스 결과가 그대로 노출된다면 union 또는 subquery 구문, 정보가 노출되지 않는다면 Blind SQL Injection 사용

- WAF과 같이 SQL Injection을 방어하는 로직 등이 존재할 경우 우회 가능성 판단

4. 정보 탈취 및 수정/삭제

- 시스템 테이블 등을 이용하여 데이터베이스의 정보 등을 획득하며, 저장된 데이터를 탈취하거나 수정/삭제하여 공격의 목적을 달성할 수 있다.

SQL Injection - DBMS Fingerprinting

각 상황별 DBMS를 파악하는 방법

- 결과 값이 출력될 때

DBMS별로 다른 환경 변수 값을 출력한다.

 

- 결과 값이 출력되지 않지만 에러가 출력될 때

에러 메시지를 통해 DBMS 파악

- 결과 값이 출력되지 않을 때

True / False 를 확인 가능한 경우 ▶ Blind로 함수, 조건문을 사용해 테스트

- 출력이 존재하지 않는 경우

Time Based

System Tables

DBMS마다 데이터베이스의 정보를 담고 있는 시스템 테이블이 있다.

DB설정, 계정 정보, 데이터베이스/테이블/컬럼 정보, 현재 실행되고 있는 쿼리 정보 등 다양한 정보들을 담고 있다.

* 대표적인 활용 상황

조건

- 게시판 서비스에서 boards 테이블에서 SELECT 구문을 통해 조회 시 SQL Injection이 발생

- 사용자 정보가 포함되어 있는 유저 테이블, 컬럼 정보 등을 모름.

공격 방법

- 시스템 테이블의 정보를 이용하여 유저 테이블의 이름 및 컬럼 정보를 획득

- 획득한 테이블, 컬럼 정보로 유저 테이블에 접근 및 사용자 정보르 획득할 수 있다.

 

WAF Bypass

WAF(Web Application Firewall, 웹 방화벽)과 같이 웹 해킹에서 주로 공격 시 사용하는 키워드들에 대해 방어하는 시스템이 존재하는 경우가 있다.

WAF 또는 특정 키워드를 방어하는 방식은 공격의 리소스를 증가시키지만, 근본적인 취약점은 해결하지 못한다.

String Case Issue

탐지 시 처리 미흡

악성 키워드 탐지 시 해당 요청을 차단하지 않고 문자열을 변환하는 등의 과정을 거친 후 처리하는 경우 발생할 수 있다.

 

대체 가능한 키워드 필터

 

Out Of DBMS

DBMS에서 제공하는 특별한 함수 또는 기능 등을 이용해 파일 시스템, 네트워크 심지어 OS 명령어 등에도 접근할 수 있다. 이를 통해 SQL Injection을 통해 단순히 데이터베이스의 정보만을 획득하는 것이 아니라 파일 시스템, 네트워크, 시스템 장악까지도 가능할 수 있다.

DBMS의 버전이 올라감에 따라 기본적으로 위험한 함수나 기능 등을 제거하거나, 기본 설정/권한으로 접근하지 못하게 하는 등 다양한 방법으로 해당 공격 방식에 대해 패치를 진행하고 있다.

DBMS 주의사항

웹 어플리케이션과 DBMS를 연동해서 사용할 때 주의해야할 사항

권한 문제

DBMS 어플리케이션 작동 권한

리눅스 서버에서는 사용자 별로 권한을 나눠서 관리한다.

root 계정이나 다른 어플리케이션(ex. www-data(ebservice)) 권한을 사용하게 될 경우 문제가 발생할 수 있다.

계정을 분리하지 않을 경우 DBMS에서 Out Of DBMS 내용과 같이 파일 시스템, 네트워크 심지어 os 명령어 등에 접근 가능할 수 있기 때문에 추가적이 ㄴSide effect가 발생할 수 있다.

DBMS 계정 권한

일반적으로 DBMS 내부에 계정과 권한이 존재한다.

웹 어플리케이션에서 DBMS의 root 계정을 사용하거나 여러 서비스에서 같은 DBMS를 사용하는데 서비스 별 계정이 분리되지 않은 경우 SQL Injection이 발생하면 해당 계정에서 접근할 수 있는 Database가 많기 때문에 더 큰 피해가 발생한다.

어플리케이션에서 기본적으로 DBMS의 root 계정을 사용하지 않는 것이 좋고 서비스/기능 별로 권한이 분리된 계정을 만들어 사용해야 한다.

 

String Compare

DBMS를 사용하는 웹 어플리케이션 코드를 작성할 때 발생할 수 있는 문제점을 인지해야 한다.

* 문제 발생 상황 예시

Case sensitive

일부 DBMS에서 비교 연산시 대소문자를 구분하지 않고 비교한다.

 

space로 끝나는 문자열 비교

일부 DBMS에서 비교 연산시 문자열 길이에 맞게 space(" ")를 padding 후 비교한다.

( https://dev.mysql.com/doc/refman/5.6/ )

Multiple statement

Multiple statement는 하나의 쿼리 요청 시 다수의 구문을 사용하는 것을 의미한다.

 

 

웹 어플리케이션에서 대부분 Multiple statement를 지원하지 않는다.

쿼리 요청 한번에 여러 statement를 처리하지 못하기 때문에 특정 쿼리에서 SQL Injection을 찾더라도 해당 쿼리를 벗어나 다른 새로운 쿼리를 실행할 수 없다.

Multiple statement를 지원할 경우 DBMS에서 값을 조회하는 쿼리에서 Database를 삭제하거나 SQLite의 경우 attach를 통해 다른 파일에 값을 쓸 수 있다.