implementando segurança em sua aplicação php

34
 © 2007 Er Galvão Abbott - http://www.galvao.eti.br/ Implementando Segurança em sua aplicação PHP v. 1.0 - Novembro/2007

Upload: er-galvao-abbott

Post on 11-Jun-2015

5.879 views

Category:

Technology


2 download

DESCRIPTION

Uma variante da palestra "PHP & Segurança - Uma união possível", procura fornecer um pouco mais de detalhes à respeito deste conteúdo.

TRANSCRIPT

Page 1: Implementando Segurança Em Sua Aplicação PHP

   

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

Implementando Segurançaem sua aplicação

PHP

v. 1.0 ­ Novembro/2007

Page 2: Implementando Segurança Em Sua Aplicação PHP

   

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

Objetivo:

    Esta apresentação tem por objetivo apresentar técnicaspara o desenvolvimento de aplicações seguras utilizando a linguagem PHP, eliminando os equívocos geralmente relacionados à esta.

Page 3: Implementando Segurança Em Sua Aplicação PHP

   

Conceitos:

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

PHP – Uma linguagem vulnerável?

    Um dos equívocos mais comuns relacionados à linguagem PHP é o de que é difícil de se produzir sistemas e ferramentas seguras quando a utilizamos.

    Este equívoco é fundamentado em 3 conceitos:

• A simplicidade da linguagem, com uma baixa curva de aprendizado

• A própria fragilidade da web como ambiente de aplicações

• Algumas features presentes na linguagem

Page 4: Implementando Segurança Em Sua Aplicação PHP

   

Conceitos: Simplicidade != Vulnerabilidade

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

O Problema:

    Por ser uma linguagem de fácil aprendizado, é grande o número de pessoas que começam a carreira de desenvolvimento deaplicações utilizando PHP. 

    Esta falta de experiência freqüentemente resulta em aplicações de baixa qualidade e com problemas relacionados, especialmente, comsegurança.

A Solução:

    A comunidade, de forma geral, precisa amadurecer e possuir acesso a recursos que a tornem melhor. Eventos, artigos e a disseminação de boas práticas de desenvolvimento são apenas alguns dos caminhos que estão sendo trilhados para chegarmos a este objetivo.

Page 5: Implementando Segurança Em Sua Aplicação PHP

   

Conceitos: Web: “A Terra de Ninguém”:

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

O Problema:    A web é um ambiente precário em termos de segurança.

    Dificuldade para identificar os usuários, ameaças que proliferam às dezenas e usuários descuidados são lugares­comuns quando tratamos de uma aplicação web.

A Solução:

    Criar o hábito de pensar qualquer aplicação web, por mais simples que seja, levando­se em consideração a questão de segurança. 

    Termos a noção de que é nossa responsabilidade como desenvolvedores criar aplicações que sejam minimamente seguras.

Page 6: Implementando Segurança Em Sua Aplicação PHP

   

Conceitos: Aplicações mais maduras:

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

O Problema:

    Algumas features que podem ser utilizadas na linguagem, como a ativação da configuração register_globals, facilitam o trabalho, mas inevitavelmente aumentam riscos de segurança e acostumam mal o desenvolvedor.

A Solução:

    Nos acostumarmos a desempenhar nosso trabalho da melhor forma possível, tendo sempre em mente que tudo o que é fácil tem seu preço e o que dá mais trabalho hoje causará menos incômodos amanhã.

Page 7: Implementando Segurança Em Sua Aplicação PHP

   

Boas Práticas: Onde tudo começa

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

register_globals desligada, sempre!

require ao invés de include!

Filtrando a entrada

Erros são para a fase de desenvolvimento!

Coloque tudo em seu devido lugar!

Criptografia: USE!

Page 8: Implementando Segurança Em Sua Aplicação PHP

   

Conceitos: register_globals desligada, sempre!

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

    A configuração register_globals é, sem dúvida, uma das mais popularesdisponíveis na configuração do interpretador PHP. Sua utilização porém é uma péssima idéia, por dois motivos:

Tira do programador a noção de origem dos dados.

Tira do interpretador da linguagem a noção de origem dos dados.

A configuração register_globals é tão polêmica que passouà ser desabilitada por default à partir da versão 4.2.0 eserá eliminada na versão 6 da linguagem.

Page 9: Implementando Segurança Em Sua Aplicação PHP

   

Prova de Caso #1: Ignorando a origem dos dados

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

Considere o seguinte código:

<?php// Arquivo: sem_origem.phpif ($autenticado) {    echo “Usuário autenticado, prosseguir...”;} else {    echo “O usuário não está autenticado!”;}?>

    Ao desprezar a origem da informação a variável $autenticado quetipicamente viria de uma sessão ou cookie, por exemplo, poderá ser completamente sobrescrita de forma absurdamente simples:

http://www.galvao.eti.br/sem_origem.php?autenticado=true

Page 10: Implementando Segurança Em Sua Aplicação PHP

   

Solução: Reconhecendo a origem dos dados

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

Observe a mudança no código:

<?php// Arquivo: sem_origem.phpif ($_SESSION['autenticado']) {    echo “Usuário autenticado, prosseguir...”;} else {    echo “O usuário não está autenticado!”;}?>

    Ao explicitar a origem da informação, torna­se muito mais difícil forjar a variável $autenticado, pois para isso um cracker teria que forjar toda a  origem desta primeiro. Ao receber a URL:

http://www.galvao.eti.br/sem_origem.php?autenticado=true

o interpretador da linguagem jamais confundiria esta informação, pois ela não faz parte do array $_SESSION, mas do array $_GET.

Page 11: Implementando Segurança Em Sua Aplicação PHP

   http://www.galvao.eti.br/sem_trava.php?DOCUMENT_ROOT=%2Fcracker%2Fpublic_html

Prova de Caso #2: Ignorando a origem de um script

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

Considere o seguinte código:

<?php// Arquivo: sem_trava.phpinclude_once(“$DOCUMENT_ROOT/trava.php”);

if ($trava) {    die(“Problemas de autenticação!”);} else {    echo “Tudo OK!”;}?>

    Se estivermos  com a diretiva register_globals ativada, nosso script pode ser facilmente desviado para outro presente em, por exemplo, /cracker/public_html:

Page 12: Implementando Segurança Em Sua Aplicação PHP

   

<?php// Arquivo: sem_trava.phpinclude_once($_SERVER['DOCUMENT_ROOT'] . “/trava.php”);

if ($trava) {    die(“Problemas de autenticação!”);} else {    echo “Tudo OK!”;}?>

Solução: Comece fechando o caminho

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

A solução passa por várias ações, mas começa certamente pela não utilização da register_globals:

    Novamente explicitamos a origem do dado, impedindo que este dado seja forjado através de um caminho alternativo.

Page 13: Implementando Segurança Em Sua Aplicação PHP

   

<?phpif ($_POST) {

foreach($_POST as $nome => $valor) {$$nome = $valor;

}}?>

Mantendo a praticidade com segurança

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

    O maior empecilho para abandonar o vício da utilização da register_globals é a perda de agilidade no processo de desenvolvimento. Embora a solução apresentada à seguir ainda seja um pouco problemática, é sempre preferível utilizá­la em detrimento da register_globals:

    Ao utilizarmos o conceito de variáveis dinâmicas ou variáveis variáveis,  

implementamos uma espécie de versão “light” da register_globals: explicitamos a origem dos dados e ainda assim mantemos uma boa praticidade.

Page 14: Implementando Segurança Em Sua Aplicação PHP

   

Boas práticas: require ao invés de include!

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

A utilização do comando include implica em uma séria questão de segurança: se o arquivo que está sendo solicitado ao servidor não existir ou se qualquer outro imprevisto cause a falha da inclusão do referido arquivo o script continuará normalmente sua execução, como se nenhum problema tivesse ocorrido.

    Colocando em termos mais simples possíveis, você estará simplesmentejogando o seu script fora. Variáveis, funções e tudo o mais será completamente ignorado e o script que faria uso deste código continuará executando como se nada tivesse acontecido.

A falha de um comando include não interrompe a execução do script!

Page 15: Implementando Segurança Em Sua Aplicação PHP

   

Prova de caso #3: o include falhou, o script não!

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

1) Considere que o arquivo autenticar.php barra o usuário em caso de problemas de autenticação e/ou autorização.

    Se por qualquer eventualidade – como um erro de digitação por exemplo – o comando include falhar ainda assim o script continuará sendo executado normalmente, como se não houvesse problemas.

<?phpinclude_once “auteticar.php”;

if (!isLoggedIn()) {    die(“Problemas de autenticação!”);} else {    echo “Informações sigilosas do usuário”;}?>

2) Considere o seguinte código, que confia nas rotinas presentes em autenticar.php para mostrar ou não informações sigilosas:

Page 16: Implementando Segurança Em Sua Aplicação PHP

   

Solução: Se é importante não corra riscos!

<?phprequire_once “auteticar.php”;

if (!isLoggedIn()) {    die(“Problemas de autenticação!”);} else {    echo “Tudo OK!”;}?>

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

    A simples troca do comando include pelo comando require informa aointerpretador PHP – note o sentido da palavra – que o arquivo não está sendo simplesmente incluído, mas é requerido para que a aplicação funcione corretamente.

    A diferença – crucial, nesse caso – é que nosso script nem mesmo fará o teste condicional, ele será imediatamente interrompido na primeira linha, quando o arquivo não for encontrado.

Page 17: Implementando Segurança Em Sua Aplicação PHP

   

Desejo continuar usando o comando include

<?phpinclude_once “auteticar.php” or die(“Falha de comando include”);

if (!isLoggedIn()) {    die(“Problemas de autenticação!”);} else {    echo “Tudo OK!”;}?>

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

    Sem problema. Existe uma forma de “emularmos” o comportamento do comando require: informamos nosso código o que ele deve fazer caso o comando include falhe.

    Como no caso de uma falha a operação de inclusão não será executada o comando que segue após o operador or será executado em seu lugar: neste caso a interrupção imediata do script e a exibição de uma mensagem.

Page 18: Implementando Segurança Em Sua Aplicação PHP

   

Boas práticas: Não confie em dados de estranhos

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

Uma das principais técnicas de segurança envolve a filtragem de dados.A falta de filtragem é a principal causas de muitas vulnerabilidades, entre elas a famosa SQL Injection, ou injeção de SQL.

Quando trabalhamos levando em conta a filtragem de dados todo o dado é suspeito, ou contaminado, até que seja validado.

    Um dos equívocos mais comuns nesse sentido é quando tratamos esta“falta de confiança” como uma premissa de que o usuário é  mal­intencionado. Na realidade problemas de segurança podem também ser causados por erros e descuidos.

Jamais, em hipótese alguma, confie no usuário!

Page 19: Implementando Segurança Em Sua Aplicação PHP

   

Prova de caso #4: Dados contaminados == SQL Injection!

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

1) Considere este código que chamaremos de mostraUsuario.php:

<?php$conn = mysql_connect('servidor', usuario', 'senha');mysql_select_db('meu_banco');

$sql = 'SELECT email FROM usuarios WHERE idusuario = ' . 

           $_GET['userid'];

$recordSet = mysql_query($sql);?>

Seu código aceitará qualquer informação vinda da query string!

2) Observe que não há filtragem do dado de entrada: $_GET['userid']

Page 20: Implementando Segurança Em Sua Aplicação PHP

   

Prova de caso #4: Dados contaminados == SQL Injection!

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

    Desta forma é simples injetar código SQL na aplicação, pois qualquer dado passado para o script será aceito sem hesitação:

    Como 'x' é sempre igual à 'x' a condição anterior terá sido invalidada pelo OR e o cracker terá em mãos  todos os e­mails armazendos na base de dados.

http://www.galvao.eti.br/mostraUsuario.php?userid=198%20OR%20'x'='x'

    Após a conversão dos caracteres codificados (%20, ou seja, espaço em branco), esta é a query que será executada em nosso ingênuo script:

SELECT email FROM usuarios WHERE idusuario = 198 OR 'x' = 'x'

Page 21: Implementando Segurança Em Sua Aplicação PHP

   

Solução: Se a query aguarda um número, receba um número!

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

    Quando nossa query espera receber um número a solução é simples: forçamos o dado à ser numérico mesmo que ele não seja, fazendo com que qualquer tentativa de injeção de SQL se transforme apenas na partenumérica da string recebida ou no número 1, dependendo do caso:

<?php$conn = mysql_connect('servidor', usuario', 'senha');mysql_select_db('meu_banco');

settype($_GET['userid'], integer);

$sql = 'SELECT email FROM usuarios WHERE idusuario = ' . 

          $_GET['userid'];

$recordSet = mysql_query($sql);?>

Page 22: Implementando Segurança Em Sua Aplicação PHP

   

Não basta forçar a tipagem: o perigo do que não é óbvio

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

    Um dos maiores problemas para se desenvolver uma aplicação segura é quando existe um risco que não é óbvio. Partindo do que vimos, torna­se óbvio o perigo de se aceitar dados não tratados. O que não fica claro é que qualquer número será válido, independente de quem esteja visualizando a informação.

<?phpsettype($_GET['userid'], integer);

if ($_SESSION['uid'] == $_GET['userid']) {// Código

}?>

    Através de uma verificação relativamente simples garantimos que mesmo que o dado informado seja aparentemente inocente a informação esteja protegida de quem não deve ter acesso à ela.

Page 23: Implementando Segurança Em Sua Aplicação PHP

   

SQL Injection com strings: o que era dor de cabeça virou enxaqueca

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

    Quando trabalhamos com strings, as coisas se complicam, pelo simples fato de que textos possuem personalidade, sentidos múltiplos, questões realmente difíceis de se interpretar logicamente. A chave aqui é tomarmos cuidado apenas com caracteres específicos que podem, por falta de um tratamento adequado, ser interpretados pela base de dados como caracteres SQL válidos:

' aspas simples – INSERT INTO foo ('bar's');­ hífen – INSERT INTO foo ('bar' ­­');; ponto­e­vírgula – INSERT INTO FOO ('bar', 1, false);­­');

    Uma coisa que nem sempre é óbvia é que nem sempre um ataque de SQL Injection destina­se à manipular dados na base, mas às vezes o objetivo é simplesmente fazer sua aplicação falhar, para tentar, dessa forma ler uma mensagem de erro na tela. É por isso que:

Page 24: Implementando Segurança Em Sua Aplicação PHP

   

Funções para auxiliar na prevenção de injeção de SQL:

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

    Uma função muito utilizada para evitar ataques é a função addslashes.Embora esta função solucione a técnica mais comum de injeção que é ainserção de aspas simples, ela não ocasiona o escape dos demais caracteresvistos.

    Para solucionar este problema, utilizamos a função addcslashes, quenos dá uma maior liberdade, permitindo que informemos cada caractereque deve ser escapado:

$dado_tratado = addcslashes($_GET['userid'], “';­”);

    

Page 25: Implementando Segurança Em Sua Aplicação PHP

   

Não re­invente a roda

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

    Utilize­se também de funções, bibliotecas e classes que já trabalhamcom a filtragem de informação. Desta forma você contribui para ofortalecimento da comunidade, agiliza seu trabalho e conta com códigosque possuem qualidade, manutenção e suporte.

    

● mysql_real_escape_string, pg_escape_string, etc...

● Pear::MDB2

● ADODB

● PDO

● etc...

Page 26: Implementando Segurança Em Sua Aplicação PHP

   

Boas práticas: Longe dos olhos... dos usuários

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

Mensagens de erro são cruciais. É através dela que o trabalho dedesenvolvimento se torna mais ágil, e são elas que nos apontam nossos pequenos deslizes.

O problema é que, quando mantemos as mensagens de erro visíveis para qualquer usuário, corremos o risco de passar informações importantes sobre o sistema e até mesmo sobre oservidor para qualquer usuário ler.

Mensagens de erro frequentemente carregam informaçõescomprometedoras!

Page 27: Implementando Segurança Em Sua Aplicação PHP

   

Prova de caso #5: Informação demais!

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

    Considere um erro de conexão mySQL típico:

Warning: mysql_connect() [function.mysql­connect]: Access denied for user 'foo'@'localhost' (using password: YES) in /usr/local/apache/htdocs/script.php on line 2

1) O tipo de banco utilizado: mysql2) O usuário de conexão: foo3) Que este usuário está tentando se conectar de dentro do próprio     servidor: @localhost4) O path absoluto em disco do script: /usr/local/apache/htdocs5) O nome do script: script.php

    Esta inocente mensagem revela 5 informações que só são úteis ao próprio desenvolvedor ou à um cracker:

Page 28: Implementando Segurança Em Sua Aplicação PHP

   

Solução: Se está em produção, grave um log!

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

    Três diretivas de configuração serão responsáveis por esconder os errose gravá­los em um arquivo de log:

    A primeira desativa a exibição dos erros.    A segunda ativa a gravação de erros em arquivo.    A terceira diz que arquivo será esse que receberá as mensagens.

1) display_errors: off ou 02) log_errors: on ou 13) error_log: /caminho/para/arquivo.log

Page 29: Implementando Segurança Em Sua Aplicação PHP

   

Boas práticas: Longe do browser

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

    O servidor web, e consequentemente o browser, não precisa acessar todos os arquivos que você possui na sua aplicação, especialmente se este arquivo não gera saída HTML ou se serve apenas de arquivo de configuração.

Se o Browser enxerga, qualquer um enxerga!A raiz web é um local público e portanto inerentemente vulnerável!

Page 30: Implementando Segurança Em Sua Aplicação PHP

   

Prova de caso #6: Entregando o ouro!

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

    Considere o seguinte arquivo de configuração típico, que chamaremospelo enigmático nome de config.php:

<?php$dbserver = 'localhost';$dbtype= 'mysql';$dbuser = 'foo';$dbpass = 'bar';?>

    Se este arquivo estiver gravado em um diretório acessível ao servidorweb, ele estará acessível à um script PHP que lerá se ele gera saída de informações, por exemplo:

<?phpfile_get_contents('http://www.galvao.eti.br/config.php');?>

Page 31: Implementando Segurança Em Sua Aplicação PHP

   

Solução: Esconda o que não precisa ser visto!

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

    Contanto que as permissões (chmod/chown) sejam setadas corretamente, o arquivo PHP pode tranquilamente ser colocado em um diretório longe da raiz utilizada pelo servidor web.

O que não está na raiz web não pode ser acessado pelo servidor web e nem pelo browser.

Page 32: Implementando Segurança Em Sua Aplicação PHP

   

Boas práticas: 97c6105c1d97d600ec16ab4abace6d4c

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

    Dados sigilosos são chamados assim por um motivo. Quando tratamosespecificamente de senhas é impressionante a quantidade de aplicações web que grava senhas em texto puro na base de dados.

Senhas são pessoais, intransferíveis e confidenciais! Ninguém além do próprio usuário deve ter acesso à senha!

    PHP implementa criptografia das mais variadas formas, pesquise,aprenda e use!

• MD5• SHA1• mcrypt• hashetc...

Page 33: Implementando Segurança Em Sua Aplicação PHP

   

Sobre o autor:

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

Er Galvão Abbott trabalha há mais de dez anos com programação de websites e sistemas corporativos com interface web. 

    Autodidata, teve seu primeiro contato com a linguagem HTML em 1995, quando a internet estreava no Brasil. 

    Além de lecionar em cursos, escrever artigos e ministrar palestras, tem se dedicado ao desenvolvimento de aplicações web, tendo nas linguagens PHP, Perl e JavaScript suas principais paixões.

É o fundador e líder do UG PHP RS, Grupo de Usuários que contahoje com mais de 600 associados em todo o Brasil.

Page 34: Implementando Segurança Em Sua Aplicação PHP

   

Contatos:

© 2007 Er Galvão Abbott ­ http://www.galvao.eti.br/

    Contatos com o autor:

    Web:    http://www.galvao.eti.br    http://blog.galvao.eti.br/    http://www.phprs.com.br

    E­mail:    [email protected]

    IM:    [email protected] (MSN)    [email protected]   (GoogleTalk)