J'essaye de comprendre le but de SecureString de .NET. Depuis MSDN:
Une instance de la classe System.String est à la fois immuable et, lorsqu'elle n'est plus nécessaire, ne peut pas être planifiée par programme pour le garbage collection; autrement dit, l'instance est en lecture seule après sa création et il n'est pas possible de prédire quand l'instance sera supprimée de la mémoire de l'ordinateur. Par conséquent, si un objet String contient des informations sensibles telles qu'un mot de passe, un numéro de carte de crédit ou des données personnelles, il existe un risque que les informations soient révélées après leur utilisation car votre application ne peut pas supprimer les données de la mémoire de l'ordinateur.
Un objet SecureString est similaire à un objet String en ce qu'il a une valeur de texte. Toutefois, la valeur d'un objet SecureString est automatiquement chiffrée, peut être modifiée jusqu'à ce que votre application le marque comme étant en lecture seule et peut être supprimée de la mémoire de l'ordinateur par votre application ou le garbage collector .NET Framework.
La valeur d'une instance de SecureString est automatiquement chiffrée lorsque l'instance est initialisée ou lorsque la valeur est modifiée. Votre application peut rendre l'instance immuable et empêcher toute modification ultérieure en appelant la méthode MakeReadOnly.
Le cryptage automatique est-il le gros avantage?
Et pourquoi ne puis-je pas simplement dire:
SecureString password = new SecureString("password");
au lieu de
SecureString pass = new SecureString();
foreach (char c in "password".ToCharArray())
pass.AppendChar(c);
Quel aspect de SecureString me manque-t-il?
la source
SecureString
de nouveau développement: github.com/dotnet/platform-compat/blob/master/docs/DE0001.mdRéponses:
J'arrêterais d'utiliser SecureString. On dirait que les gars de PG abandonnent leur soutien. Peut-être même le tirer à l'avenir - https://github.com/dotnet/apireviews/tree/master/2015-07-14-securestring .
la source
Certaines parties du framework qui utilisent actuellement
SecureString
:System.Windows.Controls.PasswordBox
contrôle de WPF conserve le mot de passe en tant que SecureString en interne (exposé en tant que copiePasswordBox::SecurePassword
)System.Diagnostics.ProcessStartInfo::Password
propriété est unSecureString
X509Certificate2
prend unSecureString
pour le mot de passeL'objectif principal est de réduire la surface d'attaque plutôt que de l'éliminer.
SecureStrings
sont «épinglés» dans la RAM afin que le garbage collector ne le déplace pas ou n'en fasse pas de copies. Il s'assure également que le texte brut ne sera pas écrit dans le fichier d'échange ou dans les vidages de mémoire. Le cryptage ressemble plus à une obfuscation et n'arrêtera pas un pirate informatique déterminé, qui serait en mesure de trouver la clé symétrique utilisée pour crypter et décrypter.Comme d'autres l'ont dit, la raison pour laquelle vous devez créer un
SecureString
caractère par caractère est le premier défaut évident de faire autrement: vous avez probablement déjà la valeur secrète sous forme de chaîne simple, alors à quoi ça sert?SecureString
s sont la première étape dans la résolution d'un problème Chicken-and-Egg, donc même si la plupart des scénarios actuels nécessitent de les reconvertir en chaînes régulières pour en faire un usage quelconque, leur existence dans le framework signifie désormais un meilleur support pour eux dans le futur - au moins à un point où votre programme ne doit pas être le maillon faible.la source
Edit : n'utilisez pas SecureString
Les directives actuelles indiquent maintenant que la classe ne doit pas être utilisée. Les détails peuvent être trouvés sur ce lien: https://github.com/dotnet/platform-compat/blob/master/docs/DE0001.md
Extrait de l'article:
DE0001: SecureString ne doit pas être utilisé
Motivation
SecureString
est d'éviter d'avoir des secrets stockés dans la mémoire du processus sous forme de texte brut.SecureString
n'existe pas de concept de système d'exploitation.System.String
- la durée de vie du tampon natif est plus courte.Recommandation
Ne pas utiliser
SecureString
pour un nouveau code. Lorsque vous portez du code vers .NET Core, considérez que le contenu du tableau n'est pas chiffré en mémoire.L'approche générale du traitement des informations d'identification consiste à les éviter et à s'appuyer à la place sur d'autres moyens pour s'authentifier, tels que les certificats ou l'authentification Windows.
Fin de la modification: résumé original ci-dessous
Beaucoup de bonnes réponses; voici un bref résumé de ce qui a été discuté.
Microsoft a implémenté la classe SecureString dans le but de fournir une meilleure sécurité avec les informations sensibles (comme les cartes de crédit, les mots de passe, etc.). Il fournit automatiquement:
Actuellement, l'utilisation de SecureString est limitée, mais on s'attend à une meilleure adoption à l'avenir.
Sur la base de ces informations, le constructeur de SecureString ne doit pas simplement prendre une chaîne et la découper en tableau de caractères, car la chaîne est épelée contre l'objectif de SecureString.
Information additionnelle:
Edit: J'ai trouvé difficile de choisir la meilleure réponse car il y a de bonnes informations dans beaucoup; dommage qu'il n'y ait pas d'options de réponse assistée.
la source
Réponse courte
Parce que maintenant vous avez
password
en mémoire; sans moyen de l'effacer - ce qui est exactement le but de SecureString .Longue réponse
La raison pour laquelle SecureString existe est que vous ne pouvez pas utiliser ZeroMemory pour effacer les données sensibles lorsque vous en avez terminé. Il existe pour résoudre un problème qui existe à cause du CLR.
Dans une application native standard , vous appelleriez
SecureZeroMemory
:Remarque : SecureZeroMemory est identique à
ZeroMemory
, sauf que le compilateur ne l'optimisera pas.Le problème est que vous ne pouvez pas appeler
ZeroMemory
ou à l'SecureZeroMemory
intérieur de .NET. Et dans .NET, les chaînes sont immuables; vous ne pouvez même pas écraser le contenu de la chaîne comme vous pouvez le faire dans d'autres langues:Alors que peux-tu faire? Comment pouvons-nous offrir la possibilité dans .NET d'effacer un mot de passe ou un numéro de carte de crédit de la mémoire lorsque nous en avons terminé?
La seule façon de le faire serait de placer la chaîne dans un bloc de mémoire natif , où vous pouvez ensuite appeler
ZeroMemory
. Un objet mémoire natif tel que:SecureString redonne la capacité perdue
Dans .NET, les chaînes ne peuvent pas être effacées lorsque vous en avez terminé avec elles:
Dispose
d'euxSecureString existe comme un moyen de transmettre la sécurité des chaînes et de garantir leur nettoyage lorsque vous en avez besoin.
Vous avez posé la question:
Parce que maintenant vous avez
password
en mémoire; sans moyen de l'essuyer. Il est bloqué là jusqu'à ce que le CLR décide de réutiliser cette mémoire. Vous nous avez remis là où nous avons commencé; une application en cours d'exécution avec un mot de passe dont nous ne pouvons pas nous débarrasser et où un vidage de la mémoire (ou Process Monitor) peut voir le mot de passe.SecureString utilise l'API de protection des données pour stocker la chaîne chiffrée en mémoire; de cette façon, la chaîne n'existera pas dans les fichiers d'échange, les vidages sur incident ou même dans la fenêtre des variables locales avec un collègue qui regarde votre devrait.
Comment lire le mot de passe?
Puis se pose la question: comment interagir avec la chaîne? Vous ne voulez absolument pas d'une méthode comme:
car maintenant vous êtes de retour là où vous avez commencé - un mot de passe dont vous ne pouvez pas vous débarrasser. Vous voulez forcer les développeurs à gérer correctement la chaîne sensible - afin qu'elle puisse être effacée de la mémoire.
C'est pourquoi .NET fournit trois fonctions d'assistance pratiques pour rassembler un SecureString dans une mémoire non managée:
Vous convertissez la chaîne en un objet blob de mémoire non géré, vous la gérez et l'effacez à nouveau.
Certaines API acceptent SecureStrings . Par exemple dans ADO.net 4.5, SqlConnection.Credential prend un ensemble SqlCredential :
Vous pouvez également modifier le mot de passe dans une chaîne de connexion:
Et il y a beaucoup d'endroits dans .NET où ils continuent d'accepter une chaîne simple à des fins de compatibilité, puis se retournent rapidement et la placent dans un SecureString.
Comment mettre du texte dans SecureString?
Cela laisse toujours le problème:
C'est le défi, mais le but est de vous faire réfléchir à la sécurité.
Parfois, la fonctionnalité est déjà fournie pour vous. Par exemple, le contrôle WPF PasswordBox peut vous renvoyer directement le mot de passe saisi sous forme de SecureString :
Ceci est utile car partout où vous aviez l'habitude de transmettre une chaîne brute, vous avez maintenant le système de types se plaignant que SecureString est incompatible avec String. Vous voulez aller le plus longtemps possible avant de devoir reconvertir votre SecureString en chaîne régulière.
La conversion d'un SecureString est assez simple:
un péché:
Ils ne veulent vraiment pas que vous le fassiez.
Mais comment obtenir une chaîne dans un SecureString? Eh bien, ce que vous devez faire est d'arrêter d'avoir un mot de passe dans une chaîne en premier lieu. Vous aviez besoin de l'avoir dans autre chose . Même un
Char[]
tableau serait utile.C'est à ce moment que vous pouvez ajouter chaque caractère et effacer le texte brut lorsque vous avez terminé:
Vous avez besoin de votre mot de passe stocké dans une mémoire que vous pouvez effacer. Chargez-le dans SecureString à partir de là.
tl; dr: SecureString existe pour fournir l'équivalent de ZeroMemory .
Certaines personnes ne voient pas l'intérêt d' effacer le mot de passe de l'utilisateur de la mémoire lorsqu'un appareil est verrouillé , ou d' effacer les frappes de la mémoire après leur authentification . Ces personnes n'utilisent pas SecureString.
la source
Il existe très peu de scénarios dans lesquels vous pouvez raisonnablement utiliser SecureString dans la version actuelle du Framework. Ce n'est vraiment utile que pour interagir avec des API non gérées - vous pouvez le rassembler à l'aide de Marshal.SecureStringToGlobalAllocUnicode.
Dès que vous le convertissez vers / depuis un System.String, vous avez atteint son objectif.
L' exemple MSDN génère le SecureString un caractère à la fois à partir de l'entrée de la console et transmet la chaîne sécurisée à une API non gérée. C'est plutôt alambiqué et irréaliste.
Vous pouvez vous attendre à ce que les futures versions de .NET prennent davantage en charge SecureString, ce qui le rendra plus utile, par exemple:
SecureString Console.ReadLineSecure () ou similaire pour lire l'entrée de la console dans un SecureString sans tout le code alambiqué de l'exemple.
Remplacement de WinForms TextBox qui stocke sa propriété TextBox.Text en tant que chaîne sécurisée afin que les mots de passe puissent être saisis en toute sécurité.
Extensions aux API liées à la sécurité pour permettre aux mots de passe d'être transmis en tant que SecureString.
Sans ce qui précède, SecureString aura une valeur limitée.
la source
Je crois que la raison pour laquelle vous devez ajouter des caractères au lieu d'une instanciation plate est que, en arrière-plan, le fait de passer "mot de passe" au constructeur de SecureString place cette chaîne de "mot de passe" en mémoire, ce qui va à l'encontre du but de la chaîne sécurisée.
En ajoutant, vous ne mettez en mémoire qu'un caractère à la fois, ce qui n'est probablement pas adjacent l'un à l'autre, ce qui rend la reconstruction de la chaîne d'origine beaucoup plus difficile. Je peux me tromper ici mais c'est ainsi que cela m'a été expliqué.
Le but de la classe est d'empêcher les données sécurisées d'être exposées via un vidage de mémoire ou un outil similaire.
la source
MS a constaté que sur certaines instances de plantage du serveur (bureau, peu importe), il y avait des moments où l'environnement d'exécution faisait un vidage de la mémoire exposant le contenu de ce qui est en mémoire. Secure String le chiffre en mémoire pour empêcher l'attaquant de récupérer le contenu de la chaîne.
la source
L'un des grands avantages d'un SecureString est qu'il est censé éviter la possibilité que vos données soient stockées sur le disque en raison de la mise en cache de la page. Si vous avez un mot de passe en mémoire et que vous chargez ensuite un programme ou un ensemble de données volumineux, votre mot de passe peut être écrit dans le fichier d'échange lorsque votre programme est paginé à court de mémoire. Avec un SecureString, au moins les données ne resteront pas indéfiniment sur votre disque en texte clair.
la source
Je suppose que c'est parce que la chaîne est censée être sécurisée, c'est-à-dire qu'un hacker ne devrait pas être capable de la lire. Si vous l'initialisez avec une chaîne, le pirate pourrait lire la chaîne d'origine.
la source
Eh bien, comme l'indique la description, la valeur est stockée cryptée, ce qui signifie qu'un vidage de la mémoire de votre processus ne révélera pas la valeur de la chaîne (sans un travail assez sérieux).
La raison pour laquelle vous ne pouvez pas simplement construire un SecureString à partir d'une chaîne constante est que vous auriez alors une version non chiffrée de la chaîne en mémoire. Le fait de vous limiter à créer la chaîne en morceaux réduit le risque d'avoir la chaîne entière en mémoire à la fois.
la source
Un autre cas d'utilisation est lorsque vous travaillez avec des applications de paiement (POS) et que vous ne pouvez tout simplement pas utiliser des structures de données immuables pour stocker des données sensibles car vous êtes un développeur prudent. Par exemple: si je stocke des données de carte sensibles ou des métadonnées d'autorisation dans une chaîne immuable, il y aura toujours le cas où ces données seront disponibles en mémoire pendant une période de temps significative après leur suppression. Je ne peux pas simplement l'écraser. Un autre avantage énorme où ces données sensibles sont conservées en mémoire cryptées.
la source