避免 SQL 注入風險

您可以透過提供 SQL 參數值作為 sql 套件函式引數,來避免 SQL 注入風險。sql 套件中的許多函式提供 SQL 陳述式的參數,以及要使用在該陳述式參數中的值(其他函式提供已準備好陳述式的參數和參數)。

下列範例中的程式碼使用 ? 符號作為 id 參數的佔位符,該參數提供為函式引數

// Correct format for executing an SQL statement with parameters.
rows, err := db.Query("SELECT * FROM user WHERE id = ?", id)

執行資料庫操作的 sql 套件函式會根據您提供的引數建立已準備好的陳述式。在執行時間,sql 套件會將 SQL 陳述式轉換為已準備好的陳述式,並將其與參數一起傳送,而參數是分開的。

注意:參數佔位符會根據您使用的 DBMS 和驅動程式而有所不同。例如,Postgres 的 pq 驅動程式 接受 $1 等佔位符形式,而不是 ?

您可能會想使用 fmt 套件中的函式來組裝 SQL 陳述式,並將參數包含在字串中,如下所示

// SECURITY RISK!
rows, err := db.Query(fmt.Sprintf("SELECT * FROM user WHERE id = %s", id))

這不安全!當您這麼做時,Go 會組裝整個 SQL 陳述式,並在將完整陳述式傳送至 DBMS 之前,以參數值取代 %s 格式動詞。這會構成 SQL 注入 風險,因為程式碼的呼叫者可以傳送意外的 SQL 片段作為 id 引數。該片段可以難以預測的方式完成 SQL 陳述式,對您的應用程式造成危險。

例如,透過傳遞特定的 %s 值,您可能會得到類似下列的結果,這可能會傳回資料庫中的所有使用者記錄

SELECT * FROM user WHERE id = 1 OR 1=1;