क्या SecureString C # एप्लिकेशन में कभी व्यावहारिक है?


224

अगर मेरी धारणाएं यहां गलत हैं, तो मुझे सुधारने के लिए स्वतंत्र महसूस करें, लेकिन मुझे यह बताने दें कि मैं क्यों पूछ रहा हूं।

MSDN से लिया गया, a SecureString:

पाठ का प्रतिनिधित्व करता है जिसे गोपनीय रखा जाना चाहिए। पाठ का उपयोग किए जाने पर गोपनीयता के लिए एन्क्रिप्ट किया जाता है, और जब आवश्यकता नहीं होती है तो कंप्यूटर मेमोरी से हटा दिया जाता है।

मुझे यह मिलता है, यह एक पासवर्ड या अन्य निजी जानकारी को एक SecureStringसे अधिक में संग्रहीत करने के लिए पूर्ण समझ में आता है System.String, क्योंकि आप यह नियंत्रित कर सकते हैं कि यह कैसे और कब वास्तव में मेमोरी में संग्रहीत है, क्योंकि System.String:

दोनों अपरिवर्तनीय है और, जब आवश्यकता नहीं होती है, तो कचरा संग्रह के लिए प्रोग्रामेटिक रूप से निर्धारित नहीं किया जा सकता है; यह है कि, उदाहरण केवल पढ़ने के बाद ही बनाया जाता है और यह अनुमान लगाना संभव नहीं है कि कंप्यूटर मेमोरी से इंस्टेंस कब डिलीट होगा। नतीजतन, यदि किसी स्ट्रिंग ऑब्जेक्ट में संवेदनशील जानकारी जैसे पासवर्ड, क्रेडिट कार्ड नंबर, या व्यक्तिगत डेटा है, तो एक जोखिम है कि जानकारी का उपयोग किए जाने के बाद पता चल सकता है क्योंकि आपका एप्लिकेशन कंप्यूटर मेमोरी से डेटा को हटा नहीं सकता है।

हालांकि, GUI एप्लिकेशन के मामले में (उदाहरण के लिए, एक ssh क्लाइंट), SecureString a से निर्मित किया जाना चाहिए System.String । सभी पाठ नियंत्रण इसके अंतर्निहित डेटा प्रकार के रूप में एक स्ट्रिंग का उपयोग करते हैं

तो, इसका मतलब यह है कि हर बार जब उपयोगकर्ता एक कुंजी दबाता है, तो पुराना स्ट्रिंग जो वहां छोड़ दिया गया था, और एक नया स्ट्रिंग यह दर्शाने के लिए बनाया गया है कि टेक्स्ट बॉक्स के अंदर का मान क्या है, भले ही पासवर्ड मास्क का उपयोग कर रहा हो। और जब या तो उन मूल्यों को स्मृति से खारिज कर दिया जाता है या हम नियंत्रित नहीं कर सकते

अब सर्वर में लॉग इन करने का समय आ गया है। अंदाज़ा लगाओ? प्रमाणीकरण के लिए आपको कनेक्शन पर एक स्ट्रिंग पास करने की आवश्यकता है । तो चलो हमारे SecureStringएक में परिवर्तित करें System.String.... और अब हमारे पास ढेर पर एक स्ट्रिंग है, जिसमें कचरा संग्रह के माध्यम से जाने के लिए मजबूर नहीं किया गया है (या इसके बफर में 0 लिखें)।

मेरी बात है : कोई फर्क नहीं पड़ता कि आप क्या करते, रेखा के साथ कहीं न कहीं, कि SecureStringहै के लिए जा रहा एक में परिवर्तित करने System.String, यह अर्थ कुछ बिंदु पर ढेर पर कम से कम अस्तित्व में (कचरा संग्रहण के किसी भी गारंटी के बिना) होगा।

मेरी बात यह नहीं है : क्या एक ssh कनेक्शन के लिए एक स्ट्रिंग भेजने को दरकिनार करने के तरीके हैं, या एक नियंत्रण स्टोर एक स्ट्रिंग (एक कस्टम नियंत्रण करें) को दरकिनार कर रहे हैं। इस प्रश्न के लिए, आप "ssh कनेक्शन" को "लॉगिन फ़ॉर्म", "पंजीकरण फ़ॉर्म", "भुगतान फ़ॉर्म", "खाद्य पदार्थ-आप-खिला-पिला सकते हैं, लेकिन अपने-अपने बच्चों के रूप में नहीं" से बदल सकते हैं, आदि।

  • तो, SecureStringवास्तव में व्यावहारिक रूप से उपयोग करना किस बिंदु पर है ?
  • क्या कभी किसी System.Stringवस्तु के उपयोग को पूरी तरह से खत्म करने के लिए अतिरिक्त विकास समय के लायक है ?
  • क्या SecureStringकेवल एक System.Stringढेर पर समय की मात्रा को कम करने का पूरा बिंदु (एक भौतिक स्वैप फ़ाइल में जाने के अपने जोखिम को कम करना) है?
  • यदि किसी हमलावर के पास पहले से ही ढेर निरीक्षण के लिए साधन हैं, तो वह सबसे अधिक संभावना है (ए) के पास पहले से ही कीस्ट्रोक्स पढ़ने का साधन है, या (बी) के पास पहले से ही भौतिक रूप से मशीन है ... इसलिए उसका उपयोग SecureStringकरने से रोकने के लिए होगा। डेटा वैसे भी?
  • क्या यह सिर्फ "अश्लीलता के माध्यम से सुरक्षा" है?

क्षमा करें, यदि मैं बहुत मोटे सवालों पर सवाल उठा रहा हूं, तो जिज्ञासा मुझे बेहतर लगी। किसी भी या मेरे सभी सवालों का जवाब देने के लिए स्वतंत्र महसूस करें (या मुझे बताएं कि मेरी धारणाएं पूरी तरह से गलत हैं)। :)


25
ध्यान रखें कि SecureStringवास्तव में एक सुरक्षित स्ट्रिंग नहीं है। यह केवल समय खिड़की को कम करने का एक तरीका है जिसमें कोई आपकी स्मृति का निरीक्षण कर सकता है और संवेदनशील डेटा को सफलतापूर्वक प्राप्त कर सकता है। यह बुलेटप्रूफ नहीं है और यह होने का इरादा नहीं था। लेकिन आप जिन बिंदुओं को उठा रहे हैं, वे बहुत मान्य हैं। संबंधित: stackoverflow.com/questions/14449579/...
थियोडोरोस Chatzigiannakis

1
@ TheodorosChatzigiannakis, हाँ, यह बहुत ज्यादा है जो मुझे लगा। मैंने आज पूरा दिन बिताया है और आवेदन के जीवनकाल के लिए पासवर्ड स्टोर करने का एक सुरक्षित तरीका जानने की कोशिश कर रहा हूं, और इसने मुझे आश्चर्यचकित कर दिया है, क्या यह इसके लायक है?
स्टीवन जेफ्रीज

1
शायद इसके लायक नहीं है। लेकिन फिर, आप एक चरम परिदृश्य के खिलाफ बचाव कर सकते हैं। अत्यधिक इस अर्थ में नहीं कि किसी के लिए आपके कंप्यूटर पर इस तरह की पहुँच प्राप्त करना असम्भव है, बल्कि इस अर्थ में कि यदि कोई इस प्रकार की पहुँच प्राप्त करता है, तो कंप्यूटर पर विचार किया जाता है (सभी इरादों और उद्देश्यों के लिए) समझौता किया जाता है और मैं डॉन ' लगता है कि कोई भी भाषा या कोई भी तकनीक है जिसका उपयोग आप पूरी तरह से बचाव के लिए कर सकते हैं।
थियोडोरोस चटजिआनियाकिस

8
यह वर्षों तक दिखाई देने वाले पासवर्ड से बचाता है , लंबे समय के बाद हर किसी ने यह सोचना बंद कर दिया कि कोई समस्या हो सकती है। एक हार्ड ड्राइव पर, पेजिंग फ़ाइल में संग्रहीत। मेमोरी को स्क्रब करना ताकि इसके लिए ऑड्स महत्वपूर्ण हैं, सिस्टम के साथ ऐसा नहीं कर सकता। क्योंकि यह अपरिवर्तनीय है। इसके लिए बुनियादी सुविधाओं की आवश्यकता होती है जो इन दिनों कुछ कार्यक्रमों तक पहुँचते हैं, देशी कोड के साथ इंटरॉप करते हैं इसलिए Mars.SecureStringXxx () तरीके उपयोगी हैं जो दुर्लभ हैं। या इसके लिए उपयोगकर्ता को संकेत देने का एक सभ्य तरीका :)
हंस पासेंट

1
सिक्योरस्ट्रिंग एक सिक्योरिटी इन-डेप्थ तकनीक है। विकास लागत और सुरक्षा लाभ के बीच का व्यापार ज्यादातर स्थितियों में अनुकूल नहीं है। इसके लिए बहुत कम उपयोग के मामले हैं।
usr

जवाबों:


237

वास्तव में बहुत व्यावहारिक उपयोग हैं SecureString

क्या आप जानते हैं कि मैंने ऐसे परिदृश्य कितनी बार देखे हैं? (उत्तर है: कई!):

  • गलती से लॉग फ़ाइल में एक पासवर्ड दिखाई देता है।
  • कहीं पर एक पासवर्ड दिखाया जा रहा है - एक बार एक जीयूआई ने आवेदन की एक कमांड लाइन दिखाई थी जो चल रही थी, और कमांड लाइन में पासवर्ड शामिल था। उफ़
  • अपने सहकर्मी के साथ प्रोफाइल सॉफ्टवेयर में मेमोरी प्रोफाइलर का उपयोग करना। सहकर्मी आपके पासवर्ड को स्मृति में देखता है। असत्य लगता है? हर्गिज नहीं।
  • मैंने एक बार RedGateसॉफ़्टवेयर का उपयोग किया था जो अपवादों के मामले में स्थानीय चर के "मूल्य" पर कब्जा कर सकता था, आश्चर्यजनक रूप से उपयोगी। हालांकि, मैं सोच सकता हूं कि यह गलती से "स्ट्रिंग पासवर्ड" लॉग करेगा।
  • क्रैश डंप जिसमें स्ट्रिंग पासवर्ड शामिल है।

क्या आप जानते हैं कि इन सभी समस्याओं से कैसे बचा जाए? SecureString। यह आम तौर पर सुनिश्चित करता है कि आप मूर्खतापूर्ण गलतियाँ न करें। इससे कैसे बचा जाए? यह सुनिश्चित करने से कि पासवर्ड अप्रबंधित मेमोरी में एन्क्रिप्ट किया गया है और वास्तविक मूल्य केवल तभी एक्सेस किया जा सकता है जब आप 90% सुनिश्चित हों कि आप क्या कर रहे हैं।

इस अर्थ में, SecureStringबहुत आसानी से काम करता है:

1) सब कुछ एन्क्रिप्टेड है

2) उपयोगकर्ता कॉल AppendChar

3) UNMANAGED MEMORY में सब कुछ डिक्रिप्ट करें और कैरेक्टर जोड़ें

4) UNMANAGED MEMORY में फिर से सब कुछ एन्क्रिप्ट करें।

क्या होगा यदि उपयोगकर्ता के पास आपके कंप्यूटर तक पहुंच हो? क्या कोई वायरस सभी तक पहुँच पाने में सक्षम होगा SecureStrings? हाँ। आपको बस इतना करना चाहिए कि RtlEncryptMemoryजब मेमोरी डिक्रिप्ट की जा रही हो, तो आप अपने आप को हुक कर लें , आपको अनएन्क्रिप्टेड मेमोरी एड्रेस की लोकेशन मिल जाएगी, और इसे पढ़ लें। देखा! वास्तव में, आप एक वायरस बना सकते हैं जो लगातार उपयोग के लिए स्कैन करेगा SecureStringऔर इसके साथ सभी गतिविधियों को लॉग इन करेगा। मैं यह नहीं कह रहा हूं कि यह एक आसान काम होगा, लेकिन यह किया जा सकता है। जैसा कि आप देख सकते हैं, SecureStringआपके सिस्टम में एक उपयोगकर्ता / वायरस होने के बाद "शक्तिशालीता" पूरी तरह से चला गया है।

आपके पोस्ट में कुछ बिंदु हैं। यकीन है, अगर आप कुछ यूआई नियंत्रणों का उपयोग करते हैं जो आंतरिक रूप से "स्ट्रिंग पासवर्ड" रखते हैं, तो वास्तविक SecureStringका उपयोग करना उपयोगी नहीं है। हालांकि, फिर भी, मैं ऊपर सूचीबद्ध कुछ मूर्खता से रक्षा कर सकता हूं।

इसके अलावा, जैसा कि अन्य ने उल्लेख किया है, WPF पासवर्डबॉक्स का समर्थन करता है जो SecureStringआंतरिक रूप से अपनी SecurePassword संपत्ति के माध्यम से उपयोग करता है।

आधार - रेखा है की; यदि आपके पास संवेदनशील डेटा (पासवर्ड, क्रेडिट-कार्ड, ..), उपयोग है SecureString। यह वह है जो C # फ्रेमवर्क का अनुसरण कर रहा है। उदाहरण के लिए, NetworkCredentialक्लास स्टोर पासवर्ड के रूप में SecureString। आप को देखें, तो यह , आप में से नेट ढांचे में ~ 80 विभिन्न उपयोगों के अधिक देख सकते हैं SecureString

ऐसे कई मामले हैं जब आपको SecureStringस्ट्रिंग में कनवर्ट करना होगा, क्योंकि कुछ एपीआई को यह उम्मीद है।

सामान्य समस्या या तो है:

  1. एपीआई सामान्य है। यह नहीं जानता कि संवेदनशील डेटा है।
  2. एपीआई जानता है कि यह संवेदनशील डेटा के साथ काम कर रहा है और "स्ट्रिंग" का उपयोग करता है - यह सिर्फ खराब डिजाइन है।

आपने अच्छी बात उठाई: जब SecureStringधर्मांतरित किया जाता है तो क्या होता है string? यह केवल पहले बिंदु के कारण हो सकता है। उदाहरण के लिए एपीआई को पता नहीं है कि यह संवेदनशील डेटा है। मैंने व्यक्तिगत रूप से ऐसा होते हुए नहीं देखा है। SecureString से स्ट्रिंग प्राप्त करना इतना आसान नहीं है।

यह एक साधारण कारण के लिए सरल नहीं है ; जैसा कि आपने कहा था कि उपयोगकर्ता को SecureString को स्ट्रिंग में बदलने देने का कभी इरादा नहीं था: GC में किक करेगा। यदि आप खुद को ऐसा करते हुए देखते हैं, तो आपको वापस कदम रखने और खुद से पूछने की आवश्यकता है: मैं ऐसा क्यों कर रहा हूं, या क्या मुझे वास्तव में जरूरत है यह क्यों?

वहाँ एक दिलचस्प मामला मैंने देखा है। अर्थात्, WinApi फ़ंक्शन LogonUser LPTSTR को पासवर्ड के रूप में लेता है, जिसका अर्थ है कि आपको कॉल करने की आवश्यकता है SecureStringToGlobalAllocUnicode। यह मूल रूप से आपको अनएन्क्रिप्टेड पासवर्ड देता है जो अप्रबंधित मेमोरी में रहता है। जैसे ही आप कर रहे हैं आपको उससे छुटकारा पाने की आवश्यकता है:

// Marshal the SecureString to unmanaged memory.
IntPtr rawPassword = Marshal.SecureStringToGlobalAllocUnicode(password);
try
{
   //...snip...
}
finally 
{
   // Zero-out and free the unmanaged string reference.
   Marshal.ZeroFreeGlobalAllocUnicode(rawPassword);
}

आप हमेशा विस्तार SecureStringविधि के साथ वर्ग का विस्तार कर सकते हैं , जैसे कि ToEncryptedString(__SERVER__PUBLIC_KEY), जो आपको इसका stringउदाहरण देता SecureStringहै सर्वर की सार्वजनिक कुंजी का उपयोग करके एन्क्रिप्ट किया गया है। केवल सर्वर तब इसे डिक्रिप्ट कर सकता है। हल की गई समस्या: कचरा संग्रह "मूल" स्ट्रिंग को कभी नहीं देखेगा, क्योंकि आप इसे प्रबंधित मेमोरी में कभी उजागर नहीं करते हैं। बिलकुल यही किया जा रहा है PSRemotingCryptoHelper( EncryptSecureStringCore(SecureString secureString))।

और जैसा कि लगभग बहुत कुछ संबंधित है: मोनो सिक्योरस्ट्रिंग बिल्कुल भी एन्क्रिप्ट नहीं करता है । कार्यान्वयन पर टिप्पणी की गई है क्योंकि ..इसके लिए .. "यह किसी भी तरह से ननिट टेस्ट के टूटने का कारण बनता है" , जो मेरे अंतिम चरण में लाता है:

SecureStringहर जगह समर्थित नहीं है। यदि मंच / वास्तुकला समर्थन नहीं करता है SecureString, तो आपको एक अपवाद मिलेगा। उन प्लेटफार्मों की एक सूची है जो प्रलेखन में समर्थित हैं।


मुझे लगता है कि अगर वहाँ व्यक्तिगत पात्रों तक पहुँचने के लिए एक तंत्र थे, तो यह SecureStringबहुत अधिक व्यावहारिक होगा। ऐसे तंत्र के लिए क्षमता एक struct प्रकार होने से बढ़ाया जा सकता है SecureStringTempBufferकिसी भी सार्वजनिक सदस्यों, द्वारा पारित किया जा सकता है जो बिना refकरने के लिए SecureString"पढ़ें एक चरित्र" विधि [अगर एन्क्रिप्शन / डिक्रिप्शन 8-चरित्र मात्रा में संसाधित किया जाता है, इस तरह की संरचना डेटा पकड़ सकता है 8 वर्णों के लिए और SecureString] के भीतर उन वर्णों में से पहला स्थान ।
सुपरकैट

2
मैं इसे प्रत्येक स्रोत कोड ऑडिट में ध्वजांकित करता हूं जो मैं करता हूं। यह भी दोहराया जाना चाहिए कि यदि आप इसका उपयोग SecureStringकरते हैं तो इसे स्टैक के माध्यम से सभी तरह से उपयोग करने की आवश्यकता है।
केसी

1
मैंने .ToEncryptedString () एक्सटेंशन लागू किया है लेकिन प्रमाणपत्र का उपयोग करके। क्या आप इस पर ध्यान देंगे और मुझे बताएंगे कि क्या मैं यह सब गलत कर रहा हूं। मैं अपने सुरक्षित engouhg gist.github.com/sturlath/99cfbfff26e0ebd12ea73316d0843330 की
Sturla

@Sturla - EngineSettingsआपकी एक्सटेंशन विधि में क्या है ?
इंटेक्सएक्सएक्सएक्स


15

आपकी धारणाओं में कुछ मुद्दे हैं।

सबसे पहले SecureString क्लास में String कंस्ट्रक्टर नहीं होता है। एक ऑब्जेक्ट बनाने के लिए आप एक ऑब्जेक्ट आवंटित करते हैं और फिर वर्णों को जोड़ते हैं।

GUI या कंसोल के मामले में, आप प्रत्येक दबाए गए कुंजी को आसानी से एक सुरक्षित स्ट्रिंग में पास कर सकते हैं।

वर्ग को इस तरह से डिज़ाइन किया गया है कि आप गलती से, संग्रहीत किए गए मान तक नहीं पहुँच सकते। इसका मतलब यह है कि आप इससे stringसीधे पासवर्ड के रूप में प्राप्त नहीं कर सकते हैं ।

इसलिए इसका उपयोग करने के लिए, उदाहरण के लिए, वेब के माध्यम से प्रमाणित करने के लिए, आपको उचित कक्षाओं का उपयोग करना होगा जो सुरक्षित भी हैं।

.NET फ्रेमवर्क में आपके पास कुछ कक्षाएं हैं जो SecureString का उपयोग कर सकती हैं

  • WPF का पासवर्डबॉक्स नियंत्रण पासवर्ड को आंतरिक रूप से SecureString के रूप में रखता है।
  • System.Diagnostics.ProcessInfo की पासवर्ड संपत्ति एक SecureString है।
  • X509Certificate2 के लिए निर्माता पासवर्ड के लिए SecureString लेता है।

(अधिक)

समाप्त करने के लिए, SecureString वर्ग उपयोगी हो सकता है, लेकिन डेवलपर से अधिक ध्यान देने की आवश्यकता है।

यह सब, उदाहरण के साथ, सुरक्षित रूप से MSDN के प्रलेखन में वर्णित है


10
मैं आपके उत्तर के तीसरे-से-अंतिम पैराग्राफ को काफी नहीं समझता। आप इसे बिना क्रमबद्ध किए नेटवर्क पर ओवर ट्रांसफर कैसे करेंगे ? मुझे लगता है कि प्रश्न का ओपी बिंदु यह है कि एक समय आता है जब आप वास्तव में सुरक्षित रूप से आयोजित मूल्य का उपयोग करना चाहते हैं , जिसका अर्थ है कि आपको इसे वहां से निकालना होगा, और यह अब सुरक्षित नहीं है। सभी फ़्रेमवर्क क्लास लाइब्रेरी में, वास्तव में कोई विधियाँ नहीं हैं जो सीधे इनपुट के रूप में स्वीकार करती हैं (जहाँ तक मैं देख सकती हूँ), तो पहली जगह में एक मूल्य रखने की बात क्या है? SecureStringstringSecureStringSecureStringSecureString
stakx -

@ DamianLeszczyński-Vash, मुझे पता है कि SecureString में एक स्ट्रिंग कंस्ट्रक्टर नहीं है, लेकिन मेरा कहना है कि आप या तो (A) एक SecureString बनाते हैं और एक स्ट्रिंग से प्रत्येक वर्ण को उसमें जोड़ते हैं, या (B) को किसी बिंदु पर उपयोग करने की आवश्यकता होती है सिक्योरस्ट्रीमिंग में एक स्ट्रिंग के रूप में संग्रहीत मूल्य इसे कुछ एपीआई में पारित करने के लिए। कहा जा रहा है, आप कुछ अच्छे बिंदु लाते हैं, और मैं देख सकता हूँ कि कुछ विशिष्ट मामलों में यह कैसे उपयोगी हो सकता है।
स्टीवन जेफ्रीज

1
@stakx आप इसे प्राप्त करके नेटवर्क पर भेज देंगे char[]और प्रत्येक charको एक सॉकेट पर भेज देंगे - इस प्रक्रिया में कोई कचरा-संग्रहणीय वस्तु नहीं बनाएंगे ।
user253751 10

चार [] संग्रहणीय है और परिवर्तनशील है, इसलिए इसे ओवरराइट किया जा सकता है।
पीटर रिची

बेशक, उस सरणी को ओवरराइट करना भूलना भी आसान है। किसी भी तरह से, आप जिस भी एपीआई को पास करते हैं, उसकी प्रतिलिपि भी बन सकती है।
cHao

10

एक SecureString उपयोगी है अगर:

  • आप इसे चरित्र द्वारा निर्मित करते हैं (जैसे कंसोल इनपुट से) या इसे किसी अप्रबंधित एपीआई से प्राप्त करें

  • आप इसे किसी अनवांटेड API (SecureStringToBSTR) में पास करके इसका उपयोग करते हैं।

यदि आप कभी इसे प्रबंधित स्ट्रिंग में परिवर्तित करते हैं, तो आपने इसके उद्देश्य को हरा दिया है।

टिप्पणी के जवाब में अद्यतन करें

... या BSTR जैसा कि आप उल्लेख करते हैं, जो किसी भी अधिक सुरक्षित नहीं लगता है

इसके बीटीएस में परिवर्तित होने के बाद, बीटीएस का उपभोग करने वाला अप्रबंधित घटक मेमोरी को शून्य कर सकता है। अप्रबंधित मेमोरी इस मायने में अधिक सुरक्षित है कि इसे इस तरह से रीसेट किया जा सकता है।

हालाँकि, .NET फ्रेमवर्क में बहुत कम, API हैं जो SecureString का समर्थन करते हैं, इसलिए आप यह कहना सही है कि यह आज बहुत सीमित मूल्य का है।

मुख्य उपयोग का मामला जो मैं देखूंगा वह एक क्लाइंट एप्लिकेशन में है जिसके लिए उपयोगकर्ता को अत्यधिक संवेदनशील कोड या पासवर्ड दर्ज करना होगा। उपयोगकर्ता इनपुट का उपयोग कैरेक्टर द्वारा सिक्योरस्ट्रिंग के निर्माण के लिए किया जा सकता है, फिर इसे एक अनवांटेड एपीआई में पारित किया जा सकता है, जो इसे उपयोग करने के बाद प्राप्त बीटीएस को शून्य करता है। किसी भी बाद की मेमोरी डंप में संवेदनशील स्ट्रिंग नहीं होगी।

सर्वर एप्लिकेशन में यह देखना मुश्किल है कि यह कहां उपयोगी होगा।

अद्यतन २

.NET API का एक उदाहरण जो SecureString स्वीकार करता है , वह X509Certificate वर्ग के लिए यह कंस्ट्रक्टर है । यदि आप ILSpy या समान के साथ स्पेलंक करते हैं, तो आप देखेंगे कि SecureString आंतरिक रूप से अप्रबंधित बफर ( Marshal.SecureStringToGlobalAllocUnicode) में परिवर्तित हो जाती है, जो तब समाप्त हो जाती है जब ( Marshal.ZeroFreeGlobalAllocUnicode) के साथ समाप्त हो जाती है ।


1
+1, लेकिन क्या आप हमेशा "अपने उद्देश्य को पराजित" नहीं करेंगे? यह देखते हुए कि फ्रेमवर्क क्लास लाइब्रेरी में लगभग कोई विधि SecureStringइनपुट के रूप में स्वीकार नहीं करती है , उनका क्या उपयोग होगा? आपको हमेशा stringजल्दी या बाद में बदलना होगा (या BSTRजैसा कि आप उल्लेख करते हैं, जो किसी भी अधिक सुरक्षित नहीं लगता है)। तो आखिर परेशान क्यों SecureString?
stakx -

5

Microsoft SecureStringनए कोड के लिए उपयोग करने की अनुशंसा नहीं करता है ।

SecureString वर्ग के प्रलेखन से :

जरूरी

हम अनुशंसा नहीं करते हैं कि आप SecureStringनए विकास के लिए कक्षा का उपयोग करें । अधिक जानकारी के लिए, देखें का SecureStringउपयोग नहीं किया जाना चाहिए

जो अनुशंसा करता है:

SecureStringनए कोड के लिए उपयोग न करें । .NET कोर में कोड पोर्ट करते समय, विचार करें कि सरणी की सामग्री को मेमोरी में एन्क्रिप्ट नहीं किया गया है।

क्रेडेंशियल्स से निपटने का सामान्य दृष्टिकोण उन्हें से बचना है और इसके बजाय प्रमाण पत्र या विंडोज प्रमाणीकरण जैसे प्रमाणीकरण के लिए अन्य साधनों पर भरोसा करना है। GitHub पर।


4

जैसा कि आपने सही ढंग से पहचाना है, SecureStringएक से अधिक विशिष्ट लाभ प्रदान करता है string: नियतात्मक उन्मूलन। इस तथ्य के साथ दो समस्याएं हैं:

  1. जैसा कि दूसरों ने उल्लेख किया है और जैसा कि आपने स्वयं देखा है, यह अपने आप से पर्याप्त नहीं है। आपको यह सुनिश्चित करना होगा कि प्रक्रिया का प्रत्येक चरण (इनपुट की पुनर्प्राप्ति सहित, स्ट्रिंग का निर्माण, उपयोग, विलोपन, परिवहन, आदि) का उपयोग किए बिना उद्देश्य को हराए बिना होता है SecureString। इसका मतलब है कि आप कभी नहीं एक जीसी कामयाब अपरिवर्तनीय बनाने के लिए सावधान रहना चाहिए stringया किसी अन्य बफर कि संवेदनशील जानकारी स्टोर करेगा (या आप का ट्रैक रखने करना होगा कि साथ ही)। व्यवहार में, इसे प्राप्त करना हमेशा आसान नहीं होता है, क्योंकि बहुत सारे एपीआई केवल साथ काम करने का एक तरीका प्रदान करते हैं string, नहीं SecureString। और यहां तक ​​कि अगर तुम सब कुछ सही प्रबंधन ...
  2. SecureStringबहुत विशिष्ट प्रकार के हमले (और उनमें से कुछ के लिए, यह विश्वसनीय भी नहीं है) से बचाता है। उदाहरण के लिए, SecureStringआपको उस समय विंडो को सिकोड़ने की अनुमति देता है जिसमें एक हमलावर आपकी प्रक्रिया की मेमोरी को डंप कर सकता है और संवेदनशील जानकारी को फिर से निकाल सकता है (फिर से, जैसा आपने सही ढंग से बताया है), लेकिन यह उम्मीद करना कि हमलावर के लिए खिड़की बहुत छोटी है अपनी मेमोरी का स्नैपशॉट लेना सुरक्षा नहीं माना जाता है।

तो, आपको इसका उपयोग कब करना चाहिए? केवल जब आप किसी ऐसी चीज़ के साथ काम कर रहे होते हैं जो आपको SecureStringआपकी सभी ज़रूरतों के लिए काम करने की अनुमति दे सकती है और तब भी आपको यह ध्यान रखना चाहिए कि यह केवल विशिष्ट परिस्थितियों में सुरक्षित है।


2
आप मान रहे हैं कि एक हमलावर किसी विशेष समय में किसी प्रक्रिया की मेमोरी को स्नैपशॉट करने में सक्षम है। यह जरूरी नहीं है कि मामला है। क्रैश डंप पर विचार करें। यदि क्रैश संवेदनशील एप्लिकेशन के साथ किए जाने के बाद हुआ है, तो क्रैश डंप में संवेदनशील डेटा नहीं होना चाहिए।

4

नीचे पाठ एचपी फोर्टिफाई स्टैटिक कोड एनालाइजर से कॉपी किया गया है

सार: PassGenerator.cs में विधि PassString () एक असुरक्षित तरीके से संवेदनशील डेटा संग्रहीत करता है (यानी स्ट्रिंग में), यह ढेर का निरीक्षण करके डेटा को निकालना संभव बनाता है।

स्पष्टीकरण: मेमोरी में संग्रहीत संवेदनशील डेटा (जैसे पासवर्ड, सोशल सिक्योरिटी नंबर, क्रेडिट कार्ड नंबर आदि) को लीक किया जा सकता है अगर इसे किसी प्रबंधित स्ट्रिंग ऑब्जेक्ट में संग्रहीत किया जाए। स्ट्रिंग ऑब्जेक्ट्स को पिन नहीं किया जाता है, इसलिए कचरा कलेक्टर इन वस्तुओं को इच्छानुसार स्थानांतरित कर सकता है और स्मृति में कई प्रतियां छोड़ सकता है। इन वस्तुओं को डिफ़ॉल्ट रूप से एन्क्रिप्ट नहीं किया जाता है, इसलिए जो कोई भी इस प्रक्रिया की मेमोरी पढ़ सकता है, वह सामग्री देख सकेगा। इसके अलावा, यदि प्रक्रिया की मेमोरी डिस्क पर स्वैप हो जाती है, तो स्ट्रिंग की अनएन्क्रिप्टेड सामग्री को स्वैप फाइल पर लिखा जाएगा। अंत में, चूंकि स्ट्रिंग ऑब्जेक्ट अपरिवर्तनीय हैं, इसलिए मेमोरी से एक स्ट्रिंग के मूल्य को हटाकर केवल CLR कचरा कलेक्टर द्वारा किया जा सकता है। जब तक सीएलआर मेमोरी पर कम न हो, तब तक कचरा संग्राहक को चलाने की आवश्यकता नहीं होती है, इसलिए इस बात की कोई गारंटी नहीं है कि कचरा संग्रहण कब होगा।

सिफारिशें: स्ट्रिंग्स जैसी वस्तुओं में संवेदनशील डेटा संग्रहीत करने के बजाय, उन्हें सिक्योरस्ट्रिंग ऑब्जेक्ट में संग्रहीत करें। प्रत्येक वस्तु हर समय स्मृति में एक एन्क्रिप्टेड प्रारूप में अपनी सामग्री संग्रहीत करती है।


3

मैं इस बिंदु को संबोधित करना चाहता हूं:

यदि एक हमलावर के पास पहले से ही ढेर निरीक्षण के लिए साधन हैं, तो वे सबसे अधिक संभावना है (ए) के पास पहले से ही कीस्ट्रोक्स पढ़ने का साधन है, या (बी) पहले से ही भौतिक रूप से मशीन है ... इसलिए SecureStringउन्हें रोकने के लिए उपयोग करने से रोकना होगा। डेटा वैसे भी?

एक हमलावर के पास कंप्यूटर और एप्लिकेशन तक पूर्ण पहुंच नहीं हो सकती है, लेकिन प्रक्रिया की मेमोरी के कुछ हिस्सों तक पहुंचने के लिए साधन हो सकते हैं। यह आमतौर पर बग की वजह से होता है जैसे बफर ओवररन जब विशेष रूप से निर्मित इनपुट मेमोरी के कुछ हिस्से को उजागर या अधिलेखित करने का कारण बन सकता है।

हार्टबेल्ड लीकिंग मेमोरी

उदाहरण के लिए हार्दिक को लीजिए। विशेष रूप से निर्मित अनुरोधों के कारण कोड हमलावर की प्रक्रिया की स्मृति के यादृच्छिक भागों को उजागर कर सकता है। एक हमलावर मेमोरी से एसएसएल सर्टिफिकेट निकाल सकता है, फिर भी उसकी जरूरत सिर्फ एक विकृत अनुरोध का उपयोग करने के लिए है।

प्रबंधित कोड की दुनिया में, बफर ओवररन अक्सर एक समस्या बन जाते हैं। और WinForms के मामले में, डेटा पहले से ही असुरक्षित तरीके से संग्रहीत है और आप इसके बारे में कुछ नहीं कर सकते। यह SecureStringबहुत बेकार के साथ सुरक्षा प्रदान करता है ।

हालांकि, GUI का उपयोग करने के लिए प्रोग्राम किया जा सकता है SecureString, और ऐसे मामले में मेमोरी में पासवर्ड की उपलब्धता को कम करना इसके लायक हो सकता है। उदाहरण के लिए, WPF से PasswordBox.SecurePassword प्रकार का है SecureString


हम्म, निश्चित रूप से जानना दिलचस्प है। सभी ईमानदारी में, मैं वास्तव में सिस्टम को प्राप्त करने के लिए आवश्यक हमलों के प्रकार के बारे में चिंतित नहीं हूं। मेरी स्मृति से बाहर मूल्य के बारे में, मैं सिर्फ शुद्ध जिज्ञासा से बाहर पूछ रहा हूं। हालाँकि, जानकारी के लिए धन्यवाद! :)
स्टीवन जेफ्रीज़

2

कुछ समय पहले मुझे जावा क्रेडिट कार्ड से भुगतान गेटवे के खिलाफ एसी # इंटरफ़ेस बनाना था और किसी को एक सुसंगत सुरक्षित संचार कुंजी एनक्रिप्ट की जरूरत थी। जैसा कि जावा कार्यान्वयन बल्कि विशिष्ट था और मुझे एक निश्चित तरीके से संरक्षित डेटा के साथ काम करना था।

मुझे यह डिज़ाइन सिक्योर स्ट्रींग के साथ काम करने की तुलना में उपयोग करने में काफी आसान और आसान लगा ... उन लोगों के लिए जो उपयोग करना पसंद करते हैं ... स्वतंत्र महसूस करते हैं, कोई कानूनी प्रतिबंध नहीं :-)। ध्यान दें कि ये कक्षाएं आंतरिक हैं, आपको उन्हें सार्वजनिक करने की आवश्यकता हो सकती है।

namespace Cardinity.Infrastructure
{
    using System.Security.Cryptography;
    using System;
    enum EncryptionMethods
    {
        None=0,
        HMACSHA1,
        HMACSHA256,
        HMACSHA384,
        HMACSHA512,
        HMACMD5
    }


internal class Protected
{
    private  Byte[] salt = Guid.NewGuid().ToByteArray();

    protected byte[] Protect(byte[] data)
    {
        try
        {
            return ProtectedData.Protect(data, salt, DataProtectionScope.CurrentUser);
        }
        catch (CryptographicException)//no reason for hackers to know it failed
        {
#if DEBUG
            throw;
#else
            return null;
#endif
        }
    }

    protected byte[] Unprotect(byte[] data)
    {
        try
        {
            return ProtectedData.Unprotect(data, salt, DataProtectionScope.CurrentUser);
        }
        catch (CryptographicException)//no reason for hackers to know it failed
        {
#if DEBUG
            throw;
#else
            return null;
#endif
        }
    }
}


    internal class SecretKeySpec:Protected,IDisposable
    {
        readonly EncryptionMethods _method;

        private byte[] _secretKey;
        public SecretKeySpec(byte[] secretKey, EncryptionMethods encryptionMethod)
        {
            _secretKey = Protect(secretKey);
            _method = encryptionMethod;
        }

        public EncryptionMethods Method => _method;
        public byte[] SecretKey => Unprotect( _secretKey);

        public void Dispose()
        {
            if (_secretKey == null)
                return;
            //overwrite array memory
            for (int i = 0; i < _secretKey.Length; i++)
            {
                _secretKey[i] = 0;
            }

            //set-null
            _secretKey = null;
        }
        ~SecretKeySpec()
        {
            Dispose();
        }
    }

    internal class Mac : Protected,IDisposable
    {
        byte[] rawHmac;
        HMAC mac;
        public Mac(SecretKeySpec key, string data)
        {

            switch (key.Method)
            {
                case EncryptionMethods.HMACMD5:
                    mac = new HMACMD5(key.SecretKey);
                    break;
                case EncryptionMethods.HMACSHA512:
                    mac = new HMACSHA512(key.SecretKey);
                    break;
                case EncryptionMethods.HMACSHA384:
                    mac = new HMACSHA384(key.SecretKey);
                    break;
                case EncryptionMethods.HMACSHA256:
                    mac = new HMACSHA256(key.SecretKey);

                break;
                case EncryptionMethods.HMACSHA1:
                    mac = new HMACSHA1(key.SecretKey);
                    break;

                default:                    
                    throw new NotSupportedException("not supported HMAC");
            }
            rawHmac = Protect( mac.ComputeHash(Cardinity.ENCODING.GetBytes(data)));            

        }

        public string AsBase64()
        {
            return System.Convert.ToBase64String(Unprotect(rawHmac));
        }

        public void Dispose()
        {
            if (rawHmac != null)
            {
                //overwrite memory address
                for (int i = 0; i < rawHmac.Length; i++)
                {
                    rawHmac[i] = 0;
                }

                //release memory now
                rawHmac = null;

            }
            mac?.Dispose();
            mac = null;

        }
        ~Mac()
        {
            Dispose();
        }
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.