diff --git a/README.md b/README.md index 9aefd31..16324b8 100644 --- a/README.md +++ b/README.md @@ -8,5 +8,9 @@ ![Tomcat内存马扫描结果展示](doc/listener.png) +增加websocket型内存马检测,如果不存在endpoint则不显示 + +![Tomcat内存马扫描结果展示](doc/endpoints.png) + ## 0x03 更多 [Filter/Servlet型内存马的扫描抓捕与查杀](https://gv7.me/articles/2020/filter-servlet-type-memshell-scan-capture-and-kill/) \ No newline at end of file diff --git a/doc/endpoints.png b/doc/endpoints.png new file mode 100644 index 0000000..83920cd Binary files /dev/null and b/doc/endpoints.png differ diff --git a/tomcat-memshell-scanner.jsp b/tomcat-memshell-scanner.jsp index 557b985..53afa1c 100644 --- a/tomcat-memshell-scanner.jsp +++ b/tomcat-memshell-scanner.jsp @@ -1,14 +1,14 @@ <%@ page import="java.net.URL" %> <%@ page import="java.lang.reflect.Field" %> -<%@ page import="java.util.HashMap" %> <%@ page import="com.sun.org.apache.bcel.internal.Repository" %> <%@ page import="java.net.URLEncoder" %> -<%@ page import="java.util.Map" %> <%@ page import="org.apache.catalina.core.StandardWrapper" %> <%@ page import="java.lang.reflect.Method" %> -<%@ page import="java.util.ArrayList" %> -<%@ page import="java.util.List" %> <%@ page import="java.util.concurrent.CopyOnWriteArrayList" %> +<%@ page import="javax.websocket.server.ServerEndpointConfig" %> +<%@ page import="javax.websocket.server.ServerContainer" %> +<%@ page import="java.util.concurrent.ConcurrentHashMap" %> +<%@ page import="java.util.*" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> @@ -155,6 +155,27 @@ return listenerList; } + public synchronized List getEndpointConfigs(HttpServletRequest request) throws Exception { + ServerContainer sc = (ServerContainer) request.getServletContext().getAttribute(ServerContainer.class.getName()); + Field _configExactMatchMap = sc.getClass().getDeclaredField("configExactMatchMap"); + _configExactMatchMap.setAccessible(true); + ConcurrentHashMap configExactMatchMap = (ConcurrentHashMap) _configExactMatchMap.get(sc); + + Class _ExactPathMatch = Class.forName("org.apache.tomcat.websocket.server.WsServerContainer$ExactPathMatch"); + Method _getconfig = _ExactPathMatch.getDeclaredMethod("getConfig"); + _getconfig.setAccessible(true); + + List configs = new ArrayList<>(); + Iterator> iterator = configExactMatchMap.entrySet().iterator(); + + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + ServerEndpointConfig config = (ServerEndpointConfig)_getconfig.invoke(entry.getValue()); + configs.add(config); + } + return configs; + } + public String getFilterName(Object filterMap) throws Exception { Method getFilterName = filterMap.getClass().getDeclaredMethod("getFilterName"); getFilterName.setAccessible(true); @@ -318,45 +339,87 @@ } out.write(""); - List listeners = getListenerList(request); - if (listeners == null || listeners.size() == 0) { - return; + List listeners = null; + try { + listeners = getListenerList(request); + } catch (Exception e) { + throw new RuntimeException(e); } - out.write(""); - List newListeners = new ArrayList<>(); - for (Object o : listeners) { - if (o instanceof ServletRequestListener) { - newListeners.add((ServletRequestListener) o); + if (listeners != null && listeners.size() != 0) { + out.write(""); + List newListeners = new ArrayList<>(); + for (Object o : listeners) { + if (o instanceof ServletRequestListener) { + newListeners.add((ServletRequestListener) o); + } } + + // Scan listener + out.write("

Listener scan result

"); + out.write("\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " "); + + int index = 0; + for (ServletRequestListener listener : newListeners) { + out.write(""); + out.write(String.format("" + , index + 1 + , listener.getClass().getName() + , listener.getClass().getClassLoader() + , classFileIsExists(listener.getClass()) + , listener.getClass().getName() + , listener.getClass().getName())); + out.write(""); + index++; + } + out.write("
IDListener classListener classLoaderListener class file pathdump classkill
%d%s%s%sdumpkill
"); } - // Scan listener - out.write("

Listener scan result

"); - out.write("\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " "); + // Scan Endpoints + List configs = null; + try { + configs = getEndpointConfigs(request); + } catch (Exception e) { + throw new RuntimeException(e); + } + if (configs != null && configs.size() != 0) { + out.write("

Endpoints scan result

"); + out.write("
IDListener classListener classLoaderListener class file pathdump classkill
\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " "); - int index = 0; - for (ServletRequestListener listener : newListeners) { - out.write(""); - out.write(String.format("" - , index + 1 - , listener.getClass().getName() - , listener.getClass().getClassLoader() - , classFileIsExists(listener.getClass()) - , listener.getClass().getName() - , listener.getClass().getName())); - out.write(""); - index++; + int index = 0; + for (ServerEndpointConfig cfg : configs) { + out.write(""); + out.write(String.format("" + , index + 1 + , cfg.getPath() + , cfg.getEndpointClass().getName() + , cfg.getEndpointClass().getClassLoader().getClass().getName() + , classFileIsExists(cfg.getEndpointClass()) + , cfg.getEndpointClass().getName() + , cfg.getEndpointClass().getName())); + out.write(""); + index++; + } + out.write("
IDURI pathEndpoint classEndpoint classLoaderEndpoint class file pathdump classkill
%d%s%s%sdumpkill
%d%s%s%s%sdumpkill
"); } - out.write(""); } %>