Introdução
Neste artigo vamos abordar testes em entradas de dados em uma aplicação web. Durante o artigo teremos uma explanação de como algumas ferramentas funcionam para testar sua aplicação web.
Quando falamos de testes em entradas de aplicações Web, muitos pensam em TDD (Test Driven Development), logo alguns iram citar até o Selenium. Embora o Selenium tenha poder para nos ajudar, o uso do browser seria na maioria dos casos inútil. Lembre-se que nosso foco é testar entradas para verificar existência de padrões nas respostas, julgando a segurança da aplicação e não a funcionalidade de uma aplicação.
Ferramentas
Embora seja interessante reinventar a roda por motivos de aprendizado ou otimização, temos em nosso alcance um grande número de ferramentas que podem ajudar nos testes.
Uma das ferramentas disponíveis é o Burp Suite, com ele poderíamos usar o intruder, para alterar os valores dos parâmetros de uma request HTTP e analisar a resposta buscando por padrões que são característicos de uma aplicação vulnerável.
Além do Burp, temos scanner de vulnerabilidades como o Skipfish e Arachni que fazem a tarefa de mapeamento do alvo bem como um “sitemap“, ou seja, é feita a abstração de todas as URLs do alvo de forma recursiva, e analisado os dados para identificar uso de entradas e, de forma automática, é feito um teste nas entradas encontradas.
Reinventando a roda, mas por um bom motivo
Pensando no aprendizado apresento a vocês o 0d1n, uma ferramenta para testar entradas em aplicações web. Essa aplicação possui código fonte simples por ter poucas funções, e usa libCurl pela praticidade para executar uma request e obter a resposta.
Supondo que você use algum derivado de unix siga os seguintes passos:
$ wget http://0d1n.googlecode.com/files/0d1n_stable_v9.zip
$ unzip -e 0d1n_stable_v9.zip; cd 0d1nstable
$ make
lembrando que você precisa da “libCurl“, caso esteja em um linux derivado de debian, por exemplo, basta o seguinte comando para instalar:
$ apt-get install libcurl-dev
Estamos preparados para usar o programa conforme a Figura 1.
$ ./0d1n
Figura 1
Como usar a ferramenta
O caractere “!” é um indicador de onde você deseja injetar os valores que estão na sua lista de payloads.
Exemplo:
site.com/site.jsp?login=admin&pass=!
Neste caso o programa irá trocar todos os “!” por strings que estão presentes em uma determinada lista(chamamos de lista de payloads), enviaria um “request” e procuraria determinadas strings que estão em “response2find”. Se contiver qualquer string do “response2find” será salvo em um log o “response”.
Outro exemplo:
http://site.com/index.jsp?var=1&feijoada=3
http://site.com/index.jsp?var=!&feijoada=!
Logo se a primeira linha da lista de payloads for ” or 1=1” nosso programa irá executar:
site.com/index.jsp?var= or 1=1&conviso=3
Para testar parâmetros POST usamos o argumento -P e o argumento -h seria o local onde receberia o POST.
Exemplo:
-h ‘http://site.com/index.jsp ‘ –P ‘var=!&var2=!&var3=teste’
Prova de Conceito
Para testar a ferramenta vamos usar o DVWA. Com o DVWA rodando vamos alterar o Security Level para Low no menu Security Level.
Antes, precisamos do Cookie da sessão do DVWA, pois para explorar o XSS preciamos estar autenticado na aplicação. Portanto logue no sistema e salve o “cookie jar”. Para isso podemos usar o plugin Export Cookie do firefox.
Tendo o Cookie da sessão em mãos definimos um alvo. Agora vamos explorar um reflected XSSna url http://localhost/dvwa/vulnerabilities/xss_r executando o seguinte comando:
$ ./0d1n -h ‘http://localhost/dvwa/vulnerabilities/xss_r/?name=!‘ -p payloads/list.txt -f response2find/find.txt -c cookies_dvwa.txt -o dvwa
Para analisar o resultado abrimos o arquivo “tables/hammer“.
Nas linhas da tabela da Figura 2 podemos ver o padrão que buscamos no conteúdo da página e clicando nela podemos identificar uma requisição onde o payload XSS foi executado e demonstra que a aplicação é vulnerável a XSS conforme a Figura 3.
Figura 2
Figura 3
Um pouco sobre o código fonte
Com uso simples de “sockets” podemos nos comunicar usando protocolo HTTP, automatizando o envio de entradas e analise das respostas.
Vamos analisar o código fonte do programa em “spider.c” (linha 46) onde é feito a construção da request com libCurlusando macros para setopt.
// injeta payload
make=payload_injector( (POST?arg[4]:arg[0]),line,old);
curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, POST?arg[0]:make);
// caso seja post
if(POST)
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, make);
// escreve o “response” na memória
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
// caso seja definido useragent
if(arg[6]!=NULL)
{
curl_easy_setopt(curl, CURLOPT_USERAGENT, arg[6]);
} else {
curl_easy_setopt(curl, CURLOPT_USERAGENT, “Mozilla/5.0 (0d1n v0.1) “);
}
// para comprimir os dados e ganhar desempenho
curl_easy_setopt(curl, CURLOPT_ENCODING,”gzip,deflate”);
// caso queira usar cookiejar
if(arg[3]!=NULL)
{
curl_easy_setopt(curl,CURLOPT_COOKIEFILE,arg[3]);
curl_easy_setopt(curl,CURLOPT_COOKIEJAR,arg[3]);
} else {
curl_easy_setopt(curl,CURLOPT_COOKIEJAR,”odin_cookiejar.txt”);
}
curl_easy_setopt(curl,CURLOPT_FOLLOWLOCATION,1);
//caso queira carregar um certificado
if(arg[7]!=NULL)
{
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2);
curl_easy_setopt(curl, CURLOPT_CAINFO, arg[7]);
} else {
curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,0);
Na linha 104, temos uma busca pela string de “response2find/*” dentro do response, repare que não usamos a função strstr(), e sim bitap, que procura uma substring aproximada a de um determinado padrão.
if(chunk.memory && bitap_search(chunk.memory,line2))
Conclusão
Concluímos então que com a simplicidade dessa ferramenta, podemos facilmente entender o funcionamento de um teste de entradas de uma aplicação de web, ver as etapas do teste de forma transparente.
Originalmente postado no Blog da Conviso Application Security – Siga-nos no Twitter @conviso Google+