欢迎访问创业驿站, 移动互联网创业资源信息分享平台
Loading
您所在的位置:首页 > 技术资讯 > 安全技术 > 正文

Struts 2漏洞层出不穷为哪般 对网民的直接影响堪比棱镜

来源: 【创业驿站】 日期:2015-7-3 11:58:14 人气:8 加入收藏 评论:0 标签:

Struts2被曝存在重大远程任意代码执行安全漏洞,据悉国内政府、金融、运营商及各大互联网公司的网站已受影响

Struts2被曝存在重大远程任意代码执行安全漏洞,影响Struts2全系版本,据悉国内政府、金融、运营商及各大互联网公司的网站已受影响。Struts团队也紧急发布了更新版本。其实在此之前很长时间内,此类漏洞就一直存在。同时,也请广大网民及时更改自己各大常用网络账号的密码!


以上来自微博:@社会网络与数据挖掘

Apache Struts团队6月底发布的Struts 2.3.15版本被曝出存在重要的安全漏洞,因此该团队紧急发布了Struts 2.3.15.1安全更新版本。

该版本修复的主要安全漏洞如下:

1. 通过在参数前面加上“action:”/“redirect:”/“redirectAction:”前缀,以实现远程代码执行,如下:

http://host/struts2-blank/example/X.action?action:%25{(new+java.lang.ProcessBuilder(new+java.lang.String[]{'command','goes','here'})).start()} http://host/struts2-showcase/employee/save.action?redirect:%25{(new+java.lang.ProcessBuilder(new+java.lang.String[]{'command','goes','here'})).start()}http://host/struts2-showcase/employee/save.action?redirectAction:%25{(new+java.lang.ProcessBuilder(new+java.lang.String[]{'command','goes','here'})).start()}

2. 通过在参数前面加上“redirect:”/“redirectAction:”前缀,以实现开放式重定向,如下:

http://host/struts2-showcase/fileupload/upload.action?redirect:http://www.yahoo.com/http://host/struts2-showcase/modelDriven/modelDriven.action?redirectAction:http://www.google.com/%23

详细漏洞信息:

  • http://struts.apache.org/release/2.3.x/docs/s2-016.html

  • http://struts.apache.org/release/2.3.x/docs/s2-017.html

  • http://struts.apache.org/release/2.3.x/docs/version-notes-23151.html

最新版本下载地址:http://struts.apache.org/

Struts2漏洞层出不穷

最近以来的Struts2更新似乎都在忙着修复各种安全漏洞,而这些漏洞都集中在此方面,比如5月底发布的Struts 2.3.14.2版本、6月初发布的2.3.14.3版本,都修复了相关的漏洞,而这些漏洞都可能导致执行远程命令、访问/控制会话以及发起XSS攻击 等。

下面来看看为什么Struts2此类安全漏洞会层出不穷?请看第2页(以下内容来自鬼仔的博客)。

从Struts2机制说起

通过框架,开发人员更加快速的开发出代码,也让代码非常具有可扩展性,那些分层架构的思想,更是深入人心。而struts这个框架占有了极大一部分市场份额,它在各个层级中的位置如图所示:

可以看到struts在web应用中,负责处理接收用户数据,调用业务处理,以及展示数据的工作。

struts2在数据流向方面,有两个重点,一个是进入(in),一个是输出(out)。而我在做漏洞挖掘的思路,也是跟着这个数据的流程,开始分析的,下面我们就开始让数据进入。

Action属性默认值可以被覆盖缺陷:

在日常的java项目中,我们经常会遇到保存一个新的对象(比如注册一个用户),然后给这个对象赋予一些用户提交上来的属性值,在这里,只需要定义一个对象类:

1
2
3
4
5
6
7
publicclassUser {
privateLong id=0l;
privateString name;
privateString pass;
privateInteger type=1;
……//下面的get和set方法代码略
}

定义后,在action中,添加一个属性

1
User reguser;

用户注册的页面代码如下:

1
2
<formXXXXXXX>
<inputname="reguser.name">

当用户提交这个form到action中后,struts2会负责自动映射reguser.name的值到reguser的相关属性 (name)中,所以在execute这个方法中,就可以使用reguser.getName()拿到用户提交的reguser.name的值。所以我们 下面的代码就很简单了:

1
2
publicString execute(){
add(user);

add方法,更简单了,因为我们项目中集成了hibernate,这个框架自动映射user类中的各个属性,自动组成insert语句。我们只要在add中调用session.save(user);就可以保存用户到数据库中。

前文提到那么多“简单”两个字,难道这些过程都是安全的而它给我们仅仅带来了方便么?

struts2只负责映射所有对象,它提供了form验证,也只能验证form中属性值的内容,比如email格式等,并不能约束用户提交其他属性上来,于是这就变成了十分危险的功能。

当User中有个属性type,代表User是否管理员时(1为普通用户,2为管理员),麻烦来了,攻击者在原来的注册表单中,新加入一个input,叫做

1
<inputname="reguser.type">

然后输入值是2,把这个值一起交给action。在这个流程中,这个值,当然也会被自动带到数据库中,向下处理的逻辑中,这个用户,就已经变成管理员了。

当你看到了一个struts2或者webwork的应用,可以尝试使用属性攻击,修改当前表单,里面有所有你猜测到的属性,一并提交上来, 就可能会影响整个逻辑,达到攻击目的。文中仅仅是一个例子,事实上,在数据传递的过程中,可以任意覆盖数据的默认值,本来就是一个危险的缺陷,而 struts2和webwork这两个框架仅仅看到了它带来的好处,忽略了这方面基于安全性的考虑,仅仅关注了用户提交数据的正确性。对比在没有 struts2这个功能的时候,我们却需要在action中一个一个的把需要的变量,从用户提交的request中解出来,一个一个处理,不可能出现这种 安全问题。现在它包装了这个过程,自以为很方便,却出了严重问题。

Struts2的action属性设计缺陷

再回头看看我们在action中的属性定义,你会发现,现在它们都成了漏洞,因为struts2规定属性的get和set方法,都必须是public的。

那么我们定义了

1
2
3
4
5
6
7
privateString name;
publicString getName() {
returnname;
}
publicvoidsetName(String name) {
this.name = name;
}

这段代码的时候,实际上,是写了两个public的方法。

那这两个表面上没有任何实质含义的方法,会有什么安全隐患呢?

我们在struts.xml文件中,定义如下:

1
2
3
4
5
6
<actionname="user">
<resultname="success">user/userlist.jsp</result>
<resultname="addUser">user/addUser.jsp</result>
<resultname="added">user/added.jsp</result>
<resultname="false">user/false.jsp</result>
</action>

这段代码含义是,UserAction中,任何一个方法执行后,如果返回的是success这个字符串, 就会把user/userlist.jsp返回给用户。

如果返回是addUser,就会把user/addUser.jsp返回给用户。

现在UserAction是管理用户的页面,在我们的系统中,有普通管理员和超级管理员,它们的区别是普通管理员可以查看用户,但是不能添加一个用户。

所以,我们在UserAction中,写了

1
2
3
4
5
6
publicString addUser(){
if(true){//事实上这里是个超级管理员的判断,我偷懒了。
return"false";
}
return"addUser";
}

这个方法的代码判断了不允许普通管理员访问,但是user/addUser.jsp这个jsp页面中并没有这个判断逻辑。因为开发认为只有返回addUser的时候,才会来到这个页面,而要返回addUser,则必须通过超级管理员的验证。

那我们能让一个方法返回addUser么?当然可以!

http://www.inbreak.net/app/user!getUsername.action?username=addUser

这个链接,struts2会怎么处理呢?

它会找struts.xml中,对应段路径user,于是找到了对应的处理 Action(net.inbreak.UserAction),由于路径中有了“!getUsername”,于是就去找这个Action中的 getUsername这个方法,很明显,这个方法其实是username这个属性的get方法,如果你要让Action接收用户提交的 username,你就必须要定义这个方法。

那这个方法会返回什么呢?会返回action的字段username的值!哈哈!username用户已经提交给action了,链接后面 写着“?username=addUser”,struts2把这个值赋予了action中的username属性。那这里返回的当然就是 “addUser”!

一系列巧合后,导致现在给用户返回了user/addUser.jsp页面,这是一个添加用户的表单页面,并且用户没有去走验证是否为超级管理员这一步。

现在用户看到了一个添加用户的页面,它有两种攻击思路:

  1. 直接提交,如果处理用户提交的那个action没有再次判断用户身份,那就提交成功了。

  2. 如果它判断了用户身份,我们还可以csrf它,因为我们知道了这个action的地址,和它需要的参数!

由于struts2的action和jsp文件分离,导致开发人员往往会在action的方法中,执行权限判断,而jsp页面中并 没有再次执行这个判断,它以为action判断就够了。而偏偏action的属性,给我们带来了一个可自定义返回result的方法,导致我们可以绕过 action访问jsp页面。

Struts2的那些result类型缺陷(redirect

其实并不是只由String类型的返回结果,struts2还有其他类型的返回,比如“redirect”类型。

1
2
3
4
<actionname="test">
<resultname="false">user/false.jsp</result>
<resultname="redir"type="redirect">${redirecturl}</result>
</action>

这是一个url redirect的方式,struts2为了方便大家开发,把“自定义302跳转到其他url”这种方式给包装了起来。只要如上定义,我们就可以在action中写方法:

1
2
3
publicString redirect() {
return"redir";
}

然后定义属性

1
privateString redirecturl;

当用户打开

http://www.inbreak.net/app/test!redirect.action?redirecturl=/a.jsp

的时候,就会302跳转到

http://www.inbreak.net/app/a.jsp

这是很常见的url跳转应用,在struts2中,如上配置一下,就可以实现。

相信明眼人都看出来了,很明显这里存在url跳转漏洞,如果用户输入了

http://www.inbreak.net/app/test!redirect.action?redirecturl=http://www.ph4nt0m.org

就会跳转到http://www.ph4nt0m.org这个钓鱼网站(-_-!)。那么如何防御呢?

要防御url跳转到钓鱼网站,我们肯定需要一个白名单机制,或者根本就让它跳转到本站下。于是有了如下判断:

1
2
3
4
5
6
7
public String redirect() {
if(redirecturl.startsWith("/"))
{
return"redir";
}
return"false";
}

可能你看出来了,仅仅判断"/"开头,其实是不能杜绝url跳转漏洞的,因为

http://www.inbreak.net/app/test!redirect.action?redirecturl=//www.ph4nt0m.org

一样会跳转。而在这里却足够了,因为struts2已经接管了这个过程,只要以“/”开头,统统先给你自动加上本地域名,抓包后,你会看到

location: http://www.inbreak.net/app//www.ph4nt0m.org

实际上是不会有问题的。

struts2也认为这样判断不会有问题了,然而用户输入

http://www.inbreak.net/app/test!getStr.action?str=redir&redirecturl=http://www.ph4nt0m.org

其实前篇已经分析过了,这样就利用action中的str属性,绕过了必须以“/”开头的判断,直接跳转了。

test里有个str属性,可自定义返回,这里自定义了“redir”,所以来到了

1
<resultname="redir"type="redirect">${redirecturl}</result>

而redirecturl的值,也提交给了action,所以跳转了。

安全问题是如何产生的

首先,是用不用框架的问题。一旦开发用了这些框架,web应用会直接面临一些漏洞:

1. 开放了某功能,导致采用框架的应用默认漏洞

因为这个框架在未经允许的情况下,悄悄的打开了某些功能,可能是为了方便开发等作用,结果导致了漏洞的产生。

2. 扩展了某功能,导致安全问题

我们的web应用,本来是可以自己写代码实现一些功能的,但是这个框架为了方便开发和管理,把开发人员要写的代码包装了下,只要简 单的几行就能实现原本大批代码才能做到的功能。而这些便利,却带来了很多安全问题。挖漏洞的同时,应该特别注意哪些地方比原来方便了很多,扩展了很多,这 些扩展和方便,是否考虑到了安全因素。

3. DEMO或教程或用户指南误导

自从框架出现后,为了让人们最快的了解和使用框架,官方出了很多用户手册、demo等功能。而很多大牛们,也相应的出了教程或者书 籍,但是这些教程、DEMO、书籍上的例子,恰恰产生了很多漏洞。甚至开发本来不按照教程走,不会有漏洞,却被教程误导了。如果黑客看到这些书籍,请立刻 把它列到你的扫描器中,绝对有不少开发会按照教程上去做。

4. 原本有安全方案,但是被某功能代码覆盖

这其实是一件悲剧的事情,告诉我们要注意在日常开发中和漏洞修补中,是否有不明真相的开发人员,为了实现某个功能,悄悄的把原本的安全方案断章取义的覆盖掉了。挖漏洞的时候,要特别注意安全方案附件的代码变动,很可能发现非常弱智的逻辑问题。

5. 不完善的安全

一个安全方案的实施,应该是彻头彻尾的,要注意方案的完整性,不能有些地方方案OK,有些地方不能实施。在挖漏洞的时候,也不要被安全方案吓住,并不是有了方案,听起来牛X,就绝对不会有漏洞的,最起码应该经过全面fuzz。

6. 版本升级后,没有醒目安全公告

我们知道所有的架构师都不愿意有事没事升级框架,特别是不稳定的框架版本,因为这个升级可能带来很多不可预料的问题,所以可能即使 看到了安全公告,也没有去升级。如果不懂安全,更不愿意升级框架了。所以官方必须做到一个漏洞的修补,一个公告的发布,必须带有相关的代码log。告诉大 家具体哪里做了改动。而挖漏洞的同学更应该盯紧这些地方,百般推敲和测试修改的部分,不要被一次公用的测试结果吓到,模糊的认为漏洞已经修补了。

7. 悲剧的方案

很多时候,我们会看到官方修补漏洞,或者一些安全方案的实施结果。那是不是真的都能达到修补漏洞的效果呢?

例如本文的<s:url>标签的xss漏洞,官方都这个漏洞的修补,真是绞尽脑汁,最终还是悲剧了。

8. 优秀的方案,悲剧的执行

9. 挑战web服务器配置

这个问题有必要说一说,struts有事没事做个静态映射做什么?其实是目的就是为了框架和应用分离,很明显那些js文件应该放在项目中的web目录下,但是为什么要做呢?还不是因为struts包发布的时候,还没有项目,只有框架。

它为了达到即使上了任何项目,也能有办法访问到它提供的那些js的目的,只好被逼无奈做了这个功能,静态目录映射。无论任何项目, 部署后,只要url后面根目录加上/struts,或者/static就可以访问js。后来做了这个功能感觉良好还不算,居然把功能提供出来,给推荐给开 发人员使用。归根结底是因为struts挑战了web服务器的配置,非要自己做静态映射。要知道人家web服务器做的映射,是经过多少年黑客入侵打磨出来 的,struts有吗?

这种情况突出在单独映射某目录,单独对某目录做权限,做DIR列表等功能。

10. 没有安全方案,也没有提醒

本文其实没有提到一些web漏洞,比如csrf,比如session fix,比如传输加密等,很明显struts是存在漏洞的。

想想官方,官方也明明知道上了自己的框架后,会存在这些漏洞,为什么连个提醒都没有呢?本来开发就不知道,你又藏着掖着。如果框架负责任,发个公告,说如果你用了我的框架,实际上要小心什么什么攻击……

这些框架除了那些“只要你用,必然有漏洞”的安全缺陷外,还有不少问题,会出现在开发人员使用框架的过程中:

1. 两个框架都方便,结合起来有漏洞

有个框架叫做Spring security,是基于url的访问权限控制,做的很好。如果你不是管理员,绝对不能访问admin目录。但是有很多web框架,访问一个action 或者访问一个controller,不止一个url可以访问,在这里做了兼容性处理,多个url指向同一个应用,导致Spring security这种基于url的访问控制,名存实亡。

2. 开发人员“正常”使用框架后,可能产生漏洞

这是最最惨的事情,框架绝对不会认领这种类型的漏洞的,它会认为这是开发的问题。然而本文的“action方法暴力破解、url redirect扩大化”这两个安全缺陷,实际上也是框架存在的意义(方便开发)带来的后果。官方会修补么?我想它顶多会说,大家不要这样那样而已,绝对 不会做什么安全方案的。要知道这些漏洞是具有struts或者webwork特色的,只有使用了这些框架才会有的。

3. 危险功能点

框架带来了一些功能点,比如Tag lib的一些XSS,只要使用,必定有漏洞。

4. 框架给开发挖坑

这根本就是陷阱,还是要说/static、/struts,如果开发不配置,顶多下载个js,影响不大,万一开发使用了这个功能,映射了某个目录,那就掉进坑里去了。

5. 一个框架带来的漏洞被另一个框架最大化

作者原文中提到了变量默认值被覆盖后,又因为hibernate不需要写sql语句,而最终被存储进了数据库中。回想一个问题,如 果让我们自己写sql语句实现,难道在添加普通用户的时候,会真的专门写个变量,接收用户传进来注册管理员的字段么?但是这是hibernate得问题 么?当然不是,只是因为有了它,导致漏洞更加严重而已。

本文网址:http://www.118s.net/jishu/anquan/55.html
读完这篇文章后,您心情如何?
  • 0
  • 0
  • 0
  • 0
  • 0
  • 0
  • 0
  • 0
更多>>网友评论
发表评论
关于本站
 创业驿站是一家免费创业信息分
享平台!希望走在创业路上的人
早日成就自己的梦想!
站长微信:wfguoqing