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.