http://erratasec.blogspot.com/ 를 운영하는 운영자에 따르면 유엔 웹사이트가 2년전부터 SQL 인젝션 공격에 노출이 되었는데 아직도 고쳐지지 않고 있다고 말하고 있다.



2년전 자신의 블로그를 통하여 http://erratasec.blogspot.com/2007/08/sql-injection-is-surpisingly-easy.html 에 지적을 하고 있었지만 아직도 여전히 동일한 취약성이 나타나고 있다는 것이다.


그것은 http://www.un.org/apps/news/infocus/sgspeeches/statments_full.asp?statID=105' 에서 다음과 같은 에러 메세지를 보여 주는 것이다.


2년전 그가 적은 포스팅에서 'SQL 인젝션' 공격은 모든 웹사이트에서 일어날수 있으며 그섯은 '실시간 해킹' 이 가능하다고 하며, 이러한 것은 몇분안에 이루어 질수 있다고 하였다.

또한 SQL 인젝션 공격이 일어나는 것은 대부분 시스템들이 코드와 데이터를 분리시키는 것이며 SQL은 이것을 조합하기 때문에 해커는 싱클쿼터 (')를 사용하여 코드와 데이타 사이에서 SQL을 인터럽트 한다고 한다.

이 블로그 운영자는 유엔 웹사이트도 마찬가지로 URL 마지막에 'StartID' 필드에 싱글 쿼터를 넣음으로 인하여 위와 같은 그림에 볼수 있다고 하였다.

이러한 SQL 에러코드는 이 블로그 운영자에 따르면 99.9% 취약성을 가지고 있다고 자신있게 말하고 있다.

그러면서 몇가지 사항을 알려주었는데 우선 구글에서 "allinurl:statID" 적고 (유엔 웹사이트와 같은 에러) 두번째 검색 결과로 가서  'statid' 에 싱글 쿼터를 적었다.  그러면 다음과 같은 메세지를 볼수 있다.,

OraOLEDB error '80004005'
ORA-01756: quoted string not properly terminated
/app/contents.asp, line 1470



그러면서 왜 사람들이 '구글' 해킹이라고 하는지 알아야 한다고 말 한다. 이러한 에러는 보이는 사이트들은 SQL 인젝션에 노출이 되어 있고 쉽게 공격을 당할수 있다고 경고를 하고 있다.

실제 구글에서 위 상황을 검색하여 실행 해 보았지만 '유엔' 사이트가 자주 접하게 되었고 나머지 대부분의 사이트들은 DB와 연결이 되지 않으며 에러메세지를 보여 주지도 않았다. 

SQL 인젝션 공격에 노출되어 있는 만큼 빠른 웹사이트 소스 코드가 수정이 되었으면 하는 바램을 가져 본다.


Posted by 엔시스

하루에도 수십만명이 접속하는 포털에서 가장 많이 공격 받는 방법은 SQL-injection 공격과 xss 공격으로 나타났다.,

관련 포스팅: 떡이떡이 블로그

“다음 홈피 보안공격 빈도,
 SQL인젝션-XSS 순”

SQL 인젝션 공격은 나온지 오래 되었음에도 불구하고 아직도 많은 수의 공격이 이루어지고 있다. 그것은 개발에 따른 보안에 대한 인식이 많이 가져다 한다는 반증이기도 하다.

다양한 웹공격에 방어를하기 위해서는 개발 초기에 보안에 신경을 써야 하겠지만 그렇지 못한 경우는 웹 방화벽을 이용한 방어에 많은 신경을 써야 할것이다.

보안관리자나 시스템 관리자는 SQL 인젝션에 대하여 보다 많은 기법으로 공격 해 올 경우를 대비하여 많은 관심을 갖어야 겠습니다..


◆SQL 인젝션 = 데이터베이스(DB) 서비스인 ‘SQL’의 쿼리 문자열 사이에 특정 악성 코드를 몰래 삽입해 넣은 뒤 실행시키는 해킹 공격 방법.

◆XSS(크로스 사이트 스크립팅) = 클라이언트 스크립트나 HTML 태그 등을 통해 악의적으로 만든 웹페이지에 접근했을 때 사용자 정보를 빼내는 해킹 공격 방법.
Posted by 엔시스

사용자 입력값이 SQL injection 발생시키지 않도록 수정

다수 사이트, SQL Injection 취약점 공격에 무방비 상태


웹 취약점을 이용한 공격이 식을 줄 모르고 있다. 공격의 목적은 게임정보 탈취와 궁극적으로는 이를 이용한 게임아이템 거래로 돈을 벌기 위한 것이다.


정보통신부와 KISA는 이에 대한 대책으로 중국에서 들어오는 IP들을 차단하고 있고 자금 여력이 없는 중소기업의 웹사이트 관리자에게 공개 웹방화벽 구축을 권유하고 있으며 개인 PC의 보안패치율을 높이기 위해 각종 캠패인을 벌이고 있다.


KISA에서 운영하는 ‘보호나라’에서는 대국민 서비스로 원격 PC점검을 해주고 있고 대기업을 중심으로 보안솔루션 도입과 시스템 구축이 한창이다. 하지만 이러한 노력에도 불구하고 해킹 관제 서비스를 실시하고 있는 업체에서는 하루에도 2백~3백건의 해킹이 이루어지고 있고 이를 통한 악성코드 유포가 지속적으로 이루어지고 있다고 지적하고 있다.


KISA 관계자는 “지난해 정부기관 사이트와 주요 웹사이트를 대상으로 대대적인 웹사이트 모의 해킹을 실시한 결과 대부분의 사이트들이 SQL Injection 취약점 공격에 맥없이 뚫렸다”며 “SQL Injection 취약점 공격에 대한 대비책을 개발자들이 기본적으로 알고 있어야한다”고 강조했다.


<보안뉴스>는 얼마전부터 웹개발자들이 기술,정신적으로 보안강화에 더욱 노력해야 한다는 기사와 관련정보를 제공해 오고 있다. 이번에는 SQL Injection 취약점에 대해 알아보자. 자료 제공은 KISA 해킹대응팀이다. 


<기획3> 악의적인 명령어 주입 공격(SQL Injection)


현재 대부분의 웹 사이트들은 사용자로부터 입력받은 값을 이용해 데이터 베이스 접근을 위한 SQL Query를 만들고 있다. 사용자 로그인 과정을 예로 들면, 사용자가 유효한 계정과 패스워드를 입력했는지 확인하기 위해 사용자 계정과 패스워드에 관한 SQL Query문을 만든다. 이때 SQL injection 기법을 통해서 정상적인 SQL query를 변조할 수 있도록 조작된 사용자 이름과 패스워드를 보내 정상적인 동작을 방해할 수 있다. 이러한 비정상적인 SQL Query를 이용해 다음과 같은 공격이 가능하다.


-사용자 인증을 비정상적으로 통과할 수 있다.

-데이터베이스에 저장된 데이터를 임의로 열람할 수 있다.

-데이터베이스의 시스템 명령을 이용하여 시스템 조작이 가능하다.


이러한 취약점을 ‘SQL Injection 취약점’이라고 하며, 사용자가 데이터 입력이 가능한 수많은 웹 페이지 상에 이러한 취약점이 존재할 수 있다.


■위협 사례


(1) 사용자 인증 공격


아래의 그림과 같이 인증을 처리하는 모듈이 입력 값에 대해 적절히 검사하지 않았을 때 공격자는 비정상적인 SQL Query를 삽입 할 수 있고 이를 이용해 사용중인 데이터베이스에 영향을 줄 수 있다.



다음은 SQL 구문을 이용하여 인증을 처리하는 일반적인 웹 페이지 구조를 나타낸다.

$row = mysql_query (" SELECT 신청인명, 접수번호 from USER_TABLE where 신청인명='첫번째입력값' and 접수번호='두번째입력값' ");

if ( $row == 1 )

// 인증 성공 루틴

else 

  // 인증 실패 루틴


이 스크립트에 공격자가 test라는 신청인명을 입력하고 인터넷접수번호 대신 A' or 'A'='A 이란 값을 입력하면 아래와 같은 SQL Query가 완성된다.


SELECT 신청인명,접수번호 FROM user_table WHERE 신청인명=‘test?? AND 접수번호=??A' OR 'A'='A'


이 경우 구문의 WHERE 절은 ??참 AND 거짓 OR 참??의 WHERE 절이 생성되며 무조건 참이 되어 SQL 구문은 올바른 입력 값으로 처리하게 되며 공격자는 웹 인증 페이지를 쉽게 통과할 수 있게 된다.


(2) MS-SQL상에서의 시스템 명령어 실행


MS-SQL 데이터베이스를 사용하는 경우를 예를 들어 보자. 만약 데이터베이스 접근 권한이 시스템 권한을 사용하고 있다면 MS-SQL에서 기본적으로 제공하고 있는 xp_cmdshell이라는 Stored Procedure를 이용하여  시스템 명령어를 실행할 수 있다.


예로 위의 인증 페이지에서 신청인명에 test, 접수번호에 ??; exec master..xp_cmdshell ??ping 10.10.1.2'-- 값을 입력했다고 가정하면 SQL Query는 다음과 같이 완성될 것이다.


SELECT 신청인명, 접수번호 from USER_TABLE where 신청인명='test' and 접수번호='; exec master..xp_cmdshell 'ping 10.10.1.2'--


이 SQL Query는 SELECT Query와 xp_cmdshell Query를  SQL Query가 순차적으로 실행되게 되며, 마지막의 -- 문자는 이후의 모든 문자열을 주석 처리하여 문장을 완성시켜 준다.


(3) 취약성 판단


-검색어 필드 및 로그인ID, PASSWD 필드에 큰따옴표("), 작은따옴표('), 세미콜론(;) 등을 입력한 후, DB error가 일어나는지 확인하자.


-로그인 모듈 점검

MS SQL인 경우: ID 필드에 ['or 1=1 ;--], 비밀번호 필드에는 아무 값이나 입력한 후 로그인을 시도한다.

Oracle인 경우: ID 필드에 ['or 1=1 --], 비밀번호 필드에는 아무 값이나 입력한 후 로그인을 시도한다.


-기타

ID 필드에 ['or ''='], 비밀번호 필드에 ['or ''=']을 입력한 후 로그인을 시도한다.


※ 위 예제 이외에도 다양한 방법이 가능하기 때문에, 로그인 및 사용자 입력 값을 사용하는 소스에서 DB Query 생성 방식을 직접 점검해야 한다.


■ 보호 대책


(1) 일반 대책

-데이터베이스와 연동을 하는 스크립트의 모든 파라미터들을 점검하여 사용자의 입력 값이 SQL injection을 발생시키지 않도록 수정한다.


-사용자 입력이 SQL injection을 발생시키지 않도록 사용자 입력 시 특수문자(' " / \ ; : Space -- +등)가 포함되어 있는지 검사하여 허용되지 않은 문자열이나 문자가 포함된 경우에는 에러로 처리한다.


-SQL 서버의 에러 메시지를 사용자에게 보여주지 않도록 설정한다. 공격자는 리턴 되는 에러 메시지에 대한 분석을 통하여 공격에 성공할 수 있는 SQL Injection 스트링을 알아낼 수 있다. 따라서 SQL 서버의 에러 메시지를 외부에 제공하지 않도록 한다.


-웹 애플리케이션이 사용하는 데이터베이스 사용자의 권한을 제한한다. 가능하면 일반 사용자 권한으로는 모든 system stored procedures에 접근하지 못하도록 하여 웹 애플리케이션의 SQL Injection 취약점을 이용하여 데이터베이스 전체에 대한 제어권을 얻거나 데이터베이스를 운용중인 서버에 대한 접근이 불가능하도록 한다.


-php.ini 설정 변경

  : php.ini 설정 중 magic_quotes_gpc 값을 On으로 설정한다.


; Magic quotes

;

; Magic quotes for incoming GET/POST/Cookie data.

magic_quotes_gpc = On  ; Off에서 On으로 변경한다.

; Magic quotes for runtime-generated data, e.g. data from SQL, from exec(), etc.

magic_quotes_runtime = Off

; Use Sybase-style magic quotes (escape ' with '' instead of \').

magic_quotes_sybase = Off


■ 개발 언어별 대책

-사용자로부터 입력받은 변수로 SQL 쿼리 구문을 생성하는 CGI는 입력받은 변수를 체크하거나 변경하는 로직을 포함하고 있어야 한다.


-입력받은 변수와 데이터 베이스 필드의 데이터형을 일치 시켜야 하고, 사용 중인 SQL 구문을 변경시킬 수 있는 특수문자가 포함되어 있는지 체크해야 한다.


-검색 부분과 같이 클라이언트로부터 생성된 SQL 구문을 받는 부분이 있다면 이를 제거해야 한다.


□ ASP

-취약한 SQL Injection 예제

prodId = Request.QueryString("productId")

Set conn = server.createObject("ADODB.Connection")

Set rs = server.createObject("ADODB.Recordset")

query = "select prodName from products where id = " & prodId

conn.Open "Provider=SQLOLEDB; Data Source=(local);

Initial Catalog=productDB; User Id=dbid; Password="

rs.activeConnection = conn

rs.open query

If not rs.eof Then

response.write "제품명" & rs.fields("prodName").value

Else

response.write "제품이 없습니다"

End If


-안전한 SQL Injection 예제

prodId = Request.QueryString("productId")

prodId = replace(prodId, "'", "''")' 특수문자 제거

prodId = replace(prodId, ";", "")

set conn = server.createObject("ADODB.Connection")

set rs = server.createObject("ADODB.Recordset")

query = "select prodName from products where id = " & prodId

conn.Open "Provider=SQLOLEDB; Data Source=(local);

Initial Catalog=productDB; User Id=dbid; Password="

rs.activeConnection = conn

rs.open query

If not rs.eof Then

response.write "제품명" & rs.fields("prodName").value

Else

response.write "제품이 없습니다"

End If


□ PHP

-addslashes() 함수 사용

  : 사용자가 입력하는 값들($_GET, $_POST)을 모두 addslashes() 함수를 이용하여 처리하여 준다.

addslashes()

용도 : DB Query와 같이 인용된 부분앞에 역슬래쉬를 붙여서 반환한다. 해당 문자에는 작은 따옴표, 큰 따옴표, 역슬래쉬, NULL이 있다. SQL Injection 공격을 위해서 사용한다.

- 적용 가능한 PHP : PHP 3 이상


-취약한 SQL Injection 예제

$query = "SELECT id, password, username FROM user_table WHERE id='$id'";// 사용자로부터 입력받은 id 값을 사용자 table에서 조회

$result = OCIParse($conn, $query);

if (!OCIExecute($result))

echo "<META http-equiv=\"refresh\" content=\"0;URL=http://victim.com\">";// 메인 페이지로 redirect

OCIFetchInto($result, &$rows);

... 중략 ...


-안전한 SQL Injection 예제

$query = sprintf("SELECT id,password,username FROM user_table WHERE id='%s';",addslashes($id));

// id변수를 문자형으로 받고, id변수의 특수문자를 일반문자로 변환한다.

// @ 로 php 에러 메시지를 막는다.

$result = @OCIParse($conn, $query);

if (!@OCIExecute($result))

error("SQL 구문 에러");

exit;

@OCIFetchInto($result,&$rows);

... 중략 ...


□ JSP

-취약한 SQL Injection 예제

String sql="SELECT*FROM user_table"+"WHERE id=" + response.getParameter("id")

+ " AND password = " + response.getParameter("password");

Class.forName("org.gjt.mm.mysql.Driver");

conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);

stmt = conn.createStatement();

rs = stmt.executeQuery(query);

while(rs.next())


-안전한 SQL Injection 예제

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();

[길민권 기자(boannews@infothe.com)]

Posted by 엔시스