<?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 => 'pt_BR',
  ),
  'this' => 
  array (
    0 => 'security.filesystem.php',
    1 => 'Seguran&ccedil;a do Sistema de Arquivos',
    2 => 'Seguran&ccedil;a do Sistema de Arquivos',
  ),
  'up' => 
  array (
    0 => 'security.php',
    1 => 'Seguran&ccedil;a',
  ),
  'prev' => 
  array (
    0 => 'security.sessions.php',
    1 => 'Seguran&ccedil;a da Sess&atilde;o',
  ),
  'next' => 
  array (
    0 => 'security.filesystem.nullbytes.php',
    1 => 'Problemas relacionados aos bytes nulos (NUL)',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'pt_BR',
    '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">Segurança do Sistema de Arquivos</h1>
<h2>Índice</h2><ul class="chunklist chunklist_chapter"><li><a href="security.filesystem.nullbytes.php">Problemas relacionados aos bytes nulos (NUL)</a></li></ul>

   <p class="simpara">
    O <abbr title="PHP: Hypertext Preprocessor">PHP</abbr> está sujeito à segurança encontrada na maioria dos sistemas de servidor
    com respeito às permissões de arquivos e diretórios. Isso permite que
    seja controlado que arquivos no sistema podem ser lidos e por quem. É preciso
    ter cuidado com quaisquer arquivos que são lidos por todos para assegurar
    que eles podem ser lidos por todos os usuários que têm acesso ao
    sistema de arquivos.
   </p>
   <p class="simpara">
    Já que o <abbr title="PHP: Hypertext Preprocessor">PHP</abbr> foi projetado para permitir acesso em nível de usuário ao sistema
    de arquivos, é possível escrever um script <abbr title="PHP: Hypertext Preprocessor">PHP</abbr> que permitirá
    ler arquivos do sistema como o <var class="filename">/etc/passwd</var>, modificar suas conexões
    de rede, enviar inúmeros trabalhos de impressão, etc. Isso tem
    algumas implicações óbvias, já que é necessário garantir que os arquivos
    lidos e gravados são apropriados.
   </p>
   <p class="simpara">
    Considere o seguinte script, onde um usuário indica que quer
    apagar um arquivo no seu diretório &quot;home&quot;. Isso presume uma situação
    onde uma interface web <abbr title="PHP: Hypertext Preprocessor">PHP</abbr> é usada regularmente para controle
    de arquivos, então o usuário do Apache tem permissão de apagar arquivos
    nos diretórios &quot;home&quot; dos usuários.
   </p>
   <p class="para">
    <div class="example" id="example-1">
     <p><strong>Exemplo #1 Verificação fraca de variáveis resulta em....</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">// Remove um arquivo do diretório "home" do usuário<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">"O arquivo foi removido!"</span><span style="color: #007700">;<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

    </div>
   Já que o nome do usuário e do arquivo são enviados pelo formulário,
   um usuário pode enviar um nome de usuário e de arquivo que pertença a outra pessoa,
   e apagá-lo, mesmo que eles não tenham permissão para fazê-lo.
   Nesse caso, é preciso ter alguma outra forma de autenticação.
   Considere o que poderia acontecer se as variáveis enviadas forem
   <code class="literal">&quot;../etc/&quot;</code> e <code class="literal">&quot;passwd&quot;</code>.
   O código então leria efetivamente:
    <div class="example" id="example-2">
     <p><strong>Exemplo #2 ... um ataque ao sistema de arquivos</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">// Remove um arquivo de qualquer lugar no disco rígido<br />// que o usuário do PHP tenha acesso. Se o PHP tiver acesso de administrador (root):<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">"O arquivo foi removido!"</span><span style="color: #007700">;<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

    </div>
    Existem duas medidas importantes que você deve tomar para prevenir
    esses problemas.
    <ul class="itemizedlist">
     <li class="listitem">
      <span class="simpara">
       Dar permissões limitadas ao usuário web binário do <abbr title="PHP: Hypertext Preprocessor">PHP</abbr>.
      </span>
     </li>
     <li class="listitem">
      <span class="simpara">
       Checar todas as variáveis que são enviadas.
      </span>
     </li>
    </ul>
    Aqui temos um script melhorado:
    <div class="example" id="example-3">
     <p><strong>Exemplo #3 Checagem com mais segura do nome do arquivo</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">// Remove um arquivo do disco rígido que o<br />// usuário do PHP tenha acesso.<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">// usando um mecanismo de autenticação<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">"Removido </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">"Falha ao remover </span><span style="color: #0000BB">$filepath</span><span style="color: #DD0000">\n"</span><span style="color: #007700">;<br />}<br /><br /></span><span style="color: #0000BB">$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>
    No entanto, ele ainda possui falhas. Se seu sistema de autenticação
    permitir que os usuários criem seus próprios logins, e um usuário
    escolher o login <code class="literal">&quot;../etc/&quot;</code>, o sistema está novamente exposto. Por
    essa razão, é preferível escrever uma verificação mais personalizada:
    <div class="example" id="example-4">
     <p><strong>Exemplo #4 Verificação mais segura do nome do arquivo</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">// usando um mecanismo de autenticação<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">"Usuário/arquivo inválido"</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">
    Dependendo do sistema operacional, existe uma variedade enorme de arquivos
    com os quais se preocupar, incluindo dispositivos (<var class="filename">/dev/</var>
    ou <var class="filename">COM1</var>), arquivos de configuração (arquivos <var class="filename">/etc/</var>
    e arquivos <code class="literal">.ini</code>), áreas de armazenamento de arquivo bem conhecidas (<var class="filename">/home/</var>,
    <var class="filename">My Documents</var>), etc. Por essa
    razão, normalmente é mais fácil criar uma política onde se proíbe
    tudo exceto aquilo que for explicitamente permitido.
   </p>
   

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