Segurança de sistema de arquivos

O PHP é assunto para a segurança construída na maioria dos sistemas de servidor, com respeito a permissões em um arquivo e em bases de diretórios. Isto permite que você controle quais arquivos no sistema de arquivos podem ser lidos. Cuidados deveriam ser tomados com arquivos que são liberados para leitura para a assegurar que eles estão protegidos para leitura para todos os usuários que tem acesso a esse sistema de arquivos.

Visto que o PHP foi desenvolvido para permitir acesso por nível de usuário ao sistema de arquivos, é inteiramente possível escrever um script PHP que permitirá a você ler sistema de arquivos tais como /etc/password, modificar suas conexões de ethernet, enviar trabalhos de impressora em massa para fora, etc. Isto tem algumas implicações óbvias, no que você precisa garantir que estes arquivos que você lê e escreve estão nos locais apropriados.

Considere o seguinte script, onde um usuário indica que eles tem como deletar um arquivo em seus diretórios home. Assume-se uma situação onde a interface web do PHP é usada regularmente para gerenciamento de arquivos, então o usuário do Apache está liberado para apagar arquivos nos diretórios home.

Exemplo 16-1. Checagem pobre de variável leva a....

<?php
// remove um arquivo de diretório home do usuário
$usuario = $_POST['user_submitted_name'];
$homedir = "/home/$usuario";
$file_to_delete = "$userfile";
unlink ("$homedir/$userfile");
echo
"$file_to_delete foi deletado!";
?>
Visto que o username é postável de um formulário de usuário, eles podem submeter um nome de usuário e arquivar pertencendo a outra pessoa, e deletar arquivos. Neste caso, você tem que utilizar outra forma de autenticação. Considere o que aconteceria se as variáveis submetidas fossem "../etc/" e "passwd". O código então leria efetivamente:

Exemplo 16-2. ... Um ataque de sistema de arquivos

<?php
// remove um arquivo de algum lugar no disco que o usuário
// do PHP tem acesso. Se o PHP possui acesso ao root:
$username = "../etc/";
$homedir = "/home/../etc/";
$file_to_delete = "passwd";
unlink ("/home/../etc/passwd");
echo
"/home/../etc/passwd foi deletado!";
?>
Há duas medidas importantes que você tomaria para prevenir estas coisas.

Aqui está um script melhorado:

Exemplo 16-3. Checagem de nome de arquivo mais seguro

<?php
// remove um arquivo do hd que o PHP usa para acessá-lo

$username = $_SERVER['REMOTE_USER']; // usando um mecanismo de autenticação

$homedir = "/home/$username";

$file_to_delete = basename("$userfile"); // Retira o caminho
unlink ($homedir/$file_to_delete);

$fp = fopen("/home/logging/filedelete.log","+a"); //Logar a deleção
$logstring = "$username $homedir $file_to_delete";
fputs ($fp, $logstring);
fclose($fp);

echo
"O $file_to_delete foi deletado!";
?>
However, even this is not without it's flaws. Se seu sistema de autenticação permite aos usuários criar seus próprios logins, e um usuário escolhe o login "../etc/", o sistema é exposto de novo. Por esta razão, você pode preferir escrever uma checagem mais detalhada:

Exemplo 16-4. Verificação de nome de arquivo mais segura

<?php
$username
= $_SERVER['REMOTE_USER']; // Usando um mecanismo de atenticação
$homedir = "/home/$username";

if (!
ereg('^[^./][^/]*$', $userfile))
     die(
'nome de arquivo maldoso'); //interromper, não processa

if (!ereg('^[^./][^/]*$', $username))
     die(
'nome de usuario maldoso'); //interromper, não processa
//etc...
?>

Dependendo de seu sistema operacional, há uma ampla variedade de arquivos que você estaria preocupado, incluindo entradas de dispositivos (/dev/ ou COM1), arquivos de configuração (arquivos /etc/ e os arquivos .ini), áreas de armazenamento de arquivos conhecidas (/home/, Meus Documentos), etc. Por este motivo, é normalmente mais fácil criar um policiamento onde você proibe tudo exceto para o que você permitir explicitamente.