1. ホーム
  2. sql-server

SQL ServerのSQLインジェクションでシングルクォートをエスケープするサニテーションはどのように破られるのでしょうか?

2023-09-01 02:26:35

質問

まず始めに、パラメータ化されたクエリが最良の選択肢であることは十分承知していますが、私が以下に提示する戦略を脆弱にするものは何なのかを尋ねています。人々は以下のソリューションが機能しないと主張しているので、私はなぜそれが機能しないかの例を探しています。

動的 SQL が SQL サーバーに送信される前に以下のエスケープを使用してコードで構築されている場合、どのような種類のインジェクションがこれを打ち負かすことができますか?

string userInput= "N'" + userInput.Replace("'", "''") + "'"

同様の質問には ここで にも回答がありましたが、どの回答もここに当てはまるとは思えません。

シングルクォートを" \" でエスケープすることは、SQL Serverではできません。

私は SQLスマグリング をUnicodeで使用することができます(概要 ここで を使用した場合、生成される文字列がシングルクォートの前のNによってUnicodeとしてマークされるため、妨害されることになります。私の知る限り、SQL Serverが自動的にシングルクォートに変換するような他の文字セットは存在しません。エスケープされていない単一引用符がなければ、インジェクションが可能であるとは思えません。

私は 文字列の切り捨て は実行可能なベクトルであると信じています。SQL Server は確かに切り捨てを行いません。 nvarchar の最大サイズは 2GB です。 マイクロソフトによると . 2GB の文字列はほとんどの状況で実現不可能であり、私の場合は不可能です。

二次射出 は可能かもしれないが、もし可能なら。

  1. データベースに入るすべてのデータは、上記の方法でサニタイズされます。
  2. データベースからの値は決して動的 SQL に追加されません (動的 SQL 文字列の静的部分でテーブルの値を参照できるのに、なぜそんなことをするのでしょうか?)。

私は、これがパラメーター化されたクエリを使用するより良い、または代替であると提案しているわけではありませんが、私が概説したものがどのように脆弱であるかを知りたいのです。何かアイデアはありますか?

どのように解決するのですか?

このエスケープ関数が失敗するケースがいくつかあります。 最も明白なのは、シングルクォートが使用されていない場合です。

string table= "\"" + table.Replace("'", "''") + "\""
string var= "`" + var.Replace("'", "''") + "`"
string index= " " + index.Replace("'", "''") + " "
string query = "select * from `"+table+"` where name=\""+var+"\" or id="+index

この場合、ダブルクオート、バックチックを使って、"break out"することができます。 最後のケースでは、quot;break out"するものがないので、次のように書くだけです。 1 union select password from users-- と書くか、攻撃者が望むどんなSQLペイロードでも書くことができます。

このエスケープ関数が失敗する次の条件は、文字列がエスケープされた後に部分文字列が取られる場合です(そして はい 私はこのような脆弱性を実際に発見しています)。

string userPassword= userPassword.Replace("'", "''")
string userName= userInput.Replace("'", "''")
userName = substr(userName,0,10)
string query = "select * from users where name='"+userName+"' and password='"+userPassword+"'";

この場合、ユーザー名は abcdefgji' は次のようになります。 abcdefgji'' に変換され、その後、エスケープ関数によって abcdefgji' に戻されます。 これを利用するには、任意のSQL文にパスワードの値を設定することで、この場合 or 1=1-- はSQLと解釈され、ユーザ名は abcdefgji'' and password= . 結果として、以下のようなクエリが生成されます。

select * from users where name='abcdefgji'' and password=' or 1=1-- 

T-SQLやその他の高度なSQLインジェクション技術については、すでに述べたとおりです。 SQL Serverアプリケーションにおける高度なSQLインジェクション は素晴らしい論文なので、まだ読んでいないのであれば読むべきです。

最後の問題は、ユニコード攻撃です。 このクラスの脆弱性は、エスケープ関数がマルチバイトのエンコードを認識しないために発生します。 を使用して、エスケープ文字を消費することができます。 . 文字列に "N" を追加しても、文字列内の後のマルチバイト文字の値には影響しないため、役に立ちません。 しかし、データベースが GBK ユニコード文字列を受け入れるように構成されていなければならないため、このタイプの攻撃は非常にまれです (そして MS-SQL がこれを実行できるかどうかはわかりません)。

二次コード注入はまだ可能です。この攻撃パターンは、攻撃者が制御するデータソースを信頼することによって作成されます。 エスケープは、制御文字をその文字リテラルとして表現するために使用されます。 から取得した値をエスケープするのを忘れた場合、開発者は、その値を文字リテラルとして表現することができます。 select そして、この値を別のクエリで使用する場合 バム とすると、攻撃者は文字リテラルであるシングルクォートを自由に使えるようになります。

すべてをテストし、何も信用しない。