ホームページ >データベース >mysql チュートリアル >mysql の高度な (24) SQL インジェクションを防御する方法のまとめ

mysql の高度な (24) SQL インジェクションを防御する方法のまとめ

黄舟
黄舟オリジナル
2017-02-11 10:53:471526ブラウズ

SQLインジェクションを防御する方法のまとめ

この記事は主にSQLインジェクションを防御する方法を説明し、インジェクションとは何なのか、インジェクションが発生する理由は何なのか、そして防御方法を紹介します。

SQL インジェクションは非常に有害な攻撃形式です。害は大きいですが、防御は XSS よりはるかに困難ではありません。

SQL インジェクションについては、こちらをご覧ください: http://www.php.cn/

SQL インジェクションの脆弱性が存在する理由は、SQL パラメーターを結合するためです。つまり、入力に使用されるクエリ パラメータが SQL ステートメントに直接結合されるため、SQL インジェクションの脆弱性が発生します。

1. 古典的な SQL インジェクションをデモンストレーションします


次のようになります: select id,no from user where id=2;

次のような SQL 文字列を結合してステートメントが取得された場合: String sql = "select id,no from user where id=" + id;

" id はユーザーが入力したパラメータです。次にユーザーが 2 を入力すると、上に示したようにデータが見つかります。 SQL インジェクション攻撃の場合、入力は 2 または 1=1 です。

したがって、上記のステートメント (select id,no from user where id=2 or 1=1;) により、user テーブル内のすべてのレコードが見つかったことがわかります。

これは典型的な SQL インジェクションです。

別の列を見ると:

テーブル sqlinject は SQL インジェクションを通じて直接削除できることがわかります。危険性が見えてきます!

2. SQL インジェクションの理由

SQL インジェクションの理由は、表面的には、変数をプリコンパイルしてバインドするために SQL ステートメントを使用せずに、文字列を結合して SQL ステートメントを形成することが原因であると言われています。

しかし、より深い理由は、ユーザーが入力した文字列が「SQL文」として実行されることです。

たとえば、上記の String sql = "select id,no from user where id=" + id;

ユーザーが入力した ID の値が文字列リテラルとしてのみ使用され、データベースに渡されることを望みます。ただし、:2 または 1=1 または 1=1 が where id= のリテラル値として使用されず、SQL ステートメントとして実行される場合。したがって、その本質は、ユーザーの入力データをコマンドとして実行することです。

3. SQL インジェクションに対する防御

1> 基本的に、SQL ステートメントを使用して変数をプリコンパイルし、バインドすることが SQL インジェクションを防御する最良の方法であることは誰もが知っています。しかし、根本的な理由がすべて理解されているわけではありません。

String sql = "select id, no from user where id=?";

PreparedStatement ps = conn.prepareStatement(sql); ps.setInt(1, id);

上に示すように、 SQL ステートメントを使用して変数をプリコンパイルしてバインドするのが一般的です。これにより SQL インジェクションが妨げられるのはなぜですか?

その理由は、PreparedStatement を使用すると、SQL ステートメント「select id, no from user where id=?」がプリコンパイルされるためです。つまり、SQL エンジンが事前に構文分析を実行し、構文ツリーを生成し、つまり、文法分析はすでに完了しており、文法分析では主に select などの SQL コマンドが分析されるため、後でどのようなパラメーターを入力しても、SQL ステートメントの文法構造には影響しません。 、ここで、and、または、order by などです。したがって、これらの SQL コマンドを後で入力しても、SQL コマンドとしては実行されません。これは、これらの SQL コマンドの実行は、まず構文分析を通過し、実行プランを生成する必要があるためです。構文分析は完了し、プリコンパイルされています。 . の場合、後で入力したパラメーターは SQL コマンドとして実行することは絶対に不可能であり、文字列リテラル パラメーターとしてのみ扱われます。したがって、SQL ステートメントのプリコンパイルによって SQL インジェクションを防ぐことができます。

2> ただし、すべてのシナリオで SQL ステートメントのプリコンパイルを使用できるわけではありません。現時点では、パラメーターのデータ型を厳密にチェックする必要があり、SQL インジェクションを防ぐためにいくつかの安全関数を使用することもできます。

例: String sql = "select id,no from user where id=" + id;

ユーザーが入力したパラメータを受け取るとき、id は int 型のみであることを厳密にチェックします。複雑な状況は正規表現を使用して判断できます。これにより、SQL インジェクションを防ぐこともできます。

次のような安全な関数の使用:

MySQLCodec codec = new MySQLCodec(Mode.STANDARD);

name = ESAPI.encoder().encodeForSQL(codec, name);

String sql = "select id,no from user where name=" + name;

ESAPI.encoder().encodeForSQL(codec, name)

この関数は、SQL エンジンが name 内の文字列を変換しないように、name に含まれるいくつかの特殊文字をエンコードします。構文解析用の SQL コマンドとして使用されます。

注意

実際のプロジェクトでは通常、ibatis、mybatis、hibernateなどのさまざまなフレームワークを使用します。通常、デフォルトでは SQL がプリコンパイルされます。 ibatis/mybatis の場合、#{name} という形式を使用すると、SQL はプリコンパイルされます。${name} を使用すると、SQL はプリコンパイルされません。

以上、SQLインジェクション防御方法をまとめましたので、皆様の今後の学習に役立てていただければ幸いです。

美しいテキストと美しい写真

上記は、SQL インジェクションを防御するための mysql の高度な (24 の) メソッドの概要です。さらに関連する内容については、 PHP 中国語 Web サイト (www.php .cn)!


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。