CS.SQL.INJECT.LOCAL
SQL インジェクションの脆弱性。SQL ステートメントが未検証の入力を使用して作成されている場合、攻撃アプリケーションによって使用されたデータベース上でこのアプリケーションの特権を使用して、悪意のあるユーザーは文字列を挿入して任意の SQL ステートメントを実行することができます。
脆弱性とリスク
コードへの入力が適切に検証されないと、攻撃者は、任意の SQL ステートメントを実行可能な形式で入力を作成することができます。この種のチャンスがある場合、攻撃者は次のことを行えます。
- アプリケーションのデータベース内の機密データを読み取ります。
- アプリケーションのデータベース内のデータを書き換えます。
- データベース内のすべての情報を削除するような任意のコマンドを実行します。
この指摘を回避するには、次のことを実行するのがベストです。
- SQL ステートメントを作成する場合、定数文字列のみを使用する。
- 入力を使用するパラメーター化された SQL ステートメントを作成する場合、安全なライブラリを使用する。
- SQL ステートメントで入力を使用する前に承認コードを追加する。
脆弱コード例
コピー
public static void DeleteUser(string username, string connectionString)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
string sqlQuery = String.Format("DELETE FROM Users WHERE UserName='{0}'", username);
SqlCommand command = new SqlCommand(sqlQuery, connection);
command.Connection.Open();
command.ExecuteNonQuery();
}
}
Klocwork は、8 行目について、安全でない SQL クエリ文字列がコマンドとして使用されていることを示す、SQL インジェクションレポートを生成します。この場合の SQL インジェクションは、username の正確な名前を持つユーザーのみを削除する代わりにデータベースからすべてのユーザーを削除する入力 “; DROP TABLE Users; --” を使用すると、発生する場合があります。
修正コード例
コピー
public static void DeleteUser(string username, string connectionString)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
string sqlQuery = "DELETE FROM Users WHERE UserName=@Username";
SqlCommand command = new SqlCommand(sqlQuery, connection);
command.Parameters.Add(new SqlParameter("@Username", username));
command.Connection.Open();
command.ExecuteNonQuery();
}
}
前のスニペットからの問題が修正されました:これにより、ユーザー名は安全なライブラリ呼び出しを使用して SQL ステートメントを作成するために使用されます。この呼び出しによって、入力が検証され、変換されて、SQL インジェクションを防止します。
外部参考資料
セキュリティトレーニング
Secure Code Warrior が提供しているアプリケーションセキュリティトレーニング教材。