Tomcat 配置了两个 Connecto,它们分别是 HTTP 和 AJP :HTTP 默认端口为 8080,处理 http 请求,而 AJP 默认端口 8009,用于处理 AJP 协议的请求,而 AJP 比 http 更加优化,多用于反向、集群等,漏洞由于 Tomcat AJP 协议存在缺陷而导致,攻击者利用该漏洞可通过构造特定参数,读取服务器 webapp 下的任意文件以及可以包含任意文件,如果有某上传点,上传图片马等等,即可以获取 shell。
Apache Tomcat 6
Apache Tomcat 7 < 7.0.100
Apache Tomcat 8 < 8.5.51
Apache Tomcat 9 < 9.0.31
https://github.com/0nise/CVE-2020-1938
https://github.com/nibiwodong/CNVD-2020-10487-Tomcat-ajp-POC
https://github.com/Kit4y/CNVD-2020-10487-Tomcat-Ajp-lfi-Scanner
https://github.com/YDHCUI/CNVD-2020-10487-Tomcat-Ajp-lfi/
1. 如未使用 Tomcat AJP 协议:
如未使用 Tomcat AJP 协议,可以直接将 Tomcat 升级到 9.0.31、8.5.51 或 7.0.100 版本进行漏洞修复。
如无法立即进行版本更新、或者是更老版本的用户,建议直接关闭 AJPConnector,或将其监听地址改为仅监听本机 localhost。
具体操作:
(1)编辑
(2)将此行注释掉(也可删掉该行)
(3)保存后需重新启动,规则方可生效。
1. 如果使用了 Tomcat AJP 协议:
建议将 Tomcat 立即升级到 9.0.31、8.5.51 或 7.0.100 版本进行修复,同时为 AJP Connector 配置 secret 来设置 AJP 协议的认证凭证。例如(注意必须将 YOUR_TOMCAT_AJP_SECRET 更改为一个安全性高、无法被轻易猜解的值):
如无法立即进行版本更新、或者是更老版本的用户,建议为 AJPConnector 配置 requiredSecret 来设置 AJP 协议认证凭证。例如(注意必须将 YOUR_TOMCAT_AJP_SECRET 更改为一个安全性高、无法被轻易猜解的值):
根据一位小伙伴(文章评论的第一位小伙伴)的反馈,又重新查了下Apache的反向代理方式,发现主要有以下三种:
1、jk方式集成 //此方式支持AJP进行参数配置(小伙伴提供)
2、ajp_proxy //此方式目前没有找到相关配置方案
3、http_proxy //此方式无需ajp,可以直接将ajp关闭
jk方式配置依照配置文件应该是(待验证,配置方法可以参考这边文章->传送门):
在worker.properties 文件中添加worker.secrect=YOUR_TOMCAT_AJP_SECRET
1.启用模块
打开 httpd.conf 启动如下模块:
LoadModule headers_module modules/mod_headers.so
2.在 conf 目录下新增配置文件 balance.conf,内容如下:
#提供基础的代理功能
LoadModule proxy_module modules/mod_proxy.so
#提供负载均衡的功能
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
#代理http协议
LoadModule proxy_http_module modules/mod_proxy_http.so
#负载均衡的算法模块
LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so
LoadModule slotmem_shm_module modules/mod_slotmem_shm.so
#兼容低版本访问
LoadModule access_compat_module modules/mod_access_compat.so
ProxyRequests Off
#启用类似ip_hash机制配置
ProxyPreserveHost on
Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED
#代理关联配置loadfactor可以分发请求权重,loadfactor越大,权重越大
BalancerMember http://localhost:8001 loadfactor=1 route=tomcat7_1
BalancerMember http://localhost:8002 loadfactor=1 route=tomcat7_2
#热部署,当着备份服务,当tomcat7_1和tomcat7_2死掉的时候,就自动访问tomcat7_3
#BalancerMember http://localhost:9080 loadfactor=1 route=tomcat7_3 status=+H
#启用类似ip_hash机制配置
ProxyPass / balancer://mycluster/ stickysession=ROUTEID nofailover=On
#负载均衡控制台,通过http://localhost/balancer-manager 访问
SetHandler balancer-manager
Order Deny,Allow
Allow from all
#Allow from localhost
3.httpd.conf 引入步骤 2 中的配置文件
include conf/balance.conf
4.重启 Apache
5.附赠测试 session 保持的 JSP 页面一枚
<%@ page contentType="text/html; charset=GBK" %>
<%@ page import="java.util.*" %>
Cluster Test8002
this is tomcat3!!
<%
out.println(" SESSION ID : " + session.getId()+"
");
String name = request.getParameter("name");
if (name != null && name.length() > 0) {
String value = request.getParameter("value");
session.setAttribute(name, value);
}
out.print("");
out.print("session key session value ");
Enumeration names = session.getAttributeNames();
while (names.hasMoreElements()) {
String key = names.nextElement();
String value = session.getAttribute(key).toString();
System.out.print(key + " --- " + value);
out.print(""+key+" "+value+" ");
}
out.print("
");
%>