うちの会社の話です。ある会員用ウェブサイトにおいて、ログイン後のページではその会員のIDをinputタグをhiddenにして保持するという方法をとり、全ページPOSTで送信するようにして、それぞれのページで会員の情報を得るという手法をとっていたのですが、これだとログイン後、inputタグのhidden内のIDだけを書き換えると、簡単に他の会員の情報が見えてしまうということが発覚しました。
他にも、3種類の選択肢が用意されているセレクトボックスがあったのですが、それぞれのoptionタグのvalue値は、『2』『3』『4』というようなものでした(実際は少し違うのですが、こんな感じです)。気になる人は気になると思いますが、なぜ『1』がなく、2からなのかと。そこで、optionタグのvalue値、例えば現在『2』となっているvalue値を『1』と書き換え、その箇所を選択すると・・・。なんと、その会員には見せてはいけない情報がズラリ。
上記は上司や先輩社員に報告することにより解決に至ったのですが、その時の上司や先輩社員の反応は、「えっ? そんなことできるの?」という感じをうけました。「GET渡しからPOST渡しに変更したうえに、リファラチェックしてるんだよ?」という感じで(注:あくまで自分の勝手なイメージです)。
結論からいうと、簡単にできます。ブラウザに付属のWeb開発者ツールをつかえば。Web開発者ツールとは、IE(8以上)では『F12 開発者ツール』、Chromeでは『Developer Tools』、Firefoxでは『開発ツール』と呼ばれてるものです(Firefoxはむしろ、『Firebug』のほうが有名ですが、Firebugはアドオンをインストール必要があり、『開発ツール』は標準で付属しているという違いがあります。機能面でいえば『Firebug』のほうが多いので、ウェブ制作に関わってる人なら『Firebug』をインストールしたほうがいいと思われます)。
では、その方法を簡単に説明します。
今回は、サンプルとして前回のHTMLのテキストボックスを、できるかぎり半角数値のキー入力のみにするで作成した半角数値しか入力できないようにしたテキストボックスから数値以外のテキストを入力し、送信する方法を三種類ご紹介。
下記ページが今回利用するページです。
テキスト入力項目の制限
HTMLとJavaScriptとPHPは下記のようになっています。
HTML
<form method="post" name="OnlyNumForm"> <input name="OnlyNum" style="ime-mode: disabled;" onkeydown="return OnlyNumber(event)" oncontextmenu="return false;" type="text" placeholder="数値のキー入力のみ" autocomplete="off"> </form>
JavaScript
function OnlyNumber(evt) { var evt = evt || window.event; var c = evt.keyCode; // 0~9のキー、96~105=テンキーの0~9、8=バックスペース、9=タブキー、13=エンターキー、17=Ctrlキー、32=スペースキー、37=左矢印キー、39=右矢印キー、46=Deleteキー、18=Altキー、112~123=F1~F12キー、 if((48<=c && c<=57) || (96<=c && c<=105) || c==8 || c == 9 || c==13 || c==17 || c==32 || c == 37 || c == 39 || c == 46 || c == 18 || (112<=c && c<=123) ){ return true; } return false; }
PHP
if( !isset($_POST["OnlyNum"]) ){ echo '上のテキストボックスに何か入力してエンターキーを押してね!'; }else if($_POST["OnlyNum"] == ""){ echo '上のテキストボックスに何か入力してエンターキーを押してね!'; }else if("http://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]== $_SERVER["HTTP_REFERER"]){ echo '先ほど入力された内容は、『' . $_POST["OnlyNum"] . '』です<br>'; if( preg_match("/^[0-9]\d*$/",$_POST["OnlyNum"]) ){ echo '数値だね!!'; }else{ echo 'おっかしいな~。数値じゃないよ~'; } }
HTMLとJavaScript側では、数値以外の値が入力できないようなテキストボックスを用意しています。formタグ内のテキストボックス内でエンターキーを押すと、フォームを送信するという仕様を利用して、エンターキーを押すと同じページに送信するようにしています。
PHP側では、POSTで渡されたOnlyNumの値をみて、数値かどうか判定しています(7行目)。特別今回の記事に必要なわけではありませんが、5行目でリファラと自身のページの情報をチェックし、同じかどうかを判定しています。
まずは開発者ツールの表示方法を説明。ChromeかIEかFirebugならF12キーを、Firefoxの開発者ツールならCtrl+Shift+Iキーを押してみてください。すると、ブラウザの下にHTMLのDOMツリーが書かれたツールが表示されると思います。これが開発者ツールです。以下、画像はChromeのDeveloper Toolsです。
このDOMツリーはソースコード(Ctrl+U で表示したソース)と全く同じというわけではなく、JavaScriptで変更したものが反映された結果となっています(その他にも、DOMツリーの仕様にしたがって変更されていることがあります)。
以下、このWeb開発者ツールを使って数値のみの入力制限をしているテキストボックスに数値以外を入れる方法を、三種類説明します。
その1
1つ目の方法は、入力制限を取り除く方法です。
まず、Chromeだと左下の虫眼鏡のようなアイコン、IEやFirefoxだと左上の矢印のアイコンをクリックし、その後にテキストボックスをクリックしてみてください。そうすると、開発者ツールの中のDOMツリーが、テキストボックスの箇所を選択した状態となります。
つづいて、テキストボックス中の、onkeydown属性の中、『return OnlyNumber(event)』をダブルクリックするとその箇所が編集できるようになるので、onkeydown属性の中身を削除してください。
これで、テキストボックスの中に数値以外の値が入力できるようになりました。試しに、『aiueo』と入力してエンターキーを押した結果は以下のようになります(style属性の中を削除するとIEとFirefoxで全角を入力できるようになり、oncontextmenu属性の中を削除すると右クリックしてメニューを表示させることができるようになります)。
その2
2つ目の方法は、ツール内で直接、値を入力する方法です。
テキストボックスの要素を選択してそのコード上で右クリックします。すると、メニューが表示されるので、Chromeでは『Add Attribute』、IEでは『属性の追加』、Firebugでは『新規属性』をクリックしてください。
すると、入力ボックスがでてくると思うので、そこに『value="aiueo"』などとして、value属性を追加し、その中に文字を入力してみてください。(Firefoxの開発者ツールでは属性を追加するという項目はないよう。仕方がないので、適当にどこか(例えば、『autocomplete="off"』上)でダブルクリックし、そのテキスト入力項目内の最後に『value="aiueo"』と追加してみてください)。
上記の作業をすることにより、ブラウザ上のテキストボックスにもvalue属性にいれた文字が入るはずです。その状態でテキストボックスにフォーカスをあてたあと、エンターキーを押すことによって数値でない値が送信されます。
その3
3つ目の方法は、コンソールを使う方法。ちょっとだけ難しくなりますが、JavaScriptが分かるのであれば難しくありません。
まず、開発者ツールの上部にある『Console』もしくは『コンソール』タブをクリックしてみてください。すると、開発者ツール内がコンソールモードに切り替わります。
そしてそのコンソール内に、『document.querySelector('input').value="aiueo"』と入力して、エンターキーを押してみてください(querySelectorについては、右記を参考:document.querySelector - Web API リファレンス | MDN)。
すると、テキストボックス内に『aiueo』と入力された状態になるので、先ほどと同じく、テキストボックスにフォーカスをあてて、エンターキーを押します。すると、数値でない『aiueo』という値が送信されます。
ところで、ChromeとFirefoxのWeb開発者ツールにはコマンドラインAPIというものが用意されており、その1やその2でしたように、テキストボックスの要素を選択状態にした後、コンソール画面にいって『$0.value="aiueo"』としても同じ動作をします。この$0というのがコマンドラインAPIで、$0は直前で選択した要素を返すAPIとなっています。コマンドラインAPIについてはそのうち書くかもしれません。
以上、inputタグ内のvalue値を変更する方法を3つ紹介しました。これ以外にもあるかもしれませんが、思いつくかぎり3つです。
もちろん、上記で紹介した方法はinputタグ内のvalue値を変更する方法以外にも利用できます。例えば、style属性を追加してレイアウトを変更することもできますし、onclick属性を追加して新たにクリックした時に発生するイベントを追加することも簡単にできます。
いろいろ気になった箇所を変更してみると、新たに脆弱性が発見できるかもしれませんね。mixiでは脆弱性報告制度なんてものができたので、これでお小遣いを増やすこともできるかも? (参考:脆弱性報告制度 << mixi Developer Center (ミクシィ デベロッパーセンター))
まあ、さすがにmixiぐらいの規模のサイトが、こんな簡単に変更できるような脆弱性を持ち合わせているとは思いませんが(あえて、『思いたくありませんが』とは書いてません・・・)。
以下、応用問題。
今回のサンプルで、送信前にJavaScriptで半角数値かどうかのチェックをいれたら、半角数値以外の値を送ることはできないんじゃないか? なんて思われた方もいるかと思いますが、そんなことはありません。
それ用のサンプルページも作ってみました:テキスト入力項目のチェック
今回はjQeuryを外部JavaScriptとして呼び出すようにし、JavaScriptのコードは以下のように変更しています。
$(function(){ $('form').bind('submit',function(){ var onlyNumText = $(this).find('input[name="OnlyNum"]').val(); if( onlyNumText.match(/[^0-9]+/) ){ alert("半角数値を入力してね!"); return false; } }); });
簡単に説明すると、フォーム送信時にテキストボックス内が半角数値かどうかチェックして、半角数値でなければアラートを出して注意を促し、送信しないという動作になっています(実は言うとこのコードでは何も入力しないと送信してしまうのですが、あくまで半角数値以外の値を入力することを考えてみてください)。
上記のページでどうやって数値以外の値を送信するかは次回説明しようと思います。
コメント