golang-gin-gorm-sql注入及解决方案
不要使用动态字符串拼接 dao.db.Raw(sql) 来查询,存在sql注入的风险
!不要动态拼接字符串
解决方案
1. 使用gorm框架语言,自带预编译,能够避免sql注入
2. 使用gorm自带的prepare预加载也能解决,但可能会增加请求往返(有待考量)
eg:(查询操作使用 db.Prepare() 方法声明预处理 SQL,使用 stmt.Query() 将数据替换占位符进行查询,更新、插入、删除操作使用 stmt.Exec() 来操作。)
// 预处理查询数据 func prepareQuery() { sqlStr := "SELECT id,name,age FROM user WHERE id > ?" stmt, err := db.Prepare(sqlStr) if err != nil { fmt.Printf("prepare sql failed, err:%v ", err) return } rows, err := stmt.Query(1) if err != nil { fmt.Printf("exec failed, err:%v ", err) return } defer rows.Close() for rows.Next() { var u user err := rows.Scan(&u.id, &u.name, &u.age) if err != nil { fmt.Printf("scan data failed, err:%v ", err) return } fmt.Printf("id:%d, name:%s, age:%d ", u.id, u.name, u.age) } }
3. 使用Raw的占位符来处理sql注入问题(推荐)
eg: 完美避免测试(使用占位符):
// QueryWaitingApply 7 or 1=1 TODO 占位符解决sql注入 func (as *ArticleService) QueryWaitingApply() (artInfo []mysqlModel.Article) { sql := "select * from articles where boss_id=? and status =?" dao.DB.Raw(sql, "7 or 1=1", 0).Scan(&artInfo) fmt.Println(artInfo) return }
sql注入成功测试(不使用占位符,纯纯拼接sql)
// QueryWaitingApply 7 or 1=1 TODO 占位符解决sql注入 func (as *ArticleService) QueryWaitingApply() (artInfo []mysqlModel.Article) { //sql := "select * from articles where boss_id=? and status = 0" //dao.DB.Raw(sql, "7 or 1=1").Scan(&artInfo) //fmt.Println(artInfo) //return sql := "select * from articles where boss_id=7 or 1=1 and status = 0" dao.DB.Raw(sql).Scan(&artInfo) fmt.Println(artInfo) return }
请注意,gorm不直接支持UNION,您需要使用db.Raw来进行联合:
db.Raw("? UNION ?", db.Select("*").Model(&Foo{ }), db.Select("*").Model(&Bar{ }), ).Scan(&union)