2009.09.14 17:21

최신 해킹 기법 분석 및 보안 대책 SQL Injection

해킹은 유명무명 사이트를 가리지 않고 진행되며 운영체제 역시 가리지 않는다. 문제는 그뿐이 아니다. 아마 리스트에 나타난 사이트를 운영하는 회사 중 대부분은 자신들이 해킹을 당했고, 지금도 계속 해킹을 당하고 있다는 사실조차 인지하지 못하고 있을 것이라는 점이다. 멀쩡한 외양간을 고치는 것은 시간과 비용의 낭비처럼 느껴질지 모르지만, 소를 잃는 것보다는 나은 일이다. 이제부터는 해커들이 그렇게 많은 사이트를 제 집 드나들 듯이 드나들며 유린하는 데 사용하는 해킹 기법과 그에 대한 보안 대책을 통해 우리가 관리하는 외양간을 더욱 튼튼하게 하는 법을 연구해보자.

그만큼 윈도우 운영체제가 외부에 많이 노출되어 있고 공격자들의 대상이 되기도 쉽다는 뜻이다. 물론, 이것은 보는 관점에 따라 달라질 수 있지만 공격대상의 관점에서만 본다면 매력 있는 것임은 분명하다. 악성코드의 관점에서 예를 들어 보자. 악성코드 확산을 효과적으로 막는 방법은 무엇일까? 많이 사용되고 있는 운영체제 또는 응용프로그램을 이용하는 것이 보다 효과적일 것이다. 이러한 이유로 유닉스 시스템의 악성코드보다는 윈도우 환경의 악성코드가 많이 발견되는 것이다.

파일 업로드

파일 업로드(File Upload) 공격은 공격자가 공격 프로그램을 해당 시스템에 업로드하여 공격하는 방법을 말한다. 파일 업로드는 공격이 쉬우면서도 영향력이나 파급 효과는 큰 공격 방법이다. 공격 방식은 공격자가 시스템 내부 명령을 실행할 수 있는 웹 프로그램(ASP, JSP, PHP)을 제작하여 자료실과 같이 파일을 업로드할 수 있는 곳에 공격용 프로그램을 업로드하는 것이다. 그리고 웹 브라우저를 이용해 공격용 프로그램에 접근하면 시스템 내부 명령을 실행시킬 수 있게 되는데, 이를 이용해 공격자는 리버스 텔넷(Reverse Telnet)과 같은 기법으로 자신의 컴퓨터로 피해 대상 시스템의 명령 창을 띄워 편하게 작업할 수도 있다. 쉽게 말해, 원격지에서 공격한 컴퓨터의 전권을 가지게 되는 것이다.
그렇다면 이러한 파일 업로드 공격에 어떻게 대응해야 할까? 가장 간단하고 효과적인 방법으로는 업로드할 때 파일 확장자 이름을 확인하는 것이다. 이때 asp나 jsp같이 업로드되는 확장자를 소문자만 체크하지 않도록 주의해야 한다. 시스템은 aSp나 jSp 같은 대소문자 혼합도 인식하기 때문에 모든 가능한 조합에 대해 필터링해야 한다. 반대로 특정 확장자 이름을 가진 파일만 업로드되도록 하는 것도 좋은 방법이다. 이때 또 한 가지 주의할 점은 필터링을 위해 자바스크립트 같은 클라이언트 스크립트 언어를 사용하지 말아야 한다는 점이다. 어느 정도 숙달된 해커라면 클라이언트 스크립트 언어쯤은 얼마든지 수정할 수 있기 때문에 asp나 jsp 같은 서버 쪽 스크립트 언어에서 필터링해야 한다.
필터링 이외에 파일이 업로드되는 디렉토리의 실행 권한을 없애는 방법이 있다. 이 경우에는 파일이 업로드되더라도 실행되지 않기 때문에 브라우저에 그대로 나타나거나 파일을 다운로드하게 된다.

디렉토리 탐색

디렉토리 탐색(Directory Traversal)은 웹 브라우저에서 확인 가능한 경로의 상위로 올라가서 특정 시스템 파일을 다운로드하는 공격 방법이다. 자료실에 올라간 파일을 다운로드할 때 전용 다운로드 프로그램이 파일을 가져오는데 이때 파일 이름을 필터링하지 않아서 생기는 취약점이다. 특정 파일을 다운로드할 때 다음과 같은 URL을 이용하여 다운로드한다고 하자.

http://www.stsc.co.kr/board/down.jsp?filename=saintsecurity.doc

공격자는 filename 변수에 해당하는 값을 다음과 같이 간단한 조작을 통해 상위 디렉토리로 거슬러 올라가 /etc/passwd 파일을 다운로드할 수 있다.

http://www.stscco.kr/board/down.jsp?filename=../../../../../../../ ../../../../etc/passwd

전용 파일 다운로드 프로그램을 이용할 때는 위의 예에서 보는 바와 같이 ‘..’ 문자열이나 ‘/’ 문자열에 대한 필터링이 없을 경우, 공격자는 상위로 올라가 특정 파일을 열어볼 수 있기 때문에 ‘..’와 ‘/’ 문자를 필터링해야 한다. 파일 업로드의 경우와 마찬가지로 자바스크립트와 같은 클라이언트 스크립트 언어로 필터링하면 공격자가 우회할 수 있기 때문에 반드시 jsp나 asp 등 서버 쪽 스크립트 언어에 필터링을 추가해야 한다.

디렉토리 리스팅

디렉토리 리스팅(Directory Listing)은 웹 브라우저에서 웹 서버의 특정 디렉토리를 열면 그 디렉토리에 있는 모든 파일과 디렉토리 목록이 나열되는 것을 말한다. 이것이 디렉토리 리스팅의 취약점이다. 물론 관리자가 어떤 목적을 위해서 웹 서버의 특정 디렉토리를 리스팅할 수 있도록 설정하기도 하지만, 어쨌든 공격자는 디렉토리 리스팅 취약점을 이용하여 웹 서버에 어떤 파일이 있는지 확인할 수 있고 추가적인 공격 취약점을 찾을 수 있다. 대부분의 웹 서버의 경우 해당 디렉토리 리스팅에 대한 여부를 가능 혹은 불가능하게 하는 옵션이 따로 준비되어 있다. 해당 설정 내용을 적절하게 변경하주면 디렉토리 리스팅을 이용한 공격은 통하지 않는다. 

인증 우회

인증 우회란 관리자 페이지나 인증이 필요한 페이지에 대한 인증을 처리하지 않고 인증을 우회하여 접속할 수 있는 취약점을 말한다. 이 취약점에 노출되면 일반 사용자나 로그인하지 않은 사용자가 관리자 페이지에 접근하여 관리자 권한을 획득한 뒤에 모든 기능을 자신이 원하는 대로 악용할 수 있게 된다. 이런 취약점은 간단하지만 의외로 웹 개발자가 자주 범하는 실수이다. 인증 우회는 아주 간단한 방법으로 공격이 이루어진다. 일반적으로 관리자로 로그인한 뒤 관리자가 이용하는 웹 페이지에 접속해야 하는데 로그인하지 않고 직접적으로 관리자만이 이용할 수 있는 웹 페이지에서 특정 작업을 수행할 수 있도록 만들기 때문이다. 예를 들면 www.stsc.co.kr/admin/login.asp를 통해 관리자로 로그인한 뒤 www.stsc.co.kr/admin/data.asp에 접근할 수 있어야 하는데, 관리자로 로그인하지 않고도 www. stsc.co.kr/admin/data.asp에 바로 접근하여 관리할 수 있는 경우를 말한다.
관리자 페이지나 인증이 필요한 페이지에 대해서는 관리자 로그인 세션에 대한 검사를 수행하는 과정을 넣어야만 이러한 공격의 피해를 막을 수 있다. 따지고 보면 웹 공격의 다수는 관리자의 부주의나 관리 패턴을 악용하는 단순한 방법이다. 이런 약점을 노출시키지 않으려면 관리자는 자신이 좀 더 불편하더라도 안전한 방법을 이용해 사이트나 파일을 관리해야 한다. 

SQL Injection 공격

SQL Injection 공격은 세상에 공개된 지 약 4년이 넘었지만 아직도 수많은 사이트가 이 공격에 취약한 묘한 해킹 방법이다. 이런 일이 가능한 것은 많은 개발자들이 이 부분을 간과한 채 웹 애플리케이션을 개발하고 있기 때문이다. 먼저 SQL Injection 공격의 패턴에 대해 알아본 뒤에 그 대응 방법을 함께 살펴보자

■ 기본 SQL Injection 공격 패턴
웹 애플리케이션에서 사용자에게서 SQL문을 입력받는 부분, 즉 데이터베이스와 연동되는 부분은 크게 로그인, 검색, 게시판으로 나눌 수 있다. 어느 사이트에서든 로그인을 하려면 아이디와 비밀번호를 넣어야 한다. 그리고 웹 애플리케이션 개발자는 정상적인 아이디와 비밀번호로 넣을 것을 기대하고 프로그래밍 한다. 그러나 모든 공격은 언제나 예상치 않은 곳에서 일어난다. 공격자는 아이디와 비밀번호를 정상적인 문자가 아닌 특정 SQL문을 넣어 공격한다. 이렇게 아이디나 비밀번호 부분에 엉뚱한 SQL문이 삽입되면 그것이 그대로 데이터베이스에 전송되어 공격자가 원하는 일이 일어난다.
SQL Injection 공격은 고난도 기술이 아니다. 물론 아주 어려운 SQL Injection 공격도 있지만 1분 만에 쉽게 배울 수 있는 SQL Injection 공격 방법도 있다. 그러면 SQL Injection 공격에 대응하기 위해서 무엇이 필요한지 살펴보자.
로그인 부분에 대한 SQL Injection 공격에 대한 이해를 돕기 위해서 로그인을 처리하는 간략한 웹 프로그래밍 코드를 살펴보자. 다음 코드는 로그인할 때 로그인 아이디와 비밀번호를 검사하여 사용자를 식별하는 ASP 코드의 한 부분이다.
일반 사용자가 웹에 접근하여 아이디와 비밀번호를 입력하면 위의 코드에 아이디와 비밀번호가 입력된다. 위의 코드는 사용자가 입력한 아이디를 strUser_id 변수에 저장하고 사용자가 입력한 비밀번호를 strPassword 변수에 넣는다. 그 뒤에 SELECT 문에서 사용자의 아이디와 비밀번호 입력에 대한 결과를 Query 변수에 저장한다. 그런 다음 GetQueryResult 함수를 이용해 Query 변수에 들어 있는 SQL문을 실행하고 그 결과를 strAuthCheck 변수에 넣는다. 쿼리 결과가 존재하지 않으면 strAuthCheck의 결과 값은 NULL이 되어 boolAuthenticated는 ‘거짓’이 되고 실행 결과 값이 있으면 boolAuthenticated는 ‘참’이 되어서 로그인 인증을 받을 수 있다.
이때 공격자가 아이디와 비밀번호에 ‘ or ‘’=’ 방식으로 입력하면 다음과 같은 결과가 나타난다.

<화면2> 자동화되어 있는 SQL Injection 공격 툴

<화면3> SQL Injection 공격 툴로 가입자 정보를 유츌한 화면

아이디: ‘ or ‘’=’
비밀번호: ‘ or ‘’=’

    ↓

SELECT user_id FROM member WHERE
user_id = ‘’ or ‘’ = ‘’ AND password = ‘’ or ‘’ = ‘’

이와 같은 쿼리문이 만들어지면서 조건문(Where문)은 항상 만족하고, strAuthCheck 값도 항상 ‘참’이 되기 때문에 공격자는 사용자 인증에 성공한다. 이처럼 위의 기법을 이용하면 아주 간단하게 로그인 창의 로그인을 우회하게 된다.
여기에서 설명한 SQL Injection 공격은 아주 기초적인 SQL Injection 공격 개념이라고 할 수 있는데 실제로 이와 같은 SQL Injection 공격을 자동화해놓은 툴들이 많이 있다. 이러한 툴을 이용하면 해당 공격 대상 서버의 시스템 명령까지 내릴 수 있으며 실제 데이터들의 조회와 수정도 가능하게 되어 심각한 문제를 야기할 수 있는 것이다.

■ SQL Injection 공격에 대한 대응 방법
SQL Injection에 대한 가장 훌륭한 해결책은 포괄적인 입력 검증을 수행하는 것이다. 모든 스크립트에 존재하는 모든 변수들을 점검하여 사용자의 입력 값이 SQL Injection을 발생하지 않도록 수정한다. 웹 애플리케이션 코드를 수정하여 사용자 입력이 SQL 문장으로 사용되지 않도록 한다. 모든 사용자 입력의 앞뒤에 따옴표를 붙이고, 사용자 입력에 존재하는 따옴표가 제거되도록 설정한다. 따옴표를 제거하는 것보다 더 확실한 방법은 사용자 입력에 따옴표가 존재하는 경우 이를 에러 처리하도록 하는 것이다. 만약 따옴표가 제거된 사용자 입력을 계속 처리하도록 허용한다면 이를 우회하는 공격에 언제나 노출되어 있는 셈이다.
따옴표에 대한 검증을 수행한 다음에는 사용자 입력으로 사용이 불가능한 스트링을 제거하고, 사용 가능한 문자집합에 포함되지 않은 모든 문자들을 제거하도록 설정한다. 이 경우에도 마찬가지로 허용되지 않은 문자열이나 허용되지 않은 문자가 포함된 경우를 에러로 처리하는 것이 더욱 안전하다.
현재 알려져 있는 공격 패턴을 기반으로 해서 사용자 입력으로 사용이 불가능한 스트링을 결정한다. 또한 새로운 공격 기술에 대비해서 사용자 입력으로 사용 가능한 최소의 문자집합을 결정한다. 사용이 허용된 문자들의 조합으로 공격 스트링을 만들 수 있기 때문에 이 두 가지 방법을 동시에 사용해야 한다. 최소 사용 가능 문자집합에는 가급적 숫자만을 포함하도록 하고 그것이 어렵다면 숫자와 문자만을 포함하도록 해야 한다. 만약 사용자 입력으로 기호문자나 구두문자 같은 문자들을 사용해야 한다면 꼭 필요한 최소의 문자만을 포함하고 허용된 문자를 HTML 문자로 변환해서 처리하도록 한다.
공격자는 리턴되는 에러 메시지에 대한 역공학 분석을 통하여 공격에 성공할 수 있는 SQL Injection 스트링을 알아낸다. 따라서 SQL 서버의 에러 메시지를 외부에 제공하지 않도록 한다. 보통 개발 과정에서 디버깅을 목적으로 에러가 리턴되도록 허용했다가 개발이 끝난 후 그 기능을 제거하는 것을 잊는 경우가 많다. 에러가 발생한 경우 에러 발생 사실을 보여주기보다 메인 페이지로 돌아가도록 하는 것이 좋다. 500 Internal Server Error Page 자체가 그 서버에 대해 SQL Injection 공격이 가능하다는 의미를 제공하는 것이다.
웹 애플리케이션이 사용하는 데이터베이스 유저의 권한을 제한시킨다. 가능하면 일반 유저 권한으로는 모든 system stored procedures에 접근하지 못하도록 한다. 이렇게 하며 웹 애플리케이션의 SQL Injection 취약점을 이용하여 데이터베이스 전체에 대한 제어권을 얻거나 데이터베이스를 운용 중인 서버에 대한 접근이 불가능하도록 한다. 이외에도 데이터베이스에 대한 보안 지침 문서를 참조하여 데이터베이스 서버의 보안 수준을 제고하도록 한다.

SQL Injection 공격 대응 방법

◆ 사용자 입력이 SQL Injection을 발생시키지 않도록 사용자 입력을 필터링한다.
◆ SQL 서버의 에러 메시지를 사용자에게 보여주지 않도록 설정한다.
◆ 웹 애플리케이션이 사용하는 데이터베이스 유저의 권한을 제한시킨다.
◆ 데이터베이스 서버에 대한 보안 설정을 수행한다.


크로스 사이트 스크립팅(XSS) 공격

버퍼 오버플로우는 공격기법의 이름에서도 어느 정도 유추할 수 있듯이 지정된 범위의 버퍼이상의 데이터를 기록할 때 발생된다. 현재 발생하고 있는 취약점 중에 많은 것들이 이 버퍼 오버플로우에 의해 일어나고 있다. 이것은 개발 시 지정된 범위 이상의 값으로 받아들이지 않도록 코딩을 하거나 안전한 함수 등을 사용하여 막을 수 있는 부분임에도 불구하고 여전히 그 피해가 끊이지 않는 대표적인 취약점 중 하나이다. 구글과 같은 검색엔진에서 ‘buffer overflow’로 검색해 보면 상당히 많은 자료를 찾아 볼 수 있다.
간단한 입력을 받는 다음의 코드를 살펴보자. array[30]으로 버퍼의 크기를 지정하였고 받은 내용을 출력하도록 프로그래밍되어 있다. 그런데 만약 사용자가 버퍼 크기 이상의 데이터를 입력하였다면 어떻게 될까? <화면 1>과 같은 화면이 나타날 것이다. * A는 16진수로 41이다.

기본적인 공격 기법 분석

공격자는 XSS 취약점이 존재하는 웹 사이트에 자신이 만든 악의적인 스크립트를 일반 사용자의 컴퓨터에 전달하여 실행시킬 수 있다. 이러한 공격으로 사용자 쿠키를 훔쳐서 해당 사용자 권한으로 로그인하거나 브라우저를 제어하는 것이다.
XSS 취약점은 다음과 같이 동적으로 웹 페이지를 생성하는 사이트에 주로 존재한다.

● 입력한 검색어를 다시 보여주는 검색엔진
● 입력한 스트링을 함께 보여주는 에러 페이지
● 입력한 값을 사용자에게 다시 돌려주는 Form
● 사용자에게 메시지 포스팅이 허용된 웹보드

XSS 취약점이 존재하는 사이트의 특징은 사용자의 입력을 검증하지 않고 그대로 동적으로 생성되는 웹 페이지에 포함해서 다시 보여준다는 점이다. XSS 공격은 <그림 3>과 같이 이루어진다. 공격자는 XSS 취약점이 존재하는 웹 페이지의 사용자 입력으로 ‘test’와 같이 정상적인 스트링을 입력하는 것이 아니라 <script>로 시작하는 악성 스크립트 코드를 입력한다. 그러면 웹 서버는 공격자가 입력한 악성 스크립트 코드가 포함된 웹 페이지를 생성해서 클라이언트에게 되돌려준다. 이 웹 페이지에 포함된 스크립트 코드는 클라이언트 측 브라우저에서 실행된다.
공격자는 웹 메일이나 게시판 등을 이용하여 리턴되는 웹 페이지를 공격 목표가 되는 일반 사용자에게 전달한다. 공격자는 웹 메일에 악성 스크립트 코드를 포함하여 전달하거나 게시판에 악성 스크립트 코드가 포함된 웹 페이지를 생성해서 클라이언트에게 되돌려준다. 이 웹 페이지에 포함된 스크립트 코드는 클라이언트 측 브라우저에서 실행된다.
공격자는 웹 메일이나 게시판 등을 이용하여 리턴되는 웹 페이지를 공격 목표가 되는 일반 사용자에게 전달한다. 공격자는 웹 메일에 악성 스크립트 코드를 포함하여 전달하거나 게시판에 악성 스크립트 코드가 포함된 글을 포스팅한 뒤에 그 글을 읽도록 한다. 일반 사용자가 공격자로부터 수신한 웹 메일을 여는 순간 혹은 공격자가 포스팅한 게시물을 읽는 순간이나 해당 웹 페이지에 읽는 순간 해당 웹 페이지에 포함된 스크립트 코드가 실행된다.
이러한 방법 외에도 악성 스크립트를 URL에 포함시켜서 전달하는 방법도 있다. 공격자는 URL의 변수 값으로 악성 스크립트를 넣은 링크를 공격 대상자에게 전달하여 그 링크를 클릭하도록 유도한다. 공격자는 이 링크를 공격 대상자에게 친숙한 내용의 HTML 메일에 포함시켜 전달하는데 메일은 공격 대상자가 반드시 그 링크를 클릭하도록 내용을 구성한다. 공격 대상자가 그 링크를 클릭함과 동시에 악성 스크립트가 포함된 웹 페이지를 수신하게 된다.

XSS 공격에 대한 대응 방법

XSS 취약점은 대부분 웹 애플리케이션 개발자가 사용자 입력을 받아들이는 부분에서 사용자 입력에 대해 어떠한 검증도 하지 않았기 때문에 일어난다. 그럼 웹 애플리케이션 개발자나 사이트 관리자는 어떤 방식으로 XSS 취약점에 대응해야 할까?

- 사용자를 식별하기 위해서 쿠키에 비밀번호와 같은 민감한 정보는 담지 않아야 한다.

- 스크립트 코드에 사용되는 특수문자에 대해 이해하고 정확한 필터링을 해야 한다. 가장 효과적인 방법은 사용자가 입력 가능한 문자(예를 들면 알파벳, 숫자, 몇몇의 특수문자)만을 정해놓고 그 문자열이 아니면 모두 필터링한다. 이 방법은 추가적인 XSS 취약점에 사용되는 특수문자를 사전에 예방할 수 있다는 장점이 있다.
<표 1> 같은 특수문자 필터링을 적용하기 위해서는 다음과 같은 함수를 이용할 수 있다.

정당화

의미

<
태그의 시작
>
태그의 끝
&
캐릭터 개체 또는 매개변수의 구별자
"
속성 값
'
속성 값
space

tab
속성 값, URL의 끝

URL의 끝
new line
URL의 끝
Non-ASCII
Iso-8859-1일 때, 2바이트 코드
%
HTTP escape sequence
" 안의!
Server Side Script
<script></script> 안의, (), {}, New Line
 

Function RemoveBad(InStr) {
InStr = InStr.replace(/\</g,“”);
InStr = InStr.replace(/\>/g,“”);
InStr = InStr.replace(/\”/g,“”);
InStr = InStr.replace(/\’/g,“”);
InStr = InStr.replace(/\%/g,“”);
InStr = InStr.replace(/\/g,“”);
InStr = InStr.replace(/\(/g,“”);
InStr = InStr.replace(/\)/g,“”);
InStr = InStr.replace(/\&/g,“”);
InStr = InStr.replace(/\+/g,“”);
Return InStr;
}

- 게시판에서 HTML 포맷의 입력은 사용할 수 없도록 설정한다. 최근에 만들어진 게시판들은 대부분 사용자들에게 다양한 효과를 제공하기 위해 HTML Tag 기능을 제공하고 있지만 꼭 필요한 경우가 아니라면 HTML을 사용할 수 없도록 제한해야 한다.

- 스크립트를 대체하여 무효화한다. javascript라고 들어오는 문자열은 무조건 x-javascript와 같이 대체하여 스크립트 실행을 무효화시키는 방법도 있다.


지금까지 살펴본 바와 같이 웹 해킹의 대부분은 웹 설정의 문제나 기본적으로 웹 환경에서 작동하는 웹 애플리케이션 제작 시 보안적인 요소를 고려하지 않고 단순히 목표로 하는 결과만 나올 수 있는 결과 중심의 프로그램 제작이 가져온 결과라고 할 수 있겠다. 더욱이 요즘처럼 웹이라는 환경에서 다루고 있는 각종 정보들이 직·간접적으로 악용되어 2차, 3차까지 이어지는 추가 해킹 사건까지 일어나고 있는 실정인데 웹 개발자들은 이제 단순히 결과만 보여주기 위한 프로그래밍보다는 그 내용 및 프로그램의 퀄리티까지 확보할 수 있는 단계가 될 수 있도록 주의해야 한다.
여기에서 다룬 해킹은 웹 사이트가 크고 웹 애플리케이션이 많을수록 더욱 쉽게 노출된다. 모든 애플리케이션에 여기에서 설명한 내용들을 적용하거나 코드를 수정하는 것이 너무 번거롭고 어렵다면 시중에 나와 있는 웹 애플리케이션 방화벽을 도입하는 것도 좋은 방안이 될 수 있을 것이다. 하지만 자신의 환경에 얼마나 잘 맞는지, 그리고 단순히 불필요한 기능들 때문에 전체 웹 시스템에 영향을 주는 솔루션을 도입을 하는 것은 벼룩 잡기 위해서 초가삼간을 모두 태운 격이 되므로 주의해야 한다.
가장 좋은 보안은 처음 애플리케이션을 개발하는 단계에서 보안에 신경을 쓰는 것이다. 약간만 신경 써서 개발한다면 수많은 개발자가 ‘각종 웹 해킹 보안 위협’에 골머리 썩으며 밤을 새는 일은 없을 것이다.
 
출처 : http://j79sw.tistory.com


Trackback 0 Comment 0