Revel框架中直接触发SQL注入的写法包括:用fmt.Sprintf或字符串拼接构造SQL(如"SELECT * FROM users WHERE id = " + strconv.Itoa(id))、WHERE子句中直接拼接用户输入(如"name LIKE '%" + name + "%")、使用sql.Raw或自定义sql.Scanner绕过参数绑定且未转义。

Revel框架里哪些写法会直接触发SQL注入
Revel本身不内置ORM,数据库操作依赖database/sql或第三方驱动(如go-sql-driver/mysql),所以防注入完全取决于你是否用了参数化查询。常见踩坑点包括:
- 用
fmt.Sprintf或字符串拼接构造SQL,比如"SELECT * FROM users WHERE id = " + strconv.Itoa(id) - 把用户输入直接塞进
query字符串里,哪怕只拼一个WHERE name LIKE '%'+name+'%' - 用
sql.Raw或自定义sql.Scanner绕过参数绑定,却没做转义
这些写法在Revel里和原生Go无异——只要没走db.Query/db.Exec的参数绑定路径,就等于裸奔。
Revel中必须用db.Query或db.Exec带参数调用
Revel的app.DB(通常为*sql.DB)支持标准的参数化接口。关键不是“Revel有没有防注入”,而是你有没有让参数值脱离SQL文本解析阶段:
- ✅ 正确:
rows, err := app.DB.Query("SELECT * FROM users WHERE email = ? AND status = ?", email, status) - ✅ 正确(命名参数,需驱动支持,如
pgx):rows, err := app.DB.Query("SELECT * FROM users WHERE email = $1 AND status = $2", email, status) - ❌ 错误:
rows, err := app.DB.Query("SELECT * FROM users WHERE email = '" + email + "'")
注意:MySQL驱动用?,PostgreSQL驱动用、,SQLite用?或:name——占位符类型必须和驱动匹配,否则报错sql: expected 0 arguments, got 2。
Revel配合GORM或sqlx时的防注入要点
很多Revel项目会引入GORM或sqlx来简化查询。它们能帮你屏蔽底层细节,但仍有陷阱:
- GORM默认安全,但
Where("email = '" + email + "'")这种手写字符串仍会注入;必须用Where("email = ?", email)或Where("email = ?", email).Where("status = ?", status) - sqlx的
Get/Select方法支持结构体扫描,但sqlx.Rebind只负责占位符替换,不校验内容——你传进去的email变量本身要是干净的 - 所有
Raw查询(如db.NamedQuery中的sql.Named)都必须显式绑定,不能靠字符串插值
特别提醒:GORM v2的Scopes或Joins如果内部拼了SQL,且你传入了用户可控字段名(如orderBy := r.Params.Get("sort")),那Order(orderBy)就可能被利用——排序字段不能直接来自请求参数。
Revel项目里容易被忽略的“非主路径”注入点
除了Controller.Action里的数据库操作,以下位置也常漏防:
-
app.Init中执行的初始化SQL(如建表、插入默认配置),若读取了环境变量或配置文件中的SQL片段,而该片段含用户可控内容,就危险 - 后台任务(
job.Job)调用数据库时,若参数来自Redis缓存或消息队列,且未校验来源,等同于间接接收用户输入 - 日志记录中拼接了SQL语句和参数值(如
log.Printf("query: %s, args: %v", sql, args)),虽不导致注入,但若日志被前端展示,可能引发XSS;更糟的是,有人把日志SQL复制出来手动执行,结果带入恶意值
真正的难点不在主干逻辑,而在那些“看起来不走用户请求”的代码分支——它们往往跳过中间件和参数校验,直连数据库。

















