JSONのエスケープをどこまでやるか問題


AjaxJSONJSONvalid(IE)

発生するかもしれない脆弱性

JSONエスケープが不足している場合に発生する可能性のある脆弱性は以下の通りです。

  • JSON内に含まれる機密情報の漏えい
  • XSS

それぞれの詳細については後述します。

開発側でやるべきこと


Unicode "\uXXXX" ASCII/<」﹁>+
PerlJSON->ascii(1) JSON
use utf8;
use Encode;
use JSON;
my $user = { 
    'mail' => 'hasegawa@example.com',
    'name' => 'はせがわようすけ',
    'bio' => '<script>alert(1)</script>',
};
my $json = new JSON;
my $json_text = $json->ascii(1)->encode( $user );
$json_text =~ s/([<>\/\+])/sprintf("\\u%04x",ord($1))/eg; 
print "$json_text\n";
{"name":"\u306f\u305b\u304c\u308f\u3088\u3046\u3059\u3051","mail":"hasegawa@example.com","bio":"\u003cscript\u003ealert(1)\u003c\u002fscript\u003e"}

JSON

発生するかもしれない脆弱性その1: 機密情報の漏えい


WebJSON(Web)JSON
JSON
[
  {
    "name" : "abc+MPv/fwAiAH0AXQA7-var t+AD0AWwB7ACIAIg-:+ACI-",
    "mail" : "hasegawa@example.jp"
  },
  {
    "name" : "John Smith",
    "mail" : "john@example.com"
  }
]

JSONhasegawa@example.jp  name From:
JSONJavaScript IE6/7使
<script src="http://target.example.com/newmail.json" charset="utf-7">
<script>
    alert(t[ 1 ].name + t[ 1 ].mail );
</script>

IE6IE7JSON Content-Type: application/json; charset=utf-8  <script>  charset JSONIE6IE7
[
  {
    "name" : "abc"}];var t=[{"":"",
    "mail" : "hasegawa@example.jp"
  },
  {
    "name" : "John Smith",
    "mail" : "john@example.com"
  }
]

tJSONJavaScriptJSON()IE8

発生するかもしれない脆弱性その2: XSS


IEContent-Type使JSONHTMLXSS
<script> HTMLJSON http://utf-8.jp/cgi-bin/json-xss.cgi 
Content-Type: application/json; charset=utf-8
X-Content-Type-Options: nosniff;

{ "foo" : "<script>alert(document.location)</script>" }

Content-Type  application/json IEapplication/jsonContent-TypeURL http://utf-8.jp/cgi-bin/json-xss.cgi?a.html IE6IE7 URLHTML*1XSS
IE8X-Content-Type-Options: nosniff HTMLHTML

その他の対策方法


JSON


XHR X-Requested-With: XMLHttpRequest 

POSTGETJSONXSS使

JSONinvalid"while(1);"GoogleXSS使


(2)

まとめ

IE6だけ爆発しても解決しないので、IE7とついでにIE8も爆発すべき。IE8が抱える(「爆発すべき」に相当する)問題についてはもう少し影響度が下がってから(シェア減るのが先か、修正されるのが先か…)書きます。→ 書きました

*1:「拡張子ではなく、内容によってファイルを開く」を無効に設定していてもHTML扱いされます