CS 공부
SQL Injection 본문
SQL Injection 이란
악의적인 사용자가 보안상의 취약점을 이용하여, 임의의 SQL 문을 주입하고 실행되게 하여 데이터베이스가 비정상적인 동작을 하도록 조작하는 행위이다,
대부분 클라이언트가 입력한 데이터를 제대로 필터링하지 못하는 경우에 발생
공격의 쉬운 난이도에 비해 피해가 상당하다.
공격 종류 및 방법
논리적 에러를 이용한 SQL Injection
가장 많이 쓰이고, 대중적인 공격 기법
위의 사진에서 보이는 쿼리문은 일반적으로 로그인 시 많이 사용되는 SQL 구문이다.
해당 구문에서 입력 값에 대한 검증이 없다면 논리적인 에러를 이용한 SQL Injection이 가능하다.
주입된 내용은 ‘ OR 1=1 -- 로 WHERE 절에 있는 싱글쿼터를 닫아주기 위한 싱글쿼터와 OR 1=1 라는 구문을 이용해 WHERE 절을 모두 참으로 만들고, -- 를 넣어줌으로 뒤의 구문을 모두 주석 처리 해주는 방법이다.
매우 간단한 구문이지만, 결론적으로 Users 테이블에 있는 모든 정보를 조회하게 됨으로 써 가장 먼저 만들어진 계정으로 로그인에 성공하게 된다.
즉 간단하게 말하면 OR 뒤에 무조건 참인 항등식을 넣는 방식이다.
보통은 관리자 계정을 맨 처음 만들기 때문에 관리자 계정에 로그인 할 수 있게되고 그러면 관리자의 권한을 이용해 또 다른 2차피해를 발생 시킬 수 있게 된다.
Union 명령어를 이용한 SQL Injection
SQL UNION이란?
여러개의 SQL문을 합쳐 하나의 SQL문으로 만들어주는 방법이다.
UNION과 UNION ALL로 나뉘는데 중복 값을 제외 하고 안하고의 차이다.
UNION은 중복 값을 제외하고 UNION ALL은 제외 하지 않고 전체를 합친다.
이러한 UNION의 특성을 이용하여 SQL Injection을 진행한다.
Union Injection을 성공하기 위해서는 두 가지의 조건이 있다.
하나는 Union 하는 두 테이블의 컬럼 수가 같아야 하고, 데이터 형이 같아야 한다.
위의 사진에서 보이는 쿼리문은 Board 라는 테이블에서 게시글을 검색하는 쿼리문이다.
입력값을 title 과 contents 컬럼의 데이터랑 비교한 뒤 비슷한 글자가 있는 게시글을 출력한다.
여기서 입력값으로 Union 키워드와 함께 컬럼 수를 맞춰서 SELECT 구문을 넣어주게 되면 두 쿼리문이 합쳐서서 하나의 테이블로 보여지게 된다.
이 공격도 역시 입력값에 대한 검증이 없다는 가정하에 가능한 방법이다.
Blind SQL Injection(Boolean based SQL)
Blind SQL Injection은 웹에서 SQL 삽입에 취약하나 데이터베이스 메시지가 공격자에게 보이지 않을 때 사용한다.
즉 데이터베이스로부터 특정한 값이나 데이터를 전달받지 않고, 단순히 참과 거짓의 정보만 알 수 있을 때 사용한다.
즉, 쿼리를 삽입하였을 때, 쿼리의 참과 거짓에 대한 반응을 구분할 수 있을때에 사용되는 기술이다.
로그인 폼에 SQL Injection이 가능하다고 가정 했을 때, 서버가 응답하는 로그인 성공과 로그인 실패 메시지를 이용하여, DB의 테이블 정보 등을 추출해 낼 수 있다.
Blind SQL 삽입은 위 두 함수를 이용하여 쿼리의 결과를 얻어, 한글자씩 끊어온 값을 아스키코드로 변환시키고 임의의 숫자와 비교하여 참과 거짓을 비교하는 과정을 거쳐가며 계속 질의를 보내어 일치하는 아스키코드를 찾아낸다. 위의 그림이 그 예시이다.
그러한 과정을 반복하여 결과들을 조합하여 원하는 정보를 얻어냄으로써 공격을 이루어지게 한다. 많은 비교과정이 필요하기 때문에 악의적인 목적을 가진 크래커들은 Blind SQL 삽입 공격을 시도할때에 자동화된 툴을 사용하여 공격한다. 취약점이 발견된다면 순식간에 많은 정보들이 변조되거나 크래커의 손에 넘어가게 된다.
Blind SQL Injection(Time based SQL)
Time Based SQL Injection 도 마찬가지로 서버로부터 특정한 응답 대신에 참 혹은 거짓의 응답을 통해서 데이터베이스의 정보를 유추하는 기법이다
하지만 해당 방법은 응답의 결과가 항상 동일하여 해당 결과만으로 참과 거짓을 판별할 수 없는 경우에 사용한다.
Time Based SQL Injection은 시간을 지연시키는 쿼리를 주입(injection)하여 응답 시간의 차이로 참과 거짓 여부를 판별할 수 있다.
시간 지연 쿼리에 사용되는 함수는 MySQL 기준으로 SLEEP 과 BENCHMARK 이다.
위의 예시의 경우 주입된 구문에서, LENGTH(DATABASE()) = 1 가 참이면 SLEEP(2) 가 동작하고, 거짓이면 동작하지 않는다. 저 구문에서 1을 조작하여 DB의 길이를 알아낼 수 있다.
저장된 프로시저에서의 SQL Injection
저장 프로시저(Stored Procedure) 은 일련의 쿼리들을 모아 하나의 함수처럼 사용하기 위한 것이다.
프로시저는 SQL에서 사용하는 함수 같은 것이다.
공격에 사용되는 대표적인 저장 프로시저는 MS-SQL 에 있는 xp_cmdshell로 윈도우 명령어를 사용할 수 있게 된다. 단, 공격자가 시스템 권한을 획득 해야 하므로 공격난이도가 높으나 공격에 성공한다면, 서버에 직접적인 피해를 입힐 수 있는 공격이다.
다량의 SQL Injection 공격
2008년에 처음 발견된 공격기법으로 기존 SQL Injection 과 달리 한번의 공격으로 다량의 데이터베이스가 조작되어 큰 피해를 입히는 것을 의미한다.
보통 MS-SQL을 사용하는 ASP 기반 웹 애플리케이션에서 많이 사용되며, 쿼리문은 HEX 인코딩 방식으로 인코딩 하여 공격한다.
보통 데이터베이스 값을 변조하여 데이터베이스에 악성스크립트를 삽입하고, 사용자들이 변조된 사이트에 접속 시 좀비PC로 감염되게 한다.
대응 방안
입력값에 대한 검증
SQL Injection 에서 사용되는 기법과 키워드는 엄청나게 많기 때문에 사용자의 입력 값에 대한 검증은 서버 단에서 화이트리스트 기반으로 검증해야 한다.
블랙리스트 기반으로 검증하게 되면 수많은 차단리스트를 등록해야 하고, 하나라도 빠지면 공격에 성공하게 되기 때문이다.
공백으로 치환하는 방법도 많이 쓰이는데, 이 방법도 취약한 방법인 것이 예를 들어 공격자가 SESELECTLECT 라고 입력 시 중간의 SELECT가 공백으로 치환이 되면 SELECT 라는 키워드가 완성되게 된다.
따라서 치환 방법을 사용하려면 공백 대신 공격 키워드와는 의미 없는 단어로 치환되어야 한다.
Prepared Statement 구문사용
서버 단에서 사용자 입력을 SQL 구문에 끼워 넣을 때 Prepared Statement 구문을 사용하게 되면, 사용자의 입력 값이 데이터베이스의 파라미터로 들어가기 전에DBMS가 미리 컴파일 하여 실행하지 않고 대기한다.
그 후 사용자의 입력 값을 문자열로 인식하게 하여 공격 쿼리가 들어간다고 하더라도, 사용자의 입력은 이미 의미 없는 단순 문자열이기 때문에 전체 쿼리문도 공격자의 의도대로 작동하지 않는다.
Error Message 노출 금지
공격자가 SQL Injection을 수행하기 위해서는 데이터베이스의 정보(테이블명, 컬럼명 등)가 필요하다.
데이터베이스 에러 발생 시 따로 처리를 해주지 않았다면, 에러가 발생한 쿼리문과 함께 에러에 관한 내용을 반환하는데 여기서 테이블명 및 컬럼명 그리고 쿼리문이 노출이 될 수 있기 때문에, 데이터베이스에 대한 오류발생 시 사용자에게 보여줄 수 있는 페이지를 제작 혹은 메시지박스를 띄우도록 해야한다.
웹 방화벽 사용
웹 공격 특화 되어있는 웹 방화벽은 소프트웨어 형, 하드웨어 형, 프록시 형 이렇게 세가지 종류로 나눌 수 있다.
소프트웨어 형은 서버 내에 직접 설치하는 방법
하드웨어 형은 네트워크 상에서 서버 앞 단에 직접 하드웨어 장비로 구성하는 방법
마지막으로 프록시 형은 DNS 서버 주소를 웹 방화벽으로 바꾸고 서버로 가는 트래픽이 웹 방화벽을 먼저 거치도록 하는 방법이다.
참조
https://noirstar.tistory.com/264
https://m.blog.naver.com/lstarrlodyl/221837243294
'CS공부 > 데이터베이스' 카테고리의 다른 글
트랜잭션(Transaction) 1(트랜잭션이란+트랜잭션 작동방식) (0) | 2021.07.20 |
---|---|
SQL vs NoSQL (0) | 2021.07.17 |
SQL-JOIN (0) | 2021.07.17 |
Database의 Key (0) | 2021.07.16 |
데이터 베이스 개요 (0) | 2021.07.16 |