MyBatisはSQL注入を防止する方法

2517 ワード

SQL注入は、データ駆動アプリケーションを攻撃するためのコード注入技術であり、実行されるエンティティフィールドに悪意のあるSQL文が挿入される
SQL注入は、一般的な攻撃方法です.攻撃者はインタフェースのフォーム情報やURLに奇妙なSQLフラグメント(例えば「or‘1’=’1’」のような文)を入力し、パラメータチェックが不足しているアプリケーションに侵入する可能性があります.そのため、私たちの応用では、このような攻撃方式に備えていくつかの仕事をする必要があります.セキュリティ要件の高いアプリケーション(銀行ソフトウェアなど)では、SQL文をすべてストレージ・プロシージャに置き換える方法がよく使用され、SQL注入を防止します.これはもちろん安全な方法ですが、私たちは普段開発中なので、このような堅苦しい方法は必要ないかもしれません.
MyBatisフレームワークは、半自動化された永続層フレームワークとして、SQL文を手動で作成する必要があります.この場合、SQL注入を防ぐ必要があります.実は、MyBatisのSQLは「入力+出力」の機能を持ち、関数のような構造で、以下のようになっています.


parameterTypeは入力のパラメータタイプ、resultTypeは出力のパラメータタイプを表します.SQL注入を防ぐためには,当然入力パラメータに工夫を凝らす必要がある.id=#{id}:入力パラメータがSQLでつづられた部分で、パラメータが入力された後、実行されたSQL文が印刷され、SQLが次のように表示されます.
SELECT id,title,author,content FROM blog WHERE id = ? MyBatisはプリコンパイル機能を有効にし、SQLが実行される前に、上のSQLをデータベースに送信してコンパイルします.実行時、コンパイルしたSQLをそのまま使用して、プレースホルダ「?」を置き換えます.それでいいです.SQL注入はコンパイルプロセスにしか機能しないため,このような方式ではSQL注入の問題をうまく回避できる.【下位実装原理】MyBatisはどのようにSQLプリコンパイルを行いますか?実はフレームワークの底には、JDBCのPreparedStatementクラスが働いています.PreparedStatementは私たちがよく知っているStatementのサブクラスで、そのオブジェクトにはコンパイルされたSQL文が含まれています.このような「準備」方式は、セキュリティを向上させるだけでなく、同じSQLを複数回実行する際に効率を向上させることができます.SQLがコンパイルされているため、再実行時にコンパイルする必要はありません.MyBatisを使えば必ずSQL注入を防ぐことができますか?もちろん違います.次のコードを見てください.


インラインパラメータのフォーマットは「#{xxx}」から「${xxx}」に変わります.パラメータ「id」に「3」を割り当てると、SQLが印刷されます.
SELECT id,title,author,content FROM blog WHERE id = 3





インラインパラメータのフォーマットは「#{xxx}」から「${xxx}」に変わります.パラメータ「orderParam」に「id」を割り当てると、SQLはそのまま印刷されます.
SELECT id,title,author,content FROM blog ORDER BY id

これではSQL注入を阻止することはできません.MyBatisでは、「${xxx}」のようなフォーマットのパラメータがSQLコンパイルに直接関与し、注入攻撃を避けることはできません.ただし、ダイナミックテーブル名とカラム名については、${xxx}のようなパラメータフォーマットしか使用できません.したがって,このようなパラメータは,注入を防止するためにコード内で手作業で処理する必要がある.
できるだけ「#{xxx}」というフォーマットを採用します.「${xxx}」パラメータを使用しなければならない場合は、SQL注入攻撃を防止するためにフィルタリングを行います.#{}:JDBCのPreparedStatementに相当${}:出力変数の値#{}は事前にコンパイルされ、安全です.${}はプリコンパイルされておらず、変数の値を取るだけで、安全ではなく、SQL注入が存在します.