Ajaxãªã¢ããªã±ã¼ã·ã§ã³ã«ããã¦ããµã¼ãããJSONãè¿ãå ´åã«ãJSONèªä½ã¯validã§ããã«ãé¢ãããã(IEã®é½åã§)ã¨ã¹ã±ã¼ããä¸è¶³ãã¦ãã¦èå¼±æ§ã«ã¤ãªãã£ã¦ãå ´åãããã®ã§ãæ¸ãã¦ããã¾ãã
çºçãããããããªãèå¼±æ§
JSONã®ã¨ã¹ã±ã¼ããä¸è¶³ãã¦ããå ´åã«çºçããå¯è½æ§ã®ããèå¼±æ§ã¯ä»¥ä¸ã®éãã§ãã
ããããã®è©³ç´°ã«ã¤ãã¦ã¯å¾è¿°ãã¾ãã
éçºå´ã§ããã¹ããã¨
æååä¸ã®Unicodeæå㯠"\uXXXX" ãªå½¢å¼ã«ã¨ã¹ã±ã¼ãããã¨ã¨ãã«ãASCIIãªç¯å²ã§ãã£ã¦ãã/ãã<ãã>ãã+ããåæ§ã«ã¨ã¹ã±ã¼ããããã¨ã«ãããåè¿°ã®èå¼±æ§ãé²ããã¨ãã§ãã¾ãã
Perlã§ããã°ã以ä¸ã®ãããªæãã«ãªãã¾ããJSON->ascii(1) ã«ç¶ãã¦ãJSONæååãæ£è¦è¡¨ç¾ã§ç½®æãã¦ãããããããã¢ã«ãªãã¾ãã
use utf8; use Encode; use JSON; my $user = { 'mail' => '[email protected]', '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":"[email protected]","bio":"\u003cscript\u003ealert(1)\u003c\u002fscript\u003e"}
æ¬ ç¹ã¨ãã¦ã¯ããããã°ãªã©ã«ããã¦ç®è¦ã§JSONã®å 容ã確èªãã«ãããã¨ããµã¤ãºã大ãããªããã¨ããããã¾ãã
çºçãããããããªãèå¼±æ§ãã®1: æ©å¯æ å ±ã®æ¼ãã
ä¾ãã°Webã¡ã¼ã«ã«ãããæ°çä¸è¦§ãªã©ã®ããã«ãJSONå
ã«ç¬¬ä¸è
ã«ç¥ããã¦ã¯ãããªãæ©å¯æ
å ±ã¨æ»æè
èªèº«ãã³ã³ããã¼ã«å¯è½ãªæååã®ä¸¡æ¹ãå«ã¾ãã¦ããå ´å(Webã¡ã¼ã«ã®æ°çæ
å ±ã§ããã°æ»æè
ã¯ã¡ã¼ã«ãéãã ãã§ããããç¶æ³ãä½ãä¸ãããã¨ãã§ãã¾ã)ãæ»æè
ã¯ç½ ãã¼ã¸ã«è¢«å®³è
ãèªå°ãããã¨ã«ããJSONå
ã®æ©å¯æ
å ±ã«ãã¢ã¯ã»ã¹ãããã¨ãå¯è½ã«ãªãã¾ãã
JSONã以ä¸ã®ãããªãã®ã ã£ãã¨ãã¾ãã
[ { "name" : "abc+MPv/fwAiAH0AXQA7-var t+AD0AWwB7ACIAIg-:+ACI-", "mail" : "[email protected]" }, { "name" : "John Smith", "mail" : "[email protected]" } ]
JSONå
ã«ã¯ãµãã¤ã®ã¦ã¼ã¶åã¨ã¡ã¼ã«ã¢ãã¬ã¹ãå«ã¾ãã¦ããã[email protected] ã®ã»ãã® name ã¯ãæ»æè
èªèº«ãFrom:çã«è¨å®ãããã¨ã«ããæ¿å
¥ãããã®ã§ãã
æ»æè
ã¯ãã®ãããªJSONãJavaScript ã½ã¼ã¹ã¨ãã¦æå®ããç½ ãã¼ã¸ãç¨æããIE6/7ã使ç¨ãã¦ãã被害è
ãèªå°ãã¾ãã
<script src="http://target.example.com/newmail.json" charset="utf-7"> <script> alert( t[ 1 ].name + t[ 1 ].mail ); </script>
IE6ãIE7ã«ããã¦ã¯JSONã®å¿çã«ããã¦ã¬ã¹ãã³ã¹ããã㧠Content-Type: application/json; charset=utf-8 ã®ããã«æåã¨ã³ã³ã¼ãã£ã³ã°ãæå®ãã¦ããã¨ãã¦ããç½ ãã¼ã¸å ã® <script> è¦ç´ ã® charset å±æ§ãåªå ããã¦ãã¾ããçµæã¨ãã¦ä¸ã§ç¤ºããJSONã¯IE6ãIE7ã§ã¯ä»¥ä¸ã®ããã«è§£éããã¾ãã
[ { "name" : "abc"}];var t=[{"":"", "mail" : "[email protected]" }, { "name" : "John Smith", "mail" : "[email protected]" } ]
çµæãå¤æ° t ã«JSONå ã®å¾ç¶æååãæ ¼ç´ãããJavaScriptããèªç±ã«ã¢ã¯ã»ã¹ã§ãããããæ»æè ã¯JSONå ã«å«ã¾ããæ©å¯æ å ±(æ»æè èªèº«ãã³ã³ããã¼ã«ã§ããªãç¯å²ã®å 容)ãç¥ããã¨ãå¯è½ã«ãªãã¾ããIE8以éã«ããã¦ã¯ãã®åé¡ã¯è§£æ±ºããã¦ãã¾ãã
çºçãããããããªãèå¼±æ§ãã®2: XSS
ããç¥ããã¦ããIEã®Content-Typeç¡è¦ç
ã使ãã¨ãJSONãHTMLã¨èª¤èªèããããã¨ã«ãã£ã¦XSSãçºçããããããã¨ãããã¾ãã
ä¾ã¨ãã¦ã<script> ã®ãããªHTMLæååã®æçãå«ãJSONã 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 ãå¿çãã¦ãã¾ãããIEã«ã¨ã£ã¦application/jsonã¨ããContent-Typeã¯æªç¥ã®ãã®ã§ãããããURLã«å°ãç´°å·¥ãæ½ã http://utf-8.jp/cgi-bin/json-xss.cgi?a.html ã®ãããªããã¡ã§IE6ãIE7 ã§ã¢ã¯ã»ã¹ããã¨ãURLããã³ã³ãã³ããHTMLã§ããã¨å¤æãã*1XSSãçºçãã¾ãã
ãªãIE8ã§ã¯ãX-Content-Type-Options: nosniff ãæå®ãããã¨ã«ãããéHTMLãHTMLã«ææ ¼ãããã¨ãæãããã¨ãã§ãã¾ãã
ãã®ä»ã®å¯¾çæ¹æ³
JSONãéå°ã«ã¨ã¹ã±ã¼ããã以å¤ã«ããä¾ãã°
- XHRããã®ãªã¯ã¨ã¹ããããã« X-Requested-With: XMLHttpRequest ãªã©ãä»ä¸ãããµã¼ãå´ã§ããã確èª
- POSTã®ã¿åãå ¥ããGETè¦æ±ã§ã¯JSONãå¿çããªãããã ããXSS対çã«ã¯ä½¿ããªãã
- JSONã®ãã©ã¼ããããinvalidãªãã®ã«ãããå é ã«"while(1);"ãªã©ãå ¥ãããªã©ãGoogleæ¹å¼ããã ããXSS対çã«ã¯ä½¿ããªãã
ãªã©ã®å¯¾çãç¥ããã¦ãã¾ã(ä¸2ã¤ã¯ãã¾ãå§ããããªã)ã
ãã以å¤ã®æ¹æ³ãããã°æãã¦ãã ããã
ã¾ã¨ã
IE6ã ãççºãã¦ã解決ããªãã®ã§ãIE7ã¨ã¤ãã§ã«IE8ãççºãã¹ããIE8ãæ±ãã(ãççºãã¹ããã«ç¸å½ãã)åé¡ã«ã¤ãã¦ã¯ããå°ãå½±é¿åº¦ãä¸ãã£ã¦ãã(ã·ã§ã¢æ¸ãã®ãå ããä¿®æ£ãããã®ãå ãâ¦)æ¸ãã¾ããâ æ¸ãã¾ãã
*1:ãæ¡å¼µåã§ã¯ãªããå 容ã«ãã£ã¦ãã¡ã¤ã«ãéãããç¡å¹ã«è¨å®ãã¦ãã¦ãHTMLæ±ãããã¾ã