[{"data":1,"prerenderedAt":3908},["ShallowReactive",2],{"blog-\u002Ffa-docker-security-under-the-hood":3},{"title":4,"description":5,"date":6,"tags":7,"body":12},"امنیت داکر: هر آنچه باید درباره مدل امنیتی زمان اجرا بدانید","بررسی عمیق مدل امنیتی داکر: قابلیت‌های لینوکس، فیلترهای سیستمی، پروفایل‌های دسترسی و فضاهای نام کاربری و این که چطور لایه‌های دفاعی چندگانه از کانتینرها در محیط تولید محافظت می‌کند.","2026-07-02",[8,9,10,11],"داکر","امنیت","لینوکس","کانتینرها",{"type":13,"value":14,"toc":3856},"minimark",[15,19,23,26,50,53,64,74,78,81,86,89,92,106,109,112,135,138,143,146,161,164,167,187,190,194,197,245,256,259,262,267,270,273,276,280,283,288,291,296,299,302,306,309,316,319,336,339,347,350,385,388,392,395,400,403,406,415,418,422,425,428,472,475,478,481,484,487,491,494,497,501,504,518,521,524,527,530,604,608,611,625,628,677,684,698,705,717,732,738,741,761,768,774,793,796,811,814,821,827,830,869,875,882,885,891,894,901,907,910,927,933,939,945,948,968,974,978,993,998,1044,1049,1177,1180,1183,1197,1200,1204,1257,1261,1377,1380,1384,1387,1390,1393,1398,1414,1418,1454,1458,1478,1481,1485,1488,1491,1511,1514,1521,1524,1527,1546,1552,1556,1577,1581,1628,1632,1722,1728,1732,1735,1738,1757,1760,1764,1767,1770,1787,1791,1794,1797,1800,1803,1810,1813,1820,1823,1827,1849,1853,1892,1896,1917,1923,1929,1938,1955,1961,1970,1978,1984,1986,2001,2004,2010,2017,2026,2032,2040,2043,2047,2059,2072,2078,2095,2104,2116,2120,2123,2126,2129,2142,2146,2149,2152,2155,2158,2162,2165,2191,2194,2198,2201,2204,2207,2211,2220,2223,2226,2230,2233,2236,2241,2244,2248,2251,2258,2261,2265,2268,2271,2278,2282,2285,2305,2315,2318,2322,2325,2328,2335,2338,2342,2345,2352,2365,2371,2388,2391,2399,2405,2446,2452,2455,2458,2462,2465,2468,2471,2474,2477,2481,2484,2488,2545,2549,2594,2597,2604,2607,2610,2645,2648,2652,2655,2658,2662,2715,2719,2761,2764,2768,2775,2778,2795,2798,2852,2861,2867,2889,2893,2896,2922,2928,2934,2940,2943,2947,2950,2960,2963,2966,2982,2988,2994,2998,3001,3004,3007,3010,3033,3036,3039,3044,3283,3289,3512,3518,3824,3827,3831,3837,3840,3843,3846,3852],[16,17,18],"h1",{"id":18},"مقدمه",[20,21,22],"p",{},"امنیت کانتینرها در سال‌های اخیر پیشرفت زیادی کرده، اما بسیاری از توصیه‌هایی که هنوز درباره امنیت داکر می‌بینیم، متعلق به سال‌ها قبل هستند.",[20,24,25],{},"اگر تا به حال دنبال بهترین روش‌های امنیتی داکر گشته باشید، احتمالاً با توصیه‌هایی مثل این مواجه شده‌اید:",[27,28,29,33,36,39,42],"ul",{},[30,31,32],"li",{},"کانتینر را با کاربر روت اجرا نکنید.",[30,34,35],{},"قابلیت‌های غیرضروری را حذف کنید.",[30,37,38],{},"از فایل‌سیستم فقط‌خواندنی استفاده کنید.",[30,40,41],{},"seccomp را فعال کنید.",[30,43,44,45,49],{},"هرگز از ",[46,47,48],"code",{},"--privileged"," استفاده نکنید.",[20,51,52],{},"همه این‌ها توصیه‌های درستی هستند، اما مشکل اینجاست که معمولاً به‌عنوان «قانون» مطرح می‌شوند، نه به‌عنوان مفهومی که باید درکشان کرد.",[20,54,55,56,63],{},"اگر دنبال یک مرجع خوب برای بهترین روش‌های امنیتی باشید، ",[57,58,62],"a",{"href":59,"rel":60},"https:\u002F\u002Fcheatsheetseries.owasp.org\u002Fcheatsheets\u002FDocker_Security_Cheat_Sheet.html",[61],"nofollow","OWASP Docker Cheat Sheet"," یکی از بهترین گزینه‌هاست. این مقاله روی همان پایه ساخته شده، با این تفاوت که مکانیزم‌های امنیتی لینوکس پشت هر توصیه را توضیح می‌دهد: این مکانیزم‌ها چه کاری انجام می‌دهند، اصلاً چرا وجود دارند، و چه معاوضه‌هایی دارند. در پایان، نه‌تنها می‌دانید از کدام گزینه‌های امنیتی استفاده کنید، بلکه می‌فهمید چرا مهم هستند و کجا باید به کارشان ببرید.",[65,66,67],"blockquote",{},[20,68,69,73],{},[70,71,72],"strong",{},"خلاصه:"," این مقاله مدل امنیتی زمان اجرای داکر را پوشش می‌دهد: قابلیت‌های لینوکس، seccomp، AppArmor، user namespaces، فایل‌سیستم‌های فقط‌خواندنی، محدودیت منابع و امنیت دیمن. هر بخش یک مکانیزم خاص را توضیح می‌دهد، می‌گوید چرا مهم است و چطور در داکر، کامپوز و کوبرنتیز پیکربندی می‌شود. تمرکز اصلی روی محدود کردن کارهایی است که مهاجم بعد از به‌دست‌آوردن اجرای کد در یک کانتینر تولید می‌تواند انجام دهد. امنیت زنجیره تأمین، اسرار و امنیت شبکه در این مقاله پوشش داده نمی‌شود.",[16,75,77],{"id":76},"مدل-تهدید","مدل تهدید",[20,79,80],{},"قبل از اینکه برویم سراغ ویژگی‌های امنیتی داکر، باید به یک سؤال ساده جواب بدهیم:",[65,82,83],{},[20,84,85],{},"اصلاً از کی داریم دفاع می‌کنیم؟",[20,87,88],{},"توصیه‌های امنیتی فقط در چارچوب یک مدل تهدید معنا پیدا می‌کنند. یک کانتینر که روی ماشین توسعه شما اجرا می‌شود، الزامات امنیتی کاملاً متفاوتی با یک API تولیدی دارد که در معرض عموم قرار دارد.",[20,90,91],{},"در ادامه این مقاله، سناریوی زیر را در نظر می‌گیریم:",[27,93,94,97,100,103],{},[30,95,96],{},"یک برنامه تولیدی داخل یک کانتینر داکر اجرا می‌شود.",[30,98,99],{},"این برنامه برای کاربران غیرقابل‌اعتماد از طریق شبکه قابل دسترسی است.",[30,101,102],{},"به خاطر یک آسیب‌پذیری در برنامه، مهاجم موفق می‌شود از راه دور (RCE) در داخل کانتینر کد اجرا کند.",[30,104,105],{},"مهاجم حالا می‌تواند هر دستوری را با همان سطح دسترسی فرآیند برنامه اجرا کند.",[20,107,108],{},"توجه کنید که در این مرحله، داکر شکست نخورده. جلوگیری از آسیب‌پذیری‌هایی مثل تزریق SQL، تزریق دستور یا سریال‌زدایی ناامن، وظیفه خود برنامه است، نه runtime کانتینر. نقش داکر از جایی شروع می‌شود که برنامه قبلاً به خطر افتاده.",[20,110,111],{},"اهداف مهاجم می‌تواند شامل این موارد باشد:",[27,113,114,117,120,123,126,129,132],{},[30,115,116],{},"خواندن داده‌های حساس مثل کلیدهای API، اعتبارنامه‌ها یا اسرار متصل شده.",[30,118,119],{},"تغییر برنامه یا پیکربندی آن.",[30,121,122],{},"ایجاد پایداری (persistence) طوری که دسترسی بعد از راه‌اندازی مجدد برنامه هم باقی بماند.",[30,124,125],{},"افزایش سطح دسترسی در داخل کانتینر.",[30,127,128],{},"فرار از کانتینر و به خطر انداختن میزبان.",[30,130,131],{},"دسترسی یا دخالت در سایر کانتینرها.",[30,133,134],{},"مصرف بیش از حد منابع سیستم برای ایجاد اختلال در سرویس.",[20,136,137],{},"هدف سخت‌سازی کانتینر این است که توانایی‌های مهاجم را بعد از یک نفوذ موفق محدود کند و انجام هر کدام از این اهداف را دشوارتر یا در حالت ایده‌آل، غیرممکن بسازد.",[139,140,142],"h2",{"id":141},"یک-مثال-واقعی","یک مثال واقعی",[20,144,145],{},"این یک سناریوی فرضی نیست. هر سال آسیب‌پذیری‌های حیاتی از نوع اجرای کد از راه دور در برنامه‌های کانتینری شده کشف می‌شود.",[20,147,148,149,154,155,160],{},"یک مثال اخیر، آسیب‌پذیری React Server Components (",[57,150,153],{"href":151,"rel":152},"https:\u002F\u002Fnvd.nist.gov\u002Fvuln\u002Fdetail\u002FCVE-2025-55182",[61],"CVE-2025-55182",") بود که روی برنامه‌های Next.js هم تأثیر گذاشت (اول با شناسه ",[57,156,159],{"href":157,"rel":158},"https:\u002F\u002Fnextjs.org\u002Fblog\u002FCVE-2025-66478",[61],"CVE-2025-66478"," برای Next.js ردیابی شد). تحت شرایط خاص، یک مهاجم تأیید نشده می‌توانست با فرستادن یک درخواست HTTP دستکاری شده به یک برنامه آسیب‌پذیر، کد دلخواه روی سرور اجرا کند.",[20,162,163],{},"فرض کنید برنامه شما داخل یک کانتینر داکر اجرا می‌شود و مهاجم با موفقیت از این آسیب‌پذیری استفاده کرده و در فرآیند برنامه به اجرای کد رسیده.",[20,165,166],{},"حالا از خودتان بپرسید:",[27,168,169,172,175,178,181,184],{},[30,170,171],{},"آیا می‌توانند برنامه را تغییر دهند؟",[30,173,174],{},"آیا می‌توانند اسرار متصل شده را بدزدند؟",[30,176,177],{},"آیا می‌توانند پایداری ایجاد کنند؟",[30,179,180],{},"آیا می‌توانند به کانتینرهای دیگر دسترسی پیدا کنند؟",[30,182,183],{},"آیا می‌توانند به میزبان فرار کنند؟",[30,185,186],{},"آیا می‌توانند منابع میزبان را تمام کنند؟",[20,188,189],{},"ویژگی‌های امنیتی داکر برای پاسخ به همین سؤال‌ها طراحی شده‌اند. سخت‌سازی کانتینر ربطی به جلوگیری از آسیب‌پذیری اولیه ندارد. آن وظیفه به عهده برنامه و وابستگی‌هایش است. هدف اصلی این است که محدود کنیم مهاجم بعد از به‌دست‌آوردن اجرای کد چه کارهایی می‌تواند بکند.",[16,191,193],{"id":192},"مرز-امنیتی-داکر","مرز امنیتی داکر",[20,195,196],{},"برای اینکه بفهمید داکر از چه چیزهایی می‌تواند محافظت کند و از چه چیزهایی نمی‌تواند، اول باید جایگاه داکر را در پشته سیستم مشخص کنید.",[198,199,203,204],"div",{"className":200},[201,202],"not-prose","my-6","\n  ",[198,205,213,214,213,224,213,229,213,233,213,237,213,241,203],{"className":206},[207,208,209,210,211,212],"mx-auto","max-w-sm","rounded-lg","border","bg-card","text-sm","\n    ",[198,215,223],{"className":216},[217,218,219,220,221,222],"border-b","px-4","py-2.5","text-center","font-medium","text-foreground","برنامه (Application)",[198,225,228],{"className":226},[217,218,219,220,227],"text-muted-foreground","کانتینر (Container)",[198,230,232],{"className":231},[217,218,219,220,227],"OCI runtime (runc)",[198,234,236],{"className":235},[217,218,219,220,227],"containerd",[198,238,240],{"className":239},[217,218,219,220,227],"موتور داکر (Docker Engine)",[198,242,244],{"className":243},[217,218,219,220,227],"هسته لینوکس (Linux Kernel)",[20,246,247,248,251,252,255],{},"دامنه مسئولیت داکر از لایه ",[46,249,250],{},"Docker Engine"," شروع می‌شود و تا لایه ",[46,253,254],{},"Container"," ادامه پیدا می‌کند. داکر چرخه عمر کانتینرها را مدیریت می‌کند، namespaceها را تنظیم می‌کند، مجموعه قابلیت‌ها را اعمال می‌کند، پروفایل‌های seccomp را پیکربندی می‌کند، LSMها را وصل می‌کند و cgroupها را مدیریت می‌کند.",[20,257,258],{},"چیزی که داکر انجام نمی‌دهد، ایجاد یک مرز امنیتی در برابر هسته لینوکس است. هسته بین همه کانتینرهای روی میزبان مشترک است. داکر فقط مکانیزم‌های امنیتی هسته را پیکربندی می‌کند؛ یک لایه امنیتی جدید روی آنها اضافه نمی‌کند.",[20,260,261],{},"این تمایز خیلی مهم است:",[65,263,264],{},[20,265,266],{},"داکر یک مرز امنیتی در برابر آسیب‌پذیری‌های هسته نیست.",[20,268,269],{},"اگر در یک زیرسیستم هسته، OverlayFS، eBPF، netfilter، io_uring یا هر زیرسیستم دیگری آسیب‌پذیری وجود داشته باشد، مهاجمی که می‌تواند با آن زیرسیستم تعامل کند، می‌تواند کاملاً از انزوای داکر عبور کند. این‌ها مشکل پیکربندی نیستند؛ باگ هسته‌اند و داکر نمی‌تواند وصله‌شان کند. بسیاری از فرارهای خطرناک از کانتینر در سال‌های اخیر از آسیب‌پذیری‌های هسته استفاده کرده‌اند، نه از نقص‌های پیکربندی داکر.",[20,271,272],{},"این حرف به این معنی نیست که داکر ناامن است. یعنی امنیت کانتینر در نهایت به امنیت لینوکس برمی‌گردد. برای درک نقاط قوت و محدودیت‌های داکر، باید مکانیزم‌های هسته‌ای را که داکر به آنها تکیه می‌کند بشناسید.",[20,274,275],{},"در ادامه مقاله، می‌بینیم که چطور ویژگی‌های مختلف داکر مثل اجرا با کاربر غیرروت، حذف قابلیت‌های لینوکس، استفاده از فایل‌سیستم فقط‌خواندنی، فعال‌سازی seccomp و اعمال سیاست‌های AppArmor یا SELinux با هم کار می‌کنند تا تأثیر یک نفوذ موفق را کاهش دهند. این مکانیزم‌ها به‌جای جلوگیری از همه حملات، طراحی شده‌اند تا وقتی مهاجم ناگزیر وارد می‌شود، دامنه خسارت را محدود کنند.",[16,277,279],{"id":278},"اجرای-کانتینرها-با-کاربر-غیرروت","اجرای کانتینرها با کاربر غیرروت",[20,281,282],{},"یکی از اولین توصیه‌هایی که تقریباً در هر راهنمای امنیتی داکر می‌بینید این است:",[65,284,285],{},[20,286,287],{},"کانتینرهایتان را با کاربر روت اجرا نکنید.",[20,289,290],{},"توصیه خوبی است، اما متأسفانه یکی از بدفهم‌ترین‌ها هم هست. یک سؤال رایج که توسعه‌دهنده‌ها می‌پرسند:",[65,292,293],{},[20,294,295],{},"اگر کانتینرها از قبل ایزوله هستند، چه فرقی می‌کند برنامه من با کاربر روت اجرا شود؟",[20,297,298],{},"جواب کوتاه: روت داخل کانتینر با روت روی میزبان یکی نیست، اما همچنان خیلی پرامتیازتر از یک کاربر معمولی داخل همان کانتینر است.",[20,300,301],{},"درک این تفاوت کلید فهم این است که چرا اجرا با کاربر غیرروت یکی از اصول اولیه سخت‌سازی کانتینر محسوب می‌شود.",[139,303,305],{"id":304},"روت-داخل-کانتینر-روت-میزبان-نیست","روت داخل کانتینر، روت میزبان نیست",[20,307,308],{},"در یک سیستم لینوکس سنتی، کاربر روت (UID 0) دسترسی نامحدودی به تقریباً همه بخش‌های سیستم عامل دارد. کانتینرها این مدل را عوض می‌کنند.",[20,310,311,312,315],{},"فرآیندهای داخل یک کانتینر همچنان یک شناسه کاربر دارند. اگر آن کاربر ",[46,313,314],{},"root"," (UID 0) باشد، در داخل namespace کاربری کانتینر به‌عنوان روت شناخته می‌شود. اما داکر چندین مکانیزم امنیتی مختلف را اعمال می‌کند - از جمله قابلیت‌های لینوکس، namespaceها، seccomp و ماژول‌های امنیتی لینوکس (AppArmor یا SELinux) - که جلوی بسیاری از امتیازاتی را که روت میزبان معمولاً دارد می‌گیرد.",[20,317,318],{},"مثلاً یک فرآیند روت داخل یک کانتینر پیش‌فرض داکر نمی‌تواند:",[27,320,321,324,327,330,333],{},[30,322,323],{},"ماژول‌های هسته را بارگذاری کند.",[30,325,326],{},"فایل‌سیستم‌های دلخواه را mount کند.",[30,328,329],{},"پارامترهای هسته را تغییر دهد.",[30,331,332],{},"ساعت سیستم را عوض کند.",[30,334,335],{},"فرآیندهای دلخواه میزبان را بازرسی یا کنترل کند.",[20,337,338],{},"این عملیات به امتیازاتی نیاز دارند که داکر عمداً حذف یا محدودشان کرده. پس روت کانتینر با روت میزبان برابر نیست، اما همچنان پرامتیازترین کاربر داخل کانتینر است.",[139,340,342,343,346],{"id":341},"چرا-کوبرنتیز-runasnonroot-را-توصیه-میکند","چرا کوبرنتیز ",[46,344,345],{},"runAsNonRoot"," را توصیه می‌کند",[20,348,349],{},"اگر برنامه‌هایتان را روی کوبرنتیز مستقر کرده باشید، احتمالاً با securityContext زیر برخورد کرده‌اید:",[351,352,357],"pre",{"className":353,"code":354,"language":355,"meta":356,"style":356},"language-yaml shiki shiki-themes catppuccin-mocha catppuccin-mocha catppuccin-mocha","securityContext:\n  runAsNonRoot: true\n","yaml","",[46,358,359,372],{"__ignoreMap":356},[360,361,364,368],"span",{"class":362,"line":363},"line",1,[360,365,367],{"class":366},"si09J","securityContext",[360,369,371],{"class":370},"sG44b",":\n",[360,373,375,378,381],{"class":362,"line":374},2,[360,376,377],{"class":366},"  runAsNonRoot",[360,379,380],{"class":370},":",[360,382,384],{"class":383},"srg_i"," true\n",[20,386,387],{},"این تنظیم به kubelet می‌گوید که بررسی کند کانتینر با UID 0 شروع نشود. اگر ایمیج طوری پیکربندی شده که با روت اجرا شود، کوبرنتیز از شروع کانتینر جلوگیری می‌کند. دلیل این تصمیم، بی‌اعتمادی کوبرنتیز به ایزولیشن داکر نیست. بیشتر برنامه‌ها برای سرویس‌دهی درخواست‌های HTTP، پردازش کارها یا ارتباط با پایگاه داده به امتیازات روت نیاز ندارند. اجرایشان به‌عنوان یک کاربر بی‌امتیاز، یک دسته کامل از تکنیک‌های پس از بهره‌برداری را با هزینه عملیاتی بسیار کم حذف می‌کند.",[139,389,391],{"id":390},"فرارهای-کانتینر-و-چرا-اهمیت-دارند","فرارهای کانتینر و چرا اهمیت دارند",[20,393,394],{},"شاید بپرسید:",[65,396,397],{},[20,398,399],{},"اگر روت داخل کانتینر روت واقعی نیست، پس چرا باید برایم مهم باشد؟",[20,401,402],{},"چون فرار از کانتینر وجود دارد.",[20,404,405],{},"هرچند نادر است، اما آسیب‌پذیری‌هایی در هسته لینوکس یا زمان اجرای کانتینر گاهی به مهاجم اجازه داده از کانتینر خارج شود و روی میزبان کد اجرا کند. اگر فرآیند آلوده از قبل امتیازات زیادی داشته باشد، بهره‌برداری از این آسیب‌پذیری‌ها خیلی راحت‌تر یا تأثیرگذارتر می‌شود. اجرای برنامه‌ها با کاربر غیرروت احتمال فرار از کانتینر را به صفر نمی‌رساند، اما امتیازات مهاجم را در صورت وقوع محدود می‌کند.",[20,407,408,409,414],{},"از نظر تاریخی، بسیاری از فرارهای خطرناک کانتینر اصلاً از پیکربندی داکر عبور نکرده‌اند؛ مستقیماً از آسیب‌پذیری‌های هسته استفاده کرده‌اند. مهاجمان از نقص‌های OverlayFS سوءاستفاده کرده‌اند، از eBPF برای افزایش امتیاز استفاده کرده‌اند، netfilter و nftables را برای رسیدن به کد هسته دستکاری کرده‌اند و از io_uring برای خواندن\u002Fنوشتن دلخواه بهره برده‌اند. در همه این موارد، مهاجم نیازی به شکستن داکر نداشت؛ باید لینوکس را می‌شکست. برای مثال، ",[57,410,413],{"href":411,"rel":412},"https:\u002F\u002Fnvd.nist.gov\u002Fvuln\u002Fdetail\u002FCVE-2023-0386",[61],"CVE-2023-0386"," یک فرار از کانتینر در فایل‌سیستم OverlayFS کرنل لینوکس بود که به مهاجم بی‌امتیاز اجازه می‌داد با mount کردن یک فایل‌سیستم دستکاری شده در داخل کانتینر، دسترسی روت روی میزبان به دست آورد.",[20,416,417],{},"به همین دلیل هر لایه سخت‌سازی هسته اهمیت دارد - هر کدام یک سطح حمله بالقوه را حذف می‌کند که یک اکسپلویت می‌تواند هدف قرار دهد.",[16,419,421],{"id":420},"user-namespaces","User Namespaces",[20,423,424],{},"تا اینجا پیکربندی پیش‌فرض داکر را فرض کردیم، جایی که UID 0 داخل کانتینر مستقیم به UID 0 روی میزبان نگاشت می‌شود. لینوکس user namespaces را هم فراهم می‌کند که به شناسه‌های کاربر کانتینر اجازه می‌دهد دوباره نگاشت شوند. این یکی از قوی‌ترین راهکارها برای کاهش تأثیر فرار از کانتینر است و بهتر است به‌عنوان یک مکانیزم امنیتی درجه یک جدی گرفته شود، نه یک افزونه اختیاری.",[20,426,427],{},"نحوه کار نگاشت مجدد به این شکل است:",[429,430,431,444],"table",{},[432,433,434],"thead",{},[435,436,437,441],"tr",{},[438,439,440],"th",{},"داخل کانتینر",[438,442,443],{},"روی میزبان",[445,446,447,456,464],"tbody",{},[435,448,449,453],{},[450,451,452],"td",{},"UID 0 (root)",[450,454,455],{},"UID 100000",[435,457,458,461],{},[450,459,460],{},"UID 1",[450,462,463],{},"UID 100001",[435,465,466,469],{},[450,467,468],{},"UID 1000",[450,470,471],{},"UID 101000",[20,473,474],{},"از دید کانتینر، برنامه همچنان با روت اجرا می‌شود. اما از دید میزبان، آن فرآیند فقط یک کاربر بی‌امتیاز معمولی است. این تفاوت ماهیت تأثیر فرار از کانتینر را عوض می‌کند.",[20,476,477],{},"حالا فرض کنید مهاجم یک آسیب‌پذیری هسته پیدا کرده که به آن اجازه می‌دهد خارج از namespaceهای کانتینر کد اجرا کند. بدون user namespaces، فرآیند فرار کرده UID 0 را روی میزبان حفظ می‌کند - یعنی مهاجم از همان اول دسترسی روت به سیستم دارد. با user namespaces فعال، فرآیند فرار کرده UID 100000 است، یک کاربر معمولی بی‌امتیاز. مهاجم از کانتینر فرار کرده اما هیچ امتیاز اضافه‌ای روی میزبان ندارد.",[20,479,480],{},"قابلیت‌ها، seccomp و LSMها همه محدود می‌کنند که یک فرآیند چه کاری می‌تواند انجام دهد. اما user namespaces هویت اصلی خود فرآیند را محدود می‌کند. مهاجمی که از namespace کانتینر فرار می‌کند، هنوز باید یک آسیب‌پذیری جداگانه برای افزایش امتیاز روی میزبان پیدا کند. این یعنی مهاجم دیگر فقط با «فرار از کانتینر» به هدفش نمی‌رسد؛ حالا باید «از کانتینر فرار کند و بعد میزبان را هم به خطر بیندازد».",[20,482,483],{},"با وجود این همه تأثیرگذاری، user namespaces در بسیاری از نصب‌های داکر به‌طور پیش‌فرض فعال نیست. دلیل اصلی سازگاری است: bind mountها، نگاشت مالکیت فایل و برخی storage backendها وقتی UIDها دوباره نگاشت می‌شوند رفتار متفاوتی دارند. بعضی ایمیج‌ها فرض می‌کنند می‌توانند فایل‌هایی را که به‌عنوان روت می‌نویسند روی میزبان هم مالک روت باشند، که با نگاشت مجدد user namespace خراب می‌شود. این مشکلات قابل حل هستند، اما نیاز به پیکربندی و آزمایش دارند که خیلی از استقرارها روی آن سرمایه‌گذاری نمی‌کنند.",[20,485,486],{},"برای محیط‌های تولیدی با الزامات امنیتی بالا، فعال‌سازی user namespaces باید اولویت داشته باشد. حفاظتی که در برابر تأثیر فرار کانتینر فراهم می‌کنند به‌سختی با هر مکانیزم دیگری به تنهایی قابل دستیابی است.",[16,488,490],{"id":489},"قابلیتهای-لینوکس","قابلیت‌های لینوکس",[20,492,493],{},"اگر اجرای کانتینرها با کاربر غیرروت اولین قدم برای کاهش امتیازات است، قابلیت‌های لینوکس دومین قدم هستند.",[20,495,496],{},"در واقع، حتی اگر برنامه شما به‌عنوان روت داخل یک کانتینر اجرا شود، باز هم امتیازات یک روت در سیستم لینوکس سنتی را ندارد. دلیلش این است که لینوکس مدرن دیگر روت را یک مفهوم همه‌یا-هیچ نمی‌بیند. در عوض، عملیات ممتاز را به مجموعه‌ای از قابلیت‌های مجزا تقسیم کرده.",[139,498,500],{"id":499},"چرا-لینوکس-روت-را-خرد-کرد","چرا لینوکس روت را خرد کرد",[20,502,503],{},"از نظر تاریخی، یونیکس فقط دو سطح امتیاز داشت:",[27,505,506,512],{},[30,507,508,511],{},[70,509,510],{},"روت (UID 0)",": دسترسی نامحدود به سیستم.",[30,513,514,517],{},[70,515,516],{},"بقیه",": دسترسی محدود.",[20,519,520],{},"این مدل ساده بود، اما خیلی درشت‌دانه. یک سرور وب مثل Nginx را در نظر بگیرید. باید به پورت 80 متصل شود، اما نیازی به بارگذاری ماژول‌های هسته، تغییر ساعت سیستم یا راه‌اندازی مجدد ماشین ندارد.",[20,522,523],{},"در مدل مجوز سنتی یونیکس، راهی برای دادن فقط امتیاز اتصال به پورت ممتاز وجود نداشت. مجبور بودید فرآیند را با روت اجرا کنید، که قدرت بسیار بیشتری از حد نیاز به آن می‌داد.",[20,525,526],{},"قابلیت‌های لینوکس این مشکل را با شکستن امتیازات روت به مجوزهای جداگانه حل می‌کنند. هر قابلیت نمایانگر یک عملیات ممتاز خاص است، و فرآیندها فقط مجوزهایی را که واقعاً نیاز دارند دریافت می‌کنند.",[20,528,529],{},"مثلاً:",[429,531,532,542],{},[432,533,534],{},[435,535,536,539],{},[438,537,538],{},"قابلیت",[438,540,541],{},"اجازه می‌دهد",[445,543,544,554,564,574,584,594],{},[435,545,546,551],{},[450,547,548],{},[46,549,550],{},"CAP_NET_BIND_SERVICE",[450,552,553],{},"اتصال به پورت‌های زیر 1024",[435,555,556,561],{},[450,557,558],{},[46,559,560],{},"CAP_NET_ADMIN",[450,562,563],{},"پیکربندی رابط‌های شبکه، جداول مسیریابی، قوانین فایروال و ...",[435,565,566,571],{},[450,567,568],{},[46,569,570],{},"CAP_SYS_PTRACE",[450,572,573],{},"ردیابی یا اشکال‌زدایی سایر فرآیندها",[435,575,576,581],{},[450,577,578],{},[46,579,580],{},"CAP_SYS_MODULE",[450,582,583],{},"بارگذاری و تخلیه ماژول‌های هسته",[435,585,586,591],{},[450,587,588],{},[46,589,590],{},"CAP_SYS_TIME",[450,592,593],{},"تغییر ساعت سیستم",[435,595,596,601],{},[450,597,598],{},[46,599,600],{},"CAP_SYS_ADMIN",[450,602,603],{},"انجام طیف گسترده‌ای از عملیات مدیریتی",[139,605,607],{"id":606},"مجموعه-قابلیت-پیشفرض-داکر","مجموعه قابلیت پیش‌فرض داکر",[20,609,610],{},"وقتی یک کانتینر را شروع می‌کنید، داکر همه قابلیت‌های لینوکس را در اختیار کانتینر قرار نمی‌دهد. در عوض، زیرمجموعه‌ای را در اختیارش قرار می‌دهد که بیشتر بارهای کاری رایج را پوشش می‌دهد، و قابلیت‌های خیلی خطرناک را حذف می‌کند.",[20,612,613,614,616,617,616,620,616,622,624],{},"درک این نکته مهم است: مجموعه قابلیت پیش‌فرض داکر یک سیاست امنیتی دقیق و بهینه نیست. یک مصالحه بین سازگاری و امنیت است. نگهدارندگان داکر لیست قابلیت‌های لینوکس را بررسی کرده و آنهایی را که قطعاً خطرناک بودند (",[46,615,580],{},", ",[46,618,619],{},"CAP_SYS_BOOT",[46,621,590],{},[46,623,600],{},") حذف کردند و بقیه را که به نظر می‌رسید برای بارهای کاری رایج نسبتاً ایمن باشند نگه داشتند. نتیجه عمداً مجازکننده است - داکر ترجیح می‌دهد چیزی را نشکند تا اینکه کاربران را مجبور به اشکال‌زدایی کند.",[20,626,627],{},"می‌توانید قابلیت‌های یک فرآیند داخل کانتینر را ببینید:",[351,629,633],{"className":630,"code":631,"language":632,"meta":356,"style":356},"language-bash shiki shiki-themes catppuccin-mocha catppuccin-mocha catppuccin-mocha","docker run --rm alpine sh -c \"\napk add --no-cache libcap >\u002Fdev\u002Fnull\ncapsh --print\n\"\n","bash",[46,634,635,660,665,671],{"__ignoreMap":356},[360,636,637,641,645,648,651,654,657],{"class":362,"line":363},[360,638,640],{"class":639},"seEE7","docker",[360,642,644],{"class":643},"swpoh"," run",[360,646,647],{"class":643}," --rm",[360,649,650],{"class":643}," alpine",[360,652,653],{"class":643}," sh",[360,655,656],{"class":643}," -c",[360,658,659],{"class":643}," \"\n",[360,661,662],{"class":362,"line":374},[360,663,664],{"class":643},"apk add --no-cache libcap >\u002Fdev\u002Fnull\n",[360,666,668],{"class":362,"line":667},3,[360,669,670],{"class":643},"capsh --print\n",[360,672,674],{"class":362,"line":673},4,[360,675,676],{"class":643},"\"\n",[20,678,679],{},[680,681],"img",{"alt":682,"src":683},"قابلیت‌های پیش‌فرض","\u002Fimages\u002Fblog\u002Fdocker-security-under-the-hood\u002FScreenshot1.png",[20,685,686,687,689,690,689,692,694,695,697],{},"می‌بینید که قابلیت‌هایی مثل ",[46,688,580],{},"، ",[46,691,619],{},[46,693,600],{}," و ",[46,696,590],{}," غایب هستند. به همین دلیل یک فرآیند روت در کانتینر پیش‌فرض داکر نمی‌تواند خیلی از کارهایی را که روت میزبان می‌کند انجام دهد.",[139,699,701,702],{"id":700},"حذف-قابلیتها-با-cap-drop","حذف قابلیت‌ها با ",[46,703,704],{},"--cap-drop",[20,706,707,708,689,710,689,712,694,714,716],{},"داکر از قبل خیلی از قابلیت‌های پرخطر را پیش‌فرض حذف کرده. دقت کنید که قابلیت‌هایی مثل ",[46,709,600],{},[46,711,580],{},[46,713,560],{},[46,715,570],{}," در مجموعه قابلیت کانتینر نیستند.",[20,718,719,720,723,724,727,728,731],{},"اما داکر هنوز یکسری قابلیت را می‌دهد که خیلی از برنامه‌ها واقعاً نیاز ندارند. مثلاً یک برنامه Next.js معمولی نیازی به ایجاد گره‌های دستگاه (",[46,721,722],{},"CAP_MKNOD",")، فرستادن بسته‌های خام شبکه (",[46,725,726],{},"CAP_NET_RAW",") یا تغییر مالکیت فایل (",[46,729,730],{},"CAP_CHOWN",") ندارد.",[20,733,734,735,737],{},"اینجاست که پرچم ",[46,736,704],{}," به کار می‌آید. به‌جای اینکه فقط به مجموعه پیش‌فرض داکر تکیه کنید، می‌توانید صریحاً قابلیت‌هایی را که نیاز ندارید حذف کنید.",[20,739,740],{},"برای شروع با مجموعه قابلیت خالی:",[351,742,744],{"className":630,"code":743,"language":632,"meta":356,"style":356},"docker run --cap-drop ALL nginx\n",[46,745,746],{"__ignoreMap":356},[360,747,748,750,752,755,758],{"class":362,"line":363},[360,749,640],{"class":639},[360,751,644],{"class":643},[360,753,754],{"class":643}," --cap-drop",[360,756,757],{"class":643}," ALL",[360,759,760],{"class":643}," nginx\n",[20,762,763,764,767],{},"اگر دوباره فرآیند را با ",[46,765,766],{},"capsh --print"," بررسی کنید، می‌بینید که مجموعه‌های قابلیت مؤثر و bounding خالی شده‌اند. فرآیند هنوز با UID 0 اجرا می‌شود، اما دیگر هیچ قابلیت لینوکسی فراتر از یک فرآیند معمولی بی‌امتیاز ندارد.",[20,769,770],{},[680,771],{"alt":772,"src":773},"قابلیت‌های حذف شده","\u002Fimages\u002Fblog\u002Fdocker-security-under-the-hood\u002FScreenshot2.png",[20,775,776,777,689,779,694,781,784,785,788,789,792],{},"تفاوت دو خروجی را ببینید. در مثال اول، فرآیند با UID 0 (root) اجرا می‌شود و مجموعه قابلیت پیش‌فرض داکر را دارد، از جمله ",[46,778,730],{},[46,780,550],{},[46,782,783],{},"CAP_SETFCAP",". بعد از ",[46,786,787],{},"--cap-drop ALL","، هر دو مجموعه Current و Bounding خالی می‌شوند، اما فرآیند هنوز با UID 0 (root) اجرا می‌شود. این به خوبی نشان می‌دهد که روت بودن به معنای ممتاز بودن نیست. یک فرآیند ممکن است شناسه کاربر ",[46,790,791],{},"0"," داشته باشد، اما بدون قابلیت‌های لازم، هسته اجازه خیلی از عملیات را به آن نمی‌دهد.",[20,794,795],{},"در عمل، بیشتر برنامه‌ها حداقل به یک یا دو قابلیت نیاز دارند. یک استراتژی رایج سخت‌افزاری:",[797,798,799,805,808],"ol",{},[30,800,801,802,804],{},"اول همه قابلیت‌ها را با ",[46,803,787],{}," حذف کنید.",[30,806,807],{},"برنامه را راه بیندازید.",[30,809,810],{},"فقط قابلیت‌های لازم برای عملکرد صحیح را اضافه کنید.",[20,812,813],{},"این رویکرد - یعنی دادن فقط مجوزهای مورد نیاز به فرآیند و نه بیشتر - همان اصل کمترین امتیاز (Principle of Least Privilege) در عمل است.",[139,815,817,818],{"id":816},"افزودن-قابلیتها-با-cap-add","افزودن قابلیت‌ها با ",[46,819,820],{},"--cap-add",[20,822,823,824,826],{},"فرض کنید Nginx را اجرا می‌کنید و می‌خواهید روی پورت 80 گوش دهد. اتصال به پورت‌های ممتاز نیاز به ",[46,825,550],{}," دارد.",[20,828,829],{},"به‌جای دادن امتیازات گسترده، فقط همان یک قابلیت را اضافه کنید:",[351,831,833],{"className":630,"code":832,"language":632,"meta":356,"style":356},"docker run \\\n  --cap-drop ALL \\\n  --cap-add NET_BIND_SERVICE \\\n  nginx\n",[46,834,835,845,854,864],{"__ignoreMap":356},[360,836,837,839,841],{"class":362,"line":363},[360,838,640],{"class":639},[360,840,644],{"class":643},[360,842,844],{"class":843},"seFKw"," \\\n",[360,846,847,850,852],{"class":362,"line":374},[360,848,849],{"class":643},"  --cap-drop",[360,851,757],{"class":643},[360,853,844],{"class":843},[360,855,856,859,862],{"class":362,"line":667},[360,857,858],{"class":643},"  --cap-add",[360,860,861],{"class":643}," NET_BIND_SERVICE",[360,863,844],{"class":843},[360,865,866],{"class":362,"line":673},[360,867,868],{"class":643},"  nginx\n",[20,870,871,872,874],{},"این کار خیلی امن‌تر از اجرای کانتینر با مجموعه پیش‌فرض داکر یا - بدتر از آن - استفاده از ",[46,873,48],{}," است.",[139,876,878,879,881],{"id":877},"چرا-cap_sys_admin-روت-جدید-نامیده-میشود","چرا ",[46,880,600],{}," «روت جدید» نامیده می‌شود",[20,883,884],{},"بین همه قابلیت‌های لینوکس، یکی نیاز به توجه ویژه دارد:",[20,886,887],{},[70,888,889],{},[46,890,600],{},[20,892,893],{},"اگر مستندات هسته یا security advisoryها را دنبال کرده باشید، حتماً این جمله را دیده‌اید:",[65,895,896],{},[20,897,898,900],{},[46,899,600],{}," روت جدید است.",[20,902,903,904,906],{},"این لقب کاملاً به‌جاست. برخلاف قابلیت‌هایی که یک امتیاز واحد و محدود می‌دهند، ",[46,905,600],{}," کلی عملیات مدیریتی نامرتبط را پوشش می‌دهد.",[20,908,909],{},"فرآیندهای دارای این قابلیت می‌توانند:",[27,911,912,915,918,921,924],{},[30,913,914],{},"فایل‌سیستم‌ها را mount و unmount کنند.",[30,916,917],{},"عملیات namespace را انجام دهند.",[30,919,920],{},"رابط‌های خاص هسته را پیکربندی کنند.",[30,922,923],{},"عملیات ممتاز فایل‌سیستم را اجرا کنند.",[30,925,926],{},"با eBPF و سایر ویژگی‌های پیشرفته هسته تعامل داشته باشند (بسته به نسخه هسته).",[20,928,929,930,932],{},"در طول سال‌ها، خیلی از آسیب‌پذیری‌های هسته و تکنیک‌های فرار کانتینر به ",[46,931,600],{}," متکی بوده‌اند. پس اعطای این قابلیت باید با احتیاط شدید انجام شود. اگر برنامه شما صریحاً به آن نیاز ندارد، آن را اضافه نکنید.",[139,934,936,938],{"id":935},"cap_net_admin-قدرتمندتر-از-چیزی-که-به-نظر-میرسد",[46,937,560],{},": قدرتمندتر از چیزی که به نظر می‌رسد",[20,940,941,942,944],{},"یک قابلیت دیگر که معمولاً اشتباه درک می‌شود ",[46,943,560],{}," است. با وجود نامش، فقط اجازه مدیریت شبکه نمی‌دهد.",[20,946,947],{},"این قابلیت انواع مختلفی از عملیات ممتاز شبکه را فعال می‌کند، از جمله:",[27,949,950,953,956,959,962,965],{},[30,951,952],{},"ایجاد یا تغییر رابط‌های شبکه.",[30,954,955],{},"پیکربندی جداول مسیریابی.",[30,957,958],{},"مدیریت قوانین فایروال.",[30,960,961],{},"فعال‌سازی ارسال بسته.",[30,963,964],{},"تغییر namespaceهای شبکه.",[30,966,967],{},"پیکربندی کنترل ترافیک (tc).",[20,969,970,971,973],{},"این امتیازات برای نرم‌افزارهای شبکه مثل سرورهای VPN، پلاگین‌های CNI یا کامپوننت‌های شبکه تعریف‌شده توسط نرم‌افزار کاملاً منطقی است. اما برای یک برنامه وب معمولی تقریباً هرگز نیاز نیست. اگر به برنامه‌ای که فقط HTTP سرویس می‌دهد ",[46,972,560],{}," بدهید، بی‌دلیل دامنه تأثیر یک نفوذ موفق را افزایش داده‌اید.",[139,975,977],{"id":976},"مثال-استفاده","مثال استفاده",[20,979,980,981,984,985,988,989,992],{},"فرض کنید یک برنامه Next.js را به محیط تولید می‌فرستید. بیشتر برنامه‌های Next.js پورت‌های ",[46,982,983],{},"80"," یا ",[46,986,987],{},"443"," را مستقیماً expose نمی‌کنند. در عوض، روی یک پورت بی‌امتیاز مثل ",[46,990,991],{},"3000"," گوش می‌دهند و یک پروکسی معکوس مثل Nginx، Traefik یا HAProxy ترافیک HTTP و HTTPS را مدیریت می‌کند. در این سناریو، برنامه به هیچ قابلیت لینوکسی نیاز ندارد.",[20,994,995],{},[70,996,997],{},"Docker Compose:",[351,999,1001],{"className":353,"code":1000,"language":355,"meta":356,"style":356},"services:\n  nextjs:\n    image: my-nextjs-app:latest\n    cap_drop:\n      - ALL\n",[46,1002,1003,1010,1017,1027,1034],{"__ignoreMap":356},[360,1004,1005,1008],{"class":362,"line":363},[360,1006,1007],{"class":366},"services",[360,1009,371],{"class":370},[360,1011,1012,1015],{"class":362,"line":374},[360,1013,1014],{"class":366},"  nextjs",[360,1016,371],{"class":370},[360,1018,1019,1022,1024],{"class":362,"line":667},[360,1020,1021],{"class":366},"    image",[360,1023,380],{"class":370},[360,1025,1026],{"class":643}," my-nextjs-app:latest\n",[360,1028,1029,1032],{"class":362,"line":673},[360,1030,1031],{"class":366},"    cap_drop",[360,1033,371],{"class":370},[360,1035,1037,1041],{"class":362,"line":1036},5,[360,1038,1040],{"class":1039},"sKAjW","      -",[360,1042,1043],{"class":643}," ALL\n",[20,1045,1046],{},[70,1047,1048],{},"Kubernetes:",[351,1050,1052],{"className":353,"code":1051,"language":355,"meta":356,"style":356},"apiVersion: apps\u002Fv1\nkind: Deployment\nmetadata:\n  name: nextjs\nspec:\n  template:\n    spec:\n      containers:\n        - name: nextjs\n          image: my-nextjs-app:latest\n          securityContext:\n            capabilities:\n              drop:\n                - ALL\n",[46,1053,1054,1064,1074,1081,1091,1098,1106,1114,1122,1135,1145,1153,1161,1169],{"__ignoreMap":356},[360,1055,1056,1059,1061],{"class":362,"line":363},[360,1057,1058],{"class":366},"apiVersion",[360,1060,380],{"class":370},[360,1062,1063],{"class":643}," apps\u002Fv1\n",[360,1065,1066,1069,1071],{"class":362,"line":374},[360,1067,1068],{"class":366},"kind",[360,1070,380],{"class":370},[360,1072,1073],{"class":643}," Deployment\n",[360,1075,1076,1079],{"class":362,"line":667},[360,1077,1078],{"class":366},"metadata",[360,1080,371],{"class":370},[360,1082,1083,1086,1088],{"class":362,"line":673},[360,1084,1085],{"class":366},"  name",[360,1087,380],{"class":370},[360,1089,1090],{"class":643}," nextjs\n",[360,1092,1093,1096],{"class":362,"line":1036},[360,1094,1095],{"class":366},"spec",[360,1097,371],{"class":370},[360,1099,1101,1104],{"class":362,"line":1100},6,[360,1102,1103],{"class":366},"  template",[360,1105,371],{"class":370},[360,1107,1109,1112],{"class":362,"line":1108},7,[360,1110,1111],{"class":366},"    spec",[360,1113,371],{"class":370},[360,1115,1117,1120],{"class":362,"line":1116},8,[360,1118,1119],{"class":366},"      containers",[360,1121,371],{"class":370},[360,1123,1125,1128,1131,1133],{"class":362,"line":1124},9,[360,1126,1127],{"class":1039},"        -",[360,1129,1130],{"class":366}," name",[360,1132,380],{"class":370},[360,1134,1090],{"class":643},[360,1136,1138,1141,1143],{"class":362,"line":1137},10,[360,1139,1140],{"class":366},"          image",[360,1142,380],{"class":370},[360,1144,1026],{"class":643},[360,1146,1148,1151],{"class":362,"line":1147},11,[360,1149,1150],{"class":366},"          securityContext",[360,1152,371],{"class":370},[360,1154,1156,1159],{"class":362,"line":1155},12,[360,1157,1158],{"class":366},"            capabilities",[360,1160,371],{"class":370},[360,1162,1164,1167],{"class":362,"line":1163},13,[360,1165,1166],{"class":366},"              drop",[360,1168,371],{"class":370},[360,1170,1172,1175],{"class":362,"line":1171},14,[360,1173,1174],{"class":1039},"                -",[360,1176,1043],{"class":643},[20,1178,1179],{},"حالا تصور کنید مهاجم از آسیب‌پذیری Next.js که قبلاً گفتیم استفاده کرده و داخل کانتینر به اجرای کد رسیده.",[20,1181,1182],{},"خود اکسپلویت موفق می‌شود، اما فرآیند آلوده نمی‌تواند عملیات ممتاز هسته مثل ایجاد سوکت خام، پیکربندی رابط‌های شبکه، بارگذاری ماژول‌های هسته، mount فایل‌سیستم یا تغییر ساعت سیستم را انجام دهد - چون آن قابلیت‌ها هرگز در اختیارش قرار نگرفته بودند.",[20,1184,1185,1186,984,1188,1190,1191,1194,1195,826],{},"اما اگر برنامه روی پورت 80 گوش دهد چه؟ بعضی برنامه‌ها، مثل یک کانتینر Nginx که مستقیم روی میزبان اجرا می‌شود، روی پورت‌های ممتاز مثل ",[46,1187,983],{},[46,1189,987],{}," گوش می‌دهند. اتصال به پورت‌های زیر ",[46,1192,1193],{},"1024"," نیاز به ",[46,1196,550],{},[20,1198,1199],{},"در این موارد، فقط همان قابلیت خاص را بدهید، نه کل مجموعه پیش‌فرض داکر.",[20,1201,1202],{},[70,1203,997],{},[351,1205,1207],{"className":353,"code":1206,"language":355,"meta":356,"style":356},"services:\n  nginx:\n    image: nginx:latest\n    cap_drop:\n      - ALL\n    cap_add:\n      - NET_BIND_SERVICE\n",[46,1208,1209,1215,1222,1231,1237,1243,1250],{"__ignoreMap":356},[360,1210,1211,1213],{"class":362,"line":363},[360,1212,1007],{"class":366},[360,1214,371],{"class":370},[360,1216,1217,1220],{"class":362,"line":374},[360,1218,1219],{"class":366},"  nginx",[360,1221,371],{"class":370},[360,1223,1224,1226,1228],{"class":362,"line":667},[360,1225,1021],{"class":366},[360,1227,380],{"class":370},[360,1229,1230],{"class":643}," nginx:latest\n",[360,1232,1233,1235],{"class":362,"line":673},[360,1234,1031],{"class":366},[360,1236,371],{"class":370},[360,1238,1239,1241],{"class":362,"line":1036},[360,1240,1040],{"class":1039},[360,1242,1043],{"class":643},[360,1244,1245,1248],{"class":362,"line":1100},[360,1246,1247],{"class":366},"    cap_add",[360,1249,371],{"class":370},[360,1251,1252,1254],{"class":362,"line":1108},[360,1253,1040],{"class":1039},[360,1255,1256],{"class":643}," NET_BIND_SERVICE\n",[20,1258,1259],{},[70,1260,1048],{},[351,1262,1264],{"className":353,"code":1263,"language":355,"meta":356,"style":356},"apiVersion: apps\u002Fv1\nkind: Deployment\nmetadata:\n  name: nginx\nspec:\n  template:\n    spec:\n      containers:\n        - name: nginx\n          image: nginx:latest\n          securityContext:\n            capabilities:\n              drop:\n                - ALL\n              add:\n                - NET_BIND_SERVICE\n",[46,1265,1266,1274,1282,1288,1296,1302,1308,1314,1320,1330,1338,1344,1350,1356,1362,1370],{"__ignoreMap":356},[360,1267,1268,1270,1272],{"class":362,"line":363},[360,1269,1058],{"class":366},[360,1271,380],{"class":370},[360,1273,1063],{"class":643},[360,1275,1276,1278,1280],{"class":362,"line":374},[360,1277,1068],{"class":366},[360,1279,380],{"class":370},[360,1281,1073],{"class":643},[360,1283,1284,1286],{"class":362,"line":667},[360,1285,1078],{"class":366},[360,1287,371],{"class":370},[360,1289,1290,1292,1294],{"class":362,"line":673},[360,1291,1085],{"class":366},[360,1293,380],{"class":370},[360,1295,760],{"class":643},[360,1297,1298,1300],{"class":362,"line":1036},[360,1299,1095],{"class":366},[360,1301,371],{"class":370},[360,1303,1304,1306],{"class":362,"line":1100},[360,1305,1103],{"class":366},[360,1307,371],{"class":370},[360,1309,1310,1312],{"class":362,"line":1108},[360,1311,1111],{"class":366},[360,1313,371],{"class":370},[360,1315,1316,1318],{"class":362,"line":1116},[360,1317,1119],{"class":366},[360,1319,371],{"class":370},[360,1321,1322,1324,1326,1328],{"class":362,"line":1124},[360,1323,1127],{"class":1039},[360,1325,1130],{"class":366},[360,1327,380],{"class":370},[360,1329,760],{"class":643},[360,1331,1332,1334,1336],{"class":362,"line":1137},[360,1333,1140],{"class":366},[360,1335,380],{"class":370},[360,1337,1230],{"class":643},[360,1339,1340,1342],{"class":362,"line":1147},[360,1341,1150],{"class":366},[360,1343,371],{"class":370},[360,1345,1346,1348],{"class":362,"line":1155},[360,1347,1158],{"class":366},[360,1349,371],{"class":370},[360,1351,1352,1354],{"class":362,"line":1163},[360,1353,1166],{"class":366},[360,1355,371],{"class":370},[360,1357,1358,1360],{"class":362,"line":1171},[360,1359,1174],{"class":1039},[360,1361,1043],{"class":643},[360,1363,1365,1368],{"class":362,"line":1364},15,[360,1366,1367],{"class":366},"              add",[360,1369,371],{"class":370},[360,1371,1373,1375],{"class":362,"line":1372},16,[360,1374,1174],{"class":1039},[360,1376,1256],{"class":643},[20,1378,1379],{},"چه Next.js، چه Nginx یا هر بار کاری دیگر، هدف یکی است: فقط قابلیت‌هایی را بدهید که برنامه واقعاً نیاز دارد. اگر به عملیات ممتاز هسته نیاز ندارد، ندهید. اگر دقیقاً یک قابلیت می‌خواهد، همان یک قابلیت را بدهید، و نه بیشتر.",[16,1381,1383],{"id":1382},"فایلسیستمهای-فقطخواندنی","فایل‌سیستم‌های فقط‌خواندنی",[20,1385,1386],{},"به‌طور پیش‌فرض، فایل‌سیستم ریشه کانتینر قابل نوشتن است. یعنی هر فرآیندی که داخل کانتینر اجرا می‌شود - از جمله فرآیندی که مهاجم کنترلش می‌کند - می‌تواند هر جا که مجوزهای فایل‌سیستم اجازه می‌دهد فایل ایجاد، تغییر یا حذف کند.",[20,1388,1389],{},"برای خیلی از برنامه‌ها، این سطح دسترسی نوشتن اصلاً لازم نیست. یک سرور وب معمولاً کد برنامه را می‌خواند، به درخواست‌ها جواب می‌دهد و داده‌های موقتی مثل لاگ یا کش می‌نویسد. به ندرت پیش می‌آید که نیاز به تغییر باینری‌های خودش یا کد منبع برنامه داشته باشد.",[20,1391,1392],{},"داکر به شما اجازه می‌دهد این فرض را با mount کردن فایل‌سیستم ریشه کانتینر به صورت فقط‌خواندنی اعمال کنید.",[20,1394,1395],{},[70,1396,1397],{},"Docker:",[351,1399,1401],{"className":630,"code":1400,"language":632,"meta":356,"style":356},"docker run --read-only nginx\n",[46,1402,1403],{"__ignoreMap":356},[360,1404,1405,1407,1409,1412],{"class":362,"line":363},[360,1406,640],{"class":639},[360,1408,644],{"class":643},[360,1410,1411],{"class":643}," --read-only",[360,1413,760],{"class":643},[20,1415,1416],{},[70,1417,997],{},[351,1419,1421],{"className":353,"code":1420,"language":355,"meta":356,"style":356},"services:\n  app:\n    image: my-app:latest\n    read_only: true\n",[46,1422,1423,1429,1436,1445],{"__ignoreMap":356},[360,1424,1425,1427],{"class":362,"line":363},[360,1426,1007],{"class":366},[360,1428,371],{"class":370},[360,1430,1431,1434],{"class":362,"line":374},[360,1432,1433],{"class":366},"  app",[360,1435,371],{"class":370},[360,1437,1438,1440,1442],{"class":362,"line":667},[360,1439,1021],{"class":366},[360,1441,380],{"class":370},[360,1443,1444],{"class":643}," my-app:latest\n",[360,1446,1447,1450,1452],{"class":362,"line":673},[360,1448,1449],{"class":366},"    read_only",[360,1451,380],{"class":370},[360,1453,384],{"class":383},[20,1455,1456],{},[70,1457,1048],{},[351,1459,1461],{"className":353,"code":1460,"language":355,"meta":356,"style":356},"securityContext:\n  readOnlyRootFilesystem: true\n",[46,1462,1463,1469],{"__ignoreMap":356},[360,1464,1465,1467],{"class":362,"line":363},[360,1466,367],{"class":366},[360,1468,371],{"class":370},[360,1470,1471,1474,1476],{"class":362,"line":374},[360,1472,1473],{"class":366},"  readOnlyRootFilesystem",[360,1475,380],{"class":370},[360,1477,384],{"class":383},[20,1479,1480],{},"با فایل‌سیستم ریشه فقط‌خواندنی، هر تلاشی برای تغییر لایه‌های ایمیج کانتینر شکست می‌خورد - حتی اگر فرآیند مجوز فایل کافی داشته باشد. این کانتینر را به یک محیط اجرای غیرقابل تغییر تبدیل می‌کند که فایل‌های برنامه بعد از راه‌اندازی قابل تغییر نیستند.",[139,1482,1484],{"id":1483},"چرا-فایلسیستم-فقطخواندنی","چرا فایل‌سیستم فقط‌خواندنی؟",[20,1486,1487],{},"وقتی مهاجم داخل کانتینر به اجرای کد رسید، یکی از اولین کارهایی که می‌کند تلاش برای ایجاد پایداری (persistence) است.",[20,1489,1490],{},"مثلاً ممکن است تلاش کند:",[27,1492,1493,1496,1499,1502,1505,1508],{},[30,1494,1495],{},"برنامه را با یک نسخه تغییر یافته عوض کند.",[30,1497,1498],{},"یک وب شل نصب کند.",[30,1500,1501],{},"بدافزار اضافی دانلود کند.",[30,1503,1504],{},"اسکریپت‌های راه‌اندازی را تغییر دهد.",[30,1506,1507],{},"ابزارهای سیستم را با نسخه‌های تروجانی جایگزین کند.",[30,1509,1510],{},"درهای پشتی برای دسترسی آینده بگذارد.",[20,1512,1513],{},"با فایل‌سیستم قابل نوشتن، همه این کارها ممکن است - اگر مجوزهای فایل‌سیستم اجازه دهد. با فایل‌سیستم ریشه فقط‌خواندنی، این عملیات بلافاصله失敗 می‌خورد. مهاجم همچنان می‌تواند دستورات را در فرآیند آلوده اجرا کند، اما نمی‌تواند ایمیج کانتینر را دائماً تغییر دهد یا بدافزار پایدار در آن نصب کند.",[139,1515,1517,1518],{"id":1516},"ذخیرهسازی-موقت-با-tmpfs","ذخیره‌سازی موقت با ",[46,1519,1520],{},"tmpfs",[20,1522,1523],{},"البته تعداد کمی از برنامه‌ها کاملاً فقط‌خواندنی هستند. بیشتر آنها به جایی برای نوشتن فایل‌های موقت نیاز دارند.",[20,1525,1526],{},"مثال‌ها:",[27,1528,1529,1534,1537,1540,1543],{},[30,1530,1531],{},[46,1532,1533],{},"\u002Ftmp",[30,1535,1536],{},"سوکت‌های زمان اجرا",[30,1538,1539],{},"فایل‌های PID",[30,1541,1542],{},"آپلودهای موقت",[30,1544,1545],{},"کش برنامه",[20,1547,1548,1549,1551],{},"به‌جای اینکه کل فایل‌سیستم را قابل نوشتن کنید، داکر به این مکان‌ها اجازه می‌دهد با یک فایل‌سیستم درون‌حافظه (",[46,1550,1520],{},") پشتیبانی شوند.",[20,1553,1554],{},[70,1555,1397],{},[351,1557,1559],{"className":630,"code":1558,"language":632,"meta":356,"style":356},"docker run --read-only --tmpfs \u002Ftmp my-nextjs-app:latest\n",[46,1560,1561],{"__ignoreMap":356},[360,1562,1563,1565,1567,1569,1572,1575],{"class":362,"line":363},[360,1564,640],{"class":639},[360,1566,644],{"class":643},[360,1568,1411],{"class":643},[360,1570,1571],{"class":643}," --tmpfs",[360,1573,1574],{"class":643}," \u002Ftmp",[360,1576,1026],{"class":643},[20,1578,1579],{},[70,1580,997],{},[351,1582,1584],{"className":353,"code":1583,"language":355,"meta":356,"style":356},"services:\n  nextjs:\n    image: my-nextjs-app:latest\n    read_only: true\n    tmpfs:\n      - \u002Ftmp\n",[46,1585,1586,1592,1598,1606,1614,1621],{"__ignoreMap":356},[360,1587,1588,1590],{"class":362,"line":363},[360,1589,1007],{"class":366},[360,1591,371],{"class":370},[360,1593,1594,1596],{"class":362,"line":374},[360,1595,1014],{"class":366},[360,1597,371],{"class":370},[360,1599,1600,1602,1604],{"class":362,"line":667},[360,1601,1021],{"class":366},[360,1603,380],{"class":370},[360,1605,1026],{"class":643},[360,1607,1608,1610,1612],{"class":362,"line":673},[360,1609,1449],{"class":366},[360,1611,380],{"class":370},[360,1613,384],{"class":383},[360,1615,1616,1619],{"class":362,"line":1036},[360,1617,1618],{"class":366},"    tmpfs",[360,1620,371],{"class":370},[360,1622,1623,1625],{"class":362,"line":1100},[360,1624,1040],{"class":1039},[360,1626,1627],{"class":643}," \u002Ftmp\n",[20,1629,1630],{},[70,1631,1048],{},[351,1633,1635],{"className":353,"code":1634,"language":355,"meta":356,"style":356},"volumes:\n  - name: tmp\n    emptyDir:\n      medium: Memory\n\ncontainers:\n  - name: nextjs\n    volumeMounts:\n      - name: tmp\n        mountPath: \u002Ftmp\n",[46,1636,1637,1644,1656,1663,1673,1679,1686,1696,1703,1713],{"__ignoreMap":356},[360,1638,1639,1642],{"class":362,"line":363},[360,1640,1641],{"class":366},"volumes",[360,1643,371],{"class":370},[360,1645,1646,1649,1651,1653],{"class":362,"line":374},[360,1647,1648],{"class":1039},"  -",[360,1650,1130],{"class":366},[360,1652,380],{"class":370},[360,1654,1655],{"class":643}," tmp\n",[360,1657,1658,1661],{"class":362,"line":667},[360,1659,1660],{"class":366},"    emptyDir",[360,1662,371],{"class":370},[360,1664,1665,1668,1670],{"class":362,"line":673},[360,1666,1667],{"class":366},"      medium",[360,1669,380],{"class":370},[360,1671,1672],{"class":643}," Memory\n",[360,1674,1675],{"class":362,"line":1036},[360,1676,1678],{"emptyLinePlaceholder":1677},true,"\n",[360,1680,1681,1684],{"class":362,"line":1100},[360,1682,1683],{"class":366},"containers",[360,1685,371],{"class":370},[360,1687,1688,1690,1692,1694],{"class":362,"line":1108},[360,1689,1648],{"class":1039},[360,1691,1130],{"class":366},[360,1693,380],{"class":370},[360,1695,1090],{"class":643},[360,1697,1698,1701],{"class":362,"line":1116},[360,1699,1700],{"class":366},"    volumeMounts",[360,1702,371],{"class":370},[360,1704,1705,1707,1709,1711],{"class":362,"line":1124},[360,1706,1040],{"class":1039},[360,1708,1130],{"class":366},[360,1710,380],{"class":370},[360,1712,1655],{"class":643},[360,1714,1715,1718,1720],{"class":362,"line":1137},[360,1716,1717],{"class":366},"        mountPath",[360,1719,380],{"class":370},[360,1721,1627],{"class":643},[20,1723,1724,1725,1727],{},"برخلاف فایل‌سیستم ریشه، یک mount ",[46,1726,1520],{}," کاملاً در حافظه قرار دارد. هر چیزی که آنجا نوشته شود با توقف یا راه‌اندازی مجدد کانتینر ناپدید می‌شود. این به برنامه‌ها یک مکان موقت می‌دهد بدون اینکه اجازه تغییرات دائمی داشته باشند.",[139,1729,1731],{"id":1730},"مسیرهای-قابل-نوشتن-باید-صریح-باشند","مسیرهای قابل نوشتن باید صریح باشند",[20,1733,1734],{},"یکی از بزرگترین مزیت‌های فعال‌سازی فایل‌سیستم فقط‌خواندنی این است که شما را مجبور می‌کند به این فکر کنید که برنامه کجا واقعاً به دسترسی نوشتن نیاز دارد. به‌جای اجازه نوشتن در همه جا، صریحاً چند مکان محدود را که باید قابل نوشتن باقی بمانند مشخص می‌کنید.",[20,1736,1737],{},"مثلاً یک برنامه ممکن است به طور مشروع نیاز داشته باشد:",[27,1739,1740,1745,1751],{},[30,1741,1742,1744],{},[46,1743,1533],{}," برای فایل‌های موقت.",[30,1746,1747,1750],{},[46,1748,1749],{},"\u002Fvar\u002Flog"," اگر لاگ‌ها روی دیسک نوشته می‌شوند.",[30,1752,1753,1756],{},[46,1754,1755],{},"\u002Fuploads"," برای محتوای آپلودی کاربر.",[20,1758,1759],{},"بقیه چیزها می‌توانند غیرقابل تغییر بمانند. این کار فرصت‌های مهاجم برای تغییر برنامه یا ایجاد پایداری را به شدت کاهش می‌دهد.",[139,1761,1763],{"id":1762},"کاهش-بدافزار","کاهش بدافزار",[20,1765,1766],{},"مهم است که بفهمید فایل‌سیستم فقط‌خواندنی چه کار می‌کند و چه کار نمی‌کند. جلوی بهره‌برداری مهاجم از آسیب‌پذیری را نمی‌گیرد. جلوی اجرای کد دلخواه را هم نمی‌گیرد. در عوض، جلوی بسیاری از تکنیک‌های رایج پس از بهره‌برداری را می‌گیرد.",[20,1768,1769],{},"مثلاً مهاجم دیگر نمی‌تواند:",[27,1771,1772,1775,1778,1781,1784],{},[30,1773,1774],{},"باینری‌های برنامه را جایگزین کند.",[30,1776,1777],{},"بدافزار را در فایل‌سیستم کانتینر دانلود کند.",[30,1779,1780],{},"فایل‌های پیکربندی را تغییر دهد.",[30,1782,1783],{},"کرون جاب یا اسکریپت راه‌اندازی نصب کند.",[30,1785,1786],{},"درهای پشتی پایدار داخل ایمیج کانتینر بگذارد.",[139,1788,1790],{"id":1789},"کانتینرهای-فقطخواندنی-و-زیرساخت-غیرقابل-تغییر","کانتینرهای فقط‌خواندنی و زیرساخت غیرقابل تغییر",[20,1792,1793],{},"ایده فایل‌سیستم فقط‌خواندنی با یک اصل زیرساختی گسترده‌تر به نام زیرساخت غیرقابل تغییر (immutable infrastructure) هماهنگ است. در یک سیستم غیرقابل تغییر، بارهای کاری در حال اجرا هرگز در محل تغییر نمی‌کنند. اگر برنامه نیاز به به‌روزرسانی دارد، SSH نمی‌زنید داخل کانتینر و فایل‌ها را ویرایش نمی‌کنید - یک ایمیج جدید می‌سازید و یک کانتینر جدید مستقر می‌کنید.",[20,1795,1796],{},"به همین ترتیب، اگر کانتینری به خطر بیفتد، آن را تمیز یا تعمیر نمی‌کنید. آن را نابود کرده و با یک نمونه جدید از یک ایمیج مورد اعتماد جایگزینش می‌کنید.",[20,1798,1799],{},"این رویکرد استقرارها را قابل پیش‌بینی‌تر می‌کند، پاسخ به حادثه را ساده‌تر می‌کند و یک دسته کامل از مشکلات رانش پیکربندی را از بین می‌برد.",[20,1801,1802],{},"فایل‌سیستم ریشه فقط‌خواندنی به طور طبیعی این فلسفه را تقویت می‌کند، چون تضمین می‌کند کانتینر در حال اجرا با ایمیجی که اول مستقر شده یکسان می‌ماند.",[16,1804,1806,1807],{"id":1805},"جلوگیری-از-افزایش-امتیاز-با-no-new-privileges","جلوگیری از افزایش امتیاز با ",[46,1808,1809],{},"no-new-privileges",[20,1811,1812],{},"تا اینجا روی کاهش امتیازات اولیه کانتینر تمرکز کردیم. اما چه می‌شود اگر یک فرآیند بعد از شروع کار سعی کند امتیازات بیشتری به دست آورد؟",[20,1814,1815,1816,1819],{},"در سیستم لینوکس سنتی، چند مکانیزم به فرآیند اجازه می‌دهد امتیازاتش را در طول اجرا افزایش دهد. رایج‌ترین‌شان باینری‌های ",[46,1817,1818],{},"setuid"," و قابلیت‌های فایل هستند.",[20,1821,1822],{},"برای جلوگیری از این نوع حملات، هسته لینوکس ویژگی No New Privileges (NNP) را فراهم کرده.",[20,1824,1825],{},[70,1826,1397],{},[351,1828,1830],{"className":630,"code":1829,"language":632,"meta":356,"style":356},"docker run --security-opt no-new-privileges:true my-app:latest\n",[46,1831,1832],{"__ignoreMap":356},[360,1833,1834,1836,1838,1841,1844,1847],{"class":362,"line":363},[360,1835,640],{"class":639},[360,1837,644],{"class":643},[360,1839,1840],{"class":643}," --security-opt",[360,1842,1843],{"class":643}," no-new-privileges:",[360,1845,1846],{"class":383},"true",[360,1848,1444],{"class":643},[20,1850,1851],{},[70,1852,997],{},[351,1854,1856],{"className":353,"code":1855,"language":355,"meta":356,"style":356},"services:\n  app:\n    image: my-app:latest\n    security_opt:\n      - no-new-privileges:true\n",[46,1857,1858,1864,1870,1878,1885],{"__ignoreMap":356},[360,1859,1860,1862],{"class":362,"line":363},[360,1861,1007],{"class":366},[360,1863,371],{"class":370},[360,1865,1866,1868],{"class":362,"line":374},[360,1867,1433],{"class":366},[360,1869,371],{"class":370},[360,1871,1872,1874,1876],{"class":362,"line":667},[360,1873,1021],{"class":366},[360,1875,380],{"class":370},[360,1877,1444],{"class":643},[360,1879,1880,1883],{"class":362,"line":673},[360,1881,1882],{"class":366},"    security_opt",[360,1884,371],{"class":370},[360,1886,1887,1889],{"class":362,"line":1036},[360,1888,1040],{"class":1039},[360,1890,1891],{"class":643}," no-new-privileges:true\n",[20,1893,1894],{},[70,1895,1048],{},[351,1897,1899],{"className":353,"code":1898,"language":355,"meta":356,"style":356},"securityContext:\n  allowPrivilegeEscalation: false\n",[46,1900,1901,1907],{"__ignoreMap":356},[360,1902,1903,1905],{"class":362,"line":363},[360,1904,367],{"class":366},[360,1906,371],{"class":370},[360,1908,1909,1912,1914],{"class":362,"line":374},[360,1910,1911],{"class":366},"  allowPrivilegeEscalation",[360,1913,380],{"class":370},[360,1915,1916],{"class":383}," false\n",[20,1918,1919,1920,1922],{},"وقتی این ویژگی فعال باشد، هسته تضمین می‌کند که فرآیند نمی‌تواند امتیازاتی را که از قبل نداشته به دست آورد، مهم نیست چه برنامه‌ای را اجرا کند. این ",[46,1921,1809],{}," را به یکی از ساده‌ترین و در عین حال مؤثرترین گزینه‌های سخت‌افزاری تبدیل می‌کند.",[139,1924,1926,1927],{"id":1925},"درک-setuid","درک ",[46,1928,1818],{},[20,1930,1931,1932,1934,1935,1937],{},"فایل‌های لینوکس می‌توانند یک مجوز ویژه به نام بیت ",[46,1933,1818],{}," داشته باشند. معمولاً یک برنامه با امتیازات کاربری که اجرایش می‌کند اجرا می‌شود. اما برنامه ",[46,1936,1818],{}," با امتیازات مالک فایل اجرا می‌شود.",[20,1939,1940,1941,1944,1945,1948,1949,1951,1952,1954],{},"مثلاً ابزار ",[46,1942,1943],{},"passwd"," باید ",[46,1946,1947],{},"\u002Fetc\u002Fshadow"," را تغییر دهد - فایلی که فقط ",[46,1950,314],{}," می‌تواند در آن بنویسد. به‌جای اینکه از هر کاربر بخواهد روت شود، لینوکس باینری را به‌عنوان ",[46,1953,1818],{}," علامت‌گذاری می‌کند تا بتواند موقتاً با امتیازات روت اجرا شود.",[20,1956,1957,1958,1960],{},"این مکانیزم خیلی مفید است، اما فرصتی برای افزایش امتیاز هم ایجاد می‌کند. اگر مهاجم بتواند یک باینری ",[46,1959,1818],{}," آسیب‌پذیر اجرا کند، ممکن است امتیازاتی را که قبلاً نداشته به دست آورد.",[20,1962,1963,1964,1966,1967,1969],{},"با فعال بودن ",[46,1965,1809],{},"، هسته بیت ",[46,1968,1818],{}," را در طول اجرا نادیده می‌گیرد. برنامه اجرا می‌شود، اما امتیازات اضافی را به ارث نمی‌برد.",[139,1971,1973,1974,1977],{"id":1972},"قابلیتهای-فایل-setcap","قابلیت‌های فایل (",[46,1975,1976],{},"setcap",")",[20,1979,1980,1981,1983],{},"قابلیت‌های لینوکس فقط به فرآیندهای در حال اجرا اختصاص داده نمی‌شوند. می‌شود با ابزار ",[46,1982,1976],{}," مستقیماً به فایل‌های اجرایی وصلشان کرد.",[20,1985,529],{},[351,1987,1989],{"className":630,"code":1988,"language":632,"meta":356,"style":356},"setcap cap_net_bind_service=+ep \u002Fusr\u002Flocal\u002Fbin\u002Fmy-server\n",[46,1990,1991],{"__ignoreMap":356},[360,1992,1993,1995,1998],{"class":362,"line":363},[360,1994,1976],{"class":639},[360,1996,1997],{"class":643}," cap_net_bind_service=+ep",[360,1999,2000],{"class":643}," \u002Fusr\u002Flocal\u002Fbin\u002Fmy-server\n",[20,2002,2003],{},"این کار به فایل اجرایی اجازه می‌دهد بدون نیاز به روت به پورت‌های ممتاز متصل شود. در شرایط عادی، اجرای این باینری قابلیت مشخص شده را به فرآیند می‌دهد.",[20,2005,2006,2007,2009],{},"اما وقتی ",[46,2008,1809],{}," فعال است، آن قابلیت‌های اضافی به دست نمی‌آیند - جلوی افزایش امتیاز از طریق قابلیت‌های فایل هم گرفته می‌شود.",[139,2011,2013,2014],{"id":2012},"نقش-execve","نقش ",[46,2015,2016],{},"execve()",[20,2018,2019,2020,2022,2023,2025],{},"هر دو ",[46,2021,1818],{}," و قابلیت‌های فایل موقع فراخوانی syscall ",[46,2024,2016],{}," اعمال می‌شوند. هر بار که یک فرآیند لینوکس برنامه دیگری را اجرا می‌کند، هسته بررسی می‌کند که آیا باینری جدید باید امتیازات اضافی دریافت کند یا نه. معمولاً اینجا جایی است که افزایش امتیاز رخ می‌دهد.",[20,2027,2028,2029,2031],{},"با ",[46,2030,1809],{},"، هسته قوانین را عوض می‌کند:",[65,2033,2034],{},[20,2035,2036,2037,2039],{},"هیچ فرآیندی نمی‌تواند از طریق ",[46,2038,2016],{}," امتیازات بیشتری نسبت به قبل به دست آورد.",[20,2041,2042],{},"فرآیند می‌تواند برنامه دیگری اجرا کند، اما نمی‌تواند ممتازتر از قبل شود.",[139,2044,2046],{"id":2045},"مثال-جلوگیری-از-افزایش-امتیاز-مبتنی-بر-setuid","مثال: جلوگیری از افزایش امتیاز مبتنی بر Setuid",[20,2048,2049,2050,2052,2053,2058],{},"یک مثال واقعی از اینکه چرا ",[46,2051,1809],{}," وجود دارد، آسیب‌پذیری PwnKit (",[57,2054,2057],{"href":2055,"rel":2056},"https:\u002F\u002Fnvd.nist.gov\u002Fvuln\u002Fdetail\u002FCVE-2021-4034",[61],"CVE-2021-4034",") است که در سال 2022 افشا شد.",[20,2060,2061,2062,2065,2066,2068,2069,2071],{},"این آسیب‌پذیری ",[46,2063,2064],{},"pkexec"," را هدف قرار داد، یک ابزار setuid-root که پیش‌فرض روی خیلی از توزیع‌های لینوکس نصب است. از آنجایی که ",[46,2067,2064],{}," با امتیازات مالکش (",[46,2070,314],{},") اجرا می‌شود، یک نقص در پیاده‌سازی‌اش به یک کاربر محلی بی‌امتیاز اجازه می‌داد شل روت بگیرد.",[20,2073,2074,2075,2077],{},"تصور کنید برنامه آسیب‌پذیر Next.js ما به خطر افتاده و مهاجم داخل کانتینر اجرای دستور دارد. در مرحله شناسایی، یک باینری ",[46,2076,2064],{}," آسیب‌پذیر پیدا می‌کند و سعی می‌کند از آن بهره‌برداری کند.",[20,2079,2080,2081,1966,2083,2085,2086,2088,2089,2091,2092,2094],{},"بدون ",[46,2082,1809],{},[46,2084,1818],{}," را در ",[46,2087,2016],{}," اجرا می‌کند. اگر اکسپلویت موفق شود، مهاجم یک شل با کاربر ",[46,2090,314],{}," می‌گیرد. با ",[46,2093,1809],{}," فعال، نتیجه فرق می‌کند.",[20,2096,2097,2098,2100,2101,2103],{},"مهاجم همچنان می‌تواند ",[46,2099,2064],{}," را اجرا کند، اما هسته امتیازات اضافی مرتبط با بیت ",[46,2102,1818],{}," را نمی‌دهد. فرآیند با امتیازات موجود مهاجم ادامه می‌دهد و این مسیر خاص افزایش امتیاز مسدود می‌شود.",[20,2105,2106,2107,2109,2110,2112,2113,2115],{},"نکته مهم: ",[46,2108,1809],{}," یک دفاع همه‌جانبه در برابر همه آسیب‌پذیری‌های افزایش امتیاز محلی نیست. این ویژگی مخصوصاً از به‌دست‌آوردن امتیازات جدید از طریق فایل‌های اجرایی ",[46,2111,1818],{}," و قابلیت‌های فایل در ",[46,2114,2016],{}," جلوگیری می‌کند.",[16,2117,2119],{"id":2118},"seccomp-محدود-کردن-syscallها","Seccomp: محدود کردن syscallها",[20,2121,2122],{},"حتی بعد از حذف قابلیت‌های غیرضروری و جلوگیری از افزایش امتیاز، یک فرآیند آلوده هنوز می‌تواند syscallهای لینوکس را صدا بزند.",[20,2124,2125],{},"هر تعاملی بین فضای کاربر و هسته لینوکس در نهایت از طریق یک syscall (فراخوان سیستمی) انجام می‌شود.",[20,2127,2128],{},"خواندن یک فایل. باز کردن یک سوکت. ایجاد یک فرآیند. تخصیص حافظه. همه این عملیات در نهایت به یک syscall ختم می‌شوند.",[20,2130,2131,2132,689,2135,689,2138,2141],{},"Seccomp به ما اجازه می‌دهد کنترل کنیم که یک فرآیند مجاز به فراخوانی کدام syscallهاست. لینوکس مدرن صدها syscall دارد: ",[46,2133,2134],{},"mount()",[46,2136,2137],{},"bpf()",[46,2139,2140],{},"ptrace()"," - رابط‌های قدرتمند هسته که بیشتر برنامه‌ها هرگز به آنها نیاز ندارند.",[139,2143,2145],{"id":2144},"پروفایل-seccomp-پیشفرض-داکر","پروفایل seccomp پیش‌فرض داکر",[20,2147,2148],{},"داکر به‌طور پیش‌فرض برای هر کانتینر یک پروفایل seccomp اعمال می‌کند.",[20,2150,2151],{},"به‌جای اجازه دسترسی نامحدود به هسته، داکر تعدادی از syscallهای پرخطر را که به ندرت توسط برنامه‌های معمولی نیاز می‌شوند مسدود می‌کند. مثال‌ها شامل عملیات اشکال‌زدایی هسته، بارگذاری ماژول‌های هسته، بعضی عملیات namespace و رابط‌های قدیمی یا خطرناک هسته است.",[20,2153,2154],{},"مهم است که بفهمید این پروفایل پیش‌فرض چیست و چیست نیست. پروفایل seccomp پیش‌فرض داکر نسبتاً مجازکننده است. syscallهایی را که قطعاً خطرناک هستند یا تقریباً در کانتینرها نیاز نمی‌شوند مسدود می‌کند، اما یک لیست سفید سختگیرانه نیست. بیشتر syscallها همچنان مجازند. این طراحی عمدی است - اگر پیش‌فرض محدودکننده‌تر بود، بسیاری از بارهای کاری قانونی را می‌شکست.",[20,2156,2157],{},"در محیط‌های با امنیت بالا، پروفایل پیش‌فرض را باید به‌عنوان نقطه شروع ببینید، نه پیکربندی نهایی. پروفایل‌های سفارشی که فقط syscallهای مورد نیاز برنامه را لیست سفید می‌کنند، حفاظت خیلی قوی‌تری دارند.",[139,2159,2161],{"id":2160},"syscallهای-خطرناک","syscallهای خطرناک",[20,2163,2164],{},"بسیاری از آسیب‌پذیری‌های تاریخی لینوکس شامل syscallهای ممتاز یا پیچیده بوده‌اند. چند مثال:",[27,2166,2167,2172,2177,2182,2188],{},[30,2168,2169,2171],{},[46,2170,2140],{}," برای اشکال‌زدایی فرآیندهای دیگر.",[30,2173,2174,2176],{},[46,2175,2134],{}," برای دستکاری فایل‌سیستم‌ها.",[30,2178,2179,2181],{},[46,2180,2137],{}," برای تعامل با زیرسیستم eBPF.",[30,2183,2184,2187],{},[46,2185,2186],{},"userfaultfd()"," که در چندین آسیب‌پذیری افزایش امتیاز نقش داشته.",[30,2189,2190],{},"بعضی syscallهای مرتبط با namespace.",[20,2192,2193],{},"این رابط‌ها فوق‌العاده قدرتمندند و برای اکثریت قریب به اتفاق برنامه‌های وب غیرضروری. مسدود کردنشان یک دسته کامل از تکنیک‌های پس از بهره‌برداری را حذف می‌کند.",[139,2195,2197],{"id":2196},"پروفایلهای-seccomp-سفارشی","پروفایل‌های seccomp سفارشی",[20,2199,2200],{},"پروفایل seccomp پیش‌فرض داکر عمداً عمومی است. برای بیشتر بارهای کاری خوب کار می‌کند، اما محیط‌های با امنیت بالا اغلب با تعریف پروفایل‌های سفارشی متناسب با یک برنامه خاص جلوتر می‌روند.",[20,2202,2203],{},"مثلاً یک برنامه Next.js نیازهای syscall کاملاً متفاوتی با یک سرور VPN یا یک زمان اجرای کانتینر دارد.",[20,2205,2206],{},"یک پروفایل seccomp سفارشی می‌تواند فقط syscallهایی را که برنامه واقعاً استفاده می‌کند لیست سفید کند و بقیه را رد کند.",[139,2208,2210],{"id":2209},"مثال-مسدود-کردن-حملات-سطح-هسته","مثال: مسدود کردن حملات سطح هسته",[20,2212,2213,2214,2216,2217,2219],{},"یک سرور API پایتون از طریق یک وابستگی آسیب‌پذیر به خطر می‌افتد. مهاجم به اجرای کد می‌رسد و سعی می‌کند از ",[46,2215,2140],{}," برای تزریق به فرآیندهای دیگر یا ",[46,2218,2137],{}," برای تعامل با زیرسیستم eBPF استفاده کند.",[20,2221,2222],{},"اگر آن syscallها توسط پروفایل seccomp مسدود شده باشند، هسته بلافاصله درخواست را رد می‌کند.",[20,2224,2225],{},"مهاجم هنوز اجرای کد دارد، اما نمی‌تواند آزادانه به هر رابط هسته‌ای روی سیستم دسترسی پیدا کند.",[16,2227,2229],{"id":2228},"apparmor-و-selinux","AppArmor و SELinux",[20,2231,2232],{},"تا اینجا قابلیت‌ها (که عملیات ممتاز را کنترل می‌کنند) و seccomp (که syscallها را کنترل می‌کند) را پوشش دادیم. یک لایه سوم هم داریم: ماژول‌های امنیتی لینوکس، یا LSMها.",[20,2234,2235],{},"AppArmor و SELinux دو LSM پراستقرار هستند. آنها به یک سؤال متفاوت از قابلیت‌ها یا seccomp جواب می‌دهند:",[65,2237,2238],{},[20,2239,2240],{},"حتی اگر فرآیند قابلیت مناسب و syscall مناسب را داشته باشد، به چه فایل‌ها، دایرکتوری‌ها، منابع شبکه و اشیاء دیگر می‌تواند دسترسی داشته باشد؟",[20,2242,2243],{},"قابلیت‌ها تعریف می‌کنند یک فرآیند چه کاری می‌تواند بکند. Seccomp تعریف می‌کند کدام APIهای هسته را می‌تواند صدا بزند. LSMها تعریف می‌کنند به کدام اشیاء می‌تواند دست بزند.",[139,2245,2247],{"id":2246},"lsmها-چه-کاری-انجام-میدهند","LSMها چه کاری انجام می‌دهند",[20,2249,2250],{},"LSM یک چارچوب هسته است که به سیاست‌های امنیتی اجازه می‌دهد روی هر عملیات حساس امنیتی اعمال شوند. هر بار که فرآیندی سعی می‌کند فایلی را باز کند، به سوکتی متصل شود یا به دایرکتوری دسترسی پیدا کند، LSM سیاستش را قبل از اجازه یا رد عملیات بررسی می‌کند.",[20,2252,2253,2254,2257],{},"AppArmor از سیاست‌های مبتنی بر مسیر استفاده می‌کند. شما یک پروفایل می‌نویسید که می‌گوید «این باینری می‌تواند ",[46,2255,2256],{},"\u002Fetc\u002Fnginx\u002Fnginx.conf"," را بخواند اما نمی‌تواند در آن بنویسد» یا «این باینری اصلاً نمی‌تواند سوکت شبکه ایجاد کند.»",[20,2259,2260],{},"SELinux از سیاست‌های مبتنی بر برچسب استفاده می‌کند. هر فرآیند و هر شی (فایل، سوکت، دستگاه و غیره) یک برچسب امنیتی می‌گیرد و سیاست تعیین می‌کند کدام فرآیندهای برچسب‌دار می‌توانند به کدام اشیاء برچسب‌دار دسترسی داشته باشند. SELinux قدرتمندتر و پیچیده‌تر است، به همین دلیل بیشتر در محیط‌های دولتی و با امنیت بالا می‌بینیدش تا استقرارهای کانتینری عمومی.",[139,2262,2264],{"id":2263},"نحوه-استفاده-داکر-از-lsmها","نحوه استفاده داکر از LSMها",[20,2266,2267],{},"وقتی کانتینری را اجرا می‌کنید، داکر می‌تواند یک پروفایل AppArmor یا SELinux context به فرآیندهای کانتینر وصل کند. این یک لایه اضافی کنترل دسترسی فراتر از قابلیت‌ها و seccomp فراهم می‌کند.",[20,2269,2270],{},"داکر یک پروفایل AppArmor پیش‌فرض برای کانتینرها دارد که دسترسی به مسیرهای حساس میزبان و منابع سیستم را محدود می‌کند. اگر AppArmor روی میزبان بارگذاری شده باشد، خودکار اعمال می‌شود.",[20,2272,2273,2274,2277],{},"پشتیبانی SELinux در داکر موجود است، اما نیاز دارد که میزبان SELinux را اجرا کند (بیشتر در سیستم‌های RHEL\u002FCentOS\u002FFedora) و پرچم ",[46,2275,2276],{},"selinux-enabled"," در دیمن داکر پیکربندی شده باشد.",[139,2279,2281],{"id":2280},"چگونه-قابلیتها-seccomp-و-lsmها-با-هم-کار-میکنند","چگونه قابلیت‌ها، Seccomp و LSMها با هم کار می‌کنند",[20,2283,2284],{},"هر مکانیزم امنیتی لینوکس به یک سؤال متفاوت جواب می‌دهد. درک این تفاوت به شما کمک می‌کند سهم هر لایه را بهتر بفهمید:",[27,2286,2287,2293,2299],{},[30,2288,2289,2292],{},[70,2290,2291],{},"قابلیت‌ها",": «چه عملیات ممتازی می‌توانم انجام دهم؟»",[30,2294,2295,2298],{},[70,2296,2297],{},"Seccomp",": «کدام APIهای هسته را می‌توانم صدا بزنم؟»",[30,2300,2301,2304],{},[70,2302,2303],{},"LSMها",": «حتی اگر بتونم صدا بزنم، به چه اشیایی می‌توانم دسترسی داشته باشم؟»",[20,2306,2307,2308,2310,2311,2314],{},"این لایه‌ها مکمل هم هستند. یک فرآیند ممکن است ",[46,2309,550],{}," داشته باشد (می‌تواند به پورت‌های ممتاز متصل شود) و seccomp ممکن است syscall ",[46,2312,2313],{},"bind()"," را مجاز کند، اما یک پروفایل AppArmor همچنان می‌تواند جلوی اتصال به یک پورت یا رابط شبکه خاص را بگیرد. هر مکانیزم یک بعد متفاوت از توانایی‌های فرآیند را محدود می‌کند.",[20,2316,2317],{},"هیچ کدام از این لایه‌ها به تنهایی کافی نیستند. اما با هم، یک موضع دفاع در عمق ایجاد می‌کنند که مهاجم باید چندین محدودیت مستقل را دور بزند تا به اهدافش برسد.",[16,2319,2321],{"id":2320},"داکر-روتلس-rootless-docker","داکر روت‌لس (Rootless Docker)",[20,2323,2324],{},"داکر روت‌لس، دیمن داکر و کانتینرها را بدون امتیازات روت روی میزبان اجرا می‌کند. این روی همان user namespaces که قبلاً بحث شد ساخته شده، اما فراتر می‌رود و خود دیمن داکر را هم به‌عنوان یک کاربر بی‌امتیاز اجرا می‌کند.",[20,2326,2327],{},"تفاوت اصلی با نگاشت مجدد user namespace استاندارد در دامنه‌اش است. در داکر استاندارد با user namespaces، فقط فرآیندهای کانتینر دوباره نگاشت می‌شوند، در حالی که دیمن داکر هنوز با روت اجرا می‌شود. در حالت روت‌لس، کل پشته داکر - دیمن، containerd و runc - بدون امتیازات روت میزبان اجرا می‌شود.",[20,2329,2330,2331,2334],{},"داکر روت‌لس محدودیت‌هایی هم دارد. نمی‌تواند به پورت‌های زیر 1024 متصل شود (اگرچه ابزارهایی مثل ",[46,2332,2333],{},"authbind"," یا redirectorها می‌توانند این را دور بزنند)، پشتیبانی محدودی برای برخی درایورهای ذخیره‌سازی دارد و با همه پیکربندی‌های شبکه کار نمی‌کند.",[20,2336,2337],{},"برای محیط‌هایی که لایه اضافه‌ای از انزوای سطح میزبان می‌خواهند، حالت روت‌لس گزینه ارزشمندی است. اما برای بیشتر استقرارهای تولیدی، ترکیب user namespaces استاندارد با سایر اقدامات سخت‌افزاری که در این مقاله گفتیم حفاظت قابل توجهی فراهم می‌کند.",[16,2339,2341],{"id":2340},"امنیت-دیمن-داکر","امنیت دیمن داکر",[20,2343,2344],{},"مدل امنیتی داکر فقط به کانتینرها محدود نمی‌شود. خود دیمن داکر یک مرز امنیتی حیاتی است.",[139,2346,2348,2349,2351],{"id":2347},"گروه-docker-معادل-روت-است","گروه ",[46,2350,640],{}," معادل روت است",[20,2353,2354,2355,2357,2358,2361,2362,2364],{},"در سیستم‌هایی که داکر نصب است، کاربران را می‌شود به گروه ",[46,2356,640],{}," اضافه کرد تا دستورات داکر را بدون ",[46,2359,2360],{},"sudo"," اجرا کنند. این راحت است، اما یک پیامد امنیتی جدی دارد: عضویت در گروه ",[46,2363,640],{}," عملاً معادل دسترسی روت روی میزبان است.",[20,2366,2367,2368,2370],{},"دلیلش ساده است. یک کاربر در گروه ",[46,2369,640],{}," می‌تواند:",[27,2372,2373,2379,2382,2385],{},[30,2374,2375,2376,2378],{},"کانتینرها را با هر قابلیتی، از جمله ",[46,2377,48],{}," شروع کند.",[30,2380,2381],{},"هر دایرکتوری میزبان را با دسترسی کامل خواندن-نوشتن به یک کانتینر mount کند.",[30,2383,2384],{},"مستقیماً به سوکت API داکر دسترسی پیدا کند.",[30,2386,2387],{},"پیکربندی داکر را تغییر دهد.",[20,2389,2390],{},"یعنی هر فرآیندی - کانتینری شده یا نه - که به سوکت داکر دسترسی دارد، عملاً دسترسی روت به میزبان دارد.",[139,2392,2394,2395,2398],{"id":2393},"mount-کردن-varrundockersock-به-داخل-کانتینر","mount کردن ",[46,2396,2397],{},"\u002Fvar\u002Frun\u002Fdocker.sock"," به داخل کانتینر",[20,2400,2401,2402,2404],{},"یک anti-pattern رایج در استقرارهای داکر، mount کردن سوکت داکر (",[46,2403,2397],{},") به داخل کانتینر است. این کار معمولاً برای این انجام می‌شود که کانتینر بتواند کانتینرهای دیگر را مدیریت کند، مثلاً یک عامل CI\u002FCD یا ابزار مانیتورینگ.",[351,2406,2408],{"className":353,"code":2407,"language":355,"meta":356,"style":356},"services:\n  container-manager:\n    image: my-manager:latest\n    volumes:\n      - \u002Fvar\u002Frun\u002Fdocker.sock:\u002Fvar\u002Frun\u002Fdocker.sock\n",[46,2409,2410,2416,2423,2432,2439],{"__ignoreMap":356},[360,2411,2412,2414],{"class":362,"line":363},[360,2413,1007],{"class":366},[360,2415,371],{"class":370},[360,2417,2418,2421],{"class":362,"line":374},[360,2419,2420],{"class":366},"  container-manager",[360,2422,371],{"class":370},[360,2424,2425,2427,2429],{"class":362,"line":667},[360,2426,1021],{"class":366},[360,2428,380],{"class":370},[360,2430,2431],{"class":643}," my-manager:latest\n",[360,2433,2434,2437],{"class":362,"line":673},[360,2435,2436],{"class":366},"    volumes",[360,2438,371],{"class":370},[360,2440,2441,2443],{"class":362,"line":1036},[360,2442,1040],{"class":1039},[360,2444,2445],{"class":643}," \u002Fvar\u002Frun\u002Fdocker.sock:\u002Fvar\u002Frun\u002Fdocker.sock\n",[20,2447,2448,2449,2451],{},"mount کردن سوکت داکر به داخل کانتینر یعنی فرآیندهای آن کانتینر همان امتیازات یک کاربر در گروه ",[46,2450,640],{}," را دارند. اگر مهاجم آن کانتینر را به خطر بیندازد، می‌تواند کانتینرهای جدید شروع کند، فایل‌سیستم‌های دلخواه میزبان را mount کند و دسترسی کامل سطح میزبان را بگیرد - همه اینها بدون فرار از کانتینر.",[20,2453,2454],{},"اگر یک بار کاری نیاز به دسترسی داکر دارد، به جای آن از API داکر از طریق TLS با گواهی مشتری استفاده کنید، یا از یک پروکسی امنیتی که فقط عملیات API خاص مورد نیاز را expose می‌کند.",[20,2456,2457],{},"علاوه بر سوکت، خود دیمن داکر هم باید ایمن شود. فعال‌سازی TLS برای API داکر از دسترسی تأیید نشده جلوگیری می‌کند و لاگ‌گیری حسابرسی به تشخیص فراخوانی‌های API مشکوک کمک می‌کند. حالت روت‌لس و سخت‌سازی عمیق‌تر دیمن را در یک مقاله بعدی پوشش می‌دهم.",[16,2459,2461],{"id":2460},"سوءاستفاده-از-منابع","سوءاستفاده از منابع",[20,2463,2464],{},"تا اینجا تمرکز کردیم روی این که مهاجم نتواند امتیازات بیشتری بگیرد یا سیستم را تغییر دهد. اما همه حملات درباره افزایش امتیاز نیستند.",[20,2466,2467],{},"گاهی مهاجم فقط می‌خواهد برنامه شما را از دسترس خارج کند.",[20,2469,2470],{},"تصور کنید برنامه آسیب‌پذیر Next.js ما به خطر افتاده. مهاجم به‌جای تلاش برای فرار از کانتینر، یک حلقه بی‌نهایت اجرا می‌کند، مدام حافظه تخصیص می‌دهد یا هزاران فرآیند فرزند می‌سازد.",[20,2472,2473],{},"این حملات به امتیازات بالا نیاز ندارند - فقط از منابع موجود کانتینر سوءاستفاده می‌کنند.",[20,2475,2476],{},"برای کاهش این نوع حملات، داکر به cgroups (گروه‌های کنترل) تکیه می‌کند و به مدیران اجازه می‌دهد روی CPU، حافظه و ایجاد فرآیند محدودیت بگذارند.",[139,2478,2480],{"id":2479},"محدودیتهای-حافظه","محدودیت‌های حافظه",[20,2482,2483],{},"بدون محدودیت حافظه، یک کانتینر آلوده می‌تواند تمام RAM موجود روی میزبان را مصرف کند و روی همه بارهای کاری دیگر تأثیر بگذارد.",[20,2485,2486],{},[70,2487,997],{},[351,2489,2491],{"className":353,"code":2490,"language":355,"meta":356,"style":356},"services:\n  nextjs:\n    image: my-nextjs-app\n    deploy:\n      resources:\n        limits:\n          memory: 512M\n",[46,2492,2493,2499,2505,2514,2521,2528,2535],{"__ignoreMap":356},[360,2494,2495,2497],{"class":362,"line":363},[360,2496,1007],{"class":366},[360,2498,371],{"class":370},[360,2500,2501,2503],{"class":362,"line":374},[360,2502,1014],{"class":366},[360,2504,371],{"class":370},[360,2506,2507,2509,2511],{"class":362,"line":667},[360,2508,1021],{"class":366},[360,2510,380],{"class":370},[360,2512,2513],{"class":643}," my-nextjs-app\n",[360,2515,2516,2519],{"class":362,"line":673},[360,2517,2518],{"class":366},"    deploy",[360,2520,371],{"class":370},[360,2522,2523,2526],{"class":362,"line":1036},[360,2524,2525],{"class":366},"      resources",[360,2527,371],{"class":370},[360,2529,2530,2533],{"class":362,"line":1100},[360,2531,2532],{"class":366},"        limits",[360,2534,371],{"class":370},[360,2536,2537,2540,2542],{"class":362,"line":1108},[360,2538,2539],{"class":366},"          memory",[360,2541,380],{"class":370},[360,2543,2544],{"class":643}," 512M\n",[20,2546,2547],{},[70,2548,1048],{},[351,2550,2552],{"className":353,"code":2551,"language":355,"meta":356,"style":356},"resources:\n  requests:\n    memory: \"256Mi\"\n  limits:\n    memory: \"512Mi\"\n",[46,2553,2554,2561,2568,2578,2585],{"__ignoreMap":356},[360,2555,2556,2559],{"class":362,"line":363},[360,2557,2558],{"class":366},"resources",[360,2560,371],{"class":370},[360,2562,2563,2566],{"class":362,"line":374},[360,2564,2565],{"class":366},"  requests",[360,2567,371],{"class":370},[360,2569,2570,2573,2575],{"class":362,"line":667},[360,2571,2572],{"class":366},"    memory",[360,2574,380],{"class":370},[360,2576,2577],{"class":643}," \"256Mi\"\n",[360,2579,2580,2583],{"class":362,"line":673},[360,2581,2582],{"class":366},"  limits",[360,2584,371],{"class":370},[360,2586,2587,2589,2591],{"class":362,"line":1036},[360,2588,2572],{"class":366},[360,2590,380],{"class":370},[360,2592,2593],{"class":643}," \"512Mi\"\n",[20,2595,2596],{},"اگر فرآیند از حد مجاز بیشتر شود، قاتل Out-Of-Memory (OOM) لینوکس آن را خاتمه می‌دهد، به‌جای اینکه اجازه دهد حافظه میزبان را تمام کند.",[139,2598,2600,2601,1977],{"id":2599},"محدودیت-فرآیند-pids_limit","محدودیت فرآیند (",[46,2602,2603],{},"pids_limit",[20,2605,2606],{},"یک تکنیک رایج دیگر انکار سرویس، fork bomb است - فرآیندی که مدام فرآیند فرزند ایجاد می‌کند تا سیستم عامل دیگر نتواند جدید بسازد.",[20,2608,2609],{},"داکر به ما اجازه می‌دهد محدود کنیم که یک کانتینر چند فرآیند می‌تواند ایجاد کند.",[351,2611,2613],{"className":353,"code":2612,"language":355,"meta":356,"style":356},"services:\n  nextjs:\n    image: my-nextjs-app\n    pids_limit: 100\n",[46,2614,2615,2621,2627,2635],{"__ignoreMap":356},[360,2616,2617,2619],{"class":362,"line":363},[360,2618,1007],{"class":366},[360,2620,371],{"class":370},[360,2622,2623,2625],{"class":362,"line":374},[360,2624,1014],{"class":366},[360,2626,371],{"class":370},[360,2628,2629,2631,2633],{"class":362,"line":667},[360,2630,1021],{"class":366},[360,2632,380],{"class":370},[360,2634,2513],{"class":643},[360,2636,2637,2640,2642],{"class":362,"line":673},[360,2638,2639],{"class":366},"    pids_limit",[360,2641,380],{"class":370},[360,2643,2644],{"class":383}," 100\n",[20,2646,2647],{},"حتی اگر مهاجم به اجرای کد برسد، نمی‌تواند بیشتر از حد مجاز فرآیند ایجاد کند.",[139,2649,2651],{"id":2650},"محدودیتهای-cpu","محدودیت‌های CPU",[20,2653,2654],{},"تمام کردن CPU یک راه مستقیم دیگر برای مختل کردن سرویس است.",[20,2656,2657],{},"با محدودیت‌های CPU، مطمئن می‌شویم که یک کانتینر نمی‌تواند پردازنده‌های میزبان را به طور کامل تصاحب کند.",[20,2659,2660],{},[70,2661,997],{},[351,2663,2665],{"className":353,"code":2664,"language":355,"meta":356,"style":356},"services:\n  nextjs:\n    image: my-nextjs-app\n    deploy:\n      resources:\n        limits:\n          cpus: \"1.0\"\n",[46,2666,2667,2673,2679,2687,2693,2699,2705],{"__ignoreMap":356},[360,2668,2669,2671],{"class":362,"line":363},[360,2670,1007],{"class":366},[360,2672,371],{"class":370},[360,2674,2675,2677],{"class":362,"line":374},[360,2676,1014],{"class":366},[360,2678,371],{"class":370},[360,2680,2681,2683,2685],{"class":362,"line":667},[360,2682,1021],{"class":366},[360,2684,380],{"class":370},[360,2686,2513],{"class":643},[360,2688,2689,2691],{"class":362,"line":673},[360,2690,2518],{"class":366},[360,2692,371],{"class":370},[360,2694,2695,2697],{"class":362,"line":1036},[360,2696,2525],{"class":366},[360,2698,371],{"class":370},[360,2700,2701,2703],{"class":362,"line":1100},[360,2702,2532],{"class":366},[360,2704,371],{"class":370},[360,2706,2707,2710,2712],{"class":362,"line":1108},[360,2708,2709],{"class":366},"          cpus",[360,2711,380],{"class":370},[360,2713,2714],{"class":643}," \"1.0\"\n",[20,2716,2717],{},[70,2718,1048],{},[351,2720,2722],{"className":353,"code":2721,"language":355,"meta":356,"style":356},"resources:\n  requests:\n    cpu: \"500m\"\n  limits:\n    cpu: \"1\"\n",[46,2723,2724,2730,2736,2746,2752],{"__ignoreMap":356},[360,2725,2726,2728],{"class":362,"line":363},[360,2727,2558],{"class":366},[360,2729,371],{"class":370},[360,2731,2732,2734],{"class":362,"line":374},[360,2733,2565],{"class":366},[360,2735,371],{"class":370},[360,2737,2738,2741,2743],{"class":362,"line":667},[360,2739,2740],{"class":366},"    cpu",[360,2742,380],{"class":370},[360,2744,2745],{"class":643}," \"500m\"\n",[360,2747,2748,2750],{"class":362,"line":673},[360,2749,2582],{"class":366},[360,2751,371],{"class":370},[360,2753,2754,2756,2758],{"class":362,"line":1036},[360,2755,2740],{"class":366},[360,2757,380],{"class":370},[360,2759,2760],{"class":643}," \"1\"\n",[20,2762,2763],{},"این محدودیت‌ها جلوی سوءاستفاده را نمی‌گیرند، بلکه آن را مهار می‌کنند.",[16,2765,2767],{"id":2766},"دسترسی-به-دستگاه","دسترسی به دستگاه",[20,2769,2770,2771,2774],{},"به‌طور پیش‌فرض، داکر کانتینرها را از سخت‌افزار میزبان ایزوله می‌کند. این مهم است چون در لینوکس، بسیاری از منابع سخت‌افزاری به‌صورت فایل در ",[46,2772,2773],{},"\u002Fdev"," expose می‌شوند. دسترسی به یکی از این دستگاه‌ها اغلب دسترسی مستقیم به یک رابط هسته‌ای می‌دهد، پس دسترسی به دستگاه باید عمداً داده شود، نه پیش‌فرض.",[20,2776,2777],{},"مثال‌های رایج:",[27,2779,2780,2783,2789,2792],{},[30,2781,2782],{},"GPUهای NVIDIA برای هوش مصنوعی و استنتاج یادگیری ماشین.",[30,2784,2785,2788],{},[46,2786,2787],{},"\u002Fdev\u002Fnet\u002Ftun"," برای نرم‌افزار VPN مثل WireGuard یا OpenVPN.",[30,2790,2791],{},"ماژول‌های امنیتی سخت‌افزاری (HSM) برای مدیریت کلید رمزنگاری.",[30,2793,2794],{},"دستگاه‌های USB یا سریال در استقرارهای صنعتی و IoT.",[20,2796,2797],{},"مثلاً یک کانتینر WireGuard نیاز به دسترسی به دستگاه TUN دارد:",[351,2799,2801],{"className":353,"code":2800,"language":355,"meta":356,"style":356},"services:\n  wireguard:\n    image: linuxserver\u002Fwireguard\n    devices:\n      - \u002Fdev\u002Fnet\u002Ftun:\u002Fdev\u002Fnet\u002Ftun\n    cap_add:\n      - NET_ADMIN\n",[46,2802,2803,2809,2816,2825,2832,2839,2845],{"__ignoreMap":356},[360,2804,2805,2807],{"class":362,"line":363},[360,2806,1007],{"class":366},[360,2808,371],{"class":370},[360,2810,2811,2814],{"class":362,"line":374},[360,2812,2813],{"class":366},"  wireguard",[360,2815,371],{"class":370},[360,2817,2818,2820,2822],{"class":362,"line":667},[360,2819,1021],{"class":366},[360,2821,380],{"class":370},[360,2823,2824],{"class":643}," linuxserver\u002Fwireguard\n",[360,2826,2827,2830],{"class":362,"line":673},[360,2828,2829],{"class":366},"    devices",[360,2831,371],{"class":370},[360,2833,2834,2836],{"class":362,"line":1036},[360,2835,1040],{"class":1039},[360,2837,2838],{"class":643}," \u002Fdev\u002Fnet\u002Ftun:\u002Fdev\u002Fnet\u002Ftun\n",[360,2840,2841,2843],{"class":362,"line":1100},[360,2842,1247],{"class":366},[360,2844,371],{"class":370},[360,2846,2847,2849],{"class":362,"line":1108},[360,2848,1040],{"class":1039},[360,2850,2851],{"class":643}," NET_ADMIN\n",[20,2853,2854,2855,2857,2858,2860],{},"به‌جای expose کردن کل سلسله‌مراتب ",[46,2856,2773],{}," یا اجرای کانتینر با ",[46,2859,48],{},"، فقط دستگاه‌هایی را که بار کاری شما نیاز دارد در اختیارش بگذارید.",[20,2862,2863,2864],{},"دسترسی به دستگاه موضوع گسترده‌ای است و دستگاه‌های دقیق بین بارهای کاری فرق می‌کند. نکته مهم حفظ کردن همه دستگاه‌ها نیست، بلکه پیروی از همان اصلی است که در کل این مقاله دنبال کردیم: ",[70,2865,2866],{},"فقط آنچه را که برنامه واقعاً نیاز دارد expose کنید، و نه بیشتر.",[20,2868,2869,2870,689,2873,689,2876,2879,2880,2883,2884,2888],{},"داکر از ویژگی‌های بیشتری هم پشتیبانی می‌کند که خارج از scope این مقاله است، از جمله مجوزهای دستگاه (",[46,2871,2872],{},"r",[46,2874,2875],{},"w",[46,2877,2878],{},"m",")، پشتیبانی GPU، رابط دستگاه کانتینر (CDI) و قوانین cgroup دستگاه. اگر بار کاری شما به پیکربندی پیشرفته‌تری نیاز دارد، مستندات رسمی داکر منبع جامعی برای پرچم ",[46,2881,2882],{},"--device"," و گزینه‌های زمان اجرای مرتبط دارد:\n",[57,2885,2886],{"href":2886,"rel":2887},"https:\u002F\u002Fdocs.docker.com\u002Freference\u002Fcli\u002Fdocker\u002Fcontainer\u002Frun\u002F#device",[61],".",[16,2890,2892],{"id":2891},"کانتینرهای-ممتاز-privileged","کانتینرهای ممتاز (Privileged)",[20,2894,2895],{},"تا اینجا چندین لایه از مدل امنیتی داکر را پوشش دادیم:",[27,2897,2898,2901,2904,2907,2910,2913,2916,2919],{},[30,2899,2900],{},"اجرا با کاربر غیرروت.",[30,2902,2903],{},"حذف قابلیت‌های غیرضروری.",[30,2905,2906],{},"فایل‌سیستم ریشه فقط‌خواندنی.",[30,2908,2909],{},"جلوگیری از افزایش امتیاز.",[30,2911,2912],{},"محدود کردن syscallها.",[30,2914,2915],{},"محدود کردن منابع.",[30,2917,2918],{},"expose کردن فقط دستگاه‌های مورد نیاز.",[30,2920,2921],{},"پیکربندی LSMها.",[20,2923,2924,2925,2927],{},"پرچم ",[46,2926,48],{}," عملاً بسیاری از این حفاظت‌ها را دور می‌زند.",[139,2929,2931,2933],{"id":2930},"privileged-واقعاً-چه-کار-میکند",[46,2932,48],{}," واقعاً چه کار می‌کند",[20,2935,2936,2937,2939],{},"اجرای کانتینر با ",[46,2938,48],{}," خیلی فراتر از «دادن مجوزهای بیشتر» است. داکر تقریباً همه قابلیت‌های لینوکس را به کانتینر می‌دهد، دسترسی گسترده‌ای به دستگاه‌های میزبان فراهم می‌کند، محدودیت‌های cgroup دستگاه را برمی‌دارد و چندین مکانیزم ایمنی پیش‌فرض زمان اجرا را غیرفعال می‌کند.",[20,2941,2942],{},"نتیجه کانتینری است که تقریباً مثل یک فرآیند معمولی که مستقیم روی میزبان اجرا می‌شود رفتار می‌کند.",[139,2944,2946],{"id":2945},"چرا-باید-از-آن-اجتناب-کنید","چرا باید از آن اجتناب کنید",[20,2948,2949],{},"یک الگوی رایج عیب‌یابی این است:",[65,2951,2952,2955],{},[20,2953,2954],{},"کانتینر مجوز ندارد.",[20,2956,2028,2957,2959],{},[46,2958,48],{}," اجراش کن.",[20,2961,2962],{},"هرچند این کار اغلب مشکل فوری را حل می‌کند، اما ده‌ها مجوزی را هم می‌دهد که برنامه احتمالاً هیچ‌وقت به آنها نیاز ندارد.",[20,2964,2965],{},"به‌جایش نیاز خاص را شناسایی کنید:",[27,2967,2968,2974,2979],{},[30,2969,2970,2971,2973],{},"آیا برنامه به ",[46,2972,560],{}," نیاز دارد؟",[30,2975,2976,2977,2973],{},"آیا به دسترسی ",[46,2978,2787],{},[30,2980,2981],{},"آیا به یک قابلیت واحد لینوکس نیاز دارد؟",[20,2983,2984,2985,2987],{},"دادن یک مجوز تقریباً همیشه بهتر از دادن همه مجوزهاست. به‌عنوان یک قاعده کلی، ",[46,2986,48],{}," را باید برای نرم‌افزارهای زیرساختی تخصصی مثل زمان‌های اجرای کانتینر سطح پایین، ابزارهای اشکال‌زدایی یا ابزارهای مدیریت سخت‌افزار نگه دارید - نه برای برنامه‌های وب معمولی، APIها یا کارگرهای پس‌زمینه.",[20,2989,2990,2991,2993],{},"اگر برنامه تولیدی شما به ",[46,2992,48],{}," نیاز دارد، اول بفهمید چرا، بعد قبولش کنید.",[16,2995,2997],{"id":2996},"جمعبندی-نهایی","جمع‌بندی نهایی",[20,2999,3000],{},"در این مقاله ویژگی‌های امنیتی داکر را جداگانه بررسی کردیم. اما در عمل، این ویژگی‌ها قرار نیست تنها استفاده شوند - مکمل هم هستند.",[20,3002,3003],{},"بیایید به مدل تهدید اول مقاله برگردیم.",[20,3005,3006],{},"یک مهاجم از آسیب‌پذیری در برنامه Next.js ما استفاده کرده و داخل کانتینر به اجرای کد از راه دور رسیده.",[20,3008,3009],{},"در این مرحله، همه اقدامات سخت‌افزاری که گفتیم با هم کار می‌کنند:",[27,3011,3012,3015,3018,3021,3024,3027,3030],{},[30,3013,3014],{},"برنامه با کاربر غیرروت اجرا می‌شود.",[30,3016,3017],{},"همه قابلیت‌های غیرضروری لینوکس حذف شده‌اند.",[30,3019,3020],{},"فایل‌سیستم ریشه فقط‌خواندنی است.",[30,3022,3023],{},"فایل‌های موقت فقط به tmpfs نوشته می‌شوند.",[30,3025,3026],{},"افزایش امتیاز غیرفعال است.",[30,3028,3029],{},"کانتینر با محدودیت‌های CPU، حافظه و PID محدود شده.",[30,3031,3032],{},"فقط حداقل منابع مورد نیاز برنامه expose شده.",[20,3034,3035],{},"هیچ کدام از این اقدامات جلوی اکسپلویت اولیه را نمی‌گیرد. در عوض، با هم گزینه‌های مهاجم را بعد از نفوذ موفق محدود می‌کنند.",[20,3037,3038],{},"مثال‌های زیر نشان می‌دهد که این پیکربندی برای یک برنامه Next.js آماده تولید که پشت پروکسی معکوس Nginx اجرا می‌شود چطور می‌تواند باشد.",[139,3040,3041],{"id":640},[46,3042,3043],{},"Docker",[351,3045,3047],{"className":630,"code":3046,"language":632,"meta":356,"style":356},"docker network create web\n\ndocker run -d \\\n  --name nextjs \\\n  --network web \\\n  --user 1000:1000 \\\n  --read-only \\\n  --tmpfs \u002Ftmp \\\n  --cap-drop ALL \\\n  --security-opt no-new-privileges:true \\\n  --memory 512m \\\n  --cpus 1 \\\n  --pids-limit 100 \\\n  my-nextjs-app:latest\n\ndocker run -d \\\n  --name nginx \\\n  --network web \\\n  -p 80:80 \\\n  --read-only \\\n  --tmpfs \u002Fvar\u002Fcache\u002Fnginx \\\n  --tmpfs \u002Fvar\u002Frun \\\n  --cap-drop ALL \\\n  --cap-add NET_BIND_SERVICE \\\n  --security-opt no-new-privileges:true \\\n  nginx:latest\n",[46,3048,3049,3062,3066,3077,3087,3097,3107,3114,3123,3131,3142,3152,3162,3172,3177,3181,3191,3201,3210,3221,3228,3238,3248,3257,3266,3277],{"__ignoreMap":356},[360,3050,3051,3053,3056,3059],{"class":362,"line":363},[360,3052,640],{"class":639},[360,3054,3055],{"class":643}," network",[360,3057,3058],{"class":643}," create",[360,3060,3061],{"class":643}," web\n",[360,3063,3064],{"class":362,"line":374},[360,3065,1678],{"emptyLinePlaceholder":1677},[360,3067,3068,3070,3072,3075],{"class":362,"line":667},[360,3069,640],{"class":639},[360,3071,644],{"class":643},[360,3073,3074],{"class":643}," -d",[360,3076,844],{"class":843},[360,3078,3079,3082,3085],{"class":362,"line":673},[360,3080,3081],{"class":643},"  --name",[360,3083,3084],{"class":643}," nextjs",[360,3086,844],{"class":843},[360,3088,3089,3092,3095],{"class":362,"line":1036},[360,3090,3091],{"class":643},"  --network",[360,3093,3094],{"class":643}," web",[360,3096,844],{"class":843},[360,3098,3099,3102,3105],{"class":362,"line":1100},[360,3100,3101],{"class":643},"  --user",[360,3103,3104],{"class":643}," 1000:1000",[360,3106,844],{"class":843},[360,3108,3109,3112],{"class":362,"line":1108},[360,3110,3111],{"class":643},"  --read-only",[360,3113,844],{"class":843},[360,3115,3116,3119,3121],{"class":362,"line":1116},[360,3117,3118],{"class":643},"  --tmpfs",[360,3120,1574],{"class":643},[360,3122,844],{"class":843},[360,3124,3125,3127,3129],{"class":362,"line":1124},[360,3126,849],{"class":643},[360,3128,757],{"class":643},[360,3130,844],{"class":843},[360,3132,3133,3136,3138,3140],{"class":362,"line":1137},[360,3134,3135],{"class":643},"  --security-opt",[360,3137,1843],{"class":643},[360,3139,1846],{"class":383},[360,3141,844],{"class":843},[360,3143,3144,3147,3150],{"class":362,"line":1147},[360,3145,3146],{"class":643},"  --memory",[360,3148,3149],{"class":643}," 512m",[360,3151,844],{"class":843},[360,3153,3154,3157,3160],{"class":362,"line":1155},[360,3155,3156],{"class":643},"  --cpus",[360,3158,3159],{"class":383}," 1",[360,3161,844],{"class":843},[360,3163,3164,3167,3170],{"class":362,"line":1163},[360,3165,3166],{"class":643},"  --pids-limit",[360,3168,3169],{"class":383}," 100",[360,3171,844],{"class":843},[360,3173,3174],{"class":362,"line":1171},[360,3175,3176],{"class":643},"  my-nextjs-app:latest\n",[360,3178,3179],{"class":362,"line":1364},[360,3180,1678],{"emptyLinePlaceholder":1677},[360,3182,3183,3185,3187,3189],{"class":362,"line":1372},[360,3184,640],{"class":639},[360,3186,644],{"class":643},[360,3188,3074],{"class":643},[360,3190,844],{"class":843},[360,3192,3194,3196,3199],{"class":362,"line":3193},17,[360,3195,3081],{"class":643},[360,3197,3198],{"class":643}," nginx",[360,3200,844],{"class":843},[360,3202,3204,3206,3208],{"class":362,"line":3203},18,[360,3205,3091],{"class":643},[360,3207,3094],{"class":643},[360,3209,844],{"class":843},[360,3211,3213,3216,3219],{"class":362,"line":3212},19,[360,3214,3215],{"class":643},"  -p",[360,3217,3218],{"class":643}," 80:80",[360,3220,844],{"class":843},[360,3222,3224,3226],{"class":362,"line":3223},20,[360,3225,3111],{"class":643},[360,3227,844],{"class":843},[360,3229,3231,3233,3236],{"class":362,"line":3230},21,[360,3232,3118],{"class":643},[360,3234,3235],{"class":643}," \u002Fvar\u002Fcache\u002Fnginx",[360,3237,844],{"class":843},[360,3239,3241,3243,3246],{"class":362,"line":3240},22,[360,3242,3118],{"class":643},[360,3244,3245],{"class":643}," \u002Fvar\u002Frun",[360,3247,844],{"class":843},[360,3249,3251,3253,3255],{"class":362,"line":3250},23,[360,3252,849],{"class":643},[360,3254,757],{"class":643},[360,3256,844],{"class":843},[360,3258,3260,3262,3264],{"class":362,"line":3259},24,[360,3261,858],{"class":643},[360,3263,861],{"class":643},[360,3265,844],{"class":843},[360,3267,3269,3271,3273,3275],{"class":362,"line":3268},25,[360,3270,3135],{"class":643},[360,3272,1843],{"class":643},[360,3274,1846],{"class":383},[360,3276,844],{"class":843},[360,3278,3280],{"class":362,"line":3279},26,[360,3281,3282],{"class":643},"  nginx:latest\n",[139,3284,3286],{"id":3285},"docker-compose",[46,3287,3288],{},"Docker Compose",[351,3290,3292],{"className":353,"code":3291,"language":355,"meta":356,"style":356},"services:\n  nextjs:\n    image: my-nextjs-app:latest\n    user: \"1000:1000\"\n    read_only: true\n    tmpfs:\n      - \u002Ftmp\n    cap_drop:\n      - ALL\n    security_opt:\n      - no-new-privileges:true\n    pids_limit: 100\n    deploy:\n      resources:\n        limits:\n          cpus: \"1.0\"\n          memory: 512M\n\n  nginx:\n    image: nginx:latest\n    ports:\n      - \"80:80\"\n    read_only: true\n    tmpfs:\n      - \u002Fvar\u002Fcache\u002Fnginx\n      - \u002Fvar\u002Frun\n    cap_drop:\n      - ALL\n    cap_add:\n      - NET_BIND_SERVICE\n    security_opt:\n      - no-new-privileges:true\n",[46,3293,3294,3300,3306,3314,3324,3332,3338,3344,3350,3356,3362,3368,3376,3382,3388,3394,3402,3410,3414,3420,3428,3435,3442,3450,3456,3463,3470,3477,3484,3491,3498,3505],{"__ignoreMap":356},[360,3295,3296,3298],{"class":362,"line":363},[360,3297,1007],{"class":366},[360,3299,371],{"class":370},[360,3301,3302,3304],{"class":362,"line":374},[360,3303,1014],{"class":366},[360,3305,371],{"class":370},[360,3307,3308,3310,3312],{"class":362,"line":667},[360,3309,1021],{"class":366},[360,3311,380],{"class":370},[360,3313,1026],{"class":643},[360,3315,3316,3319,3321],{"class":362,"line":673},[360,3317,3318],{"class":366},"    user",[360,3320,380],{"class":370},[360,3322,3323],{"class":643}," \"1000:1000\"\n",[360,3325,3326,3328,3330],{"class":362,"line":1036},[360,3327,1449],{"class":366},[360,3329,380],{"class":370},[360,3331,384],{"class":383},[360,3333,3334,3336],{"class":362,"line":1100},[360,3335,1618],{"class":366},[360,3337,371],{"class":370},[360,3339,3340,3342],{"class":362,"line":1108},[360,3341,1040],{"class":1039},[360,3343,1627],{"class":643},[360,3345,3346,3348],{"class":362,"line":1116},[360,3347,1031],{"class":366},[360,3349,371],{"class":370},[360,3351,3352,3354],{"class":362,"line":1124},[360,3353,1040],{"class":1039},[360,3355,1043],{"class":643},[360,3357,3358,3360],{"class":362,"line":1137},[360,3359,1882],{"class":366},[360,3361,371],{"class":370},[360,3363,3364,3366],{"class":362,"line":1147},[360,3365,1040],{"class":1039},[360,3367,1891],{"class":643},[360,3369,3370,3372,3374],{"class":362,"line":1155},[360,3371,2639],{"class":366},[360,3373,380],{"class":370},[360,3375,2644],{"class":383},[360,3377,3378,3380],{"class":362,"line":1163},[360,3379,2518],{"class":366},[360,3381,371],{"class":370},[360,3383,3384,3386],{"class":362,"line":1171},[360,3385,2525],{"class":366},[360,3387,371],{"class":370},[360,3389,3390,3392],{"class":362,"line":1364},[360,3391,2532],{"class":366},[360,3393,371],{"class":370},[360,3395,3396,3398,3400],{"class":362,"line":1372},[360,3397,2709],{"class":366},[360,3399,380],{"class":370},[360,3401,2714],{"class":643},[360,3403,3404,3406,3408],{"class":362,"line":3193},[360,3405,2539],{"class":366},[360,3407,380],{"class":370},[360,3409,2544],{"class":643},[360,3411,3412],{"class":362,"line":3203},[360,3413,1678],{"emptyLinePlaceholder":1677},[360,3415,3416,3418],{"class":362,"line":3212},[360,3417,1219],{"class":366},[360,3419,371],{"class":370},[360,3421,3422,3424,3426],{"class":362,"line":3223},[360,3423,1021],{"class":366},[360,3425,380],{"class":370},[360,3427,1230],{"class":643},[360,3429,3430,3433],{"class":362,"line":3230},[360,3431,3432],{"class":366},"    ports",[360,3434,371],{"class":370},[360,3436,3437,3439],{"class":362,"line":3240},[360,3438,1040],{"class":1039},[360,3440,3441],{"class":643}," \"80:80\"\n",[360,3443,3444,3446,3448],{"class":362,"line":3250},[360,3445,1449],{"class":366},[360,3447,380],{"class":370},[360,3449,384],{"class":383},[360,3451,3452,3454],{"class":362,"line":3259},[360,3453,1618],{"class":366},[360,3455,371],{"class":370},[360,3457,3458,3460],{"class":362,"line":3268},[360,3459,1040],{"class":1039},[360,3461,3462],{"class":643}," \u002Fvar\u002Fcache\u002Fnginx\n",[360,3464,3465,3467],{"class":362,"line":3279},[360,3466,1040],{"class":1039},[360,3468,3469],{"class":643}," \u002Fvar\u002Frun\n",[360,3471,3473,3475],{"class":362,"line":3472},27,[360,3474,1031],{"class":366},[360,3476,371],{"class":370},[360,3478,3480,3482],{"class":362,"line":3479},28,[360,3481,1040],{"class":1039},[360,3483,1043],{"class":643},[360,3485,3487,3489],{"class":362,"line":3486},29,[360,3488,1247],{"class":366},[360,3490,371],{"class":370},[360,3492,3494,3496],{"class":362,"line":3493},30,[360,3495,1040],{"class":1039},[360,3497,1256],{"class":643},[360,3499,3501,3503],{"class":362,"line":3500},31,[360,3502,1882],{"class":366},[360,3504,371],{"class":370},[360,3506,3508,3510],{"class":362,"line":3507},32,[360,3509,1040],{"class":1039},[360,3511,1891],{"class":643},[139,3513,3515],{"id":3514},"kubernetes",[46,3516,3517],{},"Kubernetes",[351,3519,3521],{"className":353,"code":3520,"language":355,"meta":356,"style":356},"apiVersion: apps\u002Fv1\nkind: Deployment\nmetadata:\n  name: nextjs\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app: nextjs\n  template:\n    metadata:\n      labels:\n        app: nextjs\n    spec:\n      containers:\n        - name: nextjs\n          image: my-nextjs-app:latest\n          securityContext:\n            runAsNonRoot: true\n            allowPrivilegeEscalation: false\n            readOnlyRootFilesystem: true\n            capabilities:\n              drop:\n                - ALL\n          resources:\n            requests:\n              cpu: \"250m\"\n              memory: \"256Mi\"\n            limits:\n              cpu: \"1\"\n              memory: \"512Mi\"\n          volumeMounts:\n            - name: tmp\n              mountPath: \u002Ftmp\n      volumes:\n        - name: tmp\n          emptyDir:\n            medium: Memory\n",[46,3522,3523,3531,3539,3545,3553,3559,3569,3576,3583,3592,3598,3605,3612,3621,3627,3633,3643,3651,3657,3666,3675,3684,3690,3696,3702,3709,3716,3726,3735,3742,3750,3758,3765,3777,3787,3795,3806,3814],{"__ignoreMap":356},[360,3524,3525,3527,3529],{"class":362,"line":363},[360,3526,1058],{"class":366},[360,3528,380],{"class":370},[360,3530,1063],{"class":643},[360,3532,3533,3535,3537],{"class":362,"line":374},[360,3534,1068],{"class":366},[360,3536,380],{"class":370},[360,3538,1073],{"class":643},[360,3540,3541,3543],{"class":362,"line":667},[360,3542,1078],{"class":366},[360,3544,371],{"class":370},[360,3546,3547,3549,3551],{"class":362,"line":673},[360,3548,1085],{"class":366},[360,3550,380],{"class":370},[360,3552,1090],{"class":643},[360,3554,3555,3557],{"class":362,"line":1036},[360,3556,1095],{"class":366},[360,3558,371],{"class":370},[360,3560,3561,3564,3566],{"class":362,"line":1100},[360,3562,3563],{"class":366},"  replicas",[360,3565,380],{"class":370},[360,3567,3568],{"class":383}," 1\n",[360,3570,3571,3574],{"class":362,"line":1108},[360,3572,3573],{"class":366},"  selector",[360,3575,371],{"class":370},[360,3577,3578,3581],{"class":362,"line":1116},[360,3579,3580],{"class":366},"    matchLabels",[360,3582,371],{"class":370},[360,3584,3585,3588,3590],{"class":362,"line":1124},[360,3586,3587],{"class":366},"      app",[360,3589,380],{"class":370},[360,3591,1090],{"class":643},[360,3593,3594,3596],{"class":362,"line":1137},[360,3595,1103],{"class":366},[360,3597,371],{"class":370},[360,3599,3600,3603],{"class":362,"line":1147},[360,3601,3602],{"class":366},"    metadata",[360,3604,371],{"class":370},[360,3606,3607,3610],{"class":362,"line":1155},[360,3608,3609],{"class":366},"      labels",[360,3611,371],{"class":370},[360,3613,3614,3617,3619],{"class":362,"line":1163},[360,3615,3616],{"class":366},"        app",[360,3618,380],{"class":370},[360,3620,1090],{"class":643},[360,3622,3623,3625],{"class":362,"line":1171},[360,3624,1111],{"class":366},[360,3626,371],{"class":370},[360,3628,3629,3631],{"class":362,"line":1364},[360,3630,1119],{"class":366},[360,3632,371],{"class":370},[360,3634,3635,3637,3639,3641],{"class":362,"line":1372},[360,3636,1127],{"class":1039},[360,3638,1130],{"class":366},[360,3640,380],{"class":370},[360,3642,1090],{"class":643},[360,3644,3645,3647,3649],{"class":362,"line":3193},[360,3646,1140],{"class":366},[360,3648,380],{"class":370},[360,3650,1026],{"class":643},[360,3652,3653,3655],{"class":362,"line":3203},[360,3654,1150],{"class":366},[360,3656,371],{"class":370},[360,3658,3659,3662,3664],{"class":362,"line":3212},[360,3660,3661],{"class":366},"            runAsNonRoot",[360,3663,380],{"class":370},[360,3665,384],{"class":383},[360,3667,3668,3671,3673],{"class":362,"line":3223},[360,3669,3670],{"class":366},"            allowPrivilegeEscalation",[360,3672,380],{"class":370},[360,3674,1916],{"class":383},[360,3676,3677,3680,3682],{"class":362,"line":3230},[360,3678,3679],{"class":366},"            readOnlyRootFilesystem",[360,3681,380],{"class":370},[360,3683,384],{"class":383},[360,3685,3686,3688],{"class":362,"line":3240},[360,3687,1158],{"class":366},[360,3689,371],{"class":370},[360,3691,3692,3694],{"class":362,"line":3250},[360,3693,1166],{"class":366},[360,3695,371],{"class":370},[360,3697,3698,3700],{"class":362,"line":3259},[360,3699,1174],{"class":1039},[360,3701,1043],{"class":643},[360,3703,3704,3707],{"class":362,"line":3268},[360,3705,3706],{"class":366},"          resources",[360,3708,371],{"class":370},[360,3710,3711,3714],{"class":362,"line":3279},[360,3712,3713],{"class":366},"            requests",[360,3715,371],{"class":370},[360,3717,3718,3721,3723],{"class":362,"line":3472},[360,3719,3720],{"class":366},"              cpu",[360,3722,380],{"class":370},[360,3724,3725],{"class":643}," \"250m\"\n",[360,3727,3728,3731,3733],{"class":362,"line":3479},[360,3729,3730],{"class":366},"              memory",[360,3732,380],{"class":370},[360,3734,2577],{"class":643},[360,3736,3737,3740],{"class":362,"line":3486},[360,3738,3739],{"class":366},"            limits",[360,3741,371],{"class":370},[360,3743,3744,3746,3748],{"class":362,"line":3493},[360,3745,3720],{"class":366},[360,3747,380],{"class":370},[360,3749,2760],{"class":643},[360,3751,3752,3754,3756],{"class":362,"line":3500},[360,3753,3730],{"class":366},[360,3755,380],{"class":370},[360,3757,2593],{"class":643},[360,3759,3760,3763],{"class":362,"line":3507},[360,3761,3762],{"class":366},"          volumeMounts",[360,3764,371],{"class":370},[360,3766,3768,3771,3773,3775],{"class":362,"line":3767},33,[360,3769,3770],{"class":1039},"            -",[360,3772,1130],{"class":366},[360,3774,380],{"class":370},[360,3776,1655],{"class":643},[360,3778,3780,3783,3785],{"class":362,"line":3779},34,[360,3781,3782],{"class":366},"              mountPath",[360,3784,380],{"class":370},[360,3786,1627],{"class":643},[360,3788,3790,3793],{"class":362,"line":3789},35,[360,3791,3792],{"class":366},"      volumes",[360,3794,371],{"class":370},[360,3796,3798,3800,3802,3804],{"class":362,"line":3797},36,[360,3799,1127],{"class":1039},[360,3801,1130],{"class":366},[360,3803,380],{"class":370},[360,3805,1655],{"class":643},[360,3807,3809,3812],{"class":362,"line":3808},37,[360,3810,3811],{"class":366},"          emptyDir",[360,3813,371],{"class":370},[360,3815,3817,3820,3822],{"class":362,"line":3816},38,[360,3818,3819],{"class":366},"            medium",[360,3821,380],{"class":370},[360,3823,1672],{"class":643},[20,3825,3826],{},"این مثال‌ها برای کپی شدن مستقیم در هر محیط تولیدی نیستند - هر بار کاری نیازهای متفاوتی دارد. در عوض، ذهنیت امنیتی را نشان می‌دهند که در سراسر مقاله دنبال کردیم: امتیازاتی را که نیاز ندارید حذف کنید، فقط منابعی را که برنامه واقعاً نیاز دارد expose کنید، و فرض کنید برنامه ممکن است روزی به خطر بیفتد.",[16,3828,3830],{"id":3829},"نتیجهگیری","نتیجه‌گیری",[20,3832,3833,3834,3836],{},"امنیت داکر دفاع در عمق است، نه یک گلوله نقره‌ای. کاربران غیرروت، قابلیت‌ها، فایل‌سیستم‌های فقط‌خواندنی، ",[46,3835,1809],{},"، seccomp، LSMها، cgroupها و محدودیت‌های دستگاه - هر کدام بخشی از سطح حمله را حذف می‌کنند. هر کدام به تنهایی مفیدند، اما با هم کار پس از بهره‌برداری را به شدت دشوارتر می‌کنند.",[20,3838,3839],{},"داکر جلوی به خطر افتادن برنامه شما را نمی‌گیرد. کاری که می‌کند این است که محدود می‌کند مهاجم بعد از ورود چه کارهایی می‌تواند بکند. و این تمایز مهم است. هر مجوز غیرضروری، دایرکتوری قابل نوشتن یا دستگاه expose شده، فرصتی است که لازم نبود بدهید.",[20,3841,3842],{},"امنیت درباره غیرممکن کردن نفوذ نیست. درباره این است که وقتی اتفاق افتاد، مهاجم تا جایی که ممکن است گزینه‌های کمی داشته باشد.",[3844,3845],"hr",{},[20,3847,3848],{},[3849,3850,3851],"em",{},"این مقاله روی مکانیزم‌های امنیتی زمان اجرای داکر متمرکز بود. اگر وقت کنم، ممکن است مقالات بعدی درباره امنیت زنجیره تأمین، مدیریت اسرار، سیاست‌های شبکه و تشخیص زمان اجرا بنویسم.",[3853,3854,3855],"style",{},"html pre.shiki code .si09J, html code.shiki .si09J{--shiki-light:#89B4FA;--shiki-default:#89B4FA;--shiki-dark:#89B4FA}html pre.shiki code .sG44b, html code.shiki .sG44b{--shiki-light:#94E2D5;--shiki-default:#94E2D5;--shiki-dark:#94E2D5}html pre.shiki code .srg_i, html code.shiki .srg_i{--shiki-light:#FAB387;--shiki-default:#FAB387;--shiki-dark:#FAB387}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .seEE7, html code.shiki .seEE7{--shiki-light:#89B4FA;--shiki-light-font-style:italic;--shiki-default:#89B4FA;--shiki-default-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic}html pre.shiki code .swpoh, html code.shiki .swpoh{--shiki-light:#A6E3A1;--shiki-default:#A6E3A1;--shiki-dark:#A6E3A1}html pre.shiki code .seFKw, html code.shiki .seFKw{--shiki-light:#F5C2E7;--shiki-default:#F5C2E7;--shiki-dark:#F5C2E7}html pre.shiki code .sKAjW, html code.shiki .sKAjW{--shiki-light:#9399B2;--shiki-default:#9399B2;--shiki-dark:#9399B2}",{"title":356,"searchDepth":374,"depth":374,"links":3857},[3858,3859,3860,3862,3863,3864,3865,3867,3869,3871,3873,3874,3875,3877,3878,3879,3880,3882,3884,3886,3887,3888,3889,3890,3891,3892,3893,3894,3896,3898,3899,3901,3902,3904,3905,3906,3907],{"id":141,"depth":374,"text":142},{"id":304,"depth":374,"text":305},{"id":341,"depth":374,"text":3861},"چرا کوبرنتیز runAsNonRoot را توصیه می‌کند",{"id":390,"depth":374,"text":391},{"id":499,"depth":374,"text":500},{"id":606,"depth":374,"text":607},{"id":700,"depth":374,"text":3866},"حذف قابلیت‌ها با --cap-drop",{"id":816,"depth":374,"text":3868},"افزودن قابلیت‌ها با --cap-add",{"id":877,"depth":374,"text":3870},"چرا CAP_SYS_ADMIN «روت جدید» نامیده می‌شود",{"id":935,"depth":374,"text":3872},"CAP_NET_ADMIN: قدرتمندتر از چیزی که به نظر می‌رسد",{"id":976,"depth":374,"text":977},{"id":1483,"depth":374,"text":1484},{"id":1516,"depth":374,"text":3876},"ذخیره‌سازی موقت با tmpfs",{"id":1730,"depth":374,"text":1731},{"id":1762,"depth":374,"text":1763},{"id":1789,"depth":374,"text":1790},{"id":1925,"depth":374,"text":3881},"درک setuid",{"id":1972,"depth":374,"text":3883},"قابلیت‌های فایل (setcap)",{"id":2012,"depth":374,"text":3885},"نقش execve()",{"id":2045,"depth":374,"text":2046},{"id":2144,"depth":374,"text":2145},{"id":2160,"depth":374,"text":2161},{"id":2196,"depth":374,"text":2197},{"id":2209,"depth":374,"text":2210},{"id":2246,"depth":374,"text":2247},{"id":2263,"depth":374,"text":2264},{"id":2280,"depth":374,"text":2281},{"id":2347,"depth":374,"text":3895},"گروه docker معادل روت است",{"id":2393,"depth":374,"text":3897},"mount کردن \u002Fvar\u002Frun\u002Fdocker.sock به داخل کانتینر",{"id":2479,"depth":374,"text":2480},{"id":2599,"depth":374,"text":3900},"محدودیت فرآیند (pids_limit)",{"id":2650,"depth":374,"text":2651},{"id":2930,"depth":374,"text":3903},"--privileged واقعاً چه کار می‌کند",{"id":2945,"depth":374,"text":2946},{"id":640,"depth":374,"text":3043},{"id":3285,"depth":374,"text":3288},{"id":3514,"depth":374,"text":3517},1783032848276]