node防范sql注入

发布时间:2026/9/24 1:25:24

node防范sql注入 node防范sql注入// 写法1字符串拼接 util.format const sql util.format(SELECT * FROM someTable WHERE id %s and name %s, req.params.id, req.params.name); connection.query(sql, function (err, results) {}) // 写法2占位符 ? 参数数组预编译参数化查询 const sql2 SELECT * FROM someTable WHERE id ? and name ?; connection.query(sql2, [req.params.id, req.params.name], function (err, results) {})写法 1util.format❌ 有 SQL 注入漏洞util.format只是普通 JS 字符串格式化替换只是简单把变量文本直接拼进 SQL 字符串不会做数据库转义。攻击示例 假设req.params.name or 11 拼接之后最终 SQL 变成SELECT * FROM someTable WHERE id 1 and name or 11条件恒成立攻击者可以查询全部数据还可以执行;drop table xxx;等恶意语句。⚠️ 注意%s只是 JS 层面字符串替换不是 mysql 的转义函数写法 2? 占位符 参数数组✅ 参数化查询防注入mysql/mysql2 库内部会把 SQL 模板和参数分开交给 MySQL 服务端SQL 模板SELECT * FROM someTable WHERE id ? and name ?先发给 mysql参数数组[id,name]作为独立数据传递不会把参数直接拼到 SQL 语句文本里MySQL 服务端做解析参数永远被当做普通数据值不会被解析成 SQL 语法。即使传入 or 11它只会被当做一个普通字符串值不会破坏 SQL 语法从根源防止 SQL 注入。核心根源把外部可控的用户输入直接拼接到 SQL 语句字符串中。 用户输入url 参数req.params、查询参数req.query、post 请求体req.body、cookie、header这些都是外部可控不可信任。✅安全原则不要在 JS 层拼接 SQL 文本使用占位符?参数化查询把输入当数据不当 SQL 语法。1、模板字符串${}拼接高频踩坑❌不安全代码// 危险模板字符串直接插值 const name req.body.name; const sql SELECT * FROM user WHERE name ${name}; connection.query(sql, (err, res){});不安全原因JS 层面直接把用户变量拼进 SQL 字符串。如果name值为 or 11就会 SQL 注入篡改查询条件。✅纠正使用占位符参数放数组const sql SELECT * FROM user WHERE name ?; connection.query(sql, [req.body.name], (err, res){});2、字符串 加号拼接❌不安全const id req.params.id; const sql delete from user where id id; connection.query(sql, callback);原因用户传入id1 or 11会删除整张表全部数据。✅纠正const sql delete from user where id ?; connection.query(sql, [id], callback);3、util.format/sprintf‑like 格式化工具拼接 SQL刚才你例子❌不安全const sql util.format(select * from user where name%s, req.query.name); connection.query(sql, callback);util.format只是 JS 字符串替换不是数据库转义函数不会处理单引号特殊字符。✅纠正放弃 util.format 拼接 SQL使用?占位符。4、数组 join 拼接动态条件很多人做多条件查询踩坑❌不安全let conds []; if(req.query.name){ conds.push(name${req.query.name}); // 这里直接拼接输入 } if(req.query.status){ conds.push(status${req.query.status}); } const sql select * from user where conds.join( AND ); connection.query(sql, callback);原因conds内部直接拼接用户输入存在注入。✅正确做法条件数组 参数数组分开维护let conds []; let params []; // 专门存放参数 if(req.query.name){ conds.push(name ?); params.push(req.query.name); } if(req.query.status){ conds.push(status ?); params.push(req.query.status); } let sql select * from user; if(conds.length 0){ sql WHERE conds.join( AND ); } connection.query(sql, params, callback);5、直接把用户输入当做表名 / 字段名⚠️重点?占位符不能用于表名、字段名只能用于值❌不安全// 用户传入排序字段直接拼接 const sortField req.query.sortField; const sql select * from user ORDER BY ${sortField}; connection.query(sql,[] , callback);?不能写表 / 字段下面这样写没有效果语法错误const sql select * from user ORDER BY ?; // ❌错误?只代表值不能代表列名不安全原因用户输入字段名 / 表名不受占位符保护可以注入。 攻击sortField id;drop table user;-- ✅纠正白名单校验不直接使用用户输入只允许预设好的字段。// 白名单允许的排序字段 const allowFields [user_id,name,create_time]; let sortField user_id; // 默认 if(allowFields.includes(req.query.sortField)){ sortField req.query.sortField; } const sql select * from user ORDER BY ${sortField}; connection.query(sql, [], callback);这里虽然用了${}但是变量来自白名单不是直接外部输入是安全。6、exec /query 直接接收完整用户输入 SQL极度危险❌不安全// 完全接收用户传过来的SQL语句千万不要写 let sql req.body.sql; connection.query(sql, callback);原因用户可以执行任意 SQL删库、查所有数据。 ✅纠正业务禁止接收完整 SQL 字符串只能写固定模板参数使用占位符。7、手动写 replace 简单过滤单引号企图防注入自以为安全实际不安全❌不安全// 错误自己简单替换单引号不能防御全部注入场景 let name req.query.name.replace(//g,); let sql select * from user where name${name};原因数据库的转义逻辑很复杂要处理\、反斜杠、双字节字符等手写正则永远有漏洞。 ✅纠正不要自己写过滤交给驱动的参数化?处理。安全 不安全总览表表格写法示例风险等级原因修复方案模板字符串插值select * from t where name${x}高危外部输入拼入 SQL 文本?占位符 参数数组加号字符串拼接select * from t where idx高危输入直接拼接 SQL 文本?占位符 参数数组util.format/sprintf 拼接 SQLutil.format(select * where name%s,x)高危只是 JS 字符串替换不做数据库转义?占位符 参数数组join 拼接条件内部插值conds.push(name${x})高危条件片段拼接用户输入分开维护条件数组、参数数组用户输入作为字段 / 表名直接插值order by ${req.query.sort}中危?不支持字段名可注入白名单过滤校验直接接收完整 SQL 语句执行connection.query(req.body.sql)极高危可执行任意 SQL禁止使用固定 SQL 模板手写 replace 过滤单引号x.replace(//g,)高危无法覆盖全部转义场景放弃手写过滤用参数化查询重要两个知识点?占位符只能用来替换【值】不能替换表名、字段名、关键字。 表名、字段名需要用白名单机制校验。参数化查询不是简单的字符串替换驱动把 SQL 模板和参数分开传给 MySQL 服务端参数永远被当做数据不会被解析为 SQL 语法。快速自检口诀用户输入是否直接出现在 SQL 字符串模板里面是 → 大概率不安全用户输入全部放到第二个参数数组 → 安全。拓展ORM 框架Sequelize、TypeORM、MyBatis‑Plus 底层已经封装参数化查询。 但是如果你在 ORM 里面手写raw原生 SQL 时依然会遇到注入风险同样要遵守上面规则。举个 Sequelize 危险例子// ❌raw模式直接拼接输入注入风险 const res await sequelize.query(select * from user where name${req.query.name}) // ✅raw模式参数化 const res await sequelize.query(select * from user where name ? ,{ replacements:[req.query.name] })SQL 注入常见攻击 Payload 示例环境node‑mysql后端直接拼接用户输入没有参数化查询。 注意这些仅用于学习理解原理禁止用于未授权的真实系统前置说明假设接口/getUser?namexxx后端危险代码漏洞版// ❌漏洞代码字符串拼接 const name req.query.name; const sql SELECT * FROM sys_user WHERE name ${name}; connection.query(sql, callback);下面演示不同恶意name参数传入后拼接出来的最终 SQL 和效果。1、条件绕过查询全部数据Payloadname OR 11URL 编码后浏览器传参name%27%20OR%20%271%27%3D%271拼接后 SQLSELECT * FROM sys_user WHERE name OR 11逻辑11永远 true返回 sys_user 表所有用户数据。带注释版本把后面单引号注释掉更常用 Payloadname OR 11 ----是 mysql 注释符号--后面必须有空格后面语句全部注释。 拼接 SQLSELECT * FROM sys_user WHERE name OR 11 -- -- 将原来 SQL 末尾的单引号注释语法不出错。2、联合查询 union select偷其他表数据Payloadname UNION SELECT user_id,user_name,password,status FROM sys_user --拼接后SELECT * FROM sys_user WHERE name UNION SELECT user_id,user_name,password,status FROM sys_user -- 效果利用union联合查询爆出账号密码哈希。union 要求前后查询的列数量一致攻击者会先猜列数。3、删除数据高危Payloadname; DELETE FROM sys_user; --拼接 SQLSELECT * FROM sys_user WHERE name ; DELETE FROM sys_user; -- 分号;结束第一条 select开启新 SQL 语句执行 delete清空用户表。 ⚠️注意mysql 驱动默认multipleStatements是关闭多语句会被拦截如果开启了多语句这个攻击生效。 配置项{multipleStatements: true}千万不要随便开。4、更新篡改数据Payloadname; UPDATE sys_user SET status1 WHERE user_id1; --拼接SELECT * FROM sys_user WHERE name ; UPDATE sys_user SET status1 WHERE user_id1; -- 把管理员账号设置为停用。5、报错注入拿库名表名Payloadname AND updatexml(1,concat(0x7e,database()),1) --利用 mysql 报错函数数据库抛出异常时把当前数据库名称暴露在错误信息里。 拿到库名之后继续爆所有表、字段。6、针对排序 order by 注入前面讲的字段直接拼接漏洞接口/list?sortxxx漏洞后端代码const sort req.query.sort; const sql select * from sys_user order by ${sort};Payloadsortid;drop table sys_role;--拼接 SQLselect * from sys_user order by id;drop table sys_role;--直接删除角色表。这种场景?占位符无效只能白名单校验修复。7、绕过简单过滤的 payload有些开发者简单把替换为空name.replace(//g,)原始输入name OR 11替换掉单引号之后变成name OR 11依然可以注入。证明手写正则替换字符串防御 SQL 注入几乎是不可能的总会被绕过。✅同样 payload使用参数化查询会发生什么安全代码const name req.query.name; const sql SELECT * FROM sys_user WHERE name ?; connection.query(sql, [name], callback);传入 payload OR 11 --MySQL 会把整个 payload 全部当成普通字符串的值去匹配 name 字段。 等价逻辑SELECT * FROM sys_user WHERE name \ OR 11 -- 数据库寻找name字段值等于字符串 OR 11 --的记录几乎没有数据攻击失效。驱动自动转义内部的单引号不会把 payload 解析成 SQL 语法。
延伸阅读

更多相关文章

2026/9/24 1:25:24

语义搜索实战:基于DeepSeekEmbedding的相似度匹配与向量检索

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 1:25:24

offergo 实战:技术面被问到不会的题,怎么体面应对

技术面被问住几乎是每个程序员都会遇到的事。差别只在于,有人被问住之后还能体面地把话题接回来,有人则当场卡死,后面十分钟全在自我怀疑。这篇把应对流程拆成四步,都是可以直接照做的动作。 一、先判断这是「不会」还是「没想清…

2026/9/24 1:25:24

SAP销售BOM配置与实战:从CS61到VA01的完整指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 3:35:31

Cadence IC618+180nm PDK双平衡吉尔伯特混频器仿真全流程

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 3:35:31

BWO-KELM故障诊断实战:白鲸优化算法自动调参与避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 3:35:31

交流信号ADC采样必看:差分加法电路实现直流偏置与增益解耦

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 3:30:31

C 语言函数学习笔记:从入门到实战

1. 什么是函数 今天我们一起走进 C 语言里一个非常核心的概念——函数。你可以把它想象成一个"小工具":我们把一段完成特定功能的代码装进这个工具里,给它起个名字,以后想用的时候,喊一声名字就能直接调用。这样一来&am…

2026/9/23 12:07:00

GAMP 5 基于风险的计算机化系统验证:软件分类与审计追踪实践

简介:《A Risk-Based Approach to Compliant GxP Computerized Systems》即业内熟知的GAMP 5指南,面向制药企业质量与IT合规人员、验证工程师及计算机化系统管理者,用于解决GxP法规环境下系统合规性难以科学落地的问题。文档以风险管理为主线…

2026/9/23 12:06:55

安全托管MSSP实战:从静态防御到人机协同的攻防运营与应急响应

简介:这份PPT围绕互联网业务安全托管服务展开,面向企业安全负责人、IT运维人员及关注MSSP/MSS选型的读者,重点回应传统安全过度依赖人工、碎片化静态防御难以对抗产业化攻击等痛点。资源共1个pptx文件,包体约30.63MB,以…

2026/9/24 0:00:21

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为…

2026/9/24 0:00:21

单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

简介:一份基于单细胞RNA测序数据的细胞类型注释算法研究Python毕业设计源码,针对计算机相关专业正在做毕设或需要项目实战的学习者,可用于课程设计与期末大作业。项目代码完整、经导师指导评审通过,可直接运行,覆盖数据…

2026/9/24 0:00:21

C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

第一次在项目里被反射卡住,是在一个老旧的WinForms模块里:几十个类依赖PropertyChanged通知,运行时反射读属性、发通知,每次启动慢半拍不说,一上.NET Native/AOT裁剪模式几乎全面崩盘。后来我把这段逻辑全部改成C#源生…

2026/9/22 16:34:32

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/22 20:01:30

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/22 13:25:41

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码