使用 fmt.Sprintf 防止 Go 中的 sql 注入以进行本机查询

Posted

技术标签:

【中文标题】使用 fmt.Sprintf 防止 Go 中的 sql 注入以进行本机查询【英文标题】:prevent sql injection in Go with fmt.Sprintf for native query 【发布时间】:2020-12-20 10:17:54 【问题描述】:

此查询是否会导致 sql 注入或对查询插入语句不利

    query := fmt.Sprintf("INSERT INTO users(%s) VALUES(%s) RETURNING user_id, otp",
        repo.getColumns(), // returning users columns
        repo.setValues(), // looping to create $1, $2 (depent length of users columns)
    )
    stmt, err := db.Prepare(query)
    checkError(err)
    defer func() 
        if err = stmt.Close(); err != nil 
            panic(err.Error())
        
    ()
    err = stmt.QueryRowContext(ctx,
        user.Email,
        user.CardID,
        user.CardFee,
        user.PhoneNumber,
        user.Gender,
        user.BirthDate,
        user.BirthCityID,
        user.Education,
        user.MotherName,
        user.MotherPhone,
        user.PartnerPhone,
        user.FamilyCardNumber,
        user.Religion,
        user.CitizenShip,
        user.MaritalStatus,
        user.SpouseCardID,
        user.SpouseFullName,
        user.SpouseBirthDate,
    ).Scan(&userData.ID, &userData.CardID)

这里repo.getColumns() 是一个返回用户列 字符串的方法,setValues() 是一个字符串操作,用于从方法@ 上用户列的长度创建$1、$2、... 987654324@ 会不会有潜在的安全性??对 QueryRowContext 参数第二个也是如此......它是...interface,如果我有很多列,我应该一一输入手册,这是为了让它更短吗?

【问题讨论】:

是的,存在 SQL 注入的可能性。然而,该漏洞的严重程度取决于插入到查询字符串中的数据的可信度。 如何正确编写查询?对于我的情况@mkopriva 【参考方案1】:

sql注入攻击的可能性在于函数调用repo.getColumns()repo.setValues()返回的值。

问题是您对这些函数返回的内容有多少控制权?他们的行为是否基于用户输入?如果是这样,那么您可以通过一些简单的模式处理来保护自己免受注入攻击 - 例如,如果您需要一个名称,请检查输入是否仅包含字母和空格。

您还可以尝试排除任何可用于注入攻击且不应作为值列名称的一部分的特殊标志。

...如果我有很多列,我应该一一输入手册,这是为了缩短它吗?

我建议就此提出一个单独的问题,因为这是一个独特的问题。

【讨论】:

以上是关于使用 fmt.Sprintf 防止 Go 中的 sql 注入以进行本机查询的主要内容,如果未能解决你的问题,请参考以下文章

go Slice切片使用

GO语言管道例子

GO语言管道例子

GO语言实现TCP端口转发代码

GO语言实现TCP端口转发代码

golang error信息转字符串 x := fmt.Sprintf("%s", err)