Kiedy będę potrzebował SecureString in.NET?

[[2]}próbuję podkręcić cel. NET ' s SecureString. Z MSDN:

Instancja systemu.Klasa String jest zarówno niezmienna, jak i, gdy nie jest już potrzebna, nie może być programowo zaplanowana do zbierania śmieci; to znaczy, instancja jest tylko do odczytu po jej utworzeniu i nie można przewidzieć, kiedy instancja zostanie usunięta z pamięci komputera. W związku z tym, jeśli obiekt String zawiera poufne informacje, takie jak hasło, numer karty kredytowej lub dane osobowe, istnieje ryzyko, że Informacje mogą zostać ujawnione po ich użyciu, ponieważ aplikacja nie może usunąć danych z pamięci komputera.

Obiekt SecureString jest podobny do obiektu String, ponieważ ma wartość tekstową. Jednak wartość obiektu SecureString jest automatycznie szyfrowana, może być modyfikowana, dopóki aplikacja nie oznaczy go jako Tylko do odczytu i może zostać usunięta z pamięci komputera przez aplikację lub. NET Framework garbage collector.

Wartość wystąpienia SecureString jest automatycznie szyfrowana, gdy wystąpienie jest inicjalizowane lub gdy wartość jest modyfikowana. Aplikacja może sprawić, że instancja stanie się niezmienna i zapobiec dalszej modyfikacji poprzez wywołanie metody MakeReadOnly.

Czy automatyczne szyfrowanie to duża wypłata?

And why can ' t I just say:

SecureString password = new SecureString("password");

Zamiast

SecureString pass = new SecureString();
foreach (char c in "password".ToCharArray())
    pass.AppendChar(c);

Jaki aspekt SecureString mi umyka?

Author: GEOCHET, 2008-09-26

11 answers

Niektóre części frameworka, które obecnie używają SecureString:

    Dzięki temu, że hasło jest przechowywane w bezpiecznym miejscu, można je odczytać na dysku twardym.]}
  • Właściwość System.Diagnostics.ProcessStartInfo::Password jest SecureString
  • konstruktor dla X509Certificate2 przyjmuje SecureString dla hasła

Głównym celem jest zmniejszenie powierzchni ataku, a nie jego wyeliminowanie. SecureStrings są "przypięte" w pamięci RAM, więc Garbage Collector nie będzie go przesuwał ani robił kopii. To również sprawia, że na pewno tekst jawny nie zostanie zapisany do pliku wymiany lub w zrzutach pamięci. Szyfrowanie jest bardziej jak zaciemnienie i nie zatrzyma zdeterminowanego hakera, który byłby w stanie znaleźć symetryczny klucz używany do szyfrowania i odszyfrowywania go.

Jak mówili inni, powodem, dla którego musisz utworzyć SecureString znak po znaku jest pierwsza oczywista wada robienia czegoś innego: prawdopodobnie masz już tajną wartość jako zwykły ciąg znaków, więc jaki to ma sens?

SecureStrings są pierwszy krok w rozwiązaniu problemu z kurczakiem i jajkiem, więc nawet jeśli większość obecnych scenariuszy wymaga przekształcenia ich z powrotem w zwykłe ciągi, aby w ogóle z nich skorzystać, ich istnienie w ramach oznacza teraz lepsze wsparcie dla nich w przyszłości-przynajmniej do punktu, w którym twój program nie musi być słabym ogniwem.

 104
Author: Chris Wenham,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-06 11:37:23

Wiele świetnych odpowiedzi; oto krótkie podsumowanie tego, co zostało omówione.

Microsoft zaimplementował klasę SecureString w celu zapewnienia lepszego bezpieczeństwa poufnych informacji (takich jak karty kredytowe, hasła itp.). Automatycznie dostarcza:

  • szyfrowanie (w przypadku zrzutów pamięci lub buforowanie strony)
  • przypinanie w pamięci
  • Możliwość oznaczania jako Tylko do odczytu (aby zapobiec dalszym modyfikacjom)
  • bezpieczna konstrukcja poprzez niedopuszczenie do stały ciąg znaków do przekazania w

Obecnie SecureString jest ograniczony w użyciu, ale spodziewaj się lepszego przyjęcia w przyszłości.

W oparciu o te informacje, konstruktor SecureString nie powinien pobierać tylko łańcucha znaków i kroić go do tablicy znaków, ponieważ wypisanie łańcucha łamie cel SecureString.

Dodatkowe informacje:

  • a post Z Bezpieczeństwa. NET blog mówiący o tym samym co tutaj.
  • i inne jeden przeglądając go i wspominając o narzędziu które mogą zrzucić zawartość SecureString.

Edit: trudno mi było wybrać najlepszą odpowiedź, ponieważ w wielu jest dobra informacja; szkoda, że nie ma opcji pomocy.

 34
Author: Richard Morgan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-29 12:29:46

Istnieje bardzo niewiele scenariuszy, w których można rozsądnie używać SecureString w obecnej wersji frameworka. Jest to naprawdę przydatne tylko do interakcji z niezarządzanymi interfejsami API - możesz go marshal za pomocą Marshal.SecureStringToGlobalAllocUnicode.

Jak tylko przekonwertujesz go do / z systemu.String, pokonałeś jego cel.

W przeciwieństwie do tego, że nie jest on w pełni kontrolowany przez konsolę, nie jest on w pełni kontrolowany przez konsolę i nie jest w pełni kontrolowany przez konsolę. To raczej zawiłe i nierealne.

Możesz oczekiwać, że przyszłe wersje. NET będą miały więcej wsparcia dla SecureString, co uczyni go bardziej użytecznym, np.:

  • Zabezpiecza Konsolę.ReadLineSecure () lub podobne do read console wejście do SecureString bez całego zawiłego kodu w próbce.

  • WinForms TextBox replacement, który przechowuje swoje pole tekstowe.Właściwość tekstowa jako bezpieczny ciąg znaków, dzięki czemu można wprowadzać hasła bezpiecznie.

  • Rozszerzenia interfejsów API związanych z bezpieczeństwem umożliwiające przekazywanie haseł jako SecureString.

Bez powyższego, SecureString będzie miał ograniczoną wartość.

 13
Author: Joe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-26 19:02:03

Uważam, że powodem, dla którego musisz zrobić dodawanie znaków zamiast jednej płaskiej instancji jest to, że w tle przekazanie "password" do konstruktora SecureString umieszcza ten łańcuch "password" w pamięci, pokonując cel secure string.

Poprzez dodawanie umieszczasz w pamięci tylko znaki, które nie sąsiadują ze sobą fizycznie, co znacznie utrudnia odtworzenie oryginalnego ciągu. Mogę się mylić, ale w ten sposób zostało mi to wyjaśnione.

Celem klasy jest zapobieganie ujawnieniu bezpiecznych danych za pomocą zrzutu pamięci lub podobnego narzędzia.

 11
Author: JoshReedSchramm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-26 18:47:52

MS odkrył, że w pewnych przypadkach powodujących awarię serwera (pulpitu, niezależnie od tego) zdarzały się sytuacje, w których środowisko uruchomieniowe wykonywało zrzut pamięci, ujawniając zawartość tego, co jest w pamięci. Secure String szyfruje go w pamięci, aby uniemożliwić atakującemu odzyskanie zawartości łańcucha.

 11
Author: kemiller2002,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-26 18:49:13

Krótka Odpowiedź

Dlaczego nie mogę po prostu powiedzieć:

SecureString password = new SecureString("password");

Ponieważ teraz masz password w pamięci; nie sposób go wyczyścić - co jest dokładnie punktem zabezpiecza.

Długa Odpowiedź

Powód SecureString istnieje, ponieważ nie możesz użyć ZeroMemory do usunięcia poufnych danych, gdy z nimi skończysz. Istnieje, aby rozwiązać problem, który istnieje ponieważ CLR.

W regularnym natywna Aplikacja, którą można wywołać SecureZeroMemory:

Wypełnia blok pamięci zerami.

Uwaga : SecureZeroMemory is jest identyczne z ZeroMemory, tyle, że kompilator nie zoptymalizuje go.

Problem polega na tym, że nie można wywołać ZeroMemory lub SecureZeroMemory wewnątrz .NET. i w. NET ciągi znaków są niezmienne; nie można nawet nadpisać zawartość łańcucha, tak jak można to zrobić w innych języki:

//Wipe out the password
for (int i=0; i<password.Length; i++)
   password[i] = \0;
Więc co możesz zrobić? Jak zapewnić W. NET możliwość wymazania hasła lub numeru karty kredytowej z pamięci, gdy już z tym skończymy?

Jedynym sposobem, aby to zrobić, byłoby umieszczenie łańcucha w jakimśnatywnym bloku pamięci, gdzie można następnie wywołać ZeroMemory. Obiekt pamięci natywnej, taki jak:

  • A BSTR
  • an HGLOBAL
  • CoTaskMem pamięć niezarządzana

SecureString daje utraconą zdolność wstecz

W. Net nie można wymazać ciągów po ich zakończeniu:
    Są niezmienne; nie można nadpisać ich zawartości]}
  • nie możesz Dispose z nich
  • Ich sprzątanie jest na łasce śmieciarza]}

SecureString istnieje jako sposób, aby ominąć bezpieczeństwo ciągów i być w stanie zagwarantować ich czyszczenie, gdy zajdzie taka potrzeba.

Zadałeś pytanie:]}

Dlaczego nie mogę po prostu powiedz:

SecureString password = new SecureString("password");

Ponieważ teraz masz password w pamięci; bez możliwości jej wyczyszczenia. Jest tam, dopóki CLR nie zdecyduje się ponownie użyć tej pamięci. Umieściłeś nas z powrotem tam, gdzie zaczęliśmy; uruchomiona aplikacja z hasłem, którego nie możemy się pozbyć, i gdzie zrzut pamięci (lub Monitor procesu) może zobaczyć hasło.

SecureString używa API Ochrony Danych do przechowywania zaszyfrowanego łańcucha w pamięci; w ten sposób łańcuch nie będzie istniał w plikach swap, zrzutach awaryjnych lub nawet w oknie zmiennych lokalnych z kolegą patrzącym na Twój powinien.

Jak odczytać hasło?

Wtedy pojawia się pytanie: Jak mogę wejść w interakcję z łańcuchem? Absolutnie Nie chcesz metody takiej jak:

String connectionString = secureConnectionString.ToString()

Bo teraz jesteś z powrotem tam, gdzie zacząłeś-hasło, którego nie możesz się pozbyć. Chcesz zmusić programistów do poprawnego obchodzenia się z wrażliwym ciągiem znaków - tak aby mógł zostać wymazany z pamięci.

Że w związku z tym. NET udostępnia trzy przydatne funkcje pomocnicze, które mogą pomóc w zabezpieczeniu pamięci niezarządzanej:]}

You convert ciąg w niezarządzaną plamę pamięci, zajmij się nią, a następnie wytrzyj ją ponownie.

Niektóre API akceptują SecureStrings . Na przykład w ADO.net 4.5 SqlConnection.Credential pobiera zbiór SqlCredential :

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

Możesz również zmienić hasło w ciągu połączenia:

SqlConnection.ChangePassword(connectionString, cred, newPassword);

I jest wiele miejsc wewnątrz. NET, gdzie nadal akceptują zwykły ciąg znaków dla celów kompatybilności, a następnie szybko odwracają się i umieszczają go w a SecureString.

Jak umieścić tekst w SecureString?

To nadal pozostawia problem:

Jak w pierwszej kolejności wprowadzić hasło do SecureString?

To jest wyzwanie, ale chodzi o to, żebyś myślał o bezpieczeństwie.

Czasami funkcjonalność jest już dostępna dla Ciebie. Na przykład kontrolka WPF PasswordBox może zwrócić wprowadzone hasło jako SecureString bezpośrednio:

Hasło.SecurePassword Property

Pobiera hasło aktualnie posiadane przez PasswordBox jako SecureString.

Jest to pomocne, ponieważ wszędzie, gdzie przekazywałeś surowy ciąg znaków, teraz system typów skarży się, że SecureString jest niezgodny z ciągiem. Chcesz przejść tak długo, jak to możliwe, zanim będziesz musiał przekonwertować swój SecureString z powrotem na zwykły ciąg znaków.

Konwersja SecureString jest dość łatwa:

  • SecureStringToBSTR
  • PtrToStringBSTR

Jak w:

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;
}
Nie chcą, żebyś to robił.

Ale jak wstawić sznurek do SecureString? Cóż, to co musisz zrobić, to przestać mieć hasło w String w pierwszej kolejności. Trzeba było to mieć w coś innego. Nawet tablica Char[] byłaby pomocna.

Wtedy możesz dołączyć każdy znak i Wyczyść zwykły tekst, gdy skończysz:

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

Twoje hasło musi być zapisane w jakiejś pamięci, którą możesz wyczyścić. Załaduj go stamtąd do SecureString.


Tl; dr: SecureString istnieje, aby zapewnić odpowiednik ZeroMemory .

Niektórzy nie widzą sensu w wymazywaniu hasła użytkownika z pamięci, gdy urządzenie jest zablokowane , lub wymazywaniu wymazywaniu klawiszy z pamięci po . Ci ludzie nie używają SecureString.

 11
Author: Ian Boyd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-16 21:35:10

Cóż, jak stwierdza opis, wartość jest przechowywana zaszyfrowana, co oznacza, że zrzut pamięci procesu nie ujawni wartości łańcucha (bez dość poważnej pracy).

Powodem, dla którego nie można po prostu zbudować SecureString ze stałego łańcucha jest to, że wtedy będzie mieć niezaszyfrowaną wersję łańcucha w pamięci. Ograniczenie do tworzenia ciągu w kawałkach zmniejsza ryzyko posiadania całego ciągu w pamięci na raz.

 4
Author: Mark Bessey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-26 18:51:33

Jedną z dużych zalet SecureString jest to, że ma unikać możliwości przechowywania danych na dysku z powodu buforowania stron. Jeśli masz hasło w pamięci, a następnie załadować duży program lub zestaw danych, hasło może zostać zapisane do pliku wymiany, jak program jest paged z pamięci. Z SecureString, przynajmniej dane nie będą siedzieć w nieskończoność na dysku w czystym tekście.

 4
Author: Jason Z,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-26 18:55:32

Myślę, że to dlatego, że ciąg ma być bezpieczny, tzn. haker nie powinien być w stanie go odczytać. Jeśli zainicjujesz go ciągiem znaków, haker może odczytać oryginalny ciąg znaków.

 3
Author: OregonGhost,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-26 18:46:09

Przestałbym używać SecureString . Wygląda na to, że chłopaki z PG wycofują wsparcie. Być może nawet w przyszłości - https://github.com/dotnet/apireviews/tree/master/2015-07-14-securestring .

Powinniśmy usunąć szyfrowanie z SecureString na wszystkich platformach w. NET core - powinniśmy przestarzałe SecureString-prawdopodobnie nie powinniśmy ujawniać SecureString w. NET Core

 3
Author: Joe Healy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-21 00:12:10

Innym przypadkiem użycia jest, gdy pracujesz z aplikacjami płatniczymi (POS) i po prostu nie możesz używać niezmiennych struktur danych w celu przechowywania poufnych danych, ponieważ jesteś ostrożnym programistą. Na przykład: jeśli będę przechowywać poufne dane karty lub metadane autoryzacji w niezmiennym ciągu zawsze będzie miało miejsce, gdy dane te będą dostępne w pamięci przez znaczny czas po tym, jak zostaną odrzucone. Nie mogę tego po prostu nadpisać. Kolejną ogromną zaletą, gdzie takie poufne dane są przechowywane w pamięci zaszyfrowanej.

 1
Author: Halibut,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-31 03:30:57