2024-04-19 14:55 (금)
아파치 웹서버 무력화시킬 심각한 DoS 결함 발견
상태바
아파치 웹서버 무력화시킬 심각한 DoS 결함 발견
  • 홍석범
  • 승인 2011.08.26 14:08
이 기사를 공유합니다

간단한 HTTP 요청만으로 쉽게 서버 다운시킬 수 있는 심각한 보안결함 발견
가장 대중적으로 사용되고 있는 웹서버인 Aapche에서 간단한 HTTP 요청만으로도 서버의 CPU와 Memory를 가득 채워 간단히 서비스를 마비시킬 수 있는 매우 심각한 취약성이 발견되어 관리자들의 주의가 요구된다.
8월 20일에 공개된 이 공격 코드 및 취약성은 Range응답이 가능하면서, mod_deflate 및 mod_gzip이 enable된 시스템에 해당하는데 이는 기본 설정이므로 1.3.x 뿐만 아니라 2.0.x, 2.2.x등 현존하는 모든 Apache 서버가 취약한 것으로 알려져 있다.

공격의 원리는 다음과 같다.
Range 요청을 보낼 때 공격자가 많은 범위의 서로 다른 Request를 보내면, 서버에서는 이 각각의 요청에 대해 gzip의 "Accept-Encoding" 헤더와 함께 각각 압축을 시도하게 되는데, 비정상적인 많은 요청을 처리하는 과정에서 많은 CPU와 메모리를 소모하게 되고 결국 무한루프에 빠진 것처럼 시스템을 불안하게 만드는 것이다. 먼저 공격방법과 그때의 상황을 살펴보도록 하자.
공격툴은 이미 인터넷에 공개되어 있으며 간단한 perl 스크립트로서 아래와 같다.
 
# ./killapache.pl
Apache Remote Denial of Service (memory exhaustion)
by Kingcope
usage: perl killapache.pl <host> [numforks]
example: perl killapache.pl www.example.com 50
 
만약, 취약하지 않은 시스템이라면 아래와 같이 보이게 된다.

# ./ killapache.pl  domain.com
Host does not seem vulnerable
 
공격시에 보이는 패킷은 아래와 같다.
 
# 클라이언트의 요청
HEAD / HTTP/1.1.
Host: www.example.com.
Range:bytes=0-.
Accept-Encoding: gzip.
Connection: close.
 
# 서버의 응답 .
HTTP/1.1 206 Partial Content.
Date: Fri, 26 Aug 2011 04:02:49 GMT.
Server: Apache.
Last-Modified: Thu, 06 May 2010 12:16:28 GMT.
ETag: "14ec78-3f-485ebe97dff00".
Accept-Ranges: bytes.
Content-Length: 196660.
Connection: close.
Content-Type: multipart/byteranges; boundary=4ab609e5f37a56e23..
 
# 클라이언트의 요청
HEAD / HTTP/1.1.
Host: www.example.com.
Range:bytes=0-,5-0,5-1,5-2,5-3,5-4,5-5,5-6,5-7,5-8,5-9,5-10,5-11,5-12,5-13,5-14,5-15,5-16,5-17,5-18,5-19,5-20,5-21,5-22,5-23,5-24,5-25,5-26,5-27,5-28,5-29,5-30,5-31,5-32,5-33,5-34,5-35,5-36,5-37,5-38,5-39,5-40,5-41,5-42,5-43,5-44,5-45,5-46,5-47,5-48,5-49,5-50,5-51      
  

[그림] 공격 발생 후 1-2초 후에 즉시 위와 같이 많은 CPU/Memory를 소모하고 있는 것을 알게 된다.
 
기본적으로 Range는 첫번째 필드가 두번째 필드보다 같거나 작은 숫자이어야 하는데, 위에서 보듯이, Range의 5개 필드는 이 법칙을 위반하였으며 요청했던 Range를 중복해서 요청하고 있는 것을 알 수 있다.
 
공격이 발생할 때의 access_log 를 보면, 206으로 응답하며 마치 GET Flooding 공격을 받을때처럼 동일한 URL에 대한 HEAD 또는 GET 요청이 지속적으로 발생하게 되는 것을 알 수 있다. 따라서, L7탐지가 가능한 DDoS 차단 장비가 있다면 경우에 따라 차단이 가능하다.

192.168.10.34- - [26/Aug/2011:12:14:52 +0900] "HEAD / HTTP/1.1" 206 - "-" "-"
192.168.10.34- - [26/Aug/2011:12:14:52 +0900] "HEAD / HTTP/1.1" 206 - "-" "-"
192.168.10.34- - [26/Aug/2011:12:14:52 +0900] "HEAD / HTTP/1.1" 206 - "-" "-"
192.168.10.34- - [26/Aug/2011:12:14:52 +0900] "HEAD / HTTP/1.1" 206 - "-" "-"
192.168.10.34- - [26/Aug/2011:12:14:52 +0900] "HEAD / HTTP/1.1" 206 - "-" "-"
192.168.10.34- - [26/Aug/2011:12:14:52 +0900] "HEAD / HTTP/1.1" 206 - "-" "-"
192.168.10.34- - [26/Aug/2011:12:14:52 +0900] "HEAD / HTTP/1.1" 206 - "-" "-"
192.168.10.34- - [26/Aug/2011:12:14:52 +0900] "HEAD / HTTP/1.1" 206 - "-" "-"
192.168.10.34- - [26/Aug/2011:12:14:52 +0900] "HEAD / HTTP/1.1" 206 - "-" "-"
192.168.10.34- - [26/Aug/2011:12:14:52 +0900] "HEAD / HTTP/1.1" 206 - "-" "-"
 
그렇다면, 정상적인 경우 이 Range 요청은 어떠한 경우에 사용되는가? 이는 주로 대용량의 파일을 다운로드 하거나, 이어받기 등 파일의 일부만을 다운로드하기를 원하거나 또는 p2p 등에서 파일의 일부만을 특정 서버에서 받고자 할 때 사용된다. 따라서, Range 자체는 정상적인 요청이므로 차단해서 는 안 된다. 
 
그렇다면 어떠한 대응방법이 가능할 것인가?
8월 30일자로 2.2.X 버전에 대한 패치 버전이 발표되었다.(http://www.apache.org/dist/httpd/Announcement2.2.html) 조만간 RPM등으로도 패치가 나올 것으로 보이지만, 서비스중인 서버라면 패치가 쉽지 않을 것이다. 따라서 WorkAround로 아래와 같이 설정하는 것이 권장된다.
 
  1. httpd.conf 에서 LoadModule deflate_module modules/mod_deflate.so 주석처리하여 비활성화후 apache를 재실행한다.
     
  2. httpd.conf 에서 아래 부분을 추가 후 apache를 재실행한다.
    BrowserMatch .* no-gzip
 위의 두 가지 설정은 기능상 같은 의미라고 할 수 있는데, deflate 모듈은 클라이언트에서 응답하기 전에 압축을 하여 속도를 개선하고 응답 사이즈를 줄이는 기능으로서 이를 disable하는 것을 의미한다. 일반적인 서비스 제공시 큰 영향은 없으므로 권장되는 방법이다.
mod_deflate에 대해서는 http://httpd.apache.org/docs/2.0/mod/mod_deflate.html 를 참고하기 바란다.
 
위와 같이 설정한 후, 서버에서는 206으로 응답은 하지만, 서버의 부하가 상승하는 것은 어느정도 피할 수 있다. 
이외 주의할 점 및 추가적으로 취할 수 있는 방법은 다음과 같다.
 
1) 내부 시스템이라면 ACL로 접근제한 설정을 하는 것이다.
설사 취약한 apache버전이라 하더라도 ACL을 먼저 체크하므로 만약 IP 접근 제어가 되어 있다면 200 이나 206으로 응답하지 않고 403 에러가 나게 된다.  따라서, 외부에 오픈할 필요가 없는 서버라면, .htaccess등을 활용하여 IP 접근 제어를 하는 것이 권장된다.
 
2) RequestHeader unset Range 를 추가하여 Range 를 disable할 수 있지만, 이러한 경우 앞에서 언급한대로 정상적인 range request 를 하는 video 스트리밍이나 pdf등의 다운로드가 작동하지 않게 되므로 권장하지 않는다.
 
3) 통상적으로 HEAD는 검색엔진 로봇이 문서의 변경 여부를 체크하거나 모니터링등외에는 잘 사용되지 않으므로 HEAD 메소드를 차단하는 방법을 생각할 수 있다. 그러나 공개된 공격코드는 HEAD로 요청하지만, GET으로 변경해도 동일한 효과를 낼 수 있으므로 사실상 의미가 없다고 할 수 있다.
 
4)통상적으로 Range 요청시 필드가 5개 이상은 넘지 않는다. 따라서 modsecurity 또는 웹 방화벽을 사용한다면 한번의 HTTP 요청에 많은 range 요청이 들어올 경우 차단하도록 설정할 수 있다. 또는 아래와 같이 설정 가능하다. 이 방법 역시 가장 일반적으로 권장되는 방법중 하나라고 할 수 있다.

# 2.X의 경우
SetEnvIf Range (,.*?){5,} bad-range=1
RequestHeader unset Range env=bad-range

# 1.3.X의 경우 
RewriteEngine on
RewriteCond %{HTTP:range} !(^bytes=[^,]+(,[^,]+){0,4}$|^$)
RewriteRule .* - [F]
5)HEAD 메소드에서는 기본적으로 range 요청을 할 필요가 없다.
따라서 큰 의미는 없지만, HEAD이면서 Range 요청이 있으면 차단하도록 설정할 수도 있다.
 
6) 마지막으로, 일반적으로 HTTP 요청자체는 패킷 크기가 크지 않음에 반해 공격패킷을 보면 사이즈가 매우 큰 것을 알 수 있는데, 이의 원리를 이용하여 httpd.conf 에 LimitRequestFieldSize 200 와 같이 추가하여 차단할 수 있는 방법도 있다. 이때는 아래와 같이 400 에러로 출력하게 되고
 error_log 에는 [Fri Aug 26 12:27:31 2011] [error] [client 192.168.10.34] request failed: error reading the headers 와 같이 남게 된다.

HTTP/1.1 400 Bad Request.
Date: Fri, 26 Aug 2011 03:27:21 GMT.
Server: Apache.
Connection: close.
Content-Type: text/html; charset=iso-8859-1.
 
그러나, 쿠키등의 정보가 길면 패킷 사이즈가 커지는 경우도 있으므로 오탐 가능성이 있으므로 적용시에는  주의하여야 한다.

관련하여 아래의 URL을 참고하기 바란다. 

http://seclists.org/fulldisclosure/2011/Aug/175
http://marc.info/?l=apache-httpd-dev&m=131418828705324&w=2
http://www.apache.org/dist/httpd/Announcement2.2.html 

[글. 씨디네트웍스 홍석범 , antihong@gmail.com]

■ 보안 사건사고 제보 하기

▷ 이메일 : mkgil@dailysecu.com

▷ 제보 내용 : 보안 관련 어떤 내용이든 제보를 기다립니다!

▷ 광고문의 : jywoo@dailysecu.com

★정보보안 대표 미디어 데일리시큐 / Dailysecu, Korea's leading security media!★