首页 > 解决方案 > 使用 fmt.Sprintf 防止 Go 中的 sql 注入进行本机查询

问题描述

这个查询是进行 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, .... 从方法上的用户列的长度getColumns() 它是否具有潜在的安全性?在 QueryRowContext 参数第二个等等....它是...interface{},如果我有很多列,我应该一一输入手册,这是让它更短的东西吗?

标签: databasegoprepared-statementsql-injection

解决方案


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

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

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

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

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


推荐阅读