4.11. クエリ以外の実行に HTTP の GET 命令を使わせない

HTTP を利用した Web ベースのアプリケーションでは、クエリ以外の目的で HTTP の 「GET」もしくは「HEAD」命令を使わないようにしてください。 HTTP にはさまざまな命令がたくさんあります。最も普通に使われる命令は、 GET と POST の 2 つです。 GET も POST もフォームからデータを送信できますが、GET 命令は URL にデータを 入れて送信します。その一方、POST 命令は URL とは別にデータを送信します。

GET をクエリ以外の命令(データの変更やお金の振り込み、あるサービスにサイン アップするような)に利用すると発生してしまうセキュリティ上の問題は、攻撃者が 悪意あるフォームデータが存在する URL に対してハイパーテキストリンクを 張れるところにあります。 攻撃者が犠牲者を誘導して、そのリンクをクリックしたり(ハイパーテキストリンクの 場合)、あるページを見たりしただけで(HTML の画像タグから画像として情報が 伝わってくる場合)、GET が実行されます。 GET が実行されると、犠牲者は、攻撃者が作成したフォームデータすべてを特定の リンクへと送ります。 このサイトにまたがった悪意あるコンテンツによる攻撃については、さらに Section 6.15 で論じます。

サイトにまたがった悪意あるコンテンツによる攻撃が、思いがけないデータをユーザ に見せるだけであれば、それほど問題は深刻ではありません。 もちろんこれはこれで問題なのですが、他にもこの機能を使った攻撃があるのが 問題なのです。 たとえば、ユーザが予期せずに何かを要求しまうことで、プライバシーが流出する 可能性がでてきます。そうなると、違法もしくは違法になるような資料を要求した ように見えることで、現実に問題となったり、ユーザに何らかの方法で情報を要求 させて、本来は公開されない情報を攻撃者へ公開させたりするかもしれません。 しかしもっと影響が深刻なのは、悪意ある攻撃者がただデータを見るだけでなく、 サイトをまたがったリンクによって、データを改竄する行為です。

一般的な HTTP のインタフェース(たいては CGI ライブラリ)は、GET と POST の 違いをわからなくしていますので、データ取得という点からすると双方の命令を 「同一の方法」として扱う方が便利です。 しかし、データクエリ以外の何かの処理を実際に行うなら、要求が POST 以外に 何をするのかを見てチェックする必要があります。 もしそうなら、与えられたデータをフォームに入れてただ表示し、ユーザが本当に その要求をするつもりなのか、確認してください。 こうすることで、サイトをまたがった悪意あるコンテンツに対する攻撃を防げます。 ただしユーザには、簡単にワンクリックで確認できるようにしなければなりません。

実際、HTTP の仕様書ではこの行為を強く推奨しています。 HTTP 1.1 の仕様書(IETF RFC 2616 セクション 9.1.1)によると、 「GET や HEAD 命令を検索以外で動かす「意味はないはず」です。 これらの命令は「安全」であるはずです。 これはユーザエージェントに対して、特別な方法でその他の命令である POST や PUT、 DELETE の代役を許可します。 その結果、安全でないかもしれない処理が要求されている、という事実をユーザが 知るところとなります」。

公正を期しますが、これでは問題を完全には解決できない点に注意してください。 なぜなら、ブラウザ(の設定の中)にはスクリプト化された POST で同じような 動作ができるものがあるからです。 たとえば、ECMAscript(Javascript)が動作可能な Web ブラウザが下記の HTML の断片を受け取ったと仮定します。あるブラウザは、この HTML の断片を 表示するだけで、攻撃者が定義したフォームデータを強制的にユーザが自動で 攻撃者が選んだ Web サイトに対して POST 命令を送ってしまいます。
  <form action=http://remote/script.cgi method=post name=b>
    <input type=hidden name=action value="do something">
    <input type=submit>
  </form>
  <script>document.b.submit()</script>
この点を指摘してくれた David deVitry 氏には感謝しています。 しかしこのアドバイスでも問題すべては解決できません。しかしやるだけの価値 はあります。 残りの問題はある程度、より賢いブラウザ(たとえば、ECMAscript がある Web フォームを送る前には常にそのデータを確認する)や Web ブラウザの設定(たとえば、 ECMAscript を無効にする)で解決できます。 また、この攻撃はクロスサイト・スクリプティング攻撃の多くでは機能しません。 理由は、Web サイトの多くは、ユーザが「script」コマンドを POST できないよう にしていますが、URL リンクを自由に張れるようにしているからです。 つまり、GET コマンドの動作を制限すると、クエリに対して Web アプリケーションの セキュリティが著しく改善します。