1. ホーム
  2. sql

[解決済み] シングルクォートをエスケープし、ユーザー入力をシングルクォートで囲むことで、SQLインジェクションから保護することができますか?

2022-05-09 07:28:21

質問

ユーザー入力を含むクエリを作成する場合、パラメータ化されたSQLクエリがユーザー入力をサニタイズする最適な方法だと理解していますが、ユーザー入力を受け取り、シングルクォートをすべてエスケープして文字列全体をシングルクォートで囲むと何が問題なのか疑問に思っています。以下はそのコードです。

sSanitizedInput = "'" & Replace(sInput, "'", "''") & "'"

ユーザーが入力したシングルクオートはすべてダブルシングルクオートに置き換えられ、ユーザーが文字列を終了させることができなくなります。したがって、セミコロンやパーセント記号など、ユーザーが入力したその他のものはすべて文字列の一部となり、コマンドの一部として実際に実行されることはありません。

Microsoft SQL Server 2000 を使用していますが、シングルクォートが唯一の文字列区切り文字であり、文字列区切り文字をエスケープする唯一の方法だと思いますので、ユーザーが入力したものを実行する方法はありません。

これに対してSQLインジェクション攻撃を仕掛ける方法は見当たりませんが、もしこれが防弾のようなものであれば、誰かが既に考えていて、常識になっているだろうと実感しています。

このコードのどこが問題なのでしょうか?SQLインジェクション攻撃をこのサニタイズ技術を通過させる方法があるのでしょうか? このテクニックを悪用したユーザー入力のサンプルがあれば、非常に助かります。


UPDATE

このコードに対してSQLインジェクション攻撃を効果的に行う方法を私はまだ知らないのです。何人かの人が、バックスラッシュで1つのシングルクオートをエスケープして、もう1つのシングルクオートを文字列の最後に残して、残りの文字列がSQLコマンドの一部として実行されるようにすることを提案してくれました。

また、シングルクオートのエスケープを止める方法がない限り、ユーザー入力はすべて1つの連続した文字列とみなされるため、残りの入力は何も実行されません。

入力のサニタイズにもっと良い方法があることは理解していますが、それよりも、上で提供した方法がなぜうまくいかないのかを知りたいと思っています。このサニタイズ方法に対してSQLインジェクション攻撃を仕掛ける具体的な方法を知っている人がいれば、ぜひ見てみたいです。

解決方法は?

まず第一に、それは単なるバッドプラクティスです。入力検証は常に必要ですが、常にあやふやなものでもあります。

さらに悪いことに、ブラックリストによる検証は常に問題があります。受け入れる値や形式を明示的かつ厳密に定義する方がずっとよいでしょう。確かに、これは常に可能というわけではありませんが、ある程度は常に行わなければなりません。

このテーマに関する研究論文をいくつかご紹介します。

ポイントは、あなたが行うどんなブラックリストも(そして寛容すぎるホワイトリストも)回避することができる、ということです。私の論文への最後のリンクは、引用符のエスケープさえも回避される状況を示しています。

これらの状況があなたに当てはまらないとしても、悪い考えであることに変わりはありません。さらに、あなたのアプリが非常に小さいものでない限り、メンテナンスに対処しなければならないでしょうし、おそらくある程度のガバナンスも必要でしょう:常にどこでも、正しく実行されることをどのように保証しますか?

正しい方法

  • ホワイトリストの検証:タイプ、長さ、フォーマット、または受け入れられる値
  • ブラックリストに入れたい場合は、どうぞ。引用符のエスケープは良いことですが、他の緩和策との関連で考えてください。
  • コマンドとパラメータオブジェクトを使用し、準備と検証を行う。
  • パラメータ化されたクエリのみを呼び出す。
  • より良い方法は、ストアドプロシージャのみを使用することです。
  • 動的SQLの使用は避け、文字列の連結を使用してクエリを作成しないでください。
  • SPを使用する場合は、データベース内の権限を必要なSPの実行のみに制限し、テーブルに直接アクセスしないようにすることも可能です。
  • また、コードベース全体がSPを通してのみDBにアクセスすることを簡単に確認することができます。