Mybatis s s sql注入防止の例


sql注入はよく知られていません。攻撃方法です。攻撃者は界面のフォーム情報やurlに変なsqlセグメントを入力します。例えば「or‘1’='1’」という文はパラメータチェックが足りないアプリケーションに侵入する可能性があります。だから、私たちの応用の中で、このような攻撃方法を防ぐために、いくつかの仕事が必要です。いくつかの安全性の高いアプリケーションでは、銀行ソフトなど、sql文を全部記憶過程に置き換えてsql注入を防止するという方法がよく使われています。これはもちろん安全な方法ですが、普段開発しているうちに、このような堅苦しい方法は必要ないかもしれません。
mybatisフレームは半自動化の耐久層フレームとして、sql文は自分達で手動で書かなければなりません。この時はもちろんsql注入を防ぐ必要があります。実はMybatisのsqlは、関数のような「入出力」機能を持つ構造です。

<select id="getBlogById" resultType="Blog" parameterType=”int”>
  select id,title,author,content
  from blog where id=#{id}
 </select>
ここで、parameterTypeは入力のパラメータタイプを示しており、出力のパラメータタイプを示しています。上記に対応して、sql注入を防止するためには、当然ながら入力パラメータを工夫します。上のコードのハイライト部分は、入力パラメータがsqlで綴り付けられている部分です。パラメータが入ってきたら、実行されているsql文を印刷します。sqlはこのように見えます。

select id,title,author,content from blog where id = ?
どのパラメータを入力しても、印刷されたsqlは全部このようです。これはmybatisがプリコンパイル機能を有効にしています。sqlが実行される前に、上のsqlをデータベースに送ってコンパイルします。実行する時、直接にコンパイルしたsqlを使って、プレースホルダを交換します。いいです。sql注入はコンパイルプロセスにしか作用しないので、sql注入の問題はよく避けられます。
mybatisはどうやってsqlのプリコンパイルができますか?実際には、フレームの下に、jdbcのPreparedStatimentクラスが働いています。PreparedStatimentは私たちがよく知っているSttementのサブクラスです。そのオブジェクトは良いsql文をコンパイルしています。このような「準備」の方式は安全性を高めるだけでなく、一つのsqlを何回も実行する時、効率を高めることができます。
ところで、mybatisを使って、sql注入を防げますか?もちろん違います。下のコードを見てください。

<select id="orderBlog" resultType="Blog" parameterType=”map”>
  select id,title,author,content
  from blog order by ${orderParam}
 </select>
よく観察してみると、インラインパラメータのフォーマットは「{xxx}」から$もし私たちがパラメータ「order Param」に「id」を割り当てたら、sqlをプリントアウトします。
select id,title,author,content from blog order by id
     明らかに、これはsql注入を阻止することができません。mybatisでは、「{xxx}」というフォーマットのパラメータが直接sqlコンパイルに参加し、注入攻撃を避けることができません。しかし、ダイナミックなテーブル名と列名に関しては、「$xxx」というパラメータ形式しか使えませんので、このようなパラメータはコードの中で手動で処理して注入を防ぐ必要があります。
    結論:mybatisのマッピングステートメントを作成する際には、できるだけ「嚔{xxx}」というフォーマットを採用します。このようなパラメータを使わなければならないならば、手でフィルター作業をして、sql注入攻撃を防止します。