A .NET Framework leghasználhatatlanabb osztálya

Ezennel szavazást indítok A .NET Framework leghasználhatatlanabb osztálya megtisztelő cím elnyerésére. A jelölteket a cikkhez kapcsolódó hozzászólások formájában tudjátok beküldeni.

Az én favoritom a .NET Framework 2.0-ban megjelent System.Security.SecureString osztály. Ezt az osztályt annyira fontosnak szánták a Framework tervezői, hogy mindjárt az mscorlibbe került - a szándék jó, az eredmény nem egészen.

Kezdjük talán azzal, hogy mire jó ez az osztály. Ha a System.String osztályt használjuk bizalmas információk tárolására, több biztonsági problémába is ütközhetünk:

  1. A String titkosítás nélkül tárolja az adatokat a memóriában.
  2. A String példányokat a GC takarítja a memóriából, amikor úgy gondolja, hogy épp itt az ideje a memória rendbe tételének. Azaz a bizalmas adatunk ki tudja meddig marad a memóriában.
  3. A String megváltoztathatatlan (immutable), azaz a legtöbb sztring manipulációs művelet újabb String példányokat hoz létre, amiket szintén sújtanak az 1. és 2. pontok.

Ezeknek a problémáknak a megoldására vezették be a SecureString osztályt, ami a következőket tudja:

  • A sztring DPAPI-val titkosítva kerül a memóriába és az osztály a módosítások során is gondoskodik a tartalom titkosításáról.
  • A SecureString implementálja az IDisposable interfészt, azaz meg tudjuk határozni, hogy mikor semmisüljön meg az osztály egy példánya.
  • A MakeReadOnly metódus segítségével írásvédetté tehető a tartalom.

A cél tehát, hogy megszabaduljunk a String osztálytól és helyette a SecureString osztályt használjuk, ha bizalmas adatokról van szó. Vigyázat, ez magában hordozza azt, hogy még átmenetileg sem használhatunk String példányokat! Épp itt kezdődnek a gondok, ugyanis az osztály tervezői mindent megtettek azért, hogy erre kényszerítsenek minket...

Először is nem lehet az osztályt "normálisan" inicializálni, az üres konstruktoron kívül ugyanis csak egy char*-ot (nem írtam el, valóban kar csillagot) váró unsafe konstruktora van. Idegesítő, hogy nem lehet közvetlenül Stringből inicializálni, de persze érthető, hiszen ha lehetne, akkor megint ott lennénk, ahol a part szakad, string példányt használnánk. Maradnak tehát az AppendChar, InsertAt, SetAt és RemoveAt metódusok - ez lesz az a pont, ahol majd a kedvünk kezd elmenni az egésztől....

Nézzük a másik irányt: hasonló okokból a SecureString nem hagyja, hogy Stringgé alakítsuk. Persze ki lehet belőle nyerni a tartalmat, de nem lesz barátságos. Ki írna ilyen kódot önszántából:

IntPtr bstr = Marshal.SecureStringToBSTR( mySecureString );
string notSecureAnyMore = Marshal.PtrToStringUni( bstr );

Tehát se be, se ki, hiszen épp ez az, amit el kell kerülnünk. Semmi gond, használjunk mindenhol String helyett SecureString példányokat!

Na, épp itt van az eb elhantolva: Keith Brown már 2005. januárjában megjelent cikkében, tehát már jóval a .NET 2.0 megjelenése előtt rámutatott, hogy ez az osztály önmagában használhatatlan, ha más Framework osztályok nem építenek rá. Ő épp az SqlConnection osztályt hozza fel példaként, de pontosan ugyanez a helyzet a DirectoryEntry vagy hogy még durvábbat mondjak, a NetworkCredential osztályokkal. Nem csak 2005-ben, hanem most, cirka 3 évvel később is!

Vannak persze osztályok, ahol a Microsoft igenis felhasználta az új lehetőséget, a Process már ismeri, ott van az X509Certificate2 is (biztos nagyon fontos és hasznos), de találtam még néhány SQL Server 2005-tel kapcsolatos SMO osztályt is, ami már SecureString paramétert vár. Úgy néz ki, hogy megalkották az új osztályt, egy-két másikban bizonyították, hogy életképes, azután elfelejtették. Méghozzá annyira, hogy a teljesen új fejlesztésekben sem használták fel.

Íme néhány példa: az Office 2007 VSTO-ban a Document.Password és a Workbook.Password sima string. Az új Microsoft.Web.Administration névtérben a VirtualDirectory.Password szintén mezei string. Vagy akár a .NET 3.0-ban is keresgélhetünk: System.ServiceModel.Security névtérben a UserNamePasswordClientCredential.Password tulajdonságról ordít, hogy SecureStringnek kellene lennie, de persze ez sem az.

Ez azonban mind csak a felszín, az igazi probléma sokkal mélyebben található és átjárja az egész Frameworköt. Már onnan kezdve SecureStringet kellene használni, hogy a felhasználó megad egy bizalmas információt, tehát már közvetlenül a felhasználói felületnél. Erre mit találok a PresentationFramework.dll-ben, ami a majdnem vadiúj WPF része? A PasswordBox kontroll Password tulajdonsága sem SecureString! A SharePoint csapat persze megoldotta, a WSS 3.0-ban a Microsoft.SharePoint.WebControls névtérben van egy PasswordTextBox kontroll, aminek SecurePassword tulajdonsága SecureString, tehát a feladat még weben sem lehetetlen. De persze a Console osztály még hírből sem hallott róla.

Ahhoz, hogy az egész használható legyen, az összes érintett vezérlőt át kellene írni, az egyszerű TextBoxtól kezdve a CreateUserWizardig. Így az adat bekérése már biztonságosnak mondható lehetne. Azután persze meg kellene oldani a tárolást, hogy a titkosítás feloldása nélkül tudjam elmenteni az adatokat akár adatbázisba, akár egy konfig állományba és persze vissza is olvasni onnan. Szintén érintett még az összes kommunikációs protokoll illetve az azokat elfedő osztályok (pl. a DirectoryEntry).

Hogy mindezt miért nem valósította meg a Microsoft? Nem tudom, de arra tippelnék, hogy azért, mert nem elég felügyelt kódban kiegészíteni ezeket az osztályokat, bizony teljesen át kell dolgozni őket, méghozzá natív kód bevonásával, hogy még belül, átmenetileg se használjanak string példányokat. A natív kód bevonása pedig köztudottan megsokszorozhatja a szükséges fejlesztési időt.

Ezek után mondja meg nekem valaki, hogyan használjam a SecureString osztályt?!? Aki alkalmazta már, kérem adjon tanácsot, különben az én szememben valóban ez marad a .NET Framework leghasználhatatlanabb osztálya.


zip SecureStringSampleSolution.zip (22 kB)


Balássy György (MS RD, ASP.NET MVP, MCTS)

Balássy György (MS RD, ASP.NET MVP, MCTS) Villamosmérnök, a BME Automatizálási és Alkalmazott Informatikai Tanszékén webportálok fejlesztését oktatja. 2000 óta foglalkozik a Microsoft .NET platformjával, melynek meghonosításában jelentős szerepet vállalt előadóként, konzulensként és A .NET Framework és programozása című könyv társszerzőjeként. Az MSDN Kompetencia Központon belül a Portál Technológiák Csoport vezetője, szakterülete web alapú rendszerek fejlesztése és üzemeltetése. 2004-ben Magyarországon elsőként kapta meg a Most Valuable Professional címet, majd 2005 óta a Microsoft magyarországi regionális igazgatója. Publikációi a Technet Magazinban, az MSDN Kompetencia Központ honlapján és szakmai blogjában olvashatóak.

2007.12.06. 9:09:16 | Permalink | Hozzászólások: 2 | Tárgyszavak: ,


  • Validátor ASCX-ben

    Dávid Zoltán Az ASP.NET 2.0 óta be lehet állítani, hogy melyik validátor milyen gomb megnyomása esetén ellenőrizzen. Ez egy nagyon hasznos tulajdonság: lehetővé teszi, hogy két feltöltő/szerkesztő felület is lehessen egy oldalon, amik mind validáltak, és nem szólnak bele egymás életébe. Azt, hogy mely validátorok tartoznak egy csoportba, és mely gombokra aktivizálódnak a ValidationGroup propertyjben lehet megadni. Azonos ValidationGroup = közös működés. A gond akkor kezdődik, ha többször felhasznált oldal-elemeket készítünk, például ASCX-eket. Ekkor ugyanis, ha több azonos típusú ASCX-et teszünk egy oldalra (pl.: sok FileFeltoltes.ascx-et), akkor azok gyermekvezérlői és validátorai... Tovább »
  • Active Directory lekérdezése T-SQL-ből

    Balássy György (MS RD, ASP.NET MVP, MCTS) Aki valaha is foglalkozott már az Active Directory-val az tudja, hogy a címtár felépítése gyökeresen eltér egy relációs adatbázis szerkezetétől. Nem elég, hogy az egyes elemek konténerekben helyezkednek el, melyek hierarchikus kapcsolatban állnak egymással, de egy konténeren belül teljesen különböző tulajdonságokkal bíró címtár objektumok is lehetnek. És mégis, van lehetőség arra, hogy az SQL Servernek megtanítsuk, hogyan kell lekérdezni a címtárat. Perverzek előnyben :) Tovább »


Írja meg Ön is véleményét!


Hozzászólásokat csak regisztrált, bejelentkezett felhasználóktól tudunk elfogadni!

Hozzászólások


Balássy György (MS RD, ASP.NET MVP, MCTS) Balássy György (MS RD, ASP.NET MVP, MCTS)  (2007.12.07. 11:50:23)

Az is jó ötlet, van jelölted?

Gubo Gubo  (2007.12.06. 9:48:17)

Ezen töprengeni fogok, viszont lehet hogy meg kellene hirdetni a A .NET Framework legnyakatekertebb osztályát is. Esetleg mini survey formájában szavazásra bocsájtani párat.