クライアント=サーバー間の値の受け渡し (4/4)
作成:2012-05-03 13:27
更新:2012-05-03 14:08
更新:2012-05-03 14:08
■受け取ったデータのエスケープ処理
クライアントとサーバーの間でデータをやり取りする処理を覚えるとき、あわせて覚えておきたい事柄があります。それは「データのエスケープ処理」についてです。
ユーザーから送信された値を利用する場合、「ユーザーはどんな値を送信してくるかわからない」ということを頭に入れておく必要があります。特に考えないといけないのが、JavaScriptです。入力フィールドに、<script>タグを使ったスクリプトを既述して送信されたらどうなるでしょうか。そのテキストをそのまま画面に表示するような処理になっていた場合、ページが表示されると同時にスクリプトが実行されることになります。例えば、掲示板やコメント投稿のようなシステムの場合、そのようなスクリプトが投稿され表示されるようになってしまうと、そこに誰かがアクセスする度に意図しないスクリプトが実行されることになります。
一般にXSS(クロスサイトスクリプティング)攻撃と呼ばれるサイト攻撃は、この脆弱性を突いたものです。まぁ、ここでやっているようなサンプル程度のものであれば問題など起こりようがないでしょうが、データベースなどにデータを蓄積し表示をしていくようなものになると、この種のトラブルは避けて通れません。今の段階で、「どう対処したらいいか」ぐらいは覚えておきましょう。
この種の攻撃への対策の基本は、「テキストを出力する前に、エスケープ処理をしておく」というものです。例えば、HTMLのタグで使う<>といった記号を&lt;や&>に置換するだけで、それらのタグは無効になります。このように、特別な働きを持つ記号類をエスケープ処理することで、そのデータに含まれている機能を無効化するのです。
下のリスト欄に、ごく簡単なサンプルを挙げておきます。ここではテキストを送信すると、送られたテキストから<>\&といった記号類をすべてエスケープ処理して表示しています。エスケープ処理は、getEscapedStringというメソッドとして定義してあります。テキストを出力する際、書きだすテキストをgetEscapedStringでエスケープ処理し表示すればいいわけですね。
また、エスケープ処理を行うとき、注意すべきは「テキスト入力された値だけ処理すればいい、とは思わない」という点でしょう。ここでは、チェックボックスやラジオボタンの値までgetEscapedStringで処理をしています。「そんなの送られてくる値は決まってるんだから不要では?」と思うかも知れません。が、JSPではGETでもPOSTでも同じようにgetParameterで値が得られます。ということは、例えば、helo.jsp?check=hogehogeというようにURLを指定してアクセスすることで、checkに本来とは異なる値を渡せることになります。getMethodでPOSTのみ受け付けるような処理をしていなかった場合、そのままその値が処理されてしまうでしょう。
そんなわけで、プログラム内からクライアント側へテキストを出力するときは、常にエスケープ処理するよう心がけましょう、という話でした。
ユーザーから送信された値を利用する場合、「ユーザーはどんな値を送信してくるかわからない」ということを頭に入れておく必要があります。特に考えないといけないのが、JavaScriptです。入力フィールドに、<script>タグを使ったスクリプトを既述して送信されたらどうなるでしょうか。そのテキストをそのまま画面に表示するような処理になっていた場合、ページが表示されると同時にスクリプトが実行されることになります。例えば、掲示板やコメント投稿のようなシステムの場合、そのようなスクリプトが投稿され表示されるようになってしまうと、そこに誰かがアクセスする度に意図しないスクリプトが実行されることになります。
一般にXSS(クロスサイトスクリプティング)攻撃と呼ばれるサイト攻撃は、この脆弱性を突いたものです。まぁ、ここでやっているようなサンプル程度のものであれば問題など起こりようがないでしょうが、データベースなどにデータを蓄積し表示をしていくようなものになると、この種のトラブルは避けて通れません。今の段階で、「どう対処したらいいか」ぐらいは覚えておきましょう。
この種の攻撃への対策の基本は、「テキストを出力する前に、エスケープ処理をしておく」というものです。例えば、HTMLのタグで使う<>といった記号を&lt;や&>に置換するだけで、それらのタグは無効になります。このように、特別な働きを持つ記号類をエスケープ処理することで、そのデータに含まれている機能を無効化するのです。
下のリスト欄に、ごく簡単なサンプルを挙げておきます。ここではテキストを送信すると、送られたテキストから<>\&といった記号類をすべてエスケープ処理して表示しています。エスケープ処理は、getEscapedStringというメソッドとして定義してあります。テキストを出力する際、書きだすテキストをgetEscapedStringでエスケープ処理し表示すればいいわけですね。
また、エスケープ処理を行うとき、注意すべきは「テキスト入力された値だけ処理すればいい、とは思わない」という点でしょう。ここでは、チェックボックスやラジオボタンの値までgetEscapedStringで処理をしています。「そんなの送られてくる値は決まってるんだから不要では?」と思うかも知れません。が、JSPではGETでもPOSTでも同じようにgetParameterで値が得られます。ということは、例えば、helo.jsp?check=hogehogeというようにURLを指定してアクセスすることで、checkに本来とは異なる値を渡せることになります。getMethodでPOSTのみ受け付けるような処理をしていなかった場合、そのままその値が処理されてしまうでしょう。
そんなわけで、プログラム内からクライアント側へテキストを出力するときは、常にエスケープ処理するよう心がけましょう、という話でした。
(by. SYODA-Tuyano.)
※プログラムリストが表示されない場合
AddBlockなどの広告ブロックツールがONになっていると、プログラムリスト等が表示されない場合があります。これらのツールをOFFにしてみてください。
●プログラム・リスト●
※helo.jspのサンプル <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <% String inpt = request.getParameter("input"); inpt = inpt == null ? "" : inpt; String chk = request.getParameter("check"); chk = chk == null ? "OFF" : "ON"; String rd = request.getParameter("radio"); rd = rd == null ? "" : rd; String str = "INPUT:" + getEscapedString(inpt) + "<br>" + "CHECK: " + getEscapedString(chk) + "<br>" + "RADIO: " + getEscapedString(rd) + "<br>"; %> <%! public String getEscapedString(String s){ String str = s; str = str.replace("&","&"); str = str.replace("<","<"); str = str.replace(">",">"); str = str.replace("\"","""); return str; } %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Sample jsp</title> <style> h1 {font-size:16pt; background:#AAFFAA; padding:5px; } </style> </head> <body> <h1>Sample jsp page</h1> <p>これはサンプルで用意したページです。</p> <p><%=str %></p> <table> <form method="post" action="helo.jsp"> <tr><td>入力</td><td> <input type="text" id="input" name="input"></td></tr> <tr><td></td><td> <input type="checkbox" id="c1" name="check" value="Une"> <label for="c1">チェックボックス</label></td></tr> <tr><td></td><td> <input type="radio" name="radio" id="r1" value="first"> <label for="r1">ラジオボタン1</label><br> <input type="radio" name="radio" id="r2" value="Second"> <label for="r2">ラジオボタン2</label></td></tr> <tr><td></td><td> <input type="submit" value="送信"></td></tr> </form> </table> </body> </html>
※関連コンテンツ