非同期通信+SQLなどのセキュリティ対策
昔はページをいちいち読み込んで処理していたものを、最近はノンリロードで処理するケースが多くなっています。例えば郵便番号から住所を取得したり、条件にマッチしたデータを表示したりなど。
こういうときはjQueryの非同期通信などがとても役に立つのですが、知れば知るほど「危険じゃね?」と思ってしまうものです。javascriptに非同期通信先のファイル名を書く訳ですから、そのファイルへ直接的にアクセス出来ます。
何か入力してボタンを押すと、PHPと通信して現在時刻を足してキックバックしてきます。
$(function() { /* * ボタンを押したときの処理 */ $(document).on('click','#button',function(){ if(!$("#name").val()){ alert('なんか入力してね!'); return; } var data = $("#form").serialize(); //フォームの内容をシリアライズ //query.phpへフォームの入力内容を送信 $.ajax({ type: "POST", url: "query.php", data: data, dataType :'html' }).done(function(str){ alert(str); }); }); });
例えば、https://studio-key.com/Sample2/jquery/security/query.php は普通にブラウザから見る事が出来ます(Error)と表示されますが。なので、このファイルにSQL処理なんて書きたくはないわけです。
これがPHP同士の処理であれば.htaccessで拒否ってしまう手もあるのですが、非同期通信って普通のHTTP(SSL)通信なので拒否る訳にはいかず、色々と仕込みます。
ページを読み込んだ時にユニークな値をsessionに記録する
<?php session_start(); $_SESSION['hash'] = sha1( $_SERVER["REMOTE_ADDR"].$_SERVER['HTTP_USER_AGENT'] );
これは簡単にIPとHOST情報をハッシュ化してますが、ここにシステムごとのユニークな乱数をくっつけたりなどすると更に良いと思います。
非同期通信するquery.php側でその値と検証する
<?php session_start(); /* * ページを読み込んだ時の値と違えば拒否 */ if(sha1( $_SERVER["REMOTE_ADDR"].$_SERVER['HTTP_USER_AGENT'] ) != $_SESSION['hash']): echo 'Error'; exit; endif; /* * 必要な値が定義されていなければ拒否 */ if(!isset($_POST['name']) AND !$_POST['name']): echo 'Error'; exit; endif; /* * OKならsql.phpからキックバックを受け取る */ require_once('sql/sql.php'); echo sql::query($_POST['name']);
このファイルは値を受け取り、処理ファイルsql/sql.phpへ渡し、キックバックを受け取るだけの処理を行うものにします。また、sql/ディレクトリには.htacessでアクセス制限を掛けておきます。
ファイル構造はこんな感じ。ちなみにsql.phpは入力値に日時をくっつけてキックバックしてるだけで、SQL処理はしていません。
こうすると、index.phpで発行するユニークな値が無いと、query.phpにアタックを掛けてもエラーになり余計な情報を吐き出しません。しかし、それすら通り抜ける事も出来なくは無いので、index.phpへアクセスする場合は、指定されたページを経由させ、リファラを検証するとかも有効かも。でもリファラって偽装が可能で。
なので、query.phpで更にユニークを発行したり、更に経由ファイルを増やすなど、色々とやります。
非同期通信って手軽で便利だけど怖いよねってお話でした。