هل يمكن استخدام التسمية القوية للتجميع للتحقق من مؤلف التجميع؟

StackOverflow https://stackoverflow.com/questions/369248

سؤال

لقد قرأت المقال المناسب في MSDN، الجمعيات ذات الأسماء القوية وسؤال Stack Overflow ذي الصلة، التحقق من التجميع للحصول على اسم قوي.

  1. إلى أي مدى يمكن التحقق من التجمع ذو الاسم القوي لتجنب التلاعب به؟
  2. هل من الممكن استخدام التسمية القوية للتحقق من مؤلف التجميع؟

السؤال الأول يطرح بعد قراءة مقالة CSharp411 الأسئلة الشائعة حول .NET Assembly - الجزء 3 - الأسماء القوية والتوقيع, ، والذي يذكر هذا، من بين مشاكل أخرى لاستخدام الأسماء القوية:

"لا يمكن إيقاف الاستبدال الكامل. لا يمكن للأسماء القوية أن تمنع المتسلل من إزالة توقيع الاسم الواضح، وتعديل التجميع الخاص بك بشكل ضار، وإعادة التوقيع عليه بمفتاحه الخاص، ثم تمرير تجميعه على أنه تجميعك."

يهدف السؤال الثاني إلى إيجاد الاختلافات بين التسمية القوية وأنظمة التوقيع الأخرى مثل، على سبيل المثال، رمز المصادقة.ذكرت نفس مقالة MSDN الحالات المبكرة:

"ومع ذلك، لاحظ أن الأسماء القوية في حد ذاتها لا تعني مستوى من الثقة مثل ذلك الذي يوفره، على سبيل المثال، التوقيع الرقمي والشهادة الداعمة."

هل أحاول استخدام التسمية القوية لأكثر بكثير مما تم إنشاؤه من أجله؟هل تم إنشاء التسمية القوية فقط لتجنب تضارب الأسماء أو نوع جديد من "GAC DLL Hell"؟

هل كانت مفيدة؟

المحلول

عندما تقوم بالتوقيع على تجميع باسم واضح يستند إلى مفتاح خاص تقوم بإنشائه، فإن ذلك له الفوائد التالية:

  • يضمن الاسم القوي تفرد هوية التجميع عن طريق إضافة رمز مفتاح عام وتوقيع رقمي إلى التجميع.
  • يمكن مطابقة الاسم الواضح مع مفتاح عام لإثبات أن التجميع يأتي من الناشر الذي يحمل هذا المفتاح العام، وهذا الناشر فقط.
  • يوفر الاسم القوي فحصًا قويًا للسلامة.يضمن اجتياز اختبارات أمان .NET Framework عدم تغيير محتويات التجميع منذ إنشائه آخر مرة.

هل من الممكن استخدام التسمية القوية للتحقق من مؤلف التجميع؟

نعم، كما تمت مناقشته أعلاه، يمكن للتسمية القوية التحقق من صحة التجميع أحدث مؤلف.لكنها لا تتحقق من المؤلف الأصلي.إذا قام أحد المهاجمين باستبدال الاسم القوي لتجميعك، فكل ما يمكن التحقق منه هو أنك لم تكن المؤلف الأخير للتجميع.إذا قام بإزالة الاسم القوي، فلا يمكن إجراء التحقق من المؤلف على الإطلاق.

إلى أي مدى يمكن التحقق من التجمع ذو الاسم القوي لتجنب التلاعب به؟

يتحقق كود C# التالي من أن المهاجم لم يتلاعب بالرمز المميز للمفتاح العام الذي تم كتابته إلى التجميع الخاص بك عند تطبيق الاسم الواضح.إنه لا يتجنب العبث، لكن يمكنه اكتشاف بعض أنواع العبث.تقبل الطريقة أدناه مصفوفة بايت تحتوي على رمز المفتاح العام الخاص بك، وتقارنها بالرمز الفعلي للتجميع.لاحظ أنه لكي تكون هذه التقنية فعالة، يجب على أداة التشويش التي تختارها أن تقوم بتشفير السلسلة التي تحتوي على رمز المفتاح العام الخاص بك، وفك تشفيرها فقط أثناء استخدامها.وكن على علم أيضًا أنك تحتاج إلى الحصول على إذن FullTrust حتى يعمل هذا الرمز لأنه يستخدم الانعكاس أسفل الغطاء.

// Check that public key token matches what's expected.
private static bool IsPublicTokenOkay_Check(byte [] tokenExpected)
{
    // Retrieve token from current assembly
    byte [] tokenCurrent = Assembly.GetExecutingAssembly().GetName().GetPublicKeyToken();

    // Check that lengths match
    if (tokenExpected.Length == tokenCurrent.Length)
    {
        // Check that token contents match
        for (int i = 0; i < tokenCurrent.Length; i++)
            if (tokenExpected[i] != tokenCurrent[i]) 
                return false;
    }
    else
    {
        return false;
    }
    return true;
}

طالما أنك تعمل ضمن إصدار .NET Framework قبل .NET 3.5 SP1، يمكنك أيضًا فرض التحقق من توقيع الاسم الواضح في حالة إزالة الاسم الواضح من قبل مهاجم أو تم تعطيل التحقق من الاسم الواضح في التسجيل.يوضح التعليمة البرمجية التالية استدعاء أسلوب ثابت لفئة أخرى تسمى NativeMethods.هذا هو المكان الذي سيتم فيه فرض التحقق.

// Check that this assembly has a strong name.
private bool IsStrongNameValid_Check()
{
    byte wasVerified = Convert.ToByte(false); 
     byte forceVerification = Convert.ToByte(true);
    string assemblyName = AppDomain.CurrentDomain.BaseDirectory + 
                          AppDomain.CurrentDomain.FriendlyName; 
    return NativeMethods.CheckSignature(assemblyName, 
                                        forceVerification, 
                                        ref wasVerified);
}

يتم التحقق من التوقيع الفعلي باستخدام P/Invoc كما هو موضح أدناه.استخدام StrongNameSignatureVerificationEx واجهة برمجة التطبيقات (API) معقدة للغاية - للحصول على تفسير لائق، راجع هذا الإدخال بلوق.

// P/Invoke to check various security settings
// Using byte for arguments rather than bool, 
// because bool won't work on 64-bit Windows!
[DllImport("mscoree.dll", CharSet=CharSet.Unicode)]
private static extern bool StrongNameSignatureVerificationEx(string wszFilePath, 
                                                             byte fForceVerification, 
                                                             ref byte pfWasVerified);

// Private constructor because this type has no non-static members
private NativeMethods()
{
}

public static bool CheckSignature(string assemblyName, 
                                  byte forceVerification, 
                                  ref byte wasVerified)
{
    return StrongNameSignatureVerificationEx(assemblyName, 
                                             forceVerification, 
                                             ref wasVerified );
}

لاحظ أن هذا لن يعمل بشكل افتراضي للتطبيقات التي تستخدم .NET 3.5 SP1 أو أعلى، والتي تحتوي على ميزة تجاوز الاسم القوي.من الممكن أن تعطيل هذه الميزة للتطبيق الخاص بك عن طريق إضافة إعداد إلى ملف التكوين الخاص به.ولكن بالطبع يمكن لأي مهاجم لديه حق الوصول للقراءة/الكتابة إلى ملف التكوين هذا التراجع عن قرارك.

نصائح أخرى

يعتمد رمز المصادقة على مرجع مصدق لجهة خارجية للتحقق من صحة الشهادة.تعمل التسمية القوية كشهادة موقعة ذاتيًا ويمكن التعامل معها على هذا النحو.إنه يستخدم التوقيعات الرقمية القياسية، لكن المشكلة تكمن في التحقق من صحة المفتاح العام لمؤلف التجميع.إذا حصلت عليها بشكل منفصل عبر قناة موثوقة من المؤلف وتثق في تلك القناة، فنعم، يمكنك التحقق منها تمامًا مثل الشهادة الموقعة ذاتيًا.

طالما أنك متأكد من أن المفتاح الخاص للاسم الواضح آمن من قبل المؤلف وتعرف المفتاح العام للمؤلف، فيمكنك التأكد من عدم العبث به (إلى الحد الذي يمكنك من التأكد من عدم التلاعب بالبريد الإلكتروني الموقع رقميًا).بالمناسبة لا تفهموني خطأ:الاقتباس صحيح تمامًا ويمكن للمهاجم بسهولة إنهاء التجميع أو إزالة التوقيع الموجود.ومع ذلك، سيكون للتجميع الناتج توقيع رقمي **مختلف* يمكن مقارنته بالأصل (إذا كان لديك المفتاح العمومي الأصلي).

وفي هذه الحالة، فهي تشبه شهادة موقعة ذاتيًا.إذا كان بإمكانك التأكد بطريقة أو بأخرى من المفتاح العام للمؤلف، فيمكنك التحقق من السلطة.ومع ذلك، على عكس رمز المصادقة الذي يعتمد على مرجع مصدق، لا توجد طريقة واضحة ومحددة من قبل النظام لتوزيع المفتاح العام.

أعتقد أن الأسماء القوية مفيدة لإصدار الإصدارات ويمكن استخدامها للمساعدة في تحديد مستويات الثقة لـ Code Access Security يحرر: ولكن لا يمكنك استخدامها للتحقق من تأليف التجميع بواسطة شخص موثوق به أو بواسطة مؤلف محدد. راجع تعليق @RoadWarrior وإجابة @RoadWarrior على هذا السؤال.

إن التسمية القوية لمجموعتك لا تجعلها مقاومة للتلاعب.
يحرر: اطلع على تعليقات @RoadWarrior و@divo.إذا كان تطبيقك يتحقق من المفتاح الخاص الأصلي من مؤلف التجميع ويفرض التحقق من الاسم القوي، فإن بياني غير صحيح.ومع ذلك، إذا كان المهاجم لديه حق الوصول إلى الجميع التجميعات الموجودة في تطبيقك و/أو الذي تستخدمه للتحقق من الاسم القوي الجاهز كما هو منصوص عليه مجانًا من CLR، فأنا ألتزم بما قلته.

يمكن تخريب هذا عن طريق مهاجم مصمم.

قرأت نقاش منذ بعض الوقت، تحدثنا عن الأسماء القوية والأمان الذي دفعني إلى الاعتقاد بأنه بالنسبة للتجميعات التي ننتجها، كان المصادقة بمثابة ضمان أفضل لعملائنا بأن التجميع جاء من مصدر موثوق به.

أعتقد أن هناك طريقة لاستخدام الاسم القوي لغرض "الثقة".أدرك أن Microsoft توصي فقط بالاسم القوي لضمان عدم تعديل محتويات التجميع وتقترح استخدام "رمز المصادقة" للحصول على الثقة.

ولكن إذا كان تطبيق المُحمل (التطبيق الذي يقوم بتحميل هذه التجميعات/البرامج) يحتفظ بقائمة مشفرة من "التجميعات" التي يمكنه تحميلها؛ألن يحل هذا مشكلة "الثقة"؟

على سبيل المثال، يمكن لمحمل الحزمة الحفاظ على اسم التجميع باستخدام المفاتيح العامة وتحميل التجميع/البرنامج عبر اسم التجميع الكامل؟

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top