
منشور مدونة يستكشف macOS App Sandbox، والامتيازات عبر codesign، وتقنيات الهروب من App Sandbox باستخدام launchd وLaunchAgents وسمات الحجر الصحي.
استكمالًا لسلسلة مقالاتي حول انتقالي إلى macOS، أود أن أناقش قليلًا موضوع صندوق رمل التطبيقات (App Sandbox) في macOS.
يُنصح بشدة بقراءة مقال بنية تطبيقات macOS أولًا - سأفترض أن القارئ يعرف الفرق بين التطبيقات (Apps) والعمليات (tasks)، ويعرف القليل عن launchd وعلاقته بتشغيل التطبيقات.
في المرة الأولى التي تعلمت فيها عن صندوق رمل macOS، حاولت بسذاجة إنشاء ماكرو خبيث في Word.
ما تزال هذه (حتى الآن) نقطة دخول شائعة جدًا في النظام البيئي لـWindows، لذا أردت أن أرى ما إذا كان بإمكاني تشغيل العمليات وإحداث الفوضى عمومًا.
حسنًا، الأمور ليست بتلك السهولة على macOS - فقد تمكنت، على سبيل المثال، من تشغيل العمليات، لكن يبدو أنها لم تستطع فعل الكثير.
إسقاط الملفات كان دائمًا ما يعطيني خطأً غامضًا Operation not permitted - ما الذي يحدث؟
بدأت أقرأ قليلًا عن macOS وWord ووقعت على هذا المقال الممتاز بقلم Adam Chester (يعمل في MDSec). أنصح بشدة بقراءة المقال، لكن سألخص النتائج هنا:
اعتاد macOS على توفير أداة عملية تُسمى sandbox-exec كانت تنفّذ الأوامر داخل صندوق رمل. ورغم أنها مهملة (deprecated)، فإنها قد توضّح الكثير. ترى في صفحة الدليل الخاصة بها أنها تأخذ profile، لذا يمكننا الاستنتاج أن قواعد صندوق الرمل تُحفظ في ملفات تعريف (profiles). يمكن أن تأتي ملفات التعريف هذه بأشكال وصيغ متنوعة - ملفات، أو أسماء معرّفة مسبقًا، أو حتى كنصوص حرفية (literal strings).
تنص صفحات الدليل أيضًا على أنه ينبغي على المطورين استخدام ميزة App Sandbox. بعد قراءة المزيد عنها، أدركت أن قواعد صندوق الرمل مدمجة داخل الثنائي (binary)، وفي حالتنا هذه، فهي موجودة في /Application/Microsoft Word.app/Contents/MacOS/Microsoft Word (إذا بدا لك هذا غريبًا، فاطلع على مقال بنية تطبيقات macOS).
وبينما يمكنك استخراجها يدويًا بسهولة، فمن الأفضل استخدام أداة: codesign:
```jbo@McJbo ~ % codesign -dv --entitlements - /Applications/Microsoft\ Word.app/Contents/MacOS/Microsoft\ Word
Executable=/Applications/Microsoft Word.app/Contents/MacOS/Microsoft Word
Identifier=com.microsoft.Word
Format=app bundle with Mach-O universal (x86_64 arm64)
CodeDirectory v=20500 size=351454 flags=0x10000(runtime) hashes=10972+7 location=embedded
Signature size=8980
Timestamp=Apr 10, 2023 at 8:09:50 AM
Info.plist entries=52
TeamIdentifier=UBF8T346G9
Runtime Version=13.1.0
Sealed Resources version=2 rules=13 files=28766
Internal requirements count=1 size=180
[Dict]
[Key] com.apple.application-identifier
[Value]
[String] UBF8T346G9.com.microsoft.Word
[Key] com.apple.developer.aps-environment
[Value]
[String] production
[Key] com.apple.developer.team-identifier
[Value]
[String] UBF8T346G9
[Key] com.apple.security.app-sandbox
[Value]
[Bool] true
...
[Key] com.apple.security.temporary-exception.files.absolute-path.read-only
[Value]
[Array]
[String] /Library/Preferences/com.microsoft.office.licensingV2.plist
[String] /Library/Application Support/Microsoft/
...
[Key] com.apple.security.temporary-exception.sbpl
[Value]
[Array]
[String] (allow file-read* file-write* (require-all (vnode-type REGULAR-FILE) (regex #"(^|/)~\$[^/]+$")) )
[String] (deny file-write* (subpath (string-append (param "_HOME") "/Library/Application Scripts")) (subpath (string-append (param "_HOME") "/Library/LaunchAgents")) )
[Key] com.apple.security.temporary-exception.shared-preference.read-only
[Value]
[Array]
[String] com.ThomsonResearchSoft.EndNote
...
هذا قدر كبير لاستيعابه، لذا دعنا ندوّن بعض الملاحظات العامة:
-dv، والتي ترمز إلى display وverbose. بعد ذلك، يعرض --entitlements الاستحقاقات (entitlements) المرتبطة بالتطبيق أو الثنائي (نعم، يمكن لـcodesign العمل على كليهما). سنتعمق في الاستحقاقات في مقال آخر، لكن لنقل حاليًا إنها تعكس قدرات التطبيق، وأحدها ينص على أن التطبيق يعمل داخل صندوق رمل (com.apple.security.app-sandbox له قيمة منطقية True).plists (مرة أخرى، في مقال [بنية تطبيقات macOS]) قد يشتبهون في أن قاموس المفاتيح-القيم هو تمثيل لقائمة خصائص (property list) ما، وسيكونون على حق.com.apple.security.temporary-exception.files.absolute-path.read-only مصفوفة من المسارات المطلقة التي يُسمح للتطبيق بالقراءة منها.com.apple.security.temporary-exception.sbpl موجود هنا أيضًا - وذلك لإنشاء ملفات المؤقتة سيئة السمعة التي يعشقها Word.في مقال MDSec لعام 2018 الذي ذكرته سابقًا، لم يكن جزء deny file-write* تحت com.apple.security.temporary-exception.sbpl موجودًا، مما سمح للماكرو بإنشاء ملفات بمحتوى عشوائي مثل /Library/LaunchAgents/~$evil.plist. لماذا يؤدي ذلك إلى الهروب من صندوق الرمل؟
تُعد LaunchAgents وLaunchDaemons آلية استمرارية (persistence) معروفة (ومشروعة) في macOS. لقد ذكرتها من قبل، لكن يمكنك التفكير فيها كخدمات (Services) (إذا كنت قادمًا من عالم Windows) - تبدأ LaunchDaemons عند إقلاع نظام التشغيل (وبالتالي تعمل خارج جلسة المستخدم)، بينما تبدأ LaunchAgents عند تسجيل دخول المستخدم.
المثير للاهتمام أن كليهما موصوف في ملفات plist بسيطة. إليك مثالًا واحدًا لمحدّث OneDrive الخاص بي:
jbo@McJbo ~ % plutil -p /Library/LaunchAgents/com.microsoft.OneDriveStandaloneUpdater.plist
{
"Label" => "com.microsoft.OneDriveStandaloneUpdater"
"Program" => "/Applications/OneDrive.app/Contents/StandaloneUpdater.app/Contents/MacOS/OneDriveStandaloneUpdater"
"ProgramArguments" => [
]
"RunAtLoad" => 1
"StartInterval" => 86400
}
يتم تشغيل هذه الـLaunchAgents والـLaunchDaemons بواسطة launchd (تذكر تلك العملية؟)، وبالتالي يحدث الهروب من صندوق الرمل، إذ لم يكن لدى launchd أي علم بما إذا كانت الـplist قد أُسقطت من عملية داخل صندوق رمل أم لا (وحتى لو كان لديه علم - كيف كان سيعرف أي قواعد صندوق رمل يطبّقها؟).
استُخدم هذا المفهوم الخاص باستخدام launchd للهروب من صندوق رمل macOS على نطاق واسع، وفي الواقع، لقد استخدمته أنا في الماضي.
لأوفر عليك بضع نقرات - إليك الفكرة:
launchd بتشغيل تطبيقات macOS. قد يتم تشغيل تلك التطبيقات بالنقر المزدوج عليها، أو بوسائل أخرى - على سبيل المثال، النقر على ملف zip سيستخدم Archive Utility لأنه مرتبط بملفات zip.launchd هي استخدام أمر open.open غني بالإمكانات - يمكنك استخدام بعض ميزاته المثيرة للاهتمام مثل اختيار التطبيق، واختيار اسم الملف لفتحه، أو حتى تمرير وسائط سطر أوامر كاملة.Python المدمج (الذي لم يعد موجودًا على أجهزة macOS الجديدة غير المعدّلة (vanilla)) لتشغيل Python مع وسيط stdin يعيد توجيه المدخلات القياسية من ملف أسقطته (كان ذلك الملف هو ~$evil.py بسبب قيود Word).launchd نسخة غير محصورة (unsandboxed) من تطبيق Python بدأت القراءة من ~$evil.py الذي كان يحتوي أوامر Python اعتباطية، مما أدى فعليًا إلى الهروب من صندوق الرمل.كانت هناك أفكار مشابهة في إفصاحات أخرى (مثال جيد موجود هنا) لكن الفكرة تبقى نفسها. أنا متأكد تمامًا من وجود الكثير غيرها على مرأى من الجميع!
يذهب ذكر مشرف إلى مقال رائع بقلم Wojciech Regula - هذه المرة مع التركيز على تطبيق Terminal والتلاعب بمتغير بيئة (environment variable). يجدر بك قراءته!
المشكلة التي وجدها MDSec كانت خاصة بـOffice - وتم إصلاحها بقواعد أكثر صرامة.
أما تلك التي تسيء استخدام LaunchServices (وهو اسم الإطار (framework) الخاص بتشغيل التطبيقات عبر launchd) فهي أكثر عمومية - وبالتالي كان على Apple إصلاحها.
من الأشياء التي لاحظتها أن الملفات التي يُسقطها Word تُنشأ الآن بالسمة الممتدة com.apple.quarantine، نعم، نفس تلك التي ذكرتها في مقال مقدمة إلى Gatekeeper.
كما اتضح، فإن سمة الحجر الصحي تلك تمثل تحصينًا ضد هجمات معينة - على سبيل المثال، رفض تطبيق Terminal تشغيل سكربتات الصدفة (shell scripts) المنشأة بتلك السمة. هذا هو السبب، بالمناسبة، الذي جعلني أضطر إلى استخدام خيار --stdin مع Python.
كما أشار Gergely Kalman - أضافت Apple فحوصات إضافية إلى ثنائي open لتحصين هذا النوع من الاستغلالات. يبدو أن --stdin و--args وعلامات سطر أوامر أخرى يتم تجاهلها إذا كانت العملية المستدعية داخل صندوق رمل. ومع ذلك، فإن open يستدعي ببساطة LaunchServices (في launchd) عبر IPC، وبشكل ملائم، توجد واجهات برمجة تطبيقات (APIs) لذلك، مثل LSOpenURLsWithRole.
لم أتحقق مما إذا كان LaunchServices نفسه محصنًا أيضًا - إذا لم يكن كذلك، فأعتقد أنه يمكن تحقيق عمليات هروب مماثلة من صندوق الرمل بسهولة.
ناقشنا بإيجاز تقنية أخرى من تقنيات macOS - صندوق الرمل. لقد رأينا كم هو قوي وقابل للتهيئة، وكيف يمكن كسره.
كما ربطنا بعض الأمور ببعضها - كيف تعمل التطبيقات مع قواعد صندوق الرمل، وكيف أن تشغيل launchd للتطبيقات يكسر أكثر من مجرد أشجار العمليات (process trees)، وكيف يمكن استخدام ملفات plist للخير أو للشر - هذه المرة عبر الاستمرارية (LaunchAgents وLaunchDaemons).
لحسن الحظ، ربطنا أيضًا السمة الممتدة com.apple.quarantine من مقال مقدمة إلى Gatekeeper وشرحنا كيف يمكن استخدامها كتحصين إضافي ضد الهروب من صندوق الرمل. ليس سيئًا!
في المقالات القليلة القادمة، سنستكشف المزيد من آليات الأمان في macOS وربما نتحدث عن استراتيجيات كسرها.
ترقبوا المزيد!
Jonathan Bar Or (https://jonathanbaror.com)
~$whatever.docx