JSON/XML解析本身不导致SQL注入,但解析后字段值若拼接进SQL字符串则会触发注入;唯一可靠防御是参数化查询、动态字段名白名单校验、解析器禁用外部实体。

JSON 或 XML 解析本身不会导致 SQL 注入,但解析后字段值若被拼进 SQL 字符串,就立刻中招——唯一可靠防线是:所有值进 SQL 前必须走参数化路径,动态字段名必须白名单校验,解析器配置必须禁用外部实体。
JSON.parse() 后直接拼 SQL 是最常见踩坑点
很多人以为 JSON.parse() 会“消毒”,其实它只做类型转换,{"id": "1 OR 1=1"} 解析出来仍是字符串 "1 OR 1=1",没删空格、没转义、没校验语义。
- 错误写法:
pool.query("SELECT * FROM users WHERE id = " + data.id)—— 攻击者传{"id": "1; DROP TABLE logs;"}就执行堆叠注入 - 正确做法:
pool.query("SELECT * FROM users WHERE id = ?", [data.id])(MySQL)或pool.query("SELECT * FROM users WHERE id = $1", [data.id])(PostgreSQL) - 嵌套字段也一样危险:
data.user?.name不能直接拼,必须进参数数组;lodash.get(data, 'user.name')不等于安全,只是取值更稳,不解决注入 - ORM 里也要警惕:
User.findOne({ where: { name: `'${data.name}'` } })或sequelize.literal()都等于手动开后门
XML 解析后提取节点值再进 SQL 的关键断点
XML 本身不执行 SQL,但当你用 UPDATEXML()、EXTRACTVALUE() 或手写 XPath 拼接用户输入时,就给了攻击者报错注入或布尔盲注的入口。
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
- 错误链路:接收
<user><phone>123' OR '1'='1</phone></user>→ 用doc.getElementsByTagName('phone')[0].textContent取出字符串 → 拼进"WHERE phone = '" + phone + "'" - 正确链路:先用标准 DOM/SAX 解析器提取文本 → 再作为预编译参数传给
PreparedStatement(Java)或pool.query()(Node.js) - 绝对禁止:
UPDATEXML(?, '/root/phone/text()', '')这类函数调用——?看似参数化,但函数内部仍解析 XPath 表达式,text()位置可被替换为恶意 payload - MySQL 8.0+ 推荐改用
XMLQUERY(),它默认不展开外部实体,且命名空间控制更严
XML 解析器配置不当会放大风险
即使你后续做了参数化,若 XML 解析阶段就被 XXE 或 Billion Laughs 攻击打穿,服务可能先崩溃或泄露文件,SQL 注入反而成了次要问题。
- 必须显式禁用:
http://apache.org/xml/features/disallow-doctype-decl、http://xml.org/sax/features/external-general-entities(Java JAXP) - PHP 中要调
libxml_disable_entity_loader(true),且在simplexml_load_string()前执行 - Python lxml 要传
no_network=True和resolve_entities=False - 上线前加一行快速拦截:
if (/,比等解析器报错更早切断
动态字段名(ORDER BY / GROUP BY)无法参数化,只能白名单硬控
JSON 或 XML 里常带 {"sort_by": "score", "filter": "active"} 这类控制字段,它们不能进参数占位符,因为 SQL 语法要求列名/表名是标识符,不是值。
- 错误做法:
ORDER BY ${data.sort_by}或WHERE status = '${data.filter}'—— 一旦放行sort_by: "score; DROP TABLE sessions;",后果严重 - 正确做法:
const allowedSorts = ["created_at", "score", "name"]; if (!allowedSorts.includes(data.sort_by)) throw new Error("Invalid sort field") - 注意大小写和空格:
"score ASC"不等于"score",白名单需覆盖完整合法组合,或拆成sort_by+sort_order两个字段分别校验 - 别用
Object.keys(schema).includes()动态生成白名单——schema 可能被污染,必须用字面量数组
真正难防的不是解析动作本身,而是解析后那一小段“赋值给变量 → 拼进 SQL 字符串”的代码。它往往藏在中间件、工具函数或旧逻辑里,不走主流程,测试也难覆盖。每次读到 obj[key] = value 或 query += `WHERE ${field} = '${val}'`,都要停下来问一句:这个 val 是不是来自 JSON/XML?有没有可能绕过校验?

















