Sur Windows Server 2019, le dossier C:\Windows\ServiceProfiles\LocalService\AppData\Roaming\Microsoft\Crypto\RSA
peut se remplir de millions de fichiers < 4 Ko. Voici comment comprendre le phénomène, identifier le service fautif et nettoyer sans casser la production.
Dossiers « Crypto\RSA » remplis de millions de petits fichiers sur Windows Server 2019
Vue d’ensemble de la question
Vous constatez l’apparition continue de minuscules fichiers (souvent quelques kilo‑octets) sous ...\Microsoft\Crypto\RSA
dans le profil LocalService. Le volume devient ingérable, l’explorateur se fige, et même un Administrateur ne parvient pas à les supprimer. Ces fichiers ne se nettoient pas d’eux‑mêmes et semblent « indélébiles ».
Réponse & Solution
Ce que sont ces fichiers
- Des conteneurs de clés RSA créés par la CryptoAPI (CAPI) de Windows et/ou par CNG (Cryptography Next Generation), associés au profil LocalService (
S-1-5-19
). - Ils servent à stocker des paires de clés (privées/publiques), des clés de session, ou des artefacts liés aux opérations TLS, authentification mutuelle, signatures, etc.
- Une accumulation massive indique qu’un service (proxy, agent de sécurité, service web, tâche planifiée, script) crée des conteneurs temporaires/persistants sans nettoyage (fuite de clés).
Risques à connaître
- Supprimer une clé encore utilisée peut casser TLS, l’authentification ou la signature de jetons côté service.
- Un nettoyage aveugle peut provoquer une interruption de service difficile à diagnostiquer.
- Sur un volume NTFS saturé d’entrées, les performances du système (VSS, sauvegardes, antivirus, MFT) se dégradent nettement.
A. Diagnostiquer le processus qui crée ces fichiers (recommandé avant le nettoyage)
Étape 1 : activer le journal CAPI2
- Ouvrez Observateur d’événements → Journaux des applications et des services → Microsoft → Windows → CAPI2 → Operational et Activez le journal.
- Laissez tourner quelques minutes sous charge habituelle, puis recherchez les événements signalant la création/accès à des conteneurs ou fournisseurs de stockage de clés (Key Storage Provider / Key Container), avec ProcessName et PID.
- Notez le binaire et le service associés (ex.
ServiceName
,ImagePath
, arguments).
Étape 2 : tracer les accès disque avec Process Monitor
- Lancez Process Monitor (Sysinternals) avec filtre :
- Path contains
\Microsoft\Crypto\RSA\
- Operation is
CreateFile
ouWriteFile
- Path contains
- Identifiez le processus fautif (nom, PID, service parent). Recherchez des modèles : pics à chaque handshake TLS, chaque requête HTTP, chaque job planifié.
- Corrigez ou mettez à jour ce composant : un paramétrage (TLS, certificats, persistance des clés), un bug connu, ou une mauvaise pratique d’API (absence du flag éphémère) sont souvent en cause.
Étape 3 : lister les clés côté LocalService (optionnel, avancé)
Le catalogue dépend du contexte de sécurité. Pour voir les conteneurs du compte LocalService, exécutez la commande dans ce contexte (via une tâche planifiée qui s’exécute en LocalService) :
schtasks /Create /TN "ListKeys" /SC ONCE /ST 23:59 /RU "NT AUTHORITY\LOCAL SERVICE" ^
/TR "cmd /c certutil -user -key > C:\Temp\LocalService-keys.txt" /F
schtasks /Run /TN "ListKeys"
Puis procédez à une analyse ciblée (suppression d’un conteneur précis) si nécessaire :
certutil -user -delkey <NomDuConteneur>
Réservé aux administrateurs expérimentés : une suppression erronée peut bloquer l’application.
Outils & objectifs (récapitulatif)
Outil | Objectif | À observer |
---|---|---|
Journal CAPI2 (Operational) | Tracer l’acquisition/stockage de clés | Processus/PID, conteneur visé, provider (CAPI/CNG) |
Process Monitor | Voir les créations/écritures de fichiers | Path \Microsoft\Crypto\RSA , fréquence, stack trace |
Tâche planifiée en LocalService | Lister/supprimer des conteneurs spécifiques | Sortie de certutil -user -key |
B. Nettoyage sécurisé (sans casser les services)
1) Sauvegarder & isoler
- Copiez le dossier
...\Microsoft\Crypto\RSA
vers un volume de quarantaine (hors partition système) pour rollback. - Si le volume est critique, prenez un snapshot (VSS) ou une sauvegarde avant toute action.
2) Arrêter le service responsable (si identifié)
Mettez l’application en maintenance pour libérer les verrous. Si l’identification n’est pas fiable, planifiez une fenêtre courte (5–15 min) avec test applicatif après nettoyage partiel.
3) Prendre possession et droits
Les fichiers appartiennent généralement à LOCAL SERVICE. Donnez-vous la main en Admin élevé :
takeown /f "C:\Windows\ServiceProfiles\LocalService\AppData\Roaming\Microsoft\Crypto\RSA" /r /d y
icacls "C:\Windows\ServiceProfiles\LocalService\AppData\Roaming\Microsoft\Crypto\RSA" /grant Administrators:F /t
4) Purger par ancienneté, d’abord en mode « simulation »
Déplacer d’abord les fichiers les plus anciens (ex. > 30 jours) vers une quarantaine, puis supprimer si tout fonctionne :
$src = "C:\Windows\ServiceProfiles\LocalService\AppData\Roaming\Microsoft\Crypto\RSA"
$dst = "D:\Quarantaine_RSA"
New-Item -ItemType Directory -Path $dst -Force | Out-Null
# Simulation : -WhatIf
Get-ChildItem -LiteralPath \$src -Recurse -File |
Where-Object LastWriteTime -lt (Get-Date).AddDays(-30) |
Move-Item -Destination \$dst -WhatIf
Retirez -WhatIf
une fois la sélection validée. Surveillez ensuite l’application quelques heures ; si rien ne rompt, supprimez la quarantaine.
5) Purge à très grand volume (par lots)
Des millions d’objets rendent Remove-Item
ou l’Explorateur très lents. Traitez en petits lots pour éviter les timeouts et la saturation CPU :
$path = "C:\Windows\ServiceProfiles\LocalService\AppData\Roaming\Microsoft\Crypto\RSA"
$thresholdDays = 30
$batch = 20000 # Ajustez selon la machine
$log = "C:\Temp\purge-rsa.log"
Start-Transcript -Path \$log -Append
try {
do {
\$toDelete = Get-ChildItem -LiteralPath \$path -Recurse -File -Force |
Where-Object LastWriteTime -lt (Get-Date).AddDays(-\$thresholdDays) |
Select-Object -First \$batch
```
if ($toDelete.Count -gt 0) {
$toDelete | Remove-Item -Force -ErrorAction SilentlyContinue
Write-Host "Supprimé: $($toDelete.Count) fichiers..."
Start-Sleep -Seconds 2
}
```
} while (\$toDelete.Count -gt 0)
}
finally { Stop-Transcript }
6) Chemins très longs / fichiers « accrochés »
- Privilégiez le préfixe de chemin
\\?\
pour contourner les limites héritées :cmd /c del /f /q "\\?\C:\Windows\ServiceProfiles\LocalService\AppData\Roaming\Microsoft\Crypto\RSA\*"
- Fermez les handles ouverts (arrêt du service), puis réessayez.
- Si des éléments restent « indélébiles », redémarrez en Mode sans échec ou supprimez hors ligne depuis un environnement WinPE.
7) Option de déplacement massif avec Robocopy (rapide)
Pour déplacer des millions de fichiers vers une quarantaine sans les ré‑énumérer côté PowerShell :
robocopy "C:\Windows\ServiceProfiles\LocalService\AppData\Roaming\Microsoft\Crypto\RSA" "D:\Quarantaine_RSA" *.* /MOV /E /R:1 /W:1 /NFL /NDL /NJH /NJS /NP
Vous pouvez limiter aux fichiers « anciens » (ex. ≥ 30 jours) :
robocopy "C:\...\Crypto\RSA" "D:\Quarantaine_RSA" *.* /MOV /E /MINAGE:30 /R:1 /W:1 /NFL /NDL /NJH /NJS /NP
Attention : ne jamais /MIR
directement vers un dossier critique sans comprendre l’impact.
C. Prévenir la récidive
- Corriger/mettre à jour l’application fautive ou son agent (reverse proxy Windows, EDR/AV, SDK interne, service .NET/WCF, connecteur LDAP/TLS, etc.).
- Revoir la configuration TLS/crypto : éviter la persistance inutile des clés temporaires, valider l’usage de magasins adéquats.
- Mettre à jour Windows et les dépendances (.NET, pilotes réseau, agents de sécurité, proxy), puis vérifier le comportement sous charge.
- Laisser CAPI2 activé quelques jours ; confirmer l’arrêt de la fuite (zéro nouvel événement de création répétée de conteneurs).
Pourquoi la suppression échoue souvent
Symptôme | Cause probable | Action |
---|---|---|
Access denied | Propriétaire LOCAL SERVICE, ACL restrictives | takeown + icacls puis suppression |
« Fichier utilisé par un autre processus » | Handle ouvert par le service | Arrêt du service, puis nouvelle tentative |
Explorateur se fige | Énumération d’un répertoire avec des millions d’entrées | Ligne de commande/PowerShell, traitement par lots |
Échec aléatoire | Antivirus/EDR scannant chaque fichier | Exclure temporairement le chemin le temps du nettoyage |
Différences de chemins à ne pas confondre
- Profil LocalService :
C:\Windows\ServiceProfiles\LocalService\AppData\Roaming\Microsoft\Crypto\RSA\<SID>
(cible du présent article). - Niveau machine :
C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys
(clés système/serveur). Ne pas purger sans analyse approfondie. - Profil utilisateur :
%APPDATA%\Microsoft\Crypto\RSA\<SID>
(session interactive/service dédié).
Bonnes pratiques de maintenance
- Fenêtre de maintenance : prévenir les équipes applicatives, sauvegarder, noter l’heure de début/fin, valider par un test fonctionnel.
- Quarantaine systématique avant suppression définitive (surtout en cas d’application tierce opaque).
- Journalisation : transcript PowerShell, évènements clés, nombre d’éléments déplacés/supprimés.
Surveillance continue (détection précoce)
Placez une alerte simple sur le nombre de fichiers et la croissance journalière dans le dossier :
$path = "C:\Windows\ServiceProfiles\LocalService\AppData\Roaming\Microsoft\Crypto\RSA"
$count = (Get-ChildItem -LiteralPath $path -Recurse -File -ErrorAction SilentlyContinue).Count
$threshold = 50000 # ajustez selon votre contexte
if ($count -gt $threshold) {
Write-EventLog -LogName Application -Source "RSA-Monitor" -EntryType Warning -EventId 5001 `
-Message "Crypto\RSA contient $count fichiers (> $threshold)."
}
Créez la source une fois :
New-EventLog -LogName Application -Source "RSA-Monitor"
Planifiez ce script toutes les heures via le Planificateur de tâches.
Pour les équipes de développement (prévention côté code)
- Réexaminer l’usage des API crypto : lorsqu’une clé temporaire suffit, utiliser les flags éphémères (éviter la persistance des conteneurs).
- Réutiliser les contextes de clé au lieu d’en créer un par requête.
- Réparer les traitements d’erreur qui laissent des conteneurs orphelins.
- Migrer vers des fournisseurs CNG modernes si possible et vérifier la politique de stockage.
FAQ rapide
Peut‑on supprimer tout le dossier « RSA » ?
À éviter. Le dossier et certains sous‑répertoires (associés au SID de LocalService) sont nécessaires. Privilégiez une purge par ancienneté et par lots, après arrêt du service fautif.
Comment savoir si un fichier est encore utilisé ?
Si la suppression échoue hors production et que CAPI2/ProcMon ne montrent plus d’accès récents, il est probablement orphelin. En cas de doute, placez‑le en quarantaine avant suppression définitive.
Pourquoi l’Explorateur met‑il si longtemps à ouvrir le dossier ?
Parce qu’il essaye d’énumérer des millions d’entrées et de résoudre leurs métadonnées. Utilisez la ligne de commande et traitez par lots.
La pile TLS de Windows recrée‑t‑elle des conteneurs si on en supprime ?
Oui, si l’application en a besoin. D’où l’importance de corriger la source de la fuite (paramétrage/bug) avant de purger, sinon l’accumulation repartira.
Checklist express d’intervention
- ✔️ Activer CAPI2 et lancer ProcMon.
- ✔️ Identifier le service fautif (binaire, version, configuration TLS/crypto).
- ✔️ Mettre l’application en maintenance, takeown/icacls.
- ✔️ Purger > 30 jours vers quarantaine, puis supprimer après validation.
- ✔️ Déployer correctif (update/config) et surveiller la reprise.
- ✔️ Mettre en place une alerte de volume et laisser CAPI2 actif quelques jours.
En bref
- Les fichiers sont des conteneurs de clés RSA du profil LocalService.
- Des millions d’objets = anomalie d’un service (fuite de clés).
- Diagnostiquer avec CAPI2 + ProcMon, corriger l’app fautive, puis nettoyer prudemment (prise de possession, purge par ancienneté, quarantaine).
- Surveiller ensuite pour s’assurer que l’accumulation ne reprend pas.
Annexe : scripts prêts à l’emploi
Script PowerShell — purge sécurisée (avec journal)
param(
[string]$Path = "C:\Windows\ServiceProfiles\LocalService\AppData\Roaming\Microsoft\Crypto\RSA",
[int]$OlderThanDays = 30,
[int]$BatchSize = 20000,
[switch]$WhatIfMode
)
\$log = "C:\Temp\CryptoRSA-Purge-\$(Get-Date -Format yyyyMMdd-HHmmss).log"
New-Item -ItemType Directory -Path (Split-Path \$log) -Force | Out-Null
Start-Transcript -Path \$log
try {
Write-Host "Démarrage purge sur \$Path (fichiers > \$OlderThanDays jours), lots de \$BatchSize..."
\$cut = (Get-Date).AddDays(-\$OlderThanDays)
do {
\$batch = Get-ChildItem -LiteralPath \$Path -Recurse -File -Force -ErrorAction SilentlyContinue |
Where-Object LastWriteTime -lt \$cut |
Select-Object -First \$BatchSize
```
$n = $batch.Count
if ($n -eq 0) { break }
if ($WhatIfMode) {
$batch | ForEach-Object { Write-Host "SIMULATION : $_" }
} else {
$batch | Remove-Item -Force -ErrorAction SilentlyContinue
}
Write-Host "Traitement d'un lot de $n fichiers terminé."
Start-Sleep -Milliseconds 500
```
} while (\$true)
Write-Host "Purge terminée."
}
catch {
Write-Warning $\_.Exception.Message
}
finally {
Stop-Transcript
}
Script PowerShell — comptage & alerte
$path = "C:\Windows\ServiceProfiles\LocalService\AppData\Roaming\Microsoft\Crypto\RSA"
$limit = 100000
$count = (Get-ChildItem -LiteralPath $path -Recurse -File -ErrorAction SilentlyContinue).Count
"{0:u} : {1} fichiers dans {2}" -f (Get-Date), $count, $path | Tee-Object -FilePath C:\Temp\CryptoRSA-Count.log -Append
if ($count -gt $limit) {
Write-EventLog -LogName Application -Source "RSA-Monitor" -EntryType Warning -EventId 5002 `
-Message "Seuil dépassé : $count > $limit dans $path."
}
Exemples de causes fréquentes (retour d’expérience)
- Services web .NET activant TLS mutualisé sans réutilisation de contextes ; chaque appel génère un conteneur.
- Agents de sécurité/EDR interceptant la crypto et provoquant des écritures répétées de clés temporaires persistées.
- Proxys/accélérateurs Windows faisant du SSL bridging avec un paramétrage qui force la persistance des clés éphémères.
- Script/outil qui appelle la CryptoAPI sans le flag correct (clés non éphémères).
Conclusion
Un dossier Crypto\RSA
saturé sur Windows Server 2019 n’est pas une fatalité. La recette : diagnostiquer précisément avec CAPI2 et ProcMon, corriger l’application à la source, puis nettoyer progressivement (quarantaine, ancienneté, lots) en respectant une fenêtre de maintenance. En quelques itérations, vous retrouvez un système propre et stable, sans surprises côté TLS ou authentification.