> For the complete documentation index, see [llms.txt](https://docs.stoik.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.stoik.io/cyber-best-practices/es/guias-de-remediacion-de-vulnerabilidades/ad-scan-vulnerability-remediation-guide.md).

# Guía de remediación de Active Directory Scan

Cada sección de vulnerabilidad incluye:

* **Qué significa:** una explicación del riesgo en lenguaje sencillo
* **Qué comprueba el análisis:** las condiciones específicas que activan la alerta
* **Por qué la alerta puede persistir:** soluciones parciales comunes que no son suficientes
* **Cómo diagnosticar:** comandos de PowerShell para identificar los objetos afectados
* **Cómo solucionarlo:** corrección paso a paso

> **Requisitos previos:** Todos los comandos de PowerShell requieren el `ActiveDirectory` módulo y deben ejecutarse como administrador del dominio en un controlador de dominio.
>
> ```powershell
> Import-Module ActiveDirectory
> ```

## A-LAPS-Not-Installed

#### Qué significa

Todos los equipos Windows tienen una **cuenta de Administrador local integrada**. De forma predeterminada, esta cuenta suele tener la misma contraseña en todas las máquinas, o una contraseña que nunca cambia. Si un atacante compromete una máquina, puede reutilizar esa contraseña para acceder a todas las demás.

**LAPS** (Local Administrator Password Solution) soluciona esto estableciendo automáticamente una contraseña única, generada aleatoriamente, en cada equipo y almacenándola de forma segura en Active Directory. Solo los administradores autorizados pueden recuperarla.

#### Qué comprueba el análisis

El análisis de AD busca pruebas de que LAPS se ha configurado en su Active Directory. En concreto, comprueba si los campos de datos necesarios de LAPS existen en su configuración de AD. Si no existen, significa que LAPS nunca se instaló.

#### Por qué la alerta puede persistir

* **LAPS administrado solo a través de Intune:** Si usa Microsoft Intune para administrar las contraseñas de LAPS en la nube (sin configurar el AD local), el análisis de AD no puede detectarlo. El análisis solo revisa su Active Directory local.
* **LAPS se instaló parcialmente:** La configuración de LAPS puede haberse iniciado pero no completado.

#### Cómo diagnosticar

```powershell
# Compruebe si LAPS está configurado en su Active Directory
Get-ADObject -SearchBase (Get-ADRootDSE).SchemaNamingContext `
  -Filter "name -like 'ms-Mcs-AdmPwd' -or name -eq 'ms-LAPS-Password'" |
  Select-Object Name, whenCreated
```

Si esto no devuelve resultados, LAPS no está instalado.

#### Cómo solucionarlo

**Para Windows Server 2019 y posteriores (recomendado):** LAPS moderno viene integrado en Windows. Habilítelo mediante directiva de grupo:

1. Abra `gpmc.msc` (Administración de directivas de grupo)
2. Edite o cree una GPO vinculada a las UO de sus equipos
3. Vaya a: `Configuración del equipo > Plantillas administrativas > Sistema > LAPS`
4. Configure los ajustes de LAPS (habilitarlo, establecer la complejidad de la contraseña, etc.)

**Para entornos antiguos:** Descargue Legacy LAPS de Microsoft y ejecute la extensión del esquema:

```powershell
Update-LapsADSchema
```

> **Nota:** Si administra las contraseñas de administrador local mediante otra herramienta (CyberArk, LAPS solo con Intune, etc.), contacte con el soporte de Stoïk para documentarlo como una excepción aceptada.

## A-LAPS-Joined-Computers

#### Qué significa

Cuando alguien añade ("une") un equipo al dominio de Active Directory, esa persona se convierte en el **creador** del objeto de equipo en AD. De forma predeterminada, el creador obtiene permisos especiales sobre ese objeto.

El problema es: cuando LAPS está instalado, la contraseña del administrador local se almacena en ese mismo objeto de equipo. Si el creador sigue teniendo los permisos adecuados, puede **leer la contraseña de LAPS**, incluso si no es administrador. Esto significa que un usuario normal que alguna vez unió un PC al dominio podría recuperar la contraseña de administrador local de esa máquina.

#### Qué comprueba el análisis

Para cada equipo habilitado con LAPS implementado, el análisis de AD comprueba **dos cosas**:

1. **¿La persona que unió el equipo sigue siendo el "propietario" del objeto de equipo?** Los propietarios pueden concederse cualquier permiso, incluida la lectura de la contraseña de LAPS.
2. **¿El creador sigue teniendo permisos explícitos** sobre el objeto de equipo, como `Todos los derechos extendidos` (lo que permite leer la contraseña de LAPS), `WriteDacl` (lo que permite modificar permisos), `WriteOwner` (lo que permite recuperar la propiedad), o `GenericWrite`?

La alerta se activa si **cualquiera de las** condiciones es verdadera.

#### Por qué la alerta puede persistir

Esta es la fuente de confusión más común: **cambiar el propietario solo es la mitad de la solución.**

Muchos administradores cambian el propietario a "Domain Admins" y esperan que la alerta desaparezca. Pero el análisis de AD también comprueba los permisos residuales (llamados ACE o Access Control Entries) que se concedieron al creador original. Estos permisos permanecen incluso después de cambiar el propietario y deben eliminarse por separado.

#### Cómo diagnosticar

```powershell
# Liste los equipos donde el creador aún tiene permisos de riesgo
Get-ADComputer -Filter "Enabled -eq `$true" `
  -Properties "mS-DS-CreatorSID", "nTSecurityDescriptor" |
  Where-Object { $_."mS-DS-CreatorSID" -ne $null } |
  ForEach-Object {
    $comp = $_
    $acl = $comp.nTSecurityDescriptor
    $creatorSid = $comp."mS-DS-CreatorSID"
    $owner = $acl.GetOwner([System.Security.Principal.SecurityIdentifier])

    $isOwner = ($owner.Value -eq $creatorSid.Value)

    $riskyAces = $acl.Access | Where-Object {
      -not $_.IsInherited -and
      $_.IdentityReference.Value -eq $creatorSid.Value -and
      ($_.ActiveDirectoryRights -match 'WriteDacl|WriteOwner|GenericWrite|ExtendedRight')
    }

    if ($isOwner -or $riskyAces) {
      [PSCustomObject]@{
        Equipo       = $comp.Name
        CreadorEsPropietario = $isOwner
        PermisosDeRiesgo    = ($riskyAces | ForEach-Object { $_.ActiveDirectoryRights }) -join ", "
      }
    }
  } | Format-Table -AutoSize
```

#### Cómo solucionarlo

Debe hacer **ambas** cosas para cada equipo afectado:

1. **Cambiar el propietario** a Domain Admins
2. **Eliminar los permisos explícitos del creador**

El siguiente script hace ambas cosas automáticamente:

```powershell
#Requires -Modules ActiveDirectory

$affectedComputers = Get-ADComputer -Filter "Enabled -eq `$true" `
  -Properties "mS-DS-CreatorSID", "nTSecurityDescriptor" |
  Where-Object { $_."mS-DS-CreatorSID" -ne $null }

foreach ($comp in $affectedComputers) {
  $path = "AD:$($comp.DistinguishedName)"
  $acl = Get-Acl -Path $path
  $creatorSid = $comp."mS-DS-CreatorSID"
  $modified = $false

  # Paso 1: Cambiar el propietario a Domain Admins
  $domainAdmins = New-Object System.Security.Principal.NTAccount("$env:USERDOMAIN", "Domain Admins")
  $acl.SetOwner($domainAdmins)
  $modified = $true

  # Paso 2: Eliminar los permisos explícitos concedidos al creador (y los SID huérfanos)
  $toRemove = @($acl.Access | Where-Object {
    -not $_.IsInherited -and
    ($_.IdentityReference.Value -eq $creatorSid.Value -or
     $_.IdentityReference.Value -match '^S-1-5-21-')  # SID huérfanos (cuentas eliminadas)
  })

  foreach ($ace in $toRemove) {
    $acl.RemoveAccessRuleSpecific($ace)
    Write-Host "$($comp.Name): Eliminado [$($ace.ActiveDirectoryRights)] para $($ace.IdentityReference)"
  }

  if ($modified) {
    Set-Acl -Path $path -AclObject $acl
    Write-Host "$($comp.Name): Corregido" -ForegroundColor Green
  }
}
```

> **Consejo:** Ejecute primero el comando de diagnóstico para revisar la lista de equipos afectados antes de aplicar la solución.

## A-NoServicePolicy

#### Qué significa

**Cuentas de servicio** son cuentas usadas por aplicaciones y servicios (p. ej., SQL Server, agentes de copia de seguridad) para autenticarse en Active Directory. A diferencia de las cuentas de usuario normales, las cuentas de servicio son objetivos de alto valor: a menudo tienen permisos elevados y sus contraseñas rara vez se cambian.

Una **directiva de contraseñas de granularidad fina (PSO)** es una regla de contraseña especial que puede aplicar a grupos específicos de cuentas. El análisis de AD espera que sus cuentas de servicio estén cubiertas por una PSO que requiera contraseñas de al menos **20 caracteres**, lo que las hace mucho más difíciles de descifrar.

#### Qué comprueba el análisis

El análisis de AD busca al menos una directiva de contraseñas (GPO o PSO) que imponga una longitud mínima de contraseña de **20 caracteres o más**.

#### Por qué la alerta puede persistir

1. **La cuenta de análisis no tiene permiso para leer la PSO.** Las directivas de contraseñas se almacenan en un área protegida de AD que, de forma predeterminada, solo pueden leer los Domain Admins. Si el análisis se ejecuta con una cuenta con menos privilegios, simplemente no puede ver la PSO, aunque exista.
2. **La PSO existe, pero la longitud mínima está por debajo de 20** (p. ej., 12 o 15 caracteres).
3. **La PSO existe, pero no está asignada a ningún grupo ni usuario.**

#### Cómo diagnosticar

```powershell
# Liste todas las directivas de contraseñas detalladas y sus configuraciones
Get-ADFineGrainedPasswordPolicy -Filter * |
  Select-Object Name, MinPasswordLength, @{N="AplicadoA"; E={$_.AppliesTo -join ", "}}, Precedence
```

Si esto no devuelve nada, o no existe ninguna PSO o la cuenta que ejecuta el comando no tiene permisos para verla. Intente ejecutarlo con una cuenta de Domain Admin.

#### Cómo solucionarlo

**Si la PSO existe pero el análisis no puede verla:** Ejecute el análisis de AD con una cuenta de Domain Admin.

**Si no existe ninguna PSO:** Cree una y asígnela a sus cuentas de servicio:

```powershell
# Cree una directiva de contraseñas para cuentas de servicio
New-ADFineGrainedPasswordPolicy -Name "Service Accounts - Strong Password" `
  -Precedence 10 `
  -MinPasswordLength 20 `
  -MaxPasswordAge "90.00:00:00" `
  -MinPasswordAge "1.00:00:00" `
  -PasswordHistoryCount 24 `
  -ComplexityEnabled $true `
  -ReversibleEncryptionEnabled $false `
  -LockoutDuration "00:30:00" `
  -LockoutObservationWindow "00:30:00" `
  -LockoutThreshold 5

# Asígnela a un grupo de seguridad que contenga sus cuentas de servicio
Add-ADFineGrainedPasswordPolicySubject `
  -Identity "Service Accounts - Strong Password" `
  -Subjects "SG_ServiceAccounts"
```

> **Nota:** Crear una PSO no obliga inmediatamente a cambiar las contraseñas. Las contraseñas existentes seguirán funcionando hasta que caduquen o se restablezcan manualmente. En ese momento, se aplicará el nuevo mínimo de 20 caracteres.

## A-AuditDC

#### Qué significa

**Directivas de auditoría** determinan qué eventos se registran en sus controladores de dominio. Sin una auditoría adecuada, ataques como el robo de credenciales, cambios no autorizados en grupos o el abuso de replicación (DCSync) pueden ocurrir sin dejar rastro en los registros.

El análisis de AD verifica que sus controladores de dominio estén configurados para registrar los eventos de seguridad más importantes.

#### Qué comprueba el análisis

El análisis busca **13 subcategorías de auditoría específicas** que deben habilitarse mediante directiva de grupo en todos los controladores de dominio:

| Categoría                                      | Qué registra                                                        |
| ---------------------------------------------- | ------------------------------------------------------------------- |
| Servicio de autenticación Kerberos             | Intentos de inicio de sesión mediante Kerberos                      |
| Operaciones de tickets de servicio de Kerberos | Solicitudes de tickets de servicio (detecta Kerberoasting)          |
| Administración de cuentas de equipo            | Uniones/cambios de equipos en AD                                    |
| Administración de grupos de seguridad          | Cambios en la pertenencia a grupos                                  |
| Administración de cuentas de usuario           | Creación, eliminación y restablecimiento de contraseñas de usuarios |
| Actividad de DPAPI                             | Uso de la API de protección de datos (acceso a credenciales)        |
| Creación de procesos                           | Se inician nuevos procesos (detecta herramientas maliciosas)        |
| Inicio / cierre de sesión                      | Inicios de sesión interactivos y remotos                            |
| Inicio de sesión especial                      | Inicios de sesión con privilegios elevados                          |
| Cambio de política de autenticación            | Cambios en la configuración de autenticación                        |
| Uso de privilegios sensibles                   | Uso de permisos sensibles                                           |
| Extensión del sistema de seguridad             | Cambios del subsistema de seguridad                                 |

#### Por qué la alerta puede persistir

1. **Configuraciones aplicadas mediante `auditpol` directamente en el DC** no se detectan. El análisis de AD lee archivos de directiva de grupo, no la configuración local del DC. Debe usar una GPO.
2. **GPO en conflicto:** Una GPO habilita la configuración, pero otra GPO con mayor prioridad la deshabilita.
3. **GPO no vinculada a la UO de Domain Controllers:** La GPO existe pero está vinculada a otra UO.

#### Cómo diagnosticar

```powershell
# Compruebe la directiva de auditoría efectiva en un controlador de dominio
auditpol /get /category:*
```

Si la configuración local parece correcta pero la alerta persiste, compruebe que la configuración proviene de una GPO (no de una sustitución local):

```powershell
# Verifique qué GPO están vinculadas a la UO de Domain Controllers
Get-GPInheritance -Target "OU=Domain Controllers,$($(Get-ADDomain).DistinguishedName)"
```

#### Cómo solucionarlo

1. Abra `gpmc.msc` (Consola de administración de directivas de grupo)
2. Cree o edite una GPO vinculada a `OU=Domain Controllers`
3. Vaya a: `Configuración del equipo > Directivas > Configuración de Windows > Configuración de seguridad > Configuración avanzada de directivas de auditoría > Directivas de auditoría`
4. Habilitar **Éxito y error** para todas las subcategorías indicadas arriba
5. Ejecute `gpupdate /force` en todos los controladores de dominio

Verifique la solución:

```powershell
auditpol /get /category:"Account Logon"
auditpol /get /category:"Account Management"
auditpol /get /category:"Logon/Logoff"
```

## A-BadSuccessor

#### Qué significa

Windows Server 2025 introdujo un nuevo tipo de cuenta de servicio llamado **dMSA** (Delegated Managed Service Account). Se descubrió una vulnerabilidad de seguridad por la que un usuario normal con ciertos permisos en una carpeta de Active Directory (llamada Unidad Organizativa, u OU) podía crear una dMSA y usarla para obtener acceso completo de administrador al dominio.

Este ataque solo es posible cuando:

* Tiene al menos un **Windows Server 2025** controlador de dominio
* Una **clave raíz KDS** existe (requerida para las cuentas de servicio administradas)
* Un usuario sin privilegios de administrador tiene derecho a crear objetos en una UO

#### Qué comprueba el análisis

El análisis de AD busca usuarios o grupos sin privilegios que tengan permisos para crear o controlar objetos dMSA en cualquier UO, como `CreateChild`, `GenericAll`, `WriteDacl`, o `WriteOwner`.

#### Por qué la alerta puede persistir

* La solución debe aplicarse en **cada** UO afectada, no solo en una.
* Los permisos heredados de las UO principales siguen aplicándose a las UO secundarias.
* Los grupos de administración personalizados pueden no ser reconocidos como "privilegiados" por el análisis.

#### Cómo diagnosticar

```powershell
# Compruebe los requisitos previos
Get-KdsRootKey  # La clave raíz KDS debe existir para que el ataque sea posible

Get-ADDomainController -Filter * |
  Where-Object { $_.OperatingSystem -like "*2025*" } |
  Select-Object Name, OperatingSystem  # Al menos un DC Win2025

# Busque UO con delegaciones de riesgo
Get-ADOrganizationalUnit -Filter * -Properties nTSecurityDescriptor |
  ForEach-Object {
    $ou = $_
    $ou.nTSecurityDescriptor.Access |
      Where-Object {
        -not $_.IsInherited -and
        $_.ActiveDirectoryRights -match 'GenericAll|CreateChild|WriteDacl|WriteOwner'
      } | ForEach-Object {
        [PSCustomObject]@{
          UO        = $ou.Name
          Principal = $_.IdentityReference
          Derechos    = $_.ActiveDirectoryRights
        }
      }
  } | Format-Table -AutoSize
```

#### Cómo solucionarlo

Para cada UO marcada, elimine los permisos de riesgo de los usuarios sin privilegios de administrador:

```powershell
$ouDN = "OU=Servers,DC=yourdomain,DC=com"  # Sustituya por su UO
$path = "AD:$ouDN"
$acl = Get-Acl -Path $path

# Elimine los permisos de riesgo para un grupo específico
$identity = New-Object System.Security.Principal.NTAccount("YOURDOMAIN", "HelpDeskTeam")
$toRemove = $acl.Access | Where-Object {
  $_.IdentityReference -eq $identity -and
  $_.ActiveDirectoryRights -match 'CreateChild|GenericAll'
}

foreach ($ace in $toRemove) {
  $acl.RemoveAccessRuleSpecific($ace)
}
Set-Acl -Path $path -AclObject $acl
```

## A-AdminSDHolder

#### Qué significa

Cuando un usuario se añade a un grupo privilegiado en Active Directory (como Domain Admins), el sistema marca automáticamente su cuenta con una bandera llamada `adminCount = 1`. Esta bandera forma parte de un mecanismo de protección integrado.

El problema es: **cuando elimina a ese usuario del grupo de administración, la bandera NO se borra automáticamente.** Permanece para siempre, a menos que la elimine explícitamente.

El análisis de AD marca cuentas que conservan este resto de `adminCount` indicador, pero ya no son administradores reales. Esto puede indicar:

* Un usuario que fue administrador temporalmente y la limpieza quedó incompleta
* Un posible problema de seguridad: estas cuentas aún pueden tener permisos elevados en ciertas áreas

#### Qué comprueba el análisis

El análisis encuentra cuentas de usuario habilitadas en las que `adminCount = 1` pero la cuenta no es actualmente miembro de ningún grupo privilegiado.

#### Cómo diagnosticar

```powershell
# Cree una lista de todos los usuarios privilegiados actuales
$privilegedMembers = @()
@("Domain Admins", "Enterprise Admins", "Schema Admins", "Administrators",
  "Account Operators", "Server Operators", "Backup Operators", "Print Operators"
) | ForEach-Object {
  try { $privilegedMembers += (Get-ADGroupMember $_ -Recursive).DistinguishedName } catch {}
}

# Busque cuentas con la bandera adminCount residual
Get-ADUser -LDAPFilter "(&(admincount=1)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))" `
  -Properties adminCount |
  Where-Object { $_.DistinguishedName -notin $privilegedMembers } |
  Select-Object SamAccountName, Name
```

#### Cómo solucionarlo

Después de confirmar que estas cuentas ya no deberían ser administradores, borre la bandera:

```powershell
# Borre adminCount para un solo usuario
Set-ADUser -Identity "username" -Clear adminCount

# O bórrelo para todos los usuarios sin privilegios de una vez
Get-ADUser -LDAPFilter "(&(admincount=1)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))" |
  Where-Object { $_.DistinguishedName -notin $privilegedMembers } |
  ForEach-Object {
    Set-ADUser -Identity $_ -Clear adminCount
    Write-Host "Se borró adminCount para $($_.SamAccountName)"
  }
```

## P-Kerberoasting

#### Qué significa

En Active Directory, algunas cuentas están registradas para ejecutar servicios como SQL Server o una aplicación web. Estas cuentas tienen un **Nombre principal de servicio (SPN)**, que es esencialmente una etiqueta que dice "esta cuenta ejecuta un servicio de red."

El riesgo de seguridad es: **cualquier usuario autenticado** en el dominio puede solicitar un ticket Kerberos para cualquier cuenta con un SPN. Ese ticket está cifrado con la contraseña de la cuenta, y el atacante puede intentar descifrarlo fuera de línea, sin activar ninguna alerta.

Esto se llama **Kerberoasting** ataque. Es especialmente peligroso cuando la cuenta con el SPN también es un **Administrador del dominio**, porque descifrar esa contraseña significa control total del dominio.

#### Qué comprueba el análisis

El AD Scan marca las cuentas que cumplen **las tres** condiciones:

1. La cuenta es miembro de un **grupo privilegiado** (Admins del dominio, Admins de la empresa, etc.)
2. La cuenta tiene un **Nombre principal de servicio (SPN)**
3. La **contraseña de la cuenta no se ha cambiado en más de 40 días** (dando a los atacantes más tiempo para descifrarla)

#### Por qué la alerta puede persistir

Debes abordar **las tres** condiciones. Soluciones incompletas comunes:

* **Se cambió la contraseña pero se mantuvo el SPN:** La alerta desaparece temporalmente, pero vuelve después de 40 días.
* **Se eliminó el SPN pero la cuenta sigue en Admins del dominio:** La alerta desaparece, pero el riesgo subyacente sigue existiendo.

#### Cómo diagnosticar

```powershell
$privilegedGroups = @("Domain Admins", "Enterprise Admins", "Schema Admins", "Administrators")
$threshold = (Get-Date).AddDays(-40)

foreach ($group in $privilegedGroups) {
  Get-ADGroupMember -Identity $group -Recursive |
    Where-Object { $_.objectClass -eq "user" } |
    ForEach-Object { Get-ADUser $_ -Properties ServicePrincipalName, PasswordLastSet } |
    Where-Object { $_.ServicePrincipalName.Count -gt 0 -and $_.PasswordLastSet -lt $threshold } |
    Select-Object SamAccountName,
      @{N="PasswordAge (days)"; E={[math]::Round(((Get-Date) - $_.PasswordLastSet).TotalDays)}},
      @{N="SPNs"; E={$_.ServicePrincipalName -join "; "}}
}
```

#### Cómo solucionarlo

**Mejor opción: quitar la cuenta de los grupos privilegiados.** Las cuentas de servicio rara vez necesitan ser Administradores del dominio. Crea una cuenta dedicada, sin privilegios, con solo los permisos que el servicio realmente necesita:

```powershell
Remove-ADGroupMember -Identity "Domain Admins" -Members "svc_account" -Confirm:$false
```

**Si no puedes quitarla del grupo de administradores:** Como mínimo, restablece la contraseña con regularidad (cada 30 días o menos):

```powershell
Set-ADAccountPassword -Identity "svc_account" `
  -NewPassword (ConvertTo-SecureString "YourNewStr0ngP@ssw0rd!" -AsPlainText -Force) -Reset
```

**Mejor solución a largo plazo:** Convertirla en una **Cuenta de servicio administrada por grupo (gMSA)**, que rota su contraseña automáticamente cada 30 días:

```powershell
New-ADServiceAccount -Name "gMSA_SQLService" `
  -DNSHostName "gmsa_sqlservice.yourdomain.com" `
  -PrincipalsAllowedToRetrieveManagedPassword "SQLServersGroup"
```

## P-AdminLogin

#### Qué significa

Cada dominio de Active Directory tiene una **cuenta de Administrador integrada** que se crea automáticamente cuando se configura el dominio. Esta cuenta tiene control total sobre todo el dominio y no se puede bloquear.

Debido a su poder y previsibilidad (los atacantes saben que siempre existe), debe reservarse para **solo emergencias**, como la recuperación tras un desastre. La administración diaria debe usar cuentas administrativas personales (p. ej., `adm_john`) para que las acciones puedan atribuirse a individuos.

#### Qué comprueba el análisis

El AD Scan comprueba si la cuenta de Administrador integrada ha iniciado sesión en algún Controlador de Dominio en los **últimos 35 días**. Si es así, se activa la alerta, lo que indica que la cuenta se está utilizando para tareas rutinarias en lugar de reservarse para emergencias.

#### Por qué la alerta puede persistir

* **Renombrar la cuenta no ayuda.** El escaneo identifica al Administrador integrado por su identificador interno (RID-500), no por su nombre.
* **Cambiar la contraseña no ayuda.** El escaneo comprueba la actividad de inicio de sesión, no la antigüedad de la contraseña.
* **Scripts automatizados o tareas programadas** que se ejecutan como el Administrador integrado seguirán activando la alerta.
* **Solo tienes que esperar.** Después de dejar de usar la cuenta, la alerta desaparece automáticamente tras 35 días.

#### Cómo diagnosticar

```powershell
# Comprueba cuándo inició sesión por última vez el Administrador integrado en cada DC
$domainSID = (Get-ADDomain).DomainSID
$adminSID = "$domainSID-500"

Get-ADDomainController -Filter * | ForEach-Object {
  $dc = $_
  $admin = Get-ADUser -Identity $adminSID -Server $dc.HostName -Properties LastLogon
  $lastLogon = [DateTime]::FromFileTime($admin.LastLogon)
  $daysAgo = [math]::Round(((Get-Date) - $lastLogon).TotalDays, 1)

  [PSCustomObject]@{
    DC        = $dc.HostName
    LastLogon = $lastLogon
    DaysAgo   = $daysAgo
    Status    = if ($daysAgo -le 35) { "ALERTA - Usada recientemente" } else { "OK" }
  }
} | Format-Table -AutoSize
```

También verifica si hay tareas programadas que puedan estar usando el Administrador integrado:

```powershell
Get-ADDomainController -Filter * | ForEach-Object {
  Invoke-Command -ComputerName $_.HostName -ScriptBlock {
    Get-ScheduledTask | Where-Object {
      $_.Principal.UserId -match "Administrator"
    } | Select-Object TaskName, @{N="RunAs"; E={$_.Principal.UserId}}
  }
}
```

#### Cómo solucionarlo

1. **Crear cuentas administrativas personales** para cada administrador (p. ej., `adm_john`, `adm_jane`)
2. **Actualizar cualquier tarea programada** para usar una cuenta de servicio dedicada en lugar del Administrador integrado
3. **Dejar de iniciar sesión** con el Administrador integrado para tareas rutinarias
4. La alerta se borrará automáticamente **35 días** después del último inicio de sesión

## P-AdminNum

#### Qué significa

Cuantas más cuentas con privilegios de administrador haya en tu dominio, mayor será la superficie de ataque. Cada cuenta de administrador es un posible punto de entrada para un atacante. Muchas organizaciones terminan con demasiadas cuentas de administrador con el tiempo: acceso temporal que nunca se revocó, cuentas de servicio añadidas a Admins del dominio por conveniencia, etc.

#### Qué comprueba el análisis

El AD Scan cuenta el número total de **usuarios únicos** en todos los grupos privilegiados (Admins del dominio, Admins de la empresa, Administradores, Operadores de cuentas, Operadores de servidor, Operadores de copia de seguridad, etc.). Si el mismo usuario está en varios grupos, se cuenta solo una vez.

La alerta se activa si:

* Más del **10%** de los usuarios activos son privilegiados, O
* Más del **50** existen cuentas privilegiadas

> Esta comprobación se omite para organizaciones pequeñas con menos de 100 usuarios activos.

#### Cómo diagnosticar

```powershell
$privilegedGroups = @(
  "Domain Admins", "Enterprise Admins", "Schema Admins", "Administrators",
  "Account Operators", "Server Operators", "Backup Operators", "Print Operators"
)

$uniqueMembers = @{}
foreach ($group in $privilegedGroups) {
  try {
    Get-ADGroupMember -Identity $group -Recursive |
      Where-Object { $_.objectClass -eq "user" } |
      ForEach-Object { $uniqueMembers[$_.DistinguishedName] = $_.SamAccountName }
  } catch {}
}

$activeUsers = (Get-ADUser -Filter "Enabled -eq `$true" | Measure-Object).Count
$pct = [math]::Round(($uniqueMembers.Count / $activeUsers) * 100, 1)

Write-Host "Cuentas privilegiadas: $($uniqueMembers.Count)"
Write-Host "Usuarios activos: $activeUsers"
Write-Host "Proporción: $pct% (alerta si >10% o >50 cuentas)"
Write-Host ""
$uniqueMembers.Values | Sort-Object | ForEach-Object { Write-Host "  - $_" }
```

#### Cómo solucionarlo

Revisa la lista y elimina las cuentas que realmente no necesiten acceso de administrador:

```powershell
Remove-ADGroupMember -Identity "Domain Admins" -Members "username" -Confirm:$false
```

Buenas prácticas:

* Usa **cuentas administrativas separadas** (`adm_john`) que sean diferentes de las cuentas de uso diario
* **Eliminar cuentas de servicio** de los grupos de administradores, otorgando solo los permisos específicos que necesitan
* **Revisar la pertenencia a grupos privilegiados** de forma regular

## P-ProtectedUsers

#### Qué significa

El **grupo Usuarios Protegidos** es un grupo de seguridad especial introducido en Windows Server 2012 R2. Los miembros de este grupo obtienen protecciones adicionales:

* Pueden **autenticarse solo con Kerberos** (el protocolo más seguro), no con el protocolo NTLM más antiguo
* Sus **credenciales no se almacenan en caché** en las máquinas en las que inician sesión: un atacante que comprometa una estación de trabajo no puede robar sus credenciales de la memoria
* **La delegación está deshabilitada:** su cuenta no puede ser suplantada por servicios

Estas protecciones son críticas para las cuentas de administrador, que son los principales objetivos en la mayoría de los ataques.

#### Qué comprueba el análisis

El AD Scan verifica que todas las **cuentas administrativas habilitadas** (miembros de Admins del dominio, Admins de la empresa, etc.) también sean miembros del **grupo Usuarios Protegidos** grupo.

#### Por qué la alerta puede persistir

* **Los usuarios agregados mediante grupos anidados** pueden no detectarse. Agrega a los usuarios **directamente** al grupo Usuarios Protegidos.
* **Los retrasos de replicación** entre Controladores de Dominio pueden causar inconsistencias temporales.
* **Cuentas de Servicio Administradas (gMSA)** se excluyen de esta comprobación: no necesitan estar en Usuarios Protegidos.

#### Cómo diagnosticar

```powershell
$protectedUsers = (Get-ADGroupMember -Identity "Protected Users").DistinguishedName
$privilegedGroups = @("Domain Admins", "Enterprise Admins", "Schema Admins", "Administrators")

$notProtected = foreach ($group in $privilegedGroups) {
  Get-ADGroupMember -Identity $group -Recursive |
    Where-Object { $_.objectClass -eq "user" } |
    ForEach-Object { Get-ADUser $_ -Properties Enabled } |
    Where-Object { $_.Enabled -and $_.DistinguishedName -notin $protectedUsers }
}

$notProtected | Select-Object -Unique SamAccountName, Name | Format-Table -AutoSize
```

#### Cómo solucionarlo

```powershell
Add-ADGroupMember -Identity "Protected Users" -Members "adm_john", "adm_jane"
```

> **Importante:** Agregar cuentas a Usuarios Protegidos impone **autenticación solo Kerberos**. Algunas aplicaciones heredadas que requieren NTLM podrían dejar de funcionar para estas cuentas. **Prueba primero con una cuenta** antes de añadir a todos los administradores.
>
> Mejor práctica: las cuentas administrativas deben usarse **solo para tareas de administración** (no para correo electrónico, navegación web ni ejecución de aplicaciones empresariales), por lo que la compatibilidad con NTLM rara vez es un problema.

## S-OldNtlm

#### Qué significa

Windows admite varios protocolos de autenticación, desde muy antiguos e inseguros (LM, NTLMv1) hasta modernos y seguros (NTLMv2, Kerberos). Los protocolos más antiguos tienen vulnerabilidades conocidas que los atacantes pueden explotar para capturar y descifrar contraseñas en la red.

El **El nivel de autenticación de LAN Manager** controla qué protocolos se permiten. Debe configurarse en **nivel 5**, lo que significa "aceptar solo NTLMv2, rechazar todos los protocolos anteriores."

#### Qué comprueba el análisis

El AD Scan lee objetos de directiva de grupo (GPO) para verificar que la `LmCompatibilityLevel` configuración esté establecida en **5**. Si ninguna GPO define esta configuración, Windows usa de forma predeterminada **nivel 3**, que todavía acepta algunos protocolos más débiles.

| Nivel | Lo que permite                               | ¿Seguro? |
| ----- | -------------------------------------------- | -------- |
| 0-2   | LM y/o NTLMv1                                | No       |
| 3     | NTLMv2 (pero no rechaza protocolos antiguos) | No       |
| **5** | **Solo NTLMv2, rechaza LM y NTLMv1**         | **Sí**   |

#### Por qué la alerta puede persistir

1. **Cambiaste el registro directamente** en lugar de usar una GPO. El AD Scan lee archivos GPO, no la configuración del registro local. Aunque el DC tenga el valor correcto en el registro, la alerta persiste si no se estableció mediante Directiva de grupo.
2. **GPO en conflicto:** Una GPO establece el nivel 5, pero otra GPO lo sobrescribe con un nivel inferior.
3. **Sin GPO alguna:** Sin ninguna GPO, el valor predeterminado es el nivel 3 (inseguro).

#### Cómo diagnosticar

```powershell
# Comprueba la configuración efectiva en cada DC
Get-ADDomainController -Filter * | ForEach-Object {
  $level = Invoke-Command -ComputerName $_.HostName -ScriptBlock {
    (Get-ItemProperty "HKLM:\System\CurrentControlSet\Control\Lsa" `
      -Name LmCompatibilityLevel -ErrorAction SilentlyContinue).LmCompatibilityLevel
  }
  Write-Host "$($_.HostName): Nivel de compatibilidad LM = $level"
}

# Comprueba qué GPO definen esta configuración
Import-Module GroupPolicy
Get-GPO -All | ForEach-Object {
  [xml]$r = Get-GPOReport -Guid $_.Id -ReportType Xml
  if ($r.InnerXml -match "LmCompatibilityLevel") {
    Write-Host "GPO: $($_.DisplayName)"
  }
}
```

#### Cómo solucionarlo

**A través de la Consola de administración de directivas de grupo (recomendado):**

1. Abra `gpmc.msc`
2. Edita la GPO vinculada a `OU=Domain Controllers`
3. Vaya a: `Configuración del equipo > Directivas > Configuración de Windows > Configuración de seguridad > Directivas locales > Opciones de seguridad`
4. Establece **"Seguridad de red: nivel de autenticación de LAN Manager"** en `Enviar solo respuesta NTLMv2. Rechazar LM y NTLM`
5. Establece **"Seguridad de red: no almacenar el valor hash de LAN Manager en el próximo cambio de contraseña"** en `Habilitado`
6. Ejecute `gpupdate /force` en todos los controladores de dominio

**A través de PowerShell:**

```powershell
$gpoName = "DC - Enforce NTLMv2"
$gpo = Get-GPO -Name $gpoName -ErrorAction SilentlyContinue
if (-not $gpo) { $gpo = New-GPO -Name $gpoName }

Set-GPRegistryValue -Name $gpoName `
  -Key "HKLM\System\CurrentControlSet\Control\Lsa" `
  -ValueName "LmCompatibilityLevel" -Type DWord -Value 5

Set-GPRegistryValue -Name $gpoName `
  -Key "HKLM\System\CurrentControlSet\Control\Lsa" `
  -ValueName "NoLMHash" -Type DWord -Value 1

New-GPLink -Name $gpoName `
  -Target "OU=Domain Controllers,$($(Get-ADDomain).DistinguishedName)" `
  -LinkEnabled Yes
```

## S-AesNotEnabled

#### Qué significa

Cuando te autenticas en Active Directory, tu contraseña se usa para cifrar la comunicación mediante un algoritmo específico. Los algoritmos antiguos (**DES**, **RC4**) son débiles y pueden descifrarse con relativa facilidad. Los algoritmos modernos (**AES-128**, **AES-256**) son mucho más fuertes.

El soporte de AES se introdujo con Windows Server 2008. Sin embargo, las cuentas que existían antes de la actualización, o las cuentas con configuraciones específicas, pueden seguir usando el cifrado antiguo y más débil.

#### Qué comprueba el análisis

Una cuenta se marca en dos situaciones:

1. **La contraseña de la cuenta se estableció antes de que tu dominio se actualizara a Server 2008.** Como las claves de cifrado AES solo se generan cuando se establece una contraseña en un DC moderno, estas contraseñas antiguas solo tienen claves RC4/DES débiles.
2. **La cuenta tiene un Nombre de entidad de servicio (SPN)** y su configuración de cifrado no incluye AES (el `msDS-SupportedEncryptionTypes` atributo no tiene marcas AES).

#### Cómo diagnosticar

```powershell
# Encuentra cuentas de servicio sin soporte de AES
Get-ADUser -Filter 'ServicePrincipalName -like "*"' `
  -Properties ServicePrincipalName, "msDS-SupportedEncryptionTypes", PasswordLastSet |
  Where-Object { ([int]$_."msDS-SupportedEncryptionTypes" -band 24) -eq 0 } |
  Select-Object SamAccountName,
    @{N="EncryptionTypes"; E={$_."msDS-SupportedEncryptionTypes"}},
    PasswordLastSet

# Lo mismo para las cuentas de equipo
Get-ADComputer -Filter 'ServicePrincipalName -like "*"' `
  -Properties "msDS-SupportedEncryptionTypes" |
  Where-Object { ([int]$_."msDS-SupportedEncryptionTypes" -band 24) -eq 0 } |
  Select-Object Name, @{N="EncryptionTypes"; E={$_."msDS-SupportedEncryptionTypes"}}
```

#### Cómo solucionarlo

**Para cuentas con contraseñas antiguas:** Simplemente restablece la contraseña. Esto genera nuevas claves AES:

```powershell
Set-ADAccountPassword -Identity "svc_account" `
  -NewPassword (ConvertTo-SecureString "YourNewStr0ngP@ssw0rd!" -AsPlainText -Force) -Reset
```

**Para cuentas que no tienen configurados cifrados AES:** Habilita AES en los tipos de cifrado de la cuenta:

```powershell
# Habilita AES para una cuenta específica (24 = AES-128 + AES-256)
Set-ADUser -Identity "svc_account" -Replace @{"msDS-SupportedEncryptionTypes" = 24}

# Para una cuenta de equipo
Set-ADComputer -Identity "server01" -Replace @{"msDS-SupportedEncryptionTypes" = 24}

# Corrección masiva para todas las cuentas de servicio sin AES
Get-ADUser -Filter 'ServicePrincipalName -like "*"' `
  -Properties "msDS-SupportedEncryptionTypes" |
  Where-Object { ([int]$_."msDS-SupportedEncryptionTypes" -band 24) -eq 0 } |
  ForEach-Object {
    Set-ADUser $_ -Replace @{"msDS-SupportedEncryptionTypes" = 24}
    Write-Host "AES habilitado para $($_.SamAccountName)"
  }
```

> **Nota:** Habilitar AES no es destructivo: la autenticación existente continúa funcionando. Sin embargo, prueba con servicios críticos antes de aplicarlo de forma masiva.

## A-NoGPOLLMNR

#### Qué significa

**LLMNR** (Resolución de nombres multicast local de enlace) es un protocolo que Windows usa para encontrar otros equipos en la red cuando DNS no tiene la respuesta. Funciona enviando una pregunta a todos los equipos cercanos: "¿Alguien sabe dónde está `nombre del servidor` está?"

El problema es: un atacante en la misma red puede **responder a estas transmisiones haciéndose pasar por el servidor objetivo**, engañando a la víctima para que envíe sus credenciales al atacante. Esto se llama un **envenenamiento LLMNR** ataque y es una de las técnicas más comunes utilizadas durante ataques a redes internas.

LLMNR es un protocolo heredado que las redes modernas no necesitan (DNS se encarga de todo). Debe deshabilitarse mediante Directiva de grupo.

#### Qué comprueba el análisis

El AD Scan busca una **GPO habilitada y vinculada** que deshabilita LLMNR al establecer el valor de registro `EnableMulticast` en `0`.

#### Por qué la alerta puede persistir

1. **La GPO existe pero no está vinculada** a ninguna OU.
2. **La GPO está deshabilitada**, aunque esté vinculada.
3. **LLMNR se deshabilitó manualmente** (mediante el registro o `netsh`) pero no mediante Directiva de grupo. El AD Scan lee archivos GPO, no la configuración local de la máquina.

#### Cómo diagnosticar

```powershell
Import-Module GroupPolicy
Get-GPO -All | ForEach-Object {
  [xml]$r = Get-GPOReport -Guid $_.Id -ReportType Xml
  if ($r.InnerXml -match "EnableMulticast") {
    Write-Host "GPO '$($_.DisplayName)' - Estado: $($_.GpoStatus) - Contiene la configuración de LLMNR"
  }
}
```

#### Cómo solucionarlo

```powershell
$gpoName = "Deshabilitar LLMNR"
$gpo = Get-GPO -Name $gpoName -ErrorAction SilentlyContinue
if (-not $gpo) { $gpo = New-GPO -Name $gpoName }

Set-GPRegistryValue -Name $gpoName `
  -Key "HKLM\Software\Policies\Microsoft\Windows NT\DNSClient" `
  -ValueName "EnableMulticast" -Type DWord -Value 0

# Vincúlala a la raíz del dominio para que se aplique a todos los equipos
New-GPLink -Name $gpoName `
  -Target (Get-ADDomain).DistinguishedName `
  -LinkEnabled Yes
```

Después de vincular la GPO, ejecuta `gpupdate /force` en las máquinas o espera al siguiente ciclo de actualización de Directiva de grupo (normalmente 90 minutos).

## Preguntas frecuentes

#### La alerta sigue apareciendo después de aplicar la solución. ¿Por qué?

El AD Scan no se ejecuta periódicamente. Después de aplicar una solución, necesitas **ejecutar el script de nuevo** para que la alerta desaparezca. Si la alerta persiste después de un nuevo escaneo, probablemente la solución fue parcial. Consulta la sección "Por qué la alerta puede persistir" de la vulnerabilidad correspondiente. Asegúrate de leer los detalles de la vulnerabilidad dentro de tu informe; a menudo contiene detalles sobre los activos afectados.

#### ¿Necesito derechos de Domain Admin para ejecutar el escaneo?

Algunas vulnerabilidades (p. ej., A-NoServicePolicy) requieren permisos elevados para leer ciertos objetos de AD. Ejecutar el escaneo con una **cuenta de Domain Admin** garantiza que todos los objetos sean visibles y evita falsas alertas causadas por permisos insuficientes. Si no es posible, aún puede ejecutar el script como un simple usuario de dominio, aunque algunas vulnerabilidades pueden aparecer debido a la falta de visibilidad sobre los objetos de AD.

#### Arreglé una vulnerabilidad, pero apareció una nueva. ¿Es eso normal?

Sí. Algunas correcciones pueden revelar otros problemas. Por ejemplo, instalar LAPS (corrigiendo A-LAPS-Not-Installed) puede activar A-LAPS-Joined-Computers si los objetos de equipo tienen permisos inadecuados. Esto es esperado: revise cada alerta en orden de gravedad.


---

# 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://docs.stoik.io/cyber-best-practices/es/guias-de-remediacion-de-vulnerabilidades/ad-scan-vulnerability-remediation-guide.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.
