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 语法。

相关新闻

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

语义搜索实战:基于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:15 阅读更多 →
offergo 实战:技术面被问到不会的题,怎么体面应对

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

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

2026/9/24 1:25:15 阅读更多 →
零基础搭建DeepSeek API调用监控看板:从日志埋点到可视化

零基础搭建DeepSeek API调用监控看板:从日志埋点到可视化

/* 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:24:14 阅读更多 →

最新新闻

工业无线通信模块哪个品牌靠谱?2026 选型避坑指南

工业无线通信模块哪个品牌靠谱?2026 选型避坑指南

核心结论工业无线通信模块选型,品牌可靠性需从抗干扰、稳定性、认证资质、服务支持四个维度综合评估,而非只看参数表。据中国信通院数据,2026 年国内物联网通信市场规模预计约 1.87 万亿元,工业物联网贡献约 1.98 万亿元。工程师常…

2026/9/24 8:47:01 阅读更多 →
EMC检测费用七层动态模型解析

EMC检测费用七层动态模型解析

/* 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 8:47:01 阅读更多 →
4针风扇PWM调速电路设计:从原理到PCB实战

4针风扇PWM调速电路设计:从原理到PCB实战

/* 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 8:47:01 阅读更多 →
【Pi 超轻量插件】让 Jev 去掉无用的工具调用结果,留一个清爽的上下文!

【Pi 超轻量插件】让 Jev 去掉无用的工具调用结果,留一个清爽的上下文!

背景与痛点 长会话里那些“食之无味”的历史工具输出 在使用 AI 进行较复杂的重构或排查任务时,都会遇到上下文过多压缩的情况。 在 Pi 中虽然说有压缩命令,但我们可以看看他具体压缩了些什么。 如果你用 Pi 跑过时间稍长的任务,大概清楚那个…

2026/9/24 8:47:01 阅读更多 →
PaddleNLP T5 模型家族全解析:预训练权重清单与源码级使用指南

PaddleNLP T5 模型家族全解析:预训练权重清单与源码级使用指南

人工智能大模型预训练微调LoRARLHF强化学习分布式训练 【免费下载链接】PaddleNLP Easy-to-use and powerful LLM and SLM library with awesome model zoo. 项目地址: https://gitcode.com/gh_mirrors/pa/PaddleNLP 点击查看 免费下载 T5(Text-to-Text…

2026/9/24 8:47:01 阅读更多 →
DiT详解

DiT详解

前言 在Sora[1]的技术报告中,作者指出Sora是一个Diffusion Transformer。这个Diffusion Transformer便是我们这里将要介绍的DiT[2]。相较于我们之前介绍的LDM[3],DiTs也是作用在潜空间,它最大的改进是将U-Net的CNN替换为了Transformer。同时…

2026/9/24 8:46:01 阅读更多 →

日新闻

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

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

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

2026/9/24 0:00:19 阅读更多 →
单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

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

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

2026/9/24 0:00:19 阅读更多 →
C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

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

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

2026/9/24 0:00:19 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/23 4:55:02 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/23 4:49:06 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/23 9:53:41 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/23 9:53:40 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/23 9:53:40 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/23 9:53:40 阅读更多 →