- HTTP 요청에서 패킷 사이즈를 변경하여 정수 오버플로를 발생시켜 서버에 BSOD(Blue Screen Of Death)를 유발하거나, 임의의 명령을 수행할 수 있는 취약점
취약한 버전 - Microsoft Windows 7 SP1 - Windows 8 - Windows 8.1 - Windows Server 2012 Gold 및 R2 - Windows Server 2008 R2 SP1
2.1 취약점 분석
- HTTP.sys의 주요 함수
함수명
설명
UlpParseRange
- Client 요청 패킷을 처음 처리하는 함수 - 동일한 요청에 대해서는 웹 서버에서 캐쉬된 Content를 사용해 속도를 높임
UlPrepareCacheMissRangeResponse
- Client에서 처음 요청 했을 때 Response 처리 해주는 함수
UlAdjustRangesToContentSize
- 요청 받은 range와 파일 size를 비교 및 체크를 수행하는 함수
UlpBuildCacheEntry
- 동일한 요청을 받은 경우 웹 서버 성능 향상을 위한 캐시함수
UlBuildFastRangeCacheMdlChain
- _imp__IoBuildPartialMdl 호출
_imp__IoBuildPartialMdl
- UlBuildFastRangeCacheMdlChain 함수의 return 값 만큼 메모리 할당
- 취약점이 발생하는 함수는 UlAdjustRangesToContentSize()로 다음 식을 이용해 요청 받은 파일 사이즈를 처리
// Security Check 함수 // 실제 파일 사이즈보다 작은지 검증 // Range High + 1 값이 요청받은 파일 사이즈보다 작을 경우 Security Check OK Range Low + (Range High - Range Low + 1) -> Range High + 1
// 할당 받는 메모리 크기 Return Value = Range High - Range Low + 1
- 정상적인 요청의 경우와 조작된 요청을 비교하면 다음과 같음 (Range 값 중 18은 0보다 큰 임의의 큰 값을 선택한 것)
정상적인 요청
조작된 요청
GET /hello.png HTTP/1.1 Range: 18-1365 hello.png FileSize : 184946
GET /hello.png HTTP/1.1 Range: 18-18446744073709551615 hello.png FileSize : 184946
① Range High + 1 < File Size (Security Check 수행) - 1365+1 = 1366 < 184946 // Security Check OK ② Range High - Range Low + 1 Retutn(할당 받는 메모리 크기) - 1365-18+1 = 1348 ③ _imp__IoBuildPartialMdl 메모리 할당 - 1348 만큼의 메모리 할당
①Range High + 1 < File Size (Security Check 수행) - 18446744073709551615+1 < 184946 - 18446744073709551615는 16진수로 0xFFFFFFFFFFFFFFFF - 64bit 이상 표현할 수 없기 때문에 0x0000000000000000이 됨 - 0 < 184946 이므로 Security Check OK ②Range High - Range Low + 1 Retutn(할당 받는 메모리 크기) - 18446744073709551615-18+1 = 0xFFFFFFFFFFFFFFEE ③_imp__IoBuildPartialMdl 메모리 할당 0xFFFFFFFFFFFFFFEE 만큼의 메모리 할당
[사진 3] 조작된 요청 동작 요약
- 위 표 및 사진에 따라, _imp__IoBuildPartialMdl에 의해 0xFFFFFFFFFFFFFFEE 만큼의 메모리를 받아오는 과정에서 BSOD가 발생
- 패치된 버전에서는 UlpParseRange 함수에 RtlULongLongAdd 함수를 호출하여 Overflow 여부를 확인하도록 함 - Integer Overflow가 발생할 경우 RtlULongLongAdd 함수는 STATUS_INTEGER_OVERFLOW 에러를 리턴
3.2 네트워크 측면
① 탐지 룰 등록
- 공개된 PoC를 확인해보면 Range 헤더를 조작하므로 Range 헤더 등을 탐지
alert tcp $EXTERNAL_NET any -> $HOME_NET $HTTP_PORTS (msg:"SERVER-IIS Microsoft IIS Range header integer overflow attempt"; flow:to_server,established; content:"Range"; nocase; http_header; content:"bytes"; distance:0; nocase; http_header; content:!"|0A|"; within:12; http_header; pcre:"/^Range\s*\x3a\s*bytes\s*\x3d[^\x0a]*?\d{11}/Him"; metadata:policy security-ips drop, service http; reference:bugtraq,74013; reference:cve,2015-1635; reference:url,technet.microsoft.com/en-us/security/bulletin/ms15-034; classtype:attempted-dos; sid:34061; rev:3;)
- 3-Way HandShaking의 Half-Open 연결이 가능한 것을 이용한 취약점 - 공격자는 대상 시스템에 출발지 IP를 위조해 무수한 SYN 패킷 전송 - 대상 시스템은 위조된 IP에 SYN/ACK 패킷을 전송하며, ACK 응답을 기다림 - 출발지 IP는 위조되어 정상적인 ACK 응답을 수신하지 못함 - 대상시스템은 ACK 응답을 기다리므로, 정상 서비스 제공이 불가해짐
SMURF Attack
- 출발지 IP를 대상 시스템으로 위조 및 ICMP 패킷을 직접 브로드 캐스팅 주소(X.X.X.255)로 전송 - 해당 패킷을 수신한 시스템은 대상 시스템으로 ICMP 패킷 응답 - 대상시스템은 ICMP 응답을 과다하게 수신하여, 정상 서비스 제공이 불가해짐
Land Attack
- 출발지 IP와 목적지 IP를 동일하게 설정하여 전송 - 해당 요청을 처리하는 과정에서 부하 발생
Ping of Death
- ping에 사용되는 ICMP 패킷의 크기를 정상 크기보다 크게 설정하여 전송하며, 해당 패킷은 네트워크를 거치면서(라우팅 되면서) 작은 조각으로 쪼개지면서 전송됨. - 피해 시스템에서는 수신한 패킷을 재조립하는 과정에서 부하가 발생.
Tear Drop Attack
- 패킷은 네트워크를 통해 전송되면서 단편화를 통해 분할되고, 수신지에서 재조립 - 패킷이 단편회 될 때 오프셋 값을 중복되도록 설정하는 등의 방식을 통해 수신지에서 재조립시 부하 유발
Bonk
- 모든 패킷의 순서번호를 1로 설정하여 전송
Boink
- 첫번째 패킷의 순서번호를 1, 두번째 패킷의 순서번호를 201, 세번째 패킷의 순서번호 1011 등 순서번호를 랜덤하게 전송
2. DDoS (Distributed Denial of Service) 유형
구분
공격명
설명
전통적인 공격
Trinoo
- 많은 호스트로부터 UDP Flooding을 유발
TFN(Tribed Flood Network)
- Trinoo의 발전된 형태 - UDP Flooding, ICMP Flooding, TCP SYN Flooding 가능
Stacheldraht
- Trinoo + TFN (두 공격이 제공하는 기능 모두 가짐) - 마스터와 에이전트 간 통신에 암호화 기능을 사용
3. DRDoS (Distributed Reflection Denial of Service) 유형
공격명
설명
DNS Reflection Attack
- 출발지 IP를 대상 시스템으로 위장하여, 다수의 DNS 서버에 ANY, TXT 레코드 요청. - ANY 레코드 : 도메인에 대한 모든 레코드 질의 시 사용. - TXT 레코드 : 도메인과 관련해 저장해야 할 임의의 문자를 나타냄. - 두 레코드 모두 요청에 비해 응답이 크기 때문에 공격에 주로 사용됨.
NTP Reflection Attack
- 출발지 IP를 대상 시스템으로 위장하여,다수의 NTP 서버에 monlist 요청. - monlist : 최근에 접속한 최대 600개의 호스트 정보를 요청