guest@6admin.io:~$

Durcir WinRM

WinRM est le moteur sous le PowerShell remoting et sous l’essentiel de la gestion Windows à distance, ce qui le rend à la fois indispensable et commode comme chemin d’un shell vers tout un parc. Le mettre debout tient en une commande. Le mettre debout sûrement signifie défaire deux des défauts que cette commande laisse derrière elle, choisir un transport qui veut dire quelque chose et contraindre ce qu’une session distante peut réellement faire. L’ordre compte, parce que le montage commode est le montage non sûr.

Les deux défauts à défaire d’abord

winrm quickconfig et Enable-PSRemoting -Force vous mettent en route en créant un écouteur HTTP sur 5985 et en ouvrant le pare-feu pour lui. Sur un domaine, la couche message reste chiffrée quand l’authentification est Kerberos ou NTLM, donc ce n’est pas en soi une catastrophe en clair, mais c’est une exposition que vous n’avez pas choisie délibérément et elle accepte Basic si quelqu’un l’active un jour. Traitez le montage rapide comme un point de départ à resserrer, pas comme un état fini.

Le second défaut est celui qui brûle vraiment et il est côté client:

winrm set winrm/config/client @{TrustedHosts="*"}   # à ne pas faire

TrustedHosts="*" dit au client de sauter la vérification d’identité du serveur pour n’importe quel hôte, c’est-à-dire précisément la façon dont un homme du milieu moissonne les identifiants que vous alliez envoyer. Il apparaît dans les tutoriels parce qu’il fait “juste marcher” les tests en workgroup. En production c’est une vulnérabilité permanente. Nommez les hôtes explicitement ou sur un domaine laissez-le vide et laissez Kerberos vérifier l’identité correctement:

winrm set winrm/config/client '@{TrustedHosts="dc1.company.internal,app1.company.internal"}'

Transport: HTTPS et rien de plus faible

La posture est HTTPS sur 5986 avec un vrai certificat, Basic coupé, non chiffré coupé et l’écouteur HTTP retiré pour qu’il n’y ait rien sur quoi retomber:

# écouteur HTTPS lié à un vrai certificat
$cert = Get-ChildItem Cert:\LocalMachine\My |
        Where-Object Subject -like "*server.company.internal*" |
        Sort-Object NotAfter -Descending | Select-Object -First 1
New-Item -Path WSMan:\localhost\Listener -Transport HTTPS -Address * `
    -Hostname server.company.internal -CertificateThumbprint $cert.Thumbprint -Force

# retirer HTTP, interdire Basic et le clair
winrm delete winrm/config/listener?Address=*+Transport=HTTP
winrm set winrm/config/service @{AllowUnencrypted="false"}
winrm set winrm/config/service/auth @{Basic="false"; Kerberos="true"; CredSSP="false"}

Le certificat est la partie que l’on bâcle avec New-SelfSignedCertificate, ce qui suffit à prouver que l’écouteur fonctionne et ne vaut rien comme confiance, parce que le client doit alors soit vérifier un certificat auto-signé qu’il n’a aucune raison d’approuver, soit sauter la vérification et sauter la vérification est l’erreur TrustedHosts sous un autre chapeau. Sur un domaine, c’est à cela que sert l’autorité interne.

CredSSP reste coupé pour la raison habituelle: il délègue l’identifiant complet à la cible, de sorte que l’activer à l’échelle du parc transforme chaque hôte géré en endroit où vos identifiants peuvent être volés et rejoués. Le problème du double saut qu’il résout a des réponses plus sûres et WinRM n’est pas l’endroit où le résoudre par défaut.

Contraindre ce qu’une session peut faire: JEA

Le transport décide qui se connecte; il ne décide pas ce qu’on peut lancer une fois connecté et par défaut une session distante est un shell complet. Just Enough Administration est le levier qui change cela et c’est le vrai gain de moindre privilège pour WinRM. Un point d’accès contraint n’expose que les commandes précises dont un rôle a besoin, les exécute sous un compte virtuel dédié plutôt que sous les privilèges de l’appelant et transcrit tout:

# un rôle qui peut redémarrer un service et lire des logs, rien d'autre
New-PSRoleCapabilityFile -Path C:\JEA\Operator.psrc `
    -VisibleCmdlets 'Get-Service', @{Name='Restart-Service'; Parameters=@{Name='Name'; ValidateSet='Spooler'}}, 'Get-WinEvent'

New-PSSessionConfigurationFile -Path C:\JEA\Operator.pssc `
    -SessionType RestrictedRemoteServer -RunAsVirtualAccount -TranscriptDirectory C:\JEA\Transcripts `
    -RoleDefinitions @{ 'COMPANY\ServiceOperators' = @{ RoleCapabilities = 'Operator' } }

Register-PSSessionConfiguration -Name Operator -Path C:\JEA\Operator.pssc

Un opérateur connecté à ce point d’accès peut redémarrer le Spooler et lire des événements et ne peut ni ouvrir un shell, ni lire des fichiers arbitraires, ni pivoter, bien qu’il se soit authentifié avec succès. Cet écart, entre “autorisé à se connecter” et “autorisé à faire quoi que ce soit”, est là où le durcissement de WinRM gagne sa place.

Cantonner l’écouteur et l’auditer

Le point d’accès ne devrait répondre qu’au réseau d’administration, ce qui est une règle de pare-feu appliquée au port HTTPS, la règle HTTP ayant disparu:

New-NetFirewallRule -DisplayName "WinRM-HTTPS-admin" -Direction Inbound `
    -LocalPort 5986 -Protocol TCP -Action Allow -RemoteAddress 10.0.10.0/24
Disable-NetFirewallRule -DisplayName "Windows Remote Management (HTTP-In)"

Pour la traçabilité, trois canaux portent l’histoire: le journal opérationnel WinRM pour les événements d’écouteur et de connexion, le journal opérationnel PowerShell (événement 4103 pour l’exécution de pipeline, plus le script-block log) pour ce qui a réellement tourné et le journal Sécurité pour les ouvertures de session de service derrière chaque connexion:

Get-WinEvent -LogName "Microsoft-Windows-WinRM/Operational"
Get-WinEvent -LogName "Microsoft-Windows-PowerShell/Operational" | Where-Object Id -eq 4103
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4624,4625}

Les transcriptions JEA bouclent la boucle, parce qu’elles enregistrent chaque session contrainte mot pour mot, sous le compte qui l’a exécutée.

Où atterrir

HTTPS sur 5986 avec un certificat émis par une autorité, HTTP et Basic et CredSSP disparus, TrustedHosts nommés plutôt que mis en wildcard, l’écouteur pare-feu vers le réseau d’administration et JEA contraignant les sessions distantes aux commandes dont un rôle a réellement besoin sous un compte dédié. Le défaut commode quickconfig est ce dont il faut s’éloigner par durcissement et la distance entre lui et la configuration ci-dessus est la distance entre “la gestion à distance est activée” et “la gestion à distance est un contrôle plutôt qu’un passif”.