Webセキュリティの小部屋

Twitter のフォローはこちらから Facebook ページはこちら RSSフィードのご登録はこちらから
公開日:2013年8月5日
最終更新日:2020年8月13日

JSON セキュリティ:PHP で JSON を扱う

JSON のセキュリティ対策は、以下の記事に記載した通りですが、これを PHP では組み込み関数で実現します。この記事では、JSON セキュリティ対策のサンプルプログラムを提示します。

PHP のクラスインスタンスを JSON に変換するには、組み込み関数のjson_encode を使用します。json_encode は、クラスインスタンスだけではなく、配列なども簡単に JSON に変換できます。

概要

この記事で作成する Web サービスでは、json_encode を使用して PHP クラスのインスタンスを JSON に変換します。PHP の場合は配列などを扱う方が適切かもしれませんが、他の言語のサンプルに合わせています。

クライアントからリクエストを受け取ると、Web サービスは該当するデータを検索して、一致したデータを JSON の形式でクライアントに返します。

呼び出し元のクライアントは、jQuery と prototype.js を使用した HTML を作成します。

Web サービスの作成

GET リクエストでパラメーターを受け付け、JSON で値を返すよう定義します。

・json.php

<?php

//リクエストヘッダーチェック
$headers = getallheaders();

if ($headers["X-Requested-With"] != "XMLHttpRequest") {
  header("HTTP/1.1 403 Forbidden");
  exit;
}

//パラメータ取得
$name = $_GET["name"];

//名前検索
$person = searchList($name, createList());

//セキュリティヘッダー付与
header("Content-Type: application/json; charset=utf-8");
header('X-Content-Type-Options: nosniff');

//JSON 出力
echo json_encode($person);

//Person クラス
class Person {
  var $name;
  var $age;

  function  __construct($_name, $_age) {
    $this->name = $_name;
    $this->age = $_age;
  }
}

//配列を作成
function createList() {
   $list =  array();
   $list[] = new Person("Yamada", 10);
   $list[] = new Person("Sato", 20);
   $list[] = new Person("Tanaka", 30);

   return $list;
}


//配列を検索
function searchList($name, $list) {
  foreach ($list as $person) {
    if ($person->name == $name) {
      return $person;
    }
  }

  return null;
}

?>

クライアントの作成

Web サービスにリクエストを送信し、レスポンスのデータを表示するクライアントを作成します。レスポンスのデータを表示する際、HTML エスケープしていることに注意してください。

jQuery で作成

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  <title></title>
  <script src="js/jquery-2.0.3.min.js"></script>
  <script type="text/javascript">
    $.ajax({
      type: "GET",
      url: "/json.php",
      data: 'name=Yamada',
      success: function (data, textStatus, xhr) {
 
        //HTML escape and append
        $("#person").text(data.name + " " + data.age);
      }
    });
  </script>
</head>
<body>
  <div id="person"></div>
</body>
</html>

実行結果は、以下のようになります。

Yamada 10

jQuery によって、以下の行がリクエストヘッダーに追加されていることに注意してください。

  • X-Requested-With: XMLHttpRequest

GET http://192.168.11.9/json.php?name=Yamada HTTP/1.1
Host: 192.168.11.9
Connection: keep-alive
Accept: */*
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36
Referer: http://192.168.11.9/json1.html
Accept-Encoding: gzip,deflate,sdch
Accept-Language: ja,en-US;q=0.8,en;q=0.6

以下の2行が、レスポンスヘッダー追加されていることに注意してください。

  • Content-Type: application/json; charset=utf-8
  • X-Content-Type-Options: nosniff

HTTP/1.1 200 OK
Date: Mon, 05 Aug 2013 02:41:42 GMT
Server: Apache
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Content-Length: 26
Connection: close
Content-Type: application/json; charset=utf-8

prototype.js で作成

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  <title></title>
  <script src="js/prototype.js"></script>
  <script type="text/javascript">
    new Ajax.Request("/json.php", {
      method: "GET",
      parameters:{name:"Yamada"},
      onSuccess: function (data) {
        //Text to JSON and security check
        var json = data.responseText.evalJSON(true);
        var str = json.name + " " + json.age;
        $("person").update(str.escapeHTML()); //HTML escape and update
      }
    });
 
  </script>
</head>
<body>
  <div id="person"></div>
</body>
</html>

実行結果は、以下のようになります。

Yamada 10

prototype.js によって、以下の行がリクエストヘッダーに追加されていることに注意してください。

  • X-Requested-With: XMLHttpRequest

GET http://192.168.11.9/json.php?name=Yamada HTTP/1.1
Host: 192.168.11.9
Connection: keep-alive
Accept: text/javascript, text/html, application/xml, text/xml, */*
X-Prototype-Version: 1.7.1
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36
Referer: http://192.168.11.9/json2.html
Accept-Encoding: gzip,deflate,sdch
Accept-Language: ja,en-US;q=0.8,en;q=0.6

以下の2行が、レスポンスヘッダー追加されていることに注意してください。

  • Content-Type: application/json; charset=utf-8
  • X-Content-Type-Options: nosniff

GET http://192.168.11.9/json.php?name=Yamada HTTP/1.1
Host: 192.168.11.9
Connection: keep-alive
Accept: text/javascript, text/html, application/xml, text/xml, */*
X-Prototype-Version: 1.7.1
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36
Referer: http://192.168.11.9/json2.html
Accept-Encoding: gzip,deflate,sdch
Accept-Language: ja,en-US;q=0.8,en;q=0.6

参考

Webアプリケーションセキュリティに関する記事は、以下のページにまとまっています。ぜひご確認ください。


スポンサーリンク





カテゴリー:Webアプリケーションセキュリティ対策

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA