前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片NEW
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 业务场景题真实业务问题与追问
  • 查漏补缺常见问题解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
    • AI 定制路线NEW按你的简历现排
    • AI 知识地图NEW串起全站知识点
  • 动态
    • AI 热点NEWAI 每日动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
AI 助手NEW
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片NEW
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 业务场景题真实业务问题与追问
  • 查漏补缺常见问题解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
    • AI 定制路线NEW按你的简历现排
    • AI 知识地图NEW串起全站知识点
  • 动态
    • AI 热点NEWAI 每日动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
AI 助手NEW
旧版
返回 AI 情报前线
All News · 全部资讯8611
  • 自托管Llama部署成本全解析:GPU之外容易被忽视的隐性开销
  • Builder.io开源Agent-Native框架:让人与AI共享同一操作层
  • 让AI编程代理在中断后从断点恢复:session化执行轨迹方案
  • CI如何验证AI代理真的跑了测试而不是伪造结果
  • AI产品定价数学:固定费率如何悄悄亏损
  • ZCode事件:AI编程工具静默上传全部Git历史
  • Anthropic自评:R&D自动化率26%,但完全自主为0
  • 阿里Qwen-Image-2.1:70亿参数开源图像生成拳打闭源模型
  • OWASP CRS 规则引擎:给 LLM 和 MCP 加上 WAF
  • 智谱 MaaS 上线数据不留存机制,可申请开通
  • 如何界定可完成的AI工程范围
  • Cursor中直接查询技术文档的MCP方案
  • AI Agent的过度自信陷阱
  • Cursor与.NET周报:七个实战规则
  • Qwen-Image-2.1开源:7B参数兼顾生图与编辑
  • 阿里开源 Qwen-Image-2.1:7B 参数兼顾透明图生成与多图编辑
  • 免费模型Trace不能支持的五个评估主张
  • AI重构前的副作用冻结术:先录 Ledger 再动格式
  • Agent能改Oracle则Green Build不足为信:独立检查三原则
  • AI编程导致代码质量下降?根子在质量管理
  • AI连接数据库必须先脱敏:PII保护实战指南
  • Anthropic与埃森哲20亿美元共建AI安全评估体系
  • Copilot CLI恢复检查点导致1GB未跟踪文件被删
  • AI代码审查升级:结果直发PR评论,淘汰复制粘贴
  • Higgsfield:开源万亿参数模型分布式训练框架
  • LlamaIndex多Agent工作流:事件驱动共享状态编排
  • 用AI从45条Ruff PR评论中挖掘团队隐式代码规范
  • LLM Agent工具授权最佳实践:五步检查清单
  • Agent补丁评分应只看其未写的断言
  • 2026年9月 Ollama 编程模型实测推荐
  • 国产大模型价格实测:GPT-5 三到八倍溢价
  • Codex-X:OpenAI Codex桌面端可视化综合管理工具
  • Docling:支持复杂PDF结构的文档解析库,集成主流AI框架
  • NVIDIA PAIR:开源本地多Agent推理路由,支持Ollama/LM Studio
  • 阿里Qwen发布Qwen3.8-LiveTranslate:60语言实时翻译,延迟仅2.3秒
  • Supermemory:AI记忆与上下文引擎开源实现
  • OpenSpec:AI编程时代的规格驱动开发框架
  • MCP Agent工具集成测试实战指南
  • Claude Code 在 Zed 中的 ACP 协议传输机制实测
  • 已加载 39 / 8611
8.0
热点
AI SCORE
技术实践2026-09-21 00:09

OWASP CRS 规则引擎:给 LLM 和 MCP 加上 WAF

dev.to · AI#安全#LLM#Agent
Editor brief · 编辑速览

Solo Enterprise 将 OWASP CRS 规则引擎 Coraza 应用于 LLM prompt 检查和 MCP 工具调用,在不修改 agent 的前提下实现企业级安全治理。

文章思维导图
Knowledge map
拖拽缩放
Full translation

完整中文译文

传统的 Web 应用防火墙读取 URL、一些请求头,也许还有一个表单 body。但对于 Agent 流量而言,这搞错了层级——真正有意义的内容在请求体里:LLM 调用的 prompt,MCP 调用的方法名、工具名和参数。

Solo Enterprise for agentgateway 运行的是 Coraza,这是 OWASP 维护的规则引擎,作为共享扩展。开启 body 检查后,安全团队已经熟悉如何分析的 OWASP Core Rule Set 就能应用到 prompt 和工具调用上,SOC 可以在 SecLang 中添加自己的签名,而无需触碰任何 Agent、模型或 MCP server。

策略文件位于 msquared/agentic-demo 下的 manifests/governance/。下面的每一个状态码都来自 v2026.8.2 的真实集群。

让 body 检查真正生效的配置

两个设置缺一不可,漏掉任何一个都会导致 WAF 看起来健康但放行所有 payload。

apiVersion: waf.solo.io/v1alpha1
kind: WAFPolicy
metadata:
  name: governed-llm-waf
  namespace: agentgateway-system
spec:
  processingConfig:
    request:
      mode: HeadersAndBody          # 1. buffer the body at all
  coreRuleSet:
    settings:
      inline: |
        SecDefaultAction "phase:1,log,auditlog,deny,status:403"
        SecDefaultAction "phase:2,log,auditlog,deny,status:403"
        SecAction "id:900990,phase:1,pass,t:none,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.23.0',setvar:tx.crs_setup_version=4230"
  ruleEngineSettings:
    inline: |
      SecRuleEngine On
      SecAuditEngine RelevantOnly
      SecAuditLog /dev/stdout
      SecAuditLogFormat JSON
      SecAuditLogParts AKHZ
      # 2. parse the JSON body into ARGS so rules can see prompt fields
      SecRule REQUEST_HEADERS:Content-Type "^application/json" \
        "id:200001,phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON"

mode: HeadersAndBody 让 body 可用。规则 200001 让 body 结构化:没有 JSON body processor 的话,body 就是一个不透明的大 blob,基于 ARGS 匹配的规则根本无从下手。加上它之后,一个 chat completions 请求就变成了可寻址的字段,ARGS 能覆盖 json.model、json.messages.0.content 以及文档中的所有其他内容。

自定义签名与 CRS 并列放置。以下三条是 AI 专用的,规则 ID 段是为它们预留的:

  customDirectives:
  - inline: |
      SecRule ARGS "@rx (?i)ignore\s+(all\s+)?(previous|prior|above)\s+instructions" \
        "id:9001,phase:2,deny,status:403,log,msg:'LLM prompt injection: instruction override'"
      SecRule ARGS "@rx (?i)\b(DAN|developer)\s+mode\b|\bjailbreak\b" \
        "id:9002,phase:2,deny,status:403,log,msg:'LLM jailbreak framing'"
      SecRule ARGS "@rx (?i)(print|reveal|show|repeat)\s+(your|the)\s+(system\s+prompt|hidden\s+instructions)" \
        "id:9003,phase:2,deny,status:403,log,msg:'LLM system-prompt exfiltration attempt'"

将策略绑定到路由是另一个资源,这意味着一个 WAFPolicy 可以被多个路由复用:

apiVersion: enterpriseagentgateway.solo.io/v1alpha1
kind: EnterpriseAgentgatewayPolicy
metadata:
  name: governed-llm-waf
  namespace: agentgateway-system
spec:
  targetRefs:
  - group: gateway.networking.k8s.io
    kind: HTTPRoute
    name: governed-llm
  traffic:
    entWAF:
      wafPolicyRef:
        name: governed-llm-waf

在 LLM 路由上会被拦截什么

每一行都是同一个认证用户,所以唯一变化的只有 payload:

最后三条是标准 CRS,没有任何 AI 专属配置。承载 LLM 流量的网关仍然是一个 HTTP 端点,和其他端点一样被扫描。

调用方看到的内容由你配置,返回简洁的信息比详细描述更好:

{"error":{"type":"policy_violation","message":"Request blocked by the enterprise AI WAF policy."}}

详情应该放在审计日志里,而不是放在响应体中——那是攻击者用来调整下一次尝试的素材。

关于误报问题,在被问到之前就回答

任何有 WAF 运维经验的人首先会问:这会对正常流量造成什么影响?Prompt 文本往往很长、不可预测,且充满了在上下文中看起来像恶意内容的字符串。因此测试套件包含了一个刻意刁钻但完全真实的工程 prompt:SQL 关键字、带查询参数的 URL、诊断码和固件版本。

curl -s -o /dev/null -w '%{http_code}\n' localhost:8081/governed-llm/v1/chat/completions \
  -H "Authorization: Bearer $TOKEN" -H 'content-type: application/json' \
  -d '{"model":"acme-standard","max_tokens":30,"messages":[
       {"role":"system","content":"You are a helpful assistant for platform engineers."},
       {"role":"user","content":"Summarize in two sentences: our device logs show intermittent bus errors (code 639, severity 9) on the v2 platform after firmware 2.4.1; the SELECT statement in our telemetry pipeline returns duplicates; and the admin portal at https://example.com/portal?id=42&view=full times out under load."}]}'

返回 200。这个单独的 case 值得放入 CI,因为一旦有人提高了 CRS paranoia 级别或添加了一条宽泛的自定义规则,这个请求就会告诉他们代价是什么。

同一道防火墙用在 MCP 前面

这是我之前没见过有人做的部分。MCP 是基于 HTTP 的 JSON-RPC,所以一旦 body 被解析,WAF 就能寻址协议自身的结构:json.method、json.params.name 以及 json.params.arguments 下的每一个条目。

两条自定义规则覆盖了 MCP 专属的场景:

  customDirectives:
  - inline: |
      # 9101 - JSON-RPC method allowlist
      SecRule ARGS:json.method "!@rx ^(initialize|notifications/initialized|ping|tools/list|tools/call)$" \
        "id:9101,phase:2,deny,status:403,log,msg:'MCP method not allowlisted'"
      # 9102 - prompt injection inside any tool argument
      SecRule ARGS:/^json\.params\.arguments\./ "@rx (?i)ignore\s+(all\s+)?(previous|prior|above)\s+instructions" \
        "id:9102,phase:2,deny,status:403,log,msg:'MCP tool argument carries prompt injection'"

在受治理的路由上打开一个真实的 MCP 会话,然后向它发送混合的诚实和恶意调用:

诚实的调用返回应有的结果:

{"jsonrpc":"2.0","id":8,"result":{"content":[{"type":"text",
 "text":"Weather in Portland: Temperature: 77 F, Humidity: 87%, Wind: 14.2 mph"}],"isError":false}}

被拦截的调用得到的是 JSON-RPC 格式的错误而非原始 HTML,这对 MCP client 必须解析它而言很重要:

{"jsonrpc":"2.0","error":{"code":-32000,"message":"Request blocked by the enterprise MCP WAF policy."}}

表格中的第三行和第四行是我认为最有说服力的两个例子。这两条都不是专门为 MCP 写的规则。city 参数里的 ../../etc/passwd 是路径遍历,script 标签是 XSS,不管谁发送的以及出现在哪个字段里。一旦参数可以被解析,二十年积累的 CRS 签名就立即生效了。

方法白名单是协议层面的最小权限

规则 9101 是我会优先放在每个 MCP 路由上的第一条规则,甚至在任何内容签名之前。

MCP server 暴露的不只是工具。协议中还有 resources、prompts、sampling 和 completion 方法,而给定的 client 通常只需要其中一小部分。一个只需要调用工具的 client 只需要五个方法。其他一切都是协议定义中存在但没有人真正需要的攻击面。

上表中 resources/list 返回 403 就是这条规则在起作用。网关背后的 MCP server 仍然实现了这个方法,只是 client 无法触及它,而且这个决定在联系 server 之前就做出了。

这和网络团队在允许四个端口而不是全量端口时的思路完全一致。它可以干净地迁移到工具协议上,而且不同于授权策略,它不需要身份模型就能发挥作用。

WAF 记录了什么

拦截的价值取决于审计跟踪的质量。配置了 SecAuditLogFormat JSON 和 SecAuditLog /dev/stdout 后,每一次干预都会落在 WAF server 的日志中,消息会指明触发的是哪条规则:

kubectl logs deploy/waf-server-enterprise-agentgateway -n agentgateway-system \
  --since=3m | grep -oE '"msg":"[^"]*"' | sort | uniq -c | sort -rn
   2 "msg":"MCP method not allowlisted"
   1 "msg":"XSS Attack Detected via libinjection"
   1 "msg":"SQL Injection Attack Detected via libinjection"
   1 "msg":"Path Traversal Attack (/../) or (/.../)"
   1 "msg":"MCP tool argument carries prompt injection"
   1 "msg":"LLM prompt injection: instruction override"
   1 "msg":"LLM jailbreak framing"
   1 "msg":"Found User-Agent associated with security scanner"

自定义规则和 CRS 规则以相同的格式出现在同一个流中,这让已经熟悉 ModSecurity 或 CRS 仪表板的团队可以直接使用。同一个 server 上有 Prometheus 计数器:

waf_server_requests_total{action="allow",reason=""} 64
waf_server_requests_total{action="deny",reason="waf_blocked"} 77
waf_server_policy_status{name="governed-llm-waf",status="active"} 1

执行顺序,以及一个值得知道的失败模式

WAF 不是请求遇到的第一个环节。在这条路由上,执行顺序是:JWT 认证 → CEL 授权 → WAF。匿名调用者得到 401,策略拒绝的调用者得到 403,防火墙根本不会运行。因此 WAF 拦截的一切都是已认证、已授权用户发出的恶意 payload,这比来自互联网的原始拦截计数要有意义得多。

我在《agentgateway CEL 踩坑记》两篇中写过这道前置的授权层,其中一篇描述了一个策略看似应该拒绝但实际静默放行了请求的坑。在你依赖那层来过滤到达 WAF 的流量之前,值得一读。

需要知道的失败模式:无效的 WAFPolicy 会导致 Fail Closed。规则编译不通过时,路由会得到 HTTP 500 而不是让流量无过滤地通过。这是正确的默认行为,意味着 WAF 变更后出现 500 几乎一定是编译错误而不是运行时拦截:

kubectl describe wafpolicy governed-llm-waf -n agentgateway-system
# check status.conditions[type=Ready]

运行demo

./setup.sh              # k3d cluster, mesh, gateway, agents (~15 min)
./port-forward.sh
./governance-demo.sh --act 3

Act 3 同时应用两条策略并执行上面两个表中的每一个请求,在状态码旁边打印预期结果。--check 以非交互方式运行整个治理流程并断言 24 个结果。

它需要 Solo Enterprise 许可证,因为 WAFPolicy 和 EnterpriseAgentgatewayPolicy 是企业级 CRD。规则本身是纯 SecLang 和 OWASP CRS,所以签名可以移植到任何 Coraza 或 ModSecurity 部署。网关提供的是位置优势:所有 LLM 和 MCP 请求已经必经的一个集中点,而且 body 已经解析好了。

下一步:当你停止一个已经做了你不喜欢的事情的 Agent 时,这条记录会变成什么样。

常见问题

Web 应用防火墙能检查 LLM prompt 吗?

可以,前提是开启了 request body 检查且 body 被解析为 JSON。将 processingConfig.request.mode 设为 HeadersAndBody,并添加一条带有 ctl:requestBodyProcessor=JSON 的 Coraza 规则,就能把 chat completions body 变成可检查的 ARGS,这样 OWASP Core Rule Set 规则和自定义 SecLang 签名都能针对 prompt 文本进行评估,而不只是 URL 和请求头。

如何将 OWASP CRS 应用到 MCP 工具调用上?

MCP 是基于 HTTP 的 JSON-RPC,所以同一个支持 body 的 WAF 能看到方法名、工具名以及每个工具参数作为 JSON 字段。CRS 规则然后针对参数值进行评估,这就是为什么 city 参数包含 ../../etc/passwd 会被识别为路径遍历,包含 script 标签会被识别为 XSS,而无需对 MCP server 做任何改动。

如何限制 MCP client 可以调用哪些方法?

写一条 Coraza 规则,用正则对 JSON-RPC 方法字段做否定匹配,例如 SecRule ARGS:json.method 配合 !@rx 只匹配 initialize、notifications/initialized、ping、tools/list 和 tools/call。列表之外的任何方法(如 resources/list 或 prompts/get)都会在网关处被 403 拒绝,在 MCP server 被联系之前就执行。这是协议层面的最小权限,在联系 server 之前就强制执行。

原文正式版本(含机器可读 markdown)见 https://webofmike.com/waf-for-llm-and-mcp-traffic/index.md

Original source

本文由 AI 翻译整理自 dev.to · AI,原文版权归原作者所有。

阅读英文原文
上一篇
阿里Qwen-Image-2.1:70亿参数开源图像生成拳打闭源模型
下一篇
智谱 MaaS 上线数据不留存机制,可申请开通