如何构建安全查询构建器防范SQL注入,修复Go MySQL操作注入漏洞
安全查询构建器优化方案(避免SQL注入)
问题根因
你当前的代码直接将用户传入的参数字段、参数值直接拼接为SQL语句,未做任何安全校验和参数化处理,攻击者可以构造恶意参数篡改SQL执行逻辑,导致数据泄露。
优化方案
1. 新增查询字段白名单校验
SQL的字段名无法通过参数化处理,因此必须先定义允许作为查询条件的字段白名单,过滤非法字段,避免攻击者构造恶意字段名进行注入。
2. 使用参数化查询(预编译语句)
所有用户传入的参数值绝对不能直接拼入SQL语句,统一使用占位符(MySQL 用?)替代,参数值通过Query方法的可变参数传入,数据库会自动对参数做转义处理,完全避免值注入风险。
完整优化后代码
type mysqlRepository struct { Conn *sql.DB } // 定义允许作为查询条件的字段白名单,根据业务需求调整 var allowedQueryFields = map[string]bool{ "id": true, "name": true, "teacher": true, "uuid": true, } func (dbconn *mysqlRepository) GetAll(param map[string]string) (response []models.Subject, err error) { var result models.Subject q := `SELECT id, name, teacher, uuid FROM subject` var args []interface{} conditionCount := 0 for field, value := range param { if value == "" { continue } // 过滤不在白名单内的字段 if !allowedQueryFields[field] { continue } // 拼接查询条件,值用占位符替代 if conditionCount == 0 { q += " WHERE " } else { q += " AND " } q += fmt.Sprintf("%s = ?", field) args = append(args, value) conditionCount++ } // 执行查询时传入参数列表 query, err := dbconn.Conn.Query(q, args...) if err != nil { utils.QueryErrorException(err) return } defer query.Close() for query.Next() { errorScanningDataHistory := query.Scan( &result.ID, &result.Name, &result.Teacher, &result.UUID, ) utils.QueryErrorException(errorScanningDataHistory) response = append(response, result) } return }
额外安全建议
- 可根据业务场景对参数值增加格式校验,例如
id字段必须为正整数、uuid必须符合UUID格式,进一步降低风险 - 建议在SQL末尾增加默认
LIMIT限制,避免异常情况下返回全量数据 - 不要将数据库原始报错信息返回给前端,防止泄露表结构、字段名等敏感信息
内容的提问来源于stack exchange,提问作者Elbo Shindi Pangestu
相关产品推荐
相关产品推荐

