【技术分享】自动绑定漏洞和Spring MVC

https://p1.ssl.qhimg.com/t0115008d4001019f46.jpg

作者:testvul_001

预估稿费:200RMB

投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿

前言

今天介绍一个不是很出名的漏洞—自动绑定漏洞(或者称为mass assignment)。自动绑定功能在很多框架里都实现了,它允许框架自动将HTTP请求中的参数绑定到对象中并便于开发者访问。然而攻击者可能将额外的HTTP请求参数绑定到一个对象上,当软件中存在逻辑问题时,攻击者就可以做一些有意思的事情。

自动绑定功能在框架中很流行,所以这种漏洞的攻击面按理来说是很广的,但是通常我们在没有源代码的情况下是很难发现它们的,并且每个漏洞的影响都取决于应用本身的逻辑。


相关资料

如果你之前没有听说过这种漏洞,可以先到OWASP上看看介绍(上面有几个简单的例子):https://www.owasp.org/index.php/Mass_Assignment_Cheat_Sheet 。Ryan Berg 和Dinis Cruz 在2011年发表了一个关于这个漏洞和Spring MVC的详细例子的paper(https://o2platform.files.wordpress.com/2011/07/ounce_springframework_vulnerabilities.pdf  )。


新的特性

那个paper已经是很久之前发表的了,现在Spring MVC已经不同于那时候了,它变得更酷了。

当我准备给最近的ZeroNigths HackQuest活动出题目时,我想出些和自动绑定相关的漏洞,这样人们就会更熟悉这种漏洞。

正如我之前说的,Spring MVC已经改变了,它变得更加的敏捷,有很多新的特性。其中之一是使用注释来做一些“magic”的事情。因为一些对这些特性的误解,我们能够在意想不到的地方发现自动绑定漏洞。

下面我们来看看官方的说明(http://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/html/mvc.html):

http://p4.qhimg.com/t01b6a675a3087db0d2.png

如果你并不了解Spring MVC,不要慌,通过下面的例子你就清楚了。上面的2-4有什么共性?它们都和方法中的数据传递相关!获取传递给方法的参数的一个方式是在方法的参数上使用@ModelAttribute(就如1中描述的那样)。但是这种方式会导致自动绑定漏洞,为什么?因为@ModelAttribute 过于敏捷了,我们来看一下完整的描述:

http://p3.qhimg.com/t013cc73d3bae1336ad.png

首先,@ModelAttribute从 model中(或者其他地方)获得一个对象,然后使用用户的请求request来赋值。开发者本来想从model中获取可信的数据,但是攻击者可以通过发送一个特别构造的请求改变这些数据。

我给ZN HQ设置了两个关于这个漏洞的任务,具体代码在:

https://github.com/GrrrDog/ZeroNights-HackQuest-2016 


任务一:Edik

这个例子有三个页面:注册,认证,home。我们的目标是在home页面进行表达式语言注入。这个任务的难点在于用户只能在注册流程中输入数据。应用中存在一个user 类,该类有3个变量(name, password, weight)。注册controller如下:

http://p2.qhimg.com/t0165a4065197e0493e.png

         如图,controller从用户的请求(request)中获得User 对象并进行验证,如果通过验证,就把这个对象放到”DB”中。

http://p6.qhimg.com/t01505be4daf338bc5a.png

验证过程很严格,因为使用了白名单,所以我们只能使用数字和字母。那我们要怎样在user对象中使用特殊字符呢?

攻击者要怎么做呢?让我们看看认证和home模块吧:

认证的流程很简单:

1、从用户请求中获得username 和 password。

2、使用1中的username和password从 db中获取一个user 对象。

3、将这个user对象放到FlashAttribute中,然后跳转到home方法(在response中跳转到/home)。

所以这一步也没有办法修改 user对象。

http://p9.qhimg.com/t01b541307c0208b35d.png

那么home 方法怎么样呢?它从flash attribute中获取user对象并展示给我们。@modelAttribute在这个地方用来获取user对象,但是它同样会使用用户request中的参数来给user对象赋值!所以我们可以修改user对象中的值,我们只需要通过认证并在跳转的过程中给请求添加一个额外的参数:

/home?name=${We_Can_Write_Here_wharever_we_want}

任务已经完成。自动绑定有一个有趣但是不明显的特点,在赋值的过程中,Spring MVC改变了已有变量的值而不是利用HTTP请求中的数据新建一个对象。这说明如果有一个从model中获得的对象且从HTTP请求中只获得一个参数,那么只有一个变量(和HTTP参数同名)会被改变,其他的变量会保持不变。

 

任务二:Justice League

第二个任务的应用由注册,认证,home,找回密码4个页面组成。我们关注的重点是找回密码页面,找回密码功能是一个拥有几个方法的controller。我们的目标是绕过它的验证。

应用的主要逻辑如下:

1、  用户访问找回密码页面,输入用户名并提交表单。

2、  resetHandler方法接收HTTP请求,使用username参数从db中获取一个user对象,然后将这个user对象放到Model中,同时也会自动把对象放到session中(controller中的@SessionAttribute("user")),最后跳转到下一个页面。

http://p5.qhimg.com/t01851c80ed47b23540.png

3、  用户跳转到resetViewQuestionHandler方法,实际上这个方法从session中获取user对象(使用@ModelAttribute)。这里将会使用这个user对象获取用户的安全问题并展示出来。

http://p0.qhimg.com/t0196bcf54602bf3961.png

4、  当用户发送问题的答案时,resetQuestionHandler处理这个请求。方法从answerReset参数中获取答案并和user对象中的answer变量比较,如果相等应用就会产生一个新的密码并且展示给用户。虽然方法的参数中没有@ModelAttribute修饰User user,但是Spring MVC实在是太敏捷了,它会自动从session中获取值,然后使用用户的请求request赋值。

那么我们现在要怎么实现目标呢?

1、  当我们给resetQuestionHandler发送GET请求的时候可以添加“answer=any_value”参数,这样就可以给session中的对象赋值,将原本正确的答案修改成任何值。

2、  我们也可以在最后一步POST中添加"answer=any_value"参数,并且获得相同的结果。事实上我们可以修改对象中所有变量。

http://p5.qhimg.com/t012591d78c74c78b42.png

这里有另外一个有趣的东西,当一个方法从session中获取对象并使用用户request赋值时,@SessionAttribute会强制Spring在session中存储这个对象。因此我们可以控制这个session中的对象的值,这样我们就可能实施Session Puzzling攻击(https://www.owasp.org/index.php/Testing_for_Session_puzzling_(OTG-SESS-008) 。


如何挖掘自动绑定漏洞

尽管直觉上通过黑盒测试发现自动绑定漏洞是不可能的事,我们还是解决了上面两个任务。以下一些tips将有助于我们发现自动绑定漏洞:

1、参数名称和对象的变量名称相同(并不一定需要,因为这也是可配置的)。值得注意的是,自动绑定也可以用在hashmap和array中。

2、当一个controller使用自动绑定功能时,我们发送两个相同名称的参数,对象的值会变成参数的集合。

带参数的Request:

?name=text1&name=text2

结果:

ObjectWithNameField.name = text1,text2

3、当我们收集到所有参数名称后,我们将这些参数发送给所有的入口(URL),即使这个URL(例如resetViewQuestionHandler)看起来并不接受任何参数,然后检查响应是否有变化。

总结

这篇文章的主要观点就是开发者盲目相信他所获得的对象来自可信任的地方,但事实上,攻击者可以任意修改这个对象的值。很难讲变量绑定漏洞或者和它类似的漏洞到底有多普遍,但是自动绑定漏洞确实是分布很广的(基于它产生的特性)。同时变量绑定漏洞并不仅限于HTTP的参数,理论上它可能出现在任何地方(JSON或者XML),只要这些数据能被转换并用于赋值。当然每个变量绑定漏洞的具体危害还取决于代码的业务逻辑和它使用的各种属性。

(完)