O documento discute recomendações de segurança para MySQL e PHP, incluindo: (1) não usar o usuário root no MySQL e criar usuários específicos por banco de dados; (2) atribuir privilégios estritamente necessários aos usuários; (3) esconder informações desnecessárias sobre arquivos, configurações e estrutura do banco de dados.
SLIDE DE Revolução Mexicana 1910 da disciplina cultura espanhola
MySQL e PHP: Segurança básica
1. MySQL e PHP: Segurança
Carlos Santos
LabMM 4 - NTC - DeCA - UA
Aula PHP+MySQL 07, 23-05-2012
2. MySQL: recomendações
servidor MySQL
• nunca utilizar o utilizador root para o acesso às BDs
• para cada BD, definir um novo utilizador só com acesso via localhost
3. MySQL: recomendações
no servidor MySQL
• atribuir os privilégios estritamente necessários a esse utilizador e apenas
na BD com que ele irá interagir
• se necessário, ter utilizadores com privilégios diferenciados para
frontoffice e backoffice
4. Paradigma “need to know only”
esconder toda a informação que permita saber mais do que é necessário
sobre:
• ficheiros e pastas do servidor
• configuração do servidor Web
• configuração do PHP no servidor Web
• estrutura da BD
5. Listagem de diretórios/pastas
não permitir o directory browsing
• não permitir ver os conteúdos de uma pasta quando não existe um
ficheiro por defeito
• colocar na pasta um ficheiro .htaccess (Options -Indexes)
• os efeitos do .htaccess são reflectidos nas subpastas
6. Informação sobre o servidor Web
esconder informação sobre o servidor Web
• no .htaccess (ServerSignature Off)
• também é possível utilizando o httpd.conf
• qualquer informação disponível pode dar pistas que facilitam o
reconhecimento de falhas de segurança a explorar!
7. Configuração do PHP
esconder informação sobre a configuração do PHP no servidor
• não permitir a execução da função phpinfo()
• php.ini (disable_functions = phpinfo)
• esta diretiva do php.ini pode ser utilizada para outras funções
potencialmente perigosas (disable_functions = phpinfo, exec,
passthru, shell_exec, system, proc_open, popen,
curl_exec, curl_multi_exec, parse_ini_file, show_source)
• não expor informação sobre o PHP
• php.ini (expose_php = ‘off’)
8. Mensagens de erro do PHP
esconder mensagens de erros do PHP (expõem informações importantes
sobre os ficheiros, servidor e PHP)
• php.ini
; E_ALL & ~E_NOTICE (Show all errors, except for notices and coding standards warnings.)
; E_ALL & ~E_NOTICE | E_STRICT (Show all errors, except for notices)
; E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR (Show only errors)
; E_ALL | E_STRICT (Show all errors, warnings and notices including coding standards.)
; Default Value: E_ALL & ~E_NOTICE
; Development Value: E_ALL | E_STRICT
; Production Value: E_ALL & ~E_DEPRECATED
error_reporting = E_ALL & ~E_DEPRECATED
; Default Value: On
; Development Value: On
; Production Value: Off
display_errors = Off
• em produção, ter log dos erros: log_errors=On e error_log=“file”
10. Mais recomendações
PHP Security Consortium (http://phpsec.org/)
• na secção de projectos:
• Security Guide (PDF)
• PHPSecInfo: aplicação (Download & install)
11. Execução de ficheiros via Web
impedir que se possam visualizar/alterar ou executar, via web, ficheiros
potencialmente perigosos
• .htaccess
<Files ~ ".(log|inc|sql|ini)$">
Order allow,deny
extensões não permitidas
Deny from all
</Files>
<Files ~ "^.ht">
Order allow,deny impedir o acesso ao .htaccess
Deny from all
Satisfy All
</Files>
12. Inclusão e upload de ficheiros
incluir ficheiros sempre através do require/require_once -> qualquer erro
termina execução do PHP
no upload de ficheiros a partir de uma formulário:
• testar a extensão do ficheiro carregado: $_FILES[‘ficheiro’][‘type’] ou
através da função pathinfo()
• testar o tamanho do ficheiro carregado: $_FILES[‘ficheiro’][‘size’] ou
através da função filesize()
• no final usar sempre a função move_uploaded_file(), para colocar o
ficheiro na sua pasta destino
13. Filtragem de dados
muitas das ameaças à segurança pode provir de dados maliciosos
introduzidos em formulários, variáveis superglobais ($_GET, $_POST,
$_SESSION, $_FILES, etc), queries à BD, etc…
• filtragem lógica -> associada à lógica do algoritmo de processamento
dos dados
• filtragem de limpeza -> remoção de todos os caracteres potencialmente
perigosos nos dados
• usar sempre -> filtragem cliente-side (JavaScript) + filtragem server-
side (PHP)
• evitar utilização de hidden form fields
• evitar, sempre que possível, a passagem de parâmetros na Query String
-> usar Variáveis de sessão
• parâmetros na Query String -> são de fácil edição e partilha e podem
revelar estrutura da BD ou de outros parâmetros da aplicação
14. Filtragem e codificação de dados
Valores contidos numa variável
• filter_var($a, FILTER_VALIDATE_INT);
• filter_var($a, FILTER_SANITIZE_NUMBER_INT);
• filter_var($b, FILTER_VALIDATE_EMAIL);
• filter_var($b, FILTER_SANITIZE_EMAIL);
• Mais critérios em http://php.net/manual/en/filter.constants.php
• Artigo sobre filtragem: http://www.phpro.org/tutorials/Filtering-Data-with-
PHP.html
15. Filtragem e codificação de dados
preservar a formatação HTML mas codificar inputs para utilizarem HTML
entities
• htmlentities($d);
limpar tags HTML e PHP
• strip_tags($e);
problemas com codificação
• utf8_encode($e1);
• utf8_decode($e2);
Retirar espaços do início e do final de uma string
• trim($a);
16. Filtragem e codificação de dados
get_magic_quotes_gpc() -> avalia o estado da directiva no php.ini
• por defeito está “Off” (no PHP 6 será removida!)
• quando “On” todos os valores vindos por $_GET, $_POST, $_COOKIE
recebem o escape automático de certos caracteres: ‘, ”,
stripslashes() -> remove as de uma string
mysql_real_escape_string() -> faz o escape de ‘, “ e
17. SQL Injection
A introdução de inputs não filtrados nas queries pode originar falhas de
segurança. É inadmissível em páginas de produção!
18. SQL Injection: funções de filtragem
remover eventuais comandos SQL
• preg_replace ($padrao_a_procurar, $valor_substituicao,
$string_alvo_da_procura)
palavras a procurar
• $padrao_a_procurar = “/(…|…|…)/i” (expressões regulares).
“i” no final torna pesquisa
case insensitive
function valida($a) {
$a = strip_tags($a); //remover tags
$a = mysql_real_escape_string($a);
$padrao = "/(select|from|where|like|order|drop|insert|
delete|update|values|and|or|create|tables|table|#|;)/i";
$a = preg_replace($padrao, "", $a);
$a = trim($a);
return $a;
}!
19. Outras funções úteis na filtragem/validação
pesquisa de padrões
• preg_match($padrao_a_procurar, $string_alvo_da_procura);
• preg_match("/@ua.pt/i",$f);
• preg_match("/^(?!d+$|[a-z]+$|.*[W_])/i",$g);
• http://www.phpf1.com/tutorial/php-regular-expression.html
• http://weblogtoolscollection.com/regex/regex.php
• ctype_alnum($string); -> valida caracteres alfanuméricos
• ctype_alpha($string); -> validação de caracteres alfabéticos
• ctype_digit($string); -> valida caracteres numéricos
20. Codificação de passwords
Armazenar na BD as passwords codificadas!
• MD5 (128bits)
• $pwd_codif = md5($pwd);
• SHA1 (160bits) ou hash()
• $pwd_codif = sha1($pwd);
• BASE64
• $pwd_codif = base64_encode($pwd);
• $pwd = base64_decode($pwd_codif);
• hash(...) e crypt(...)
• permitem escolher o tipo de codificação
• o crypt() permite adicionar uma string de SALT
21. XSS - Cross Site Scripting
Introdução de código (normalmente JS) em áreas de User Generated
Content (blogues, fóruns, comments, etc.)
• não é um ataque direto ao site, mas sim ao utilizador…
• diferenças entre browsers!
• Exemplo 1
• Input: <script language="javascript"> document.location="http://
www.ua.pt"; </script>
echo $_POST['campo1']; //vai redirecionar
• Exemplo 2
• Input: <script language="javascript"> document.location="http://
www.ua.pt"; </script>
echo strip_tags($_POST['campo1']); //não redireciona
echo htmlentities($_POST['campo1']); //não redireciona