[IT Trend]/Security

[웹 파이어월 강좌] 웹 애플리케이션 공격의 이해

하늘을닮은호수M 2006. 5. 23. 15:52
반응형

출처 : http://www.ionthenet.co.kr/newspaper/view.php?idx=10901

[웹 파이어월 강좌] 웹 애플리케이션 공격의 이해

지난 연재에서는 웹 애플리케이션 공격의 주요 시나리오들을 살펴 봄으로써 웹 애플리케이션 공격을 통해서 어떤 일들이 일어날 수 있는지, 그리고 웹 애플리케이션 보안이 왜 중요한지를 고민해 보았다. 이번 회에는 웹 애플리케이션 공격에 자주 사용되는 실제 공격 기법들을 하나씩 알아보자.

이종일 | 파이오링크 연구소 아테나팀 과장

웹 애플리케이션에 대한 보안을 강화하기 위해서는 먼저 악의적인 공격자들이 어떤 식으로 공격해 오는지 알아야 한다. 이번에는 웹 애플리케이션 공격에 주로 사용되는 실제 공격 기법의 개념을 알아보고, 이같은 공격이 어떤 식으로 이뤄지는지 이해해 보자. 또한 이를 통해 웹 애플리케이션 공격과 기존 네트워크 수준의 공격의 차이점을 알아보자.

리퀘스트 플러딩
필자가 이번 연재를 위해서 글을 쓰고 있는 지금, 뉴스에서는 수험생들이 대입 원서를 접수한 후에 다른 수험생들이 원서 접수를 못하도록 대입 원서 접수 사이트를 ‘방법’해버린 사건에 대한 소식이 흘러나오고 있다.
‘방법’이라는 말은 한 인터넷 커뮤니티 사이트에서 만들어진 신조어로 해킹과 유사한 뜻으로 사용되고 있는데, 이번 공격에 사용된 소프트웨어는 ‘방법 2006’으로 특정 사이트에 1초에 4번씩 자동접속을 시도해, 서버에 과부하를 주는 방식을 사용한다. 이 ‘방법 2006’은 지난 2003년도 일본의 교과서 왜곡 사건으로 네티즌들이 일본 문부성 사이트를 공격할 때 처음 만들어진 방법 프로그램의 2006년도 업그레이드 판이다.
이 ‘방법’ 프로그램은 특정 사이트에서 반복해서 F5(새로 고침) 키를 눌러서 서버에 과부하를 주는 소위‘F5 공격’을 자동화한 것이다. 이 ‘F5 공격’은 별도의 툴도 필요없는 가장 간단한 DDoS(Distributed Denial of Service) 방법이지만, 굉장히 효과적인 공격 방법이기도 하다. 서비스를 제공하는 쪽에서는 정상 접속과 DDoS 공격 접속이 구분되지 않기 때문에, 막기가 아주 어렵기 때문이다.
그래도 ‘F5 공격’은 동일한 출발지 IP 주소에서 여러 개의 접속을 반복적으로 생성하기 때문에 일반적인 네트워크 보안 장비에서도 공격을 탐지하고 차단하는 것이 불가능한 것은 아니다. 동일 IP에서의 초당 접속 횟수를 제한하는 것으로 어느 정도 막을 수 있기 때문이다.
그런데, 실제로 웹 서버에 많은 부하를 주는 과정은 접속을 맺는 과정이 아니라, 웹 서버가 클라이언트의 요청(Request)을 처리하는 과정이다. (그림 1)과 같이, HTTP/1.0에서는 하나의 요청이 하나의 접속을 통해 이뤄졌기 때문에, 접속 레이트를 제어하는 것이 곧 요청 레이트를 제어하는 것이었다. 하지만 HTTP/1.1에서는 신규 접속처리에 대한 오버헤드를 제거하기 위해, 요청할 때마다 접속을 새로 하지 않고 기존 접속을 활용해 하나의 접속으로 여러 번의 요청을 수행할 수 있다.

이 HTTP/1.1에서의 접속 유지 기능을 악용해서 반복적인 요청을 웹서버에 보내 부하를 주는 공격 방법이 리퀘스트 플러딩(Request Flooding)이다.
리퀘스트 플러딩은 접속 레이트를 제어하더라도, 실제 웹 서버에 부하를 주는 요청 레이트는 제어할 수 없기 때문에, 초당 접속 횟수를 제어하는 일반적인 네트워크 보안 장비에서는 효과적으로 방어하기 힘들다.

강제 브라우징
강제 브라우징(Forceful Browsing)은 웹 서비스 제공자가 링크를 통해서 접속할 수 있도록 명시적으로 공개해 놓지 않은 제한된 웹 서버의 컨텐츠를, 기존에 참조된 링크를 통하지 않고 브라우저의 URL을 고의로 변경하거나 임의로 생성해 접근하는 행위를 가리킨다.
예를 들어, (그림 2)와 같은 구조의 웹 애플리케이션이 있다고 생각해 보자. 사용자는 /index.html을 통해 /login.html에 접근하고, /login.html의 폼에 데이터를 입력하면, /cgi-bin/login.cgi가 호출되며, 이 login.cgi는 /~private/ 아래에 있는 데이터를 사용해 인증을 수행한다.


일반적인 경우, /~private 디렉토리는 링크가 전혀 걸려있지 않기 때문에, 사용자들은 /_private 디렉토리의 존재 여부에 대해서 모르고, 그 아래에 있는 중요 파일에 대해서도 특별히 접근을 시도하지 않는다. 그런데, 이 웹 애플리케이션의 개발과정에서 최종 발표 직전의 소스코드를 login.py.bak라는 파일 이름으로 login.py와 같은 디렉토리에 복사해 놓았다. 그리고는 이 파일의 존재에 대해서 잊어버린 채 개발을 종료했다고 생각해 보자.
이후 악의적인 공격자는 login.py 프로그램을 보고 .bak를 붙여서 login.py.bak에 대한 접근을 시도했다. 이 login.py.bak에는 /~private 디렉토리 아래의 파일의 용도와 인증방법이 친절하게 기술돼 있었고, 공격자는 결국 /~private/passwd.dat 파일에 직접 접근해 패스워드 파일을 빼내갈 수도 있다.
이같은 예에서, login.py 뒤에 .bak를 붙여 직접 접근을 시도하는 행위나 링크가 연결돼 있지 않은 /~private/passwd.dat 파일을 직접 접근하려는 시도를 강제 브라우징이라고 한다. 강제 브라우징이 해킹의 범주에 속하는가에 관한 논란이 있긴 하지만, 이에 대한 부분은 논외로 하자. 실제로 강제 브라우징은 다양한 웹 애플리케이션 공격에 활용되고 있는데, 그 중에서 중요한 몇 가지 공격 유형을 나열하면 (표 1)과 같다.

SQL 인젝션
SQL 인젝션(SQL Injection)은 웹 애플리케이션의 입력에 SQL 쿼리나 명령 등을 삽입하는 공격 방식이다. 악의적인 공격자가 삽입한 SQL 쿼리는 웹 애플리케이션에서 데이터베이스로 전송되는 SQL 쿼리가 조작되도록해 공격자가 원하는 결과를 얻어낸다.
SQL 삽입 공격의 가장 간단한 예제는 지난 연재에서 설명한 바와 같이 SQL 삽입을 사용해 인증을 통과하는 방법이다. 로그인을 처리하는 프로그램의 일부가 다음과 같이 작성돼 있다고 가정하자.

Query = "SELECT User FROM UserTable WHERE User = '" & strUser & "' AND Passwd = '" & strPasswd & "'"
strAuthUser = DoQuery(Query)

이때 악의적인 사용자가 (그림 3)과 같이 입력을 넣으면, 웹 애플리케이션에서 데이터베이스로 가는 SQL 쿼리는 다음과 같이 구성되고, 실제 데이터베이스 테이블의 사용자명과 비밀번호가 무엇이든지 간에 OR ''=''라는 구문으로 인해 항상 참이 됨으로써 인증과정을 건너뛸 수 있다.

SELECT User From UserTable WHERE User = '' OR ''='' AND Passwd = '' OR ''=''

(그림 3)


SQL 삽입을 성공시키기 위해서는 프로그램의 코딩 방식을 예측해 상황에 따라서 삽입되는 SQL문을 변경함으로써, 문법에 맞는 SQL 쿼리가 데이터베이스에 전달돼야 한다. 만약 사용자의 입력을 SQL문으로 구성하는 코드가 다음과 같이 사용자의 입력을 숫자로 받아 WHERE 문에 넣는다면, 입력에 바로 SQL문을 삽입하는 것이 가능하다.

strSQL = "SELECT Name, Address FROM Students WHERE Sid = " & nStudentID

그리고 사용자의 입력을 SQL 키워드의 인자로 넣는 경우도 마찬가지다.

strSQL = "SELECT Name, Address FROM Students ORDER BY " & strSort

이같은 두 경우는 SQL문을 직접 넣어도 SQL문의 문법을 위반하지 않고 데이터베이스에 전달할 수 있기 때문에 이를 다이렉트 SQL 인젝션(Direct SQL Injection)이라고 부른다. 하지만 이런 경우는 상당히 드물고, 이같은 두 경우 이외는 모두 Quoted SQL 인젝션이다.
대부분의 SQL 쿼리를 조합하는 코드는 다음과 같이 작은따옴표(single quote)로 입력 값을 인용한다.

strSQL = "SELECT Name, Address FROM Students WHERE Sid = '" & strStudentID & "'"

이런 경우는 SQL 쿼리를 삽입하더라도 인용부호 때문에, 일반 문자열로 처리된다. 그래서 삽입하는 SQL 쿼리의 앞, 뒤에 작은따옴표를 붙여서 이를 피하는 것이다. 이는 앞의 인증 통과 예제를 참고하기 바란다. 또한, 삽입한 SQL 쿼리 이후에 나오는 다양한 SQL 조건을 데이터베이스가 무시하도록 만들기 위한 추가적인 기법을 사용한다. 예를 들어, 마이크로소프트의 SQL 서버가 ‘--’이후에 나오는 모든 것을 무시해버리는 점을 이용해, SQL 서버를 대상으로 한 SQL 삽입의 경우에는 삽입하는 SQL 쿼리의 뒤에 항상 ‘--’를 붙여준다.

크로스 사이트 스크립팅
크로스 사이트 스크립팅(Cross Site Scripting, 이하 XSS)은 피해자(victim)가 신뢰하는 사이트에 악의적인 공격자가 악성 스크립트를 삽입해, 신뢰받는 사이트와 같은 보안정책으로 스크립트가 실행되도록 하는 공격 방법이다. 엄밀히 말하면, XSS는 웹 서버나 웹 애플리케이션을 직접 공격하는 것은 아니지만, 웹 애플리케이션을 사용하는 다른 사용자를 공격하는 것이므로 넓은 의미에서 웹 애플리케이션 공격으로 볼 수 있다.
XSS도 지난 회에서 간단한 예제를 들어 설명한 적이 있는데, 공격자가 게시판에 (그림 4) 같이 스크립트를 포함시켜 포스팅한다.

(그림 4) 게시판을 이용한 스크립트 포스팅


만약 다른 사용자가 스크립트가 포함된 글을 읽으면, (그림 5)와 같은 스크립트가 실행된다.

(그림 5) 실행된 스크립트


XSS는 크게 stored XSS와 reflected XSS의 두 가지 유형으로 나눌 수 있다.
stored XSS는 앞에서 설명한 예제와 같이 웹 서버를 매개로 웹 서버에 저장된 스크립트가 피해자의 시스템에서 실행되도록 하는 것이다. (그림 6)과 같이 공격자는 악성 스크립트가 포함된 페이지를 웹 서버에 저장하고, 이후에 피해자가 그 페이지를 열람하는 순간 스크립트가 실행되도록 하는 것이다.

reflected XSS는 클라이언트에서 제공한 데이터가 서버의 응답 페이지에 바로 포함돼 돌려지는 것을 악용하는 공격 방법이다. 사용자의 입력에 대해 따옴표와 같은 인용처리를 하지 않고 그대로 페이지에 포함시키는 웹 애플리케이션의 경우, 사용자의 입력에 스크립트가 포함돼 있으면, 그 스크립트가 동적으로 생성되는 페이지에 포함돼 클라이언트에서 실행된다.
예를 들어, 검색 결과를 표시해주는 웹 애플리케이션이 있는데, 이 웹 애플리케이션은 검색 결과 페이지에 사용자가 검색한 키워드를 표시해주도록 되어 있다고 하자. 이때 다음과 같은 요청을 서버로 보내본다.

http://somesearch.com/search?keyword=

이 입력을 받은 웹 서버는 다음과 같은 HTML을 돌려주고, 이 HTML 속의 스크립트가 실행된다.



키워드 :
검색 결과

검색 결과가 없습니다.

reflected XSS는 주로 링크를 클릭하도록 유도함으로써 이루어지는데, 링크에 스크립트가 포함되도록 하는 방식이다. (그림 7)과 같이 공격자는 XSS 취약점이 존재하는 웹 서버의 링크에 악성 스크립트를 포함시킨 링크를 만들고, 악성 스크립트를 실행하고자 하는 피해자에게 클릭을 유도하는 전자우편을 보낸다. 피해자가 그 링크를 클릭하면, XSS 취약점이 존재하는 웹 서버로 요청을 보내고, 취약한 웹 서버는 클라이언트가 보내온 입력을 동적 페이지에 포함해 피해자에게 보낸다. 악성 스크립트가 포함된 동적 페이지를 받은 피해자의 브라우저는 페이지에 포함된 스크립트를 웹 서버에서 보내왔기 때문에, 그대로 실행하게 된다.


보통 XSS에 이용되는 취약한 웹 서버들은 유명한 웹 사이트들인 경우가 많기 때문에, 피해자들은 링크를 클릭하거나 게시판의 글을 읽을 때도 특별한 주의를 기울이지 않게 되고, 쉽게 XSS 공격을 당한다.
웹 애플리케이션의 입장에서는 XSS 공격에 이용당해도 웹 애플리케이션 자체의 보안이 파괴되는 것은 아니지만, 웹 애플리케이션이 운영되는 사이트의 신뢰도에는 심각한 타격을 받는다.

버퍼 오버플로우 공격
버퍼 오버플로우 공격(Buffer Overflow Attack)은 웹 애플리케이션 공격에만 사용되는 공격 방법은 아니다. 버퍼 오버플로우 공격은 프로그램 상의 입력에 사용하기 위해 할당된 버퍼보다 큰 데이터가 입력돼 버퍼의 경계를 넘어서서 데이터가 저장되는 버퍼 오버플로우를 고의로 일으키는 공격 방법이다.
이 버퍼 오버플로우는 프로그램 상의 메모리의 다양한 영역에서 발생할 수 있지만, 흔히 사용되는 스택(Stack) 오버플로우에 대해서 살펴보자.
프로그램의 실행 중에 사용되는 스택은 함수의 인자, 리턴 포인터, 지역 변수(local variable) 등이 저장된다. 함수의 인자는 함수를 호출할 때, 전달되는 데이터이고, 리턴 포인터는 함수의 실행이 끝났을 때, 다음으로 실행할 프로그램의 위치다. 그리고 지역 변수는 함수 내부에서 사용하는 변수를 저장하는 메모리다. 예를 들어, 다음과 같은 C 코드가 있다.

void function(int a, int b, int c)
{
char buffer1[5];
char buffer2[10];
}

void main()
{
function(1,2,3);
}

이 프로그램의 function 함수가 실행될 때의 메모리는 (그림 8)과 같이 구성된다.

함수를 호출할 때 넘겨주는 인자를 c, b, a 순서대로 스택에 저장하고, 함수를 호출했던 main() 함수로 돌아갈 포인터 RET를 저장한다. 그리고 function() 함수가 자체적으로 사용하는 지역변수 buffer1, buffer2가 순서대로 스택에 할당된다.
스택의 메모리가 (그림 8)과 같이 구성돼 있을 때, buffer1이 할당된 크기인 5보다 큰 입력을 buffer1에 strcpy() 등과 같은 함수를 사용해서 복사하면, (그림 9)와 같이 함수의 실행 후에 돌아갈 리턴 포인터인 RET에 저장된 값을 잘못 덮어쓰게 됨으로써 프로그램 실행 오류가 발생한다. 리눅스를 사용하는 경우라면, ‘Segmentation Fault’라는 오류 메시지가 표시된다.

스택에서의 버퍼 오버플로우를 활용하는 공격은 이 덮어쓰는 리턴 포인터를 조작하는 방식으로 이뤄진다. 공격자가 실행하고자 하는 코드를 쉘코드(shellcode)로 변환해 입력에 포함시키고, 스택의 리턴 포인터인 RET가 그 쉘코드를 가리키도록 조작해서 공격자가 원하는 코드를 실행시킨다.

웹 애플리케이션의 경우에 폼을 통해서 클라이언트로부터 받는 입력에 대해서 경계값 검사(boundary check)를 수행하지 않는다면, (그림 10)과 같이 쉘코드를 포함한 조작된 입력을 통해 공격자가 원하는 임의의 코드를 실행할 수 있다.

쿠키 조작
HTTP 쿠키(cookie)는 웹 서버에 의해 브라우저로 전송되고, 브라우저가 그 웹 서버로 접속할 때마다 재전송하는 정보다. HTTP 쿠키는 사용자 인증, 사용자 추적, 그리고 사용자 기반 정보의 유지를 위해 사용된다.
쿠키는 클라이언트에 저장되는데, 이 쿠키는 변경되지 않고 서버로 전달된다고 가정된다. (그림 11)과 같이 서버가 응답(Response)의 Set-Cookie 헤더를 통해 user=shocker라는 정보를 클라이언트로 전달하면, 클라이언트는 서버로 접속할 때마다 요청(Request)의 쿠키 헤더를 통해서 user-shocker 정보를 서버로 전달한다.


그런데, 만약 악의적인 공격자가 서버로 전송되는 쿠키를 변조하면, 쿠키 값을 신뢰하는 웹 애플리케이션은 공격자의 의도대로 동작한다. 공격자가 쿠키의 내용을 변조해 웹 애플리케이션을 공격하는 것을 쿠키 조작(Cookie Poisoning)이라고 부른다.

장바구니 기능을 제공하는 쇼핑몰 사이트를 예로 들어보자. 이 쇼핑몰 사이트의 웹 애플리케이션은 데이터베이스 접근 횟수를 줄이기 위해 장바구니에 저장된 제품의 항목과 가격을 쿠키에 저장하고, 결제시에 클라이언트에서 보내오는 제품 정보를 기반으로 결제하도록 구현돼 있다.
이 쇼핑몰을 사용하는 사용자가 CookieSpy나 웹 프록시와 같이 쿠키를 모니터링할 수 있는 툴을 사용하고 있다면, 이같은 웹 애플리케이션의 동작을 눈치채고, 쿠키를 수정해서 싼 값에 쇼핑몰의 제품을 구매하려고 시도할 것이다.
또 다른 예로, 쿠키를 사용해서 세션 관리를 하는 웹 애플리케이션의 경우 만약 네트워크 스니핑과 같은 도청 기법을 통해 다른 사용자의 세션 쿠키 정보를 알아낼 수 있다면, 악의적인 공격자는 자신의 쿠키를 수정해 다른 사용자의 세션 ID를 사용할 수 있다. 세션 ID를 통해 인증된 사용자를 구분하는 웹 애플리케이션에서는 훔친 쿠키 정보를 통해 다른 사용자의 신분으로 손쉽게 위조할 수 있다. 이같은 방식으로 세션을 가로채는 것을 쿠키 조작을 통한 세션 가로채기(Session Hijacking)라고 부른다.

반응형