85

私は同僚と SO の両方に、特に .NET アプリケーションで SQL クエリでパラメーターを使用することの利点について説教してきました。私は、SQL インジェクション攻撃に対する免疫を与えると約束するところまで行きました。

しかし、私はこれが本当なのか疑問に思い始めています。パラメータ化されたクエリに対して成功する既知の SQL インジェクション攻撃はありますか? たとえば、サーバーでバッファ オーバーフローを引き起こす文字列を送信できますか?

もちろん、Web アプリケーションが安全であることを確認するために考慮すべきことは他にもあります (ユーザー入力のサニタイズなど) が、今は SQL インジェクションについて考えています。MsSQL 2005 および 2008 は私のプライマリ データベースであるため、これらに対する攻撃に特に関心がありますが、どのデータベースも興味深いものです。

編集:パラメーターとパラメーター化されたクエリの意味を明確にするため。パラメータを使用するとは、SQL クエリを文字列で作成する代わりに「変数」を使用することを意味します。
したがって、これを行う代わりに:

SELECT * FROM Table WHERE Name = 'a name'

これを行います:

SELECT * FROM Table WHERE Name = @Name

次に、クエリ/コマンド オブジェクトで @Name パラメータの値を設定します。

4

9 に答える 9

50

インジェクションを防ぐには、プレースホルダーで十分です。バッファ オーバーフローの可能性は依然としてありますが、それは SQL インジェクションとはまったく異なる種類の攻撃です (攻撃ベクトルは SQL 構文ではなくバイナリになります)。渡されたパラメータはすべて適切にエスケープされるため、攻撃者が「ライブ」SQL のように扱われるデータを渡す方法はありません。

プレースホルダー内で関数を使用することはできません。プレースホルダーは文字列リテラルとしてエスケープされ、引用符で囲まれているため、列またはテーブルの名前として使用することはできません。

ただし、動的クエリ内の文字列連結の一部としてパラメーターを使用する場合、文字列はエスケープされずリテラルになるため、依然としてインジェクションに対して脆弱です。パラメーターに他の型 (整数など) を使用しても安全です。

そうは言っても、入力を使用して のような値を設定している場合security_level、誰かがシステムの管理者になり、誰でも自由に使えるようになる可能性があります。しかし、これは基本的な入力検証に過ぎず、SQL インジェクションとは関係ありません。

于 2008-11-20T20:09:16.103 に答える
13

いいえ、検証されていないデータを SQL クエリに補間するときは常に、SQL インジェクションのリスクがあります。

クエリ パラメーターは、SQL 構文からリテラル値を分離することで、このリスクを回避するのに役立ちます。

'SELECT * FROM mytable WHERE colname = ?'

それは問題ありませんが、SQL 値ではなく、テーブル名、列名、式、またはその他の構文であるため、クエリ パラメーターを使用できない動的 SQL クエリにデータを補間する目的は他にもあります。

'SELECT * FROM ' + @tablename + ' WHERE colname IN (' + @comma_list + ')'
' ORDER BY ' + @colname'

ストアド プロシージャを使用しているか、動的 SQL クエリをアプリケーション コードから直接実行しているかは問題ではありません。リスクはまだあります。

これらの場合の救済策は、必要に応じてFIEOを使用することです。

  • フィルター入力:データを補間する前に、データが正当な整数、テーブル名、列名などのように見えることを検証します。

  • エスケープ出力:この場合の「出力」とは、データを SQL クエリに入れることを意味します。関数を使用して、SQL 式で文字列リテラルとして使用される変数を変換し、文字列内の引用符やその他の特殊文字をエスケープします。また、関数を使用して、テーブル名、列名などとして使用される変数を変換する必要があります。他の構文に関しては、SQL 式全体を動的に記述するなど、より複雑な問題です。

于 2008-11-20T20:48:58.490 に答える
12

このスレッドでは、「パラメータ化されたクエリ」の定義について混乱しているようです。

  • パラメータを受け入れるストアド プロシージャなどの SQL。
  • DBMS パラメータ コレクションを使用して呼び出される SQL。

前者の定義を考えると、リンクの多くは有効な攻撃を示しています。

しかし、「通常の」定義は後者です。その定義を考えると、機能する SQL インジェクション攻撃はわかりません。ないというわけではありませんが、まだ見たことがありません。

コメントから、私は自分自身を十分に明確に表現していないので、うまくいけばより明確になる例を次に示します。

このアプローチSQL インジェクションに対してオープンです

exec dbo.MyStoredProc 'DodgyText'

このアプローチは、SQL インジェクションに対してオープンではありません

using (SqlCommand cmd = new SqlCommand("dbo.MyStoredProc", testConnection))
{
    cmd.CommandType = CommandType.StoredProcedure;
    SqlParameter newParam = new SqlParameter(paramName, SqlDbType.Varchar);
    newParam.Value = "DodgyText";
    .....
    cmd.Parameters.Add(newParam);
    .....
    cmd.ExecuteNonQuery();
}
于 2008-11-20T21:49:32.720 に答える
10

動的クエリの構築に使用される文字列型 (varchar、nvarchar など) の SQL パラメータは、依然として脆弱です。

それ以外の場合は、パラメーターの型変換 (int、decimal、date など) により、パラメーターを介して sql を挿入しようとする試みが排除されます。

編集: パラメータ @p1 がテーブル名であることを意図している例

create procedure dbo.uspBeAfraidBeVeryAfraid ( @p1 varchar(64) ) 
AS
    SET NOCOUNT ON
    declare @sql varchar(512)
    set @sql = 'select * from ' + @p1
    exec(@sql)
GO

@p1 がドロップダウン リストから選択された場合、SQL インジェクション攻撃ベクトルとなる可能性があります。

@p1 が、ユーザーが介入する能力なしでプログラムによって定式化されている場合、それは潜在的な sql-injection 攻撃ベクトルではありません

于 2008-11-20T20:09:25.743 に答える
6

バッファ オーバーフローは SQL インジェクションではありません。

パラメーター化されたクエリは、SQL インジェクションに対して安全であることを保証します。SQL サーバーにバグという形でエクスプロイトの可能性がないことを保証するものではありませんが、それを保証するものはありません。

于 2008-11-20T20:10:14.260 に答える
2

パーミッションはテーブルレベルである必要があるため、何らかの形や形式で動的SQLを使用する場合、データは安全ではありません。はい、その特定のクエリからのインジェクション攻撃の種類と量を制限しましたが、ユーザーがシステムに侵入する方法を見つけた場合にユーザーが取得できるアクセスを制限せず、内部ユーザーがアクセスしてはならないものに完全にアクセスできます。詐欺を犯したり、個人情報を盗んで販売したりするため。あらゆるタイプの動的SQLは危険な行為です。非動的ストアドプロシージャを使用する場合は、プロシージャレベルで権限を設定でき、プロシージャによって定義されたもの以外のユーザーは何もできません(もちろんシステム管理者を除く)。

于 2008-11-20T20:28:31.620 に答える
1

パラメータを使用すると、文字列を簡単に保存できることを覚えておいてください。または、ポリシーがない場合はユーザー名を言うことができます。

これ自体は害を及ぼすことはありませんが、その日付がアプリケーションのどこでどのように使用されるかをよく知っておく必要があります (たとえば、Cookie に保存され、後で他の処理を行うために取得されます)。

于 2009-07-22T00:32:49.860 に答える
1

例として動的SQLを実行できます

DECLARE @SQL NVARCHAR(4000);
DECLARE @ParameterDefinition NVARCHAR(4000);

SELECT  @ParameterDefinition = '@date varchar(10)'

SET @SQL='Select CAST(@date AS DATETIME) Date'

EXEC sp_executeSQL @SQL,@ParameterDefinition,@date='04/15/2011'
于 2011-04-12T14:47:07.523 に答える
1

ストアド プロシージャは、オーバーフロー/切り捨てによる特別な種類の SQL インジェクションに対して脆弱である可能性があります。参照: データ切り捨てによるインジェクションの有効化:

http://msdn.microsoft.com/en-us/library/ms161953.aspx

于 2008-11-20T20:15:15.577 に答える