Public/Get-TechCareSecurity.ps1
|
function Get-TechCareSecurity { <# .SYNOPSIS Revision de seguridad del equipo, con correcciones seguras opcionales. .DESCRIPTION Revisa Microsoft Defender, la antiguedad de las firmas, el firewall, UAC, BitLocker, SMBv1, cuentas locales sin contrasena obligatoria, RDP y los parches pendientes. Sin -Apply solo informa. Con -Apply aplica unicamente tres correcciones que no pueden dejar al usuario fuera de su equipo ni romper una sesion en curso: activar el firewall, actualizar las firmas de Defender y desactivar SMBv1. Todo lo demas (UAC, BitLocker, RDP, cuentas) queda como recomendacion, porque aplicarlo a ciegas rompe equipos: UAC necesita reinicio, BitLocker necesita una clave de recuperacion custodiada y cerrar RDP puede dejar sin acceso al propio tecnico. TechCare nunca desactiva Defender ni Windows Update. .PARAMETER Apply Aplica las tres correcciones seguras. Requiere administrador. .EXAMPLE Get-TechCareSecurity Solo revisa y devuelve hallazgos y recomendaciones. .EXAMPLE Get-TechCareSecurity -Apply -WhatIf Muestra que correcciones seguras se aplicarian. .EXAMPLE Get-TechCareSecurity -Apply -Confirm:$false Aplica las correcciones seguras sin preguntar. .OUTPUTS PSCustomObject .LINK https://github.com/earbona23/TechCare #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium')] [OutputType([pscustomobject])] param( [switch]$Apply ) if (-not (Test-TechCarePlatform)) { throw $script:PlatformMessage } $findings = New-Object -TypeName System.Collections.ArrayList $actions = New-Object -TypeName System.Collections.ArrayList $recs = New-Object -TypeName System.Collections.ArrayList $status = 'Green' $mod = 'Security' $admin = Test-TechCareAdmin $canFix = ($Apply -and $admin) if ($Apply -and -not $admin) { [void]$findings.Add('-Apply solicitado sin privilegios de administrador: solo se revisa.') [void]$recs.Add('Relanzar como administrador para aplicar las correcciones seguras.') } Write-Progress -Activity 'TechCare' -Status 'Revisando Defender' -PercentComplete 10 try { $mp = Get-MpComputerStatus -ErrorAction Stop [void]$findings.Add(('Defender - tiempo real: {0} / antivirus: {1} / antiguedad de firmas: {2} dias' -f $mp.RealTimeProtectionEnabled, $mp.AntivirusEnabled, $mp.AntivirusSignatureAge)) if (-not $mp.RealTimeProtectionEnabled) { $status = 'Red' [void]$recs.Add('Proteccion en tiempo real de Defender apagada: averiguar si la apago un antivirus de terceros o una politica antes de reactivarla.') } if ($mp.AntivirusSignatureAge -gt 3) { if ($status -ne 'Red') { $status = 'Yellow' } [void]$recs.Add('Firmas de Defender con mas de 3 dias.') if ($canFix -and $PSCmdlet.ShouldProcess('Microsoft Defender', 'Actualizar firmas')) { try { Update-MpSignature -ErrorAction Stop [void]$actions.Add('Firmas de Defender actualizadas.') } catch { [void]$findings.Add('No se pudieron actualizar las firmas: ' + $_.Exception.Message) } } } } catch { [void]$findings.Add('Defender no disponible o sin acceso (probable antivirus de terceros): ' + $_.Exception.Message) } Write-Progress -Activity 'TechCare' -Status 'Revisando firewall' -PercentComplete 25 try { $fwProfiles = Get-NetFirewallProfile -ErrorAction Stop foreach ($p in $fwProfiles) { [void]$findings.Add(('Firewall perfil {0}: {1}' -f $p.Name, $p.Enabled)) if ($p.Enabled) { continue } $status = 'Red' [void]$recs.Add(('Firewall apagado en el perfil {0}.' -f $p.Name)) if ($canFix -and $PSCmdlet.ShouldProcess(('Firewall, perfil ' + $p.Name), 'Activar')) { try { Set-NetFirewallProfile -Profile $p.Name -Enabled True -ErrorAction Stop [void]$actions.Add(('Firewall activado en el perfil {0}.' -f $p.Name)) } catch { [void]$findings.Add(('No se pudo activar el firewall {0}: {1}' -f $p.Name, $_.Exception.Message)) } } } } catch { [void]$findings.Add('No se pudo consultar el firewall: ' + $_.Exception.Message) } Write-Progress -Activity 'TechCare' -Status 'Revisando UAC' -PercentComplete 40 try { $uacKey = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System' $uac = Get-ItemProperty -LiteralPath $uacKey -ErrorAction Stop $enableLua = $uac.PSObject.Properties['EnableLUA'] $consent = $uac.PSObject.Properties['ConsentPromptBehaviorAdmin'] if ($null -ne $enableLua) { [void]$findings.Add(('UAC EnableLUA: {0}' -f $enableLua.Value)) if ($enableLua.Value -ne 1) { $status = 'Red' [void]$recs.Add('UAC desactivado: reactivarlo requiere reinicio, por eso TechCare no lo toca.') } elseif ($null -ne $consent -and $consent.Value -eq 0) { if ($status -ne 'Red') { $status = 'Yellow' } [void]$recs.Add('UAC eleva sin preguntar (ConsentPromptBehaviorAdmin = 0): valorar subir el nivel.') } } } catch { [void]$findings.Add('No se pudo leer la configuracion de UAC: ' + $_.Exception.Message) } Write-Progress -Activity 'TechCare' -Status 'Revisando BitLocker' -PercentComplete 55 try { $systemVolume = $env:SystemDrive + '\' $bl = @(Get-BitLockerVolume -ErrorAction Stop | Where-Object { $_.MountPoint -eq $systemVolume }) if ($bl.Count -gt 0) { [void]$findings.Add(('BitLocker en {0}: {1}' -f $bl[0].MountPoint, $bl[0].ProtectionStatus)) if ($bl[0].ProtectionStatus -ne 'On') { if ($status -ne 'Red') { $status = 'Yellow' } [void]$recs.Add('BitLocker apagado en el volumen del sistema. Activarlo exige custodiar la clave de recuperacion: decision del responsable, no del script.') } } else { [void]$findings.Add('BitLocker: el volumen del sistema no aparece como volumen cifrable.') } } catch { [void]$findings.Add('BitLocker no consultable (sin administrador o edicion no compatible): ' + $_.Exception.Message) } Write-Progress -Activity 'TechCare' -Status 'Revisando SMBv1' -PercentComplete 65 try { $smb = Get-SmbServerConfiguration -ErrorAction Stop [void]$findings.Add(('SMBv1 habilitado: {0}' -f $smb.EnableSMB1Protocol)) if ($smb.EnableSMB1Protocol) { if ($status -ne 'Red') { $status = 'Yellow' } [void]$recs.Add('SMBv1 habilitado. Antes de quitarlo, confirmar que no hay NAS ni impresoras antiguas que solo hablen SMBv1.') if ($canFix -and $PSCmdlet.ShouldProcess('SMBv1 (servidor)', 'Desactivar el protocolo')) { try { Set-SmbServerConfiguration -EnableSMB1Protocol $false -Force -ErrorAction Stop [void]$actions.Add('SMBv1 desactivado en el servidor SMB.') } catch { [void]$findings.Add('No se pudo desactivar SMBv1: ' + $_.Exception.Message) } } } } catch { [void]$findings.Add('No se pudo consultar la configuracion SMB: ' + $_.Exception.Message) } Write-Progress -Activity 'TechCare' -Status 'Revisando cuentas locales' -PercentComplete 78 try { $weak = @(Get-LocalUser -ErrorAction Stop | Where-Object { $_.Enabled -and -not $_.PasswordRequired }) if ($weak.Count -gt 0) { if ($status -ne 'Red') { $status = 'Yellow' } foreach ($u in $weak) { [void]$findings.Add('Cuenta local activa sin contrasena obligatoria: ' + $u.Name) } [void]$recs.Add('Poner contrasena a las cuentas locales listadas, o deshabilitarlas si no se usan.') } else { [void]$findings.Add('Cuentas locales activas sin contrasena obligatoria: 0') } } catch { [void]$findings.Add('No se pudo enumerar cuentas locales: ' + $_.Exception.Message) } Write-Progress -Activity 'TechCare' -Status 'Revisando RDP' -PercentComplete 88 try { $tsKey = 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server' $rdp = Get-ItemProperty -LiteralPath $tsKey -Name 'fDenyTSConnections' -ErrorAction Stop $rdpOn = ($rdp.fDenyTSConnections -eq 0) [void]$findings.Add(('RDP habilitado: {0}' -f $rdpOn)) if ($rdpOn) { [void]$recs.Add('RDP habilitado: comprobar que NLA esta exigido, que el firewall no lo expone a internet y quien esta en el grupo de Escritorio Remoto. TechCare no lo cierra: podria dejar sin acceso al propio tecnico.') } } catch { [void]$findings.Add('No se pudo leer el estado de RDP: ' + $_.Exception.Message) } try { $session = New-Object -ComObject Microsoft.Update.Session $searcher = $session.CreateUpdateSearcher() # BrowseOnly=0 excluye las actualizaciones opcionales que Windows no # ofrece por si solo, para no inflar la cuenta de parches pendientes. $pending = $searcher.Search("IsInstalled=0 and IsHidden=0 and Type='Software' and BrowseOnly=0") [void]$findings.Add(('Parches de software pendientes: {0}' -f $pending.Updates.Count)) if ($pending.Updates.Count -gt 0) { if ($status -ne 'Red') { $status = 'Yellow' } [void]$recs.Add('Aplicar los parches pendientes con el modulo Update.') } } catch { [void]$findings.Add('No se pudo consultar los parches pendientes: ' + $_.Exception.Message) } if (-not $Apply) { [void]$recs.Add('Ejecutar con -Apply para aplicar solo las tres correcciones seguras: firewall, firmas de Defender y SMBv1.') } Write-Progress -Activity 'TechCare' -Status 'Revision de seguridad completada' -Completed return Add-TechCareResult -Module $mod -Status $status -Findings $findings.ToArray() -Actions $actions.ToArray() -Recommendations $recs.ToArray() } |