HTTP status code 416 (Chrome)

HTTPサーバのログにはステータスコード416を返していることが結構あったりするようです。Rangeヘッダは先ごろApache Killerで有名な問題がありましたが、特にDoSしようとしているわけでもなく普通のリクエスト。共通項は

  • Chrome (新旧問わず 6.0.472.63, 15.0.874.121, 17.0.963.56, …)
  • GET対象のサイズが6で割り切れる(リクエストは複数ですが対象は高々3つだけなのでたぶんたまたま)。

くらいしか見当たりません。ただし新しめのChromeでは416の直後に再度GETして正常取得しているので、何らかの対症療法が施されているように見えます。https://code.google.com/p/chromium/issues/detail?id=68298によれば13で修正されているようですがregressionでしょうか、はたまた別件でしょうか。Range, If-*ヘッダをログ、ChromeからのRangeはunsetして様子を見ることにします。

あ、その金庫、横に鍵が張り付けてありますが中身大丈夫ですか?

動けばよいってもんじゃない 」ですが、ショッピングカートはその最たるものの一つです。かつてネット通販が出始めの頃、いろいろなケースに出会いました…

最も多かった問題が、返信メールに記載されたURLをクリックするとログインもしていない(そういう通販サイトにはcookieとかセッションとかいう概念が存在しません)のに住所から注文内容から確認できるものです。メールにURLを記載しなければ良いという話でもなく、注文するときはそのようなシステムと知らないわけで、注文終わってからあーやばい通販だったかと学習することになります。今では使う通販も決まってきて新しいシステムの通販に手を出すことはほとんどないのでそういう思いをすることもまずないですが、いまだに某大手ISPのアンケートシステムでも使われてました。海外のTシャツ屋、今は無くなってしまった書店、今もある比較的大手の通販、などなど何度か出会いました。「該当URLが404を返すようにして、あと恐ろしいのでカードの情報も削除しておいてね」とお願いすると、そのすべてから「URLにランダムな文字列が入っているので大丈夫!」(鍵が貼り付けてある金庫なので当然大丈夫じゃないです。念のため)「SSLだからデータは安全!」(通信路の暗号化であり、しかもメールで送られてきてしまったURLは暗号化されていないうえに両端ではデータは復号化された状態なので全然大丈夫じゃないです…)と笑い話にもならない自信満々のお返事を頂戴したものです。

このたび「noindex,nofollow,noarchiveと書いてあるし、user agentでロボットはじいているから大丈夫!」という説も増えたようですが、何にせよ鍵が横に貼り付けてある金庫を、メールで送ったりブラウザから送信させておいて、その金庫の中身が大丈夫だと言ってしまうのはこれまた…

今時ですとブラウザに各種ツールバーをインストールされている方も昔よりも格段に多いでしょうから、tappingやらbrute forceされるまでもなく、そして自らが認識しているかどうかにかかわらず閲覧しているURLが他ホストに自動的に送られている場合も、セキュリティのためなどと称して多数あることでしょう。また別の側面では「ランダムな文字列」が実は順番の数字のBASE64エンコードだったりソルト無しハッシュ値のような、なんちゃってランダムだったときにもノーガード公開状態となります。

このようなシステムを作ってしまう人がここ十数年絶えることなく出続けてきたわけですから、webアプリ作成者の常識に期待することをあきらめるとすると今回のような深刻な犠牲者を増やさないためにはどうすればよいでしょうか。セキュリティソフトと呼ばれるものの中には生のまま特定の情報が送受信される場合に通信を遮断する機能を持つものがありますが、メールで送られてくるURLの場合のように他人のシステムから送られてきてしまう場合、そしてそのページに問題がある場合にはいかんともしようがありません。良さそうなのは、ショッピングカートに限らず鍵付き金庫をばら撒くようなシステム採用サイトのレピュテーションサービスでしょうか。コミュニティーベースでしか成立しそうにないですが、消費者保護とサービス提供者の常識確保のために政府にやっていただければ良いですね。そしてやはり経営者さん、特に消費者の不利益に直結するサイトを運営されている経営者の方たちも「動けばいいってもんじゃない」を考えていただけるとありがたいです。

と今回の某通販での大惨事の記事を見て思ったことでした。

文書に記述する際の説明用/例示用のドメイン名、IPアドレス、MACアドレス RFC6890,RFC5737,RFC3849,RFC2606,RFC6761,RFC7042 IANAなどなど

説明書などでドメイン名を例示するときに、 hoge とか foo とか bar とか chome などにを適当なTLDをつなげたり、最近ではTLDとして使ってしまうと自分のドメインでない場合や、自分のドメインでも更新しなかった場合などに問題になる可能性があります。IPアドレスもしかりです。そのままコピペされたり検索エンジンにインデックスされて他人に迷惑をかけないためにも、文書に記述するときに使ってよいドメイン名、IPアドレス、MACアドレス(EUI-48)が決まっています。

RFC6890によって RFC5735 はobsoleteにされました。(RFC5735によって RFC3330 はobsoleteにされました。参考: IPv4枯渇)

  • 2016-06-28 MACアドレス関連追記
  • 2013-10-11 RFC6890関連追記(Documentation用IPアドレスの変更はありません)
  • 2011-02-10 .lg.jp関連追記
  • 2011-01-26 .テスト などTLD関連追記
  • 2010-03-17 .jp関連追記
192.0.2.0/24192.0.2.0 – 192.0.2.255TEST-NET-1 (TEST-NET)RFC6890 RFC5737(RFC5735 RFC3330)
198.51.100.0/24198.51.100.0 – 198.51.100.255TEST-NET-2RFC6890 RFC5737(RFC5735 RFC3330)
203.0.113.0/24203.0.113.0 – 203.0.113.255TEST-NET-3RFC6890 RFC5737(RFC5735)
2001:db8::/322001:db8::0 –
2001:db8:ffff:ffff:ffff:ffff:ffff:ffff
Documentation PrefixRFC6890 RFC3849(RFC5156)
00-00-5E-00-53-00-00-5E-00-53-00 –
00-00-5E-00-53-FF
EUI-48 (MAC addresses) Documentation ValuesRFC7042 2.1.2 (2.1.1)
00-00-5E-EF-10-00-00- 他00-00-5E-EF-10-00-00-00 –
00-00-5E-EF-10-00-00-FF
EUI-64 (unmodified 64-bit MAC addresses) Documentation ValuesRFC7042 2.2.3
.testrecommended for use in testingTLDs for Testing, & Documentation ExamplesRFC2606 RFC6761
.测试(.XN–0ZWM56D)
.परीक्षा(.XN–11B5BS3A9AJ6G)
.испытание(.XN–80AKHBYKNJ4F)
.테스트(.XN–9T4B11YI5A)
.測試(.XN–G6W251D)
.பரிட்சை(.XN–HLCJ6AYA9ESC7A)
.δοκιμή(.XN–JXALPDLP)
.テスト(.XN–ZCKZAH)
.טעסט
(.XN–DEBA0AD)
.آزمایشی
(.XN–HGBK6AJ7F53BBA)
.إختبار
(.XN–KGBECHTV)
e.g.
ほげ.テスト
(xn--18j4d.xn--zckzah)
Reserved for testing internationalised domain namesRoot Zone Database
.examplerecommended for use in documentation or as examples
e.g. hoge.example
TLDs for Testing, & Documentation ExamplesRFC2606 RFC6761
.invalidintended for use in online construction of domain names that are sure to be invalidTLDs for Testing, & Documentation ExamplesRFC2606 RFC6761
.localhosthaving an A record(DNS) pointing to the loop back IP address and is reserved for such useTLDs for Testing, & Documentation ExamplesRFC2606 RFC6761
example.come.g.
hoge.example.com, example.com
Reserved Example Second Level Domain NamesRFC2606 RFC6761
example.nete.g.
hoge.example.net, example.net
Reserved Example Second Level Domain NamesRFC2606 RFC6761
example.orge.g.
hoge.example.org, example.org
Reserved Example Second Level Domain NamesRFC2606 RFC6761
example.jp
example0.jp
example1.jp

example9.jp
ドメイン名例.jp
(xn--eckwd4c7cu47r2wf.jp)
e.g.
hoge.example.jp, example7.jp,
ほげ.ドメイン名例.jp
(xn--18j4d.xn--eckwd4c7cu47r2wf.jp)
 汎用 JP ドメイン名における予約ドメイン名の3 JPRS FAQ
example.<属性ラベル>.jp
example0.<属性ラベル>.jp

example9.<属性ラベル>.jp
example.<市区町村ラベル>.<都道府県ラベル>.jp

example.<都道府県属性ラベル>.<都道府県ラベル>.jp

example.<市区町村属性ラベル>.<市区町村ラベル>.<都道府県ラベル>.jp

など詳細は右記技術細則にて
e.g.
hoge.example3.ed.jp,
example7.city.shibuya.tokyo.jp
 属性型(組織種別型)・地域型JPドメイン名登録等に関する技術細則の4.4 JPRS FAQ
example.lg.jp
example0.lg.jp

example9.lg.jp
e.g.
city.example8.lg.jp
 LG ドメイン名登録等に関する技術細則の3.4 JPRS FAQ

ばっちり書けてますかhref= 特に&(&amp;)などを含む場合 属性値としてのCDATA

<a href=”xxx”>や、<param name=”FlashVars” value=”xxx”>のxxxに&(ampersand アンパサンド)が含まれる場合、正しい書き方ができていますでしょうか?


追記(2016/8/31)

最近ではAccelerated Mobile Pages(AMP)を有効にするパラメータとして本当にampが使われてamp=1とかを利用するプラグインなどが出てきました。今時ではXHTMLも使わないでしょうし&amp + ;以外の記号 でもエラー部分を消さずに &amp;amp + ;以外の記号 相当とみなしてパースが進行するようになっているので気にする必要もないかもしれません。

  • <link rel=”amphtml” href=”/hoge?amp=1″ /> OK
  • <link rel=”amphtml” href=”/hoge?param1=1&amp;amp=1″ /> OK
  • <link rel=”amphtml” href=”/hoge?param1=1&amp=1″ /> NG

とはいえ、amphtml以外のpathが/ampで終わらないようにできるのであれば、 /amp を query string の amp=1 に、例えばmod_rewriteならば

のようにwebサーバ側でrewiteする方が気にすることも減って無難かもしれません。

追記終了


複数の変数/パラメータを渡したい場合、その変数/パラメータの名前がampだったり、値に&が含まれている場合を考えていきます。

書くまでも無い当たり前なネタなのかもしれませんが、AdobeサイトのFlashVars解説にも誤記が あったり、「表示」⇒「ページのソース」だけで学んでいる人は気づかなかったりするかもしれないので、関連仕様書を一まとめにしておく意味でも書いておき ます。大きな問題であるわけでもなく気にしなければしないですませられますが、実体参照と同じ名前の変数を使いたい場合のように機能的に困る場合があります。


クイズです。次のHTMLをノートパッドなどのテキストエディタで作成してhoge.html等適当な名前で保存します。

次にこのファイルをお好きなwebブラウザでこのHTMLファイルを開き、アンカーのリンク先を右クリック等ででクリップボードにコピーし、テキストエディタにペーストします。どうなるか予想できましたでしょうか。

Windowsの実験機で試した結果は以下の通りです。

FF3⇒notepad file:///?hoge=123&=567
Safari4⇒notepad file:///?hoge=123&=567
Opera10⇒notepad file://localhost/?hoge=123&=567
IE8⇒notepad file:///D:/?hoge=123&=567
IE7⇒notepad file:///D:/?hoge=123&=567
IE6⇒notepad file:///D:/?hoge=123&=567
IE5.5⇒notepad file:///D:/?hoge=123&=567

hostのあるものやpathにドライブのあるものなどいろいろ面白いですが、今回の本題は123の右です。どこにもampがありません。これは「不幸に も多くのHTMLユーザエージェントは変な実体参照でも適当に問題をシカトして先に進んでしまう。(下記参照)」からです。&amp=の部分を& amp;quot=や&copy=などに変えたり、先頭に

を付けたりして(ローカルのファイルでもXML宣言を見てこれをエラーにするブラウザは有りましたか?)いろいろ試してみてください。quotやcopy等では&すら出てこなくなるので間違いにすぐに気づくかもしれません。今まで気づいていなかった方にはとても違和感があるかもしれませんが、パラメータampに値567を渡したい場合の正解は

になります。Flash PlayerにFlashVarsを<object>の中の<param>で渡したい場合はどうでしょうか。HTMLやXHTMLの世界での話なので、変数p1,p2,ampにそれぞれ値を渡したい場合は

といったものが正しい書き方になります。あとは=前後の%エンコード(Percent-Encoding)(FlashVarsの説明ではURL encodingと書かれていますが、各種のURLencode()のような関数やapplication/x-www-form-urlencodedで使われるエンコードではあの記号はそのまま、この記号は%エンコードという奇々怪々な仕組みも含まれる場合があるので素直に%エンコードと呼び、かつFlashVarsの値はECMAScriptのencodeURIComponent()相当の符号化、つまりUTF-8以外の場合はUTF-8に変換をしてから英数以外は積極的に%エンコードする、というのがさまざまな場合で無難だと思います)もお忘れなく。具体的にはもしFlashVarsで変数p1,p2,ampに&が含まれている値を渡したい場合は次のようになります。(%26はUS- ASCIIのスーパーセットの文字セット-文字符号化では&になります。)

変数側に記号を入れてみたりするのも面白いかもしれません(例外的にNULは文字列終端扱いである模様で、例えば

ではswfのhogeにheroが渡されました。実装された詳細仕様は不明です)。href=での%エンコードの話は、サーバ側、アプリケーション側がどうなっているかに依存する、つまりwebサーバやアプリケーションサーバ、CGIもからんできて、単純にこうだとは書くことができません。

では

のように、HTMLとしては期待されていない処理を誘発し、XHTMLとしてはエラーになる属性値(value=の部分)の場合、swfに何が渡ってくるでしょうか(IEはobject要素がparam以外の要素を持てないのでコメント要素は取り除きます)。Flash Player 10.0.42.34との組み合わせで以下の通りです。もっとも、HTMLを解釈してFlash Playerに渡すまでの作業はwebブラウザ(HTMLユーザエージェント、HTMLパーサ)の仕事であり、もしFlash Playerのバージョンで変わるとすればそれはFlashVars自体の仕様の変化となります。また、XHTMLとしてちゃんとエラー扱いになった場合はそもそもFlash Playerが起動しません。

FF3 swfのampの内容は空
Safari4 swfのampの内容は空
Opera10 swfのampの内容は空
IE8 swfのampの内容は空

同時に&amp;amp=bazで正しくswfのampにbazが渡ってくること、そして残念ながら世の中に氾濫している&xxx=bazでも、エラー扱いではなくかつxxxが文字実体参照や数値文字参照にぶつかっていないものはbazが渡ってくることも確認しました。上の href=と同じ状況で予想通りです。

ところでこれはHTMLやXHTMLの世界での話なので、HTML内での記述ではなくて別の外部ファイル(.js等)に分けて、

などで提供される分にはまったく当てはまりません。パラメータhoge,p1,p2,ampにそれぞれ値を渡したい場合はそのまま

というような文字リテラルでOKです。

HTML内でのonclick=などの属性値ではContent-Script-Typeがapplication/javascript(text/javascript)の場合

のようになります。<script>で記述する場合は内容モデルがHTMLではCDATA, XHTMLでは#PCDATA(下記参照)という別な話が登場して終わらなくなってしまいますので機会があれば別途。とにかく外部ファイルにしてしまうと 決めていれば稀な場合でも大きな問題にならないはずです。

優れたバリデータは文法エラーは当然のこと、誤った処理をさせる部分を検出して警告してくれるので活用されると良いかもしれません。

なお、弊社遊び場の中のFlashアプリの ページでは、ActiveX用とNetscape式plugin用さらにはSWFObject用に同じパラメータを何度も書かなければいけないという問題 とSWFObjectだけではJavaScript依存にしてしまうという問題を解決し、かつActiveXでなくても古いFlash Playerが入っていればExpress Installationが起動するというちょっと素敵なやり方をしています。機会があればご紹介します。

長くなりましたが、以下に根拠となる仕様書(一部ですが)のリンクと、簡単な説明をまとめてみました。ぜひご自身でも読み解いて、上に書かれていることが本当か確認してください。間違いがあったらぜひコメントをお願いします。

<param>要素のvaue=属性の値に関する仕様書の一部の超訳

<a>要素,<link>要素のhref=属性の値に関する仕様書の一部の超訳

属性値の場合のCDATAに関連する仕様書の一部の超訳

  • HTML 4.01:CDATAは文書文字集合のシーケンスで、文字実体を含むことができる。ユーザエージェントは属性値を次のように解釈するべきである。文字実体を文字で置きかえる。LFを無視する。CRやTABは各々SPに置き換える。: http://www.w3.org/TR/1999/REC-html401-19991224/types.html#h-6.2
  • HTML 4.01(SGML tutorial):属性値はダブルクォートかシングルクォートで括る。決められた文字だけの場合は括らなくてもいいけど。数値文字参照を利用し て"でダブルクォート、'でシングルクォートを値に含められるし、ダブルクォートで括られている場合は文字実体参照を利 用して&quot;でシングルクォートを値に含められる。: http://www.w3.org/TR/1999/REC-html401-19991224/intro/sgmltut.html#h-3.2.2
  • XML 1.0: ダブルクォートかシングルクォートで括る。<と&と括り始めのクォート以外の文字、あるいは「参照」で構成される。: http://www.w3.org/TR/2008/REC-xml-20081126/#NT-AttValue
  • XML 1.0: 参照は、実体参照(例:&quot;)か、文字参照(例:",")である。: http://www.w3.org/TR/2008/REC-xml-20081126/#NT-Reference
  • XHTML 1.0: SGMLでもXMLでも&(ampersand character)は実体参照の開始宣言であるが、不幸にも多くのHTMLユーザエージェントは変な実体参照でも問題をシカトして先に進んでしまう。 XMLユーザエージェントはこの不正な使用を認められない: http://www.w3.org/TR/2002/REC-xhtml1-20020801/#C_12
  • HTML 5 (右は訳ではなくて注釈):今までのHTMLではそのものすばりと書かれていなかったようだけど、ついにどうやって間違った文法(前出のHTMLの場合で は&amp=を&ampy=にしたり、&copy=を&copydayo=にするといった悲しくも不正な回避方法が使わ れてしまった場合)をパースし続けるかが定義(恐るべし膨大なレガシー資産パワー!)される模様。: (このリンク先はレンダリングするのに結構リソース消費します。クリックするときは注意してください)http://dev.w3.org/html5/spec/Overview.html#tokenizing-character-references

<script>要素に関する仕様書の一部の超訳(参考)

要素内容の場合のCDATAに関連する仕様書の一部の超訳(参考)

Adobe.comでの説明(頻繁にURLが変わりpermalinkも無いのでたまに修正していますがリンク切れの場合がしょちゅうあります)(参考) (サンプルは適切でないです。修正されることはなさそうです。)

  • TechNote (Knowledge Base): <PARAM NAME=FlashVars VALUE=”foo=Hello%20Worldgraph=first+line%0Dsecond+line”> の部分はおそらく VALUE="foo=Hello%20World&amp;paragraph=first+line%0Dsecond+line" の意図で書かれたものと思われますが、graphの前に&すらなくなってしまっているのでサンプルの意味がとてもあいまいになってしまっています(2010/1/14時点)。Macromediaからのお引っ越しの際にでも発生したエラーでしょうか: Using FlashVars to pass variables to a SWF
  • Flex 4: この説明文の<param>等のHTMLでFlashVarsを使用しているもののうち、&lastname=の部分(2010/1 /14時点)は、勝手にlastnameが文字実態参照に使われないことを暗黙のうちにリザーブしています。lastname部分をampやquotやcopyやnbspやltやgtや…にした場合は動作しないことを記載するか、あるいは普通にXHTMLでもHTMLでもampやquotやcopyという変数を渡したいときでも百万が一にも文字実体参照に&lastname;が追加された場合も使えるサンプルにするためにも、&amp;lastname=を使用するのが妥当と考えられます: Passing request data with flashVars properties – Communicating with the wrapper
  • Developer Connection: ユーザの入力を動的にFlashVarsに渡すような場合、%エンコードすることの重要性やURLのような場合はスキーマやホストの確認なども重要であることが書かれています。一読をお勧めします。: Creating more secure SWF web applocations

2010/4/13 文章校正(項目の順序入れ替え)