Saltar al contenido
Microsoft scripts

Scripts de Defender

Software con CVE críticos por dispositivo

Lista por computadora el software con vulnerabilidades críticas, cuántas tienen exploit público y qué actualización se recomienda, para priorizar parches.

Antes de correrloCon Microsoft 365 Business Premium no funciona solo: Defender for Business trae administración de vulnerabilidades básica en el portal, pero no búsqueda avanzada, que es de donde salen estas tablas. Necesitas Defender for Endpoint Plan 2, Defender Vulnerability Management o Microsoft Defender Suite for Business Premium. Solo cubre computadoras incorporadas a Defender for Endpoint, y estas tablas no devuelven datos si la consulta se hace contra Microsoft Sentinel. Si activaste RBAC en Defender for Endpoint, ese RBAC decide qué datos de dispositivos ve la cuenta, no solo el rol Lector de seguridad.

Ejemplo en México

Maquiladora de electrónicos en Ciudad Juárez, 400 personas con tres turnos

Las ventanas para parchar son cortas porque las líneas no paran. Hay que elegir qué actualizar en el siguiente cambio de turno.

.\get-vulnerabilidades-criticas.ps1 -RutaCsv .\vulnerabilidades.csv

Obtiene la lista priorizada y aprovecha la ventana para parchar primero lo que ya tiene exploit público.

Cómo implementarlo

  1. Instala el módulo si no lo tienes: Install-Module Microsoft.Graph.Authentication -Scope CurrentUser.
  2. Corre el script e inicia sesión con una cuenta con el rol Lector de seguridad.
  3. Abre el CSV: arriba quedan las filas con Urgente: hay exploit público.
  4. Actualiza ese software con la columna Actualizaciones y vuelve a correr el script para confirmar que bajó.
Ver el código completo de get-vulnerabilidades-criticas.ps1
<#
.SYNOPSIS
    ¿Qué software tiene CVE críticos en cada computadora y cuál actualizo primero?

.DESCRIPTION
    Consulta las tablas de Microsoft Defender Vulnerability Management con búsqueda avanzada y
    lista, por dispositivo y software, los CVE de severidad crítica, cuántos tienen exploit público
    y qué actualización se recomienda. Pone primero lo que ya se puede explotar.
    Solo lectura: el POST a runHuntingQuery es una consulta.

.PARAMETER RutaCsv
    Ruta del CSV de salida. Si se omite, solo se muestra en pantalla.

.EXAMPLE
    .\get-vulnerabilidades-criticas.ps1 -RutaCsv .\vulnerabilidades.csv

.NOTES
    Permisos: ThreatHunting.Read.All
    Rol mínimo: Lector de seguridad
    Licencia: Microsoft Defender for Endpoint Plan 2 o Microsoft Defender Vulnerability Management (complemento o independiente), o Microsoft Defender for Servers. Microsoft 365 Business Premium por sí solo no alcanza: Defender for Business no incluye búsqueda avanzada
    Licencia del código: MIT. Se entrega TAL CUAL, sin garantía. Pruébalo primero en un tenant de pruebas.
#>
[CmdletBinding()]
param(
    [string]$RutaCsv
)

$ErrorActionPreference = 'Stop'
$permisos = @('ThreatHunting.Read.All')

if (-not (Get-Command Connect-MgGraph -ErrorAction SilentlyContinue)) {
    throw 'Falta el módulo. Instálalo con: Install-Module Microsoft.Graph.Authentication -Scope CurrentUser'
}
Connect-MgGraph -Scopes $permisos -NoWelcome

$consulta = @'
DeviceTvmSoftwareVulnerabilities
| where VulnerabilitySeverityLevel =~ "Critical"
| join kind=leftouter (DeviceTvmSoftwareVulnerabilitiesKB | project CveId, CvssScore, IsExploitAvailable) on CveId
| summarize CveCriticos = dcount(CveId), ConExploit = countif(IsExploitAvailable == 1), CvssMaximo = max(todouble(CvssScore)),
    ListaCve = make_set(CveId), Actualizaciones = make_set(RecommendedSecurityUpdate)
    by DeviceName, OSPlatform, SoftwareVendor, SoftwareName, SoftwareVersion
'@
$respuesta = Invoke-MgGraphRequest -Method POST -Uri 'https://graph.microsoft.com/v1.0/security/runHuntingQuery' -Body (@{ Query = $consulta } | ConvertTo-Json) -ContentType 'application/json; charset=utf-8'
if (@($respuesta.results).Count -ge 100000) { Write-Warning 'Se alcanzó el tope de 100,000 filas de la consulta: pueden faltar resultados. Reduce el periodo o filtra más.' }

$filas = foreach ($r in $respuesta.results) {
    [pscustomobject]@{
        Prioridad       = if ([int]$r.ConExploit -gt 0) { 'Urgente: hay exploit público' } else { 'Alta' }
        Dispositivo     = $r.DeviceName
        Sistema         = $r.OSPlatform
        Fabricante      = $r.SoftwareVendor
        Software        = $r.SoftwareName
        Version         = $r.SoftwareVersion
        CveCriticos     = [int]$r.CveCriticos
        ConExploit      = [int]$r.ConExploit
        CvssMaximo      = $r.CvssMaximo
        ListaCve        = @($r.ListaCve) -join ', '
        Actualizaciones = @($r.Actualizaciones | Where-Object { $_ }) -join ', '
    }
}
$filas = $filas | Sort-Object @{ Expression = 'ConExploit'; Descending = $true }, @{ Expression = 'CveCriticos'; Descending = $true }, Dispositivo

$equipos = @($filas | Select-Object -ExpandProperty Dispositivo -Unique).Count
$urgentes = @($filas | Where-Object ConExploit -GT 0).Count
Write-Host "Software con CVE críticos: $(@($filas).Count) registros en $equipos dispositivos. Con exploit público: $urgentes"
if ($RutaCsv) {
    # UTF-8 con BOM para que Excel en español muestre bien los acentos.
    $filas | Export-Csv -Path $RutaCsv -NoTypeInformation -Encoding utf8BOM
    Write-Host "CSV guardado en $RutaCsv"
} else {
    $filas | Format-Table -AutoSize
}

Relacionados