[PR]小規模ECサイトに最適なWAF、SiteGuard Lite

徳丸浩の日記


2010年01月18日

_iモードブラウザ2.0のXMLHttpRequestでPOSTデータの扱いが困難になった

このエントリでは、iモードブラウザ2.0の制限により、XMLHttpRequestでPOSTメソッドの利用が困難になっていることを確認したので報告する。

iモードブラウザ2.0のJavaScriptを試していて、POSTメソッドでデータが渡せていないことに気がついた。以下のようなプログラムで検証してみた。

【post.html】
<html>
<head>
<script>
function test() {
  try {
    var requester = new XMLHttpRequest();
    requester.open('POST', '/dumppost.php', true);
    requester.onreadystatechange = function() {
       if (requester.readyState == 4) {
           onloaded(requester);
       }
    };
    requester.setRequestHeader("Content-Type" , "application/x-www-form-urlencoded");
    requester.send("aaa=bbb&ccc=ddd");
  } catch (e) {
    res = requester.responseText;
    document.getElementById('result').innerHTML = e.toString();
  }
}

function onloaded(requester) {
  res = requester.responseText;
  document.getElementById('result').innerHTML = res;
}
</script>
</head>
<body>
<input type=button value="go" onclick="test()">
<div id="result"></div>
</body>
</html>

【dumppost.php】
<?php
echo "aaa=" . htmlspecialchars($_POST['aaa'], ENT_QUOTES, 'Shift_JIS') . "<br>";
echo "ccc=" . htmlspecialchars($_POST['ccc'], ENT_QUOTES, 'Shift_JIS') . "<br>";
?>

実行結果は、以下のようになった。まずはChromeのものだが、IEやFirefoxでも同等の結果だ。

Choromeでの結果

次に、ドコモP-07Aによる結果

P-07Aでの結果

ドコモの場合を検証するために、Webサーバーに来ているリクエストをキャプチャしてみた。

POST /dumppost.php HTTP/1.1
X-UE-Version: 1
Host: XXXXXXXXXXXXX
User-Agent: DoCoMo/2.0 P07A3(c500;TB;W24H15)
Content-Type: text/xml
Content-Length: 15

aaa=bbb&ccc=ddd

ご覧のようにPOSTデータそのものは送信されてきているが、Content-Typeがtext/xmlになっているために、Webアプリケーション側で受け取れないようだ。

JavaScript側では、この値をapplication/x-www-form-urlencodedに変更しているが、P-07AでもJavaScriptが再開され、あらたな制限がみつかったで報告したように、setRequestHeaderが無効化されているために、この設定が無視されていることが原因のようだ。

これは明らかに、setRequestHeader無効化の副作用であるが、その代償は大きいように思う。PHP以外に、ASP/ASPX、J2EE(JSP)にこのデータを入力してみたが、いずれも値を読み取ることはできなかった。一方、PerlのCGIモジュールでは、POSTDATAという名称のデータとして、POSTデータ全体を読み取ることができた。Perl以外の場合でも、Webサーバーにデータ自体は到達しているのだから値を利用する手段はあるかもしれないが、私が調べた範囲では分からなかった。

上記の結果として、AjaxでPOSTメソッドを扱うには、標準的でない方法を用いる必要があるわけだが、その方法を検討してみた。

  1. POSTをあきらめてGETを使う
  2. Perlのように、text/xml形式のデータを読み出せる言語を選択する
  3. DOMにより、IFRAME内にFORMを作成してSUBMITする

このうち、上記1.については、セキュリティ上の問題が発生し得る。Ajaxのセキュリティ対策として、「GETメソッドを拒絶する」という方法があるからだ。具体的には、SCRIPT要素を使ってSame Origin Policyを回避してAjaxデータを読み出す手法に対抗して、SCRIPT要素では必ずGETメソッドになることから、POSTのみを許容することで対策するという方法だ。既存のアプリケーションがこのような手法によりセキュリティ対策されている場合に、安易にGETメソッドを許容してしまうと、セキュリティホールが混入することになりかねない。

3.については、私が試した範囲ではうまくいっていない。JavaScriptからIFRAME内のFORM操作がうまくいかないのだ。これも、ひょっとすると制限を掛けているのかもしれない。アドホックな方法ならありそうだが、まだ十分に検証できていない。

一つの疑問は、このような情報がインターネット上に見あたらないことだ。AjaxでPOSTメソッドが使えないというのはとんでもないことだが、検索してもそのような情報がみあたらないのだ。iモードブラウザ2.0のAjaxを誰も使っていないのか、それとも事業者が恐ろしくて口をつぐんでいるのか。

しかし、このような技術情報が流通していかない限り、iモードブラウザ2.0のJavaScriptを使ったコンテンツは普及していかないだろう。NTTドコモにはさらなる情報開示を期待したいし、ケータイWebの開発者にも、もっとブログなどでの情報公開を期待する。

本日のツッコミ(全11件) [ツッコミを入れる]
_ masa (2010年01月18日 09:57)

formのactionに直接パラメータを積むとか?

_ twk (2010年01月18日 10:08)

xml形式のデータをsubmitしたら読み取れる?

_ 徳丸浩 (2010年01月18日 10:48)

masaさん、twkさん、コメントありがとうございます。
formのactionにパラメータ積んだら、それは実質的にGETということになりませんか?
xml形式のデータをSUBMITというのは、実はやってみたのですが、PHP、ASP/ASP.NETなどではうまく受け取れていません。やり方があるのかもしれませんが、私は知りません。

_ Kenji (2010年01月18日 11:45)

PHP なら、php://input でデータを取得できるのではないでしょうか?

file_get_contents('php://input');

http://www.php.net/manual/ja/wrappers.php.php

_ 徳丸浩 (2010年01月18日 11:56)

Kenjiさん、コメントありがとうございます。php://inputというものがあるのですね。確認したところ、確かにデータを取得できました。

_ 金床 (2010年01月18日 22:12)

サーバサイドJavaの場合、ServletRequestのgetInputStreamからストリームとして取得できます

_ 猪股健太郎 (2010年01月18日 22:57)

ASP.NETの場合なら、HttpContext.Current.Request.InputStreamから読めると思います。

_ yamagata (2010年01月18日 23:49)

ストリームとして取得して自分で分解する方法で対応しようと思えば出来る状況だとしても、(それまでに比べて)手順がフクザツなので、「あきらめてGETを使う」に流れてしまう開発者も多そう。setRequestHeaderが少なくとも"Content-Type"に対しては今までどおり動作するように再改修されることが望まれますね。。

_ (2010年02月06日 05:23)

記事とは関係ないコメントですいません

http://nat-q.jp/ctg3/q_detail.php?no=10340
ユーザ同士で質問を回答するサイトの1ページなのですが
iモードブラウザ2.0ブラウザによる乗っ取りなのでしょうか?
自分では判断できないので検証していただきたいです
(ちがうなら、あたしの勘違いでいいのですが
あたりなら実害が出ているとドコモなどへ報告していただきたいです)

_ 徳丸浩 (2010年02月06日 08:36)

姫さん

質問を見てみましたが、これはご本人がドコモショップに相談に行くのがよいと思います。あくまで想像ですが、のっとりなどではないような気がします。
最近は携帯電話を購入すると、必要のないコンテンツを購入させられて「いらなければ直ぐに解約してください」と言われることがよくあります。そのたぐいの話で、ショップの店員が説明していなかったとか、説明を聞き漏らしていたとか、理由は無数に考えられます。

_ 徳丸浩 (2010年04月15日 15:56)

コメントいただいた皆様、ありがとうございました。
さすがに、言語毎に方法はあるのですね。
ですが、あまり知られていない方法を使わないといけないこと、そのための説明などがドコモの解説などにないことから、やはりPOSTデータの扱いは「困難」だなと思います。
この問題は引き続きウォッチしたいと思います。ありがとうございました。

本日のリンク元
アンテナ
その他のリンク元
検索


[PR]小規模ECサイトに最適なWAF、SiteGuard Lite

ockeghem(徳丸浩)の日記はこちら
HASHコンサルティング株式会社

最近の記事

最近のツッコミ

  1. 徳丸浩 (04-15)
  2. 徳丸浩 (02-06)
  3. 姫 (02-06)
Google