engineering/Network Eng.2006. 8. 7. 13:47
보안에 관심 있는 사람이라면 "버퍼 오버플로우"란 용어가 낯설지 않을 것이며, 그 중 적극적인 관리자라면 인터넷에 널려있는 다양한 버퍼 오버플로우 exploit(공격코드)을 다운로드 받아서 테스트도 해 봤을 것이다. 그 결과는 어떠했나? Exploit 코드가 지시하는 컴파일 옵션과 대상 서버가 적절했다면 손쉽게 root 권한을 획득했을 것이다. 물론 공격에 성공했다고 '버퍼 오버플로우"에 대해서 모든 것을 안다고 자신 있게 말할 수 있는 사람은 그리 많지 않을 것이다.

본 문서에서 "버퍼 오버플로우"의 A~Z까지를 설명할 필요는 없을 것이며(이미 뛰어난 문서들이 발표되어 있기 때문에) "버퍼 오버플로우"의 개념 이해를 목적으로 설명하겠다.

"버퍼 오버플로우"란?

말 그대로 버퍼를 넘치게(overflow) 하는 것을 의미하며, 풀어서 설명하면 메모리에 할당된 버퍼의 양을 초과하는 데이터를 입력하여 프로그램의 복귀 주소(return address)를 조작, 궁극적으로 해커가 원하는 코드를 실행하는 것이다. 여기에서 "버퍼(buffer)"란 프로그램 처리 과정에 필요한 데이터가 일시적으로 저장되는 공간으로 메모리의 스택(stack) 영역과 힙(heap) 영역이 여기에 속하며, "버퍼 오버플로우"가 이 두 가지 영역 중 어떤 것을 이용하느냐에 따라서 두 가지로 분류할 수 있다. 본 문서에서는 그 개념이 잘 알려져 있고 스택 기반의 버퍼 오버플로우에 초점을 맞춰서 설명하겠다. 이처럼 버퍼 오버플로우의 개념을 이해하기 위해서는 프로그래밍에 대한 기초 지식이 필요하며 이로 인하여 고급 해킹 기법으로 분류되고 있다.

"버퍼 오버플로우"의 역사

버퍼 오버플로우는 해킹 기법이 아닌 단순한 프로그램상의 문제로 처음 소개되었는데 1973년경 C언어의 데이터 무결성 문제로 그 개념이 처음 알려졌다.
이후 1988년 모리스웜(Morris Worm)이 fingerd 버퍼 오버플로우를 이용했다는 것이 알려지면서 이 문제의 심각성이 인식되기 시작했으며, 1997년에는 온라인 보안잡지로 유명한 Phrack(7권 49호)에 Aleph One이 "Smashing The Stack For Fun And Profit"란 문서를 게재하면서 보다 널리 알려지게 됐다. 이 문서는 다양한 "버퍼 오버플로우" 공격을 유행시키는 계기가 됐으며 현재까지 해커 지망생들의 필독 문서로 자리잡아 오고 있다. 이후 "버퍼 오버플로우"는 SANS(www.sans.org)

에서 매년 발표하는 TOP20 공격기법 가운데 상당수를 차지하면서 해커들의 꾸준한 사랑을 받아오고 있다.


"버퍼 오버플로우"는 어떻게 이루어지는가?

버퍼 오버플로우의 정확한 동작원리를 이해하기 위해서는 프로그램에 의해 데이터가 어떻게 저장되는가를 우선 이해해야 한다. 하나의 프로그램은 수많은 서브 루틴들로 구성되는데 이런 서브 루틴이 프로그램에 의해 호출될 때, 함수 변수와 서브 루틴의 복귀 주소(return address) 포인터를 스택(stack)이라는 논리적 데이터 구조에 저장하게 된다. 스택은 실행중인 프로그램이 필요로 하는 정보를 저장하는 메모리 영역이다. 서브 루틴이 종료될 때 운영체제는 그것을 호출한 프로그램에 제어권을 반환해야 하기 때문에, 복귀 포인터를 통해서 프로그램이 서브 루틴의 실행을 마치고 나서 되돌아갈 주소를 가리키게 된다.

버퍼는 할당된 메모리 공간의 높은 주소에서 낮은 주소로 채워지며, 스택 영역에 마지막으로 들어가 데이터가 제일 먼저 빠져 나오는 LIFO(Last in, First out) 특정을 가지고 있다. 이런 LIFO 특성에 의해 가장 먼저 들어가 것(복귀 포인터)이 스택에서 가장 나중에 제거된다는 것을 기억해야 한다. 서브 루틴이 실행을 마치면 가장 나중에 행해지는 것은 복귀 포인터를 스택에서 제거하여 서브 루틴을 호출한 함수로 반환하는 것인데, 만약 이 포인터가 사용되지 않는다면 서브 루틴이 실행을 마쳤을 때 프로그램은 더 이상 어디로 진행해야 할지를 알 수 없을 것이다.

포인터(pointer)는 메모리의 위치를 저장하는 변수이다. 프로그램 실행을 위한 목적으로 다른 코드로 이동할 때 어디에서 떠났는지를 기억하기 위해 포인터를 사용해야 하며, 만약 포인터를 사용하지 않는다면 서브 루틴의 실행이 끝나고 어디로 돌아와야 할지를 알 수 없을 것이다.

이제 스택을 조작하게 되면 어떤 일이 일어나는지를 살펴 보겠다. 프로그램이 변수의 할당된 공간에 저장될 데이터의 크기를 검사하지 않고 크기에 제한을 두지 않는다면, 변수 공간은 넘치게 될 것이다. 즉, 버퍼에 오버플로우가 발생하면 저장된 데이터는 인접한 변수 영역도 침범할 것이며 결국에는 포인터 영역까지 침범하게 될 것이다. 해커는 이러한 데이터의 길이와 내용을 적절히 조정함으로써 버퍼 오버플로우를 일으키고 운영체제의 스택을 붕괴시켜 특정 코드가 실행되도록 한다. 해커가 보낸 데이터는 대개의 경우 특정 시스템에서 실행될 수 있는 기계어 코드와 복귀 포인터에 저장될 새로운 주소로 구성되어 있으며, 복귀 포인터에 저장될 새로운 주소는 다시 메모리의 스택 영역을 가리켜서 프로그램이 서브 루틴에서 반환될 때 해커가 작성한 명령어를 실행하게 되는 것이다.

이때 고려해야 할 것은 공격 대상이 되는 프로그램이 무엇이든 간에 해커가 공격 코드는 프로그램이 실행되고 있는 권한으로 실행될 것이라는 점이다. 따라서 해커는 공격을 성공시켰을 경우에 시스템에 대한 최상위 권한을 얻기 위해, root 또는 administrator 권한으로 실행 중인 프로그램을 공격 대상으로 삼을 것이다.

이론상으로는 매우 직관적인 것 같지만 실제로 이 공격을 실행하는 것은 간단한 작업이 아니다. 하지만 이런 과정이 어떻게 이뤄지는지 제대로 이해하지 못 하는 스크립트 키디(script kiddie)

도 쉽게 공개된 공격 코드를 이용하여 버퍼 오버플로우 공격을 시도할 수 있으니 보안 관리자들에게 보다 많은 업무를 주는 상황이라고 할 수 있다.



"버퍼 오버플로우" 취약성이 많은 이유는?

많은 프로그램이 취약성을 갖는 중요한 이유는 오류 검사를 제대로 수행하지 않기 때문이다. 오류 검사를 수행하지 않는 큰 이유 중의 하나는 개발자가 근거 없는 특수한 가정을 하기 때문이며, 정상적인 환경에서 변수에 할당된 메모리의 크기가 충분하다고 과신하는 것도 문제가 된다. 취약한 프로그램일지라도 사용자들이 올바르게 사용하여 발표된 지 수 년이 지나도 아무런 문제 없이 동작해온 경우도 있다. 그러던 중 누군가가 갑자기 "만일 프로그램에 원래와 다른 종류의 정보를 넣으면 어떤 일이 생길까?", "프로그램에 기대되는 크기보다 더 많은 데이터를 넣으면 어떤 일이 일어날까?"하는 식의 궁금증을 갖게 되었고 오류 검사를 수행하지 않는 프로그램들은 그런 궁금증의 실험대상이 되어 해킹의 목표가 되고 있다.

이 글을 마무리하며

"버퍼 오버플로우" 공격은 취약한 프로그램을 대상으로 공격자가 원하는 코드를 실행시킬 수 있다는 측면에서 매우 위험하며, 그 결과로 얻는 피해 범위는 시스템을 중지시키는 것에서부터 관리자 권한을 얻는 것까지 다양하다.
보안 관리자는 "버퍼 오버플로우"가 어떻게 동작하는지 이해하고, 평상시에 벤더에서 제공하는 소프트웨어 관련 패치 적용, 최소 권한으로의 프로그램 실행, 불필요한 서비스 제거, 침입차단시스템을 통한 유해 트래픽 차단을 통해 공격 피해 가능성을 최소화해야 한다.
오늘 아무런 문제가 없었다 하더라고 내일 역시 안전할 것이라는 맹신을 버려야 한다. 지금 이 시간에도 지구 저편에서는 열심히 공격코드를 테스트하는 누군가가 있을 테니까….


내용출처 : [기타] (주)코코넛 시큐레터 6월호
(출처 : '[해킹 기법과 대응] ② 버퍼 오버플로우(Buffer overflow)' - 네이버 지식iN)
Posted by theYoungman
engineering/Network Eng.2006. 8. 7. 13:44
생활의 모든 부분에서 인터넷을 이용하고 있으며, 모든 것이 빠른 속도로 변해 가고 있다. 이런 점을 이용하여 인터넷을 통한 공격도 다양해져서 사용자들이 곤란에 빠지기도 한다. 그런데 이 기법이 나날이 고도로 지능화 되고, 순식간에 전 세계로 퍼질 수 있으므로, 각 기업 보안담당자들은 이런 현상에 대해 정확히 대비할 수 있는 지식을 갖추는데 좀 더 많은 노력을 기울여야 할 필요가 있다.

앞으로 약 6회에 걸쳐, 가장 일반적이며 이슈가 되고 있는 해킹 기법과 대응방법에 대해 알아보도록 하자.

1. 서비스 거부 공격(Denial of Service Attack)

차를 몰아본 경험이 없는 사람이라 하여도, 출퇴근길 뿐만 아니라 시도 때도 없이 막히는 서울의 교통체증은 누구나 다 아는 이야기이다. 이러한 체증의 원인 중에 하나가 "병목현상"이란 단어로 설명될 수 있는데, 이 현상은 쉴새 없이 수많은 정보들을 전세계로 이어 주고 있는 인터넷이란 교통구간에서도 동일하게 적용되고 있다.

최근 1.25 대란 사태에도 인터넷의 주소지 역할을 하는 DNS(Domain Name Server)가 처리할 수 있는 용량을 크게 넘는 요청이 쇄도하여 서비스가 중지됨으로써 하루동안 인터넷을 사용하지 못하는 대형사고가 발생하였던 경험을 가지고 있다. 다행이 업무시간을 피해 주말에 일어난 사고라 개개인들이 직접 피부로 느끼지는 못하였지만 일부 중요 서비스의 중단만으로도 사회 곳곳에서 많은 불편을 겪어야만 했다.

서비스 거부 공격이라 함은, 시스템의 정상적인 서비스를 방해할 목적으로 대량의 데이터를 보내 대상 네트워크나 시스템의 성능을 급격히 저하시켜 대상 시스템에서 제공하는 서비스들을 사용하지 못하게 하는 공격으로 해킹 수법중의 가장 일반적인 방법이다.

인터넷 사용자가 많지 않았던 초기의 서비스 거부 공격은 단일 시스템이나 서비스를 목표로 하는 공격자에 대한 피해자의 1:1 유형이 주류를 이루고 있었다. 그러나 최근에는 분산 서비스 거부공격이란 이름으로 N개의 불특정 시스템이 단일 네트워크를 대상으로 공격을 시도하는 N:1 유형이 주류를 이루고 있다.

이러한 공격은 사전에 공격을 받아 감염된 불특정 다수의 시스템으로부터 동시에 공격이 시도됨으로써 그 피해는 단일 시스템 뿐만 아니라 전체 네트워크까지 마비시킬 수 있는 파괴력을 가지고 있다. N:1 유형의 공격방법은 수작업으로는 많은 시간이 소요되기 때문에 주로 웜(Worm)

과 같은 자동화된 공격도구가 사용되는 경우가 많다. 따라서 공격도구의 특성을 제대로 파악하면 이에 대한 대응방법도 마련될 수 있기 때문에 이러한 연구활동도 전세계적으로 활발하게 진행되고 있다.

기술적인 대응방법뿐만 아니라 가장 중요한 것은 사전에 증후 발견이다. 이러한 공격은 대규모 네트워크를 이용하기 때문에 비정상적인 네트워크 흐름을 유발하여 초기에 이상징후를 탐지한다면 이에 대한 빠른 대응이 가능하게 된다.

이를 위하여 기본적인 보안솔루션을 구축하는 것은 물론, 적절한 관리와 운영이 병행해야 할 것이다. 또는 전세계적인 망을 가지고 있는 침해 사고 대응팀, 혹은 보안서비스 전문업체와 긴밀한 관계를 유지하여 기업보안 대책을 지속적으로 업데이트 시켜 주는 것이 무엇 보다 중요하다 하겠다.


내용출처 : [기타] (주)코코넛 시큐레터 6월호
(출처 : '[해킹 기법과 대응] ① 서비스 거부 공격' - 네이버 지식iN)
Posted by theYoungman