Segurança de AplicaçãoUncategorized

Construindo um fuzzer com Ruckus e DFuzz

Introdução

A comunidade de segurança da informação já está bastante acostumada com a palavra fuzzing. Para aqueles que ainda não conhecem, fuzzing é uma técnica de teste tendo como objetivo a descoberta de vulnerabilidades. Existem diversas ferramentas (fuzzers) disponíveis que implementam esta técnica. Neste post é apresentado alternativas Ruby-like para a realização de fuzzing, são elas: Ruckus[1] e DFuzz[2]. Primeiramente é apresentado o Ruckus, os principais tipos de dados que o mesmo é capaz de representar e como é possível através dele modelar um formato de dados. Em seguida é mostrado como o DFuzz pode ser utilizado para a realização de fuzzing. Por fim, é feita a combinação do Ruckus com o DFuzz para demonstrar que a dupla pode ser usada na construção de um smart fuzzer.

Ruckus

Ruckus é um smart fuzzer escrito em Ruby. Considera-se smart fuzzer as ferramentas que fazem fuzzing levando em consideração o tipo dos dados que estão sendo testados [3]. Com o Ruckus pode-se fazer a modelagem de formatos de dados (formato de arquivo ou protocolo) utilizando a própria linguagem Ruby para isto. Para começar a modelar uma estrutura basta criar uma nova classe herdando de Ruckus::Structure, conforme visto na Figura 1.

Figura 1: Modelagem de estrutura no Ruckus.

Tipos

Uma vez feito isto, é hora de representar os campos que o formato a ser testado contém. No Ruckus os principais tipos de dados disponíveis são: Number e Str.

Number, como o nome já diz, é usado para representar diversos tipos de inteiros. Para campos deste tipo é possível definir algumas características, conforme visto na tabela 1.

Tabela 1: Propriedades do Ruckus::Number

 


:width
Quantidade de bits do campo.
:endian
Representação em :big ou :little endian.
:ascii
Representação textual do campo (:true ou :false).
:radix
Definir base do número caso o campo seja textual.


Do tipo Number originaram-se outros tipos, são eles: byte, be16, be32, le16, le32, le64, be64, decimal, entre outros. Na Figura 2 pode-se ver um exemplo de definição de campos inteiros (be32 e be16).

 

Figura 2: Exemplo de campos inteiros.

Para um campo do tipo Str, também é possível definir características. Estas características podem ser vistas na tabela 2.

Tabela 2: Propriedades do Ruckus::Str

:size
Tamanho (absoluto) do campo (forçará padding se preciso).
:min
Tamanho mínimo do campo.
:max
Tamanho máximo do campo.
:padding
Caractere usado em caso de padding (padrão: ”)
:pad_to
Alinhamento do padding.
:unicode
Define se o campo deve ser unicode.
:nul_terminated
Define se o campo deve ser terminado com nulo.

Na Figura 3 pode-se observar um exemplo de uso do Str, neste exemplo é definido um campo chamado filename e setado seu valor padrão para “default.txt”.

  Figura 3: Definição do campo filename do tipo str.

Há outros campos interessantes que podem ser usados no Ruckus como: ipv4, bit e nibble. Com os tipos disponíveis é possível modelar diversos formatos de arquivos e protocolos.

Relação

O Ruckus é capaz de manter relações entre campos. Na definição do formato PseudoFileFormat existe o campo len que é um inteiro de 16 bits, big endian e o campo filename que contém uma string. Pode-se relacionar o campo len com o tamanho da string em filename. Toda vez que essa string for alterada este campo será automaticamente atualizado. Na Figura 4, pode-se ver a criação do relacionamento utilizando o método relate_value.

Figura 4: Relacionamento entre o campo len e o campo filename.

 

Resultado do PseudoFileFormat

Para visualização em hexdump o formato definido, foi utilizanda a gem Ruby BlackBag[4]. Pode-se observar na Figura 5 que o campo len é setado automaticamente para o tamanho da string filename. Na Figura 6 vemos que após a alteração de filename o campo len é atualizado para refletir a modificação.

format = PseudoFileFormat.new
puts format.to_s.hexdump

 

Figura 5: Visualização em hexadecimal do formato PseudoFileFormat. O campo len está destacado.

format.filename = “post.txt”
puts format.to_s.hexdump

 

Figura 6: Visualização em hexadecimal do formato PseudoFileFormat após modificação do campo filename. O campo len está destacado.

 

DFuzz

Embora exista a capacidade de fazer fuzzing utilizando somente o código do próprio Ruckus, para este post foi escolhido o DFuzz porque o mesmo possui uma interface mais amigável para condução dos testes. A boa notícia é que o DFuzz já vem embutido no Ruckus. Mas afinal, o que é o DFuzz? DFuzz é um código em Ruby escrito pelo pesquisador Dino Dai Zovi que provê uma série de inputs que podem ser utilizados para se testar sistemas. Os inputs são gerados de acordo com o tipo de dado a ser testado. Os principais tipos suportados pelo DFuzz são: Integer, Byte, Short, Long e String. Na Figura 7 é possível ver um exemplo de uso do DFuzz. Utilizando DFuzz::String é possível encontrar falhas como buffer overflows, format strings, path traversal, entre outros.

 

Figura 7: Exemplo de uso do DFuzz.

PseudoFuzzer

Para este post foi escrito um código a fim de exemplificar como o Ruckus e o DFuzz podem ser utilizados em conjunto para criação de uma ferramenta de fuzzing. Na Figura 8 segue o que seria um fuzzer para o PseudoFileFormat. Neste exemplo, o teste focou-se apenas no campo filename, mas o código poderia ser estendido para testar os outros campos. Nem o Ruckus, nem DFuzz possuem um mecanismo para monitorar as exceções que podem ocorrer durante os testes. Para isto foi feita uma abstração na linha 27.

Figura 8: Exemplo do que seria um fuzzer para o PseudoFileFormat

Conclusão

Utilizando o Ruckus é possível modelar um formato de dados e com o DFuzz pode-se obter inputs úteis para realização de fuzzing. Com a combinação destas duas ferramentas é possível a criação de smart fuzzers utilizando funcionalidades e facilidades que estão presentes na linguagem Ruby.

Referências

[1] https://github.com/tqbf/ruckus/
[2] https://github.com/tqbf/ruckus/blob/master/ruckus/dfuzz.rb
[3] http://peachfuzzer.com/SmartFuzzer
[4] https://github.com/emonti/rbkb
[5] http://www.matasano.com/research/ruby_for_pentesters/Ruby-For-Pentesters.pdf

Autor do Post

Ricardo Silva é estudante de Computação e atualmente trabalha como Analista de Segurança da Informação na Conviso. Como exploiter já contribuiu para o metasploit framework. Sua área de interesse inclui fuzzing, análise e exploração de vulnerabilidades, engenharia reversa, arquitetura de computadores e sistemas operacionais. Acredita que 0x41414141 é um número mágico!
Originalmente postado no Blog da Conviso Application Security – Siga-nos no Twitter @conviso Google+
About author

Articles

Uma equipe de profissionais, altamente conectados com as notícias, técnicas e informações sobre a segurança de aplicações.
Related posts
Segurança de Aplicação

Como Desenvolver Aplicações Com Segurança? Um guia inicial

Por que desenvolver com segurança? Seria muito bom se não precisássemos ter antivírus, que…
Read more
Code FightersMobileSegurança de Aplicação

Pré-testes Android: Conceitos básicos e uma introdução ao tema

Fazer um bom laboratório para testes de segurança em aplicações android pode ser uma tarefa…
Read more
NotíciasSegurança de Aplicação

Treinamento online e gratuito sobre Segurança de Aplicações: Conheça o AppSec Starter

A Conviso disponibilizou em seu canal de YouTube o treinamento AppSec Starter – um treinamento…
Read more

Deixe um comentário