این پژوهش تکنیکهای پس از بهرهبرداری را نشان میدهد که میتواند به مهاجمی که روی یک نود Kubernetes به خطر افتاده دسترسی root دارد امکان دهد از یک استاندارد باز و پیادهسازی مرجع برای هویت ماشین موسوم به SPIFFE/SPIRE سوءاستفاده کند تا هویت بارهای کاری هممکان را جعل کند و SVIDهای SPIFFE را جمعآوری کند. نشان میدهیم که فرض اعتمادی که در هسته هر سامانه هویت ماشین قرار دارد — اینکه نود معتمد است — زمانی که مهاجم روی آن نود به دسترسی root برسد فرو میریزد. گروه Unit 42 بهرهبرداری از این تکنیک را در فضای واقعی مشاهده نکرده است.
چارچوب Secure Production Identity Framework for Everyone (SPIFFE)/محیط اجرایی SPIFFE (SPIRE) بهطور گسترده در Kubernetes و محیطهای cloud-native به کار گرفته میشود تا رازهای بلندمدت را با هویتهای بارکاری کوتاهعمر و بهصورت رمزنگاریشده قابلاعتبارسنجی جایگزین کند.
پژوهش ما نشان میدهد مهاجمی با دسترسی root میتواند اطلاعات گروهِ کنترل لینوکس (cgroup) را که ایجنت SPIRE در جریان گواهیدهی بارکاری از آن استفاده میکند جعل کند. این کار ایجنت را فریب میدهد تا SVID متعلق به یک بارکاری هممکان را برای فرایندی که تحت کنترل مهاجم است صادر کند.
بهعنوان بخشی از این پژوهش، ما Spooffe را توسعه دادیم؛ ابزار متنبازی که مدافعان میتوانند از آن استفاده کنند تا بیازمایند آیا مهاجمی با دسترسی مدیریتی میتواند فراداده cgroup را دستکاری کند و هویتهای بارکاری هممکان را بازیابی کند و دامنه اثر هویتیِ حاصل را ارزیابی کند.
هنگام طراحی مدلهای تهدید برای SPIFFE/SPIRE، سازمانها باید فرض کنند که دسترسی در سطح root به یک نود، دسترسی به همه هویتهای رمزنگاریشدهای را که در محدوده آن نود هستند فراهم میکند. برای کاهش میزان مواجهه، انجام فعالیتهای زیر توصیه میشود:
- سختسازی نودها
- محدود کردن دسترسی root
- ممنوع کردن کانتینرهای privileged و دسترسی به میزبان
- کاهش اتکا به selectorهای ضعیف
مشتریان Palo Alto Networks از طریق محصولات و خدمات زیر در برابر تهدیدهای توصیفشده در اینجا محافظت بهتری دارند:
- راهکارهای Cortex XDR و XSIAM
- سرویس Cortex Cloud Identity Threat Detection
اگر تصور میکنید ممکن است به مخاطره افتاده باشید یا موضوعی فوری دارید، با تیم پاسخگویی به رخداد Unit 42 تماس بگیرید.
مقدمه
استاندارد SPIFFE یک استاندارد متنباز برای هویت ماشین است که برای حل مسئله «Secret Zero» — چالش معرفی امن نخستین رازِ لازم برای بوتاسترپ اعتماد — با جایگزین کردن رازهای بلندمدت با هویتهای کوتاهعمرِ ورکلود طراحی شده است. وقتی بهدرستی مستقر شود، SPIFFE مرزهای هویتی محکمی میان ورکلودها اعمال میکند.
با اینحال، این تضمینها بر یک فرض بنیادی که در همه سامانههای هویتی مشترک است تکیه دارند: اینکه نود زیرین مورد اعتماد است. اگر مهاجم به دسترسی root روی یک نود دست یابد، میتواند با سازوکارهای هویت تعامل کند و همه هویتهایی را که برای آن نودِ به مخاطرهافتاده مجاز شدهاند بازیابی کند.
پژوهش ما بررسی میکند که مهاجمان چگونه میتوانند از دسترسی root سوءاستفاده کنند تا هویتهای ورکلود را از یک نودِ به مخاطرهافتاده جمعآوری کنند. در این نوشتار، با توضیح هویت ماشین و اینکه SPIFFE چگونه در محیطهای cloud-native اعتماد را برقرار و راستیآزمایی میکند، بستر بحث را فراهم میکنیم. سپس جعل هویت ورکلود از طریق selector spoofing را نشان میدهیم. در نهایت، Spooffe را معرفی میکنیم؛ ابزاری که برای خودکارسازی استخراج این هویتهای ورکلود (SVIDها) ساختهایم.
یادداشت برای خوانندگان: اگر از پیش با مفاهیم و معماری SPIFFE/SPIRE آشنا هستید، میتوانید مستقیماً به بخشهای تأیید اصالت ورکلود و نحوه تأیید اصالت ورکلود توسط Agent بروید.
مروری بر SPIFFE
فرض کنید دو برنامه، یکی فرانتاند و دیگری بکاند، باید بهصورت امن با یکدیگر ارتباط برقرار کنند.
میتوانیم جفتکلید تولید کنیم و کلیدهای عمومی را مبادله کنیم تا از طریق امنیت لایه انتقالِ دوسویه (mTLS) ارتباط برقرار کنیم، اما این گزینه چند پرسش کلیدی مطرح میکند:
- چه کسی آن کلیدها را چرخش میدهد؟
- اگر برنامه به مخاطره بیفتد، چه کسی آنها را ابطال میکند؟
- آیا میتوانیم راستیآزمایی کنیم چه کسی/چه چیزی در حال ارائه کلیدها است؟
استاندارد SPIFFE این مسائل را با استانداردسازی شیوه نامگذاری ماشینها و شیوه صدور اعتبارنامههای کوتاهعمر برطرف میکند.
واژه «ماشینها» به دو دسته کلی اشاره دارد:
- ورکلودها: کانتینرها، فرایندها و سرویسهایی که منطق کاربردی را اجرا میکنند
- دستگاهها: پایانههایی مانند رایانههای رومیزی، دستگاههای همراه و سامانههای اینترنت اشیاء (IoT) یا فناوری عملیاتی (OT)
- (توجه: هویت دستگاه بخشی از مشخصات اصلی SPIFFE نیست.)
مولفههای هویتی SPIFFE
به هر بارکاری سه مؤلفه هویتی اختصاص داده میشود:
- شناسه SPIFFE: اینکه چه کسی هستید (نام شما).
- هویت قابلاعتبارسنجی SPIFFE (SVID): اثبات اینکه همان هویتی هستید که ادعا میکنید (اعتبارنامههای شما).
- بسته اعتماد: اینکه دیگران چگونه راستیآزمایی میکنند که یک مرجع مورد اعتماد اعتبارنامه شما را صادر کرده است.
اکنون به جزئیات هر یک میپردازیم.
شناسه SPIFFE یک نام متعارف برای هویت بارکاری است که از قالبی بهسبک URI مانند spiffe://<trust-domain>/<path> پیروی میکند (شکل 1).
بخش میانی (example[.]com) در شکل 1 دامنه اعتماد است؛ صادرکننده هویت که بهعنوان مرز امنیتی عمل میکند.
به این ترتیب، بارکاریها میتوانند دارای هویت باشند و بدانند با چه کسانی باید ارتباط برقرار کنند.
با این حال، هویت بهتنهایی تضمینکننده اعتماد یا امنیت نیست؛ بنابراین سند هویت قابلاعتبارسنجی SPIFFE (SVID) را میافزاییم. این یک اعتبارنامه کوتاهعمر است که بارکاری برای اثبات هویت خود ارائه میکند. این سند بهصورت رمزنگاریشده توسط سرور مرجع صدور گواهی (CA) امضا میشود و همواره SPIFFE ID بارکاری را در بر دارد.
دو قالب اصلی برای SVID وجود دارد:
- قالب X.509 برای SVID: گواهی با کلید عمومی توکار که معمولاً برای mTLS بهکار میرود.
- قالب JSON Web Token (JWT) برای SVID: توکن JWT امضاشده که بهعنوان توکن حامل برای مجوزدهی در سطح برنامه استفاده میشود.
در نهایت، بسته اعتماد را داریم که مجموعهای از تکیهگاههای اعتماد است — گواهیهای Root CA یا JSON Web Key Sets (JWKS). از اینها برای راستیآزمایی این موضوع استفاده میشود که یک مرجع مورد اعتماد، یک SVID را درون یک دامنه اعتماد صادر کرده است.
برای درک اینکه این مؤلفههای هویتی در عمل چگونه صادر و راستیآزمایی میشوند، ابتدا باید به معماری SPIRE و مؤلفههای هستهای زمان اجرای آن نگاه کنیم.
معماری SPIRE
پروژه SPIRE یک پیادهسازی آماده استفاده در محیط تولید از مشخصات SPIFFE است. هرچند پیادهسازیهای متعددی وجود دارد، برای این پژوهش SPIRE را برگزیدیم زیرا در محیطهای Kubernetes بهطور گسترده استقرار یافته و استاندارد SPIFFE را بهطور کامل پیادهسازی میکند. افزون بر این، چون SPIRE متنباز است، میتوانیم درونیات آن را بررسی کنیم تا دریابیم مشخصات در عمل چگونه کار میکند.
پروژه SPIRE از چند جزء ساده تشکیل شده است (همانگونه که در شکل 2 زیر نشان داده شده است):
- بارکاری: یک جزء نرمافزاری منفرد که برای انجام کاری مشخص استقرار یافته است (مثلاً یک process، یک container یا یک pod).
- سرور SPIRE (control plane): این همان CA است که ورودیهای ثبت را نگهداری میکند. همچنین SVIDها را صادر و بهصورت رمزنگاریشده امضا میکند. علاوه بر این، باندل اعتماد مربوط به دامنه اعتماد را منتشر میکند.
- ایجنت SPIRE: این مولفه روی هر گره محاسباتی (مثلاً یک گره Kubernetes، یک VM یا یک میزبان bare-metal) اجرا میشود. فعالیتهای زیر را انجام میدهد:
- درخواستها را از بارکاریها بهصورت محلی از طریق Workload API (UNIX socket) میپذیرد.
- از طریق Node API با سرور ارتباط برقرار میکند.
- تصدیق را انجام میدهد.
- مدارک SVID را در کش ذخیره میکند.
- چرخش را مدیریت میکند.
با در نظر داشتن معماری SPIRE، اکنون میتوانیم گامبهگام بررسی کنیم که اعتبارسنجی هویت بارکاری-به-بارکاری از ابتدا تا انتها چگونه عمل میکند.
جریان اعتبارسنجی هویت بارکاری-به-بارکاری
هرگاه بارکاری A نیاز داشته باشد از طریق mTLS با بارکاری B ارتباط برقرار کند، یک اعتبارنامه کوتاهعمر از ایجنت محلی SPIRE درخواست میکند. ایجنت بارکاری را تصدیق کرده و دادههای تصدیق را به سرور SPIFFE ارسال میکند. بر اساس سیاستهای ثبت از پیش تعریفشده، سرور شناسه SPIFFE مناسب را برای بارکاری انتخاب و یک SVID مبتنی بر X.509 با عمر کوتاه صادر میکند.
سرور همچنین کلیدهای عمومی متناظر را بهعنوان بخشی از باندل اعتماد منتشر میکند.
زمانی که بارکاری A اتصال را آغاز میکند، SVID خود را در طول دستدهی mTLS ارائه میدهد. بارکاری B با اعتبارسنجی امضا در برابر باندل اعتماد، بررسی انقضای گواهی، و تأیید اینکه شناسه SPIFFE با هویت مورد انتظار مطابقت دارد، SVID را راستیآزمایی میکند.
اگر این بررسیها موفق باشند، بارکاری B میتواند بهصورت رمزنگاریشده بارکاری A را احراز هویت کند و یک اتصال امن برقرار کند. این رویکرد ارتباط بارکاری-به-بارکاری مبتنی بر هویت را بهجای تکیه بر اسرار بلندعمر ممکن میکند (شکل 3).
جریان هویتی که در بالا توصیف شد به تصدیق وابسته است؛ فرایندی که طی آن SPIRE تعیین میکند آیا یک بارکاری مجاز به دریافت یک هویت هست یا خیر. SPIRE تصدیق را در دو سطح انجام میدهد:
- تصدیق گره اعتماد را به ایجنتی برقرار میکند که روی یک گره اجرا میشود.
- تصدیق بارکاری هویت تکتک بارکاریها را تعیین میکند.
در این مطلب، بر تأیید بار کاری تمرکز میکنیم، زیرا این سازوکار مستقیماً در ارزیابی selector و حملاتی که در ادامه بحث میشوند دخیل است.
تأیید بار کاری
پیش از آنکه ایجنت بار کاریها را تأیید کند، مدیر سرور SPIRE باید selectorهای بار کاری را در سرور SPIRE ثبت کند تا بعداً بتواند آنها را با selectorهای موجود در ایجنت مقایسه کند.
در این مثال از Kubernetes، این ورودی ثبتنام هر پادی را که در namespace default اجرا میشود و از service account default استفاده میکند، مجاز میکند تا هویت SPIFFE مشخصشده (spiffeID) را دریافت کند.
رکورد حاصل بهصورت زیر روی سرور SPIRE ذخیره میشود:
ایجنت SPIRE بهصورت دورهای این ورودیهای ثبتنام را از سرور همگام و در کش ذخیره میکند و هنگام تأیید بار کاری بهصورت محلی از آنها استفاده میکند تا تعیین کند کدام هویت اعمال میشود. ایجنت برای هر ورودی ثبتنام جفتکلید تولید میکند، درخواستهای امضای گواهی (CSR) به سرور میفرستد و SVIDهای حاصل را در کش نگه میدارد.
هنگامی که یک بار کاری بخواهد احراز هویت کند، از طریق Workload API از ایجنت هویت درخواست میکند (شکل 4، گام 1). ایجنت با گردآوری selectorها از فرایند بار کاری و تطبیق آنها با ورودیهای ثبتنام کششده، تأیید بار کاری را انجام میدهد (شکل 4، گام 2).
پس از تطبیق موفق (شکل 4، گام 3)، عامل موارد زیر را بازمیگرداند:
- هویت X.509 SVID.
- کلید خصوصی.
- بسته اعتماد.
نکته: این مثال بر اساس یک درخواست X.509 SVID است. برای درخواستهای JWT SVID، عامل تنها یک توکن JWT امضاشده بازمیگرداند.
با در نظر داشتن جریان سطحبالا، اکنون میتوانیم بررسی کنیم که تصدیق در عمل چگونه کار میکند.
نحوه تصدیق بارکاری توسط عامل
زمانی که یک بارکاری یک SVID درخواست میکند (از طریق FetchJWTSVID یا FetchX509SVID)، به Workload API عامل، معمولاً از طریق یک سوکت دامنه Unix (مانند /run/spire/sockets/agent.sock)، متصل میشود. سپس عامل PID فرایند فراخوان را استخراج میکند.
پس از اینکه عامل PID را دریافت کرد، آن را به پلاگینهای workload attestor پیکربندیشده میسپارد که بر اساس فراداده فرایند و کانتینر، selectorها را جمعآوری میکنند. عاملهای SPIRE از چندین پلاگین workload-attestor پشتیبانی میکنند. پلاگینهای رایج شامل docker، k8s، systemd، Unix و Windows هستند. در خوشه ما، عامل از پلاگینهای k8s و Unix استفاده میکند.
پلاگین Kubernetes (k8s)
پلاگین k8s از PID بارکاری برای دسترسی به /proc/<pid>/mountinfo یا /proc/<pid>/cgroups استفاده میکند. این پلاگین تابع GetPodUIDAndContainerID را فراخوانی میکند تا UID پاد و شناسه کانتینر را استخراج کند. در محیط ما، این فرایند به صورت زیر است:
پس از استخراج شناسه کانتینر و UID پاد، پلاگین k8s برای بازیابی فراداده پاد، kubelet را کوئری میکند. برای این کار، از توکن service account عامل SPIRE که در /var/run/secrets/kubernetes.io/serviceaccount/token ذخیره شده است، استفاده میکند.
service account عامل دارای مجوزهای زیر است که به آن اجازه میدهد فهرست پادها را بگیرد و به اطلاعات نود دسترسی داشته باشد:
با استفاده از این توکن، افزونه تابع getPodList را برای بازیابی همه پادهای موجود روی نود فراخوانی میکند. سپس پادی را شناسایی میکند که UID و شناسه کانتینر آن با مقادیری که از مسیر /proc استخراج شدهاند تطابق دارند. پس از انطباق، از فراداده پاد، selectorها را جمعآوری میکند:
افزونه Unix
افزونه Unix اطلاعات را از /proc گردآوری میکند تا selectorهایی مانند شناسه کاربر (UID) و شناسه گروه (GID) تولید کند. این selectorها در جریان تأیید اصالت بارکاری بهکار میروند تا هویت یک بارکاری را به ویژگیهای سطح سیستمعاملِ فرآیند فراخوان پیوند دهند و بدینترتیب به SPIRE کمک میکند میان بارکاریهای مختلفی که روی همان نود اجرا میشوند تمایز قائل شود.
در ادامه نمونهای از selectorهایی که این افزونه آنها را جمعآوری میکند آمده است:
ایجنت این سلکتورها را از هر دو پلاگین k8s و Unix ترکیب میکند. سپس این مجموعهٔ سلکتور را با ورودیهای ثبت کششده بهصورت محلی تطبیق میدهد. اگر سلکتورهای یک ورودی زیرمجموعهای از سلکتورهای ورکلود باشند، ایجنت SVID کششدهٔ متناظر را به همان ورکلود برمیگرداند.
جعل هویت ورکلود: جعل سلکتور از طریق cgroup
این حمله به دسترسی در سطح روت روی نود نیاز دارد. تحلیل ما نشان داد که احراز اصالت ورکلود بهشدت به مسیر cgroup آن ورکلود متکی است. مهاجمی که روی نود دسترسی روت دارد میتواند این مسیر cgroup را دستکاری کند و احتمالاً ایجنت را فریب دهد تا ادعاهای احراز اصالت را متعلق به ورکلود دیگری بداند و هویت آن ورکلود را بهدست آورد. این امر میتواند به مهاجم امکان دهد هویت ورکلود قربانی را جعل کند و به هر خدمت یا منبعی که تحت آن هویت مورد اعتماد است دسترسی یابد.
بهعنوان گام نخست، یک ورودی ثبت برای پادی با نام workload-a در سرور ایجاد کردیم و تأیید کردیم که میتوانیم هویت آن را از همان پاد دریافت کنیم:
تأیید کردیم که با درخواست یک JWT SVID نمیتوانیم این هویت را از روی میزبان بازیابی کنیم:
برای جعل cgroup مربوط به workload-a، ابتدا PID آن را بهدست میآوریم:
مسیر cgroup آن را بر اساس PID فوق بررسی کردیم:
این مسیر را به یک مسیر cgroup شبیهسازیشده کپی کردیم و PID جاری پوسته خودمان ($$) را در فایل cgroup.procs مربوط به cgroup شبیهسازیشده نوشتیم:
شایان ذکر است که نوشتن PID بهطور مستقیم در مسیر cgroup اصلی نیز کار میکرد. تنها برای پرهیز از تغییر وضعیت زماناجرای بارکاری اصلی از یک cgroup جداگانه استفاده کردیم.
اجرای دوباره فرمان fetch هویت مرتبط با PID 9072 را با موفقیت بازیابی کرد:
همچنین میتوانیم شناسه SPIFFE مربوط به workload-a را درون توکن JWT ببینیم:
نمایش جعل دستی نشان میدهد که مدل امنیتی بهطور کامل بر یک فرض واحد و آسیبپذیر درباره یکپارچگی گره تکیه دارد. هنگامی که دسترسی سطح روت داریم، میتوانیم هویت هر بارکاری روی گره را بهدست آوریم.
این نمایش جعل دستی یک فرض اعتماد بحرانی در اعتبارسنجی بارکاری را برجسته میکند. هنگامی که مهاجم به یک گره با سطح دسترسی روت دسترسی دارد، میتواند اطلاعات cgroup را دستکاری کند تا ایجنت SPIRE هویتهای بارکاری را به نادرستی نسبت دهد. در این شرایط، مهاجم میتواند بارکاریهای دیگری را که روی همان گره اجرا میشوند جعل هویت کند و هویتهای آنها را بهدست آورد.
ابزار Spooffe
این یافتهها ما را برانگیخت تا ابزار Spooffe را توسعه دهیم؛ ابزاری که به مدافعان امکان میدهد جعل selector را خودکار کنند تا همه هویتهای بارکاری را از گره بازیابی کنند.
ابزار Spooffe گره را برای بارکاریهای در حال اجرا پویش میکند، مسیرهای cgroup آنها را مییابد و آنها را بهصورت یک cgroup ساختگی برای فرایند خودش بازتولید میکند. سپس برای هویتهای حاصل (SVIDs) از ایجنت محلی SPIRE پرسوجو میکند و به ما اجازه میدهد همه هویتهای بارکاری موجود روی میزبان را جمعآوری کنیم (شکل 5).
علاوه بر جعل selector، ابزار Spooffe قابلیتهای دیگری نیز دارد. با این حال، در این نوشتار تنها بر ویژگیهای مرتبط با این پژوهش تمرکز میکنیم.
یکی از این قابلیتها جعل هویت ایجنت است که بررسی میکند آیا مهاجم میتواند ایجنت SPIRE را جعل هویت کند و برای استخراج هویتهای بارکاری مستقیماً با سرور ارتباط برقرار کند یا خیر.
جمعبندی
در این مقاله نشان دادیم که مهاجمی با دسترسی سطح روت روی یک گره بهخطرافتاده چگونه میتواند از اعتبارسنجی بارکاری SPIFFE/SPIRE سوءاستفاده کند تا بارکاریهای هممکان را جعل هویت کند و هویتهای آنها را بازیابی کند. با دستکاری فراداده cgroup نشان دادیم چگونه مهاجمان میتوانند ایجنت SPIRE را گمراه کنند تا SVIDهای معتبر را برای یک فرایند تحت کنترل مهاجم صادر کند. همچنین Spooffe را معرفی کردیم؛ ابزاری که این تکنیک را برای فهرستکردن و استخراج هویتهای بارکاری از یک گره خودکار میکند.
این یافتهها یک فرض بنیادین در سامانههای هویت بارکاری را برجسته میکند: اعتماد به گرهِ زیربنایی. در حالی که SPIFFE/SPIRE تضمینهای قدرتمند هویت مبتنی بر رمزنگاری را میان بارهای کاری اعمال میکند، این تضمینها بر یکپارچگی محیطی که در آن فرایند attestation انجام میشود اتکا دارند. به محض آنکه این مرز اعتماد شکسته شود، جداسازی هویتی میان بارهای کاری فرو میریزد و به مهاجمان امکان میدهد بهجای اسرار سرقتشده، با استفاده از اعتبارنامههای مشروع حرکت جانبی انجام دهند.
سازمانهایی که هویت بارکاری را بهکار میگیرند باید نفوذ در سطح گره را معادل نفوذ به تمام هویتهایی بدانند که به آن گره محدود شدهاند. برای کاهش ریسک، کانتینرهای دارای امتیاز را محدود کنید، دسترسی مستقیم به میزبان را کاهش دهید و اتکا به selectorهای ضعیف یا بهسادگی قابل جعل را به حداقل برسانید.
شرکت Palo Alto Networks یافتههای ما را با اعضای همپیمان در Cyber Threat Alliance (CTA) به اشتراک گذاشته است. اعضای CTA از این اطلاعات برای استقرار سریع محافظتها برای مشتریان خود و برهمزدن نظاممند فعالیت بازیگران مخرب در فضای سایبری استفاده میکنند. درباره Cyber Threat Alliance بیشتر بدانید.















