首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

Struts2安全缺陷(下)(转)

2012-09-19 
Struts2安全缺陷(上)(转)本文介绍了java开发流行框架struts2以及webwork的一些安全缺陷,并举例说明框架本

Struts2安全缺陷(上)(转)

本文介绍了java开发流行框架struts2以及webwork的一些安全缺陷,并举例说明框架本身以及开发人员使用框架时,所产生的种种安全问题,以及作者挖掘框架安全漏洞的一些心得体会。推荐以下人群阅读:了解java开发了解框架开发了解web application安全“网络安全爱好者”正文:当前java开发网站,通常不会是纯JSP的,大都使用了java?framework。有了这些framework,让开发人员更加快速的开发出代码,也让代码非常具有可扩展性,那些分层架构的思想,更是深入人心。这些也大大影响了安全代码审核,曾提出“分层审核代码”的思想,比如在DAO层专门检查sql注入,在view层检查xss等。这些框架都有自己的层级,本次文章主要讲的是struts这个框架的相关安全问题,也会有小部分涉及到struts后面的DAO层。而struts这个框架更新占有市场份额极大的一个框架,它在各个层级中,位于如图所示位置:

?

?

可以看到struts在web应用中,负责处理接收用户数据,调用业务处理,以及展示数据的工作。所以本文把struts的功能分为controller层和view层,controller层来完成接收用户数据,分发用户请求,而view专门用于展示数据。一个单独的struts,是不合逻辑的,因为架构师通常喜欢多种框架集合,让它们各自负责某一层的处理。研究一个框架的安全问题,不能仅仅站在框架的角度,还应该充分考虑到开发人员是如何使用这些框架的,他们最喜欢写什么样的代码,这样才能还原一个正常的、完整的web应用场景。从搜索结果看,互联网中,绝大多数教程推荐struts+hibernate+spring这样的黄金组合,那么,我假设有一个应用使用了这个组合,以struts为重点,站在攻击者的角度,层层分析struts的设计缺陷。Struts2开发回顾与简单学习为了让大家回顾或者学习一下struts2,我们一起来建立一个action、jsp页面,做一个接收用户输入,之后处理一下,再展示出来给用户的过程,精通struts2的同学可以跳过此步。-------------------------------------struts回顾start首先建立action,叫做AaaaAction:

public class AaaaAction extends ActionSupport{

??? private String name;??? public String getName() {??????? return name;??? }??? public void setName(String name) {??????? this.name = name;??? }??? public String execute(){??????? System.out.println("exe");??????? return SUCCESS;??? }??? public String bbb(){??????? System.out.println("bbbbb");??????? return SUCCESS;??? }}请注意execute这个方法,让用户输入action的地址后,默认会访问这个方法。之后配置struts.xml文件

<action name="aaaaaaa" width="369" alt="Struts2安全缺陷(下)(转)" height="157" src="/img/2012/09/14/1456132691.jpg">

?

但是struts2把所有public的方法都暴露了出去,导致现在用户输入了http://www.inbreak.net/app/userlogin!list.action用户访问这个链接后,struts2调用list方法,然后返回结果给用户,所以没有登陆,就显示了所有用户信息,直接绕过了login中的登陆验证。

?

?

在没有struts2的时候,我们要在servlet的doget或者dopost方法中,写if判断等代码,才能让用户调用其他servlet中的方法,现在看来其实这也是一种保护措施。而现在struts2为了方便开发,把所有的public方法统一映射了出去,导致开发把一个经常使用的功能,习惯写成一个public的方法,现在居然成了严重漏洞。struts2的action属性设计缺陷:再回头看看我们在action中的属性定义,你会发现,现在他们都成了漏洞,因为struts2规定属性的get和set方法,都必须是public的。那么我们定义了

private String name;

public String getName() {

??? return name;}

public void setName(String name) {

??? this.name = name;}这段代码的时候,实际上,是写了两个public的方法。那这两个表面上没有任何实质含义的方法,会有什么安全隐患呢?这需要和前文联系起来,前文提到,我们在struts.xml文件中,定义如下:

<action name="user" width="441" alt="Struts2安全缺陷(下)(转)" height="81" src="/img/2012/09/14/1456132693.jpg">

?

一系列巧合后,导致现在给用户返回了user/addUser.jsp页面,这是一个添加用户的表单页面,并且用户没有去走验证是否为超级管理员这一步。现在用户看到了一个添加用户的页面,他有两种攻击思路:1,直接提交,如果处理用户提交的那个action没有再次判断用户身份,那就提交成功了。2,如果他判断了用户身份,我们还可以csrf他,因为我们知道了这个action的地址,和它需要的参数!由于struts2的action和jsp文件分离,导致开发人员往往会在action的方法中,执行权限判断,而jsp页面中并没有再次执行这个判断,他以为action判断就够了。而偏偏action的属性,给我们带来了一个可自定义返回result的方法,导致我们可以绕过action访问jsp页面。Struts2的那些result类型缺陷(redirect):刚才我们领教了struts2给我们带来那些属性的好处,现在我们再往后走一步,研究Action方法的返回结果。其实并不是只由String类型的返回结果,struts2还有其他类型的返回,比如“redirect”类型。

<action name="test" type="redirect">${redirecturl}</result>

</action>这段代码,大家唯一可能看不懂的,就是type="redirect"了。这是一个url redirect的方式,struts2为了方便大家开发,把“自定义302跳转到其他url”这种方式给包装了起来。只要如上定义,我们就可以在action中写方法:

public String redirect() {

??? return "redir";}然后定义属性private String 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跳转到钓鱼网站,我们肯定需要一个白名单机制,或者根本就让他跳转到本站下。于是有了如下判断:

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”,所以来到了

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

而redirecturl的值,也提交给了action,所以跳转了。Struts2的那些result类型缺陷(Ajax):在struts2中使用ajax,也是被struts2支持的,它提供了一种返回类型,叫做“stream”。在研究这个result的使用时,作者看到一本书,叫做《 Struts 2权威指南:基于WebWork核心的MVC开发 》。这本书非常出名,几乎所有的struts2使用者都推荐使用。http://book.csdn.net/bookfiles/479/index.html书上介绍ajax可以这么使用:配置struts.xml

<action name="ajaxtest" type="redirect">${redir}</result>

????<result name="testloadfilepath">${testloadfilepath}</result>

??? <result name="false">user/redirfalse.jsp</result>

??? <result name="input">user/input.jsp</result>

</action>请注意,其中一条result,名称是”testloadfilepath”,${testloadfilepath}的作用是自定义的jsp页面地址,接收session或request中传过来的这个变量的值。那么用户提交http://www.inbreak.net/app/test.action?testloadfilepath=user/test.jsp当然就会返回user/test.jsp页面,非常的灵活。虽然并不是所有的开发都会这么做,但是一旦出现这种情况,会产生什么问题呢?http://www.inbreak.net/app/test!getRedir.action?redir=testloadfilepath&testloadfilepath=WEB-INF/classes/hibernate.cfg.xml不知道大家看懂这段url的含义没有,先调用getRedir,可以自定义返回到testloadfilepath,而testloadfilepath已经指定了WEB-INF/classes/hibernate.cfg.xml。WEB-INF目录下,都是受web容器保护的东西,默认不允许直接request相对地址来访问。该目录里面有程序编译后的class文件(可以被直接反编译为java源码),有数据库配置文件等敏感文件,现在打开如上url,直接被下载了hibernate.cfg.xml,这里放着数据库用户名和密码。

?

?

这样,攻击者就可以下载你的所有源代码,所有服务器上的文件。struts在提供给我们这种方式的时候,并没有任何官方说明这里有危险,这就是一个不定时炸|弹。struts2的taglib设计缺陷经过几个例子下来,不知道大家注意到没有,从用户输入走到这里,已经走到了输出这一步了。struts2的那些result的type,其实就是几种输出方式,有jsp、ajax、redirect,经过jsonplugin等插件配置,还可以支持其他输出方式。甚至支持一些标签库,比如freemarker等标签库。不过我们只谈struts2自带的标签库,在一个jsp页面的最上方,写上一段代码,就可以使用struts2提供的数据输出和页面数据操作的标签了。比以往我们在jsp输出“<%=name%>”要方便的多,下面给个例子:test.jsp代码

<%@ taglib prefix="s" uri="/struts-tags" %>

<s:property value="username"/>

第一行是告诉struts这里要使用struts的标签库,第二行就是一个标签的使用,含义是输出username的 值,username会从session、request、page等地方取,这里不关注取数据的次序。

struts2的taglib设计缺陷(struts2.0不支持escapeJavaScript)说到输出,大家都能想到XSS漏洞,那么作为一个流行框架,struts2在这里做了什么控制呢?struts2.0对部分标签做了默认的htmlescape:刚才那个标签实际上效果等于

<s:property value="username" escape="true"/>

别以为做了htmlescape就够了,输出在javascript中的时候,还会出现xss漏洞。所以struts在2.1.6这个版本也支持了javascriptescape:struts2.1.6:

<s:property value="pass" escape="true" escapeJavaScript="false"/>

默认开启如上所示,当你要输出到js中的时候,可以使用escapeJavaScript进行转义。也就是说,一旦你确定这个struts是2.0的,只要开发人员把变量输出到js中,十有八九会出xss问题。struts2的taglib设计缺陷(没有富文本安全输出标签)而包括最高版本2.1.8在内,仍然没有支持富文本安全输出,这是一件悲剧的事情,如果用struts开发一个大众blog的应用,又支持富文本的文章,开发人员只能把htmlescape和jsescape都去掉,才能保证业务正常运行,所以导致了XSS漏洞。

?

热点排行