从用户控制的源构建的数据库查询¶
ID: go/sql-injection
Kind: path-problem
Security severity: 8.8
Severity: error
Precision: high
Tags:
- security
- external/cwe/cwe-089
Query suites:
- go-code-scanning.qls
- go-security-extended.qls
- go-security-and-quality.qls
如果数据库查询(例如 SQL 或 NoSQL 查询)是根据用户提供的数据构建的,但没有进行充分的净化,则恶意用户可能会运行泄露、篡改或销毁数据库中存储的数据的命令。
建议¶
大多数数据库连接器库都提供了一种通过查询参数或预处理语句将不受信任的数据安全地嵌入到查询中的方法。请使用这些功能,而不要通过字符串连接来构建查询。
示例¶
在以下示例中,假设函数 handler
是 Web 应用程序中的 HTTP 请求处理程序,其参数 req
包含请求对象
package main
import (
"database/sql"
"fmt"
"net/http"
)
func handler(db *sql.DB, req *http.Request) {
q := fmt.Sprintf("SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='%s' ORDER BY PRICE",
req.URL.Query()["category"])
db.Query(q)
}
处理程序使用 fmt.Sprintf
不安全地构建一个涉及从请求对象获取的用户输入的 SQL 查询,将请求参数直接嵌入到查询字符串 q
中。该参数可能包含引号字符,允许恶意用户终止嵌入参数的字符串字面量,并在其后添加任意 SQL 代码。
相反,应使用占位符参数安全地嵌入不受信任的查询参数
package main
import (
"database/sql"
"net/http"
)
func handlerGood(db *sql.DB, req *http.Request) {
q := "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='?' ORDER BY PRICE"
db.Query(q, req.URL.Query()["category"])
}