安全な Golang データベース インタラクション: SQL インジェクションの防止
今日の開発環境では、安全なコーディングの実践が最も重要です。 この記事では、データベースと対話する際の一般的な脅威である SQL インジェクションの脆弱性から Golang アプリケーションを保護することに焦点を当てています。生の SQL とオブジェクト リレーショナル マッピング (ORM) フレームワークの両方を使用した防止手法を検討します。
SQL インジェクションについて
SQL インジェクション (SQLi) は、Web セキュリティの重大な欠陥です。 攻撃者は、悪意のある SQL コードをデータベース クエリに挿入することでこれを悪用し、データの整合性とアプリケーションのセキュリティを侵害する可能性があります。
脆弱なクエリの例:
<code class="language-go">query := "SELECT * FROM users WHERE username='" + username + "' AND password='" + password + "'" rows, err := db.Query(query)</code>
username
または password
への悪意のある入力により、クエリのロジックが変更される可能性があります。
SQL インジェクションについてさらに詳しく理解するには、この他の投稿を参照してください。
生の SQL クエリの保護
SQL を直接操作する場合は、次のセキュリティ対策を優先してください:
1.プリペアド ステートメント: Go の database/sql
パッケージは、SQLi に対する重要な防御手段であるプリペアド ステートメントを提供します。
脆弱な例:
<code class="language-go">query := "SELECT * FROM users WHERE username='" + username + "' AND password='" + password + "'" rows, err := db.Query(query) // Vulnerable to SQL injection</code>
安全なバージョン (準備されたステートメント):
<code class="language-go">query := "SELECT * FROM users WHERE username = ? AND password = ?" rows, err := db.Query(query, username, password) if err != nil { log.Fatal(err) }</code>
準備されたステートメントはユーザー入力を自動的にエスケープし、インジェクションを防ぎます。
2.パラメーター化されたクエリ: パラメーター化されたクエリのプレースホルダーには db.Query
または db.Exec
を使用します:
<code class="language-go">query := "INSERT INTO products (name, price) VALUES (?, ?)" _, err := db.Exec(query, productName, productPrice) if err != nil { log.Fatal(err) }</code>
動的クエリの場合は文字列の連結または fmt.Sprintf
を避けてください。
3. QueryRow
単一レコードの場合: 単一行の取得の場合、QueryRow
によりリスクが最小限に抑えられます:
<code class="language-go">query := "SELECT id, name FROM users WHERE email = ?" var id int var name string err := db.QueryRow(query, email).Scan(&id, &name) if err != nil { log.Fatal(err) }</code>
4.入力の検証とサニタイズ: 準備されたステートメントを使用する場合でも、入力を検証してサニタイズします:
入力検証の例:
<code class="language-go">func isValidUsername(username string) bool { re := regexp.MustCompile(`^[a-zA-Z0-9_]+$`) return re.MatchString(username) } if len(username) > 50 || !isValidUsername(username) { log.Fatal("Invalid input") }</code>
5.ストアド プロシージャ: データベース ストアド プロシージャ内にクエリ ロジックをカプセル化します:
<code class="language-sql">CREATE PROCEDURE AuthenticateUser(IN username VARCHAR(50), IN password VARCHAR(50)) BEGIN SELECT * FROM users WHERE username = username AND password = password; END;</code>
Go からの呼び出し:
<code class="language-go">_, err := db.Exec("CALL AuthenticateUser(?, ?)", username, password) if err != nil { log.Fatal(err) }</code>
ORM による SQL インジェクションの防止
GORM や XORM などの ORM はデータベースのやり取りを簡素化しますが、安全な方法が依然として重要です。
1.ゴーム:
脆弱な例 (動的クエリ):
<code class="language-go">db.Raw("SELECT * FROM users WHERE name = '" + userName + "'").Scan(&user)</code>
安全な例 (パラメータ化されたクエリ):
<code class="language-go">db.Raw("SELECT * FROM users WHERE name = ? AND email = ?", userName, email).Scan(&user)</code>
GORM の Raw
メソッドはプレースホルダーをサポートしています。 Where
:
<code class="language-go">query := "SELECT * FROM users WHERE username='" + username + "' AND password='" + password + "'" rows, err := db.Query(query)</code>
2.複雑なクエリでは生の SQL を避ける: 複雑な生のクエリでもプレースホルダーを使用します。
3.安全なマッピングのための構造体タグ: 安全な ORM マッピングのための構造体タグを使用します:
<code class="language-go">query := "SELECT * FROM users WHERE username='" + username + "' AND password='" + password + "'" rows, err := db.Query(query) // Vulnerable to SQL injection</code>
避けるべきよくある間違い:
結論
Golang は、安全なデータベース対話のための強力なツールを提供します。 準備されたステートメント、パラメーター化されたクエリ、ORM を正しく使用し、ユーザー入力を入念に検証してサニタイズすることで、SQL インジェクションの脆弱性のリスクを大幅に軽減できます。
次の方法で私と連絡を取ってください:
以上がGolang での生の SQL と ORM による SQL インジェクションの防止の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。