セキュリティ

GORMは、SQL文を構築するためにdatabase/sqlの引数プレースホルダーを使用しており、SQLインジェクションを回避するために引数を自動的にエスケープします。

注意 ロガーからのSQLは、実行されるもののように完全にエスケープされていません。SQLコンソールでコピーして実行する際には注意してください。

クエリ条件

ユーザーの入力は、例えば以下のように引数としてのみ使用する必要があります。

userInput := "jinzhu;drop table users;"

// safe, will be escaped
db.Where("name = ?", userInput).First(&user)

// SQL injection
db.Where(fmt.Sprintf("name = %v", userInput)).First(&user)

インライン条件

// will be escaped
db.First(&user, "name = ?", userInput)

// SQL injection
db.First(&user, fmt.Sprintf("name = %v", userInput))

ユーザーの入力によって数値の主キーを持つオブジェクトを取得する際、変数の型を確認する必要があります。

userInputID := "1=1;drop table users;"
// safe, return error
id, err := strconv.Atoi(userInputID)
if err != nil {
return err
}
db.First(&user, id)

// SQL injection
db.First(&user, userInputID)
// SELECT * FROM users WHERE 1=1;drop table users;

SQLインジェクション手法

いくつかの機能をサポートするために、いくつかの入力はエスケープされません。これらのメソッドでユーザーの入力を使用する際には注意してください。

db.Select("name; drop table users;").First(&user)
db.Distinct("name; drop table users;").First(&user)

db.Model(&user).Pluck("name; drop table users;", &names)

db.Group("name; drop table users;").First(&user)

db.Group("name").Having("1 = 1;drop table users;").First(&user)

db.Raw("select name from users; drop table users;").First(&user)

db.Exec("select name from users; drop table users;")

db.Order("name; drop table users;").First(&user)

SQLインジェクションを回避するための一般的なルールは、ユーザーが送信したデータを信頼しないことです。ユーザー入力を既知の、承認された、定義された入力のセットに対してテストするために、ホワイトリスト検証を実行できます。また、ユーザー入力を使用する場合は、それらを引数としてのみ使用してください。

プラチナスポンサー

ゴールドスポンサー

プラチナスポンサー

ゴールドスポンサー