SQL Injection

chi·2024년 7월 13일

web hacking

목록 보기
9/15

DBMS

데이터베이스와 데이터베이스를 관리하는 애플리케이션 Database Management System(DBMS)

DBMS는 데이터베이스를 관리하는 애플리케이션이다
데이터베이스에 정보 등록, 수정, 삭제를 한다
여러 사람이 동시에 DB에 접근할 수 있고 복잡한 요구사항의 데이터를 조회할 수 있다
DBMS은 관계형 Relational, 비관계형 Non-Relational으로 나뉜다
관계형: 행열 테이블로 데이터 저장. MySQL, MariaDB, PostgreSQL, SQLite
비관계형: 키-값(Key-Value)으로 데이터 저장. MongoDB, CouchDB, Redis

Relational DBMS

RDBMS의 조건
1. 행열의 집합으로 구성된 테이블의 묶음 형식으로 데이터를 관리
2. 테이블 형식의 데이터를 조작할 수 있는 관계 연산자 제공
Structured Query Language (SQL) 라는 쿼리 언어를 사용
쿼리를 통해 테이블 형식의 데이터를 조작한다

Structured Query Language (SQL)

SQL은 RDBMS의 데이터를 정의하고 질의, 수정을 위해 고안된 언어
SQL은 구조화된 형태를 가지는 언어로 웹 어플리케이션이 DBMS와 상호작용할 때 사용된다
사용 목적과 행위에 따라 다양한 구조가 존재한다 (DDL, DML, DCL)

웹 어플리케이션은 SQL을 통해 DBMS와 상호작용한다
RDBMS에서 사용하는 기본적인 구조: 데이터베이스 → 테이블 → 데이터

DDL (DB,테이블 생성)

데이터를 다루기 위해 데이터베이스, 테이블을 생성해야 하며 DDL을 사용해야 한다
DDL의 CREATE 명령으로 새 데이터베이스와 테이블을 생성할 수 있다
Dreamhack이라는 데이터베이스를 생성하는 쿼리문 >

CREATE DATABASE Dreamhack;

앞서 생성한 데이터베이스에 Board 테이블을 생성하는 쿼리문

USE Dreamhack;
# Board 이름의 테이블 생성
CREATE TABLE Board(
	idx INT AUTO_INCREMENT,
	boardTitle VARCHAR(100) NOT NULL,
	boardContent VARCHAR(2000) NOT NULL,
	PRIMARY KEY(idx)
);

DML (데이터 추가)

생성된 테이블에 데이터를 추가
INSERT: 새로운 데이터를 생성한다
SELECT: 데이터를 조회한다
UPDATE: 데이터를 수정한다

Board 테이블에 데이터를 삽입하는 쿼리문

INSERT INTO 
  Board(boardTitle, boardContent, createdDate) 
Values(
  'Hello', 
  'World !',
  Now()
);

Board 테이블의 데이터를 조회하는 쿼리문

SELECT 
  boardTitle, boardContent
FROM
  Board
Where
  idx=1;

Board 테이블의 컬럼 값을 변경하는 쿼리문

UPDATE Board SET boardContent='DreamHack!' 
  Where idx=1;

SQL Injection

DBMS에서 사용하는 쿼리를 조작해 데이터베이스의 정보를 획득하는 해킹 방법
Injection 인젝션이란? 입력값의 처리 과정에서 입력값이 구조나 문법적인 데이터로 해석되어 발생하는 취약점

웹서비스는 이용자의 입력을 SQL 구문에 포함해 요청하는 경우가 있다
로그인 시 ID/PW를 포함하거나
게시글의 제목과 내용을 포함하는 등

/*
아래 쿼리 질의는 다음과 같은 의미를 가지고 있습니다.
- SELECT: 조회 명령어
- *: 테이블의 모든 컬럼 조회
- FROM accounts: accounts 테이블 에서 데이터를 조회할 것이라고 지정
- WHERE user_id='dreamhack' and user_pw='password': user_id 컬럼이 dreamhack이고, user_pw 컬럼이 password인 데이터로 범위 지정
즉, 이를 해석하면 DBMS에 저장된 accounts 테이블에서 이용자의 아이디가 dreamhack이고, 비밀번호가 password인 데이터를 조회
*/
SELECT * FROM accounts WHERE user_id='dreamhack' and user_pw='password'

DB의 accounts테이블에서 해당 기준(user_id가 dreamhack, user_pw가 password)을 만족하는 데이터를 조회함
이 쿼리문에서 이용자의 아이디와 패스워드가 담겨있다
이렇게 SQL구문에 문자열을 삽입하는 행위가 SQL Injection
SQL Injection이 발생하면 조작된 쿼리로 인증을 우회하거나 DB의 정보를 유출할 수 있다

/*
아래 쿼리 질의는 다음과 같은 의미를 가지고 있습니다.
- SELECT: 조회 명령어
- *: 테이블의 모든 컬럼 조회
- FROM accounts: accounts 테이블 에서 데이터를 조회할 것이라고 지정
- WHERE user_id='admin': user_id 컬럼이 admin인 데이터로 범위 지정
즉, 이를 해석하면 DBMS에 저장된 accounts 테이블에서 이용자의 아이디가 admin인 데이터를 조회
*/
SELECT * FROM accounts WHERE user_id='admin'

Blind SQL Injection

SQL Injection으로 인증 우회말고도 데이터베이스의 데이터를 알아낼 수 있다
이때 사용하는 공격 기법이 Blind SQL Injection
UP DOWN게임처럼 질의를 통해

Question #1. dreamhack 계정의 비밀번호 첫 번째 글자는 'x' 인가요?
Answer. 아닙니다
Question #2. dreamhack 계정의 비밀번호 첫 번째 글자는 'p' 인가요?
Answer. 맞습니다 (첫 번째 글자 = p)
Question #3. dreamhack 계정의 비밀번호 두 번째 글자는 'y' 인가요?
Answer. 아닙니다.
Question #4. dreamhack 계정의 비밀번호 두 번째 글자는 'a'인가요?
Answer. 맞습니다. (두 번째 글자 = a)

질의 결과를 이용자가 화면에서 직접 확인하지 못할 때 true/false 반환 결과로 데이터를 획득하는 공격 기법이 Blind SQL Injection

# 첫 번째 글자 구하기
SELECT * FROM user_table WHERE uid='admin' and substr(upw,1,1))='a'-- ' and upw=''; # False
SELECT * FROM user_table WHERE uid='admin' and substr(upw,1,1))='b'-- ' and upw=''; # True
# 두 번째 글자 구하기
SELECT * FROM user_table WHERE uid='admin' and substr(upw,2,1))='d'-- ' and upw=''; # False
SELECT * FROM user_table WHERE uid='admin' and substr(upw,2,1))='e'-- ' and upw=''; # True 

만약 로그인이 실패할 경우 첫 번째 문자가 'a'가 아님을 알 수 있다
이런 식으로 패스워드를 유추한다
substr은 문자열에서 지정한 위치부터 길이까지의 값을 가져온다

substr(string, position, length)
substr('ABCD', 1, 1) = 'A'
substr('ABCD', 2, 2) = 'BC'

0개의 댓글