آیا می توانم از رشته ها استفاده کنم؟
بله، رشته ها در Sandbox2 پشتیبانی می شوند.
همه رشته ها باید sandboxed شوند
به دلیل نحوه عملکرد لینوکس، خط مشی seccomp-bpf فقط برای رشته فعلی اعمال می شود: این بدان معناست که این خط مشی برای سایر رشته های موجود اعمال نمی شود، اما رشته های آینده این خط مشی را به ارث می برند:
- اگر از Sandbox2 در حالت اول استفاده می کنید که sandboxing قبل از
execve()
فعال است، همه رشته ها این خط مشی را به ارث می برند و مشکلی وجود ندارد. این حالت ترجیحی sandboxing است. - اگر از حالت دوم استفاده میکنید که در آن اجراکننده
set_enable_sandbox_before_exec(false)
را دارد و Sandboxee به مجری میگوید که چه زمانی میخواهد باSandboxMeHere()
sandbox شود، مطمئن شوید که فیلتر روی همه رشتهها اعمال میشود. در غیر این صورت، خطر فرار Sandbox وجود دارد: کدهای مخرب می توانند از یک رشته sandbox به یک رشته بدون Sandbox مهاجرت کنند.
چگونه باید Sandboxee خود را کامپایل کنم؟
اگر مراقب نباشید، به راحتی میتوانید وابستگیها و عوارض جانبی زیادی را به ارث ببرید (سیستالهای اضافی، دسترسی به فایل یا حتی اتصالات شبکه) که سندباکسینگ را سختتر (ردیابی همه عوارض جانبی) و کمتر ایمن میکنند (زیرا syscall و فایل). سیاست ها گسترده تر است). برخی از گزینه های کامپایل می توانند به کاهش چنین مشکلاتی کمک کنند:
- باینری Sandboxee را به صورت ایستا کامپایل کنید تا از پیوند پویا که از تعداد زیادی syscalls استفاده میکند (
open
/openat
،mmap
و غیره) جلوگیری کنید. از آنجایی که Bazel به طور پیشفرض
pie
اضافه میکند، اما static با آن ناسازگار است، از پرچم ویژگیها برای حذف آن از طریق گزینههای زیر در قوانین cc_binary استفاده کنید:linkstatic = 1, features = [ "fully_static_link", # link libc statically "-pie", ],
با این حال: استفاده از استاتیک دارای جنبه منفی کاهش آنتروپی پشته ASLR (از 30 بیت به 8 بیت) است که بهره برداری را آسان تر می کند. بسته به اجرای جعبه ایمنی و خط مشی خود، با دقت تصمیم بگیرید که چه چیزی ارجح است:
- ایستا نیست : ASLR پشتهای خوب، بهطور بالقوه اجرای کد اولیه سختتر است، اما به قیمت سیاستهای جعبه ماسهبازی کمتر مؤثر است، بهطور بالقوه خروج از آن آسانتر است.
- static : ASLR بد هیپ، به طور بالقوه اجرای کد اولیه آسان تر است، اما یک خط مشی جعبه ایمنی کارآمدتر است، به طور بالقوه خروج از آن سخت تر است.
انتخاب ناخوشایندی است زیرا کامپایلر از PIE ایستا (اجرای مستقل موقعیت) پشتیبانی نمی کند. PIE با قرار دادن باینری یک شی پویا پیادهسازی میشود و لودر پویا قبل از اجرای آن، آن را در یک مکان تصادفی نقشهبرداری میکند. سپس، چون پشته به طور سنتی در یک افست تصادفی بعد از آدرس پایه باینری قرار میگیرد (و با syscall brk گسترش مییابد)، این بدان معناست که برای باینریهای استاتیک، آنتروپی ASLR پشته فقط به این مقدار است زیرا PIE وجود ندارد.
برای نمونههایی از این گزینههای کامپایل، به مثال استاتیک BUILD.bazel نگاه کنید: static_bin.cc
به صورت ایستا کامپایل شده است، که به ما امکان میدهد یک خطمشی syscall بسیار فشرده داشته باشیم. این همچنین برای سندباکس کردن باینری های شخص ثالث به خوبی کار می کند.
آیا می توانم باینری های 32 بیتی x86 سندباکس؟
Sandbox2 فقط می تواند همان معماری را که با آن کامپایل شده است جعبه سندباکس کند.
علاوه بر این، پشتیبانی از x86 32 بیتی از Sandbox2 حذف شده است. اگر سعی کنید از یک مجری 64 بیتی x86 برای جعبه سندباکس یک باینری x86 32 بیتی، یا یک باینری 64 بیتی x86 که سیستمهای 32 بیتی ایجاد میکند (از طریق int 0x80)، هر دو یک نقض سندباکس ایجاد میکنند که میتواند توسط برچسب معماری [X86-32].
دلیل این رفتار این است که اعداد syscall بین معماری ها متفاوت است و از آنجایی که خط مشی syscall در معماری اجراکننده نوشته شده است، اجازه دادن به یک معماری متفاوت برای Sandboxee خطرناک است. در واقع، این می تواند منجر به اجازه دادن به یک syscall به ظاهر بی ضرر شود که در واقع به این معنی است که syscall مضرتر دیگری می تواند جعبه شنی را به سمت فرار باز کند.
آیا محدودیتی در تعداد جعبه های ماسه ای وجود دارد که یک فرآیند مجری می تواند درخواست کند؟
برای هر نمونه Sandboxee (فرآیند جدیدی که از forkserver ایجاد می شود)، یک رشته جدید ایجاد می شود - این جایی است که محدودیت وجود دارد.
آیا یک Executor می تواند درخواست ایجاد بیش از یک Sandbox را بدهد؟
خیر. یک رابطه 1:1 وجود دارد - یک نمونه Executor PID Sandboxee را ذخیره می کند، نمونه Comms را به نمونه Sandbox مدیریت می کند و غیره.
چرا در داخل forkserver.cc "عملکرد اجرا نشد" را دریافت می کنم؟
Sandbox2 فقط از اجرا بر روی هسته های نسبتاً جدید پشتیبانی می کند. برش فعلی ما هسته 3.19 است، اگرچه ممکن است در آینده تغییر کند. دلیل این امر این است که ما از ویژگی های هسته نسبتاً جدید از جمله فضاهای نام کاربری و seccomp با پرچم TSYNC استفاده می کنیم.
اگر روی prod اجرا میکنید، این موضوع نباید مشکلی داشته باشد، زیرا تقریباً کل ناوگان یک هسته جدید به اندازه کافی اجرا میکند. اگر در این مورد مشکلی دارید، لطفا با ما تماس بگیرید.
اگر روی دبیان یا اوبونتو اجرا میکنید، بهروزرسانی هستهتان به آسانی اجراست:
sudo apt-get install linux-image-<RECENT_VERSION>
،
آیا می توانم از رشته ها استفاده کنم؟
بله، رشته ها در Sandbox2 پشتیبانی می شوند.
همه رشته ها باید sandboxed شوند
به دلیل نحوه عملکرد لینوکس، خط مشی seccomp-bpf فقط برای رشته فعلی اعمال می شود: این بدان معناست که این خط مشی برای سایر رشته های موجود اعمال نمی شود، اما رشته های آینده این خط مشی را به ارث می برند:
- اگر از Sandbox2 در حالت اول استفاده می کنید که sandboxing قبل از
execve()
فعال است، همه رشته ها این خط مشی را به ارث می برند و مشکلی وجود ندارد. این حالت ترجیحی sandboxing است. - اگر از حالت دوم استفاده میکنید که در آن اجراکننده
set_enable_sandbox_before_exec(false)
را دارد و Sandboxee به مجری میگوید که چه زمانی میخواهد باSandboxMeHere()
sandbox شود، مطمئن شوید که فیلتر روی همه رشتهها اعمال میشود. در غیر این صورت، خطر فرار Sandbox وجود دارد: کدهای مخرب می توانند از یک رشته sandbox به یک رشته بدون Sandbox مهاجرت کنند.
چگونه باید Sandboxee خود را کامپایل کنم؟
اگر مراقب نباشید، به راحتی میتوانید وابستگیها و عوارض جانبی زیادی را به ارث ببرید (سیستالهای اضافی، دسترسی به فایل یا حتی اتصالات شبکه) که سندباکسینگ را سختتر (ردیابی همه عوارض جانبی) و کمتر ایمن میکنند (زیرا syscall و فایل). سیاست ها گسترده تر است). برخی از گزینه های کامپایل می توانند به کاهش چنین مشکلاتی کمک کنند:
- باینری Sandboxee را به صورت ایستا کامپایل کنید تا از پیوند پویا که از تعداد زیادی syscalls استفاده میکند (
open
/openat
،mmap
و غیره) جلوگیری کنید. از آنجایی که Bazel به طور پیشفرض
pie
اضافه میکند، اما static با آن ناسازگار است، از پرچم ویژگیها برای حذف آن از طریق گزینههای زیر در قوانین cc_binary استفاده کنید:linkstatic = 1, features = [ "fully_static_link", # link libc statically "-pie", ],
با این حال: استفاده از استاتیک دارای جنبه منفی کاهش آنتروپی پشته ASLR (از 30 بیت به 8 بیت) است که بهره برداری را آسان تر می کند. بسته به اجرای جعبه ایمنی و خط مشی خود، با دقت تصمیم بگیرید که چه چیزی ارجح است:
- ایستا نیست : ASLR پشتهای خوب، بهطور بالقوه اجرای کد اولیه سختتر است، اما به قیمت سیاستهای جعبه ماسهبازی کمتر مؤثر است، بهطور بالقوه خروج از آن آسانتر است.
- static : ASLR بد هیپ، به طور بالقوه اجرای کد اولیه آسان تر است، اما یک خط مشی جعبه ایمنی کارآمدتر است، به طور بالقوه خروج از آن سخت تر است.
انتخاب ناخوشایندی است زیرا کامپایلر از PIE ایستا (اجرای مستقل موقعیت) پشتیبانی نمی کند. PIE با قرار دادن باینری یک شی پویا پیادهسازی میشود و لودر پویا قبل از اجرای آن، آن را در یک مکان تصادفی نقشهبرداری میکند. سپس، چون پشته به طور سنتی در یک افست تصادفی بعد از آدرس پایه باینری قرار میگیرد (و با syscall brk گسترش مییابد)، این بدان معناست که برای باینریهای استاتیک، آنتروپی ASLR پشته فقط به این مقدار است زیرا PIE وجود ندارد.
برای نمونههایی از این گزینههای کامپایل، به مثال استاتیک BUILD.bazel نگاه کنید: static_bin.cc
به صورت ایستا کامپایل شده است، که به ما امکان میدهد یک خطمشی syscall بسیار فشرده داشته باشیم. این همچنین برای سندباکس کردن باینری های شخص ثالث به خوبی کار می کند.
آیا می توانم باینری های 32 بیتی x86 سندباکس؟
Sandbox2 فقط می تواند همان معماری را که با آن کامپایل شده است جعبه سندباکس کند.
علاوه بر این، پشتیبانی از x86 32 بیتی از Sandbox2 حذف شده است. اگر سعی کنید از یک مجری 64 بیتی x86 برای جعبه سندباکس یک باینری x86 32 بیتی، یا یک باینری 64 بیتی x86 که سیستمهای 32 بیتی ایجاد میکند (از طریق int 0x80)، هر دو یک نقض سندباکس ایجاد میکنند که میتواند توسط برچسب معماری [X86-32].
دلیل این رفتار این است که اعداد syscall بین معماری ها متفاوت است و از آنجایی که خط مشی syscall در معماری اجراکننده نوشته شده است، اجازه دادن به یک معماری متفاوت برای Sandboxee خطرناک است. در واقع، این می تواند منجر به اجازه دادن به یک syscall به ظاهر بی ضرر شود که در واقع به این معنی است که syscall مضرتر دیگری می تواند جعبه شنی را به سمت فرار باز کند.
آیا محدودیتی در تعداد جعبه های ماسه ای وجود دارد که یک فرآیند مجری می تواند درخواست کند؟
برای هر نمونه Sandboxee (فرآیند جدیدی که از forkserver ایجاد می شود)، یک رشته جدید ایجاد می شود - این جایی است که محدودیت وجود دارد.
آیا یک Executor می تواند درخواست ایجاد بیش از یک Sandbox را بدهد؟
خیر. یک رابطه 1:1 وجود دارد - یک نمونه Executor PID Sandboxee را ذخیره می کند، نمونه Comms را به نمونه Sandbox مدیریت می کند و غیره.
چرا در داخل forkserver.cc "عملکرد اجرا نشد" را دریافت می کنم؟
Sandbox2 فقط از اجرا بر روی هسته های نسبتاً جدید پشتیبانی می کند. برش فعلی ما هسته 3.19 است، اگرچه ممکن است در آینده تغییر کند. دلیل این امر این است که ما از ویژگی های هسته نسبتاً جدید از جمله فضاهای نام کاربری و seccomp با پرچم TSYNC استفاده می کنیم.
اگر روی prod اجرا میکنید، این موضوع نباید مشکلی داشته باشد، زیرا تقریباً کل ناوگان یک هسته جدید به اندازه کافی اجرا میکند. اگر در این مورد مشکلی دارید، لطفا با ما تماس بگیرید.
اگر روی دبیان یا اوبونتو اجرا میکنید، بهروزرسانی هستهتان به آسانی اجراست:
sudo apt-get install linux-image-<RECENT_VERSION>