Suas aplicações são seguras?

Conheça a Conviso!

Exploração automatizada com Nmap Scripting Engine (NSE)

Introdução

Este artigo visa demonstrar o quão poderosa e flexível é a Engine de script do Nmap. O exemplo utilizado neste artigo é inteiramente didático, apesar de explorar uma falha publicamente conhecida. Nem a Conviso® nem o autor se responsabilizam pelo mau uso do material aqui apresentado.

O principal objetivo desta engine é automatizar uma série de tarefas de rede, através do uso de uma linguagem de domínio especifico, que facilita a elaboração de scripts que realizam atividades relacionadas a teste de segurança em redes. 

A base do NSE ( Nmap Scripting Engine )[1] é um interpretador LUA embutido na ferramenta. LUA[2] é uma linguagem interpretada, multiparadigma, fortemente tipada e que tem como foco legibilidade, foi projetada para expandir aplicações em geral. LUA foi desenvolvida por um time de desenvolvedores da PUC-RIO, a principio apenas para um projeto específico e devido a sua eficiência passou a ser usada em diversos ramos da programação. O Adobe Photoshop Lightroom, o jogo Angry Birds, o nmap entre outros, já usam LUA como uma extensão dos seus aplicativos[3].

Tanto o manual do NSE[9] quanto o livro Nmap Exploration and Security auditing Cookbook[10] são ótimas referências para desenvolver os scripts. O próprio NMAP possui um script protótipo[12] que pode ser usado como exemplo para desenvolvimento dos scripts

ShellCode

Para demonstrar a flexibilidade do NSE sem criar um manual de how-to, foi utilizado o artigo[4] do pesquisador Maycon Vitali onde fez uma excelente análise da falha publicada no CVE-2012-5905[5]. No experimento descrito no artigo, Maycon  demonstra a execução de código remoto em uma falha que descrevia apenas a possibilidade de negação de serviço.

Na análise, Maycon executou um código remoto como demonstração e provou que muitas vezes as falhas em softwares publicadas não representam o real problema existente na aplicação. Neste artigo você verá este real problema, pois o código executado remoto é um bind shell.

 

Adaptação do exploit

O exploit original[6] foi escrito em python e explora o serviço KnFTPD[7] no WinXP SP3 – English, e em minha estrutura utilizei WinXP SP3 – pt-BR, para isso foi necessário adaptar o exploit. Foi necessário apenas alterar o endereço que contém a instrução JMP ESP do WinXP pt-BR.

 

O Ollydbg[8] foi utilizado para localizar o endereço de alguma instrução “JMP ESP” em alguma biblioteca que já estivesse carregada em memória. Achamos o código procurado e foi encontrado dentro da kernel32.dll no endereço 0x7C86467B”.

 

Ollydbg – JMP ESP

No exploit foi alterado o endereço utilizado no método struct.pack, que codifica o endereço de hexadecimal para binário, ordenado no padrão (little-endian), que armazena o dado do último byte para o primeiro.

 

Endereço JMP ESP alterado no exploit

Assim o exploit original, que abre a calc.exe passa a funcionar na minha estrutura.

 

O próximo passo foi sair da prova de conceito e provar o quão perigosa é este tipo de falha, ganhando a shell da máquina.

 

Foi utilizado o shellcode bindshell [9] que possui 214 bytes e coube nos 284 bytes que tínhamos disponível de acordo com a vulnerabilidade explorada. A Imagem abaixo mostra o shellcode mencionado.
 

Shellcode

Podemos notar de acordo com a imagem abaixo que a vulnerabilidade foi explorada abrindo a porta 28876.

 

Porta 28876 aberta no host alvo, exploit executado com sucesso

Ao estabelecermos conexão com o host na porta 28876, que foi aberta pelo exploit no host alvo, bingo!

 

Shell do host alvo

 

Automatizando com NSE

A ideia é mostrar o quanto a Engine de Script do Nmap é flexível e eficaz para os mesmos propósitos descritos na sessão anterior, para isso foi criado um script NSE, que ao encontrar um KnFTPD em execução ele executa os seguintes passos: (I) monta e envia o payload, (II) executa o Egg-hunter[19], (III) checa se o exploit foi executado com sucesso e se a máquina foi realmente explorada, mostrando o IP e Porta que foi aberta caso a máquina tenha sido explorada. A porta fica em listen enquanto o serviço estiver aberto apenas aguardando a conexão, ao se conectar bingo! está com a shell da máquina exatamente como foi mostrado com o exploit em pyhton, só que automatizado pelo Nmap.

Script NSE

Segue abaixo o cabeçalho do script, que contém a descrição e a referência, logo depois as tags @usagee @output que descreve como devemos utilizar este script e o exemplo da saída do script. Também o autor a licença e a categoria, conforme pede a documentação do NSE. É importante definir corretamente em qual categoria seu script se enquadra, pois faz parte da usabilidade do nmap, ao executar um scan com script é possível escolher rodar todos os scripts de uma determinada categoria. As categorias e suas descrições encontram-se na referência [13].

 
Inicio do script knftpd-exploit.nse

LUA, como a maioria das linguagens, permite a criação de bibliotecas com um grupo de funções comuns. Para este script foi utilizado as bibliotecas abaixo. As bibliotecas existentes podem ser consultadas a partir da referência [14].
 
Bibliotecas

Para um script NSE ser executado é necessário definirmos uma regra e a condição dessa regra retorne verdadeiro. A regra é uma função LUA que possui condições que retornam verdadeiro ou falso e pode ser definida como: prerule, hostrule, portrule e postrule.
 
Neste script foi utilizado a regra portrule, que tem como condição o IP, porta e/ou o estado da porta como open, filtered ou unfiltered. O script é executado quando a condição definida na regra for verdadeira. Para funções mais comuns como um serviço em execução ou uma porta aberta, geralmente utilizamos a biblioteca shortport[16] como foi usada neste artigo. Mais detalhes sobre as rules, você encontra na referência[15].
 
Rule Portrule declarada

Em seguida foi definido a função action, que é o coração do NSE pois contém todas as instruções que serão executadas, a action só é executada quando o critério definido na rule for verdadeiro, no nosso caso usamos a rule portrule, e o nosso critério é encontrar um serviço FTP rodando no host alvo.
 
Função Action declarada

Foi definido que a ação do script tem como parâmetro, o host e a porta. A seguir veremos o desenvolvimento da ação do script.
 
A variável shellcode foi declarada em hexadecimal, isto é necessário para montagem do payload.
 
Shellcode

Declarando a variável payload, esta parte do script foi a mais importante, destaco duas bibliotecas, a stdnse[17] com a função tohex, está função codifica uma string ou um número em hexadecimal e a biblioteca bin[18] com a função pack, que codifica o dado para binário, no nosso caso o dado está em hexadacimal e será codificado para binário. Ambas são cruciais para o exploit funcionar.
 
Detalhes do exploit está na pesquisa[4], para não prolongar muito o artigo não vou entrar na questão da construção do exploit, vou explicar as funções que foram utilizadas para escrever o script em LUA.
 
O formato utilizado segue o mesmo padrão do que foi utilizado no exploit do Maycon[6], [nops] + [shellcode] + [return address] + [padding] + [tag Egg-hunter (w00tw00t)]. Apenas tive que fazer algumas conversões para hexadecimal e binário, utilizando as bibliotecas stdnse e bin.
 
Montagem do Payload

E para finalizar o payload, foi declarado o endereço de retorno e o Egg-hunter.
 
Endereço de retorno e o Egg Hunter

Foi criado um socket tcp, conectando no host e porta que foi escaneado e verificamos se o serviço ftp é o KnFTPD, se não for o script não é executado, se for o script continua e envia o exploit para a máquina alvo.
 

Há um detalhe interessante nessa parte do script, precisamos enviar uma string de 7 carácteres junto com o payload para que o exploit seja executado, para isso foi criado a string de forma randômica, o que evita que o exploit seja bloqueado por algum IDS, WAF ou algum ativo que use pattern matching. A string foi gerada com a lib stdnse[17] com a função generate_random_string.    

 

Abrindo o socket e enviando o exploit

 

 

Após a execução do exploit, foi verificado se a máquina foi realmente explorada, conectando no host alvo na porta 28876, o script tenta durante 10 segundos se conectar ao host, se não conectar, não foi aberto o socket e o host não foi explorado.

 

Validando se o host foi explorado

 

 

Sendo assim o usuário receberá uma mensagem dizendo, “Command shell hasn’t been opened!”

 

Mensagem no script para o host não explorado

 

Saída do payload enviado e host não explorado

 

 

E finalmente, se o socket na porta 28876 estiver aberto o usuário receberá a mensagem “Command shell has been opened. (<host>:28876).

 

No script saída de host explorado

 

Saída do payload enviado e host explorado

 

 

Conforme o exemplo, basta se conectar no IP 192.168.208.138 na porta 28876 para ganhar a shell da máquina.

 

Shell do host

 

 

O script completo pode ser baixado na referência[18].

Conclusão

Lua é uma linguagem simples de programar, leve e muito flexível, junto com o Nmap as possibilidades de automação são infinitas. O Nmap está na versão 6.25 e possui 433 scripts, caso precise de algum script customizado para alguma demanda específica, como vocês viram, é simples criar scripts que atendam necessidades pontuais.

 
Gostaria de agradecer ao Maycon Vitali pelo apoio no shellcode e ao Ulisses Castro pela ajuda durante a pesquisa e desenvolvimento deste artigo.
 

Referência:

 

[1]  http://nmap.org/book/nse
[2]  http://www.lua.org/manual/5.1/manual   
[3]  http://www.lua.org/uses
[4]  http://blog.conviso.com.br/cve-2012-5905-de-negacao-de-servico
[5]  http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2012-5905
[6]  http://www.hacknroll.com/~maycon/CVE-2012-5905_py.txt
[7]  http://sourceforge.net/projects/knftp/
[8]  http://www.ollydbg.de/odbg110.zip
[9]  http://code.google.com/p/w32-bind-ngs-shellcode/downloads/list
[10] http://nmap.org/book/nsedoc
[11] http://www.amazon.com/Nmap-exploration-security-auditing-Cookbook/dp/1849517487
[12] https://svn.nmap.org/nmap/docs/sample-script.nse?p=30373
[13] http://nmap.org/book/nse-usage#nse-categories
[14] http://nmap.org/book/nse-library
[15] http://nmap.org/book/nse-tutorial#nse-tutorial-rule
[16] http://nmap.org/nsedoc/lib/shortport
[17] http://nmap.org/nsedoc/lib/stdnse
[18] https://github.com/rochax/NSEE/blob/master/knftpd-exploit.nse
[19] http://www.hick.org/code/skape/papers/egghunt-shellcode.pdf

[20] http://projectshellcode.com/?q=node/23

 

 

Originalmente postado no Blog da Conviso Application Security – Siga-nos no Twitter @conviso Google+

Tags

Deixe um comentário

topo
%d blogueiros gostam disto: