53

OJT 会社のアプリケーション管理システムをプログラムする必要があります。フロントエンドは C# で、バックエンドは SQL で行います。

今、私はこれまでこの範囲のプロジェクトを行ったことがありません。学校では、SQL に関する基本的な授業しかありませんでした。どういうわけか、私たちの先生は SQL インジェクションについて完全に議論しませんでした。ネットで読んで初めて知りました。

とにかく私の質問は、C# で SQL インジェクションをどのように防ぐのですか? アプリケーションのテキストフィールドを適切にマスクして、指定された形式の入力のみを受け入れるようにすることで実現できると漠然と考えています。例: 電子メールのテキスト ボックスは、「example@examplecompany.tld」の形式にする必要があります。このアプローチで十分でしょうか? それとも、.NET には、このようなものを処理する定義済みのメソッドがありますか? テキストボックスにフィルターを適用して、メールアドレス形式または名前テキストボックスのみを受け入れ、特殊文字を受け入れないようにすることはできますか?

4

4 に答える 4

66

パラメータのSqlCommandおよびその子コレクションを使用することで、SQL インジェクションをチェックする手間がすべてなくなり、これらのクラスによって処理されます。

上記の記事の 1 つから抜粋した例を次に示します。

private static void UpdateDemographics(Int32 customerID,
    string demoXml, string connectionString)
{
    // Update the demographics for a store, which is stored  
    // in an xml column.  
    string commandText = "UPDATE Sales.Store SET Demographics = @demographics "
        + "WHERE CustomerID = @ID;";

    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        SqlCommand command = new SqlCommand(commandText, connection);
        command.Parameters.Add("@ID", SqlDbType.Int);
        command.Parameters["@ID"].Value = customerID;

        // Use AddWithValue to assign Demographics. 
        // SQL Server will implicitly convert strings into XML.
        command.Parameters.AddWithValue("@demographics", demoXml);

        try
        {
            connection.Open();
            Int32 rowsAffected = command.ExecuteNonQuery();
            Console.WriteLine("RowsAffected: {0}", rowsAffected);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}
于 2013-01-17T10:28:20.750 に答える
10

SQL インジェクションは厄介な問題になる可能性がありますが、それを回避する方法があります。Linq2Entities、Linq2SQL、NHibrenate などの ORM を使用するだけで、リスクが軽減されます。ただし、それらを使用しても SQL インジェクションの問題が発生する可能性があります。

SQL インジェクションの主なものは、ユーザー制御の入力です (XSS の場合と同様)。ユーザー名とパスワードを受け取るログインフォームがある場合の最も単純な例 (これを行うだけのフォームがないことを願っています)。

SELECT * FROM Users WHERE Username = '" + username + "' AND password = '" + password + "'"

ユーザーがユーザー名Admin' に対して次のように入力した場合 --データベースに対して実行すると、SQL ステートメントは次のようになります。

SELECT * FROM Users WHERE Username = 'Admin' --' AND password = ''

この単純なケースでは、パラメータ化されたクエリ (ORM が行うこと) を使用すると、リスクが取り除かれます。また、あまり知られていない SQL インジェクション攻撃ベクトルの問題もあり、それはストアド プロシージャにあります。この場合、パラメータ化されたクエリまたは ORM を使用しても、SQL インジェクションの問題が発生します。ストアド プロシージャには実行コマンドを含めることができ、それらのコマンド自体が SQL インジェクション攻撃を受けやすい可能性があります。

CREATE PROCEDURE SP_GetLogin @username varchar(100), @password varchar(100) AS
DECLARE @sql nvarchar(4000)
SELECT @sql = ' SELECT * FROM users' +
              ' FROM Product Where username = ''' + @username + ''' AND password = '''+@password+''''

EXECUTE sp_executesql @sql

したがって、この例では、パラメータ化されたクエリまたは ORM を使用している場合でも、前の例と同じ SQL インジェクションの問題が発生します。この例はばかげているように見えますが、このようなものがどれほど頻繁に書かれているかに驚かれることでしょう。

私のお勧めは、ORM を使用して SQL インジェクションの問題が発生する可能性をすぐに減らし、問題のあるコードとストアド プロシージャを見つけて修正する方法を学ぶことです。必要がない限り、ADO.NET (SqlClient、SqlCommand など) を直接使用することはお勧めしません。パラメーターを指定して使用するのは安全ではないからではなく、怠惰になって SQL の記述を開始する方がはるかに簡単だからです。文字列を使用してパラメーターを無視してクエリを実行します。ORMS は、パラメーターの使用を強制するという素晴らしい仕事をします。

次に、SQL インジェクションに関する OWASP サイトhttps://www.owasp.org/index.php/SQL_Injectionにアクセスし、SQL インジェクション チート シートを使用して、コードで発生する問題を見つけて解決できるようにします。 https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet 最後に、SQL インジェクションや XSS などについてお互いのコードを確認できる、社内の他の開発者との間で適切なコード レビューを行うことをお勧めします。多くの場合、プログラマーは機能を急いで実装しようとしていて、コードのレビューにあまり時間をかけないため、このようなことを見逃しています。

于 2013-01-17T10:27:17.227 に答える
9

私の答えはとても簡単です:

C# と SQL データベース間の通信には Entity Framework を使用します。これにより、SQL インジェクションに対して脆弱ではないパラメーター化された SQL 文字列が作成されます。

ボーナスとして、作業も非常に簡単です。

于 2013-01-17T10:05:33.253 に答える
5

入力を検証しようとしても、SQL インジェクションを防ぐことはできません。代わりに、その入力をデータベースに渡す前に適切にエスケープする必要があります。

入力を完全にエスケープする方法は、データベースとのインターフェースに使用しているテクノロジーによって異なります。ほとんどの場合、生の SQL を記述していない限り (これはできる限り避ける必要があります)、フレームワークによって自動的に処理されるため、無料で防弾保護が得られます。

インターフェイス テクノロジを正確に決定した後、この問題をさらに調査する必要があります。

于 2013-01-17T10:05:58.513 に答える