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 #1 Checagem fraca de variáveis resulta em....
<?php
// remove a file from the user's home directory
$username = $_POST['user_submitted_name'];
$userfile = $_POST['user_submitted_filename'];
$homedir = "/home/$username";
unlink("$homedir/$userfile");
echo "The file has been deleted!";
?>
Exemplo #2 ... um ataque ao sistema de arquivos
<?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 "The file has been deleted!";
?>
Exemplo #3 Checagem mais segura do nome do arquivo
<?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 = "Deleted $filepath\n";
} else {
$logstring = "Failed to delete $filepath\n";
}
$fp = fopen("/home/logging/filedelete.log", "a");
fwrite($fp, $logstring);
fclose($fp);
echo htmlentities($logstring, ENT_QUOTES);
?>
Exemplo #4 Checagem mais segura do nome do arquivo
<?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("Bad username/filename");
}
//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.