CGIスクリプトの動作環境、環境変数、デコード方法について参考になると思われるスクリプトを作成してみました。詳細な説明は、スクリプトの中に書いてあるコメントを参照してください。wwwperl.cgiこのスクリプトを以下の場所に置いています。いろいろな方法で呼び出して、実行結果をみてください。(オフラインでは表示できません。)
- URLで呼び出す
- http://〜/〜/wwwperl.cgi
- URLで呼び出す(引数付き)
- http://〜/〜/wwwperl.cgi?aaa+bbb
- フォームからMETHOD=GETで呼び出す
- フォームからMETHOD=POSTで呼び出す
CGIスクリプトを記述する際に注意しなければならないことを、UNIXサーバーの場合、Windowsサーバーの場合に分けて説明します。(多くのプロバイダではUNIXサーバーを利用しています。たまにWindows NTサーバーもあるようです。)
- サーバーがCGIをサポートしているか(共通)
- セキュリティ確保のためCGIの使用を禁止していたり、CGIの設定を行っていなかったりするため、CGIを利用できない場合があります。
- .htaccessファイルは必要ないか(UNIX)
- NCSA httpd や Apache というサーバーソフトの場合、.htaccess というファイルの設定が必要な場合があります。プロバイダやサーバー管理者に問い合わせてください。
- 動作チェックはサーバー経由で行っているか(共通)
- CGIスクリプトの動作チェックは必ずWWWサーバーから http://〜 という形式で読み込むようにしてください。file:〜 という形式で読み込んだ場合は動作しません。
- perlのパス名はあっているか(UNIX)
- CGIスクリプトの1行目は、プロバイダが perl を設置場所に応じて適切に変更してください。例えば、BIGLOBE の場合は #!/usr/mesh/bin/perl となります。
- CGIスクリプトの場所は適切か(共通)
- サーバーの設定によってはCGIスクリプトを置くディレクトリが制限されている場合があります。普段 HTMLファイルを置いているのとは別のサーバーに設置しなくてはならないプロバイダもあります。CGIスクリプトを置く場所がこのホームページで説明されている場所と合わない場合は、プロバイダの指示などに従って、適切にディレクトリを変更してください。
- CGIスクリプトの拡張子は適切か(共通)
- CGIスクリプトの拡張子が .cgi でなくてはならない場合があります。
- perlはインストールされているか(Windows)
- Windows NTにはperlが標準では装備されていませんから、perl for Win32 を入手してインストールする必要があります。また、MicrosoftのIISを用いる場合は、.cgi という拡張子に対して perl.exe が起動されるように、IISのヘルプを見ながら適切にレジストリを設定してやる必要があります。
- CGIスクリプトのパーミッションは適切か(UNIX)
- サーバーがUNIXの場合は、CGIスクリプトファイルのパーミッションを755にしてください。また、CGIスクリプトが書込むデータファイルは、666 にしてください。一部のプロバイダでは、755, 666 の代わりに、744, 644 でも動作するようです。(この方がセキュリティが高い)
- ユーザーの権限設定は正常か?(Windows)
- MicrosoftのIISでは、IUSER_MachineName というユーザーの権限でコマンドが実行されます。このユーザーがCGIスクリプトを実行する権限を持っているか確認してください。
- CGIスクリプトの改行コードは適切か(共通)
- CGIスクリプトファイルの改行コードは、サーバーのOSタイプに適したものでなくてはなりません。
- CGIスクリプト内で使用するコマンドのパス(共通)
- スクリプト実行時、スクリプト内で使用するコマンドのパス(PATH)が通っていない場合があります。TELNETなどでログインした時のPATHと、CGIスクリプトが実行される時のPATHは異なるので注意してください。コマンドはなるべくフルパスで記述したほうが無難かもしれません。
- 最初の1行(UNIX)
- CGIスクリプトの最初の1行は「#!」で始めるようにしてください。 「#!」の行の前に空行があってもいけませんし、「#!」の前にスペースがあってもいけません。
- ヘッダ行のあとの空行(共通)
- Content-type: text/html などのCGIヘッダの後には必ず、1行以上の空行を出力してください。これを怠るとCGIスクリプトは正常に動作しません。
- ヘッダのスペルミス(共通)
- 意外に多いのがこれ。Context-type: になっていたり、test/html や type/html になっていたり....もう一度確認してみましょう。
- CGIスクリプトの出力漢字コード(共通)
- CGIスクリプトから出力する漢字コードはJISコードにするのが無難です。通常はブラウザが自動判断するのですが、Windowsで使用されているシフトJISと、UNIXで使用されているEUCの場合は誤判断してしまうことがあります。
- ファイルへの同時アクセスに注意(共通)
- CGIスクリプトは複数のブラウザ(ひとつのブラウザからでも)同時に起動されます。CGIスクリプトからファイルを更新する際は、ロックファイルの生成などにより排他制御を行う必要があります。
- 大文字、小文字の区別(UNIX)
- UNIXというOSは通常、 アルファベットの大文字と小文字を別の文字として扱いますので注意してください。 たとえば、filename と FileName はまったく別の文字列です。
- ブラウザの[画像表示]チェック(共通)
- CGIを<IMG>タグから呼び出す場合、Netscapeの場合[オプション]→[画像の自動読み込み]、Internet Explorerの場合[表示]→[オプション]→[情報]→[画像の表示]がオンになっていないと読み込まれません。
- ブラウザのキャッシング(共通)
- ブラウザがCGIスクリプトの結果をキャッシングするために、 スクリプトを書き換えても古い情報が表示されたりします。 CGIスクリプト変更時には十分に注意して、再読み込みを欠かさないようにしましょう。
- text/plain のわな(共通)
- Content-type: text/plain を使用した場合、Internet Explorer 3.0以降ではうまく動かないことがあります。 [表示]→[オプション]→[プログラム]→[ファイルタイプ]で、.cgiという拡張子のファイルにメモ帳などのプログラムを割り当てている場合、text/plain 形式の実行結果をダウンロードしてしまい、期待通りの動作をしないことがあります。
通常のCGIスクリプトの出力はWWWサーバー経由でWWWブラウザに渡されますが、NPHスクリプト形式にすると、CGIスクリプトから直接WWWブラウザに渡されるため、WWWサーバーの負荷が軽くなり、速度も若干速くなります。CGIスクリプトをNPHスクリプトにするには次の2つの作業を行ってください。
次は、NPHスクリプトの例です。(nph-sample.cgi)
- CGIスクリプトを nph- で始まるファイル名にする。
- Content-type: を出力する前に、「HTTP/1.0 200 OK」を出力する。
#!/usr/local/bin/perl print "HTTP/1.0 200 OK\n"; print "Content-type: text/html\n"; print "\n"; print "<HTML>\n"; print "<HEAD>\n"; print "<TITLE>NPHスクリプトのテスト</TITLE>\n"; print "</HEAD>\n"; print "<BODY>\n"; print "これは、NPHスクリプトのテストです。\n"; print "</BODY>\n"; print "</HTML>\n";
SSIやCGIは便利さの代償としてセキュリティ的には非常に危険なものです。 以下の文章はセキュリティを強化するために必要な情報ですが、反面、未防御のシステムに対してアタックをかけるための情報にもなってしまいます。 この場で記載すべきかどうか悩んだのですが、このホームページの読者を信用して公開することにしました。
- index.htmlを設置する
- CGIスクリプトを置くディレクトリには index.html を置いておきましょう。index.html が存在しない場合、cgi-bin ディレクトリをブラウザでみるとCGIスクリプトの一覧が見えてしまいます。ファイル名からセキュリティホールのあるスクリプトを見つけてアタックされる可能性が高くなります。
- 見られるとまずいファイルはpublic_htmlの外に
- パスワードファイルなど、見られるとまずいファイルは、public_htmlの外など、通常の閲覧者が見ることのできないディレクトリに置きましょう。(それでも、同じサーバーにログインできる人や、他の人のCGIのセキュリティホールのために、見られてしまうことはあります。)
- evalの危険性
- perlはよく分からないのでCGIスクリプトをシェルで記述しよう・・・と思った時など、CGIスクリプトのパラメータを解釈するためによく、UNIX のシェルの eval を利用しますが、これは大変危険です。 もし、変数名NAMEの値として「値;危険なコマンド」を指定されると・・・
- grepの危険性
- 「grep $KEY file」というコードも危険です。 もし、KEYの値としてバッククォーテーション( ` )で囲まれた「`危険なコマンド`」を指定されると・・・
- SSIの危険性
- チャットや伝言板など利用者の書き込んだメッセージを表示するシステムではSSIに注意してください。 もし、「<!--#exec cmd="危険なコマンド"-->」を書き込まれると・・・
- パスワード漏洩の危険性
- 人様のパスワードを扱う場合はとにかく厳重に扱ってください。 多くの人は同じパスワードを使いまわします。 あなたのサービスが不法使用されるだけでなく、同じパスワードを使いまわしていた他の有料サービスも不法使用される恐れがあります。 あなたのCGIスクリプトは完璧でも、同じサーバー上の他の人の不備で情報が漏れる可能性もあります。 パスワード情報ファイルに password.txt などといった安直な名前はつけないようにしましょう。