Page 1

Sua aplicação web é segura?

SEGURANÇA

Aplicação web protegida Aplicações web oferecem grandes riscos à segurança. Aprenda a proteger todos os elementos dessa complexa equação. por Celio de Jesus Santos e Cloves Ferreira Junior

A

construção de sites dinâmicos se tornou muito comum com o decorrer dos tempos, trazendo inúmeras vantagens para as empresas e sendo utilizada como uma poderosa ferramenta de marketing. Porém, isso pode se converter em um problema caso o site ou a aplicação não seja desenvolvido com as devidas preocupações relacionadas à segurança da informação. Ao se tratar de algo voltado para a Internet, esse site estará exposto para quem quiser acessá-lo, ou seja, se torna público e sua segurança é colocada à prova por qualquer pessoa que queira testar o nível de proteção, independentemente de sua índole. Todas as linguagens de programação têm suas particularidades, mas no decorrer deste artigo trabalharemos com a linguagem PHP, pois é a base da maioria dos sites existentes atualmente.

Ataques de sessão

A definição para este tipo de problema está relacionada à má implementação das conexões realizadas pelos usuários a uma determinada aplicação que necessita rastrear as requisições destes ou tomar decisões com base nas credenciais de autenticação [1]. 66

Os danos causados por esse tipo de ataque vão desde a elevação de privilégios até o roubo de informações de usuários e o comprometimento dos dados da aplicação uma vez que o atacante consiga elevar os privilégios de um usuário vítima e obtenha acesso por meio de um usuário com privilégios administrativos. Como exemplo, poderíamos utilizar um cookie, um campo oculto etc., mas vamos partir de uma página que recebe pela URL as credenciais de um usuário já autenticado: http://site.com.br/pagina. php?usuario=bob&nivel=1

A listagem 1 ilustra como seria o código-fonte de pagina.php que foi codificado sem a preocupação com a alteração indesejável dos dados por um usuário que detém algum conhecimento sobre aplicações web. Note que este código recebe os dados vindos do usuário e implementa uma consulta em uma base de dados para uma possível decisão futura de acordo com o retorno da consulta. Isso significa que se aplicarmos os truques que caracterizam esse tipo de ataque – isto é, alterar as credenciais de um usuário válido

por meio da URL –, conseguiríamos sucesso: http://site.com.br/pagina. php?usuario=alice&nivel=1

Com isso, o usuário da aplicação conseguiria visualizar uma página montada dinamicamente, mas que pertence a outro usuário da aplicação (no caso, alice). A partir desse ponto, ele poderia fazer tudo o que a aplicação permite ao usuário alice. Para evitar esse tipo de problema, o ideal é não armazenar essas credenciais de usuário no lado do cliente, mas em um objeto session no lado servidor. Para implementar essa solução nesse ambiente de exemplo, bastaria armazenarmos um hash das credenciais do usuário em um objeto session no lado servidor no momento da autenticação e em todas as páginas que necessitassem dessas credenciais. Antes de executar qualquer ação com as credenciais fornecidas ao programa atual, o servidor faria uma comparação entre o hash informado e aquele armazenado no lado servidor. Vejamos na listagem 2 como podemos implementar esta solução. Trata-se de um trecho do código do

http://www.linuxmagazine.com.br


Aplicações web | SEGURANÇA

programa autentica.php, que cria o hash das credenciais com a função md5() do PHP no momento da autenticação e a armazena em uma variável de sessão (objeto SESSION). Na linha 1 da listagem 2, iniciamos o objeto de sessão. Na sequência, verificamos se houve sucesso na autenticação do usuário e, em caso positivo, o hash é armazenado em uma variável da sessão. Agora vamos verificar como ficaria a codificação da validação das credenciais informadas ao programa pagina.php na listagem 3. Esse código implementa uma validação com os dados recebidos por meio da comparação dos hashes. Com o sucesso da validação, é executado o restante do script; caso contrário, pode-se informar o erro ao usuário ou redirecioná-lo para uma nova tentativa de autenticação. É importante implementar outras alternativas, como a proteção dos parâmetros passados via URL, a criptografia das informações de tokens etc.

Cross-site scripting (XSS) Ataques do tipo XSS, ou Cross-site scripting (scripts entre sites), acontecem quando a aplicação recebe dados do usuário e os envia de volta ao cliente sem as devidas validações para sua correta exibição no navegador. A técnica do XSS se caracteriza pela inserção de tags HTML, em particular a tag <script> [1]. Quando a aplicação executa a tag no navegador cliente em vez de apenas imprimir este conteúdo, os dados da sessão – incluindo informações potencialmente sensíveis do usuário – podem ser enviados para qualquer destino sem que o servidor ou o cliente percebam. Esta vulnerabilidade em uma aplicação pode causar sérios danos para seu usuário, uma vez que o foco não é acessar ou manipular

Linux Magazine #60 | Novembro de 2009

dados da aplicação como no caso da injeção de SQL, mas explorar vulnerabilidades do próprio navegador do usuário com a execução de scripts maliciosos em JavaScript, VBScript, ActiveX etc. Outro problema potencial é o sequestro de sessão, dependendo de como forem armazenadas as credenciais de um usuário autenticado. O teste mais simples para esta vulnerabilidade é a inserção da string a seguir em uma página parametrizada por meio de uma variável, que no nosso exemplo é a variável id: http://site.com.br/pagina. php?id=<script>alert(‘XSS’); </script>

O código vulnerável que poderia receber uma string como esta é: <?php //pagina.php print $_REQUEST[“id”]; ?>

Qualquer página com um código semelhante a este está vulnerável, pois os dados são obtidos e impressos na tela sem qualquer verificação, ou seja, acreditamos ingenuamente que o usuário sempre passará dados confiáveis. Vamos imaginar um mural de recados que armazene os dados em uma tabela de banco de dados ou até mesmo em um arquivo texto. Suponhamos que o código desse mural aceite a seguinte string a seguir no lugar do texto que seria o recado: <script>for(i=0%3bi<10%3bi%2b%2b) {alert(i)%3b}</script>

O problema causado por essa string seria simples, mas emitiria dez mensagens de alerta toda vez que a página fosse carregada, como mostra a figura 1. Contudo a gravidade do problema estaria ligada à criatividade da pessoa que a fizer. Para corrigir esse problema, seria preciso alterar o arquivo pagina.php

Listagem 1: Página insegura 01 02 03 04 05 06 07 08 09 10 11 12

<?php /*Dados do formulário*/ $usuario = $_REQUEST[“usuario”]; $nivel = (int)$_REQUEST[“nivel”]; /*montando a Query*/ $sql =”SELECT *        FROM tabela       WHERE usuario = ‘”.$usuario.”’ AND       nivel = “.$nivel; $rs = mysql_query($sql);

Listagem 2: Segurança na autenticação 01 <?php 02 /*autentica.php*/ 03 session_start(); ... 16 /*Sucesso na autenticação*/ 17 if ($autenticado){ 18 $_SESSION[“hash”]=md5($usuario.””.$nivel); 19 } 20 21 ?>

67


SEGURANÇA  | Aplicações web

:<?php //pagina.php print htmlentities($_ REQUEST[“id”], ENT_QUOTES); ?>

e também o mural.php, responsável por exibir o mural de recados: <?php //mural.php . . . print htmlentities($dados[“recado”], ENT_QUOTES); ?>

Esta solução foi utilizada com a função do PHP que faz uma conversão dos dados para entidades HTML, htmlentities(), mas também podemos utilizar outra função chamada strip_tags(), ou até mesmo expressões regulares.

No caso do XSS, a aplicação deve garantir que somente o seu próprio código seja executado, impedindo que os usuários insiram códigos arbitrários. Isso evita que a aplicação tenha seu comportamento alterado, o que pode prejudicar o acesso do usuário à aplicação.

Falhas de autenticação

A autenticação de usuários é uma das primeiras partes de uma aplicação web a ser testada por alguém que deseja verificar seu nível de segurança. Portanto, é fundamental usar códigos seguros – preocupe-se até com os mínimos detalhes envolvidos no ato do desenvolvimento. Este problema envolve falhas no mecanismo de autenticação da aplicação, que por um motivo ou outro não foi bem codificado ou não recebeu a devida atenção com relação à gerência da pós-autenticação, talvez até mesmo por imaturidade do desenvolvedor. Os danos causados por esse tipo de pro-

Listagem 3: Validação das credenciais 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

68

<?php /*Iniciando a sessão*/ session_start(); /*Dados do formulário*/ $usuario = $_REQUEST[“usuario”]; $nivel= (int)$_REQUEST[“nivel”]; /*Obetendo os hashes atuais*/ $hash = md5($usuario.””.$nivel); /*verifica se os hashes são iguais*/ if(strcmp($_SESSION[“hash”], $hash) == 0){     /*montando a Query*/     $sql = “SELECT *          FROM tabela         WHERE usuario = ‘”.$usuario.”’          AND nivel = “.$nivel;     $rs = mysql_query($sql); } else {     /*requer autenticação novamente*/     header(“Locarion: login.php”); } ?>

blema incluem o roubo de contas de usuários, o que caracteriza a violação de privacidade. O primeiro cuidado que o desenvolvedor deve tomar para evitar ataques de falha de autenticação é garantir que a tela de login seja acessada por meio de uma comunicação segura para que as credenciais informadas pelo usuário não sejam facilmente capturadas durante o transporte até o servidor web. A proteção mais prática, nesse caso, é utilizar o protocolo HTTPS para servir a página de autenticação. Outro cuidado importante é o uso de uma boa lógica para a programação do sistema de autenticação, realizando as validações necessárias para que somente sejam aceitos dados relevantes para a aplicação, como exemplifica a listagem 4. Além disso, toda aplicação fornece um link para permitir ao usuário encerrar sua sessão autenticada. Porém, também é obrigatório garantir que, se ele clicar somente no botão para fechar a janela do navegador, em vez de usar o link de encerramento da sessão, a sessão seja completamente destruída [2]. Caso isso não ocorra, é possível que o próximo usuário que utilizar a aplicação no mesmo computador encontre a sessão já autenticada. Por isso, a aplicação deve expirar a sessão após um prazo determinado sem utilização para garantir que a sessão do usuário não fique exposta. O código abaixo (arquivo logoff. php) realiza todas essas operações de uma só vez: <?php //logof.php unset($_SESSION); ?>

Um ponto importante que também está relacionado à autenticação é o bloqueio da conta do usuário em casos de múltiplas falhas de autenticação num intervalo pré-deter-

http://www.linuxmagazine.com.br


Aplicações web | SEGURANÇA

minado. Isso evita ataques de força bruta, frequentemente ignorados pelos desenvolvedores web, porém extremamente perigosos. Com relação à comunicação da aplicação web com o usuário, é fundamental que este seja notificado sobre qualquer incidente que ocorra com relação à sua conta de usuário. Os cuidados citados não dependem da linguagem utilizada do lado servidor, mas do uso de alguns truques para evitar esses problemas que estão diretamente ligados à boa gerência da sessão autenticada.

Servidor assegurado

Por se tratar da parte que fica exposta à Internet, o servidor web também precisa estar protegido; suas configurações devem fornecer apenas o necessário para que a aplicação funcione. Esse trabalho não cabe ao desenvolvedor, mas é necessário algum conhecimento sobre o assunto, pois a segurança da aplicação pode ser comprometida caso seja explorada alguma falha de segurança por parte do servidor web e vice-versa. Isso significa que a segurança não deve estar localizada somente no servidor web ou somente na aplicação, mas em ambos.

Figura 1 Um “ataque” de exemplo seria a inclusão de código para exibir dez avisos no navegador do cliente.

Os principais cuidados que devem ser tomados no ato da configuração de um servidor web são descritos a seguir.

Menor privilégio

O princípio do menor privilégio dita que o serviço HTTP deve ser executado com uma conta do sistema operacional que não tenha privilégios de administrador, mas apenas os privilégios necessários para a execução deste serviço. Para isso, o correto é criarmos um grupo de usuários com o nome do serviço e um usuário com o mesmo nome – e evidentemente pertencente a esse grupo – no sistema operacional com os privilégios mínimos. No caso do Apache, todas as distribuições responsáveis já criam um usuário apache e um grupo apache, responsáveis por executar o servidor web. O usuário apache não precisa sequer acessar um shell, então é seguro

definir seu shell padrão como /bin/ false, por exemplo. O usuário e o grupo, depois de criados, devem ser informados no arquivo de configuração do apache, httpd.conf: User apache Group apache

Com esse procedimento, garantimos que o serviço HTTP seja executado com o menor privilégio possível [1].

Serviços necessários

Também é muito importante executar no servidor somente os serviços necessários ao bom funcionamento da aplicação web. Com isso, eliminam-se várias fontes potenciais de insegurança,

Log robusto

O log do serviço HTTP deve ser o mais detalhado possível, pois é por meio dele que conseguiremos idenCAVA

VIA GR S CAVALO DE TR ÓIA PHIS HING VÍR US CAVALO DE TRÓVÍR VIAGRA IA

LO D E

TRÓ

SPAMs?

IA

FRAUDE

Saiba como importantes empresas estão solucionando este problema

(11) 3522-3011 www.unodata.com.br

Linux Magazine #60 | Novembro de 2009

Baseado em software livre Filtro de Entrada e Saída Eficiente sem descartar mensagens importantes Flexível e customizável Clientes 100% satisfeitos

Acesse www.unodata.com.br e veja nossos casos de sucesso.

PHIS

HING

ES FRAUD

30 D GRÁ IAS TIS! 69


SEGURANÇA  | Aplicações web

Listagem 4: Lógica de validação robusta 01 <?php 02 //autentica.php 03 session_start(); 04 include (“includes/conexao.php”); 05 //Recebendo as credenciais e escapando aspas e removendo 06 //qualquer tag de script e tentativas de injeção de sql 07 $login = addslashes(strip_tags(filtroSql($_POST[“login”]))); 08 $senha = $_POST[“senha”]; 09 //Verificando se existe caracteres inválidos para o login 10 if (!ctype_alnum($login)){ 11 die(“Caracteres Inválidos!”); 12 } 13 //Query com um hash da senha e comparada com o hash armazenado. 14 $sql = “SELECT id, 15 login 16 FROM usuarios 17 WHERE login = ‘”.$login.”’ AND 18 senha = ‘”.md5($senha).”’ “; 19 //Executando a query e suprimindo qualquer possível erro 20 $rs = @mysql_query($sql); 21 //Sucesso na execução da query 22 if($rs){ 23 //Evitando que uma possível alteração de query 24 //traga mais registros que o esperado. 25 if(mysql_num_rows($rs) == 1){ 26 $dados = mysql_fetch_array($rs); 27 $_SESSION[“autenticado”] = true; 28 $_SESSION[“login”] = $dados[“login”] ; 29 //Aqui pode redirecionar para a página que se deve 30 //acessar com autenticação 31 header(“Location: home.php”); 32 } 33 else{ 34 die(“Login e/ou senha inválidos!”); 35 } 36 } 37 else{ 38 die(“Falha na execução da query!”); 39 } 40 //Filtro para remoção de caracteres que possivelmente 41 //são usados para tentativas de sql injection 42 function filtroSql($tempString){ 43 $badChars = array(“select”, “drop”, “table”, “;”, “--”, “insert”, “delete”, “update”, “xp_”, “#”, “%”, “&”, “’”, “(“, “)”, “/”, “:”, “;”, “<”, “>”, “=”, “[“, “]”, “?”, “`”, “|”); 44 foreach ($badChars as $char) { 46 $tempString = str_replace($char, “”, $tempString); 47 } 48 return $tempString; 49 } 50 51 ?>

tificar se a aplicação está sofrendo tentativas de ataque ou se houve algum ataque bem sucedido [1]. Além da grande importância dos logs HTTP, as mensagens de log dos demais servidores da sua rede devem ser centralizadas em uma única máquina, um servidor de log. Isso 70

facilita o gerenciamento, a análise e a solução de problemas ocorridos em toda a rede de uma forma geral. Mais importante ainda é que qualquer invasão ao servidor será incapaz de apagar seus próprios rastros, pois estes serão enviados imediatamente para o servidor de log [3].

Cuidado com o PHP

Em relação ao servidor de aplicação – PHP + Apache, nos exemplos deste artigo –, também há alguns cuidados que devemos tomar ao configurar o PHP. Em primeiro lugar, por questões de segurança e desempenho, o ideal

http://www.linuxmagazine.com.br


Aplicações web | SEGURANÇA

é que o PHP seja executado como um módulo do servidor web, e não no modo CGI [4]. Além disso, deve-se desativar as variáveis superglobais: register_globals = Off

Executar o PHP no modo seguro (safe_mode) também é uma medida importante de segurança: safe_mode = Off

Deve-se ainda limitar o acesso do PHP aos arquivos com a opção open_basedir: open_basedir = /home/www/

Recomenda-se definir nessa diretiva o mesmo diretório usado como document root pelo servidor web (/ home/www/, no nosso exemplo). Assim, a aplicação só terá acesso à leitura dos arquivos que estiverem dentro do diretório raiz do servidor web; isso impede, por exemplo, que a aplicação leia o arquivo /etc/passwd do servidor.

Sem erro

Evitar que o servidor imprima mensagens de erro para os usuários também é uma medida importante, pois, uma vez que o PHP imprima mensagens de erros para um usuário, ele fornece informações importantes para um agressor dar os primeiros passos na preparação do ataque. Uma maneira de perceber esse problema antes que o pior aconteça é usar a função error_reporting() para ajudar a aumentar a segurança do código PHP e encontrar o uso de variáveis potencialmente perigosas. Ao testar seu código, antes de colocá-lo em produção, com E_ALL é possível encontrar rapidamente áreas onde as variáveis podem sofrer alterações nocivas ou outras modificações. Uma vez

Linux Magazine #60 | Novembro de 2009

que o código esteja pronto para produção, deve-se ou desabilitar mensagens de erro completamente passando-se o valor 0 para a função error_reporting(). Outra possibilidade é desligar o envio de erros com a opção display_errors no arquivo php.ini, evitando assim a sondagem do código. Nesse caso, também se recomenda definir o caminho para o arquivo de registro usando a diretiva error_log e ligar a diretiva log_errors [5].

Considerações finais

Com relação à programação de aplicações web, a solução para cada problema demonstrado neste artigo recai sobre algum tipo de tratamento dos dados recebidos pela aplicação. É necessário sem-

pre fazer uma forte validação dos dados fornecidos. Outro ponto importante é que não devemos atribuir certos problemas a uma determinada linguagem de programação caso não tenham sido levadas em consideração as boas práticas de codificação para o desenvolvimento de uma aplicação. Portanto, podemos concluir que a preocupação com a segurança da informação deve existir desde a fase de planejamento do sistema, assim como em projeto de software. Em conclusão, é importante ressaltar que o uso destas técnicas para reforçar a segurança da aplicação web e seu respectivo servidor não substitui os outros mecanismos tradicionais de proteção de redes, como firewall, IDS e IPS.  n

Mais informações [1] Mike Shema, “Hack Notes – Segurança na Web”. Editora Campus, 2003. [2] Comunidade OWASP-BR: http://www.owasp.org/images/4/42/OWASP_TOP_10_2007_PT-BR.pdf [3] Guia Foca Linux: http://focalinux.cipsga. org.br/guia/avancado/ch-log.html [4] Carlos Sica, Peter Villa Real, “Programação Segura Utilizando PHP”. Editora Ciência Moderna, 2007. [5] PHP: http://www.php.net [6] Comunidade OWASP: http://www.owasp.org/index.php/Main_Pag

Sobre o autor Célio de Jesus Santos é graduado em Sistemas da Informação e especialista em Segurança da Informação. É professor na Universidade Estadual de Goiás e coordenador de desenvolvimento em uma empresa privada. Cloves Ferreira Junior é mestre em Ciências da Computação pela Universidade Federal de Pernambuco. É professor titular da Universidade Salgado de Oliveira e professor titular do Centro Federal de Educação Tecnológica de Goiás.

Gostou do artigo? Queremos ouvir sua opinião. Fale conosco em cartas@linuxmagazine.com.br Este artigo no nosso site: http://lnm.com.br/article/3115

71

http://www.linuxmagazine.com.br/images/uploads/pdf_aberto/LM_60_66_71_06_seg_webapps  

Revista Linux Magazine - Artigo sobre Segurança

Read more
Read more
Similar to
Popular now
Just for you