Go项目中如何修复SQL注入漏洞与安全防护
时间:2026-08-21 | 作者:电竞小硕 | 阅读:0Go中SQL防注入必须用参数化查询(或$1),禁用字符串拼接;ORDER BY等结构化部分需白名单校验;GORM Raw()不自动防护动态拼接;所有用户输入均须统一参数化+白名单。
db.Query 和 db.Exec 必须用 或 $1,不能拼字符串
Go 本身不防注入,防注入靠的是你有没有把用户输入当“值”传进去。只要写 db.Query("SELECT * FROM users WHERE name = '" + name + "'"),就等于把数据库钥匙塞给攻击者。
正确的做法是让驱动来负责参数绑定:db.Query("SELECT * FROM users WHERE name = ", name)(MySQL/SQLite)或者 db.Query("SELECT * FROM users WHERE name = $1", name)(PostgreSQL)。驱动会将SQL模板和参数分开进行发送,即使用户输入 admin' OR '1'='1,也只会被当作一个字符串值,不会引发语法解析。
- 占位符写错(比如 MySQL 里写
$1)不会报错,但参数会被忽略,查不到数据或意外匹配字面量$1 fmt.Sprintf、strconv.Itoa、+拼接一律禁止,哪怕加了单引号也没用db.Query和db.Prepare安全性完全一致,区别只在是否复用执行计划;高频查询用Prepare省点开销,普通场景用Query更直白
ORDER BY / 表名 / 字段名必须走白名单校验
db.Query("SELECT * FROM users ORDER BY ", "name") 会直接 panic:sql: expected 0 arguments, got 1。SQL 标准规定这些属于查询结构,数据库编译阶段就要确定,没法参数化。
真正该做的,是提前定义合法值并严格比对:
- 排序字段:用
map[string]bool{"created_at": true, "score": true, "name": true},查不到就拒掉 - 排序方向:
if dir != "ASC" && dir != "DESC" { return err },别信strings.ToUpper(dir)后直接拼 - 表名映射:用
switch或常量,比如tenantID == "prod"→ 查users_prod;别写"users_" + tenantID
GORM 的 Raw() 不是免死金牌
db.Raw("SELECT * FROM users WHERE name = ", name) 是安全的;但 db.Raw(fmt.Sprintf("SELECT * FROM %s", tableName)) 就是裸奔。GORM 不会拦截你塞进去的拼接字符串,它只保证占位符部分被转义。
常见的翻车点:db.Raw("UPDATE users SET status = WHERE id IN (" + idsStr + ")", status)。这里要注意,如果idsStr来自用户且没有进行校验,一旦idsStr = "1, (SELECT password FROM admins)",就会触发注入。这是因为SQL注入攻击的核心原理就是攻击者通过在用户输入中插入恶意SQL代码,使服务器执行未授权的数据库操作。在这种情况下,数据被当作代码执行,原本的SQL逻辑就被篡改了,从而可能导致越权访问、数据窃取甚至服务器控制等严重后果。
- 所有动态拼接进
Raw()的部分(表名、字段名、IN列表、WHERE条件片段)都必须白名单校验或预定义枚举 - 批量 ID 查询优先用
db.Where("id IN ", ids).Update(...),而不是手拼IN子句 - NULL 字段需用
sql.NullString等类型Scan,结构体字段顺序须与SELECT一致,否则可能漏读或 panic
别信“只读接口就安全”这种说法
即使只是 SELECT 查询,攻击者也能通过 UNION SELECT 拖库,或用 AND SLEEP(5) 做盲注探测表结构。所谓“只读账户”只能限制写操作,不能阻止信息泄露。
- 所有用户可控输入,无论接口是 GET 还是 POST,无论返回字段是否敏感,都要统一走参数化+白名单
- 错误日志里别打原始 SQL,更别把
err.Error()直接返回给前端——ERROR: relation "users_xxx" does not exist这类提示等于告诉攻击者表名格式 - 生产环境数据库账号权限必须最小化:删掉
CREATE、DROP、EXECUTE,连SELECT都按表粒度授权
修复不是改一两行代码的事,而是要把所有 SQL 构建路径都拉出来过一遍:哪些地方用了拼接、哪些地方绕过了 ORM、哪些字段名/表名是动态生成的——最容易被忽略的,永远是那些“反正只查一个字段,应该没问题”的临时逻辑。
免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。
相关文章
更多-
- 迅捷路由器怎么调信号最强,设置时要注意什么?
- 时间:2026-08-27
-
- vivo浏览器怎么卸不掉?原因和解决方法在这里
- 时间:2026-08-27
-
- OPPO R11s黑屏了,怎么强制恢复出厂设置?
- 时间:2026-08-27
-
- 飞利浦显示器包装盒有生产日期和保修期吗?怎么看?
- 时间:2026-08-27
-
- 联想新平板开机必须联网吗?怎么做?
- 时间:2026-08-27
-
- 平板横竖屏切换设置与问题解决
- 时间:2026-08-27
-
- 移动电源容量怎么测?要准备哪些工具?
- 时间:2026-08-27
-
- 荣耀90 Pro防水吗?防水级别多少?怎么用才安全
- 时间:2026-08-27
精选合集
更多大家都在玩
大家都在看
更多-
- 糖尿病完全不能吃糖吗
- 时间:2026-09-15
-
- 蚂蚁庄园小课堂2026年9月16日最新题目答案
- 时间:2026-09-15
-
- 小鸡答题今天的答案是什么2026年9月16日
- 时间:2026-09-15
-
- 蚂蚁庄园每日答题答案2026年9月16日
- 时间:2026-09-15
-
- 以下哪种粮食是酿造绍兴黄酒的主要原料 蚂蚁庄园今日答案9月16日
- 时间:2026-09-15
-
- 劝学名句“及时当勉励,岁月不待人”出自哪位诗人 蚂蚁庄园今日答案9.16
- 时间:2026-09-15
-
- 蚂蚁庄园今天答题答案2026年9月16日
- 时间:2026-09-15
-
- 蚂蚁庄园答题今日答案2026年9月16日
- 时间:2026-09-15
