<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <HTML ><HEAD ><TITLE >Segurança do Sistema de Arquivos</TITLE ><META NAME="GENERATOR" CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK REL="HOME" TITLE="Manual do PHP" HREF="index.html"><LINK REL="UP" TITLE="Segurança" HREF="security.html"><LINK REL="PREVIOUS" TITLE="Instalado como módulo do Apache" HREF="security.apache.html"><LINK REL="NEXT" TITLE="Segurança de Bancos de Dados" HREF="security.database.html"><META HTTP-EQUIV="Content-type" CONTENT="text/html; charset=UTF-8"></HEAD ><BODY CLASS="chapter" BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#840084" ALINK="#0000FF" ><DIV CLASS="NAVHEADER" ><TABLE SUMMARY="Header navigation table" WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" ><TR ><TH COLSPAN="3" ALIGN="center" >Manual do PHP</TH ></TR ><TR ><TD WIDTH="10%" ALIGN="left" VALIGN="bottom" ><A HREF="security.apache.html" ACCESSKEY="P" >Anterior</A ></TD ><TD WIDTH="80%" ALIGN="center" VALIGN="bottom" ></TD ><TD WIDTH="10%" ALIGN="right" VALIGN="bottom" ><A HREF="security.database.html" ACCESSKEY="N" >Próxima</A ></TD ></TR ></TABLE ><HR ALIGN="LEFT" WIDTH="100%"></DIV ><DIV CLASS="chapter" ><H1 ><A NAME="security.filesystem" >Capítulo 26. Segurança do Sistema de Arquivos</A ></H1 ><P > O PHP está sujeito à segurança encontrada na maioria dos sistemas de servidor com respeito à permissões de arquivos e diretórios. Isso permite que você controle quais 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 tem acesso ao sistema de arquivos. </P ><P > Já que o PHP foi desenhado para permitir acesso em nível de usuário ao sistema de aruqivos, é possível escrever um script PHP que permitirá ler arquivos do sistema com /etc/passwd, modificar suas conexões de ethernet, enviar trabalhos de impressão gigantes, etc. Isso tem algumas implicações óbvias, já que você precisa ter certeza que os arquivos que você lê e escreve são apropriados. </P ><P > Considere o seguinte script, onde um usuário indica que ele quer apagar um arquivo no seu diretório home. Isso presume uma situação onde uma interface web PHP é usada regularmente para controle de arquivos, então o usuário do Apache tem permissão de apagar arquivos nos diretórios home dos usuários. </P ><P > <TABLE WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" CLASS="EXAMPLE" ><TR ><TD ><DIV CLASS="example" ><A NAME="AEN6415" ></A ><P ><B >Exemplo 26-1. Checagem fraca de variáveis resulta em....</B ></P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" CELLPADDING="5" ><TR ><TD ><code><font color="#000000"> <font color="#0000BB"><?php<br /></font><font color="#FF8000">// remove um arquivo do diretório home do usuário<br /></font><font color="#0000BB">$username </font><font color="#007700">= </font><font color="#0000BB">$_POST</font><font color="#007700">[</font><font color="#DD0000">'user_submitted_name'</font><font color="#007700">];<br /></font><font color="#0000BB">$homedir </font><font color="#007700">= </font><font color="#DD0000">"/home/$username"</font><font color="#007700">;<br /></font><font color="#0000BB">$file_to_delete </font><font color="#007700">= </font><font color="#DD0000">"$userfile"</font><font color="#007700">;<br /></font><font color="#0000BB">unlink </font><font color="#007700">(</font><font color="#DD0000">"$homedir/$userfile"</font><font color="#007700">);<br />echo </font><font color="#DD0000">"$file_to_delete foi apagado!"</font><font color="#007700">;<br /></font><font color="#0000BB">?></font> </font> </code></TD ></TR ></TABLE ></DIV ></TD ></TR ></TABLE > Já que o nome do usuário é enviado de um formulário do usuário, eles podem enviar um nome de usuário e um arquivo pertencente a outra pessoa e apagar os arquivos. Nesse caso, você desejaria ter alguma outra forma de autenticação. Considere o que poderia acontecer se as variáveis enviadas forem "../etc/" and "passwd". O código então leria efetivamente: <TABLE WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" CLASS="EXAMPLE" ><TR ><TD ><DIV CLASS="example" ><A NAME="AEN6418" ></A ><P ><B >Exemplo 26-2. ... um ataque ao sistema de arquivos</B ></P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" CELLPADDING="5" ><TR ><TD ><code><font color="#000000"> <font color="#0000BB"><?php<br /></font><font color="#FF8000">// remove um arquivo em qualquer lugar do disco rígido no qual<br />// o usuário do PHP tem acesso. Se o PHP tiver acesso de administrador (root):<br /></font><font color="#0000BB">$username </font><font color="#007700">= </font><font color="#DD0000">"../etc/"</font><font color="#007700">;<br /></font><font color="#0000BB">$homedir </font><font color="#007700">= </font><font color="#DD0000">"/home/../etc/"</font><font color="#007700">;<br /></font><font color="#0000BB">$file_to_delete </font><font color="#007700">= </font><font color="#DD0000">"passwd"</font><font color="#007700">;<br /></font><font color="#0000BB">unlink </font><font color="#007700">(</font><font color="#DD0000">"/home/../etc/passwd"</font><font color="#007700">);<br />echo </font><font color="#DD0000">"/home/../etc/passwd foi apagado!"</font><font color="#007700">;<br /></font><font color="#0000BB">?></font> </font> </code></TD ></TR ></TABLE ></DIV ></TD ></TR ></TABLE > Existem duas medidas importantes que você deve tomar para previnir esses problemas. <P ></P ><UL ><LI ><P > Só dar permissões limitadas ao usuário executando o binário do PHP. </P ></LI ><LI ><P > Checar todas as variáveis que são enviadas. </P ></LI ></UL > Aqui temos um script melhorado: <TABLE WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" CLASS="EXAMPLE" ><TR ><TD ><DIV CLASS="example" ><A NAME="AEN6426" ></A ><P ><B >Exemplo 26-3. Checagem mais segura do nome do arquivo</B ></P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" CELLPADDING="5" ><TR ><TD ><code><font color="#000000"> <font color="#0000BB"><?php<br /></font><font color="#FF8000">// remove um arquivo do disco rígido que<br />// o usuário do PHP tem acesso:<br /></font><font color="#0000BB">$username </font><font color="#007700">= </font><font color="#0000BB">$_SERVER</font><font color="#007700">[</font><font color="#DD0000">'REMOTE_USER'</font><font color="#007700">]; </font><font color="#FF8000">// usando um mecanismo de autenticação<br /><br /></font><font color="#0000BB">$homedir </font><font color="#007700">= </font><font color="#DD0000">"/home/$username"</font><font color="#007700">;<br /><br /></font><font color="#0000BB">$file_to_delete </font><font color="#007700">= </font><font color="#0000BB">basename</font><font color="#007700">(</font><font color="#DD0000">"$userfile"</font><font color="#007700">); </font><font color="#FF8000">// retira caminhos<br /></font><font color="#0000BB">unlink </font><font color="#007700">(</font><font color="#0000BB">$homedir</font><font color="#007700">/</font><font color="#0000BB">$file_to_delete</font><font color="#007700">);<br /><br /></font><font color="#0000BB">$fp </font><font color="#007700">= </font><font color="#0000BB">fopen</font><font color="#007700">(</font><font color="#DD0000">"/home/logging/filedelete.log"</font><font color="#007700">,</font><font color="#DD0000">"+a"</font><font color="#007700">); </font><font color="#FF8000">// registra a remoção<br /></font><font color="#0000BB">$logstring </font><font color="#007700">= </font><font color="#DD0000">"$username $homedir $file_to_delete"</font><font color="#007700">;<br /></font><font color="#0000BB">fwrite </font><font color="#007700">(</font><font color="#0000BB">$fp</font><font color="#007700">, </font><font color="#0000BB">$logstring</font><font color="#007700">);<br /></font><font color="#0000BB">fclose</font><font color="#007700">(</font><font color="#0000BB">$fp</font><font color="#007700">);<br /><br />echo </font><font color="#DD0000">"$file_to_delete foi apagado!"</font><font color="#007700">;<br /></font><font color="#0000BB">?></font> </font> </code></TD ></TR ></TABLE ></DIV ></TD ></TR ></TABLE > No entanto, ele ainda possui falhas. Se seu sistema de autenticação permitir que os usuários criem seu próprios logins, e um usuário escolher o login "../etc/", o sistema está novamente exposto. Por essa razão, você pode preferir escrever uma checagem mais específica: <TABLE WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" CLASS="EXAMPLE" ><TR ><TD ><DIV CLASS="example" ><A NAME="AEN6429" ></A ><P ><B >Exemplo 26-4. Checagem mais segura do nome do arquivo</B ></P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" CELLPADDING="5" ><TR ><TD ><code><font color="#000000"> <font color="#0000BB"><?php<br />$username </font><font color="#007700">= </font><font color="#0000BB">$_SERVER</font><font color="#007700">[</font><font color="#DD0000">'REMOTE_USER'</font><font color="#007700">]; </font><font color="#FF8000">// usando um mecanismo de autenticação<br /></font><font color="#0000BB">$homedir </font><font color="#007700">= </font><font color="#DD0000">"/home/$username"</font><font color="#007700">;<br /><br />if (!</font><font color="#0000BB">ereg</font><font color="#007700">(</font><font color="#DD0000">'^[^./][^/]*$'</font><font color="#007700">, </font><font color="#0000BB">$userfile</font><font color="#007700">))<br /> die(</font><font color="#DD0000">'nome de arquivo inválido'</font><font color="#007700">); </font><font color="#FF8000">// morre, não processa<br /><br /></font><font color="#007700">if (!</font><font color="#0000BB">ereg</font><font color="#007700">(</font><font color="#DD0000">'^[^./][^/]*$'</font><font color="#007700">, </font><font color="#0000BB">$username</font><font color="#007700">))<br /> die(</font><font color="#DD0000">'nome de arquivo inválido'</font><font color="#007700">); </font><font color="#FF8000">//morre, não processa<br />//etc...<br /></font><font color="#0000BB">?></font> </font> </code></TD ></TR ></TABLE ></DIV ></TD ></TR ></TABLE > </P ><P > Dependendo do seu sistema operacional, existe uma variedade enorme de arquivos que você tem que se preocupar, incluindo dispositivos (/dev/ or COM1), arquivos de configuração (arquivos /etc/ e .ini), áres de armazenamento conhecidas (/home/, My Documents), etc. Por essa razão, normalmente é mais fácil criar uma política onde você proibe tudo exceto aquilo que for explicitamente permitido. </P ></DIV ><DIV CLASS="NAVFOOTER" ><HR ALIGN="LEFT" WIDTH="100%"><TABLE SUMMARY="Footer navigation table" WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" ><TR ><TD WIDTH="33%" ALIGN="left" VALIGN="top" ><A HREF="security.apache.html" ACCESSKEY="P" >Anterior</A ></TD ><TD WIDTH="34%" ALIGN="center" VALIGN="top" ><A HREF="index.html" ACCESSKEY="H" >Principal</A ></TD ><TD WIDTH="33%" ALIGN="right" VALIGN="top" ><A HREF="security.database.html" ACCESSKEY="N" >Próxima</A ></TD ></TR ><TR ><TD WIDTH="33%" ALIGN="left" VALIGN="top" >Instalado como módulo do Apache</TD ><TD WIDTH="34%" ALIGN="center" VALIGN="top" ><A HREF="security.html" ACCESSKEY="U" >Acima</A ></TD ><TD WIDTH="33%" ALIGN="right" VALIGN="top" >Segurança de Bancos de Dados</TD ></TR ></TABLE ></DIV ></BODY ></HTML >