
Determinar privilegios a partir de credenciales de la nube mediante pruebas de fuerza bruta.
Tengo credenciales, ¿y ahora qué?
CloudPrivs es una herramienta que aprovecha el poder existente de SDKs como Boto3 para forzar por fuerza bruta los privilegios de todos los servicios en la nube y determinar qué permisos existen para un conjunto dado de credenciales.
Esta herramienta es útil para Pentesters, Red Teamers y otros profesionales de la seguridad. Los servicios en la nube normalmente no ofrecen una forma de determinar qué permisos tiene un conjunto de credenciales, y el gran número de servicios y operaciones hace que sea una tarea abrumadora confirmarlo manualmente. Esto puede significar que sea posible una escalada de privilegios a partir de un conjunto de credenciales, pero uno nunca lo sabría porque simplemente no sabe que las credenciales de AWS que encontró pueden ejecutar Lambda.
Actualmente no disponible en PyPi, pero estoy trabajando en ello
git clone https://github.com/AbstractClass/CloudPrivs
cd CloudPrivs
python -m pip install -e .
Esto es sin un entorno virtual y no se recomienda si ejecutas muchos programas de Python.
git clone https://github.com/AbstractClass/CloudPrivs
cd CloudPrivs
python -m venv venv/
./venv/bin/activate # activate.ps1 en windows
python -m pip install -e .
También puedes usar Pyenv+virtualenv si está disponible:
git clone https://github.com/AbstractClass/CloudPrivs
cd CloudPrivs
pyenv virtualenv CloudPrivs
pyenv local CloudPrivs
python -m pip install -e .
cloudprivs [PROVIDER] [ARGS]
Actualmente, el único proveedor disponible es AWS, pero estoy trabajando en GCP. Si deseas ayudar, consulta #Personalización.
Opciones:
-v, --verbose Muestra las pruebas fallidas y con errores en la salida
-s, --services TEXTO Solo probar los servicios indicados en lugar de todos los servicios disponibles
-p, --profile TEXTO El nombre del perfil de AWS a escanear; si no se especifica, se usarán las variables de entorno
-t, --custom-tests ARCHIVO Ruta del archivo YAML de pruebas personalizadas. Lea la documentación para más información
-r, --regions TEXTO Lista de filtros para coincidir con regiones, ej.: "us", "eu-west", "ap-north-1"
--help Muestra este mensaje y sale.
Se admiten múltiples argumentos para --region y --service, pero deben proporcionarse con el flag cada vez, es decir, cloudprivs aws -r us -r eu -s ec2 -s lambda. A mí tampoco me gusta, pero es una limitación en Click para la que aún no he encontrado una solución.
Nota: el flag
regionadmite coincidencias parciales; los argumentos más comunes son-r us -r eupara cubrir solo las regiones comunes
Los resultados se muestran agrupados por región y cada línea contiene un caso de prueba y el resultado de la prueba.
Si la herramienta encuentra errores inesperados durante las pruebas, se emitirán a stderr a medida que ocurren, lo que significa que pueden interrumpir el flujo de salida; si no deseas verlos, puedes redirigir stderr.
A diferencia de otras herramientas como WeirdAAL que escriben manualmente cada caso de prueba, CloudPrivs consulta directamente el SDK de Boto3 para generar dinámicamente una lista de todos los servicios disponibles y todas las regiones disponibles para cada servicio.
Una vez que se genera una lista completa, cada función se llama sin argumentos por defecto, aunque se admite la opción de agregar argumentos personalizados por operación (más información en #Personalización).
Nota: algunas funciones de AWS pueden incurrir en costos al ser llamadas; solo he permitido operaciones que comienzan con
get_,list_ydescribe_para mitigar costos accidentales, lo que parece seguro en mis propias pruebas, pero úsalo con precaución. Aunque esto parece seguro para otras herramientas como enumerate-iam, no garantizo que no incurras accidentalmente en costos al llamar a todas estas funciones (incluso si es sin argumentos).
CloudPrivs admite una fácil extensión/personalización en dos áreas:
Implementar un nuevo proveedor (ej. GCP) es sencillo:
CloudPrivs/providers, crea una nueva carpeta para tu proveedor (ej. 'gcp').CloudPrivs/providers/__init__.py, agrega tu proveedor a la variable __all__; debe coincidir con el nombre de la carpeta.cli.py en la carpeta de tu proveedor.cli (consulta el proveedor de AWS como referencia).cloudprivs <proveedor> ahora debería mostrar tu CLI.El proveedor de AWS admite la inyección de argumentos al llamar a funciones de AWS. Esta característica se proporciona porque a menudo una función de AWS requiere argumentos para ser llamada y, en algunos casos, estos argumentos pueden ser variables fijas. Esto significa que si podemos proporcionar variables ficticias, podemos aumentar nuestra cobertura de pruebas. En otros casos, podemos inyectar argumentos como dryrun=true para que las llamadas sean más rápidas.
Las pruebas personalizadas se almacenan en un archivo YAML en cloudprivs/providers/aws/CustomTests.yaml.
La estructura del YAML es la siguiente:
---
<nombre-servicio>:
- <nombre-función>:
args:
- <arg1>
- <arg2>
kwargs:
arg1: val1
arg2: val2
Nota: el nombre de la función funciona con coincidencias parciales; esto significa que puedes usar un nombre de función como 'describe_' y los argumentos especificados se inyectarán en todas las funciones que contengan 'describe_'. Las reglas se evalúan según el principio de 'primero encontrado', por lo que si deseas anular una regla genérica, coloca tu regla más específica encima de la genérica. Ej.:
ec2:
- describe_instances
args:
kwargs:
DryRun: True
NoPaginate: True
- describe_
args:
kwargs:
DryRun: True
Se pueden agregar nuevas reglas modificando el archivo CustomTests.yaml existente o creando un nuevo archivo YAML y especificándolo con el flag --custom-tests. El nuevo archivo se fusionará con el archivo de pruebas existente y cualquier valor duplicado se sobrescribirá, dando prioridad al archivo proporcionado.
El proveedor de AWS está escrito como una biblioteca para su integración en otras herramientas. Puedes usarlo de la siguiente manera:
import boto3
from cloudprivs.providers.aws import service
from concurrent.futures import ThreadPoolExecutor
session = boto3.Session('default')
with ThreadPoolExecutor(15) as executor:
iam = service.Service('iam', session, executor=executor)
scan_results = iam.scan() # cubrirá todas las regiones listadas en el executor (todas las regiones disponibles por defecto)
formatted_results = iam.pretty_print_scan(scan_results)
print(formatted_results)
Todo está completamente documentado en el código; debería ser bastante fácil de interpretar.
Esta herramienta es funcional, pero está lejos de estar completa. Estoy trabajando activamente en nuevas funciones y estoy abierto a contribuciones, así que no dudes en abrir Issues/Solicitudes de funciones y enviar PRs.
Funciones planificadas