النسخ الاحتياطي موثوقة وآمنة وتنوعا ل U2F

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

yubikey

طرق النسخ الاحتياطي شعبية


حتى الآن ، كان من الممارسات الجيدة الاحتفاظ برمز U2F مستقل ثانٍ للنسخ الاحتياطي ؛ يجب إضافة هذا الرمز المميز يدويًا إلى كل خدمة وتخزينه في مكان "آمن". ممارسة شائعة أخرى هي استخدام الأسلوب غير U2F كنسخة احتياطية (OTP ، رموز الاسترداد). بصراحة ، كلا الطريقتين تترك الكثير مما هو مرغوب فيه.

رمز U2F المستقل


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

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

في رأيي ، هذه "الممارسة المثالية" ليست موثوقة للغاية ، ومرهقة إلى حد ما. دعنا ننظر إلى ممارسة شائعة أخرى.

طريقة غير U2F كنسخة احتياطية


مكتب المدعي العام:

  • استخدام OTP كنسخة احتياطية أفضل من استخدامه كطريقة 2FA الرئيسية ، ولكن حقيقة وجود OTP تفتح بطريقة ما ناقلًا إضافيًا للهجوم ؛
  • تتعطل الهواتف وتضيع وتُسرق ، وإذا كانت هناك بعد فقدانها فرصة أن تكون في أيدي أشخاص غير مصرح لهم ، فأنت بحاجة إلى تذكر هذه النسخة الاحتياطية يدويًا على جميع الحسابات ؛
  • أحمل دائمًا هاتفًا ورمز U2F معي ، لذا مرة أخرى ، فإن طريقة النسخ الاحتياطي هذه ليست مثالية: إن احتمال فقدهما فورًا أعلى بكثير مما لو تم تخزين النسخة الاحتياطية بشكل منفصل. ولكن يمكن تعويض هذا العنصر قليلاً باستخدام ، على سبيل المثال ، Authy ، الذي يخزن النسخة الاحتياطية المشفرة على خادمه ؛
  • طريقة غير عالمية: لسوء الحظ ، يوجد عدد كاف من الخدمات التي تقدم تطبيقات مخصصة فقط ولا تدعم TOTP القياسي.

رموز الاسترداد:

  • يجب تخزين رموز الاسترداد في مكان آمن. مرة أخرى ، من المرجح أن يكون هذا "المكان الآمن" هو منزلي ، حيث تعاني من نفس المشكلات تقريبًا مثل رمز U2F منفصل ؛
  • مرة أخرى ، طريقة غير عالمية: كل خدمة لها نهجها الخاص في النسخ الاحتياطي

باختصار ، كل هذه الأساليب غير عالمية ومرهقة وليست آمنة.

أفضل طريقة النسخ الاحتياطي


الآن ، بعد أن انتقدت الوضع الحالي بما فيه الكفاية ، سأقول أخيرًا ما أريد حقًا. أريد حقًا أن يكون لدي رمزان U2F: أساسي ونسخ احتياطي ، ولكن يجب تهيئتهما بطريقة معينة:

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

قبل أن نناقش الجدوى الفنية لهذا الأمر داخل U2F ، سأشرح لك سبب كونه رائعًا وكيف أستخدمه.

لماذا هو عظيم


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

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

وإذا حدث شيء سيء بالفعل مع الرمز الرئيسي ، فأفعل ما يلي:

  • أنا أحفر / أزل رمزًا للنسخ الاحتياطي ؛
  • المصادقة على جميع خدماتي مع U2F ، وبالتالي إلغاء الرمز الرئيسي ؛
  • أطلب زوجًا جديدًا من الرموز ، وعند الاستلام ، أضف رمزًا رئيسيًا جديدًا على جميع الخدمات ، وألغي الرمز القديم.

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

تطبيق


نظرة عامة على بروتوكول U2F


قبل أن نتمكن من التحدث عن التنفيذ ، نحتاج أن نفهم في مستوى معين كيف تعمل U2F. تقوم معظم الشركات المصنعة بتنفيذها على النحو التالي (ليس كل ما يلي موجودًا في المعيار ؛ بعض الأشياء هي تفاصيل التنفيذ ، لكن معظم التطبيقات الحالية ، حسب علمي ، تعمل بهذه الطريقة):

device_secret برمجة device_secret في الرمز المميز U2F ، إلى جانب counter 32 بت ، والذي يمكن device_secret فقط. عندما نسجل رمز U2F على إحدى الخدمات ، يحدث ما يلي:

  • يرسل المستعرض AppID (في الواقع ، اسم المجال) إلى جهاز U2F ؛
  • ينشئ الجهاز رقمًا عشوائيًا ( nonce ) ، device_secret مع AppID ، device_secret عبر HMAC-SHA256 باستخدام device_secret كمفتاح ، وتصبح التجزئة الناتجة المفتاح الخاص لهذه الخدمة المعينة: service_private_key ؛
  • من service_private_key ، service_public_key إنشاء المفتاح العمومي service_public_key ؛
  • يأخذ الجهاز AppID مرة أخرى ، service_private_key مع service_private_key ، device_secret عبر HMAC-SHA256 مرة أخرى باستخدام device_secret كمفتاح. تصبح النتيجة ( MAC ) ، بالإضافة إلى nonce التي تم إنشاؤها مسبقًا ، key_handle ؛
  • يرسل الجهاز key_handle و service_public_key مرة أخرى إلى المستعرض ، key_handle المستعرض إلى الخدمة ، التي تحفظ هذه البيانات للمصادقة في المستقبل.

تستمر المصادقة اللاحقة على النحو التالي:

  • تنشئ الخدمة challenge (بيانات تم إنشاؤها عشوائيًا) وترسلها إلى المستعرض مع key_handle (الذي يتكون من nonce و MAC ). يمرر المستعرض كل هذا إلى الجهاز ، إلى جانب AppID (أي اسم المجال) ؛
  • يقوم الجهاز ، الذي يحتوي على nonce و AppID ، بإنشاء service_private_key بالطريقة نفسها التي تم إنشاؤها أثناء التسجيل ؛
  • ينشئ الجهاز MAC بنفس طريقة التسجيل ، ومقارنته مع MAC المستلم من المستعرض ، فإنه يتأكد من nonce استبدال nonce ، وبالتالي ، فإن service_private_key موثوقة ؛
  • زيادات الجهاز counter .
  • يقوم الجهاز بتوقيع challenge و AppID counter باستخدام service_private_key ، ويرسل التوقيع الناتج ( signature ) counter المستعرض ، الذي ينقل هذه البيانات إلى الخدمة ؛
  • تقوم الخدمة بالتحقق من signature باستخدام service_public_key لديها بعد التسجيل. أيضًا ، تحقق معظم الخدمات من أن counter أكبر من القيمة السابقة (إذا لم تكن المصادقة الأولى). الغرض من هذا الاختبار هو جعل استنساخ أجهزة U2F غير ممكن الوصول إليه. نتيجة لذلك ، إذا كانت مطابقة signature counter أكبر من القيمة السابقة ، فسيتم اعتبار المصادقة مكتملة بنجاح ، وتوفر الخدمة قيمة counter الجديدة.

الآن دعنا نوضح التفاصيل المتعلقة مباشرة بالمناقشة.

تفاصيل الاهتمام


الأول هو أن الجهاز لا يخزن service_private_key لكل خدمة: بدلاً من ذلك ، فإنه يعرض service_private_key كل مرة باستخدام HMAC-SHA256. هذا مهم للغاية بالنسبة لنا: من الواضح أنه إذا كان كل جهاز سيخزن مفاتيح فريدة بشكل منفصل لكل خدمة ، عندها فقط يمكن لهذا الجهاز المصادقة لاحقًا.

هذا ، بالمناسبة ، ليس من متطلبات U2F: U2F لا يشير إلى كيفية تخزين المفاتيح ، وقد فعلت بعض عمليات التنفيذ المبكرة لـ U2F ، في الواقع ، مفاتيح المتجر لكل خدمة على حدة. هذا النهج له عيب أن عدد الخدمات التي يمكن استخدام الجهاز لها محدود. اشتقاق service_private_key هذا العيب.

وثانيا ، يحتوي الجهاز على counter لمنع الاستنساخ.

للوهلة الأولى ، قد يبدو أن هذا counter لا يسمح لنا بتنفيذ إستراتيجية النسخ الاحتياطي التي تمت مناقشتها (على الأقل بدا لي عندما حاولت إيجاد حل) ، ولكنه في الحقيقة ، يساعدنا فقط! ساوضح الان

الفكرة الرئيسية


الفكرة هي: في مرحلة الإنتاج ، قم device_secret بطريقة بحيث يكون لكل منهما نفس device_secret ، ولكن يحتاج رمز النسخ الاحتياطي إلى بعض التصحيح: بدلاً من استخدام counter في شكله النقي (كما تفعل الرموز المميزة العادية) ، يجب إضافة بعض ثابت كبير counter . على سبيل المثال ، نصف نطاق 32 بت ، أي ما يقرب من 2 000 000 000 ، يبدو ذلك معقولًا: لا يُرجح أن استنفد الكثير من المصادقة في حياتي كلها.

في الواقع ، هذا كل شيء. بسيطة وفعالة.

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

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

ملاحظة حول العداد


قد يلاحظ القارئ اليقظ وجود مشكلة الأمان التالية: ماذا لو تمكن المهاجم من الوصول إلى الرمز الرئيسي وبدأ بطريقة أو بأخرى مصادقة 2،000،000،000؟ ثم يمكنه الوصول إلى الخدمة حتى بعد استخدام رمز النسخ الاحتياطي في هذه الخدمة.

لحسن الحظ ، هذه المشكلة لديها حل بسيط. في أي حال ، يجب تنفيذ العداد في الأجهزة (من المفترض على بعض معالج التشفير) ، وللتنفيذ الآمن ، يجب أن يكون عداد الأجهزة هذا أقل من 32 بت. على سبيل المثال ، على ATECC508A ، لا يمكن للعدادات حساب حتى 2097151 ، لذلك من خلال تعيين الثابت المضافة إلى العداد على أي قيمة أكبر من الحد الأقصى لقيمة العداد ، يمكننا أن نتأكد من أن الرمز المميز الرئيسي لا يمكن أبدًا عده إلى العداد في رمز النسخ الاحتياطي.

للتوضيح: دعنا نقول أن رمز U2F الخاص بنا يستخدم ATECC508A ، ويشير إلى العداد الموجود داخل ATECC508A على أنه hw_counter . ثم:

  • في الرمز الرئيسي ، نستخدم للحسابات: hw_counter ؛
  • في رمز النسخ الاحتياطي ، نستخدم للحسابات: hw_counter + 2000000000 .

يرجى ملاحظة أننا لا نقوم بتعديل hw_counter الحقيقي داخل معالج التشفير ؛ سيستمر الحساب من 0 إلى 2097151. بدلاً من ذلك ، في كل مرة نحتاج فيها للحصول على قيمة العداد ، نقرأ hw_counter من ATECC508A ، ثم نضيف hw_counter ونعيده (لمزيد من الحسابات لـ U2F).

وبالتالي ، سيكون نطاق قيم العداد في الرمز الرئيسي هو [0 ، 2097151] ، في حين أن نطاق قيم العداد في الرمز المميز للنسخ الاحتياطي سيكون [2000000000 ، 2002097151]. حقيقة أن هذه النطاقات لا تتداخل تضمن إلغاء الرمز المميز الرئيسي عند استخدام النسخ الاحتياطي (إذا كانت الخدمة تستخدم counter ؛ والخدمات الرئيسية التي راجعت استخدامه).

التنفيذ الفعلي


لا تدعم أي من الشركات المصنعة لرموز U2F التي أعرفها حول التخصيص المطلوب اليوم. ولكن لحسن الحظ ، هناك تطبيق مفتوح المصدر لرمز U2F: SoloKeys .

كتبت مقالتي الأصلية (باللغة الإنجليزية) قبل عام ، وهذا الجزء قديم قليلاً: ثم كانت SoloKeys في مرحلة النماذج الأولية ، واستخدمت التكرار السابق للمشروع: u2f-zero . لذلك ، لن أترجم هذا الجزء الآن ، لأن الطريقة الوحيدة للحصول على جهاز u2f-zero هي لحامه بنفسك ، ومن المستحسن القيام بذلك (على الرغم من وجود إرشادات على github).

ومع ذلك ، ترد جميع تفاصيل التعديل الضروري لـ u2f-zero في المقالة الأصلية .

عندما تصل يدي إلى solokeys ، سأكتب تعليمات لتعديله.

بطريقة أو بأخرى ، هذه هي الطريقة الوحيدة التي أعرفها اليوم للحصول على رمز U2F يعمل مع نسخة احتياطية موثوقة. أظهر التحقق من عدة خدمات (على الأقل google و github) أنه يعمل: من خلال تسجيل الرمز المميز الرئيسي في الخدمة ، يمكننا أيضًا استخدام النسخ الاحتياطي ، وبعد أول استخدام للنسخ الاحتياطي ، يتوقف الرمز الرئيسي عن العمل. Awwwwwww. <3

تحذير


على الرغم من أن استراتيجية النسخ الاحتياطي هذه رائعة ، إلا أنني لست متأكدًا من تنفيذها بشكل محدد من خلال u2f-zero أو solokey. هذا المسار هو الطريقة الوحيدة للحصول على ما تريد ، لذلك ذهبت بهذه الطريقة ؛ لكن على افتراض أن المهاجم يحصل على وصول فعلي إلى جهاز U2F ، لست متأكدًا من أن اختراق الجهاز (أي الحصول على device_secret منه) سيكون صعباً كما سيكون في حالة Yubikey أو الشركات المصنعة الرئيسية الأخرى. يدعي مؤلفو solokey أن "مستوى الأمان هو نفسه في مفتاح السيارة الحديث" ، لكنني لم أجري أي فحوصات لتأكيد ذلك.

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

لذا ، فإن السيناريو الوحيد الذي قد يكون فيه solokey أقل أمانًا من أي شيء آخر هو عندما يحاول المهاجم الوصول إلى الجهاز لفترة قصيرة من الوقت ، والحصول على device_secret منه ، وإعادة الجهاز مرة أخرى ، بطريقة غير مرئية. للقيام بذلك ، يحتاج إلى قراءة محتويات متحكم الفلاش (أو RAM في الوقت المناسب) ، وهذا ليس تافهاً للغاية.

مع الأخذ في الاعتبار جميع العوامل ، أعتقد أن الحصول على نسخة احتياطية موثوق بها بالنسبة لي شخصياً أهم بكثير من وجود تطبيق آمن للغاية للأجهزة لجهاز U2F. يعد احتمال حدوث مشكلات في مثل هذا التنفيذ الآمن وعدم وجود نسخة احتياطية جيدة أكبر من احتمال حدوث مشكلات في استخدام u2f-zero (solokey) والنسخ الاحتياطي.

استنتاج


تتفوق استراتيجية النسخ الاحتياطي المدروسة على البدائل بجميع أبعادها: فهي عالمية وأكثر أمانًا وموثوقية من أي طرق أخرى.

سأكون سعيدًا إذا قام أحد المنتجين الرئيسيين على الأقل بتنفيذ هذا في منتجاتهم ، لكن ليس هناك يقين بعد. حتى أخبرني أحد رجال دعم يوبيكو ، جيمس أ ، أن النسخة الاحتياطية هي حسب احتياجي ، "غير ممكن بالطريقة التي تم تصميم U2F" ، وبعد أن حددت تفاصيل التنفيذ ، توقف عن الاستجابة.

لحسن الحظ ، لم يكن هذا مستحيلًا كما يعتقد يوبيكو.



مقالتي الأصلية باللغة الإنجليزية: نسخ احتياطي موثوق وآمن وعالمي لـ U2F Token . لأن مؤلف المقال الأصلي هو نفسي ، إذن ، بعد إذنكم ، لم أضع هذا المقال في فئة "الترجمة" .

Source: https://habr.com/ru/post/ar474300/


All Articles