[해킹보안] 창과 방패 끝없는 전쟁

■ 입력데이터 검증 및 표현

프로그램 입력값에 대한 검증 누락 또는 부적적한 검증, 데이터의 잘못된 형식지정, 일관되지 않은 언어셋 사용 등으로 인해 발생되는 보안 약점으로 SQL 삽입, 크로스 사이트 스크립트(XSS) 등의 공격 유발 가능.

- SQL Injection

 > 개요

  데이터베이스(DB)와 연동된 웹 어플리케이션에서 입력된 데이터에 대한 유효성 검증을 하지 않을 경우, 공격자가 입력 폼 및 URL 입력란에 SQL문을 삽입하여 DB로 부터 정보를 열람하거나 조작할 수 있는 보안약점을 말함.

 

<그림 3-1>에서 나타낸 것처럼, 취약한 웹 응용프로그램에서는  사용자로부터 입력된 값을 필터링 과정 없이 넘겨받아 동적쿼리(Dynamic Query)를 생성하기 때문에 개발자가 의도하지 않은 쿼리가 생성되어 정보유출에 악용될 수 있다.

동적쿼리(Dynamic Query) : DB에서 실시간으로 받는 쿼리.Prepared Statement가 동적쿼리가 됨.

> 보안대책

 - Prepared Statement 객체 등을 이용하여 DB에 컴파일 된 쿼리문(상수)을 전달하는 방법을 사용한다. Prepared Statement 를 사용하는 경우에는 DB쿼리에 사용되는 외부 입력값에 대하여 특수문자 및 쿼리 예약어를 필터링하고, 스트러츠(Struts), 스프링(Spring)등과 같은 프레임워크를 사용하는 경우에는 외부 입력값 검증 모듈 및 보안 모듈을 상황에 맞추어 적절하게 사용한다.

Prepared Statement 객체: 컴파일된 쿼리 객체로 MySQL, Oracle, DB2, SQL Server등에서 지원하며, JAVA의 JDBC, Perl의 DBI, PHP의 PDO, ASP의 ADO를 이용하여 사용 가능

> 코드예제

- 다음은 안전하지 않은 코드의 예를 나타낸 것으로, 외부로부터 tableName과 name의 값을 받아서 SQL 쿼리를 생성하고 있으며, name의 값으로 name' OR 'a'='a를 입력하면 조작된 쿼리를 생성하는 문자열 전달이 가능하다.

 

 

이를 안전한 코드로 변환하면 다음과 같다. 파라미터(Parameter)를 받는 preparedStatement 객체를 상수 스트링으로 생성하고, 파라미터 부분을 setXXX 메소드로 설정하여, 외부의 입력이 쿼리문의 구조를 바꾸는 것을 방지하는 것이 필요하다.

 

다음의 예제는 SQL Injection 공격 중 JDO의 경우를 나타내는 것으로, JDO API의 SQL 또는 JDO SQL 쿼리 생성을 위한 문자열이 외부 공격자에 의해 그 의미가 왜곡되거나 구조가 변경되어 임의의 쿼리를 수행하는 것을 나타내고 있다.

아래 코드에서 공격자가 외부의 입력(name)값을 name';DROP TABLE MYTABLE;-- 로 입력하게 되면, 최종적으로 수행되는 쿼리는 다음과 같이 변경되고 이 쿼리로 수행되어 테이블이 삭제된다.

SELECT col1 FROM MYTABLE WHERE name = 'name';DROP TABLE MYTABLE;--'

 

위 코드를 아래 코드와 같이 외부 입력값이 위치하는 부분을 ?로 설정하고, 실행시에 해당 파라미터가 전달 되도록 수정함으로써 외부의 입력(name)이 쿼리의 구조를 변경시키는 것을 방지할 수 있다.

 

SQL Injection 공격 Persistence는 Java 계열 언어에서 발생할 수 있는 SQL Injection 공격의 일종으로서 J2EE Persistence API를 사용하는 응용프로그램에서 외부의 입력을 아무런 검증 없이 질의문으로 사용할 때 내부 정보가 노출되는 공격이다.

아래 코드에서 공격자가 외부 입력(id) 값으로 foo';DROP TABLE MYTABLE;--을 주게 되면, 다음과 같은 질의문이 실행되어 테이블이 삭제된다.

 

SELECT OBJECT(i) FROM item i WHERE col1 i.itemNAME = 'foo' ; DROP TABLE MYTABLE;--'

 

위 코드를 안전한 코드로 변경하는 방법은 아래 예제 코드와 같이 파라미터를 받는 쿼리(query)를 생성하고, 파라미터를 설정하여 실행하도록 한다. 이를 통해 외부의 입력이 쿼리의 구조를 변경시키는 것을 방지할 수 있다.

 

 

SQL Injection 공격 MyBatis Data Map은 외부에서 입력되는 값이 SQL 질의문을 연결하는 문자열로 사용되는 경우에 의도하지 않은 정보가 노출될 수 있는 공격 형태이다.

 

아래의 코드를 보면 정의된 질의문 중 delStudent 명령어 선언에서 쿼리에 삽입되는 파라미터들 중 $name$으로 전달되는 문자열 값이 그대로 연결되어 쿼리로 만들어진다. 따라서 만약 name의 값으로 ' OR 'x'='x'을 전달하면 다음과 같은 쿼리로 수행되어 테이블의 모든 원소를 삭제하게 된다.

DELETE STUDENTS WHERE NUM = '' and NAME = '' or 'x' = 'x'

 

위 코드는 아래와 같이 Name 파라미터를 #name# 형태로 받도록 수정하는 것이 안전하다.

 

 

[참고문헌]

[1] CWE-89 SQL Injection, MITRE,

http://cwe.mitre.org/data/definitions/89.html

[2] 2013 OWASP Top 10 - A1 Injection, OWASP,

http://www.owasp.org/index.php/Top_10_2013

[3] 2011 CWE/SANS Top 25 - RANK 1 (CWE-89), MITRE,

http://cwe.mitre.org/top25/

[4] 시큐어코딩 보안가이드

https://www.kisa.or.kr/public/laws/laws3_View.jsp?mode=view&p_No=259&b_No=259&d_No=55&ST=T&SV=

 

[출처] 행안부, 한국인터넷진흥원

'시큐어코딩' 카테고리의 다른 글

SQL Injection 시큐어코딩  (0) 2016.01.04

Comment +0