Búsqueda de sitios web

Cómo realizar un seguimiento de eventos importantes de seguridad de Windows con PowerShell


Muchas organizaciones dependen de las tecnologías de Microsoft para realizar su trabajo. Al mismo tiempo, los actores de amenazas pueden explotar sistemas operativos como Windows. Afortunadamente, Windows registra los eventos de seguridad del sistema operativo para ayudarle a rastrear este comportamiento.

Los eventos de seguridad producidos por Windows sirven como un recurso crítico en el proceso de respuesta a incidentes. Herramientas como el Visor de eventos de Windows de Microsoft le brindan el acceso necesario para revisar los eventos capturados, pero detectar anomalías desplazándose manualmente a través de un registro lleno de gente no es realista.

En esta publicación, aprenderá cómo rastrear posibles violaciones de seguridad en Windows aprendiendo sobre políticas de auditoría, registros de eventos de Windows y analizando eventos de seguridad con PowerShell.

Requisitos previos

Este artículo tiene como objetivo transmitir información que le enseñe cómo analizar los eventos de seguridad de Windows con PowerShell. Si desea seguir alguna de las demostraciones, necesitará:

  • Una PC con Windows 10+: esta PC se utilizará para generar y rastrear posibles eventos de seguridad en el registro de eventos. Este tutorial utilizará Windows PowerShell 5.1.
  • Derechos de administrador en la PC con Windows
  • Un editor de código PowerShell como PowerShell ISE o Visual Studio (VS) Code.

Dónde Windows almacena eventos de seguridad

Cuando se realiza una acción en un sistema operativo Windows, Windows registra la acción como un evento en uno o más registros de eventos. Los registros de eventos de Windows se almacenan en el sistema de archivos, de forma predeterminada, en el directorio %SystemRoot%\system32\winevt\logs. Esta ubicación se puede cambiar modificando la subclave de registro EventLog del registro de eventos respectivo.

Si desea ver dónde se almacenan los registros de eventos más destacados (Aplicación, Seguridad y Sistema) en su sistema, copie y pegue el siguiente código en una consola PowerShell o guárdelo como un script.

Para acceder a la ubicación de almacenamiento del archivo de registro de seguridad, debe ejecutar el código como administrador.

#Present application, security, and system logs in an array.
 $arrLogs = @(
     "Application"
     "Security"
     "System"
 )
 #Use the ForEach-Object cmdlet to target each respective log with the Get-ItemProperty cmdlet.
 $arrLogs | ForEach-Object {
     #Use Get-ItemProperty cmdlet to list the configured file path for the application, security, and system log.
     Get-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Services\EventLog\$_ -Name File | Select-Object PSChildName,File
 }

La siguiente captura de pantalla muestra el resultado esperado del código, mostrando el nombre del registro y la ubicación de almacenamiento para los archivos de registro Aplicación, Seguridad y Sistema.

Políticas de auditoría: definición de eventos para registrar

De forma predeterminada, Windows no captura todos los eventos de seguridad que podrían ser necesarios para detectar o investigar una infracción. Para controlar lo que Windows registra y no registra, debe definir y aplicar políticas de auditoría. Una política de auditoría es un conjunto de instrucciones pasadas a Windows que le indican qué eventos registrar.

Hay algunas formas diferentes de asignar y trabajar con políticas de auditoría, como la Política de grupo. La política de grupo funciona bien si debe implementar políticas de auditoría en muchas máquinas. Pero en este artículo te limitarás a un solo dispositivo, por lo que utilizarás la herramienta auditpol. La herramienta auditpol viene instalada con Windows y le permite buscar y configurar políticas de auditoría en un sistema Windows.

Encontrar políticas de auditoría

Por ejemplo, para encontrar el estado de todas las políticas de auditoría en su sistema Windows, use el parámetro /get como se muestra a continuación. El uso del parámetro /category seguido de un comodín le indica a auditpol que busque el estado de todas las políticas de auditoría; no solo uno que coincida con una categoría o subcategoría específica.

#Obtain the system's audit policy configuration.
auditpol /get /category:*

La siguiente captura de pantalla muestra una versión truncada del resultado esperado del código, que muestra la categoría, las subcategorías y el estado (Configuración) de la política de auditoría de Administración de cuentas.

Una Configuración configurada como Sin auditoría significa que no se registrarán todos los eventos asociados con esa subcategoría de política de auditoría.

Establecer políticas de auditoría

La herramienta auditpol puede hacer más que ver la configuración de la política de auditoría. También puede modificarlos usando el comando auditpol /set. Para demostrar secciones futuras de este tutorial, abra una consola PowerShell como administrador y ejecute el siguiente comando. Este comando comienza a registrar todos los eventos (éxitos y fracasos) que forman parte de la subcategoría Inicio de sesión.

La configuración de la subcategoría Inicio de sesión obliga a su sistema a registrar eventos:

  • 4624: Se inició sesión correctamente en una cuenta
  • 4625: Una cuenta no pudo iniciar sesión
  • 4626: Información de reclamaciones de usuario/dispositivo
  • 4648: Se intentó iniciar sesión utilizando credenciales explícitas
  • 4675: Se filtraron los SID
#Set Logon Events to capture Success/Failure activity.
auditpol /set /subcategory:"Logon" /success:enable /failure:enable

Hay numerosos recursos disponibles para ayudarle con la configuración de políticas de auditoría de mejores prácticas, incluidos los puntos de referencia del Centro de Seguridad de Internet (CIS) y las Guías de implementación técnica de seguridad (STIG) de la Agencia de Sistemas de Información de Defensa (DISA), y la guía publicada por Microsoft.

Generación de registros de errores de inicio de sesión para análisis

Este artículo será un tutorial y esperamos que lo sigas. Si ha configurado Windows para auditar los eventos de inicio de sesión anteriores, generemos ahora algunos eventos de seguridad para analizarlos más adelante. Más específicamente, generemos 35 intentos fallidos de inicio de sesión que se registrarán en el registro de seguridad de su sistema para imitar la actividad de fuerza bruta.

1. Abre tu editor de código favorito.

2. Copie el siguiente código y péguelo en el editor de código. Este fragmento de código intenta abrir el proceso PowerShell.exe utilizando el cmdlet Start-Process utilizando nombres de usuario y contraseñas falsos.

#Define 5 usernames to record as logon failures.
 $arrUsers = @(
     "AtaBlogUser1"
     "AtaBlogUser2"
     "AtaBlogUser3"
     "AtaBlogUser4"
     "AtaBlogUser5"
 )
 #Loop through usernames using ForEach-Object to generate a logon failure for each one.
 $arrUsers | ForEach-Object {
     $securePassword = ConvertTo-SecureString "AtA810GRu13Z%%" -AsPlainText -Force 
     $storedCredential = New-Object System.Management.Automation.PSCredential($_, $securePassword)
     Start-Process -FilePath PowerShell -Credential $storedCredential
 }
 #Generate 30 logon failures for user AtaBlogUser.
 $i = 0
 Do {
     $securePassword = ConvertTo-SecureString "AtA810GRu13Z%%" -AsPlainText -Force 
     $storedCredential = New-Object System.Management.Automation.PSCredential("AtaBlogUser", $securePassword)
     Start-Process -FilePath PowerShell -Credential $storedCredential
     $i++
 } Until ($i -eq 30)

3. Guarde el script de PowerShell como Invoke-BogusEvents.ps1 o el nombre que desee y ejecute el script.

Cuando se ejecute, notará un error esperado repetido 35 veces que indica El nombre de usuario o la contraseña son incorrectos.

Si no recibe el resultado esperado, asegúrese de que el servicio de inicio de sesión secundario esté en estado de ejecución.

Acceder a eventos de Windows con PowerShell

Ahora que está seguro de tener al menos 35 eventos de seguridad de Windows, analicemos cómo encontrarlos con el cmdlet Get-WinEvent de PowerShell.

Es posible que esté familiarizado con el cmdlet Get-EventLog de PowerShell, que también se utiliza para acceder al registro de eventos mediante programación. Get-EventLog utiliza una interfaz de programación de aplicaciones (API) Win32 que está en desuso y no se analizará en esta publicación.

Abra una consola de PowerShell como administrador e invoque el cmdlet Get-WinEvent pasándole el parámetro FilterHashtable y MaxEvents como se muestra a continuación.

El siguiente comando consulta el registro de seguridad de su sistema (LogName='Security') para el ID del evento 4625 (ID=4625) y devuelve las primeras 10 instancias más nuevas (MaxEvents 10).

#Filter the security log for the first 10 instances of Event ID 4625
Get-WinEvent -FilterHashtable @{LogName='Security';ID=4625} -MaxEvents 10

Si tiene éxito, debería ver un resultado similar al siguiente:

Accediendo a las propiedades del evento con Get-WinEvent

En la sección anterior, utilizó Get-WinEvent para ver los eventos de seguridad de Windows en un nivel alto, pero un evento de Windows contiene mucha más información. Cada evento de Windows tiene propiedades valiosas que puede utilizar para un análisis más profundo.

Eventos de Windows como XML

Cuando Windows registra un evento, se almacena en formato XML. Si ese es el caso, entonces ¿por qué su comando Get-WinEvent devolvió objetos típicos de PowerShell? El cmdlet Get-WinEvent lee la API nativa de Windows y traduce los eventos en objetos de PowerShell para una mayor funcionalidad.

Cada evento de Windows tiene varios atributos que siguen un esquema o estructura XML específico.

Verás a continuación que cada evento sigue una estructura específica con tres atributos:

  • name - El nombre de la propiedad
  • inType: la definición del tipo de entrada o cómo el evento acepta un valor
  • outputType: la definición del tipo de salida o cómo se registra el evento

Encontrar plantillas XML de eventos con PowerShell

Como se mencionó anteriormente, cada evento de seguridad de Windows se almacena en XML y tiene un esquema específico, pero ¿cómo es ese esquema? Vamos a averiguar.

En una de las secciones anteriores, generó algunos eventos con ID 4625 en el registro de eventos de seguridad. Este tipo de evento tiene atributos específicos que sólo se aplican a él. Para encontrar esos atributos y cómo se ve la plantilla:

1. Abra una consola PowerShell como administrador si aún no la tiene abierta.

2. Ejecute Get-WinEvent nuevamente, pero esta vez use el parámetro ListProvider que especifica el proveedor que utiliza Windows para registrar eventos en el registro de eventos de seguridad y solo devuelve los Events. Propiedad .

La propiedad Events contiene todos los eventos que el proveedor de la lista ha registrado y expone la plantilla XML para cada uno de esos eventos.

(Get-WinEvent -ListProvider 'Microsoft-Windows-Security-Auditing').Events

3. Ahora que tiene el código para buscar plantillas para todos los tipos de eventos, limítelo devolviendo solo el evento asociado con el ID 4625.

(Get-WinEvent -ListProvider 'Microsoft-Windows-Security-Auditing').Events | Where-Object -Property ID -eq 4625

4. Una vez que devuelva solo el tipo de evento de inicio de sesión con ID de evento 4625, limítelo para mostrar solo la propiedad Plantilla como se muestra a continuación.

#Obtain event XML template for event properties of Event ID 4625.
 ((Get-WinEvent -ListProvider 'Microsoft-Windows-Security-Auditing').Events | Where-Object -Property ID -eq 4625).Template

La siguiente captura de pantalla muestra una versión truncada de la salida del código, identificando el nombre de la propiedad del evento, el tipo de entrada y el tipo de salida. Puede ver que el ID de evento 4625 tiene propiedades de evento con varias definiciones de entrada y salida.

La siguiente captura de pantalla resalta la propiedad SubjectUserSid del ID de evento 4625. Este evento en particular acepta un tipo de entrada (inType) de win:SID y representa el salida (outType) como una cadena que es como se almacena dentro del registro de seguridad.

Cómo PowerShell traduce XML en objetos

Ahora que ha visto cómo Windows almacena eventos en XML y cómo ver esas plantillas en PowerShell, veamos cómo PowerShell traduce ese XML en objetos.

1. Ejecute el comando Get-WinEvent nuevamente para devolver nuestro ID de evento 4625. Hasta ahora, esto no es nada nuevo. Tenga en cuenta que PowerShell solo muestra cuatro propiedades, TimeCreated, Id, LevelDisplayName y Message.

Get-WinEvent -FilterHashtable @{LogName='Security';ID=4625} -MaxEvents 1

De forma predeterminada, el cmdlet Get-WinEvent no devuelve todos los atributos del origen de datos XML del evento como un objeto de PowerShell.

2. Ahora, canalice la salida del comando anterior al cmdlet Select-Object y especifique el parámetro Property pasando un valor de para mostrar todas las propiedades.

Get-WinEvent -FilterHashtable @{LogName='Security';ID=4625} -MaxEvents 1 | Select-Object -Property *

Observe a continuación que PowerShell ocultaba muchas propiedades diferentes. Más específicamente, una propiedad llamada Propiedades. La propiedad Properties contiene el valor de cada atributo de evento que vio anteriormente en la plantilla XML.

3. Limite la salida del comando Get-WinEvent anterior para exponer la propiedad Properties. Esta propiedad almacena todas las propiedades del evento, no las propiedades del objeto PowerShell, en una matriz.

#Output event properties array for the first instance of Event ID 4625
 $eventProperties = (Get-WinEvent -FilterHashtable @{LogName='Security';ID=4625} -MaxEvents 1).properties
 $eventProperties

A la izquierda de la captura de pantalla siguiente se encuentra el resultado del comando anterior. La matriz contiene los valores para cada uno de los atributos XML en la plantilla XML en el lado derecho de la captura de pantalla.

El resultado del código que se muestra en la captura de pantalla comunica que se produjo un error de autenticación para el usuario AtaBlogUser (TargetUserName) del sistema Desktop-XXXXX (WorkstationName ) utilizando una dirección IP de ::1 (IpAddress).

Quizás solo desee devolver el valor de la propiedad del evento TargetUserName. Como ya almacenó todas las propiedades del evento en una variable llamada $eventProperties, haga referencia al quinto índice, que contiene el valor de TargetUserName.

Debe hacer referencia a la propiedad value en el objeto de propiedad del evento individual para devolver solo el valor (AtaBlogUser). $eventProperties[5] .valor

$eventProperties[5].value

Las prácticas descritas a lo largo de esta sección se utilizarán en secciones posteriores para rastrear el intento de fuerza bruta que simuló anteriormente en esta publicación.

Detectar un ataque de fuerza bruta

¡Ahora estás preparado para usar tus habilidades de PowerShell para localizar el ataque de fuerza bruta que replicaste anteriormente en esta publicación! Pongamos a prueba tus habilidades simulando cómo se vería rastrear un ataque de fuerza bruta en función de un período de tiempo específico.

Supongamos que recibió una alerta sobre un incidente en el que su organización cree que alguien está intentando utilizar una cuenta administrativa para iniciar sesión en un servidor Windows importante. Esta actividad comenzó ayer. Debe descubrir el número de ID del evento 4625: Una cuenta no pudo iniciar sesión que ocurrió durante las últimas 24 horas y determinar el tipo de inicio de sesión de cada evento.

1. Busque todos los eventos con ID 4625 (ID=4625) en el registro de seguridad de Windows (LogName="Security") durante las últimas 24 horas (StartTime= ((Get-Date).AddDays(-1).Date), finalizando en la hora actual (Get-Date).

$events = Get-WinEvent -FilterHashTable @{LogName="Security";ID=4625;StartTime=((Get-Date).AddDays(-1));EndTime=(Get-Date)}

2. Ahora, cuente todos los eventos almacenados en la variable para determinar si hay más eventos de registro fallidos de los esperados.

$events.Count

Ahora debería ver un valor numérico que indica la cantidad de veces que se encontró el evento ID 4625 en el registro de eventos de seguridad durante las últimas 24 horas.

3. Si ha determinado que se ha producido un ataque de fuerza bruta, ahora busque más información sobre estos eventos de seguridad de Windows. Para hacerlo, devuelva solo los atributos de cada uno de los eventos que le interesan.

Como se mencionó anteriormente, cada valor de un evento particular se almacena en una matriz con un índice específico. Las propiedades de eventos interesantes para esta demostración se encuentran a continuación.

  • Nombre de usuario objetivo Índice: [5]
  • Índice LogonType: [10]
  • Nombre de la estación de trabajo Índice: [13]
  • Dirección IP Índice: [19]

El siguiente ejemplo de código lee cada objeto en la variable $events, recopila solo las propiedades interesantes y las concatena en una sola línea.

#Extract TargetUserName, LogonType, WorkstationName, and IpAddress event properties from all instances of Event ID 4625 in the last 24 hours.
 $events | ForEach-Object {
     ## Reference the properties object property
     ## Only return the value of indexes 5,10,13 and 19 from the properties array
     ## Concatenate all values together by joining them with a comma
     $_.properties[5,10,13,19].value -join ", "
 }

La siguiente captura de pantalla muestra una versión truncada del resultado esperado del código, detallando una lista separada por comas de TargetUserName, LogonType, WorkstationName y Dirección IP.

4. Como vio anteriormente en la plantilla XML, la plantilla del evento ID 4625 tiene un atributo LogonType. Este atributo indica el método en el que la cuenta intentó autenticarse. Al investigar un poco más, notó que LogonType era diferente en ocasiones.

El valor LogonType es un valor numérico del 2 al 11, pero ¿qué significa eso? Investigas un poco y descubres qué significa cada valor.

2 - Interactivo: un usuario inició sesión en esta computadora.

3 - Red: un usuario o computadora inició sesión en esta computadora desde la red.

4 - Lote: el tipo de inicio de sesión por lotes lo utilizan los servidores por lotes, donde los procesos pueden ejecutarse en nombre de un usuario sin su intervención directa.

5 - Servicio: el Administrador de control de servicios inició un servicio.

7 - Desbloquear: esta estación de trabajo fue desbloqueada.

8 - NetworkCleartext: un usuario inició sesión en esta computadora desde la red. La contraseña del usuario se pasó al paquete de autenticación en su formato sin hash. La autenticación integrada empaqueta todas las credenciales hash antes de enviarlas a través de la red. Las credenciales no atraviesan la red en texto sin formato (también llamado texto sin cifrar).

9 - NewCredentials: una persona que llama clonó su token actual y especificó nuevas credenciales para las conexiones salientes. La nueva sesión de inicio de sesión tiene la misma identidad local, pero utiliza credenciales diferentes para otras conexiones de red.

10 - RemoteInteractive: una persona que llama clonó su token actual y especificó nuevas credenciales para las conexiones salientes. La nueva sesión de inicio de sesión tiene la misma identidad local, pero utiliza credenciales diferentes para otras conexiones de red.

11 - CachedInteractive: un usuario inició sesión en esta computadora con credenciales de red que estaban almacenadas localmente en la computadora. No se contactó al controlador de dominio para verificar las credenciales.

Ahora que comprende bien cada LogonType, en lugar de ver un valor numérico en la salida, desea una cadena más descriptiva. Para crear "mapas" en PowerShell, utilice una tabla hash.

$logonTypes = @{
     [uint32]2 = "Interactive"
     [uint32]3 = "Network"
     [uint32]4 = "Batch"
     [uint32]5 = "Service"
     [uint32]7 = "Unlock"
     [uint32]8 = "NetworkCleartext"
     [uint32]9 = "NewCredentials"
     [uint32]10 = "RemoteInteractive"
     [uint32]11 = "CachedInteractive"
 }

5. Combine Get-WinEvent y la tabla hash LogonType con ForEach-Object para crear un script que solo devolverá las propiedades que desea con un valor LogonType fácil de usar, como se muestra a continuación. El cmdlet Format-Table se suma a la salida fácil de usar al formatear la respuesta de PowerShell como una tabla.

#Use Get-WinEvent to access the properties of each logged instance of Event ID 4625
$events = Get-WinEvent -FilterHashTable @{LogName="Security";ID=4625;StartTime=((Get-Date).AddDays(-1).Date);EndTime=(Get-Date)}
## Create the numerical value to string "map"
$logonTypes = @{
    [uint32]2 = "Interactive"
    [uint32]3 = "Network"
    [uint32]4 = "Batch"
    [uint32]5 = "Service"
    [uint32]7 = "Unlock"
    [uint32]8 = "NetworkCleartext"
    [uint32]9 = "NewCredentials"
    [uint32]10 = "RemoteInteractive"
    [uint32]11 = "CachedInteractive"
}
## Begin processing each object in the $events array
$events | ForEach-Object {
    ## Look up the numerical value in the hashtable
    $logonType = $logonTypes[$_.properties[10].value] 
    #Create custom PowerShell object to output relevant event properties 
    [PSCustomObject]@{     
        TimeCreated = $_.TimeCreated     
        TargetUserName = $_.properties[5].value     
        LogonType = $logonType     
        WorkstationName = $_.properties[13].value     
        IpAddress = $_.properties[19].value 
    }
} | Format-Table -Wrap

En este punto, ahora tiene un script que devuelve objetos de tipo PSCustomObject que le permiten realizar muchos tipos diferentes de análisis. Para finalizar el análisis de este tutorial, priorice los intentos fallidos de autenticación de TargetUserName. Para priorizar los errores mediante la propiedad TargetUserName, combine el código anterior con el cmdlet Group-Object. Utilice Ordenar-Objeto y su interruptor Descendente para identificar al usuario más infractor.

#Use Get-WinEvent to access the properties of each logged instance of Event ID 4625
$events = Get-WinEvent -FilterHashTable @{LogName="Security";ID=4625;StartTime=((Get-Date).AddDays(-1).Date);EndTime=(Get-Date)}
## Create the numerical value to string "map"
$logonTypes = @{
    [uint32]2 = "Interactive"
    [uint32]3 = "Network"
    [uint32]4 = "Batch"
    [uint32]5 = "Service"
    [uint32]7 = "Unlock"
    [uint32]8 = "NetworkCleartext"
    [uint32]9 = "NewCredentials"
    [uint32]10 = "RemoteInteractive"
    [uint32]11 = "CachedInteractive"
}
## Begin processing each object in the $events array
$events | ForEach-Object {
    ## Look up the numerical value in the hashtable
    $logonType = $logonTypes[$_.properties[10].value] 
    #Create custom PowerShell object to output relevant event properties 
    [PSCustomObject]@{     
        TimeCreated = $_.TimeCreated     
        TargetUserName = $_.properties[5].value     
        LogonType = $logonType     
        WorkstationName = $_.properties[13].value     
        IpAddress = $_.properties[19].value 
    }
} | Group-Object -Property TargetUserName | Sort-Object -Property Count -Descending

¡Buen trabajo! Acaba de utilizar PowerShell para detectar el intento de fuerza bruta que simuló anteriormente en esta publicación. Según el resultado, AtaBlogUser no pudo autenticarse 30 veces en las últimas 24 horas.

Próximos pasos

En este tutorial, aprendió cómo Windows registra eventos, cómo habilitar el registro de eventos para ciertos tipos de eventos y cómo crear una herramienta PowerShell para consultar estos eventos.

Con el script de PowerShell que tienes ahora, ¿cómo puedes mejorarlo? ¿Cómo tomará el código que ha aprendido hoy y creará una herramienta mejor?

Artículos relacionados