과거, 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초 이내로 짧게 설정해주어 서버 지연시간을 줄여준다.
2. Content-length 길이 제한
아파치인 경우, 다음과 같이 Content-length에 제한을 주어 필요 이상의
요청을 막는다. 이 파라미터는 0 (제한없음) 부터 2147483647 (2GB) 까지이다. 예를 들어 100K까지 제한을 둔다고 하면 다음과 같이 설정한다. HTTP 헤더정보의 Content-length가 해당 범위 내에
없으면 “413 Requset Entiry Too Large”를 반환한다.
'Network' 카테고리의 다른 글
네트워크 보안 사전 탐지 기술 30가지 (0) | 2012.03.12 |
---|---|
iptables 를 이용한 나만의 IPS 환경 구축 (0) | 2012.02.29 |
SSDP 대량발생, 이상징후인가? (0) | 2012.02.16 |
구글의 독자적인 프로토콜, SPDY (0) | 2011.12.14 |
[Tool][Wi-Fi] 8가지 Wi-Fi 무료 툴 (0) | 2011.12.14 |