본문 바로가기

Network

[Tool][DoS] HTTP POST DoS, RUDY (R-U-Dead-Yet version 2.2 )

과거, TCP기반(Layer4)이 주를 이루었던 DoS공격들은 다행히도 현재 장비에서 처리가 가능하다. 그리고  HTTP GET DoS 툴로 잘 알려져 있는 Slowloris 는 완전한 헤더정보를 보내지 않음으로써 서버는 헤더정보가 올 때까지 지연되어, 커넥션수가 늘어남에 따라 DoS가 발생하게 되는 공격이다. 이 공격은 헤더의 끝 문자가 \r\n으로 오는것으로 탐지 할 수 있었다.

이번에 소개할 DoS 공격기법은 HTTP POST DoS이다. 특정한 패턴이 존재하지 않고, Layer7 에 대한 DoS는 탐지기법자체도 장비에 영향을 줄 수 있어 대응이 어렵다. 하지만 프로그래밍된 요청에서 나오는 특이점과 몇 가지 대응방안을 생각해 볼 수 있다.

 RUDY 는 FORM을 이용한 HTTP Post를 전송하는 웹 페이지에 대해서 DoS 공격을 하는 툴이다. Content-Length를 매우 크게 설정하여 서버의 지연을 유발하는 공격기법이다. 서버는 클라이언트의 HTTP Header Content-Length를 보고 그 길이만큼의 Content가 올 때까지 대기하고 있다. 이 점을 이용하여 초기에 길이를 크게 설정해놓고, Content는 일정한 시간 간격으로 한 문자씩 전송한다. 결국, 서버는 한 세션당 [Content-Length * Interval Seconds] 만큼의 지연시간이 발생한다.


 
python 으로 구현되어있는 이 툴은 두 가지 방법으로 실행시킬 수 있다.

1. argument URL를 입력하여 실행 

python.exe r-u-dead-yet-v2.2.py http://domain/post_test.html


입력된 URL 페이지의 요소를 검사하여 Form이 존재하는 경우 각 설정 값을 입력 받는다. 하지만, form의 형태가 미리 정해져 있어 공격 대상 페이지에 설정되어 있는 input type name 그리고 form action도 수정해주어야 제대로 사용할 수 있다

  


소스를 분석해보면 다음과 같이 동작한다. 일단, 페이지 내에 Form 요소가 있는지 찾고, form 내에서 action으로부터 공격대상이 되는 url을 추출한다. 하지만 만약 이것이 절대주소가 아닐 경우 호출한 부모 URL action value 를 붙이는 형태가 되어 오류가 발생한다.


그리고 method post인지 찾는다. post인 경우 각 파라미터에서 정보를 추출하는데, type이 지정되어야 있어야 하고, 파라미터의 이름은 id, name 두가지 밖에 없다.


URL
을 인자로 입력하는 것은 소스를 직접 구미에 맞게 수정해야 편리하게 사용할 수 있다.

 


2. 파일에 환경변수로 지정하여 실행

python.exe r-u-dead-yet-v2.2.py

 
같은 폴더 내에 rudeadyet.conf 파일로 설정정보를 가져와서 실행한다.
 


1의 방법처럼 URL뿐만 아니라 커넥션수, 파라미터, 프록시를 파일을 통해 설정 할 수 있다. 공격자는 파라미터 정보를 미리 알고 있어야 한다.

 







 위의 2가지 방법으로 실행하게 되면 다음과 같이 동작한다.
 

1.     일단 공격대상 URL을 호출하여 설정 되어있는 쿠키정보가 있다면 이를 반영하여 헤더를 재 구성한다.

2.     헤더의 Content-Length를 크게 설정하여 POST 방식의 헤더를 구성한다.

3.     설정되니 Connection수만큼 Client를 생성하여 호출한다.

4.     Client 10초에 한번씩 하나의 문자를 전송하며 Server의 대기 시간을 지연시킨다.



다음과 같이 headers는 정의 되어있다. 여기서 주목해야 할 부분은 Content-Length 이다. 서버는 클라이언트와 TCP세션을 확립한 후, Content-Length의 길이만큼 Content가 모두 도착할 때까지 기다린다.


그리고 다음과 같이 HTTP를 호출하는 부분을 살펴보면, “A”문자를 10초마다 한번씩 전송하는 것을 볼 수 있다. 그렇기 때문에 이 하나의 세션은 (Content의 길이 x 10) 만큼의 지연을 유발한다. 



# 탐지 방법

1. GET 요청 제한

 

 이 툴의 특성상 POST 공격 이전에 쿠키정보를 셋팅하기 위해서 공격대상 URL을 한번 호출하는 부분이 있다. User-Agent “Python-urllib/2.6” 이런형태로 되어 있으므로 여기에 주목하여 시그니처를 작성할 수 있다. 만약 GET은 이용하지 않는 웹 페이지라면, 각 페이지의 GET요청을 막는 시그니처를 생성할 수 있다.
 

 alert tcp any 1024: -> any $HTTP_PORTS (msg:"wrong_request"; content:"GET /"; nocase; offset:0; depth:5; nocase; content:"|0d0a|User-Agent|3a| Python-urllib/“; sid:1; rev:0;)





 



2. Flowbits, Threshold, PCRE

 POST 요청은 정상적인 것과 구분할만한 것이 없다. 이것은 웹서버 설정에 Timeout을 짧게 지정한다거나 Content-length에 제한을 주어 공격에 제한을 줄 수 있다. 하지만 룰로 해결해야 한다면 다음과 같이 두가지 방법을 생각해 볼 수있다.

 

- POST요청에 관한 지속적인 “A” 문자 스트림 : flowbits, threshold

 

 POST 요청에 content:”A” flowbits로 잡은 다음 Threshord로 처리 할 수 있을 것이다.

 

alert tcp any 1024: -> any $HTTP_PORTS (msg:"dos_post_attack "; content:"POST /"; nocase; offset:0; depth:6; nocase; flowbits:set,dos_post; sid:12345; rev:0;)

 

alert tcp any 1024: -> any $HTTP_PORTS (msg:"dos_post_attack_sub"; content:"A"; offset:0; depth:1; flowbits:isset,dos_post; threshold:type both,track by_src,count 100, seconds 10; sid:123456; rev:0;)

 

 



- content-length 제한 : pcre

 

POST요청 이후 Content-Length의 길이를 3자리까지 제한한다면, 다음과 같이 pcre를 작성하여 탐지 할 수 있다.

 

alert tcp any 1024: -> any $HTTP_PORTS (msg:"dos_post_attack_limit_content_length";  content:"POST /"; nocase; offset:0; depth:6; content:"Content-Length: "; nocase; pcre:"/[0-9]{4,}/"; sid:1234567; rev:0;)

 

# 웹서버 설정
 

 1. Timeout 설정


 
아파치인 경우 다음과 같이 Timeout 5초 이내로 짧게 설정해주어 서버 지연시간을 줄여준다

 


 Apache Timeout으로 서버 지연방지



2. Content-length 길이 제한

 

아파치인 경우, 다음과 같이 Content-length에 제한을 주어 필요 이상의 요청을 막는다. 이 파라미터는 0 (제한없음) 부터 2147483647 (2GB) 까지이다. 예를 들어 100K까지 제한을 둔다고 하면 다음과 같이 설정한다. HTTP 헤더정보의 Content-length가 해당 범위 내에 없으면 “413 Requset Entiry Too Large”를 반환한다.