Struts2框架安全缺陷Word格式.docx

上传人:b****6 文档编号:19761457 上传时间:2023-01-09 格式:DOCX 页数:27 大小:34.41KB
下载 相关 举报
Struts2框架安全缺陷Word格式.docx_第1页
第1页 / 共27页
Struts2框架安全缺陷Word格式.docx_第2页
第2页 / 共27页
Struts2框架安全缺陷Word格式.docx_第3页
第3页 / 共27页
Struts2框架安全缺陷Word格式.docx_第4页
第4页 / 共27页
Struts2框架安全缺陷Word格式.docx_第5页
第5页 / 共27页
点击查看更多>>
下载资源
资源描述

Struts2框架安全缺陷Word格式.docx

《Struts2框架安全缺陷Word格式.docx》由会员分享,可在线阅读,更多相关《Struts2框架安全缺陷Word格式.docx(27页珍藏版)》请在冰豆网上搜索。

Struts2框架安全缺陷Word格式.docx

publicclassAaaaActionextendsActionSupport{

privateStringname;

publicStringgetName(){

returnname;

}

publicvoidsetName(Stringname){

this.name=name;

publicStringexecute(){

System.out.println("

exe"

);

returnSUCCESS;

publicStringbbb(){

bbbbb"

}

请注意execute这个方法,让用户输入action的地址后,默认会访问这个方法。

之后配置struts.xml文件

<

actionname="

aaaaaaa"

class="

net.inbreak.AaaaAction"

>

<

resultname="

success"

user/aaa.jsp<

/result>

/action>

配置这个文件后,当用户输入

的时候,struts会负责让AaaaAction中的execute方法处理用户请求。

处理之后,该方法返回“returnSUCCESS;

”,struts又负责找到result的name是seccuess所指向的jsp页面。

把该页面解析后,返回给用户。

而用户看到的就是aaa.jsp页面的html代码。

struts2继承了webwork的所有优点,其实等于是webwork的升级,如果开发人员想让用户直接访问action中的

某方法,而不是访问默认的execute方法,只要定义一个方法叫做bbb,并且是public的,用户就可以直接输入

直接访问了bbb方法。

那request中的参数如果接收呢?

struts2中,这个过程被包装了起来,使用非常方便,只要在action中定义

一个属性,叫做publicStringname;

然后加入getName和setName方法,就可以像正常使用属性一样,接收到

用户传递过来的变量。

无论是get请求还是post请求,都可以使用这种方式接收用户输入。

整个过程就如此简单,现在大家对流程有了了解,我们就开始讨论正文,如果还是想了解更多,请自行google。

----------------------------------struts回顾end

Struts2安全缺陷

可以看到struts2在数据流向方面,有两个重点,一个是进入(in),一个是输出(out)。

而我在做漏洞

挖掘的思路,也是跟着这个数据的流程,开始分析的,下面我们就开始让数据进入。

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

在日常的java项目中,我们经常会遇到保存一个新的对象(比如注册一个用户),然后给这个对象赋予一些

用户提交上来的属性值,在这里,只需要定义一个对象类:

publicclassUser{

privateLongid=0l;

privateStringpass;

privateIntegertype=1;

下面的get和set方法代码略

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

Userreguser;

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

formXXXXXXX>

inputname="

reguser.name"

当用户提交这个form到action中后,struts2会负责自动映射reguser.name的值到reguser的相关属性(name)

中,所以在execute这个方法中,就可以使用reguser.getName()拿到用户提交的reguser.name的值。

所以我们

下面的代码就很简单了:

publicStringexecute(){

add(user);

add方法,更简单了,因为我们项目中集成了hibernate,这个框架自动映射user类中的各个属性,自动组成

insert语句。

我们只要在add中调用session.save(user);

就可以保存用户到数据库中。

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

struts2只负责映射所有对象,他提供了form验证,也只能验证form中属性值的内容,比如email格式等,

并不能约束用户提交其他属性上来,于是这就变成了十分危险的功能。

当User中有个属性type,代表User是否管理员时(1为普通用户,2为管理员),麻烦来了,攻击者在原来的

注册表单中,新加入一个input,叫做

reguser.type"

然后输入值是2,把这个值一起交给action。

在这个流程中,这个值,当然也会被自动带到数据库中,向下

处理的逻辑中,这个用户,就已经变成管理员了。

当你看到了一个struts2或者webwork的应用,可以尝试使用属性攻击,修改当前表单,里面有所有你猜测到

的属性,一并提交上来,就可能会影响整个逻辑,达到攻击目的。

文中仅仅是一个例子,事实上,在数据传递

的过程中,可以任意覆盖数据的默认值,本来就是一个危险的缺陷,而struts2和webwork这两个框架仅仅看到

了它带来的好处,忽略了这方面基于安全性的考虑,仅仅关注了用户提交数据的正确性。

对比在没有struts2

这个功能的时候,我们却需要在action中一个一个的把需要的变量,从用户提交的request中解出来,一个一个

处理,不可能出现这种安全问题。

现在它包装了这个过程,自以为很方面,却出了严重问题。

Action中的方法被暴力猜解缺陷

前文提到,有一种方法可以让用户访问action时,不访问默认的execute方法,而是直接访问其他action中

的方法,条件是在action中,写一个public的方法。

开发人员如果需要做一个登陆后,展示所有用户列表的

功能,而他的一个“解耦合”的开发习惯,将在这里导致安全缺陷。

定义一个如下的action

publicclassUserloginextendsActionSupport{

privateStringuname="

"

;

privateStringupwd;

privateListlist;

//getterandsetter方法略

publicStringlogin(){

if(uname!

=null&

&

upwd!

uname.equals("

kxlzx"

)&

upwd.equals("

pass"

))

{//ifloginsuccess

returnlist();

returnfalse;

publicStringlist(){

list.add("

list.add("

kxlzx1"

kxlzx2"

kxlzx3"

return"

list"

Userlogin中,因为list这个功能(显示所有用户列表),其实是一个通用的功能,很容易被其他地方调用,

所以开发人员把它单独写成了一个方法。

当用户登陆的时候,打开

来到了用户的登陆页面,可以看到,只有用户输入正确的用户名和密码,才能最终调用list()方法,显示结果。

但是struts2把所有public的方法都暴露了出去,导致现在用户输入了

用户访问这个链接后,struts2调用list方法,然后返回结果给用户,所以没有登陆,就显示了所有用户信息,

直接绕过了login中的登陆验证。

在没有struts2的时候,我们要在servlet的doget或者dopost方法中,写if判断等代码,才能让用户调用其他

servlet中的方法,现在看来其实这也是一种保护措施。

而现在struts2为了方便开发,把所有的public方法

统一映射了出去,导致开发把一个经常使用的功能,习惯写成一个public的方法,现在居然成了严重漏洞。

struts2的action属性设计缺陷

再回头看看我们在action中的属性定义,你会发现,现在他们都成了漏洞,因为struts2规定属性的get和

set方法,都必须是public的。

那么我们定义了

privateStringname;

publicStringgetName(){

publicvoidsetName(Stringname){

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

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

这需要和前文联系起来,前文提到,我们在struts.xml文件中,定义如下:

user"

net.inbreak.UserAction"

user/userlist.jsp<

addUser"

user/addUser.jsp<

added"

user/added.jsp<

false"

user/false.jsp<

这段代码含义是,UserAction中,任何一个方法执行后,如果返回的是success这个字符串,就会把

user/userlist.jsp返回给用户。

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

现在UserAction是管理用户的页面,在我们的系统中,有普通管理员和超级管理员,他们的区别是普通管理员

可以查看用户,但是不能添加一个用户。

所以,我们在UserAction中,写了

publicStringaddUser(){

if(true){//事实上这里是个超级管理员的判断,我偷懒了。

这个方法的代码判断了不允许普通管理员访问,但是user/addUser.jsp这个jsp页面中并没有这个判断逻辑。

因为开发认为只有返回addUser的时候,才会来到这个页面,而要返回addUser,则必须通过超级管理员的验证。

那我们能让一个方法返回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)

刚才我们领教了struts2给我们带来那些属性的好处,现在我们再往后走一步,研究Action方法的返回结果。

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

test"

net.inbreak.TestAction"

redir"

type="

redirect"

${redirecturl}<

这段代码,大家唯一可能看不懂的,就是type="

了。

这是一个urlredirect的方式,struts2为了方便大家开发,把“自定义302跳转到其他url”这种方式给包装了

起来。

只要如上定义,我们就可以在action中写方法:

publicStringredirect(){

然后定义属性

privateStringredirecturl;

当用户打开

的时候,就会302跳转到

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

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

就会跳转到http:

//www.ph4nt0m.org这个钓鱼网站(-_-!

)。

那么如何防御呢?

要防御url跳转到钓鱼网站,我们肯定需要一个白名单机制,或者根本就让他跳转到本站下。

于是有了如下判断:

if(redirecturl.startsWith("

/"

{

可能你看出来了,仅仅判断"

开头,其实是不能杜绝url跳转漏洞的,因为

一样会跳转。

而在这里却足够了,因为struts2已经接管了这个过程,只要以“/”开头,统统先给你自动加上

本地域名,抓包后,你会看到

location:

实际上是不会有问题的。

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

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

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

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

Struts2的那些result类型缺陷(Ajax)

在struts2中使用ajax,也是被struts2支持的,它提供了一种返回类型,叫做“stream”。

在研究这个

result的使用时,作者看到一本书,叫做《Struts2权威指南:

基于WebWork核心的MVC开发》。

这本书非常

出名,几乎所有的struts2使用者都推荐使用。

书上介绍ajax可以这么使用:

配置struts.xml

ajaxtest"

net.inbreak.ajax.TestajaxAction"

resulttype="

stream"

paramname="

contentType"

text/html<

/param>

inputName"

input<

之后写TestajaxAction:

publicInputStreaminput;

publicStringexecute()throwsException{

input=newStringBufferInputStream("

aaaa<

td>

script>

alert("

)<

/script>

aa"

其实大家都看出来我的意思了,返回了contentType为“text/html”的页面,内容为

alert('

kxlzx'

aa

结果浏览器解析的时候,出现了XSS漏洞。

本来默认的contentType是text/plain,不需要配置,如果用户直接打开,只会看到一个Stream,不会解析

其中的html和js。

现在书上介绍说要写成这样,不知道作者是否知道这个教程对大家的影响,结果已经误导了

大批的开发人员。

事实上,这不是struts的问题,是struts“权威”教程的问题。

权威的教程,一旦出现安全漏洞,往往会

误导大批的开发人员,不知道大家在挖漏洞的时候,是否注意到了这点,特别是当官方的DEMO出现漏洞,

那绝对是惊天地泣鬼神的悲剧。

Struts2的那些result类型缺陷(自定的页面)

有时候,开发人员为了方便,喜欢配置struts.xml如下:

user/test.jsp<

testpro"

user/testproperty.jsp<

${redir}<

testloadfilepath"

${testloadfilepath}<

user/redirfalse.jsp<

input"

user/input.jsp<

请注意,其中一条result,名称是”testloadfilepath”,${testloadfilepath}的作用是自定义的jsp页面

地址,接收session或request中传过来的这个变量的值。

那么用户提交

当然就会返回user/test.jsp页面,非常的灵活。

虽然并不是所有的开发都会这么做,但是一旦出现这种情况,

会产生什么问题呢?

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 研究生入学考试

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1