朝日薫さん、
なるほど、確かにCGIの問題ですね。
ブラウザやHTTPサーバではどうしようもない話ですから。
うーん、やっぱりこの問題はマイナーなんでしょうなぁ…。
例えば「http://localhost/cgi-bin/bbs.cgi」が出力するHTML内に、以下のような画像タグがあるとします。
<img src=image/foo.jpg>
するとブラウザはこの画像を「http://localhost/cgi-bin/image/foo.jpg」のURLで探します。
ところがおなじCGIを「http://localhost/cgi-bin/bbs.cgi/」として呼び出すと、
ブラウザは「http://localhost/cgi-bin/bbs.cgi/image/foo.jpg」というURLでGETリクエストを出します。
もちろんブラウザ側からは“壊れた画像データ”にしかみなされず「×印」が表示されるだけですから、単に見ているだけの人には何が起こったのかわかりません。
けれどWebサーバのほうは上記のような<img>タグの数だけ、正直に「/cgi-bin/bbs.cgi」を実行し、そのHTMLを返しているんですよね…(^^A;
#俗に言う「アイコン掲示板」の類ではおおむね数10〜数100個の画像タグを含むので、簡単にリソースを食いきるし、ログも一気に膨れます。OSのファイルロックの実装手段によってはゾンビが大量発生しかねない余禄も…。
#ですから2ch等にこういう“/”付きリンクを置いて短時間にたくさんの人にクリックさせれば、充分DoS攻撃の代用になりうるんですわ。<悪用禁止!
#この問題は掲示板設置者が画像タグを一切使わないか、全画像タグをすべて絶対URLで書くか、<base href=http://localhost/cgi-bin/bbs.cgi>というタグをHTMLヘッダに記述すれば容易に回避できます。これはまあ、CGIソフト配布側の啓蒙しだいですけどねぇ。
朝日薫さん、
現在の仕様では、PATH_INFO かどうかの判定の 前 に 最後のドットがある URL に対して 404エラーとしてしまっています。
つまりURLのパス部分以降(?以降を除く)に "./" を含むか最後が "." である場合、その時点で 404 です。
それがOKで、実行可能な拡張子がある場合、それ以降を PATH_INFO としています。
最後のドットにこだわるのは Windows が最後のドットがあってもなくても同じファイル名とみなすからです。
なお、もちろん、PATH_INFO の判断はコマンドラインがやるわけではありません。
「例えば画像を多数使用する掲示板 CGIがあり、... 」のところは、ちょっとよく理解できませんでした。例をあげてもらえますか?
その後いろいろ考えたので、PATH_INFO の件について補足します。
パスの途中に(ディレクトリではなく)ファイル名があったら、そこより右を“PATH_INFO”に格納して該当ファイルを呼ぶ、というのがこの場合の基本動作のはずですが、
foo.cgi/hoge. → SCRIPT_NAME= foo.cgi PATH_INFO= /hoge.
~~~~~~~
↑実体ファイル名(ディレクトリではない)
こうならないで「SCRIPT_NAME= foo.cgi/hoge.」になるのが現在の挙動です。
(PATH_INFO は実体ファイル名ではなく、あくまでも QUERY_STRING と同等のコマンドパラメータであるはずなんですが…)
WInAPI に付いては門外漢ですが、この切り分け処理は AnHttpd 内で独自処理しているわけではないのでしょうか?
現在のところ、この症状がセキュリティホールに直結するようなことはないと思いますが(単に証明できないだけとも言える)、PATH_INFO の処理ルールは実装次第では危険な問題もはらむものですから、どうなってるのかちょっと気になったわけです。
(例えば画像を多数使用する掲示板 CGIがあり、その画像タグが下向きの相対パス指定である場合、URLの末尾に/を付加するだけで***画像タグの数だけ*** くだんのCGIが繰り返しブラウザから呼び出されます。これはブラウザにはURLを見ただけではファイルもディレクトリも区別のつけようがないからで、ブラウザのソケットコネクション同時最大使用数次第ですがリモートDoS攻撃の代用手段にも充分なりえます)
(ですから本来実体ファイル名が途中に出現するURIを許可するか否かを、Webサーバは設定可能であることが望ましいと考えているのですが…。Apacheもこのへんは弱かったりしますしね)
ちなみにWindows/DOSのコマンドラインルールでは「foo.cgi/hoge.」は「foo.cgi」コマンドに「/hoge.」スイッチを渡す(argv[1]に代入)と解釈されます。UNIXではこれが(シェルの前処理で)PATH_INFO に格納されますが、AnHttpd では即時実行可能拡張子を持たないCGIファイルは直接実行せず、いったんファイルとして読もうとするので、そこで“存在しない”エラーになるのか?とか思いました。
朝日薫さん、
それはどちらかというと仕様です。
Windowsでは最後にドットがあってもなくても同じとみなします。
最後のドットを許すと、たとえばリクエストの bbs.cgi に対して bbs.cgi. が存在し、しかも拡張子なしとみなしてしまうので、bbs.cgi の中身を直接見たりダウンロードできたりしてしまいます。
おそらく最後にドットをつけても、Windowsでは最後のドットなしのファイル名になると思うので現状で差し支えはないと思っています。
もしそれを区別するとすれば、最後のドットの前のドットを調べて本当の拡張子を調べる作業を入れればいいのですが、そこまでする必要はないと判断しました。
不具合見つけました。
PATH_INFO を利用するCGIで「foo.cgi/hoge.」の用に末尾にピリオドのあるURLで呼ぶと、必ず404エラーになってしまいます。(1.37d で確認)
http://www.hinocatv.ne.jp/~askn/