PHPのイタい入門書を読んでAjaxのXSSについて検討した(2)〜evalインジェクション〜


 AjaxXSSXSS
 PHPWebXAMPP/jQuery/HTML5WeAjaxP201-23


 AjaxXMLHttpRequestXMLJSONJavaScriptHTMLAjax




XMLJSON

HTTP(5) 





HTML
 FHTMLXSSHTMLXSS
 BD

本書固有の「<i>」で区切る形式


 JSON使HTMLi<i>
30<i>山田<i>ABC<i>234-5678<i>Bコース<i>5<i>2010-04-29<i>2010-04-30

 out.split("<i>")
 CSV<i>1
 <i>

JSON形式の説明


 JSON(JavaScript Object Notation)JavaScriptJSON5.8 [PHP]JSONJSON
 JSONChap7/revxmasjson.htmChap7/revxmasjson.phpJSON
PHP
$rows = mysql_query("select * from xmastran where book_id = '$book_id'");
if($rows > 0){
  $row = mysql_fetch_assoc($rows);
  //header("Content-Type: text/javascript; charset=utf-8"); 
  echo json_encode($row);
}else {
  echo "参照不成功:book_id = ".$book_id;
}

 JSONheader1SQL
$rows = mysql_query("select * from xmastran where book_id = '$book_id'");
if($rows && mysql_num_rows($rows) > 0) {
  $row = mysql_fetch_assoc($rows);
  //header("Content-Type: text/javascript; charset=utf-8");
  $row['stat'] = "参照成功:book_id = ".$book_id;
  echo json_encode($row);
}else {
  echo '{"stat":"参照不成功:book_id = ' . $book_id . '"}';
}

 2JSONJSONjson_encode使JSONJSON
{"book_id":"30","name":"\u5c71\u7530","org":"ABC","addr":"\u677f\u6a4b\u533a","tel":"234-5678","mail":"b@example.jp","course":"B\u30b3\u30fc\u30b9","nums":"5","adddate":"2010-04-29","moddate":"2010-04-30","stat":"\u53c2\u7167\u6210\u529f\uff1abook_id = 30"}

 
var query = {};
$(function(){ 
  $("#rev").click(function(){   // id=revのイベントハンドラ
    query["book_id"] = $("#book_id").val();  // XHRのクエリストリング
    $.get("revxmasjson.php", query, show);   // XHRの呼び出し
  });
// 中略
});
function show(out){  // $.getのイベントハンドラ
  alert("out="+out);
  var json = eval(out);
  //var json = eval("("+json+")");
  alert(json);
/* 注:以下他のスクリプトから流用した表示機能のコメントアウトが続く */
}

 alertevalshow
function show(out){
  var res = eval("("+out+")");
  clearui(); // 画面クリア(別の箇所で定義済み)
  var fields = ['name', 'org', 'addr', 'tel', 'mail', 'course', 'nums', 'stat'];
  $.each(fields, function() {
    if (res[this]) {
      $("#" + this).text(res[this]);
    }
  });
}

 2outJSON*1jQuery
 JavaScriptHTMLJSONxmastrantdid使
 


JSONエスケープとevalインジェクション


 JSONJSONJavaScriptevalPHPjson_encode使JSONjson_encodejson_encodejson_encode使JSON
 JSON
  echo '{"stat":"参照不成功:book_id = ' . $book_id . '"}';

$book_id
"+alert(1)+"

JSON
{"stat":"参照不成功:book_id = "+alert(1)+""}

JSONalertJSONJavaScritevalalert


 使JavaScriptJavaScriptbook_ideval

対策


 evalJSON"\"\\\json_encode
  echo json_encode(array('stat' => "参照不成功:book_id = $book_id"));

 evaljQueryjQueryJSONJavaScriptgetgetJSONeval
    $.get("revxmasjson.php", query, show);   // XHRの呼び出し
   ↓
    $.getJSON("revxmasjson.php", query, show);   // XHRの呼び出し

function show(out){
  var res = eval("("+out+")");
     ↓
function show(res){
  // evalは不要となる

 evaljQuerygetJSONJSONeval
 JSONPHPjQueryeval
 

まとめ


 Ajax/JSONXMLJSONCSVJSONeval
 

補足


 
  $("#" + this).text(res[this]);

 text$("#" + hogehoge)


jQueryXSS - 0   - subtech

jQuery | 


 ids<s>this is a pen</s>#
  $("#" + "<s>").text("this is a pen.");

 onerrorimg
 var id = '<img src="!" onerror="alert(1)">';
 $('#'+id).text(text);

 !onerroralert
 3

[PR]

*1:本書P144にはJSONの動くサンプルが記載されていますが、こちらは配列形式のJSONなので括弧で囲む必要がないのでした