<?php
include_once $_SERVER['DOCUMENT_ROOT'] . '/include/shared-manual.inc';
$TOC = array();
$TOC_DEPRECATED = array();
$PARENTS = array();
include_once dirname(__FILE__) ."/toc/security.inc";
$setup = array (
  'home' => 
  array (
    0 => 'index.php',
    1 => 'PHP Manual',
  ),
  'head' => 
  array (
    0 => 'UTF-8',
    1 => 'ja',
  ),
  'this' => 
  array (
    0 => 'security.filesystem.php',
    1 => 'ファイルシステムのセキュリティ',
    2 => 'ファイルシステムのセキュリティ',
  ),
  'up' => 
  array (
    0 => 'security.php',
    1 => 'セキュリティ',
  ),
  'prev' => 
  array (
    0 => 'security.sessions.php',
    1 => 'セッションのセキュリティ',
  ),
  'next' => 
  array (
    0 => 'security.filesystem.nullbytes.php',
    1 => 'Null バイト関連の問題',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'ja',
    'path' => 'security/filesystem.xml',
  ),
  'history' => 
  array (
  ),
  'extra_header_links' => 
  array (
    'rel' => 'alternate',
    'href' => '/manual/en/feeds/security.filesystem.atom',
    'type' => 'application/atom+xml',
  ),
);
$setup["toc"] = $TOC;
$setup["toc_deprecated"] = $TOC_DEPRECATED;
$setup["parents"] = $PARENTS;
manual_setup($setup);

contributors($setup);

?>
<div id="security.filesystem" class="chapter">
  <h1 class="title">ファイルシステムのセキュリティ</h1>
<h2>目次</h2><ul class="chunklist chunklist_chapter"><li><a href="security.filesystem.nullbytes.php">Null バイト関連の問題</a></li></ul>

   <p class="simpara">
    <abbr title="PHP: Hypertext Preprocessor">PHP</abbr> は、ファイルおよびディレクトリ毎に権限を設定する多くのサーバーシ
    ステム上に組み込まれたセキュリティを提供します。これにより、ファイ
    ルシステム内のファイルを読み込み可能に制御することが可能になります。
    全てのファイルは世界中から読み込み可能であり、このファイルシステム
    にアクセスした全てのユーザーから読み込まれても安全であることを確認す
    る必要があります。
   </p>
   <p class="simpara">
    <abbr title="PHP: Hypertext Preprocessor">PHP</abbr>は、ファイルシステムにユーザーレベルのアクセスを許可するように設
    計されているため、<abbr title="PHP: Hypertext Preprocessor">PHP</abbr>スクリプトから <var class="filename">/etc/passwd</var> のようなシステム
    ファイルを読み込み可能としたり、イーサネット接続を修正したり、巨大
    なプリンタジョブを出力したりすることができます。これから明らかにわ
    かることですが、読み書きするファイルを適切に設定する必要があります。
   </p>
   <p class="simpara">
    各自のホームディレクトリにあるファイルを削除する次のスクリプトを見
    てみましょう。これは、ファイル管理用にWebインターフェイスを使用す
    る場合に通常生じるような設定を仮定しています。この場合、Apacheユー
    ザはそのユーザーのホームディレクトリにあるファイルを削除可能です。
   </p>
   <p class="para">
    <div class="example" id="example-1">
     <p><strong>例1 甘い変数の確認から生じるリスク</strong></p>
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br /></span><span style="color: #FF8000">// ユーザーのホームディレクトリからファイルを削除する<br /></span><span style="color: #0000BB">$username </span><span style="color: #007700">= </span><span style="color: #0000BB">$_POST</span><span style="color: #007700">[</span><span style="color: #DD0000">'user_submitted_name'</span><span style="color: #007700">];<br /></span><span style="color: #0000BB">$userfile </span><span style="color: #007700">= </span><span style="color: #0000BB">$_POST</span><span style="color: #007700">[</span><span style="color: #DD0000">'user_submitted_filename'</span><span style="color: #007700">];<br /></span><span style="color: #0000BB">$homedir  </span><span style="color: #007700">= </span><span style="color: #DD0000">"/home/</span><span style="color: #0000BB">$username</span><span style="color: #DD0000">"</span><span style="color: #007700">;<br /><br /></span><span style="color: #0000BB">unlink</span><span style="color: #007700">(</span><span style="color: #DD0000">"</span><span style="color: #0000BB">$homedir</span><span style="color: #DD0000">/</span><span style="color: #0000BB">$userfile</span><span style="color: #DD0000">"</span><span style="color: #007700">);<br /><br />echo </span><span style="color: #DD0000">"ファイルは削除されました!"</span><span style="color: #007700">;<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

    </div>
    username および filename はユーザーフォームから投稿可能であるため、別の
    username および filename を投稿して
    削除すべきではない削除することが可能となります。この場合、
    他の何らかの形式の認証を使用するべきです。投稿された変数が、
    <code class="literal">&quot;../etc/&quot;</code> と <code class="literal">&quot;passwd&quot;</code> であった場合について考えてみましょう。簡単
    なコードを以下に示します。
    <div class="example" id="example-2">
     <p><strong>例2 ... ファイルシステムへの攻撃</strong></p>
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br /></span><span style="color: #FF8000">// 外部からPHPユーザーがアクセス可能なハードドライブを削除します。PHPが<br />// ルートのアクセス権限を有している場合、<br /></span><span style="color: #0000BB">$username </span><span style="color: #007700">= </span><span style="color: #0000BB">$_POST</span><span style="color: #007700">[</span><span style="color: #DD0000">'user_submitted_name'</span><span style="color: #007700">]; </span><span style="color: #FF8000">// "../etc"<br /></span><span style="color: #0000BB">$userfile </span><span style="color: #007700">= </span><span style="color: #0000BB">$_POST</span><span style="color: #007700">[</span><span style="color: #DD0000">'user_submitted_filename'</span><span style="color: #007700">]; </span><span style="color: #FF8000">// "passwd"<br /></span><span style="color: #0000BB">$homedir  </span><span style="color: #007700">= </span><span style="color: #DD0000">"/home/</span><span style="color: #0000BB">$username</span><span style="color: #DD0000">"</span><span style="color: #007700">; </span><span style="color: #FF8000">// "/home/../etc"<br /><br /></span><span style="color: #0000BB">unlink</span><span style="color: #007700">(</span><span style="color: #DD0000">"</span><span style="color: #0000BB">$homedir</span><span style="color: #DD0000">/</span><span style="color: #0000BB">$userfile</span><span style="color: #DD0000">"</span><span style="color: #007700">); </span><span style="color: #FF8000">// "/home/../etc/passwd"<br /><br /></span><span style="color: #007700">echo </span><span style="color: #DD0000">"ファイルは削除されました!"</span><span style="color: #007700">;<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

    </div>   
    こうした問題を防止するために必要な重要なチェック手段として以下の2
    種類のものがあります。
    <ul class="itemizedlist">
     <li class="listitem">
      <span class="simpara">
       <abbr title="PHP: Hypertext Preprocessor">PHP</abbr> Webユーザーバイナリに制限された権限のみを許可する。
      </span>
     </li>
     <li class="listitem">
      <span class="simpara">
       投稿された全ての変数を確認する。
      </span>
     </li>
    </ul>
    以下に改良されたスクリプトを示します。
    <div class="example" id="example-3">
     <p><strong>例3 より安全なファイル名の確認</strong></p>
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br /></span><span style="color: #FF8000">// PHPユーザーがアクセス可能なハードドライブからファイルを削除する。<br /></span><span style="color: #0000BB">$username </span><span style="color: #007700">= </span><span style="color: #0000BB">$_SERVER</span><span style="color: #007700">[</span><span style="color: #DD0000">'REMOTE_USER'</span><span style="color: #007700">]; </span><span style="color: #FF8000">// 認証機構を使用する<br /></span><span style="color: #0000BB">$userfile </span><span style="color: #007700">= </span><span style="color: #0000BB">basename</span><span style="color: #007700">(</span><span style="color: #0000BB">$_POST</span><span style="color: #007700">[</span><span style="color: #DD0000">'user_submitted_filename'</span><span style="color: #007700">]);<br /></span><span style="color: #0000BB">$homedir  </span><span style="color: #007700">= </span><span style="color: #DD0000">"/home/</span><span style="color: #0000BB">$username</span><span style="color: #DD0000">"</span><span style="color: #007700">;<br /><br /></span><span style="color: #0000BB">$filepath </span><span style="color: #007700">= </span><span style="color: #DD0000">"</span><span style="color: #0000BB">$homedir</span><span style="color: #DD0000">/</span><span style="color: #0000BB">$userfile</span><span style="color: #DD0000">"</span><span style="color: #007700">;<br /><br />if (</span><span style="color: #0000BB">file_exists</span><span style="color: #007700">(</span><span style="color: #0000BB">$filepath</span><span style="color: #007700">) &amp;&amp; </span><span style="color: #0000BB">unlink</span><span style="color: #007700">(</span><span style="color: #0000BB">$filepath</span><span style="color: #007700">)) {<br />    </span><span style="color: #0000BB">$logstring </span><span style="color: #007700">= </span><span style="color: #DD0000">"</span><span style="color: #0000BB">$filepath</span><span style="color: #DD0000"> を削除しました\n"</span><span style="color: #007700">;<br />} else {<br />    </span><span style="color: #0000BB">$logstring </span><span style="color: #007700">= </span><span style="color: #DD0000">"</span><span style="color: #0000BB">$filepath</span><span style="color: #DD0000"> の削除に失敗しました\n"</span><span style="color: #007700">;<br />}<br /></span><span style="color: #0000BB">j<br />$fp </span><span style="color: #007700">= </span><span style="color: #0000BB">fopen</span><span style="color: #007700">(</span><span style="color: #DD0000">"/home/logging/filedelete.log"</span><span style="color: #007700">, </span><span style="color: #DD0000">"a"</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">fwrite</span><span style="color: #007700">(</span><span style="color: #0000BB">$fp</span><span style="color: #007700">, </span><span style="color: #0000BB">$logstring</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">fclose</span><span style="color: #007700">(</span><span style="color: #0000BB">$fp</span><span style="color: #007700">);<br /><br />echo </span><span style="color: #0000BB">htmlentities</span><span style="color: #007700">(</span><span style="color: #0000BB">$logstring</span><span style="color: #007700">, </span><span style="color: #0000BB">ENT_QUOTES</span><span style="color: #007700">);<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

    </div>
    しかし、これでも、傷口を塞いだことにはなりません。
    ユーザーが自分用のユーザーログインを作成することをあなたの認証システムが
    許可しており、ユーザーが <code class="literal">&quot;../etc/&quot;</code> へのログインを選択した場合、システム
    はまたも公開されてしまいます。このため、よりカスタマイズされたチェッ
    クを行なう方がよいでしょう。
    <div class="example" id="example-4">
     <p><strong>例4 より安全なファイル名の確認</strong></p>
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br />$username     </span><span style="color: #007700">= </span><span style="color: #0000BB">$_SERVER</span><span style="color: #007700">[</span><span style="color: #DD0000">'REMOTE_USER'</span><span style="color: #007700">]; </span><span style="color: #FF8000">// 認証機構を使用する<br /></span><span style="color: #0000BB">$userfile     </span><span style="color: #007700">= </span><span style="color: #0000BB">$_POST</span><span style="color: #007700">[</span><span style="color: #DD0000">'user_submitted_filename'</span><span style="color: #007700">];<br /></span><span style="color: #0000BB">$homedir      </span><span style="color: #007700">= </span><span style="color: #DD0000">"/home/</span><span style="color: #0000BB">$username</span><span style="color: #DD0000">"</span><span style="color: #007700">;<br /><br /></span><span style="color: #0000BB">$filepath     </span><span style="color: #007700">= </span><span style="color: #DD0000">"</span><span style="color: #0000BB">$homedir</span><span style="color: #DD0000">/</span><span style="color: #0000BB">$userfile</span><span style="color: #DD0000">"</span><span style="color: #007700">;<br /><br />if (!</span><span style="color: #0000BB">ctype_alnum</span><span style="color: #007700">(</span><span style="color: #0000BB">$username</span><span style="color: #007700">) || !</span><span style="color: #0000BB">preg_match</span><span style="color: #007700">(</span><span style="color: #DD0000">'/^(?:[a-z0-9_-]|\.(?!\.))+$/iD'</span><span style="color: #007700">, </span><span style="color: #0000BB">$userfile</span><span style="color: #007700">)) {<br />    die(</span><span style="color: #DD0000">"Bad username/filename"</span><span style="color: #007700">);<br />}<br /><br /></span><span style="color: #FF8000">// etc.<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

    </div>
   </p>
   <p class="para">
    オペレーティングシステムによって、注意するべきファイルは大きく変化し
    ます。これらには、デバイスエントリ(<var class="filename">/dev/</var> または <var class="filename">/dev/</var>)、設定ファイル(<var class="filename">/etc/</var> ファイルおよび <code class="literal">.ini</code> ファイル)、よく知られたファイル保存領
    域 (<var class="filename">/home/</var>、<var class="filename">My Documents</var>)等が含まれます。このため、明示的に許可す
    るもの以外の全てを禁止する方針とする方が通常はより簡単です。
   </p>   
   

  </div>
<?php manual_footer($setup); ?>