今天给大家展示一段神奇的代码。就这几行神奇的代码,网站都能崩溃,这是怎么回事?就是下面这个函数,根据传入的起始位置和结束位置读取文件数据:char*Read(intfd,intstart,intend){unsignedintlength=end-start+1;if(length>1024)returnNULL;returnReadFile(fd,start,end);}函数只支持一次读取1024字节,所以增加了一个判断逻辑。现在请大家想一想,这个功能有什么问题吗?---Thinking------Thinking------5------Second------Minute---让我们想一想,假设我这样调用这个函数:Read(0,0,4294967295);会发生什么?您可能已经注意到,这里传递了一个非常特殊的参数。乍一看,这个数字很大,远远超过了1024,按理说会没通过函数内部校验吧?但事情并没有这么简单,这个特殊的数字——4294967295,是一个32位无符号整数所能表示的最大范围。但是请注意Read函数的参数,start和end都是int变量,当把4294967295传给end时,会被解析为有符号整数,也就是-1!现在看一下Read函数中计算长度的代码行:unsignedintlength=end-start+1;计算结果为-1-0+1=0!length的结果将为0!逃避下面的长度检查是很自然的:if(length>1024)returnNULL;上面的代码不仅仅是一个假设的模型,其实它曾经存在过!其漏洞编号为:CVE-2015-1635。这是微软Internet服务器IIS中的一个漏洞,更重要的是,该漏洞位于IIS处理HTTP请求的HTTP.sys驱动中。众所周知,驱动程序运行在操作系统的内核中。一旦内核驱动执行异常,后果轻则蓝屏死机,重则攻击者远程执行代码控制服务器!在HTTP1.1版本协议中,可以通过请求头中的Range字段来请求或上传指定资源的部分内容,例如:GET/bg-upper.pngHTTP/1.1User-Agent:curl/7.35。0Host:127.0.0.1:8180Accept:*/*Range:bytes=0-10Range字段的格式如下:Range:bytes=start-end为了提高性能,微软的IIS把HTTP协议解析放在了内核驱动HTTP.sys完成。范围字段的处理出现了我们文章开头的逻辑错误。不同的是上面的例子是32位整数版本,而IIS真正的漏洞是64位整数引起的问题,但是原理是一样的。通过向存在漏洞的IIS服务器发送相应的HTTP请求,可以使目标服务器蓝屏,实现DOS——拒绝服务攻击。这种攻击方式就是——整数溢出攻击。接下来我们搭建环境来验证一下。在虚拟机中搭建IIS7web服务器:64位无符号整数所能表示的最大数为:18446744073709551615。向服务器发送包含range参数的请求可能会导致服务器蓝屏。使用神器metasploit利用此漏洞发起攻击:现在看,服务器已经挂了:为什么很有可能,不一定是蓝屏,如何实现服务器稳定蓝屏?这需要进一步更详细地了解漏洞。其实这个漏洞的原理比文章开头的逻辑还要复杂。这里只是简单介绍一下。关于这个漏洞的更多细节,可以阅读360大师MJ0011写的技术分析(PS:有点硬核,想多看几遍就明白):《MS15-034/CVE-2015-1635 HTTP远程代码执行漏洞分析》https://blogs.360.cn/post/cve_2015_6135_http_rce_analysis.html我们平时编程的时候,一定要注意变量的数据类型,尤其是涉及到数据类型转换的地方,要格外小心。比如有符号数和无符号数之间的转换,32位整数和64位整数的转换等。处理从外界传入的参数时要小心,一个小的变量类型可能会对服务器计算机造成毁灭性的打击。
