支付附言中的XSS漏洞:AI辅助编程时代的渲染边界
先问一个真实的业务场景:你在网银里发起一笔转账,收款人信息之外,还有一栏叫“附言”或“付款说明”。大多数时候,我们只会在里面填“房租”“货款尾款”“工单号 20240501”这类普通文本。开发者看到这个字段的第一反应通常是:这不过是一段短文本,还能闹出什么幺蛾子?
但真正做过银行系统、支付系统、或任何带有“资金流 + 后台管理”的系统的人,会在这个字段上多停几秒。因为“支付附言”有两个其他字段不太常见的特点:它完全由用户控制,它会被系统复制到多个不同的展示位置。更关键的是,这些展示位置里往往包括运营人员、风控人员、审计人员使用的高权限后台。于是,当一段附言被当作“可信任的 HTML”插入某个页面时,一次普通的转账操作,就可能变成一次隐藏的脚本投递。
这个思路,正是 "Banking AI XSS: The exploit is in the payment reference" 想表达的核心。它不是在讲 AI 会主动发起攻击,而是在讲:在 AI 辅助编程普及之后,生成一个带有 XSS 漏洞的支付附言渲染逻辑,成本低到了几乎可以忽略。我们真正要解决的问题,已经不是“哪里会有 XSS”,而是“在 AI 生成代码的新工作流里,怎么让人和代码都守住渲染边界”。
1. 为什么“支付附言”会被低估成一个安全输入点
在业务上,附言的定义非常朴素:交易说明文字。产品文档通常会写“用于描述交易目的,方便双方核对”。于是研发侧的实现也相当朴素:一个文本框,一个长度限制,数据库里一个 varchar。很多人从没想过在这上面做 XSS 防护,因为“我们只是把这段文本显示出来而已”。
问题就出在这个“只是显示出来”。从安全视角看,一个输入字段具备两个特征时就值得警惕:第一,它的值是否来自不可信方;第二,它的值是否会在多个偏离输入点的位置被回显或持久化展示。支付附言把这两条都占齐了。
1.1 开发者视角:它只是一个短文本字段
站在开发者的角度,附言看起来简单得多。校验通常只需要关心长度、是否必填、是否允许特殊符号。不少项目甚至会允许用户填写任意字符,包括 <、>、/、& 这些对 HTML 来说很敏感的符号。之所以允许,是因为业务上确实有用户要在附言里写“合同编号 #2024-005/AB&C”,你总不能把合法的业务文本拦掉。
这个取舍本身没有错。真正的漏洞不产生于“允许了特殊字符”,而在于“允许了特殊字符之后,没有在每一个展示它的地方做对应的编码”。开发者关心的是“这个字段能不能保存”,安全人员关心的是“这个字段会出现在哪些页面、哪些上下文、以什么方式被插入”。当这两套关心没有对齐时,附言就会变成一个隐藏的注入源。
还有一点容易被忽略:附言的入口并不只有网页一个渠道。移动 App、开放银行 API、对公批量导入、甚至人工客服代录,都可能向同一个附言字段写入内容。不同渠道的校验规则往往不一致,文件导入的清洗逻辑通常最薄弱。这意味着,“我限制了网页端的输入格式”并不能代表“全渠道的附言都安全”。
1.2 一个输入,多个渲染出口
附言的真正特殊性,在于它进入系统后会被复制到很多地方。每增加一个展示点,就增加一个需要做编码决策的地方。这里列一份常见清单:
| 渲染出口 | 典型场景 | 出错后果 |
|---|---|---|
| HTML 交易流水页 | 用户查看自己的收支记录 | 普通用户浏览器执行脚本 |
| HTML 管理后台 | 运营、风控、审计查看交易明细 | 高权限后台被脚本接管,风险最大 |
| 邮件 / 短信通知 | 向收款方发送到账提醒 | 邮件客户端渲染 HTML 时触发 |
| PDF 对账单 | 生成电子回单、月结单 | 模板拼接时引入注入点 |
| API JSON 响应 | SPA 或移动端通过接口拿到交易数据 | 前端用 innerHTML 渲染时触发 DOM XSS |
| AI 交易摘要 | 大模型生成交易说明并渲染到页面 | 新增的、最容易被遗忘的渲染上下文 |
注意最后一行。现在的银行类应用开始把大模型接入交易辅助功能:AI 根据附言生成“这笔钱是什么用途”的摘要,或者 AI 助手在聊天窗口里把交易明细展示给用户。这些 AI 编排的界面同样要把附言当成 HTML 或文本渲染出来。如果没有把输出编码规则传给新的渲染组件,等于在原本已经收敛好的攻击面上重新开了一道口子。
1.3 管理后台是最危险的出口
在所有这些出口里,管理后台的风险等级最高。原因有三层。
第一,管理后台的使用者权限更高。运营人员不仅能看到交易,还能做调账、标记、审批、导出等操作。如果脚本在管理员浏览器里执行,攻击者拿到的不是普通用户的会话,而是接近后台管理员的操作能力。第二,管理后台的内容更集中。一条带有恶意附言的交易,可能