终于有时间复现一下经典老洞s2-001了,写个笔记和复现时的心路历程
s2-001漏洞复现
环境搭建
漏洞复现及分析
基础知识:
OGNL表达式
大致流程如下:
从index.jsp的<s:textfiled>
进入struts2-core-2.0.1.jar的ComponentTagSupport.class的doEndTag
函数中
再进入UIBean.class的end
函数中
再进入evaluateParams
函数中,在276行,进入findvalue
函数
进入TextParseUtil.class的translateVariables
函数
最后,在translateVariables
中的55行执行了命令
poc解释:
网上的漏洞分析其实已经很多了,主要是一些关键的判断点,正常时和执行命令时会有哪些不同
在进入evaluateParams函数时,由于会给其this.name进行赋值
导致后面由于value为空,对username添加了%{}
成为了表达式的格式。
对其进行评估过后,会将传入的username参数的值赋给对象o(这里我们可以看到,如果表达式不是以%{开头,也就是传入的值正常时,会进入return。)
此时expression为%{4+5},且并没有进行return,也就是说会继续上面的步骤进行循环,直到expression不为表达式为止。
但此时,请看,由于expression依然是表达式的形式,于是它将%{4+5}
当成表达式进行了执行
于是就有了s2-001这个漏洞。而且由于while始终为True,所以在外面套多少层%{}都能执行。
下面贴一个没加%{}
的,蓝色为运行位置,和上面的区别一看就知道:
命令执行解释:
如果要命令执行,就涉及到OGNL的一些概念了,由于我学的也不是很深,写的可能不是很好,所以希望大佬轻喷。
比如下面的命令执行(在逗号处用了回车,这样分析起来更好看一些,用的时候最好别这么写)
1 | %{ |
1 | # 取非根元素值,#a可以看作一个变量 |
一点碎碎念
其实想整这玩意很久了,毕竟是个经典老洞,但公司事有点多,有时候复现到一半又去干活了,加上下班回家后就很难有学习欲望,就搁置了很久。现在看来其实这个洞还算是蛮好理解的。复现这洞的时候,乱看一通,很难找到重点,尤其是findValue,因为有很多赋值操作,所以findValue进进出出,有点难把握,加上对OGNL不是很懂。看了好几遍,加上网上其他师傅的复现文章才明白漏洞位置和关键点。找到关键点后有一种醍醐灌顶的感觉,很爽。
- 本文作者: Sn1pEr
- 本文链接: https://sn1per-ssd.github.io/2021/09/10/struts2-s2-001复现/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!