> For the complete documentation index, see [llms.txt](https://g4b0.gitbook.io/g4b0-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://g4b0.gitbook.io/g4b0-docs/documentation/active-directory/kerberos-double-hop-problem.md).

# Kerberos "Double Hop" Problem

Este inconveniente ocurre frecuentemente al usar WinRM o PowerShell, ya que su mecanismo de autenticación por defecto (Kerberos) solo emite un ticket para un recurso específico. Esto bloquea el movimiento lateral o el acceso a carpetas compartidas desde una shell remota, denegando el acceso incluso si el usuario tiene los privilegios adecuados.

La raíz del problema radica en cómo se manejan las credenciales en la memoria del sistema durante la conexión:

**Autenticación con WinRM (Kerberos):** Al establecer una sesión remota mediante este método, no se utiliza ni se guarda la contraseña en la sesión. Si analizamos la memoria con herramientas como Mimikatz tras conectarnos por WinRM, veremos que las credenciales del usuario están en blanco, lo que impide acceder a un tercer equipo.

**Autenticación tradicional (ej. PSExec por SMB/LDAP):** Cuando se obtiene una shell explotando una aplicación o usando herramientas como PSExec, la autenticación mediante contraseña guarda el hash NTLM en la memoria. Esto permite al equipo extraer ese hash posteriormente para autenticarnos en otros recursos sin problemas.

```powershell
PS C:\htb> PS C:\Users\ben.INLANEFREIGHT> Enter-PSSession -ComputerName DEV01 -Credential INLANEFREIGHT\backupadm
[DEV01]: PS C:\Users\backupadm\Documents> cd 'C:\Users\Public\'
[DEV01]: PS C:\Users\Public> .\mimikatz "privilege::debug" "sekurlsa::logonpasswords" exit
```

```powershell
mimikatz(commandline) # privilege::debug
mimikatz(commandline) # sekurlsa::logonpasswords
mimikatz(commandline) # exit
```

De hecho, existen procesos que se ejecutan en el contexto del usuario backupadm, como wsmprovhost.exe, que es el proceso que se inicia cuando se abre una sesión de Windows Remote PowerShell.

```powershell
[DEV01]: PS C:\Users\Public> tasklist /V |findstr backupadm
wsmprovhost.exe               1844 Services                   0     85,212 K Unknown         INLANEFREIGHT\backupadm
                             0:00:03 N/A
tasklist.exe                  6532 Services                   0      7,988 K Unknown         INLANEFREIGHT\backupadm
                             0:00:00 N/A
conhost.exe                   7048 Services                   0     12,656 K Unknown         INLANEFREIGHT\backupadm
                             0:00:00 N/A
```

En pocas palabras, en esta situación, al intentar ejecutar un comando multiservidor, nuestras credenciales no se enviarán de la primera máquina a la segunda.

Supongamos que tenemos tres hosts: Host de ataque --> DEV01 --> DC01. Nuestro Host de ataque es un servidor Parrot dentro de la red corporativa, pero no está unido al dominio. Obtenemos las credenciales de un usuario del dominio y descubrimos que pertenece al grupo de Usuarios de administración remota en DEV01. Queremos usar PowerView para enumerar el dominio, lo cual requiere comunicación con el controlador de dominio, DC01.

<figure><img src="/files/s42kwKQlXQ9fulzD0Ia2" alt=""><figcaption></figcaption></figure>

Cuando nos conectamos a DEV01 usando una herramienta como evil-winrm, nos conectamos con autenticación de red, por lo que nuestras credenciales no se almacenan en memoria y, por lo tanto, no estarán presentes en el sistema para autenticarse en otros recursos en nombre de nuestro usuario. Cuando cargamos una herramienta como PowerView e intentamos consultar Active Directory, Kerberos no puede indicarle al controlador de dominio que nuestro usuario puede acceder a los recursos del dominio. Esto sucede porque el ticket TGT (Ticket Granting Ticket) de Kerberos del usuario no se envía a la sesión remota; por lo tanto, el usuario no tiene forma de demostrar su identidad y los comandos ya no se ejecutarán en el contexto de este usuario. En otras palabras, al autenticarse en el host de destino, el ticket del servicio de concesión de tickets (TGS) del usuario se envía al servicio remoto, lo que permite la ejecución de comandos, pero el ticket TGT del usuario no se envía. Cuando el usuario intenta acceder a recursos posteriores en el dominio, su TGT no estará presente en la solicitud, por lo que el servicio remoto no podrá demostrar que el intento de autenticación es válido y se nos denegará el acceso.

Si unconstrained delegation está habilitada en un servidor, es probable que no nos encontremos con el problema del "doble salto". En este caso, cuando un usuario envía su ticket TGS para acceder al servidor de destino, su ticket TGT se envía junto con la solicitud. El servidor de destino ahora tiene el ticket TGT del usuario en memoria y puede usarlo para solicitar un ticket TGS en su nombre en el siguiente host al que intenta acceder. En otras palabras, el ticket TGT de la cuenta se almacena en caché, lo que le permite firmar tickets TGS y otorgar acceso remoto. En general, si se accede a un servidor con delegación sin restricciones, ya se ha resuelto el problema y no hay que preocuparse por esto.

### Workarounds

Se abordan algunas soluciones alternativas para el problema del doble salto. Podemos usar un comando Invoke-Command anidado para enviar credenciales (tras crear un objeto PSCredential) con cada solicitud, de modo que si intentamos autenticarnos desde nuestro host de ataque al host A y ejecutar comandos en el host B, se nos permitirá el acceso. En esta sección, cubriremos dos métodos: el primero, que podemos usar si trabajamos con una sesión evil-winrm, y el segundo, si tenemos acceso a la interfaz gráfica de usuario de un host Windows (ya sea un host de ataque en la red o un host unido a un dominio que hayamos comprometido).

#### Workaround #1: PSCredential Object

Iniciamos importando el módulo de powerview\.ps1 en el target con el usuario obtenido

```powershell
*Evil-WinRM* PS C:\Users\backupadm\Documents> import-module .\PowerView.ps1
```

Revisamos el ticket del usuario actual con klist

```powershell
*Evil-WinRM* PS C:\Users\backupadm\Documents> klist
```

Ahora, vamos a configurar un objeto PSCredential e intentarlo de nuevo. Primero, configuraremos nuestra autenticación.

```powershell
*Evil-WinRM* PS C:\Users\backupadm\Documents> $SecPassword = ConvertTo-SecureString '!qazXSW@' -AsPlainText -Force
```

Consultamos al AD sobre las cuentas SPN usando powerview

```powershell
get-domainuser -spn -credential $Cred | select samaccountname
```

SI probamos la consulta sobre las cuentas SPN sin la flag -credential se observa un error

```
*Evil-WinRM* PS C:\Users\backupadm\Documents> get-domainuser -spn | select samaccountname 
```

Si nos conectamos por RDP al mismo host, abrimos una ventana de comandos y escribimos `klist`, veremos que tenemos los tickets necesarios almacenados en caché para interactuar directamente con el controlador de dominio, y no tendremos que preocuparnos por el problema del doble salto. Esto se debe a que nuestra contraseña está almacenada en memoria, por lo que se puede enviar con cada solicitud que realicemos.

```powershell
C:\htb> klist
Current LogonId is 0:0x1e5b8b

Cached Tickets: (4)

#0>     Client: backupadm @ INLANEFREIGHT.LOCAL
        Server: krbtgt/INLANEFREIGHT.LOCAL @ INLANEFREIGHT.LOCAL
        KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
        Ticket Flags 0x60a10000 -> forwardable forwarded renewable pre_authent name_canonicalize
        Start Time: 6/28/2022 9:13:38 (local)
        End Time:   6/28/2022 19:13:38 (local)
        Renew Time: 7/5/2022 9:13:38 (local)
        Session Key Type: AES-256-CTS-HMAC-SHA1-96
        Cache Flags: 0x2 -> DELEGATION
        Kdc Called: DC01.INLANEFREIGHT.LOCAL

#1>     Client: backupadm @ INLANEFREIGHT.LOCAL
        Server: krbtgt/INLANEFREIGHT.LOCAL @ INLANEFREIGHT.LOCAL
        KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
        Ticket Flags 0x40e10000 -> forwardable renewable initial pre_authent name_canonicalize
        Start Time: 6/28/2022 9:13:38 (local)
        End Time:   6/28/2022 19:13:38 (local)
        Renew Time: 7/5/2022 9:13:38 (local)
        Session Key Type: AES-256-CTS-HMAC-SHA1-96
        Cache Flags: 0x1 -> PRIMARY
        Kdc Called: DC01.INLANEFREIGHT.LOCAL

#2>     Client: backupadm @ INLANEFREIGHT.LOCAL
        Server: ProtectedStorage/DC01.INLANEFREIGHT.LOCAL @ INLANEFREIGHT.LOCAL
        KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
        Ticket Flags 0x40a50000 -> forwardable renewable pre_authent ok_as_delegate name_canonicalize
        Start Time: 6/28/2022 9:13:38 (local)
        End Time:   6/28/2022 19:13:38 (local)
        Renew Time: 7/5/2022 9:13:38 (local)
        Session Key Type: AES-256-CTS-HMAC-SHA1-96
        Cache Flags: 0
        Kdc Called: DC01.INLANEFREIGHT.LOCAL

#3>     Client: backupadm @ INLANEFREIGHT.LOCAL
        Server: cifs/DC01.INLANEFREIGHT.LOCAL @ INLANEFREIGHT.LOCAL
        KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
        Ticket Flags 0x40a50000 -> forwardable renewable pre_authent ok_as_delegate name_canonicalize
        Start Time: 6/28/2022 9:13:38 (local)
        End Time:   6/28/2022 19:13:38 (local)
        Renew Time: 7/5/2022 9:13:38 (local)
        Session Key Type: AES-256-CTS-HMAC-SHA1-96
        Cache Flags: 0
        Kdc Called: DC01.INLANEFREIGHT.LOCAL


```

#### Workaround #2: Configuracion de Registro PSSession

Hemos visto cómo solucionar este problema al usar una herramienta como evil-winrm para conectarnos a un host mediante WinRM. ¿Qué ocurre si estamos en un host unido a un dominio y podemos conectarnos remotamente a otro mediante WinRM? ¿O si trabajamos desde un host de ataque Windows y nos conectamos a nuestro objetivo mediante WinRM usando el cmdlet Enter-PSSession? En estos casos, tenemos otra opción para modificar nuestra configuración y poder interactuar directamente con el controlador de dominio u otros hosts/recursos sin tener que configurar un objeto PSCredential e incluir credenciales con cada comando (lo cual puede no ser posible con algunas herramientas).

Establecemos una session WinRM a un equipo remoto

```powershell
PS C:\htb> Enter-PSSession -ComputerName ACADEMY-AEN-DEV01.INLANEFREIGHT.LOCAL -Credential inlanefreight\backupadm
```

Si comprobamos los tickets en caché con klist, veremos que persiste el mismo problema. Debido al problema del doble salto, solo podemos interactuar con los recursos de nuestra sesión actual, pero no podemos acceder al controlador de dominio directamente con PowerView. Podemos observar que nuestro TGS actual es adecuado para acceder al servicio HTTP en el destino, ya que nos conectamos mediante WinRM, que utiliza solicitudes SOAP (Simple Object Access Protocol) en formato XML para comunicarse a través de HTTP, por lo que tiene sentido.

```powershell
[ACADEMY-AEN-DEV01.INLANEFREIGHT.LOCAL]: PS C:\Users\backupadm\Documents> klist

Current LogonId is 0:0x11e387

Cached Tickets: (1)

#0>     Client: backupadm @ INLANEFREIGHT.LOCAL
       Server: HTTP/ACADEMY-AEN-DEV01.INLANEFREIGHT.LOCAL @ INLANEFREIGHT.LOCAL
       KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
       Ticket Flags 0x40a10000 -> forwardable renewable pre_authent name_canonicalize
       Start Time: 6/28/2022 9:09:19 (local)
       End Time:   6/28/2022 19:09:19 (local)
       Renew Time: 0
       Session Key Type: AES-256-CTS-HMAC-SHA1-96
       Cache Flags: 0x8 -> ASC
       Kdc Called:
```

Tampoco se podrá intercatuar con el DC directamente con powerview

```powershell
[ACADEMY-AEN-DEV01.INLANEFREIGHT.LOCAL]: PS C:\Users\backupadm\Documents> Import-Module .\PowerView.ps1
[ACADEMY-AEN-DEV01.INLANEFREIGHT.LOCAL]: PS C:\Users\backupadm\Documents> get-domainuser -spn | select samaccountname

Exception calling "FindAll" with "0" argument(s): "An operations error occurred.
"
At C:\Users\backupadm\Documents\PowerView.ps1:5253 char:20
+             else { $Results = $UserSearcher.FindAll() }
+                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
   + FullyQualifiedErrorId : DirectoryServicesCOMException
```

Un truco que podemos usar aquí es registrar una nueva configuración de sesión mediante el cmdlet Register-PSSessionConfiguration.

```powershell
PS C:\htb> Register-PSSessionConfiguration -Name backupadmsess -RunAsCredential inlanefreight\backupadm

 WARNING: When RunAs is enabled in a Windows PowerShell session configuration, the Windows security model cannot enforce
 a security boundary between different user sessions that are created by using this endpoint. Verify that the Windows
PowerShell runspace configuration is restricted to only the necessary set of cmdlets and capabilities.
WARNING: Register-PSSessionConfiguration may need to restart the WinRM service if a configuration using this name has
recently been unregistered, certain system data structures may still be cached. In that case, a restart of WinRM may be
 required.
All WinRM sessions connected to Windows PowerShell session configurations, such as Microsoft.PowerShell and session
configurations that are created with the Register-PSSessionConfiguration cmdlet, are disconnected.

   WSManConfig: Microsoft.WSMan.Management\WSMan::localhost\Plugin

Type            Keys                                Name
----            ----                                ----
Container       {Name=backupadmsess}                backupadmsess
```

Una vez hecho esto, debemos reiniciar el servicio WinRM escribiendo `Restart-Service WinRM` en nuestra PSSession actual. Esto nos desconectará, así que iniciaremos una nueva PSSession utilizando la sesión registrada con nombre que configuramos previamente.

Tras iniciar la sesión, podemos ver que el problema del doble salto se ha solucionado y, si escribimos `klist`, tendremos los tickets en caché necesarios para comunicarnos con el controlador de dominio. Esto funciona porque nuestra máquina local ahora suplantará la identidad de la máquina remota en el contexto del usuario `backupadm` y todas las solicitudes de nuestra máquina local se enviarán directamente al controlador de dominio.

```powershell
PS C:\htb> Enter-PSSession -ComputerName DEV01 -Credential INLANEFREIGHT\backupadm -ConfigurationName  backupadmsess
[DEV01]: PS C:\Users\backupadm\Documents> klist

Current LogonId is 0:0x2239ba

Cached Tickets: (1)

#0>     Client: backupadm @ INLANEFREIGHT.LOCAL
       Server: krbtgt/INLANEFREIGHT.LOCAL @ INLANEFREIGHT.LOCAL
       KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
       Ticket Flags 0x40e10000 -> forwardable renewable initial pre_authent name_canonicalize
       Start Time: 6/28/2022 13:24:37 (local)
       End Time:   6/28/2022 23:24:37 (local)
       Renew Time: 7/5/2022 13:24:37 (local)
       Session Key Type: AES-256-CTS-HMAC-SHA1-96
       Cache Flags: 0x1 -> PRIMARY
       Kdc Called: DC01
```

Ahora podemos ejecutar herramientas como PowerView sin necesidad de crear un nuevo objeto PSCredential.

```powershell
[DEV01]: PS C:\Users\Public> get-domainuser -spn | select samaccountname

samaccountname
--------------
azureconnect
backupjob
krbtgt
mssqlsvc
sqltest
sqlqa
sqldev
mssqladm
svc_sql
sqlprod
sapsso
sapvc
vmwarescvc
```

Nota: No podemos usar Register-PSSessionConfiguration desde una shell evil-winrm porque no podremos obtener la ventana emergente de credenciales. Además, si intentamos ejecutar esto configurando primero un objeto PSCredential y luego intentando ejecutar el comando pasando credenciales como -RunAsCredential $Cred, obtendremos un error porque solo podemos usar RunAs desde una terminal de PowerShell con privilegios elevados. Por lo tanto, este método no funcionará a través de una sesión evil-winrm, ya que requiere acceso a la interfaz gráfica de usuario y una consola de PowerShell adecuada. Además, en nuestras pruebas, no pudimos hacer que este método funcionara desde PowerShell en un host de ataque Parrot o Ubuntu debido a ciertas limitaciones en cómo PowerShell en Linux funciona con credenciales Kerberos. Este método sigue siendo muy efectivo si estamos probando desde un host de ataque Windows y tenemos un conjunto de credenciales o comprometemos un host y podemos conectarnos a través de RDP para usarlo como un "host intermedio" para lanzar ataques adicionales contra hosts en el entorno.

También podemos utilizar otros métodos como CredSSP, el reenvío de puertos o la inyección en un proceso que se ejecuta en el contexto de un usuario objetivo (proceso de sacrificio), que no abordaremos aquí.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://g4b0.gitbook.io/g4b0-docs/documentation/active-directory/kerberos-double-hop-problem.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
