SQL Injection
SQL 인젝션이란 악의적인 사용자가 보안상의 취약점을 이용하여, 임의의 SQL문을 주입하고 실행되게 하여 데이터베이스가 비정상적으로 동작을 하도록 조작하는 행위이다. 인젝션 공격은 비교적 쉬운 편이지만, OWASP Top10 중 첫 번째에 속해 있으며 공격에 성공할 경우 큰 피해를 입힐 수 있는 공격이다.
공격 방법
1. Error based SQL Injection
논리적 에러를 이용한 SQL Injection
SELECT * FROM Users WHERE id = 'INPUT1' AND password = 'INPUT2';
SELECT * FROM Users WHERE id = '' OR 1=1 -- ' AND password = 'INPUT2'
> 과정
싱글쿼터를 닫아주기 위한 싱글쿼터와, OR 1=1 구문을 이용해 WHERE 절을 모두 참으로 만들고, -- 를 넣어줌으로써 뒤의 구문을 모두 주석 처리 해버림
> 결과
Users 테이블에 있는 모든 정보를 조회하게 됨으로써 가장 먼저 만들어진 계정 (보통 관리자 계정) 으로 로그인할 수 있게 됨
→ 관리자 계정 탈취
2. Union based SQL Injection
Union 명령어를 이용한 SQL Injection
SELECT * FROM Board WHERE title LIKE '%INPUT%' OR contents '%INPUT%'
SELECT * FROM Board WHERE title LIKE '% ' UNION SELECT null,id,passwd FROM Users -- INPUT%' OR contents '%INPUT%'
위 쿼리문은 Board라는 테이블에서 게시글을 검색하는 쿼리문이다.
입력값을 tiltle 과 contents 컬럼의 데이터와 비교한 뒤 비슷한 글자가 있는 게시글을 출력한다. 여기서 입력값으로 UNION 키워드와 함께 컬럼 수를 맞춰서 SELECT 구문을 넣어주게 되면 두 쿼리문이 합쳐져서 하나의 테이블로 보여지게 된다.
> 성공 조건
1) UNION하는 두 테이블의 컬럼 수가 같아야함
2) UNION하는 두 테이블의 데이터 형이 같아야함
> 과정
사용자의 id와 passwd를 요청하는 쿼리문을 주입함
> 결과
사용자의 개인정보가 게시글과 함께 화면에 보여짐
3. Blind SQL Injection (Boolean based SQL)
특정한 값이나 데이터를 전달 받는 것이 아닌, 쿼리를 통해 나온 참과 거짓의 정보만을 통해 정보를 취득한다.
SELECT * FROM Users WHERE id = 'INPUT1' AND password = 'INPUT2'
SELECT * FROM Users WHERE id = 'abc123' and ASCII(SUBSTR((SELECT name FROM information_schema.tables WHERE table_type='base table' limit 0,1),1,1)) > 100 (로그인이 될 때까지 시도) -- INPUT1' AND password = 'INPUT2'
위의 쿼리문은 DB의 테이블명을 알아내는 쿼리문이다.
> 사용되는 SQL문 : LIMIT, SUBSTR, ASCII
> 과정
임의로 가입한 abc123이라는 아이디와 함께 뒤의 구문을 주입한다.
해당 구문은 테이블 명을 조회하는 구문으로 limit 키워드를 통해 하나의 테이블만 조회하고, SUBSTR 함수로 첫 글자만, ASCII를 통해서 ascii 값으로 변환한다.
만약 조회되는 테이블 명이 Users 라면 'U' 자가 ascii 값으로 조회가 될 것이고, 뒤의 100이라는 숫자 값과 비교하게 된다.
> 결과
거짓이면 로그인 실패가 될 것이고, 참이 될 때까지 뒤의 100이라는 숫자를 변경해 가면서 비교하면 된다. 공격자는 이 프로세스를 자동화 스크립트로 만들어 단기간 내에 테이블 명을 알아낼 수 있다.
4. Blind SQL Injection (Time based SQL)
쿼리 결과를 특정 시간만큼 지연시키는 것 & 궁금적으로 DB 구조를 파악하기 위함
SELECT * FROM Users WHERE id = 'INPUT1' AND password = 'INPUT2'
SELECT * FROM Users WHERE id = 'abc123' OR (LENGTH(DATABASE())=1 (SLEEP 할 때까지 시도) AND SLEEP(2)) -- INPUT1' AND password = 'INPUT2'
> 사용되는 SQL문 : SLEEP, BENCHMARK
> 과정
LENGTH(DATABASE()) = 1 이 참이면 SLEEP(2)가 동작하고, 거짓이면 동작하지 않는다.
> 결과
숫자 1 부분을 조작하여 DB의 길이를 알아낼 수 있다.
> 예외
SLEEP이라는 단어가 치환 처리 되어있는 경우, BENCHMARK나 WAIT 함수 사용
5. Stored Procedure SQL Injection
Stored Procedure : 편의를 위해 일련의 쿼리들을 모아 하나의 함수처럼 모아둔 것.
> 상황
대표적으로, MS SQL에서 사용할 수 있는 xp_cmdshell을 통해 윈도우 명령어를 실행할 수 있음 → 자주 악용됨
단, 공격자가 시스템 권한을 획득해야 하므로 공격난이도가 높음.
> 결과
공격에 성공한다면 서버에 직접적인 피해를 입힐 수 있음
방어 방법
1. 입력값에 대한 검증
- 검증 로직을 추가하여 미리 설정한 특수문자들이 들어왔을 때 요청 막기
- 특수문자 등의 에러 발생 유무 확인
- 서버 단에서 화이트리스트 기반이 아닌 블랙리스트 기반으로 검증하게 되면 수많은 차단리스트를 등록해야 하고, 하나라도 빠지면 공격에 성공하게 된다.
2. Error Message 노출 금지
- 별도로 처리해주지 않을 경우 에러가 발생한 쿼리문과 함께 에러에 관한 내용 반환
- 이 때, 테이블명, 컬럼명, 쿼리문이 노출될 수 있기 때문에 메세지가 표시되지 않도록 처리하거나 새로운 페이지 제작
3. 저장 프로시저 사용
- 사용하고자 하는 쿼리에 미리 형식을 지정하여 지정된 형식의 데이터가 아니면 쿼리 실행 안 되도록 함
4. 서버 보안
- 최소 권한 유저로 DB 운영
- 목적에 따라 쿼리 권한 수정- 신뢰할 수 있는 네트워크, 서버에 대해서만 접근 허용- 웹 방화벽 사용
참고
| https://doh-an.tistory.com/27
| https://velog.io/@yanghl98/Database-SQL-Injection
| https://m.blog.naver.com/dktmrorl/222048311115
| https://choco4study.tistory.com/10
| https://noirstar.tistory.com/264
'Database' 카테고리의 다른 글
[DB] 정규화 & 비정규화 (0) | 2022.10.07 |
---|---|
[DB] Index & B-Tree (2) | 2022.10.05 |
[DB] SQL vs NoSQL (4) | 2022.10.03 |
[DB] 조인(JOIN) 정리 (0) | 2022.09.28 |
[DB] 키(KEY) 정리 (2) | 2022.09.27 |