Question

J'essaie de décrire l'objectif de SecureString de .NET. À partir de MSDN:

  

Une instance de la classe System.String est à la fois immuable et, lorsqu'elle n'est plus nécessaire, elle ne peut pas être programmée par programme pour le garbage collection. c'est-à-dire que l'instance est en lecture seule après sa création et qu'il est impossible 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 est possible 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 sens qu'il a une valeur textuelle. Toutefois, la valeur d'un objet SecureString est automatiquement chiffrée, peut être modifiée jusqu'à ce que votre application le marque en lecture seule et puisse être supprimée de la mémoire de l'ordinateur par votre application ou par le nettoyeur de déchets .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 un grand 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 est l'aspect de SecureString qui me manque?

Était-ce utile?

La solution

Certaines parties de la structure qui utilisent actuellement SecureString :

L'objectif principal est de réduire la surface d'attaque, plutôt que de l'éliminer. SecureStrings sont " ; épinglé " dans la RAM afin que le ramasse-miettes ne le déplace pas et ne le copie pas. Cela garantit également que le texte brut ne sera pas écrit dans le fichier d'échange ou dans les vidages de mémoire. Le cryptage s'apparente davantage à une obfuscation et n'empêche pas un pirate informatique déterminé, qui pourrait trouver le clé symétrique utilisée pour le chiffrer et le déchiffrer.

Comme d'autres l'ont déjà dit, vous devez créer un SecureString caractère par caractère est le premier défaut évident à faire autrement: vous avez probablement la valeur secrète sous forme de chaîne simple, quel est donc le point?

SecureString s constituent la première étape de la résolution d’un problème poulet-œuf, alors même si la plupart des scénarios actuels exigent de les reconvertir en chaînes normales pour pouvoir les utiliser, leur présence dans le cadre signifie désormais qu’ils sont mieux pris en charge. l'avenir - au moins au point où votre programme ne doit pas nécessairement être le maillon faible.

Autres conseils

Beaucoup de bonnes réponses; Voici un résumé rapide de ce qui a été discuté.

Microsoft a mis en œuvre la classe SecureString dans le but de renforcer la sécurité des informations sensibles (telles que les cartes de crédit, les mots de passe, etc.). Il fournit automatiquement:

  • chiffrement (en cas de vidage de la mémoire ou la mise en cache de la page)
  • épingler en mémoire
  • possibilité de marquer en lecture seule (pour éviter toute modification ultérieure)
  • construction sûre en ne permettant PAS à une chaîne constante d'être passée dans

Actuellement, l'utilisation de SecureString est limitée, mais une meilleure adoption est attendue à l'avenir.

Sur la base de ces informations, le constructeur de SecureString ne devrait pas simplement prendre une chaîne et la découper dans un tableau de caractères, car la chaîne épelée annulait l'objectif de SecureString.

Informations supplémentaires:

  • Un publication de la sécurité .NET blog parle à peu près la même chose que couvert ici.
  • Et un autre un revisiter et mentionner un outil qui peut vider le contenu de la SecureString.

Edit: J'ai eu du mal à choisir la meilleure réponse car il y a de bonnes informations dans beaucoup de cas; dommage qu'il n'y ait pas d'options de réponse assistée.

Réponse courte

  

pourquoi ne puis-je pas simplement dire:

SecureString password = new SecureString("password");

Parce que maintenant vous avez mot de passe en mémoire; sans moyen de l'effacer - ce qui est exactement le point de SecureString .

Réponse longue

Si SecureString existe, c'est que vous ne pouvez pas utiliser ZeroMemory pour effacer les données sensibles une fois que vous en avez terminé. Il existe pour résoudre un problème existant car dans le CLR.

Dans une application native normale, appelez SecureZeroMemory :

  

Remplit un bloc de mémoire avec des zéros.

Remarque : SecureZeroMemory est identique à ZeroMemory , sauf que le compilateur ne l'optimise pas.

Le problème est que vous ne pouvez pas appeler ZeroMemory ou SecureZeroMemory dans .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:

//Wipe out the password
for (int i=0; i<password.Length; i++)
   password[i] = \0;

Alors que pouvez-vous faire? Comment permet-on 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 fini?

La seule façon de le faire serait de placer la chaîne dans un bloc de mémoire natif , où vous pouvez appeler ensuite ZeroMemory . Un objet de mémoire natif tel que:

  • un BSTR
  • un HGLOBAL
  • mémoire non gérée CoTaskMem

SecureString rend la capacité perdue

Dans .NET, les chaînes ne peuvent pas être effacées lorsque vous avez terminé:

  • ils sont immuables; vous ne pouvez pas écraser leur contenu
  • vous ne pouvez pas en disposer
  • leur nettoyage est à la merci du ramasse-miettes

SecureString existe comme moyen de contourner la sécurité des chaînes et de garantir leur nettoyage lorsque vous en avez besoin.

Vous avez posé la question:

  

pourquoi ne puis-je pas simplement dire:

String connectionString = secureConnectionString.ToString()

Parce que maintenant vous avez mot de passe en mémoire; sans moyen de l'essuyer. Il est bloqué jusqu'à ce que le CLR décide de réutiliser cette mémoire. Vous nous avez remis exactement 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 swap, les vidages sur incident ou même dans la fenêtre des variables locales avec un collègue qui surveillera votre dossier.

Comment lire le mot de passe?

Alors se pose la question: comment puis-je interagir avec la chaîne? Vous ne voulez absolument pas une méthode telle que:

SqlCredential cred = new SqlCredential(userid, password); //password is SecureString
SqlConnection conn = new SqlConnection(connectionString);
conn.Credential = cred;
conn.Open();

parce que vous êtes maintenant de retour à votre point de départ - un mot de passe dont vous ne pouvez 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 la raison pour laquelle .NET fournit trois fonctions d’aide utiles pour rassembler une chaîne SecureString dans une mémoire non gérée:

Vous convertissez la chaîne en un blob de mémoire non géré, vous la manipulez, puis vous l'effacez à nouveau.

Certaines API acceptent SecureStrings . Par exemple, dans ADO.net 4.5, SqlConnection.Credential prend un ensemble SqlCredential :

SqlConnection.ChangePassword(connectionString, cred, newPassword);

Vous pouvez également modifier le mot de passe dans une chaîne de connexion:

private static string CreateString(SecureString secureString)
{
    IntPtr intPtr = IntPtr.Zero;
    if (secureString == null || secureString.Length == 0)
    {
        return string.Empty;
    }
    string result;
    try
    {
        intPtr = Marshal.SecureStringToBSTR(secureString);
        result = Marshal.PtrToStringBSTR(intPtr);
    }
    finally
    {
        if (intPtr != IntPtr.Zero)
        {
            Marshal.ZeroFreeBSTR(intPtr);
        }
    }
    return result;
}

Et il existe de nombreux endroits dans .NET où ils continuent d’accepter une chaîne simple à des fins de compatibilité, puis de rapidement la transformer en une chaîne SecureString.

Comment insérer du texte dans SecureString?

Cela laisse toujours le problème:

  

Comment puis-je obtenir un mot de passe dans SecureString en premier lieu?

C'est le défi, mais le but est de vous faire réfléchir sur la sécurité.

Parfois, les fonctionnalités vous sont déjà fournies. Par exemple, le contrôle WPF PasswordBox peut vous renvoyer directement le mot de passe saisi sous forme de SecureString :

  

PasswordBox Propriété .SecurePassword

     

Obtient le mot de passe actuellement détenu par le PasswordBox en tant que SecureString .

Cela est utile car partout où vous utilisiez une chaîne brute, vous avez maintenant le système de types qui se plaint de l'incompatibilité de SecureString avec String. Vous voulez partir le plus longtemps possible avant de devoir reconvertir votre SecureString en chaîne normale.

La conversion d'une chaîne SecureString est assez simple:

  • SecureStringToBSTR
  • PtrToStringBSTR

comme dans:

for (int i=0; i < PasswordArray.Length; i++)
{
   password.AppendChar(PasswordArray[i]);
   PasswordArray[i] = (Char)0;
}

Ils ne veulent vraiment pas que vous le fassiez.

Mais comment puis-je insérer une chaîne dans un SecureString? Ce que vous devez faire, c'est commencer par cesser de saisir un mot de passe dans une Chaîne . Vous deviez l'avoir dans quelque chose autrement. Même un tableau Char [] serait utile.

Vous pouvez ensuite ajouter chaque caractère et pour supprimer le texte en clair lorsque vous avez terminé:

<*>

Votre mot de passe doit être stocké dans une mémoire que vous pouvez effacer. Chargez-le dans le SecureString à partir de là.

tl; dr: SecureString existe pour fournir l'équivalent de ZeroMemory .

Certaines personnes ne voient pas l'intérêt de effacer le mot de passe de l'utilisateur de la mémoire lorsqu'un périphérique est verrouillé , ou effacez effacement des frappes de mémoire après leur authentification . Ces personnes n'utilisent pas SecureString.

Il existe très peu de scénarios dans lesquels vous pouvez utiliser judicieusement 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 marshaler à l'aide de Marshal.SecureStringToGlobalAllocUnicode.

Dès que vous l'avez converti en / à partir d'un System.String, vous en avez perdu le but.

Le exemple de MSDN génère le SecureString un caractère à la fois à partir de console et passe la chaîne sécurisée à une API non gérée. C'est plutôt compliqué et irréaliste.

Vous pouvez vous attendre à ce que les versions futures de .NET prennent davantage en charge SecureString, ce qui le rendra plus utile, par exemple:

.
  • SecureString Console.ReadLineSecure () ou similaire pour lire une entrée de console dans un SecureString sans tout le code compliqué 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 entrés de manière sécurisée.

  • Extensions aux API liées à la sécurité pour permettre la transmission de mots de passe en tant que SecureString.

Sans ce qui précède, SecureString aura une valeur limitée.

Je pense que la raison pour laquelle vous devez ajouter un caractère au lieu d'une instanciation plate est parce qu'en arrière-plan, vous passez le mot de passe " mot de passe " au constructeur de SecureString insère ce " mot de passe " chaîne en mémoire annulant le but de la chaîne sécurisée.

En ajoutant, vous ne faites que mettre en mémoire un caractère à la fois, ce qui a peu de chances de ne pas être physiquement adjacents, ce qui rend beaucoup plus difficile la reconstruction de la chaîne d'origine. Je peux me tromper ici mais c'est comme ça que ça m'a été expliqué.

Le but de la classe est d'empêcher que des données sécurisées soient exposées via un vidage de mémoire ou un outil similaire.

MS a constaté que, dans certains cas de panne du serveur (poste de travail ou autre), l'environnement d'exécution effectuait parfois un vidage de la mémoire en exposant le contenu de ce qui était 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.

L'un des gros avantages de SecureString est qu'il est supposé éviter la possibilité que vos données soient stockées sur le disque en raison de la mise en cache des pages. Si vous avez un mot de passe en mémoire et que vous chargez ensuite un programme volumineux ou un ensemble de données volumineux, votre mot de passe peut être écrit dans le fichier d'échange lorsque votre programme est paginé de la mémoire. Avec un SecureString, au moins les données ne resteront pas indéfiniment sur votre disque en texte clair.

Je suppose que c’est parce que la chaîne est censée être sécurisée, c’est-à-dire qu’un pirate informatique ne devrait pas pouvoir la lire. Si vous l'initialisez avec une chaîne, le pirate pourrait lire la chaîne d'origine.

Eh bien, comme le dit la description, la valeur est stockée sous forme 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 parce qu'alors vous auriez une version non chiffrée de la chaîne en mémoire. En vous limitant à la création de la chaîne par morceaux, vous réduisez le risque que la chaîne entière soit en mémoire en même temps.

Je cesserais d'utiliser SecureString. On dirait que les gars de PG abandonnent tout soutien. Peut-être même tirez-vous dans le futur - https://github.com / dotnet / apireviews / tree / master / 2015-07-14-securestring .

  

Nous devrions supprimer le cryptage de SecureString sur toutes les plates-formes de .NET Core - Nous devrions obsolètes SecureString - Nous ne devrions probablement pas exposer SecureString dans .NET Core

Un autre cas d'utilisation concerne les applications de paiement (POS) et vous ne pouvez tout simplement pas utiliser de structures de données immuables afin de stocker des données sensibles, car vous êtes un développeur avisé. 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 un cas où ces données seront disponibles en mémoire pendant un laps de temps important après leur suppression. Je ne peux pas simplement l'écraser. Un autre avantage considérable est que ces données sensibles conservées en mémoire sont cryptées.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top