Saltar al contenido
Microsoft scripts

Scripts de Defender

Opciones débiles en políticas anti-phishing

Compara tus políticas anti-phishing, de Safe Links y de Safe Attachments con el nivel Standard de Microsoft y señala cada opción por debajo.

Antes de correrloAplica por completo con Microsoft 365 Business Premium. Revisa cada política, pero no si tiene una regla que la aplique a alguien: confirma en el portal que la política débil sí esté en uso. La política de Protección integrada permite por diseño algunas opciones que aquí salen como débiles, como AllowClickThrough. Standard es una recomendación de Microsoft, no una obligación.

Ejemplo en México

Constructora en León, 85 personas

Tras un intento de fraude con una factura de proveedor suplantado, la dirección pide revisar cómo está configurada la protección del correo.

.\get-politicas-antiphishing.ps1 -RutaCsv .\politicas.csv

Obtiene las opciones por debajo de Standard y activa la protección contra suplantación para sus principales proveedores.

Cómo implementarlo

  1. Instala el módulo si no lo tienes: Install-Module ExchangeOnlineManagement -Scope CurrentUser.
  2. Corre el script e inicia sesión con una cuenta con el rol Lector de seguridad.
  3. Revisa en el CSV primero las filas con Riesgo Alto.
  4. Corrige esas opciones en el portal de Microsoft Defender o activa la directiva preestablecida Standard.
Ver el código completo de get-politicas-antiphishing.ps1
<#
.SYNOPSIS
    ¿Qué opciones de mis políticas anti-phishing, Safe Links y Safe Attachments están débiles?

.DESCRIPTION
    Compara cada política con el nivel Standard que Microsoft recomienda y lista las opciones por
    debajo. Las opciones que el cmdlet no devuelve se omiten, y si tu licencia no incluye Safe Links
    o Safe Attachments, el reporte lo indica en vez de fallar.
    Solo lectura: no cambia nada en el tenant.

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

.EXAMPLE
    .\get-politicas-antiphishing.ps1 -RutaCsv .\politicas.csv

.NOTES
    Permisos: Ninguno de Graph; usa roles de Exchange Online (ExchangeOnlineManagement)
    Rol mínimo: Lector de seguridad
    Licencia: Anti-phishing básico en todo buzón en la nube. Safe Links, Safe Attachments y protección contra suplantación requieren Microsoft Defender for Office 365 Plan 1 o superior (Plan 1 viene en Microsoft 365 Business Premium)
    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'

if (-not (Get-Command Connect-ExchangeOnline -ErrorAction SilentlyContinue)) {
    throw 'Falta el módulo. Instálalo con: Install-Module ExchangeOnlineManagement -Scope CurrentUser'
}
Connect-ExchangeOnline -ShowBanner:$false

# Debil lista los valores por debajo de Standard en "Recommended settings for EOP and Defender for Office 365".
function Regla($opcion, $debil, $recomendado, $riesgo, $efecto) {
    @{ Opcion = $opcion; Debil = $debil; Recomendado = $recomendado; Riesgo = $riesgo; Efecto = $efecto }
}
$revisiones = @(
    @{
        Tipo   = 'Anti-phishing'
        Cmdlet = 'Get-AntiPhishPolicy'
        Reglas = @(
            Regla 'Enabled' @($false) 'True' 'Alto' 'La política está apagada.'
            Regla 'EnableSpoofIntelligence' @($false) 'True' 'Alto' 'No se detecta la suplantación de remitentes.'
            Regla 'HonorDmarcPolicy' @($false) 'True' 'Medio' 'No se respeta la política DMARC del dominio que envía.'
            Regla 'EnableFirstContactSafetyTips' @($false) 'True' 'Bajo' 'No se avisa al recibir correo de un remitente nuevo.'
            Regla 'EnableUnauthenticatedSender' @($false) 'True' 'Bajo' 'No se marca al remitente sin autenticar.'
            Regla 'EnableViaTag' @($false) 'True' 'Bajo' 'No se muestra la etiqueta "via".'
            Regla 'PhishThresholdLevel' @(1, 2) '3 o más' 'Medio' 'El umbral de phishing es menos agresivo que el recomendado.'
            Regla 'EnableTargetedUserProtection' @($false) 'True, con lista de usuarios' 'Alto' 'No se protege a usuarios clave de la suplantación.'
            Regla 'EnableOrganizationDomainsProtection' @($false) 'True' 'Alto' 'No se protegen tus dominios de la suplantación.'
            Regla 'EnableTargetedDomainsProtection' @($false) 'True, con lista de dominios' 'Medio' 'No se protegen dominios de socios o proveedores.'
            Regla 'EnableMailboxIntelligence' @($false) 'True' 'Medio' 'La inteligencia de buzón está apagada.'
            Regla 'EnableMailboxIntelligenceProtection' @($false) 'True' 'Medio' 'La inteligencia de buzón no actúa contra la suplantación.'
            Regla 'TargetedUserProtectionAction' @('NoAction') 'Quarantine' 'Alto' 'La suplantación de usuarios se detecta, pero no se actúa.'
            Regla 'TargetedDomainProtectionAction' @('NoAction') 'Quarantine' 'Alto' 'La suplantación de dominios se detecta, pero no se actúa.'
            Regla 'MailboxIntelligenceProtectionAction' @('NoAction') 'MoveToJmf' 'Medio' 'Lo que detecta la inteligencia de buzón no recibe acción.'
            Regla 'EnableSimilarUsersSafetyTips' @($false) 'True' 'Bajo' 'No se avisa de usuarios parecidos.'
            Regla 'EnableSimilarDomainsSafetyTips' @($false) 'True' 'Bajo' 'No se avisa de dominios parecidos.'
            Regla 'EnableUnusualCharactersSafetyTips' @($false) 'True' 'Bajo' 'No se avisa de caracteres inusuales en el remitente.'
        )
    }
    @{
        Tipo   = 'Safe Links'
        Cmdlet = 'Get-SafeLinksPolicy'
        Reglas = @(
            Regla 'EnableSafeLinksForEmail' @($false) 'True' 'Alto' 'Safe Links no revisa las ligas del correo.'
            Regla 'EnableSafeLinksForTeams' @($false) 'True' 'Medio' 'Safe Links no revisa las ligas de Microsoft Teams.'
            Regla 'EnableSafeLinksForOffice' @($false) 'True' 'Medio' 'Safe Links no revisa las ligas en aplicaciones de Office.'
            Regla 'EnableForInternalSenders' @($false) 'True' 'Medio' 'No se revisan las ligas del correo interno: una cuenta tomada las puede repartir.'
            Regla 'ScanUrls' @($false) 'True' 'Alto' 'No se analizan en tiempo real las ligas sospechosas.'
            Regla 'DeliverMessageAfterScan' @($false) 'True' 'Medio' 'El correo se entrega antes de terminar de analizar sus ligas.'
            Regla 'DisableUrlRewrite' @($true) 'False' 'Medio' 'Las ligas no se reescriben, así que dependen solo de la revisión por API.'
            Regla 'TrackClicks' @($false) 'True' 'Medio' 'No se registran los clics, y pierdes la evidencia para investigar.'
            Regla 'AllowClickThrough' @($true) 'False' 'Alto' 'El usuario puede seguir a la liga original aunque Safe Links lo advierta.'
        )
    }
    @{
        Tipo   = 'Safe Attachments'
        Cmdlet = 'Get-SafeAttachmentPolicy'
        Reglas = @(
            Regla 'Enable' @($false) 'True' 'Alto' 'La política no analiza adjuntos.'
            Regla 'Action' @('Allow') 'Block' 'Alto' 'Los adjuntos con malware se entregan: el modo Monitor solo observa.'
        )
    }
)

$filas = try {
    foreach ($revision in $revisiones) {
        if (-not (Get-Command $revision.Cmdlet -ErrorAction SilentlyContinue)) {
            [pscustomobject]@{ Tipo = $revision.Tipo; Politica = '-'; Opcion = '-'; ValorActual = '-'; Recomendado = '-'; Riesgo = '-'; Hallazgo = "No disponible: $($revision.Cmdlet) no existe en tu sesión. Revisa la licencia o el rol." }
            continue
        }
        foreach ($politica in & $revision.Cmdlet) {
            $debiles = @(foreach ($regla in $revision.Reglas) {
                $valor = $politica.($regla.Opcion)
                # Null significa que tu licencia o la versión del cmdlet no expone esa opción.
                if ($null -eq $valor -or $valor -notin $regla.Debil) { continue }
                [pscustomobject]@{ Tipo = $revision.Tipo; Politica = $politica.Name; Opcion = $regla.Opcion; ValorActual = "$valor"; Recomendado = $regla.Recomendado; Riesgo = $regla.Riesgo; Hallazgo = $regla.Efecto }
            })
            if ($debiles) { $debiles } else {
                [pscustomobject]@{ Tipo = $revision.Tipo; Politica = $politica.Name; Opcion = '-'; ValorActual = '-'; Recomendado = '-'; Riesgo = '-'; Hallazgo = 'Sin debilidades frente a Standard' }
            }
        }
    }
} finally {
    Disconnect-ExchangeOnline -Confirm:$false
}

$hallazgos = @($filas | Where-Object Opcion -NE '-')
Write-Host "Opciones débiles: $($hallazgos.Count). Riesgo alto: $(@($hallazgos | Where-Object Riesgo -EQ 'Alto').Count)"
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