SQLインジェクションとXSS攻撃を100%防止することは、言うより簡単だと思われますが、なぜですか?
静的コード分析ツールは、ユーザーが提供したすべての入力ベクトル(ユーザーが汚染した変数を含む)が確実にサニタイズされることを保証できませんか?それとも、制限的なプログラミング言語やフレームワークでそれを強制しますか?
以下のルールはXSSとSQLインジェクションを不可能にしませんか?
<meta charset="utf-8">
を必要とし、すべてのデータが同じエンコーディングで処理されるようにします。では、このアイデアの何が問題なのでしょうか?
参照:
決して不可能なことはありません。
しかし、SQLインジェクションの脆弱性は、最も一般的な間違いを防止するORMとクエリビルダーによって低下しました。私の経験では、デフォルトで安全な(ish)テンプレートエンジンを使用するアプリケーションでも、XSSの問題は少なくなっています。
しかし、主な問題は次のとおりです。
query
)にフラグを立てる必要があります。準備されたクエリに変数を含めることはできず、例外を作成することもできません(入力はユーザーではありません-制御されているので問題ありません」、「[...]」というまれな状況では、すぐに管理できなくなります)。これにより、開発者の使いやすさが大幅に制限されます。PHP=の例を見てみましょう。さまざまなSQL関数(query
など)のすべての使用にフラグを付け、prepare
の使用のみを許可できます。また、変数がprepare
に渡されていないことを確認する必要があります。
$stmt = $conn->prepare("SELECT test from table WHERE x=?");
$stmt->bind_param("s", $test);
しかし、テーブル名を可変にしたい場合はどうでしょうか?それとも、最初に作成する必要がある複雑なクエリの場合はどうでしょうか。例えば:
$filterquery = " WHERE ";
for ($filter in $filterarray) {
$filterquery = ...
}
$stmt = $conn->prepare("SELECT test from $tablename" . $filterquery);
$stmt->bind_param("s", [...]);
$filterquery
が安全かどうかを確認することは簡単ではないため、これは許可することができませんでした。ただし、クエリで変数を許可しないと、開発者が厳しく制限されます。
クエリビルダーを使用して、バインディング関数のみがパラメーターを受け入れることを確認できます(例:DoctrineのsetParameter
)。ただし、変数がwhere
などの他の関数に渡されないようにする必要があります。 。これには正当なユースケースがあるため、開発者の使いやすさも制限されます。
XSSでは、これはさらに困難になります。まず、データを出力するすべての関数をチェックし、それを防止する必要があります(echo
、print
、die
など)。出力はテンプレートを介してのみ実行できますエンジン(これは確かに実行可能です)。
ただし、テンプレートの外部でHTMLコードを動的に構築することはできません。複雑な変数をそれに渡すことができないためです(データが(部分的に)ユーザー制御であるかどうかを知る方法がありません)。
XSSの多くのケースを防ぐために、デフォルトでデータをHTMLエンコードできるようになりました。しかし、JavaScriptのコンテキストにいるかどうかはどのようにしてわかりますか?またはsrc
属性コンテキスト(javascript:
リンクを防ぐ必要がある場所)?これも簡単に確認できます(または、変数が出力されるコンテキストにフラグを付ける必要があります。これはエラーが発生しやすくなります)。
そして DOMベースのXSS があります。また、一部のユーザーがHTMLの限られたサブセットを投稿できるようにしたい場合があります(これはフィルタリングできますが、テンプレートで例外が必要になります)。