Mostrando entradas con la etiqueta GPO. Mostrar todas las entradas
Mostrando entradas con la etiqueta GPO. Mostrar todas las entradas

jueves, 16 de abril de 2026

WINDOWS. GPO. Grupo administradores locales

 Propósito


Hacer un GPO que se aplique en las estaciones de trabajo y que elimine/vacíe todos los usuarios y grupos  que hay en el grupo de administradores locales, y en este caso solo deje al usuario administrador local del PC. 
 
Yo tengo combinada esta GPO con el LAPS para reforzar su seguridad, junto con la GPO que los administradores de dominio no pueden hacer logon en los PCs.

Pasos


Las GPO se aplican cada 90 minutos, si alguien consiguiese añadirse al grupo de administradores locales del PC, a los 90 minutos se borraría.


by GoN | Published: April 2026 | Last Updated:

miércoles, 15 de abril de 2026

WINDOWS. GPO. Denegar logon y RDP a los administradores de dominio en las estaciones de trabajo

 

Siguiendo las BP, vamos a crear una GPO que bloquea el acceso de los administradores de dominio para que puedan hacer RDP o logon en los PCS, así evitamos movimientos laterales y que la contraseña de un administrador se pueda quedar en el cache de alguna estación de trabajo.


Como seguro, para evitar impactos no deseado, por si se mete en la OU un servidor o se asigna la GPO a una OU de Servidores, añado un filtro para que solo se aplique a estaciones de trabajo.






Con que combinarlo: Yo tengo LAPS en todos los PCs, es una red de unos 1000 PCs, el único usuario que tiene permisos de administrador en los PCs es el administrador local, si lo unimos a lo que comento en este artículo y los tenemos bien parcheados el nivel de protección en nuestros PCs se incrementa considerablemente.

by GoN | Published: April 2026 | Last Updated:
 

sábado, 14 de marzo de 2026

WINDOWS. PS. Hosts sin conectar al dominio.

 Propósito

Una opción más para mantener nuestro Active Directory al día es asegurarnos de que no existan equipos que ya no estén en uso. Deberíamos procurar que los PCs estén lo más actualizados posible: últimas actualizaciones, parches, configuraciones de seguridad (GPOs), patrones de antivirus, etc. Además, un equipo que no se conecta o que ya no está activo sigue consumiendo licencias innecesariamente.

Para tener un control mínimo, he preparado este script que se ejecuta una vez por semana y informa de los equipos que llevan más de 30 y 60 días sin contactar con nuestro AD.

Pasos

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

#  VARIABLES DEL USUARIO

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

$SMTPServer = "smtp.com"

$SMTPPort   = 25

$From       = "HelpDesk@Miempresa.com"

$To         = "alertas@Miempresa.com"

$Subject    = "OU Computers que llevan tiempo sin conectar"

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

#  CONFIGURACIÓN

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

Import-Module ActiveDirectory

 

$Hoy = (Get-Date)

$Dias30 = $Hoy.AddDays(-30)

$Dias60 = $Hoy.AddDays(-60)

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

#  OBTENER EQUIPOS AD

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

$Equipos = Get-ADComputer -Filter * -Properties Description, LastLogonTimestamp, CanonicalName |

    Select-Object Name,

                  Description,

                  @{Name="OU";Expression={($_.CanonicalName -replace "^[^/]+/","")}},

                  @{Name="LastLogon";Expression={[DateTime]::FromFileTime($_.LastLogonTimestamp)}}

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

#  FILTRADOS

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

$Entre30y60 = $Equipos | Where-Object { $_.LastLogon -le $Dias30 -and $_.LastLogon -gt $Dias60 }

$Mas60      = $Equipos | Where-Object { $_.LastLogon -le $Dias60 }

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

#  GENERAR TABLAS HTML

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

function Convert-ToHtmlTable {

    param($Data, $Titulo)

 

    if ($Data.Count -eq 0) {

        return "<h3>$Titulo</h3><p>No hay equipos en este rango.</p>"

    }

 

    $Data | Select-Object Name, Description, OU, LastLogon |

        ConvertTo-Html -Fragment -PreContent "<h3>$Titulo</h3>"

}

 $Html30_60 = Convert-ToHtmlTable -Data $Entre30y60 -Titulo "Equipos sin conectar entre 30 y 60 dias"

$Html60    = Convert-ToHtmlTable -Data $Mas60 -Titulo "Equipos sin conectar mas de 60 dias"

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

#  EMAIL HTML

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

$Body = @"

<html>

<head>

<style>

table { border-collapse: collapse; width: 100%; }

th, td { border: 1px solid #999; padding: 6px; text-align: left; }

th { background-color: #f2f2f2; }

h3 { font-family: Arial; }

</style>

</head>

<body>

<h2>Informe de equipos que llevan tiempo sin conectar</h2>

<p>Generado desde SRVDC04 $(Get-Date -Format "dd/MM/yyyy HH:mm")</p>

 

$Html30_60

<br>

$Html60

 

</body>

</html>

"@

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

#  ENVÍO DEL EMAIL

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

Send-MailMessage -From $From -To $To -Subject $Subject -Body $Body -BodyAsHtml `

    -SmtpServer $SMTPServer -Port $SMTPPort


El resultado vendría a ser un email así: 



by GoN | Published: Mar 2026 | Last Updated:

 

martes, 3 de marzo de 2026

WINDOWS. GPO. Reinicio rapido de Windows.

Propósito

Qué hace realmente el Inicio rápido y por qué afecta a las GPO
Cuando el Inicio rápido está activado, Windows no realiza un apagado completo. En su lugar:
  • Cierra la sesión del usuario.
  • Hiberna el kernel y los drivers.
  • Guarda el estado en hiberfil.sys.
  • Al encender, no ejecuta un arranque completo, sino una restauración parcial.
Esto implica:
  • No se procesan todas las GPO de equipo.
  • No se ejecutan scripts de Startup.
  • No se reinician servicios críticos.
  • No se aplican extensiones de GPO que requieren arranque completo (por ejemplo, ciertas configuraciones de seguridad, firewall, drivers, etc.).
En cambio, un reinicio sí hace un arranque completo y aplica todas las GPO.

Por eso, si lo que queremos es apagar/encender = reiniciar, debemos desactivar el Inicio rápido.

Pasos

Crear una GPO "FastStartup_Disable"




                                                                                        by GoN | Published: Mar 2026 | Last Updated:

martes, 10 de febrero de 2026

WINDOWS. GPO. Longitud password 15

Propósito 

Cambiar la Default Domain Policy para que las contraseña tengan una longitud de 15 o más caracteres

Pasos

La sorpresa es que por defecto, si no tocamos nada, la GPO solo permite hasta 14 caracteres.


Para poder ampliarla necesitamos Habilitar la siguiente directiva "Reducir los limites de longitud mínima de la contraseña"



Y solucionado!!!



by GoN | Published: Feb 2026 | Last Updated:

miércoles, 21 de enero de 2026

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: