您的位置:首页 > 编程语言 > Java开发

Java浮点值拒绝服务漏洞危害分析

2013-07-23 15:56 615 查看
By空虚浪子心http://www.inbreak.net/
JAVA出了漏洞,CVE-2010-4476,会导致拒绝服务攻击。大家能从公告上,看到这样一段代码,挺长的。意思是只有开发人员写出这样的代码,才会对服务器造成影响。

我们肯定会首先考虑,这么长的代码,究竟有多少开发会傻乎乎的写出来?而我们究竟打不打补丁呢?其实作者知道,目前还有很多公司没有打补丁,不过没关系,等会儿你就要打了。

先看看官方给出的代码。

SendaJavaProgramIntoAnInfiniteLoop

Compilethisprogramandrunit;theprogramwillhang(atleastitdoesona32-bitsystemwiththelatestJRE/JDK):

classrunhang{

publicstaticvoidmain(String[]args){

System.out.println(“Test:”);

doubled=Double.parseDouble(“2.2250738585072012e-308″);

System.out.println(“Value:”+d);

}

}

—————————————————————————————————————-

SendtheJavaCompilerIntoAnInfiniteLoop

Trytocompilethisprogram;thecompilerwillhang:

classcompilehang{

publicstaticvoidmain(String[]args){

doubled=2.2250738585072012e-308;

System.out.println(“Value:”+d);

}

}


以上代码,其实举了两个例子,首先简化一下代码:

这段代码会在编译时挂掉:

doubled=2.2250738585072012e-308;

这段代码会在运行时挂掉:

doubled=Double.parseDouble(“2.2250738585072012e-308″);


作者很奇怪后面的System.out是啥意思,按照实际测试以及官方原理,这句压根不会执行,楼上都已经“无限循环”了,怎么可能走下来呢?不过这个不重要。

下文所说的漏洞,是指假设我们的开发人员写了“XXX”的代码,攻击者就可能攻击我们服务器。

我们来逆推攻击过程,从漏洞的角度上说,只有程序传入的值,由用户控制,才会导致漏洞触发,毕竟开发不会直接写这个值。而编译中挂掉,几乎不可能存在,很难有正常的业务需要用户提交代码,让服务器编译执行。所以,漏洞的产生只会出在这一句上:

这段代码会在运行时挂掉:

doubled=Double.parseDouble(“2.2250738585072012e-308″);


那么再次逆推,要求这个值有用户控制,如果环境是javawebapplication,开发想写出有漏洞的代码,必须这样搞:

这段代码会在运行时挂掉:

doubled=Double.parseDouble(request.getParameter(“double”));


当开发人员写出这样的代码,攻击者可以提交:
http://www.inbreak.net/double.do?double=2.2250738585072012e-308
于是,程序就”hang!”(其实我不知道这个词的意思),挂了,从表面上看不出来,但是实际上你的CPU会立刻100%,当前线程走不下去,页面
卡死,不给你任何响应。当然,其他页面也许会好,因为web容器是多线程的,可惜已经有人100%CPU了,页面速度可想而知。

很多人,就考虑到了这段,除非开发人员真的写了这样的代码,否则很难出现漏洞,所以没有打补丁。

Javaweb在很多年前,都已经开始走框架路线了,我们熟知的spring
mvc、struts2、webwork等等,甚至还有一些公司自己实现框架,比如阿里巴巴公司的开源框架webx(宣传一下http://code.taobao.org/project/view/401/)。在这样的框架中,开发人员更不可能自己去做转义,这都是框架自己负责的。是不是意味着,漏洞不可能存在呢?

这恰恰是最可怕的地方,这些框架没有让开发人员参与类型转义,用户本来提交的是一个String的2.2250738585072012e-308,框架会自动转义类型为Double,经测试,所有的框架都有自动类型转义(否则框架意义何在啊)。

开发什么都不需要做,只要在action中有一个对象,对象中有一个字段类型为double,或许他都不需要定义对象,其他开发早定义好了,他只需要写一个action。比如:

//订单处理action

publicclassOrderActionextendsActionSupport{

//订单对象

publicOrderorder;

publicStringexecute(){

returnSUCCESS;

}

}

//Order对象的内容

PublicclassOrder{

//前面还有其他字段,这里只说Double类型的。

Doublemoney;

}




这是很常见的写法,只要Order对象中,有一个字段是Double的。我们就可以对此action提交:
http://www.inbreak.net/order.do?order.money=2.2250738585072012e-308
这就“hang”了。

我们可以写个扫描器,那么会有哪些字段通常被定义为double呢?扫描器自己去抓页面,抓回来的input,如果为user.name,我们就猜测
user对象中可能存在money,可能存在score、point等,然后让它们等于那个值,自动提交。这等于挂字典,猜测对象中可能存在的
double类型字段。

有没有线上的例子呢?

163的网易宝单日支付金额限制:





正常的情况,填入1元,看看效果:





立刻来到了

但是我们填上:2.2250738585072012e-308





等啊等,等啊等。。。等到花儿也谢了,还是不响应!

你猜猜它们的服务器怎样了?

Java
web框架化以后,开发人员和架构师都忘记了转义类型的事情,也不需要自己做转义,代码变得越来越简单。作者为了研究漏洞,去询问有些资深架构师时,甚至
以为“开发不会写这样的代码”,所以我们的程序不会受到影响。最终还是作者亲手用现有框架搭建了环境,把CPU真的跑到100%,才开始相信这个漏洞对框
架的危害。

作者相信,J2EE框架对这个漏洞的完美支持,足以使很多门户网站沦陷。而这只是刚刚开始,你可以抱有侥幸心理,不过下一篇和这个漏洞有关的文章,会让你彻底打消这个念头。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: