SQL Injection
SQL인젝션이란
- 웹 애플리케이션의 취약점을 악용하여 악의적인 sql 코드를 삽입하고 이를 통해 데이터베이스를 조작하거나 불법적으로 접근하는 공격 기법
- 웹 애플리케이션은 사용자 입력을 기반으로 sql 쿼리를 생성하여 데이터베이스와 상호작용한다. 이때 입력데이터에 대한 검증이 이루어지지 않을 경우, 공격자는 입력필드에 악성 sql코드를 주입해 데이터베이스를 제어할 수 있게 된다.
- sql 인젝션 공격을 통해 개인 정보 탈취, 웹 페이지 내용 변조, 관리자 권한 탈취는 물론 심각한 경우 데이터베이스 전체를 삭제하는 피해 발생 가능성 존재
수행방법
예시플로우 :
- 웹 애플리케이션은 인증 프로세스를 구현하기 위해 SQL 질의를 사용하는데
- 사용자는 애플리케이션이 해당 사용자 계정의 암호 해시를 조회하는데 사용하는데 사용자이름을 제공
- 사용자가 제공한 암호의 해시가 이 암호 해시와 일치하면 사용자가 성공적으로 인증되고 계정에 대한 엑세스 권한을 획득
예시에 앞선 설명:
- 웹 애플리케이션이 sql쿼리에 포함되기 전에 사용자 이름에 대한 유효성 검사를 수행하지 않으면 프로그램에서 의도적으로 잘못된 형식의 사용자 이름을 잘못 해석할 수 있다.
- sql쿼리는 일반적으로 ‘ 이나 “ 를 사용하여 명령의 데이터를 나타내는데
- 사용자 이름을 사용자를 기반으로 데이터베이스에서 고객의 레코드를 조회하는 명령은
- SELECT * FROM customers WHERE username = “user”
공격예시:
- sql쿼리에
- “SELECT * FROM customers WHERE username=”user” OR “1”=”1”
- 사용자 이름(username)이 유저가제공한 값(user)과 일치하는 레코드를 찾는 대신 이 쿼리는 두개 조건중 하나만 일치하는 래코드를 반환
- username=”user”인 레코드는 속임수로 사용하는 조건
- “1”=”1”는 항상참이므로 데이터베이스의 모든 레코드를 반환(공격 조건)
- 이를 통해 공격자는 다른 사용자에 대한 정보를 추출하거나 인증을 우회하거나 다른 사용자로 인증도 시도할 수 있다.
SQL 인젝션의 유형
- sql 인젝션은 공격자가 악성 코드나 명령어를 삽입해 시스템의 동작을 조작하는 공격 기법
- sql 인젝션은 공격방식에 따라 4가지 유형으로 구분된다.
- 각 공격 유형을 이해하고 맞는 보안 대책을 마련하는 것이 중요하다.
1. Error based SQL Injection
- 데이터베이스에서 발생하는 오류 메시지를 통해 데이터베이스 구조나 정보를 파악하는 공격기법
- 공격자는 SQL 쿼리에서 의도적으로 오류를 발생시켜 오류메시지에 나타나는 정보를 통해 데이블명, 컬럼 구조, 데이터내용 등 데이터베이스의 정보를 추론
2. Union SQL Injection
- SQL의 UNION 명령어를 사용하여 원래 쿼리에 악의적인 쿼리를 삽입하고 두 쿼리를 합쳐서 정보를 탈취하는 공격기법
- 공격자는 UNION 명령어를 사용하여 원본 쿼리와 동일한 형태의 악성쿼리를 추가하여 사용자 정보, 로그인 계정, 시스템 정보를 탈취한다.
3. Blind SQL Injection
- True쿼리문과 False쿼리문 입력 시 반환되는 서버의 응답이 다른것을 이용하여 이를 비교해 데이터를 추출하는 공격
- blind SQL Injection은 다른 유형의 SQL Injection과 달리 추출하려는 실제 데이터가 눈에 보이지 않는다
- 따라서 참, 거짓의 입력값에 따른 서버의 응답을 통해 값을 유추해야한다.
- blind SQLi가 성공하려면 True쿼리문과 False쿼리문에 대한 서버의 응답이 상이할 때 가능하다.
Blind SQL Injectoin공격과정 :
- 데이블 목록화 → 컬럼 목록화 → 데이터목록화 순으로 진행한다.
- 전체 Data 개수 확인을 먼저해야한다.
- 자동화툴 사용 등 공격 진행 방향을 판단하기 위해 전체 Data개수를 파악
- 전체 Data 중 1개의 Data를 조회한다.
- 조회한 Data의 문자 1개를 조회한다.
- 문자를 숫자로 변환한다.
- 비교연산을 위해 문자를 아스키(숫자)로 변환한다.
- 비교결과에 따른 참, 거짓 반응을 보고 값을 유추할 수 있다.
- ASCII(e) = 100 > 100 : 참
- ASCII(e) = 101 > 101 : 거짓
- ASCII(e) = 101 = 101 : 참
- “문자조회 → 숫자로 변환” 이 과정을 반복하여 1개 Data에 대한 전체 문자를 확인할 수 있다.
- Data조회과정으로 돌아가 새로운 Data를 추출할 수 있다.
공격에 사용되는 함수:
- SUBSTR함수 - 문자열 자르기
- Blind SQL Injection은 문자열에 대한 특정 위치의 문자를 확인할 수 있다.
- 이때 문자열은 자르는 SUBSTR함수를 사용한다.
- SUBSTR 예시 :
- SELECT SUBSTR(’문자열’, 시작위치, 자르고 싶은 개수) FROM 테이블명
- SELECT SUBSTR(”qwe”, 1, 1) FROM KB ⇒ q
- SELECT SUBSTR(”qwe”, 2, 3) FROM KB ⇒ we
- MySQL경우에는 SUBSTRING함수를 사용한다.
- ASCII함수 - 문자를 숫자로 변환하기
- 위에서 SUBSTR함수로 문자열중 1개문자를 출력한 후, 조건문에서 값을 비교하기 위해 논리형 자료로 가공한다.
- 추출한 문자를 숫자로 변환하여 범위를 설정해 값을 유추하면 비교연산을 쉽게 진행할 수 있다.
- 문자를 ASCII(10진수)로 변환한다. 이때 비교대상이 불일치하면 “Invalid Number”라고 에러가 발생한다.
- 문자를 숫자로 변환 예시:
- “qwe”에서 첫번째 문자 q를 ASCII함수로 변환하고 참거짓조건문에 대한 출력결과
- SELECT ASCII(SUBSTR(’qwe”, 1, 1)) FROM 테이블명 ⇒ 113
- 문자열에 1번쨰 문자가 q인것을 ASCII로 113 인것을 확인
- SELECT ‘image’ FROM 테이블명 WHERE ASCII(SUBSTR(’qwe”, 1, 1)) > 0 ⇒ image
- 비교문(113>0)의 결과는 참이므로 image를 출력
- SELECT ‘image’ FROM 테이블명 WHERE ASCII(SUBSTR(’qwe”, 1, 1)) > 112 ⇒ image
- 비교문(113>112)의 결과는 참이므로 image를 출력
- SELECT ‘image’ FROM 테이블명 WHERE ASCII(SUBSTR(’qwe”, 1, 1)) > 113 ⇒ 없음
- 비교문(113>113)의 결과는 거짓이므로 아무것도 출력하지 않음
- SELECT ‘image’ FROM 테이블명 WHERE ASCII(SUBSTR(’qwe”, 1, 1)) = 113 ⇒ image
- 비교문(113=113)의 결과는 참이므로 image를 출력
Blind SQL Injectoin 진행과정
- 취약점 존재 여부확인
- Blind SQL Injection 진행
- 테이블정보확인
- 컬럼정보확인
- 데이터정보확인
- 원하는 데이터 탈취
3. Stored Procedure SQL Injection
- 데이터베이스에 저장된 저장프로시져의 취약점을 이용하는 공격기법
- 저장프로시져는 미리 컴파일된 SQL 코드를 저장하여 데이터베이스 객체로, 공격자는 저장프로시저에 악성 SQL을 삽입하여 데이터베이스를 제어
- 저장 프로시저의 권한을 이용하여 데이터베이스 전체를 장악 가능
SQL Injection 대응방법
SQLi간단설명
- SQL Injection은 SQLi 공격이라고도 한다.
- SQL명령에 신뢰할 수 없는 데이터를 사용할떄 입력 유효성 검사가 잘못되었다고 뜨는 점을
- 다수의 SQLi 공격은 사용자 입력 내에서 ‘ “ 문자를 사용한 공격방식이다.
대응방법
- 입력 유효성 검사
- 영어 숫자 이름을 사용한 username만 허용하는 등 특정문자가 사용자 입력에 포함되지 않도록 하는 것
- 입력 유효성 검사는 중요하지만 SQL 삽입 공격으로 보호하기에 충분x
- 공격자는 차단을 피하기 위해 예기치 않은 문자 조합을 사용하여 허용 목록 또는 차단 목록을 우회하기도 한다.
- 웹 애플리케이션 방화벽(WAF)
- 웹 애플리케이션 및 API 보호(WAAP)
보안대책
- Prepared Statement :
- SQL Injection의 근본적인 해결책이지만, 문법적/비즈니스 로직 상 사용이 불가한 로직이 있으며 서버가 운영 중일 경우 소스코드 수정이 어려울 수 있다.
- Filtering:
- White List Filter 방식을 적용해 허용할 문자열을 지정하는 것이 좋다. 상황에 따라 Black
List Filter 방식을 적용해야 한다면, 공격 기법에 사용될 수 있는 예약어 및 특수 문자를 모두 Filtering 해야
한다
- 문자열 Filtering 시 대소문자 모두 Filtering 하는 것을 권장한다.
- Blind SQL Injection의 경우 SUBSTR, ASCII, <, > 등 공격에 활용되는 함수, 연산자 등을 필터링해야 한다.
그외
파라미터화된 쿼리
- sql Injection을 방지하는 가장 효과적인 방법
- 쿼리문을 템플릿 형태로 미리 준비하고 사용자 입력은 파라미터로 전달해 구조 변경을 차단한다.
- 입력 값은 쿼리 실행 시점에 안전하게 전달되어 악성 코드 삽입을 막을 수 있다
입력값 필터링
- 사용자 입력을 허용된 패턴으로 제한하거나 위험한 문자를 제거하여 공격을 차단한다
- Prepared Statement와 함께 사용하면 보안 효과가 더욱 강화된다.
DB 계정 권한 최소화
- 웹 애플리케이과 관리자 계정을 분리하고, 최소 권한만 부여해야한다.
- 계정이 탈취되더라도 제한된 권한으로 인해 데이터베이스 전체를 장악하기 어렵다.
보안 도구 활용
- 보안도구를 활용하여 SQL Injection 공격 가능성 점검
- SQL Injection 시도가 가능한 파라미터를 탐지하고 다양한 입력값으로 반복적으로 시도하여 애플리케이션의 반응을 분석해 취약점을 알아내고, 예상치 못한 입력에도 안전하게 작동하도록 보안을 강화할 수 있다.