mirror of
https://github.com/php/doc-pt_br.git
synced 2026-03-23 22:52:12 +01:00
237 lines
7.7 KiB
XML
237 lines
7.7 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!-- EN-Revision: 91570644fbbe4d23e79908e1a04c4c4d003fe587 Maintainer: rafaelbernard Status: ready --><!-- CREDITS: rafaelbernard,narigone,leonardolara -->
|
|
<!-- splitted from ./index.xml, last change in rev 1.66 -->
|
|
<chapter xml:id="security.filesystem" xmlns="http://docbook.org/ns/docbook">
|
|
<title>Segurança do Sistema de Arquivos</title>
|
|
<simpara>
|
|
O <acronym>PHP</acronym> 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.
|
|
</simpara>
|
|
<simpara>
|
|
Já que o <acronym>PHP</acronym> foi projetado para permitir acesso em nível de usuário ao sistema
|
|
de arquivos, é possível escrever um script <acronym>PHP</acronym> que permitirá
|
|
ler arquivos do sistema como o <filename>/etc/passwd</filename>, 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.
|
|
</simpara>
|
|
<simpara>
|
|
Considere o seguinte script, onde um usuário indica que quer
|
|
apagar um arquivo no seu diretório "home". Isso presume uma situação
|
|
onde uma interface web <acronym>PHP</acronym> é 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.
|
|
</simpara>
|
|
<para>
|
|
<example>
|
|
<title>Verificação fraca de variáveis resulta em....</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
// Remove um arquivo do diretório "home" do usuário
|
|
$username = $_POST['user_submitted_name'];
|
|
$userfile = $_POST['user_submitted_filename'];
|
|
$homedir = "/home/$username";
|
|
|
|
unlink("$homedir/$userfile");
|
|
|
|
echo "O arquivo foi removido!";
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
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
|
|
<literal>"../etc/"</literal> e <literal>"passwd"</literal>.
|
|
O código então leria efetivamente:
|
|
<example>
|
|
<title>... um ataque ao sistema de arquivos</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
// Remove um arquivo de qualquer lugar no disco rígido
|
|
// que o usuário do PHP tenha acesso. Se o PHP tiver acesso de administrador (root):
|
|
$username = $_POST['user_submitted_name']; // "../etc"
|
|
$userfile = $_POST['user_submitted_filename']; // "passwd"
|
|
$homedir = "/home/$username"; // "/home/../etc"
|
|
|
|
unlink("$homedir/$userfile"); // "/home/../etc/passwd"
|
|
|
|
echo "O arquivo foi removido!";
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
Existem duas medidas importantes que você deve tomar para prevenir
|
|
esses problemas.
|
|
<itemizedlist>
|
|
<listitem>
|
|
<simpara>
|
|
Dar permissões limitadas ao usuário web binário do <acronym>PHP</acronym>.
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
Checar todas as variáveis que são enviadas.
|
|
</simpara>
|
|
</listitem>
|
|
</itemizedlist>
|
|
Aqui temos um script melhorado:
|
|
<example>
|
|
<title>Checagem com mais segura do nome do arquivo</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
// Remove um arquivo do disco rígido que o
|
|
// usuário do PHP tenha acesso.
|
|
$username = $_SERVER['REMOTE_USER']; // usando um mecanismo de autenticação
|
|
$userfile = basename($_POST['user_submitted_filename']);
|
|
$homedir = "/home/$username";
|
|
|
|
$filepath = "$homedir/$userfile";
|
|
|
|
if (file_exists($filepath) && unlink($filepath)) {
|
|
$logstring = "Removido $filepath\n";
|
|
} else {
|
|
$logstring = "Falha ao remover $filepath\n";
|
|
}
|
|
|
|
$fp = fopen("/home/logging/filedelete.log", "a");
|
|
fwrite($fp, $logstring);
|
|
fclose($fp);
|
|
|
|
echo htmlentities($logstring, ENT_QUOTES);
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
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 <literal>"../etc/"</literal>, o sistema está novamente exposto. Por
|
|
essa razão, é preferível escrever uma verificação mais personalizada:
|
|
<example>
|
|
<title>Verificação mais segura do nome do arquivo</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
$username = $_SERVER['REMOTE_USER']; // usando um mecanismo de autenticação
|
|
$userfile = $_POST['user_submitted_filename'];
|
|
$homedir = "/home/$username";
|
|
|
|
$filepath = "$homedir/$userfile";
|
|
|
|
if (!ctype_alnum($username) || !preg_match('/^(?:[a-z0-9_-]|\.(?!\.))+$/iD', $userfile)) {
|
|
die("Usuário/arquivo inválido");
|
|
}
|
|
|
|
// etc.
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Dependendo do sistema operacional, existe uma variedade enorme de arquivos
|
|
com os quais se preocupar, incluindo dispositivos (<filename>/dev/</filename>
|
|
ou <filename>COM1</filename>), arquivos de configuração (arquivos <filename>/etc/</filename>
|
|
e arquivos <literal>.ini</literal>), áreas de armazenamento de arquivo bem conhecidas (<filename>/home/</filename>,
|
|
<filename>My Documents</filename>), etc. Por essa
|
|
razão, normalmente é mais fácil criar uma política onde se proíbe
|
|
tudo exceto aquilo que for explicitamente permitido.
|
|
</para>
|
|
<sect1 xml:id="security.filesystem.nullbytes">
|
|
<title>Problemas relacionados aos bytes nulos (NUL)</title>
|
|
<simpara>
|
|
Como o <acronym>PHP</acronym> usa funções em C para operações relacionadas ao
|
|
sistema de arquivos, ele pode lidar com bytes nulos de maneira inesperada.
|
|
Como bytes nulos denotam fim de string em C, strings que os contém
|
|
não serão consideradas de forma inteira, mas apenas até que um byte nulo ocorra.
|
|
|
|
O seguinte exemplo mostra um código vulnerável que demonstra esse problema:
|
|
</simpara>
|
|
<example>
|
|
<title>Script vulnerável a bytes nulos</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
$file = $_GET['file']; // "../../etc/passwd\0"
|
|
|
|
if (file_exists('/home/wwwrun/' . $file. '.php')) {
|
|
// file_exists retornará true porque o arquivo /home/wwwrun/../../etc/passwd existe
|
|
include '/home/wwwrun/' . $file . '.php';
|
|
// o arquivo /etc/passwd será incluído
|
|
|
|
}
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<para>
|
|
Portanto, qualquer string comprometida que é usada em uma operação de sistema de arquivos deve
|
|
sempre ser validada corretamente. Aqui está uma versão melhorada do exemplo anterior:
|
|
</para>
|
|
<example>
|
|
<title>Validando entrada corretamente</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
$file = $_GET['file'];
|
|
|
|
// Autorizando valores possíveis
|
|
switch ($file) {
|
|
case 'main':
|
|
case 'foo':
|
|
case 'bar':
|
|
include '/home/wwwrun/include/' . $file . '.php';
|
|
break;
|
|
default:
|
|
include '/home/wwwrun/include/main.php';
|
|
}
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</sect1>
|
|
|
|
</chapter>
|
|
|
|
<!-- Keep this comment at the end of the file
|
|
Local variables:
|
|
mode: sgml
|
|
sgml-omittag:t
|
|
sgml-shorttag:t
|
|
sgml-minimize-attributes:nil
|
|
sgml-always-quote-attributes:t
|
|
sgml-indent-step:1
|
|
sgml-indent-data:t
|
|
indent-tabs-mode:nil
|
|
sgml-parent-document:nil
|
|
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
|
|
sgml-exposed-tags:nil
|
|
sgml-local-catalogs:nil
|
|
sgml-local-ecat-files:nil
|
|
End:
|
|
vim600: syn=xml fen fdm=syntax fdl=2 si
|
|
vim: et tw=78 syn=sgml
|
|
vi: ts=1 sw=1
|
|
-->
|