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.
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.
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.
Exemplo 26-1. Checagem fraca de variáveis resulta em....
<?php // remove um arquivo do diretório home do usuário $username = $_POST['user_submitted_name']; $homedir = "/home/$username"; $file_to_delete = "$userfile"; unlink ("$homedir/$userfile"); echo "$file_to_delete foi apagado!"; ?>
|
|
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:
Exemplo 26-2. ... um ataque ao sistema de arquivos
<?php // remove um arquivo em qualquer lugar do disco rígido no qual // o usuário do PHP tem acesso. Se o PHP tiver acesso de administrador (root): $username = "../etc/"; $homedir = "/home/../etc/"; $file_to_delete = "passwd"; unlink ("/home/../etc/passwd"); echo "/home/../etc/passwd foi apagado!"; ?>
|
|
Existem duas medidas importantes que você deve tomar para previnir
esses problemas.
Aqui temos um script melhorado:
Exemplo 26-3. Checagem mais segura do nome do arquivo
<?php // remove um arquivo do disco rígido que // o usuário do PHP tem acesso: $username = $_SERVER['REMOTE_USER']; // usando um mecanismo de autenticação
$homedir = "/home/$username";
$file_to_delete = basename("$userfile"); // retira caminhos unlink ($homedir/$file_to_delete);
$fp = fopen("/home/logging/filedelete.log","+a"); // registra a remoção $logstring = "$username $homedir $file_to_delete"; fwrite ($fp, $logstring); fclose($fp);
echo "$file_to_delete foi apagado!"; ?>
|
|
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:
Exemplo 26-4. Checagem mais segura do nome do arquivo
<?php $username = $_SERVER['REMOTE_USER']; // usando um mecanismo de autenticação $homedir = "/home/$username";
if (!ereg('^[^./][^/]*$', $userfile)) die('nome de arquivo inválido'); // morre, não processa
if (!ereg('^[^./][^/]*$', $username)) die('nome de arquivo inválido'); //morre, não processa //etc... ?>
|
|
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.