2010-05-10 7 views
18

क्या आपकी कंपनी द्वारा हस्ताक्षरित किसी अन्य असेंबली से उपयोग/कॉलिंग को रोकने/कॉल करने के लिए कक्षा/संपत्ति कक्षा/विधि स्तर पर अपनी असेंबली को सुरक्षित करने का कोई तरीका है?अनधिकृत कॉलर्स से सुरक्षित सी # असेंबली

मैं मजबूत नामकरण (जैसे StrongNameIdentityPermission का उपयोग करने) पर किसी भी आवश्यकता के बिना ऐसा करना चाहता हूं और एक असेंबली पर हस्ताक्षर किए जाने के साथ चिपकना चाहता हूं। मैं वास्तव में InternalsVisibleTo विशेषता का उपयोग करने का सहारा नहीं लेना चाहता क्योंकि यह किसी भी बदलते सॉफ्टवेयर पारिस्थितिक तंत्र में रखरखाव योग्य नहीं है।

उदाहरण के लिए:

परिदृश्य एक

Foo.dll मेरी कंपनी द्वारा हस्ताक्षर किए है और Bar.dll बिल्कुल हस्ताक्षरित नहीं है।

फू क्लास ए है बार कक्षा बी है

क्लास ए सार्वजनिक विधि GetSomething() कक्षा बी Foo.A.GetSomething (कॉल करने के लिए कोशिश करता है) है और अस्वीकार कर दिया है

अस्वीकृत एक अपवाद हो सकता है या किसी न किसी प्रकार

परिदृश्य में अनदेखा किया जा रहा दो

Foo.dll मेरी कंपनी द्वारा हस्ताक्षर किए है और Moo.dll भी द्वारा हस्ताक्षर किए गए है मेरी कंपनी।

फू है कक्षा सी

क्लास ए सार्वजनिक विधि GetSomething() कक्षा सी Foo.A.GetSomething (कॉल करने के लिए कोशिश करता है) और

+0

"हस्ताक्षरित" समझाएं। आपने विशेष रूप से मजबूत नामकरण नहीं कहा है, इसलिए आप .NET में उपलब्ध साइनिंग विकल्प के बारे में बात नहीं कर रहे हैं (क्योंकि यह मजबूत नामकरण है)। क्या आप इसके बजाय प्रामाणिक हस्ताक्षर का संकेत दे रहे हैं? –

+0

हस्ताक्षरित लेकिन मजबूत नाम नहीं, मजबूत नामकरण हस्ताक्षर कर रहा है और अधिक। तो यदि आपके पास Verisign प्रमाण है तो आप इसका उपयोग डीएलएल, EXE, या जो भी हो, पर हस्ताक्षर करने के लिए कर सकते हैं। –

+0

सही, तो कोड हस्ताक्षर प्रमाणपत्र के माध्यम से फिर से प्रमाणीकरण हस्ताक्षर? –

उत्तर

6

यदि आप कॉलर्स को केवल उस कोड पर सीमित करना चाहते हैं जो किसी विशिष्ट प्रमाणपत्र द्वारा हस्ताक्षरित प्रमाणीकरण किया गया है, तो भी आप सीएएस (केवल स्ट्रॉन्गनाम इडेंटिटी पैरामिशन नहीं) का उपयोग कर सकते हैं।

PublisherIdentityPermission का उपयोग करें जैसे कि आपने किसी भी सीएएस अनुमतियों का उपयोग किया होगा। या यदि आप इसे घोषणात्मक रूप से करना चाहते हैं, use an attribute

+0

धन्यवाद, मैं इसमें खोदूँगा। ऐसा लगता है कि यह मेरी पहली नज़र में समस्या को हल कर सकता है। –

+0

क्या आप कोड उदाहरण प्रकाशित कर सकते हैं? (Http://pastebin.com/ या कोई भी कोडहोस्टिंग मदद कर सकता है) – Elshan

+0

प्रति एमएसडीएन, यह समाधान अब .NET 4.0 के रूप में मान्य नहीं है। ढांचे द्वारा पहचान आधारित अनुमतियों को अब लागू नहीं किया जाता है। –

2

मैंने देखा है DLL के अस्वीकार कर दिया है है क्लास ए मू है कंपनियों द्वारा लिखित (सबसे विशेष रूप से पेगासस इमेजिंग) जो असेंबली अनलॉक करने के लिए चुनौती/प्रतिक्रिया प्रणाली का उपयोग करती है। डीएलएल के क्रेता को क्रेता के नाम से बंधे "लाइसेंस कोड" के साथ प्रदान किया जाता है, जिसे डीएलएल का उपभोक्ता डीएलएल की विशेषताओं के एक विशिष्ट सबसेट को अनलॉक करने के लिए उपयोग करता है।

इसलिए जब असेंबली एप्लिकेशन द्वारा पहली बार उपयोग की जाती है, तो Unlock() विधि को असेंबली में बुलाया जाता है। उपयोगकर्ता का नाम और अनलॉक कोड पास किया जाता है और एक एल्गोरिदम के माध्यम से चलाया जाता है जो पहचान को सत्यापित करता है, संभवतः किसी प्रकार के सार्वजनिक कुंजी एन्क्रिप्शन एल्गोरिदम का उपयोग कर।

अनलॉक कोड में एन्कोड किए गए कुछ बिट्स हैं जो विशेषताएं निर्दिष्ट करते हैं; इन बिट्स ने असेंबली में कुछ फीचर फ्लैग सेट किए हैं। उचित कॉलिंग सक्षम है या नहीं, यह निर्धारित करने के लिए सभी कॉलिंग फ़ंक्शंस को इन झंडे को जांचना होगा। Unlock() विधि केवल एक बार बुलाया जाता है, और लोड असेंबली के जीवनकाल के लिए अच्छा है।

बेशक, चूंकि आपको असेंबली में "निजी कुंजी" प्रदान करनी है, इसलिए यह प्रक्रिया हैक-सबूत (क्या है?) नहीं है, लेकिन यह उचित रूप से सुरक्षित है, और ईमानदार लोगों को ईमानदार बनाए रखेगी।

+0

मैं निश्चित रूप से अपना खुद का छोटा ढांचा लिख ​​सकता हूं कि एक असेंबली में हर विधि जिसे मुझे सुरक्षित करने की आवश्यकता है उसे एक बूल कहा जाएगा: इसे करने के लिए आगे बढ़ने की अनुमति देने से पहले() विधि या कुछ सत्यापित करें। हालांकि मैं कुछ ऐसा ढूंढ रहा हूं जो मुझे उम्मीद है कि नेट फ्रेमवर्क का हिस्सा है और इसे असेंबलीइन्फो में जोड़ा जा सकता है, मूल रूप से कुछ और वैश्विक जो संकलन समय पर सुरक्षित काम से निपटेंगे। –

+0

उत्कृष्ट। मैं थोड़ी देर के लिए इस तरह के शिखर सम्मेलन के लिए चारों ओर कास्टिंग कर रहा हूं। वेब पर इस तरह के सुरक्षा विवरण का अधिक क्यों नहीं है। –

+0

@ क्रीपी जीनोम: इसके लिए आपको अपना खुद का ढांचा लिखने की आवश्यकता नहीं है, यही एओपी है। – R0MANARMY

0

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

आप निष्पादन वातावरण को नियंत्रित हैं, तो आप एक AppDomain जहाँ आपके कोड पूरी तरह से विश्वसनीय है बना सकते हैं, और तीसरे पक्ष के कोड आंशिक रूप से विश्वसनीय है और जब तक आप एक AllowPartiallyTrustedCallersAttribute (APTCA) विधानसभा पर डाल अपने कोड फोन नहीं कर सकते हैं। आप एपीटीसीए असेंबली में SecurityCritical और SecuritySafeCritical विशेषताओं के साथ कौन सी विधियों को कॉल कर सकते हैं प्रतिबंधित कर सकते हैं।

How to: Run Partially Trusted Code in a Sandbox

2

सबसे पहले, के रूप में आपको पता है, यह नहीं InternalsVisibleTo उपयोग करने के लिए पर्याप्त है - आप भी हस्ताक्षर और दृढ़ता से नाम प्रत्येक विधानसभा कोई सुनिश्चित करने के लिए सिर्फ नाम धोखा नहीं कर सकता की आवश्यकता होगी।

अब यह कि रास्ते से बाहर है, आपको अपने आप को चुनौती-प्रतिक्रिया कार्यान्वयन विकसित करना होगा - यह ऐसा कुछ नहीं है जब तक कि आप InternalsVisibleTo दृष्टिकोण का उपयोग करने के इच्छुक न हों, जिसे आप स्पष्ट रूप से वर्णन करते हैं उपयोग नहीं करना चाहते हैं।

एक सी-आर मॉडल में, आपको प्रत्येक विधि कॉल (या शायद किसी ऑब्जेक्ट को तुरंत चालू करने के लिए) के साथ किसी प्रकार का टोकन पास करना होगा। टोकन एक वर्ग होगा जो केवल आपका कोड एक उदाहरण बना सकता है - मैं इसे उस असेंबली का एक आंतरिक वर्ग बनाउंगा जिसे आप उपभोग करना चाहते हैं और InternalsVisibleTo के साथ इसे सुलभ बनाते हैं - इस तरह केवल एक वर्ग को प्रबंधित करने की आवश्यकता होती है:

// SharedAssembly.dll 
// marks ConsumingAssembly.dll as having access to internals... 

internal sealed class AccessToken { } 

public class SecuredClass 
{ 
    public static bool WorkMethod(AccessToken token, string otherParameter) 
    { 
     if(token == null) 
      throw new ArgumentException(); // you may want a custom exception. 

     // do your business logic... 
     return true;   
    } 
} 



// ConsumingAssembly.dll (has access via InternalsVisibleTo) 

public class MainClass 
{ 
    public static void Main() 
    { 
     var token = new AccessToken(); // can create this because of IVT access 
     SecuredClass.WorkMethod(token, ""); // tada... 
    } 
} 

आप किसी तृतीय विधानसभा में AccessToken वर्ग डाल करने के लिए है कि दोनों सेवा प्रदाता और उपभोक्ता के बारे में इतना है कि आप लगातार विभिन्न विधानसभाओं के लिए पहुँच टोकन कक्षाओं के लिए एक अलग समूह बनाए रखने के लिए की जरूरत नहीं है पता कर सकते हैं।

प्रत्येक विधि के लिए सी-आर तंत्र का निर्माण बोझिल और थकाऊ है। यह 100% मूर्खतापूर्ण नहीं है - पर्याप्त समय और धैर्य वाला कोई व्यक्ति शायद इसके चारों ओर एक रास्ता खोज सकता है।

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

2

मुझे लगता है कि यह कुछ भी नहीं है! यदि आप वास्तव में सुरक्षा चाहते हैं, तो अपने कोड को सर्वर के पीछे रखें और क्लाइंट-सर्वर आर्किटेक्चर का उपयोग करें। या वेब सेवाएं। या डब्ल्यूसीएफ, या रिमोटिंग जैसे बीच में कुछ। फिर क्लाइंट को प्रमाणीकृत करने के लिए प्रमाणीकरण का उपयोग करें।

हेक आप सबकुछ निजी बना सकते हैं, सार्वजनिक एपीआई का पर्दाफाश कर सकते हैं और स्थानीय रूप से कॉल जड़ सकते हैं।

डेस्कटॉप में अनधिकृत कॉलर्स से एक डीएल सुरक्षित करना केवल पर्यावरण केवल मामलों को और अधिक जटिल और काम करने में कठिन बनाता है। उल्लेख नहीं है कि यह अंदर पर बहुत बदसूरत लगेगा।

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

6

जाहिर है आपको बुलाए गए विधि के भीतर से प्रत्येक कॉल पर एक चेक करना है - प्रतिबंधों को लागू करने की कोशिश कर रहे किसी भी बाहरी सिस्टम को प्रतिबिंब का उपयोग करके आसानी से बाईपास किया जाता है।

विधि के भीतर से

आप

new StackTrace().GetFrame(1).GetMethod().Module.Assembly 

का उपयोग बुला विधानसभा पाने के लिए कर सकते हैं। अब आप

callingAssembly.GetName().GetPublicKey() 

का उपयोग बुला विधानसभा की सार्वजनिक कुंजी प्राप्त करने के लिए और कहा जाता विधानसभा की सार्वजनिक कुंजी के साथ तुलना कर सकते हैं। यदि वे मेल खाते हैं - मानते हैं कि आपकी सभी असेंबली एक ही कुंजी जोड़ी के साथ हस्ताक्षरित हैं - कॉलर को वैध कॉलर के रूप में स्वीकार किया जाता है।

लेकिन एक लूप छेद है - एक तृतीय पक्ष असेंबली में आपकी कंपनियों की सार्वजनिक कुंजी के साथ हस्ताक्षर किए जा सकते हैं और डिजिटल हस्ताक्षर सत्यापन से बाहर रखा जा सकता है। नतीजतन लोडर तीसरे पक्ष की असेंबली को एक मजबूत नाम और आपकी कंपनियों की सार्वजनिक कुंजी के साथ लोड करेगा, भले ही यह अभी तक हस्ताक्षरित न हो। इस लूप छेद को बंद करने के लिए आपको हस्ताक्षर की जांच करनी होगी। कोई प्रबंधित एपीआई है और आप पी करने के लिए है/true को fForceVerification सेट के साथ आह्वान

Boolean StrongNameSignatureVerificationEx(
    String wszFilePath, 
    Boolean fForceVerification, 
    ref Boolean pfWasVerified) 

और यदि परिणाम true है की जाँच करें।

सभी एक साथ यह प्रति कॉल काफी अधिक ओवरहेड हो सकता है। प्रलोभन शायद परिणाम को कैश करने के लिए है, लेकिन प्रतिबिंब अनुमति के साथ एक कॉलर मानते हुए शायद इस तरह के कैश में हेरफेर करना मुश्किल नहीं है। दूसरी तरफ आप 100% निश्चित नहीं होंगे। जो सिस्टम को कभी नियंत्रित करता है वह लगभग हर चीज (लगभग) करने के लिए स्वतंत्र होता है - एक डीबगर संलग्न करें, मेमोरी सामग्री संशोधित करें, पुस्तकालयों या पूरे रनटाइम में हेरफेर करें। आखिरकार आपको अपनी असेंबली को अपघटन और संशोधन से कुशलता से सुरक्षित रखना होगा।

+0

इस चेक के संबंध में: नया स्टैकट्रेस()। GetFrame (1) .GetMethod()। मॉड्यूल। एस्सेप्लर, क्या हम स्टैक ट्रेस को सभी तरह से असेंबली की जांच नहीं करनी चाहिए? अन्यथा हमलावर से संबंधित एक मध्यस्थ असेंबली (या कॉलिंग एप्लिकेशन) हो सकता है। –

+0

यदि आप प्रत्येक विधि (और संपत्ति) में चेक करते हैं, तो आप हमेशा एक अनधिकृत कॉलर को पकड़ लेंगे जब वह पहले संरक्षित कोड में कॉल करने का प्रयास करता है - स्टैक पर चलने की कोई आवश्यकता नहीं है। –

संबंधित मुद्दे