当前位置: 首页 > 工具软件 > golang-gosql > 使用案例 >

golang-gin-gorm-sql注入及解决方案

郭凯
2023-12-01

不要使用动态字符串拼接 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\n", err)
        return
    }
    rows, err := stmt.Query(1)
    if err != nil {
        fmt.Printf("exec failed, err:%v\n", 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\n", err)
            return
        }
        fmt.Printf("id:%d, name:%s, age:%d\n", 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)
 类似资料: