
یادداشت هایی در مورد آسیب پذیری های زنجیره تأمین
یکی از دستاوردهای ناشناخته توسعه نرم افزار مدرن ، درجه سازگاری آن است: نه چندان دور ، وقتی می خواستید یک نرم افزار بنویسید ، مجبور بودید تمام مطالب را با استفاده از هر ابزار ارائه شده بنویسید. با زبانی که می نوشتید ، شاید با چند کتابخانه تخصصی مانند OpenSSL. دیگر نه. ترکیبی از زبانهای جدیدتر ، توسعه متن باز و سیستمهای مدیریت بسته آسان برای استفاده مانند npm جاوا اسکریپت یا Rust / Cargo / crates.io انقلابی در نحوه نوشتن نرم افزار توسط مردم ایجاد کرده است و استفاده از آن در کتابخانه های شخص ثالث حتی برای ساده ترین کارها را به یک روش استاندارد تبدیل می کند. ؛ این کاملاً غیرمعمول نیست که برنامه ها به صدها یا هزاران بسته شخص ثالث وابسته باشند.
اگرچه این الگوی جدید انقلابی در توسعه نرم افزار ایجاد کرده است ، اما همچنین خطر حملات زنجیره تامین را که در آن یک مهاجم یکی از شما را به خطر می اندازد ، بسیار افزایش می دهد. وابستگی ها و از طریق آن نرم افزار شما. مصداق مشهور این مورد ، سازش 2018 بسته event-stream
برای سرقت بیت کوین از رایانه های مردم است. تاریخچه مختصر ثبت نام درک مقیاس مسئله را فراهم می کند:
آیرتون اسپارلینگ ، دانشجوی علوم کامپیوتر در دانشگاه ایالتی کالیفرنیا ، فولرتون (FallingSnow در GitHub) ، هفته گذشته این مشکل را در یک پست شماره GitHub پرچم گذاری کرد. طبق گفته Sparling ، تعهد به ماژول جریان رویداد ، جریان flatmap را به عنوان یک وابستگی اضافه کرد ، که شامل کد تزریق برای بسته بندی دیگر ، ps-tree بود.
روش های مختلفی وجود دارد که در آن مهاجم ممکن است موفق به تزریق شود. بدافزار را در یک بسته قرار دهید. در این حالت ، به نظر می رسد آنچه اتفاق افتاده این است که نگهدارنده اصلی رویداد-جریان دیگر روی آن کار نمی کرد و شخص دیگری داوطلب شد تا آن را تحویل بگیرد. به طور معمول ، این عالی خواهد بود ، اما در اینجا به نظر می رسد که داوطلب بدخواه بوده است ، بنابراین عالی نیست.
اخیراً ، اریک بروور ، راب پایک ، ابیشک آریا ، آن برتسیو و کیم لواندوفسکی پیشنهادی را برای آدرس دهی در وبلاگ امنیتی Google ارسال کردند. آسیب پذیری در نرم افزار Open Source. آنها موارد مختلفی از جمله مدیریت آسیب پذیری و امنیت تدوین را پوشش می دهند ، و چیزهای خوبی در اینجا وجود دارد ، اما بخشی که بیشترین توجه را به خود جلب کرده است ، این پیشنهاد است که بسته های خاص باید "مهم" تعیین شوند:
برای نرم افزار که برای امنیت حیاتی است ، ما باید در مورد فرآیندهای توسعه که اطمینان از بررسی کافی ، اجتناب از تغییرات یک جانبه و به طور شفاف منجر به نسخه های رسمی کاملاً قابل تأیید و قابل تأیید است ، توافق کنیم.
اینها روشهای توسعه خوبی هستند و مواردی که ما در Mozilla دنبال می کنیم ، بنابراین من مطمئناً مردم را تشویق می کنم که آنها را بپذیرند با این حال ، به نظر می رسد تلاش برای تهیه آنها برای نرم افزارهای حیاتی مشکلاتی داشته باشد.
برای توسعه دهنده اصطکاک ایجاد می کند
یکی از مزایای واقعی این مدل جدید توسعه نرم افزار ، اصطکاک کم آن است: آسان است برای ایجاد یک کتابخانه و در دسترس قرار دادن آن – شما فقط آن را می نویسید و آن را در یک مخزن بسته مانند crates.io قرار می دهید – و استفاده از آن بسته ها آسان است – شما فقط آنها را به پیکربندی ساخت خود اضافه می کنید. اما پس از آن شما موفق هستید و ناگهان بسته شما به طور گسترده ای مورد استفاده قرار می گیرد و "حیاتی" تلقی می شود و اکنون شما باید انواع روشهای جدید را اعمال کنید. اگر این کار را انجام دهید احتمالاً بهتر خواهد بود ، اما اگر این کار را نکنید چه می کنید؟ در این مرحله بسته شما به طور گسترده ای مورد استفاده قرار می گیرد – یا مهم نخواهد بود – پس اکنون چه باید کرد؟
کافی نیست
حتی بسته هایی که به خوبی نگهداری می شوند و به طور معمول از توسعه های خوبی برخوردار هستند ، معمولاً آسیب پذیر هستند. به عنوان مثال ، فایرفاکس اخیراً نسخه جدیدی را منتشر کرده است که یک آسیب پذیری را در موتور گرافیکی محبوب ANGLE برطرف کرده است ، که توسط Google حفظ می شود. هم موزیلا و هم گوگل از روال پیشنهادی این پست وبلاگ پیروی می کنند ، اما فقط مواردی است که افراد مرتکب اشتباه می شوند. به نقل از استیو بلووین (احتمالاً اشتباه) ، "نرم افزار اشکالاتی دارد. نرم افزار مربوط به امنیت دارای اشکالات مربوط به امنیت است ". بنابراین ، گرچه این اقدامات برای کاهش خطر آسیب پذیری مهم هستند ، اما ما می دانیم که آنها نمی توانند آنها را از بین ببرند.
البته این در مورد آسیب پذیری های سهوی اعمال می شود ، اما در مورد بازیگران مخرب چه می توان گفت (اگرچه توجه داشته باشید که Brewer و همکاران مشاهده می کنند که " یک قدم به عقب برگردیم ، اگرچه حملات زنجیره تأمین یک خطر است ، اکثریت قریب به اتفاق آسیب پذیری ها پیش پا افتاده و ناخواسته هستند – اشتباهات صادقانه ای که توسط توسعه دهندگان خوش فکر انجام شده است. ")؟ ممکن است برخی از تغییرات پیشنهادی آنها (به ویژه منع نویسندگان ناشناس) در اینجا تأثیر داشته باشد ، اما درک اینکه چگونه این کار عملی است واقعاً دشوار است. استاندارد برای ناشناس نبودن چیست؟ اینکه آدرس ایمیل دارید؟ یک صفحه وب؟ شماره DUNS؟ هیچ یک از این موارد جعل ساختگی برای یک مهاجم فداکار خصوصاً دشوار به نظر نمی رسد و البته هرچه سختگیرانه تر شرایط را ایجاد کنید ، برای اکثریت قریب به اتفاق توسعه دهندگان قانونی سنگین تر خواهد بود.
من می خواهم اذعان کنم که Brewer و دیگران به وضوح بیان کنید که چندین لایه محافظتی لازم است و داشتن مکانیزم های قوی برای مدیریت دفاع از آسیب پذیری ضروری است. من با همه اینها موافقم ، در مورد این قطعه خاص فقط اطمینان کمتری دارم.
بخشی از دشواری این است که راههایی وجود دارد که یک نرم افزار می تواند "حیاتی" باشد:
- این می تواند کاری انجام دهد که ذاتاً از نظر امنیتی حساس است (به عنوان مثال ، پشته OpenSSL SSL / TLS که مسئول تأمین تعداد زیادی از ترافیک اینترنت است).
- می توان آن را به طور گسترده ای استفاده کرد (به عنوان مثال ، جعبه ورود به سیستم Rust) ، اما ذاتاً آن حساس نیست. [19659017] اکثریت قریب به اتفاق بسته ها – که بسیار مورد استفاده قرار می گیرند یا نه – در دسته دوم قرار می گیرند: آنها کارهای مهمی انجام می دهند اما از نظر امنیتی مهم نیست. متأسفانه ، به دلیل نحوه ساخت نرم افزار به طور کلی ، این مهم نیست: حتی وقتی نرم افزار از انبوهی از اجزای کوچک ساخته شده باشد ، وقتی در یک برنامه واحد بسته بندی شوند ، هر جز component دارای تمام امتیازاتی است که آن برنامه دارد. بنابراین ، به عنوان مثال ، فرض کنید که شما برای انجام محاسبات آماری ، م componentلفه ای در نظر گرفته اید: اگر آن م compromلفه به خطر بیفتد ، هیچ چیز مانع از باز شدن پرونده ها روی دیسک و سرقت رمزهای عبور یا بیت کوین یا هر چیز دیگری می شود. این مصالحه به دلیل آسیب پذیری سهوی یا بدافزار تزریق شده در بسته ، درست است: یک مشکل در هر جز in کل سیستم را به خطر می اندازد. در واقع ، م componentsلفه های جزئی غیر امنیتی اهداف جالبی را ایجاد می کنند زیرا ممکن است به اندازه م componentsلفه های امنیتی با مشخصات بالا مورد بررسی قرار نگرفته باشند.
هنگامی که از این منظر به آنها نگاه می شود ، مشخص است که ما یک مشکل تکنولوژی داریم: هیچ دلیل خوبی برای فردی وجود ندارد اجزا to برای داشتن اینقدر قدرت. در عوض ، آنها فقط باید توانایی لازم برای انجام وظیفه مورد نظر خود را داشته باشند (اصطلاح فنی حداقل امتیاز). فقط این است که ابزارهای نرم افزاری ما در تهیه این ویژگی کار خوبی انجام نمی دهیم. این وضعیتی است که مدتهاست در نرم افزارهای پیچیده ای مانند مرورگرهای وب شناخته شده است ، که از تکنیکی به نام "sandboxing فرآیند" (پیشگام Chrome) استفاده می کند که در آن کدی که با وب سایت تعامل دارد در "sandbox" خود اجرا می شود. و توانایی های محدودی برای تعامل با رایانه شما دارد. هنگامی که بخواهد کاری را انجام دهد که مجاز به انجام آن نیست ، با کد اصلی مرورگر وب صحبت می کند و از او می خواهد که این کار را برای آن انجام دهد ، بنابراین به آن کد اجازه می دهد قوانین را اجرا کند بدون اینکه در معرض آسیب پذیری بقیه مرورگر قرار بگیرد.
جعبه شن و ماسه فرآیندی ابزاری مهم و قدرتمند است ، اما ابزاری سنگین است. عملی نیست که هر زیر ملفه یک برنامه بزرگ را در فرآیند خود جدا کنید. خبر خوب این است که چندین فناوری اخیر وجود دارد که اجازه می دهد این نوع جعبه ماسه ریز ریز ، هر دو مبتنی بر WebAssemble باشد. برای برنامه های WebAssemble ، پردازش های نانو به اجزای جداگانه اجازه می دهد تا در جعبه شن و ماسه خود با لیست های کنترل دسترسی مختص اجزا اجرا شوند. اخیراً ، ما در حال تجربه یک فناوری به نام RLBox هستیم که توسط محققان UCSD ، UT Austin و Stanford ساخته شده است و به برنامه های معمولی مانند Firefox اجازه می دهد اجزای جعبه ماسه را اجرا کنند. ایده اصلی در پشت هر دوی این موارد یکسان است: استفاده از تکنیک های جمع آوری ایستا برای اطمینان از اینکه حافظه از حافظه بی خطر است (یعنی نمی تواند به خارج از خود برسد تا قسمت های دیگر برنامه را لمس کند) و سپس فقط توانایی های لازم را به آن می دهید. وظایف خود را انجام دهد.
روشهایی مانند این راه رسیدن به رویكرد فنی مقیاس پذیر برای محافظت از خود در برابر اجزای شخص ثالث است: هر جز component در جعبه ماسه مخصوص خود جدا شده و لیستی از قابلیتهای مورد نیاز خود را دارد (كه اغلب به عنوان با استفاده از کامپایلر اعلام می کند که هیچ قابلیت دیگری ندارد (این خیلی غیر از مجوزهایی نیست که برنامه های تلفن همراه درخواست می کنند). این مسئله مشکل از قرار دادن یک جز component جدید را بسیار ساده تر می کند زیرا شما فقط می توانید به توانایی های درخواست شده آن نگاه کنید ، بدون اینکه تأیید کنید که کد خود به درستی رفتار می کند.
گرچه قدرتمند است ، جعبه ماسه سازی خود – خواه از روال سنتی باشد یا از تنوع WebAssemble – به دو دلیل کافی نیست. اول ، API هایی که باید با آنها کار کنیم به اندازه کافی ریز ریز نیستند. مورد یک مولفه را در نظر بگیرید که برای باز کردن و پردازش پرونده ها روی دیسک طراحی شده است. این لزوماً باید بتواند پرونده ها را باز کند ، اما چه چیزی مانع از خواندن Bitcoins شما به جای پرونده هایی می شود که برنامه نویس می خواست آنها را بخواند؟ ممکن است یک لیست قابلیت ایجاد شود که فقط خواندن فایلهای خاص را شامل شود ، اما این API نیست که سیستم عامل به شما می دهد ، بنابراین اکنون باید چیزی را اختراع کنیم. موارد بسیاری از این دست وجود دارد ، بنابراین همه چیز پیچیده می شود.
دلیل دوم این است که برخی از اجزای سازنده حیاتی هستند زیرا عملکردهای حیاتی را انجام می دهند. به عنوان مثال ، هر چقدر OpenSSL را sandbox کنید ، باز هم باید نگران این باشید که داده های حساس شما را مدیریت می کند و بنابراین اگر به خطر بیفتد ، ممکن است نشت کند. خوشبختانه ، این کلاس از اجزای حیاتی کوچکتر است ، اما صفر است.
این بدان معنا نیست که جعبه ماسه مفید نیست ، فقط کافی نیست. آنچه ما نیاز داریم چندین لایه محافظتی است ، لایه اول مکانیسم های رویه ای برای دفاع در برابر کد است که در معرض خطر قرار می گیرد و لایه دوم جعبه شنی ریز دانه است تا بتواند تأثیر مصالحه را داشته باشد. همانطور که قبلاً اشاره شد ، سنگین ساختن فرایندهای بهتر بر دوش سازنده ملفه مشکل ساز به نظر می رسد ، خصوصاً وقتی تعداد زیادی پروژه وابسته وجود دارد ، بسیاری از آنها با بودجه بسیار خوبی تأمین می شوند.
چیزی که ما به دنبال بررسی داخلی آن بوده ایم موزیلا راهی است که آن پروژه ها می توانند وابستگی هایی را که استفاده می کنند و به آن وابسته هستند ، برچسب گذاری کنند. روش کار این است که سپس هر پروژه با مجموعه ای از پروژه های دیگر که از آن استفاده می کنند ، برچسب گذاری می شود (به عنوان مثال ، "Firefox از این جعبه استفاده می کند"). سپس وقتی می خواهید از یک جز component استفاده کنید می توانید ببینید که چه کسی از آن استفاده می کند ، که به شما اعتماد به نفس می دهد. البته ، شما نمی دانید که این سازمان ها چه نوع حسابرسی انجام می دهند ، اما اگر می دانید که پروژه X از امنیت بالایی برخوردار است و آنها از م Yلفه Y استفاده می کنند ، این امر می تواند تا حدی به شما اطمینان دهد. این در واقع فقط یک اتوماتیک کردن اتفاقی است که قبلاً به صورت غیررسمی اتفاق افتاده است: افراد اجزا را بر اساس این که دیگران از آنها استفاده می کنند قضاوت می کنند. برخی از الحاقات واضح در اینجا وجود دارد ، به عنوان مثال برچسب گذاری نسخه های خاص ، داشتن نشانه هایی از نوع حسابرسی پروژه بسته ، یا اجازه دادن به افراد برای پیکربندی سیستم های ساخت خود به طور خودکار به پروژه هایی که توسط مجموعه ای از پروژه های دیگر احراز شده اعتماد می کنند و از ارائه مصونیت ها خودداری می کنند پروژه ها ، حفظ پایگاه داده ای از نسخه های ناامن (این چیزی است که پیشنهاد Brewer و همکاران نیز پیشنهاد می کند). مزیت این نوع رویکرد این است که سنگینی را بر دوش افرادی می اندازد که از یک پروژه بهره مند می شوند ، نه اینکه برخی از پروژه های پرکاربرد به طور ناگهانی مشمول انبوهی از الزامات جدید شوند که ممکن است علاقه ای به تحقق آنها نداشته باشند. این کار هنوز در مراحل اکتشافی است ، بنابراین اگر علاقه مند هستید با من تماس بگیرید.
بدیهی است که این تنها در صورتی جواب می دهد که افراد در واقع نوعی نوع دقت لازم را قبل از اینکه به یک م componentلفه بستگی داشته باشند ، انجام دهند. در Mozilla ، ما این کار را تا حدی انجام می دهیم ، اگرچه بررسی هر خط کد در یک بسته غول پیکر مانند WebRTC در واقع عملی نیست. در اینجا نیز امیدواری وجود دارد: از آنجا که زبان های مدرن مانند Rust یا Go از حافظه بی خطر هستند ، بسیار راحت تر می توانید خود را متقاعد کنید که برخی رفتارها غیرممکن است – حتی اگر برنامه نقصی داشته باشد – که این کار حسابرسی را آسان تر می کند. در اینجا نیز می توان منشورهای روشنی داشت که توصیف می کند برنامه به چه قابلیت هایی نیاز دارد و صحت آنها را تأیید می کند (بعد از مدتی کار).
همانطور که در ابتدا گفتم ، Brewer و همکاران. قطعاً حق دارند که نگران این نوع حمله باشند. بسیار راحت است که بتوانید از کار دیگران استفاده کنید ، اما دشواری در تشخیص کیفیت آن یک مشکل بزرگ است. خوشبختانه ، ما شاهد یک سری پیشرفتهای فنی هستیم که راه حل را بدون نیاز به بازگشت به روزهای بد گذشته برای نوشتن همه چیز ، خود نشان می دهد.
