بيئة تنفيذ موثوقة على مثال Intel SGX. مبادئ أساسية بعبارات بسيطة. "مرحبا بالعالم!"

هذه المقالة موجهة في المقام الأول إلى أخصائي مبتدئ فقط

بدأ البحث عن طرق وطرق ضمان أمن المعلومات لرمز البرنامج القابل للتنفيذ. عاجلاً أم آجلاً ، يواجه جميع مطوري البرامج ومهندسي النظام مثل هذه المهمة ، والتي حدثت في أحد مشاريع أنظمة Altiriks ، والتي كان من الضروري في إطارها تنفيذ التنفيذ الآمن لرمز البرنامج في بيئة غير محمية بشروط. لهذا الغرض ، بالإضافة إلى الأساليب والوسائل المعروفة والموضحة جيدًا لحماية المعلومات ، تم اختيار تقنية بيئة التنفيذ الموثوقة (TEE) ، والتي نادرًا ما تستخدم في المشاريع الروسية ، أو ، عند التحدث باللغة الروسية ، تقنية بيئات التنفيذ الموثوقة. على وجه التحديد في هذه المقالة ، قررنا وصف مثال عملي لاستخدام جيوب معالج Intel لبيئة تنفيذ التعليمات البرمجية الموثوقة (Intel Software Guard Extensions أو SGX).



لا يتم دعم أوقات التشغيل الموثوقة فقط بواسطة معالجات من جهة تصنيع معينة. أيضًا ، يتم دعم TEE بواسطة عدد من معالجات AMD (بيئة التنفيذ الآمنة والتكنولوجيا الآمنة) ومعالجات ARM (TrustZone) ومعالجات RISC-V. بالإضافة إلى ذلك ، يتم دعم TEE بواسطة حواسيب IBM Z المركزية الحديثة ، وقد اخترنا Intel SGX كمثال لأننا نعتقد أنه في وقت كتابة هذا التقرير (صيف 2020) كانت معالجات Intel هي الأكثر شيوعًا ومتاحة للمبتدئين في منطقة ما بعد الاتحاد السوفيتي. للحصول على قائمة كاملة بنماذج معالجات Intel التي تدعم Intel SGX ، قم بزيارة موقع Intel على الويب بموجب مواصفات منتجات Intel (ARK) عن طريق تحديد التقنية المناسبة للبحث. ونعم ، ربما تستفيد من محاكاة Intel SGX للأغراض التعليمية أو البحثية.كشف العمل مع العديد من هذه المحاكاة عن عدد من الصعوبات في إعدادها. تحتاج أيضًا إلى فهم أنه بالنسبة للمشروعات "القتالية" الحقيقية ، لا يُقبل بالطبع محاكاة التكنولوجيا القائمة على وظائف الجهاز.



ستساهم أي من تعليقاتك ، خاصةً مع التعليقات والإضافات من المتخصصين الذين لديهم بالفعل خبرة في استخدام TEE في مشاريعهم ، أو مع أسئلة من أولئك الذين بدأوا للتو في الغوص في هذه التكنولوجيا ، في كشف أكثر تفصيلاً عن هذا الموضوع في المقالات التالية. شكرا مقدما!



المقدمة



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



حلقات الامتياز



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





رقم الخاتم 3. تحتوي الحلقة الخارجية على جميع تطبيقات المستخدم التي نستخدمها على الكمبيوتر في الحياة اليومية ، ولديها أدنى مستوى من الوصول.

الخاتم رقم 2 ورقم 1. توجد أنظمة التشغيل وبرامج تشغيل الأجهزة في هذه المستويات.

رقم الخاتم 0. وضع المشرف. هذا هو المكان الذي توجد فيه نواة نظام التشغيل (الإدارة الطرفية ، وتخصيص الموارد بين العمليات) ، بالإضافة إلى برامج تشغيل النظام.

رقم الخاتم -1. برنامج Hypervisor. مسؤول عن تخصيص الموارد في حالة تشغيل العديد من أنظمة التشغيل على الكمبيوتر في نفس الوقت ، كما أنه مسؤول عن عزلها.

رقم الخاتم -2.وضع إدارة النظام (SMM - وضع إدارة النظام). يدير إمداد الطاقة للنظام ، ويدير بطاقات التوسيع.



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



مقاطعة



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





التطبيقات التي تعمل مع بيئة موثوقة



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



الجزء الموثوق به هو مجموعة من الوظائف والإجراءات تسمى ECALL (Enclave Call). يجب كتابة توقيع هذه الوظائف في ملف رأس خاص ، وتنفيذها في ملف التعليمات البرمجية المصدر. بشكل عام ، النهج مشابه لما نستخدمه في الكتابة المعتادة للرؤوس ، ومع ذلك ، في هذا السياق ، يتم استخدام لغة خاصة تشبه لغة C (لغة تعريف Enclave). من الضروري أيضًا كتابة نماذج أولية لتلك الوظائف التي يمكن استدعاؤها من داخل الجيب ، وتسمى هذه الوظائف OCALL (الاتصال الخارجي). تتم كتابة النماذج الأولية في نفس العنوان حيث توجد وظائف ECALL ، ويتم كتابة التنفيذ ، على عكس ECALL ، وفقًا لذلك في الجزء غير الموثوق به من التطبيق.

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



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



مرحبا بالعالم!



دعنا ننتقل من النظرية إلى التطبيق. لنكتب برنامجًا صغيرًا ينفذ المهمة الأساسية بالفعل: طباعة السلسلة "Hello world!" في هذا التفسير ، سوف نشير أيضًا إلى المكان الذي سيتم إرسال الرسالة منه.



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





قم بتشغيل VS وأنشئ مشروع Intel SGX.





نختار اسما للمشروع والحل وننتظر "التالي".



بعد ذلك ، سيُطلب منك تحديد تكوين المشروع ، لا تغير أي شيء ، اترك القيم التي تم اقتراحها في الأصل.







ثم أضف مشروعًا آخر إلى الحل الذي تم إنشاؤه: تطبيق وحدة تحكم C ++ عادي.

نتيجة لذلك ، يجب أن تظهر الصورة التالية في مربع حوار المشاريع:







إذن فأنت بحاجة إلى ربط الجيب بالجزء غير الموثوق به. انقر بزر الماوس الأيمن فوق مشروع "الجزء غير الموثوق به".







بعد ذلك ، تحتاج إلى تغيير بعض خصائص المشاريع.



صورة






يجب القيام بذلك حتى يعمل البرنامج بشكل صحيح. نكرر الخطوات لكلا المشروعين.



من الضروري أيضًا الإشارة إلى المشروع الرئيسي في خصائص الحل.





هذا كل شيء ، برنامجنا جاهز للتنفيذ.



سيحتوي هذا البرنامج على 3 ملفات سنعمل معها: Enclave.edl (نفس العنوان) ، Enclave.cpp (يتم توضيح تنفيذ ECALLs) ، الجزء غير الموثوق به. cpp (ملف المشروع الرئيسي هو الجزء غير الموثوق به). لنضع



الكود التالي في الملفات:



Untusted Part.cpp:



#define ENCLAVE_FILE "Enclave.signed.dll" //,     

#include "sgx_urts.h" // ,           
#include "Enclave_u.h" //   
#include "stdio.h"

void print_string(char* buf) //OCALL     -   
{
	printf("ocall output: %s\n", buf);
}

int main()
{
	sgx_enclave_id_t eid; // id ,      ,    id
	sgx_status_t ret = SGX_SUCCESS; //        
	sgx_launch_token_t token = { 0 }; //    
	int updated = 0; //      
	const int BUF_LEN = 30; //  ,     

	ret = sgx_create_enclave(ENCLAVE_FILE, SGX_DEBUG_FLAG, &token, &updated, &eid, NULL); //  

	if (ret != SGX_SUCCESS)
	{
		printf("Failed to create enclave with error number: %#x\n", ret); //  
		return 0;
	}
	char buf[BUF_LEN]; //  ,      

	enclaveChat(eid, buf, BUF_LEN); // ECALL  

	printf("\noutput form main(): %s\n", buf); //  
}


Enclave.edl:



enclave {
    from "sgx_tstdc.edl" import *;

    trusted {
        /* define ECALLs here. */
        public void enclaveChat([out, size=len] char* str, size_t len);
        /*   ,    . OUT -   ,   
                , out     .
           ,          ,
                 .
        */
    };

    untrusted {
        /* define OCALLs here. */
        void print_string([in, string] char* buf); //  ,     
    };
};


Enclave.cpp:



#include "Enclave_t.h"

#include "sgx_trts.h"
#include <cstring>

void enclaveChat(char* str, size_t len)
{
	char* secret = "Hello from better place"; //   

	memcpy(str, secret, len); //   ,  

	print_string(secret); // OCALL-  
}


اضغط على f7 - قم ببناء الحل ، ثم اضغط على ctrl + f5 للتشغيل.



إذا تلقيت خطأ مثل هذا:





تأكد من تمكين Intel SGX في BIOS: Bios: Security / IntelSGX / Enabled.



في حالة عدم وجود أخطاء وأمام الشاشة على الكونسول رأيت الأسطر التالية:





... تهانينا ، برنامجك الأول مع تقنية Intel SGX جاهز. آمل أن تكون التعليقات الواردة في الكود شاملة للفهم ، وإلا يمكنك دائمًا طرح الأسئلة هنا في التعليقات أو في الرسائل الخاصة.



All Articles