jueves, 22 de enero de 2026

WINDOWS. Seguridad. Consejo. Cuenta importante

 

En las propiedades de los usuarios podemos encontrar la siguiente característica “la cuenta es importante y no se puede delegar”


Por seguridad, se debería activar para todas las cuentas privilegiadas o que tengan permisos especiales, ya que: 

  • Una cuenta privilegiada NO es una cuenta personal
  • Delegar una cuenta privilegiada es abrir la puerta al desastre
  • Las cuentas privilegiadas deben usarse SOLO para tareas privilegiadas

Activar ese tip es una forma de reforzar una idea clave: Una cuenta privilegiada no es una herramienta compartida, es un activo crítico que requiere control absoluto, uso limitado y responsabilidad individual.


by GoN | Published: Jan 2026 | Last Updated:

miércoles, 21 de enero de 2026

WINDOWS. PS IOC


 Propósito

Dada una palabra o un ejecutable, buscar un IOC (Indicador de compromiso) en un Host.

Introduces las palabras clave y el script analiza:

  • Procesos
  • Servicios
  • Tareas programadas
  • Carpetas sospechosas
  • Claves RUN / RUNONCE
  • Servicios en el registro
  • Búsqueda de binarios en AppData / Temp
  • Exportación CSV
  • Programas instalado
  • Ejecución en RAM

·         Startup del usuario y del sistema


Pasos

Para ejecutar: powershell.exe -ExecutionPolicy Bypass -File .\BuscasIOC.ps1

<#

    Detect-Strings-Extended.ps1

    Autor: Guillermo

    Objetivo:

        Script INFORMÁTICO que analiza el equipo para encontrar cualquier rastro

        de cadenas sospechosas en:

 

            • Programas instalados

            • Procesos en RAM

            • Servicios

            • Tareas programadas

            • Carpetas sospechosas

            • Entradas en RUN / RUNONCE

            • Servicios en el Registro

            • Archivos en AppData / Temp

            • Programas configurados en el inicio de Windows

 

        NO modifica nada. NO detiene nada. NO elimina nada.

#>

 

Write-Host "======================================================" -ForegroundColor Cyan

Write-Host "   ANALIZADOR DE INDICADORES - MODO INFORMATIVO"       -ForegroundColor Cyan

Write-Host "======================================================" -ForegroundColor Cyan

 

# 1) Pedir cadenas al usuario

$input = Read-Host "Introduce las cadenas a buscar (separadas por coma). Ej: updater, malware, test"

$patterns = $input.Split(",") | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne "" }

 

if ($patterns.Count -eq 0) {

    Write-Host "No se han introducido cadenas. Saliendo..." -ForegroundColor Red

    exit

}

 

Write-Host "`nCadenas a buscar:" -ForegroundColor Yellow

$patterns | ForEach-Object { Write-Host " - $_" -ForegroundColor Green }

 

# Convertir a regex OR

$regex = ($patterns -join "|")

 

$results = New-Object System.Collections.Generic.List[object]

 

function Add-Result($Tipo,$Ruta,$Detalle) {

    $results.Add([pscustomobject]@{

        Tipo    = $Tipo

        Ruta    = $Ruta

        Detalle = $Detalle

    })

}

 

# =====================================================================

# [0] PROGRAMAS INSTALADOS (Add/Remove Programs)

# =====================================================================

Write-Host "`n========== [0] PROGRAMAS INSTALADOS ==========" -ForegroundColor Cyan

 

$installedApps = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*, `

                                  HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*, `

                                  HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* `

                    -ErrorAction SilentlyContinue

 

foreach ($app in $installedApps) {

    if ($app.DisplayName -match $regex) {

        Add-Result "Programa Instalado" $app.DisplayName $app.DisplayVersion

        Write-Host "Programa detectado: $($app.DisplayName)" -ForegroundColor Green

    }

}

 

# =====================================================================

# [1] PROCESOS

# =====================================================================

Write-Host "`n========== [1] PROCESOS ==========" -ForegroundColor Cyan

Get-Process -ErrorAction SilentlyContinue |

    Where-Object { $_.Name -match $regex } |

    ForEach-Object {

        Add-Result "Proceso" ($_.Path) ($_.Name)

        $_

    }

 

# =====================================================================

# [2] SERVICIOS

# =====================================================================

Write-Host "`n========== [2] SERVICIOS ==========" -ForegroundColor Cyan

Get-Service -ErrorAction SilentlyContinue |

    Where-Object { $_.Name -match $regex -or $_.DisplayName -match $regex } |

    ForEach-Object {

        Add-Result "Servicio" $_.Name $_.DisplayName

        $_

    }

 

# =====================================================================

# [3] TAREAS PROGRAMADAS

# =====================================================================

Write-Host "`n========== [3] TAREAS PROGRAMADAS ==========" -ForegroundColor Cyan

Get-ScheduledTask -ErrorAction SilentlyContinue |

    Where-Object { $_.TaskName -match $regex -or $_.Description -match $regex } |

    ForEach-Object {

        Add-Result "Tarea Programada" $_.TaskName $_.Description

        $_

    }

 

# =====================================================================

# [4] CARPETAS HABITUALES

# =====================================================================

Write-Host "`n========== [4] CARPETAS HABITUALES ==========" -ForegroundColor Cyan

$paths = @(

    "$env:LOCALAPPDATA",

    "$env:LOCALAPPDATA\Programs",

    "$env:APPDATA",

    "$env:TEMP",

    "$env:ProgramFiles",

    "$env:ProgramFiles(x86)"

)

 

foreach ($base in $paths) {

    if (Test-Path $base) {

        Get-ChildItem $base -Recurse -ErrorAction SilentlyContinue |

            Where-Object { $_.Name -match $regex } |

            ForEach-Object {

                Add-Result "Archivo/Carpeta" $_.FullName "Coincidencia en nombre"

                Write-Host "Encontrado: $($_.FullName)" -ForegroundColor Green

            }

    }

}

 

# =====================================================================

# [5] RUN / RUNONCE

# =====================================================================

Write-Host "`n========== [5] RUN / RUNONCE ==========" -ForegroundColor Cyan

$runKeys = @(

    "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run",

    "HKCU:\Software\Microsoft\Windows\CurrentVersion\RunOnce",

    "HKLM:\Software\Microsoft\Windows\CurrentVersion\Run",

    "HKLM:\Software\Microsoft\Windows\CurrentVersion\RunOnce"

)

 

foreach ($rk in $runKeys) {

    if (Test-Path $rk) {

        $vals = Get-ItemProperty $rk -ErrorAction SilentlyContinue

        foreach ($prop in $vals.PSObject.Properties) {

            if ($prop.Name -notlike "PS*" -and (

                $prop.Name -match $regex -or ($prop.Value -as [string]) -match $regex

            )) {

                Add-Result "RunKey" $rk "$($prop.Name) = $($prop.Value)"

                Write-Host "[RUN] $rk → $($prop.Name) = $($prop.Value)" -ForegroundColor Green

            }

        }

    }

}

 

# =====================================================================

# [6] SERVICIOS DEL REGISTRO

# =====================================================================

Write-Host "`n========== [6] SERVICIOS DEL REGISTRO ==========" -ForegroundColor Cyan

Get-ChildItem "HKLM:\SYSTEM\CurrentControlSet\Services" -ErrorAction SilentlyContinue |

    Where-Object { $_.Name -match $regex } |

    ForEach-Object {

        Add-Result "RegistroServicio" $_.Name "Coincidencia en nombre de clave"

        $_.Name

    }

 

# =====================================================================

# [7] INICIO DE WINDOWS (Startup)

# =====================================================================

Write-Host "`n========== [7] PROGRAMAS EN EL INICIO ==========" -ForegroundColor Cyan

 

$startupPaths = @(

    "$env:APPDATA\Microsoft\Windows\Start Menu\Programs\Startup",

    "$env:ProgramData\Microsoft\Windows\Start Menu\Programs\Startup"

)

 

foreach ($sp in $startupPaths) {

    if (Test-Path $sp) {

        Get-ChildItem $sp -ErrorAction SilentlyContinue |

            Where-Object { $_.Name -match $regex } |

            ForEach-Object {

                Add-Result "Inicio Windows" $_.FullName "Coincidencia en acceso directo"

                Write-Host "En inicio: $($_.FullName)" -ForegroundColor Yellow

            }

    }

}

 

# =====================================================================

# [8] BINARIOS EN APPDATA / TEMP

# =====================================================================

Write-Host "`n========== [8] BINARIOS APPDATA / TEMP ==========" -ForegroundColor Cyan

$binroots = @("$env:LOCALAPPDATA","$env:APPDATA","$env:TEMP")

 

foreach ($br in $binroots) {

    if (Test-Path $br) {

        Get-ChildItem $br -Recurse -ErrorAction SilentlyContinue |

            Where-Object { $_.Name -match $regex } |

            ForEach-Object {

                Add-Result "Binario" $_.FullName "Coincidencia en nombre"

                Write-Host "Binario detectado: $($_.FullName)" -ForegroundColor Green

            }

    }

}

 

# =====================================================================

# RESUMEN + EXPORTACIÓN

# =====================================================================

 

Write-Host "`n==============================================" -ForegroundColor Cyan

Write-Host "                 RESUMEN" -ForegroundColor Cyan

Write-Host "==============================================" -ForegroundColor Cyan

 

$results | Format-Table -AutoSize

 

# Nombre con fecha y hora

$timestamp = (Get-Date).ToString("yyyy-MM-dd_HH-mm-ss")

$output = "C:\Temp\Deteccion-Resultado_$timestamp.csv"

 

New-Item -ItemType Directory -Path (Split-Path $output) -Force | Out-Null

$results | Export-Csv -Path $output -NoTypeInformation -Encoding UTF8

 

Write-Host "`nArchivo exportado: $output" -ForegroundColor Yellow

Write-Host "`n--- ANÁLISIS FINALIZADO ---" -ForegroundColor Cyan

 






by GoN | Published: Jan 2026 | Last Updated:

WINDOWS. Security. LAPS

 


    Propósito

    El objetivo este post es explicar un poco como implantar una configuración de Microsoft LAPS.
    Microsoft LAPS (Local Administrator Password Solution) es una herramienta de Microsoft diseñada para gestionar automáticamente las contraseñas de las cuentas de administrador local en equipos Windows dentro de un dominio.
    Esto solo son algunas de las muchas opciones que hay para gestionar una implantación de este tipo.
    Usa la información oficial de Microsoft para hacer este proceso. Este post úsalo de apoyo y consulta por si tienes alguna duda o problema.
    Antes de ponerlo en un entorno de producción valídalo en un entorno de pruebas.
    Aplicar una configuración de LAPS sin conocimiento y todas las garantías de éxito podría tener un impacto en las infraestructuras.
    Revisa el documento completo antes de empezar y su puedes contrástalo con Microsoft por si han habido cambios.
    Pasos

    Para que funcione LAPS hay que tener en cuenta varios fases

    [01] Preparar el AD
    [02] Asignar configurar las OU
    [03] Script para consultar la OU autorizadas por LAPS
    [04] Check cuantos computers han entrado en LAPS
    [05] Laps Diagnosticos
    [06] Como comprobar si un PC tiene LAPS
    [07] GPO
    [08] Notas

[01] Preparar el AD

Debemos tener la plantilla preparada para la gestión del LAPS:

Copy from:

C:\Windows\PolicyDefinitions\LAPS.admx

C:\Windows\PolicyDefinitions\<language>\LAPS.adml

 

Copy to:

\\<domain>\SYSVOL\<domain>\Policies\PolicyDefinitions\

\\<domain>\SYSVOL\<domain>\Policies\PolicyDefinitions\<language>\

Verifica que el esquema de AD tiene los atributos del nuevo LAPS

Ejecuta en tu DC:

COMANDO: Get-ADObject -SearchBase "CN=Schema,CN=Configuration,DC=Midomino,DC=com" -LDAPFilter "(lDAPDisplayName=msLAPS-EncryptedPassword)"


COMANDO: Get-ADObject -SearchBase (Get-ADRootDSE).schemaNamingContext -LDAPFilter "(|(name=*laps*)(name=*admPwd*))" | Select-Object name

Si no lo tiene hay que prepararlo 

Es recomendable que el usuario que lo vaya a configurar pertenezca a los grupos:

·         Scheme Administrator /      Organization Administrator       

     Para que la configuración no de problemas se debe hacer desde un Controlador de Dominio que tenga el módulo de LAPS instalado.

ç     Empezamos. NO debes ejecutarlo si:

  • El esquema ya fue actualizado previamente (solo se hace una vez por bosque).

  • Tu dominio ya tiene los atributos de LAPS nuevo (Windows Server 2019/2022 + actualizaciones ya los incluyen).

  • Estás usando LAPS Legacy (el antiguo) y no piensas migrar.

     Esta configuración podría cambiar en función a la evolución que de Microsoft a este servicio. Mucho cuidado en configurar el LAPS sin haber tenido en cuenta los puntos anteriores.

      Preparamos el AD

       C:\> Update-LapsADSchema


Debemos crear 2 nuevos grupos de usuarios, uno que solo podrá leer las contraseñas y otro para gestionar el LAPS

[] Permiso de lectura

COMMAND: PS C:\> Set-LapsADReadPasswordPermission -Identity "OU=LAPS,DC=midominio,DC=com" -AllowedPrincipals @("laps\LapsPasswordReadersGroup")

[] Permitir acceso a contraseñas cifradas (Password Encryption Allowed Principals)

Para visualizar contraseñas cuando LAPS está configurado con cifrado, los usuarios deben pertenecer a un grupo autorizado.

COMMAND: Set-LapsADPasswordEncryptionAllowedPrincipals -Identity "OU=LAPS,DC=midominio,DC=com" -AllowedPrincipals "Domain Admins","Grupo_Laps_Management"

Members of the Domain Admins group already have password query permission by default.

[] Consultar permisos extendidos (Query Extended Rights Permissions)

Este comando permite verificar qué grupos o usuarios tienen permisos avanzados sobre la OU, incluyendo lectura de contraseñas y escritura de atributos gestionados por LAPS.

COMMAND: Find-LapsADExtendedRights -Identity "OU=LAPS,DC=midominio,DC=com"


Command: PS C:\> Import-Module LAPS


Hay que autorizar a un grupo del AD de usuarios para poder leer las contraseñas del LAPS


[02] Asignar configurar las OU

Este será el día a día cuando debamos modificarlo

En cada OU que queramos que se le aplique la GPO hay que autorizarla por comandos


Grupo con permisos de LAPS: GG_Laps_Management_PCs


# VERIFICAR PERMISOS
Find-LapsADExtendedRights -Identity "OU=Standard,OU=Computers,OU=Tier2,DC=MiDominio,DC=com"



#Asigna LAPS A UNA OU. Permitir que los equipos escriban su contraseña
Set-LapsADComputerSelfPermission -Identity "OU=Standard,OU=Computers,OU=Tier2,DC=MiDominio,DC=com"

Aquí aplico permisos de dos maneras, solo funcionará una en función como tengas configurado el LAPS (antiguo o moderno)

#LAPS OLD
Set-LapsADReadPasswordPermission -Identity "OU=Standard,OU=Computers,OU=Tier2,DC=MiDominio,DC=com" -AllowedPrincipals "MiDominio\GG_Laps_Management_PCs"



# LAPS NEW - CIFRADAS
Set-LapsADPasswordEncryptionAllowedPrincipals -Identity "OU=Standard,OU=Computers,OU=Tier2,DC=MiDominio,DC=com" -AllowedPrincipals "MiDominio\GG_Laps_Management_PCs"

# VERIFICAR PERMISOS
Find-LapsADExtendedRights -Identity "OU=Standard,OU=Computers,OU=Tier2,DC=MiDominio,DC=com"


Apunte, solo aplicas permisos en OU=Standard, entonces:
  • Sub1 NO tiene permisos LAPS
  • Sub2 NO tiene permisos LAPS
  • Sub3 NO tiene permisos LAPS
A menos que ejecutes los comandos también en ellas.

[03] Script para consultar la OU autorizadas por LAPS

Se recorre el AD y mira todas las OU, saca las que con el comando anterior han sido autorizadas

Import-Module ActiveDirectory

 

# GUID del atributo específico

$lapsEncryptedGuid = [guid]"f3531ec6-6330-4f8e-8d39-7a671fbac605"

 

# Obtener todas las OUs del dominio

$OUs = Get-ADOrganizationalUnit -Filter *

 

$ousWithWritePermission = foreach ($OU in $OUs) {

    # Leer ACL de la OU usando ADSI

    $entry = [ADSI]"LDAP://$($OU.DistinguishedName)"

    $acl = $entry.ObjectSecurity

 

    # Filtrar ACEs con WriteProperty sobre el GUID específico

    $writeAce = $acl.Access | Where-Object {

        ($_.ActiveDirectoryRights -band [System.DirectoryServices.ActiveDirectoryRights]::WriteProperty) -and

        $_.ObjectType -eq $lapsEncryptedGuid

    }

 

    if ($writeAce) {

        foreach ($ace in $writeAce) {

            [PSCustomObject]@{

                OU        = $OU.DistinguishedName

                Trustee   = $ace.IdentityReference

                Inherited = $ace.IsInherited

            }

        }

    }

}

 

# Mostrar lista única de OUs con permisos WRITE

if ($ousWithWritePermission) {

    $ousWithWritePermission |

        Sort-Object OU -Unique |

        Format-Table -AutoSize

} else {

    Write-Output "No se encontraron OUs con permisos WRITE sobre ms-LAPS-Encrypted-Password-Attributes."

}





Otra opcion

Comando: Get-ADObject -SearchBase (Get-ADRootDSE).schemaNamingContext -LDAPFilter "(name=*LAPS*)"




[04] Check cuantos computers han entrado en LAPS

Se verifica los PCs que tiene algo dentro de la contraseña de LAPS

 Write-Host "Ejecutando v3.1..."

Write-Host "Hay que asegurarse que las OUs donde hay equipos LAPS este autorizadas con: Set-LapsADComputerSelfPermission y que recorre todas las Sub-OUS, este proceso puede durar varios minutos. "

# --- Configuración ---

$ou = "OU=Equipos,DC=midominio,DC=com"

# Fecha y hora para el nombre del archivo

$timestamp = Get-Date -Format "yyyyMMdd_HHmm"

$csvPath = "C:\scripts\Computer_LAPS_with_assigned_passwd_$timestamp.csv"

 # --- Obtener equipos de la OU ---

$computers = Get-ADComputer -SearchBase $ou -Filter * -Properties Description, MemberOf, DistinguishedName

 # --- Lista de resultados ---

$resultados = @()

 foreach ($computer in $computers) {

    try {

        # Intenta obtener la contraseña con el nuevo esquema de LAPS

        $laps = Get-LapsADPassword -Identity $computer.Name -ErrorAction Stop

         if ($laps) {

            # Obtener OU desde el DN

            $computerOU = ($computer.DistinguishedName -split ",",2)[1]

             # Obtener grupos del AD

            $groups = $computer.MemberOf | ForEach-Object {

                ($_ -split ",")[0] -replace "^CN="

            }

             $resultados += [PSCustomObject]@{

                ComputerName = $computer.Name

                Description  = $computer.Description

                OU           = $computerOU

                ADGroups     = ($groups -join ";")

                PasswordSet  = $true

                Expiration   = $laps.ExpirationTimestamp

            }

        }

    }

    catch {

        # No se añade a la lista

    }

}

 # --- Exportar a CSV ---

$resultados | Export-Csv -Path $csvPath -NoTypeInformation -Encoding UTF8

 Write-Host "Archivo CSV generado correctamente: $csvPath"

Write-Host "Total de filas exportadas: $($resultados.Count)"

 





[05] Laps Diagnosticos

COMANDO: Get-LapsDiagnostics

Get-LapsDiagnostics: all data for this run was written to the following zip file:

 C:\Users\R\AppData\Local\Temp\LapsDiagnostics\LapsDiagnostics_DC_2025122312_155158.zip



[06] Como comprobar si un PC tiene LAPS

COMANDO: Get-ADComputer PC001 -Properties msLAPS-PasswordExpirationTime, msLAPS-EncryptedPassword


Si esos atributos tienen valores, LAPS está aplicado y funcionando.

Si aparecen vacíos o null, el equipo no ha aplicado la GPO o no ha podido escribir en AD.


[07] GPO











[08] Script interesante 


Detecta TODAS las OUs donde LAPS está realmente aplicado
Comprueba permisos LAPS (lectura, cifrado, self‑permission)
Detecta inconsistencias
Genera un informe claro en pantalla

Write-Host "=== AUDITORIA LAPS EN OUs CON EQUIPOS ===" -ForegroundColor Cyan

# Ruta del script para guardar el CSV en la misma carpeta
$scriptPath = Split-Path -Parent $MyInvocation.MyCommand.Path

# Fecha y hora para el archivo
$timestamp = (Get-Date).ToString("yyyyMMdd_HHmm")

# Detectar atributos disponibles en el esquema
$schema = (Get-ADObject -SearchBase (Get-ADRootDSE).schemaNamingContext -LDAPFilter "(objectClass=attributeSchema)" -Properties lDAPDisplayName).lDAPDisplayName

$hasNewLAPS = $schema -contains "msLAPS-PasswordExpirationTime"
$hasLegacyLAPS = $schema -contains "ms-Mcs-AdmPwdExpirationTime"

Write-Host "Atributos detectados:" -ForegroundColor Yellow
Write-Host " - Windows LAPS: $hasNewLAPS"
Write-Host " - LAPS Legacy: $hasLegacyLAPS"
Write-Host ""

# Construir lista de propiedades validas
$props = @()
if ($hasNewLAPS) { $props += "msLAPS-PasswordExpirationTime" }
if ($hasLegacyLAPS) { $props += "ms-Mcs-AdmPwdExpirationTime" }

# Obtener todas las OUs
$OUs = Get-ADOrganizationalUnit -Filter *

$results = @()
$OUsSinPermisos = @()
$OUsPeligrosas = @()

foreach ($ou in $OUs) {

    $ouDN = $ou.DistinguishedName

    # Obtener equipos de la OU
    try {
        $computers = Get-ADComputer -Filter * -SearchBase $ouDN -Properties $props -ErrorAction Stop
    }
    catch {
        continue
    }

    # Saltar OUs sin equipos
    if ($computers.Count -eq 0) { continue }

    # 1. Intentar obtener permisos LAPS sin romper el script
    try {
        $rights = Find-LapsADExtendedRights -Identity $ouDN -ErrorAction Stop
    }
    catch {
        $rights = $null
    }

    # 2. Detectar si hay equipos con atributos LAPS
    $lapsActive = $false
    foreach ($c in $computers) {
        foreach ($p in $props) {
            if ($c.$p) { $lapsActive = $true; break }
        }
        if ($lapsActive) { break }
    }

    # 3. SELF permission
    $selfPermission = $false
    if ($rights) {
        if ($rights.ExtendedRightHolders -match "SELF") { $selfPermission = $true }
    }

    # 4. Detectar automaticamente todos los grupos con permisos LAPS
    $gruposLAPS = @()
    if ($rights) {
        foreach ($g in $rights.ExtendedRightHolders) {
            if ($g -notmatch "SELF") {
                $gruposLAPS += $g
            }
        }
    }

    # Registrar OUs sin permisos correctos
    if (-not $selfPermission -or $gruposLAPS.Count -eq 0) {
        $OUsSinPermisos += $ouDN
    }

    # Registrar OUs con demasiados grupos (riesgo)
    if ($gruposLAPS.Count -gt 3) {
        $OUsPeligrosas += $ouDN
    }

    # Resultado
    $results += [PSCustomObject]@{
        OU = $ouDN
        PermisosLAPS = if ($rights) { "Si" } else { "No" }
        SELF = if ($selfPermission) { "Si" } else { "No" }
        GruposConPermisos = if ($gruposLAPS.Count -gt 0) { ($gruposLAPS -join "; ") } else { "Ninguno" }
        EquiposConLAPS = if ($lapsActive) { "Si" } else { "No" }
        NumeroEquipos = $computers.Count
    }
}

# Mostrar tabla
$results | Sort-Object OU | Format-Table -AutoSize

# Exportar CSV en la misma carpeta del script
$exportPath = "$scriptPath\LAPS_Auditoria_$timestamp.csv"
$results | Sort-Object OU | Export-Csv $exportPath -NoTypeInformation -Encoding UTF8

Write-Host "`nCSV exportado en: $exportPath" -ForegroundColor Green

# Mostrar recomendaciones al final
Write-Host ""
Write-Host "=== RECOMENDACIONES ===" -ForegroundColor Cyan

Write-Host "`n1) OUs sin permisos LAPS correctos:" -ForegroundColor Yellow
if ($OUsSinPermisos.Count -eq 0) {
    Write-Host " - Todas las OUs estan correctamente configuradas."
} else {
    $OUsSinPermisos | ForEach-Object { Write-Host " - $_" }
}

Write-Host "`n2) Como aplicar permisos LAPS a todas las OUs con PCs:" -ForegroundColor Yellow
Write-Host "   Set-LapsADComputerSelfPermission -Identity <OU>"
Write-Host "   Set-LapsADReadPasswordPermission -Identity <OU> -AllowedPrincipals <GrupoLectura>"
Write-Host "   Set-LapsADPasswordEncryptionAllowedPrincipals -Identity <OU> -AllowedPrincipals <GrupoLectura>"

Write-Host "`n3) OUs con permisos peligrosos (demasiados grupos con acceso):" -ForegroundColor Yellow
if ($OUsPeligrosas.Count -eq 0) {
    Write-Host " - No se han detectado OUs con exceso de grupos."
} else {
    $OUsPeligrosas | ForEach-Object { Write-Host " - $_" }
}

Write-Host "`n=== FIN DE AUDITORIA ===" -ForegroundColor Cyan




[09] Notas

Para acceder a las estaciones de trabajo con LAPS, solo los administradores locales deben tener acceso. Los administradores de dominio lo deben tener prohibido. 

No debería haber un usuario con contraseña común en más de un PC.

Sería recomendable renombrar por GPO el administrador local.

Sería recomendable, hacer una exportación cada 15 días de las contraseñas, en un lugar seguro, con contraseña y cifrado. Por si hay algún problema poder consultarla.

Solo los usuarios que den soporte deberían poder consultar la contraseña, siempre elevándose con un usuario privilegiado especial.

Se debería auditar todos los accesos que consulten las contraseñas de LAPS.

Pendiente un Script semanal comprobando si hay algún Host en el dominio que aún no se le aplique el LAPS que se ejecute al menos una vez a la semana.


by GoN | Published: Jan 2026 | Last Updated Mar 2026: