영보의 SystemOut.log

SQL Injection 취약점과 대응 방법 본문

기타

SQL Injection 취약점과 대응 방법

영보로그 2021. 7. 13. 10:44
반응형

 취약점 설명 및 사례

1.1) 취약점 설명

 데이터베이스(DataBase)와 연동된 웹 어플리케이션에서 공격자가 입력 폼 및 URL 입력란에 SQL문을 삽입하여 DB로부터 정보를 열람(또는 조작)할 수 있는 취약점

 

 (출처: https://portswigger.net/web-security/sql-injection )

 

 

1.2) 사례

 - ㅇㅇ포털 사이트의 URL에 거짓 코드(Query)를 삽입하면 비정상적인 화면이 노출

 - DB 이름의 길이를 알아내는 SQL 코드를 삽입하면 DB이름을 찾아내고, 매개변수 값에 오류를 발생시키는 코드('+\\+"+\\+')를 삽입하여 페이지를 요청하면 카테고리 값이 변경되어 출력됨

 

 

 

 

 

 점검 방법

2.1) 로그인 페이지 점검

 가) 관리하고 있는 웹서버의 로그인 페이지로 이동

 나) 아이디와 패스워드 란에 아래 문자열을 입력하여 결과 확인

// 점검 예)

아이디 : ' or 1=;--
비밀번호 : ' or 1=1;--

 다) 인증 실패 메시지가 나타날 경우 => SQL Injection취약점은 존재하지 않음

 라) 로그인이 될 경우 SQL Inejction 취약점이 존재
 마) 웹서버 오류 메시지가 나타날 경우, SQL Injection 가능성이 있으므로 정보시스템, 홈페이지 보안가이드을 참고하여 세부적인 점검이 필요함

필터링 대상
'or 1=1;- - or 1=1-- ')or('a'='a + or 1=1- -
' ' or 1=1- - 'or 'a'='a sql' or 1=1- - "
"or 1=1 -- " or "a"="a sql" or 1=1-- '

 

 

2.2) 페이지 입력값 점검

 가) 관리하고 있는 웹서버의 게시판으로 이동

 나) 게시판 등의 게시물 링크를 복사하여 브라우저의 주소표시줄에 입력

 다) 주소표시줄에 입력한 값 중 게시판 번호(또는 글 번호) 등의 입력 값에 아래 예와 같이 인용부호( ' 또는 " )를 입력하여 결과 확인

// 점검 예)
http://www.점검사이트.es.kr/bbs/view.asp?Name=Notice&bbs=09"
http://www.점검사이트.es.kr/bbs/view.asp?bbs=01"&page=09

라) 내용에 DB오류 또는 웹서버의 디렉터리가 노출될 경우, 입력값 검증 부재로 인해 추가 SQL Injection 공격을 차단(특수문자 치환 등)하는 장치가 마련되어 있지 않아 취약한 것을 의미

 

 

 

 

 대응 방안

3.1) 웹 서버 내에서의 조치

 가) 웹 서버의 오류 정보가 사용자에게 노출되지 않도록 조치

 나) 웹 애플리케이션과 연동되는 데이터베이스의 접근 권한을 최소화

 다) 사용자 입력 폼(로그인 폼, 검색 폼, URL 등)을 대상으로 특수문자, 특수구분 필터링 규칙 적용

필터링 대상
' " -- # ( )
= */ /* + < >
user_tables user_table_columns table_name column_name syscolumns
union select insert drop update and
or if join substring from where
declare substr openrowset xp_ 'sysobjects %

 

3.2) 홈페이지 개발 보안 조치

 가) 홈페이지 소스코드는 사용자로부터 입력되는『입력 값』에 대한 검증과 예외처리

  ① ID, PASSWORD, 게시판 제목, 본문, 검색창, 주소검색창 등의 모든 입력란에 특수문자 (등호, 부등호, 인용부호 등)를 직접 입력하지 못하도록 웹서버의 소스코드를 수정

  ② 입력 값에 정의된 문자 길이를 검증하여 SQL문이 추가 삽입되지 않도록 예외처리

  ③ 파라미터가 숫자인 경우 isnumeric과 같은 함수를 이용하여 검증하며, 문자인 경우 정규표현식을 이용하여 특수문자를 치환 특히 sql문에서 활용되는 문자(', ", ;, --, or 등)는 반드시 치환

 

 

3.3) 보안 코드 사용

 대부분의 SQL 주입 인스턴스는 쿼리 내에서 문자열 연결 대신 매개변수화된 쿼리(prepared 문)를 사용하여 방지할 수 있다.

다음 코드는 사용자 입력이 쿼리에 직접 연결되기 때문에 SQL 주입에 취약합니다.

String query = "SELECT * FROM products WHERE category = '"+ input + "'";

Statement statement = connection.createStatement();

ResultSet resultSet = statement.executeQuery(query);
String sql= "SELECT*FROM user_table" + "WHERE id = ?" + "AND password =?";
ResultSet rs = null;
PreparedStatement pstmt = null;
try
conn = DBManager.getConnection();
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, request.getParameter("id"));
pstmt.setString(2, request.getParameter("password"));
rs = pstmt.executeQuery();

 

이 코드는 사용자 입력이 쿼리 구조를 방해하는 것을 방지하는 방식으로 쉽게 다시 작성할 수 있다.

PreparedStatement statement = connection.prepareStatement("SELECT * FROM products WHERE category = ?");

statement.setString(1, input);

ResultSet resultSet = statement.executeQuery();

 매개변수화된 쿼리 WHERE는 INSERTor UPDATE문의 절과 값을 포함하여 신뢰할 수 없는 입력이 쿼리 내 데이터로 나타나는 모든 상황에 사용할 수 있다 . 테이블이나 열 이름 또는 ORDER BY절 과 같은 쿼리의 다른 부분에서 신뢰할 수 없는 입력을 처리하는 데 사용할 수 없다 . 신뢰할 수 없는 데이터를 쿼리의 해당 부분에 배치하는 응용 프로그램 기능은 허용된 입력 값을 화이트리스트에 추가하거나 다른 논리를 사용하여 필요한 동작을 제공하는 것과 같은 다른 접근 방식을 취해야 한다.

반응형