توزیع سیستم عامل منبع باز OpenBSD در بین sysadmin ها، به ویژه آنهایی که سرورها را مدیریت می کنند، به دلیل تمرکز بر امنیت بیش از سرعت، ویژگی ها و قسمت های جلویی فانتزی معروف است.
شاید به درستی، لوگوی آن یک ماهی پف کرده باشد - باد کرده، با سنبله هایش آماده دفع هر هکر حیله گری که ممکن است وارد شود.
اما تیم OpenBSD احتمالاً نه به خاطر کل توزیعش، بلکه به خاطر جعبه ابزار دسترسی از راه دور شناخته شده است OpenSSH که در اواخر دهه 1990 برای گنجاندن در خود سیستم عامل نوشته شد.
SSH، کوتاه شده برای پوسته امن، در اصل توسط دانشمند کامپیوتر فنلاندی ساخته شد تاتو یلونن در اواسط دهه 1990 به این امید که sysadmin ها را از عادت خطرناک استفاده از پروتکل Telnet کنار بگذارند.
مشکل با Telnet
Telnet بسیار ساده و موثر بود: به جای اتصال سیم های فیزیکی (یا استفاده از یک مودم از طریق خط تلفن) برای ایجاد اتصال تله تایپ به سرورهای راه دور، به جای آن از اتصال TELetype NETwork استفاده کردید.
اساساً، دادههایی که معمولاً از طریق یک اتصال سریال اختصاصی یا خط تلفن Dial-Up جریان مییابند، از طریق اینترنت ارسال و دریافت میشوند، با استفاده از اتصال شبکه TCP سوئیچ بسته به جای پیوند نقطهبهنقطه با سوئیچ مدار. .
همان سیستم ورود آشنا، اتصالات ارزان تر، بدون نیاز به خطوط داده اختصاصی!
عیب بزرگ Telnet، البته، عدم رمزگذاری کامل آن بود، به طوری که شناسایی دقیق جلسه ترمینال شما بی اهمیت بود، و به کرکرها اجازه می داد هر دستوری را که تایپ می کنید (حتی اشتباهاتی که مرتکب شده اید و تمام دفعاتی که ضربه می زنید) ببینند. [Backspace]
و هر بایت خروجی تولید شده…
...و البته نام کاربری و رمز عبور شما در ابتدای جلسه.
هر کسی در مسیر شبکه شما نه تنها می تواند به راحتی جلسات sysadmin شما را در زمان واقعی در صفحه شخصی خود بازسازی کند، بلکه احتمالاً با تغییر دستوراتی که به سرور راه دور ارسال کرده اید و جعل کردن پاسخ های برگشتی به طوری که متوجه نشوید، جلسه شما را نیز دستکاری کند. مزاحمت
آنها حتی می توانند یک سرور تقلبی راه اندازی کنند، شما را به سمت آن فریب دهند و تشخیص فریب را برای شما به طرز شگفت انگیزی دشوار کنند.
رمزگذاری قوی FTW
هدف SSH Ylönen اضافه کردن یک لایه رمزگذاری و احراز هویت قوی به هر انتهای یک جلسه شبکه راه دور بود که یک پوسته امن (اگر تا به حال فکر کرده اید این نام مخفف آن است، اگرچه تقریباً همه فقط آن را صدا می کنند ess-ess-aitch این روزها).
این یک موفقیت فوری بود و پروتکل به سرعت توسط sysadmin ها در همه جا پذیرفته شد.
همانطور که در بالا ذکر کردیم OpenSSH به زودی دنبال شد و اولین بار در اواخر سال 1999 به عنوان بخشی از آن ظاهر شد OpenBSD 2.6 را آزاد کند.
تیم OpenBSD می خواست یک پیاده سازی رایگان، قابل اعتماد و منبع باز از پروتکلی که آنها و هر کس دیگری می تواند استفاده کندبدون هیچ یک از پیچیدگیهای مجوز یا تجاری که اجرای اصلی Ylönen را در سالهای بلافاصله پس از انتشار آن سخت کرده بود.
در واقع، اگر سرور SSH ویندوز را اجرا کنید و در حال حاضر از طریق یک رایانه لینوکس به آن متصل شوید، تقریباً مطمئناً در هر دو طرف به اجرای OpenSSH متکی خواهید بود.
پروتکل SSH همچنین در سایر سرویس های سرویس گیرنده-سرور محبوب از جمله SCP و SFTP به اختصار استفاده می شود کپی امن و FTP امن به ترتیب. SSH آزادانه به این معنی است که "به طور ایمن متصل شوید و یک دستور SHell را در انتهای دیگر اجرا کنید"، معمولاً برای ورود به سیستم تعاملی، زیرا برنامه Unix برای پوسته فرمان معمولاً /bin/sh
. SCP مشابه است، اما برای فایل های CoPying، زیرا دستور Unix file-copy به طور کلی فراخوانی می شود /bin/cp
و SFTP تقریباً به همین صورت نامگذاری شده است.
OpenSSH تنها ابزار SSH در شهر نیست.
سایر پیاده سازی های شناخته شده عبارتند از: libssh2، برای توسعه دهندگانی که می خواهند پشتیبانی SSH را مستقیماً در برنامه های خود ایجاد کنند. قطره قطره، یک سرور SSH حذف شده از کدگذار استرالیایی مت جانستون که به طور گسترده در دستگاه های به اصطلاح IoT (اینترنت اشیا) مانند روترها و چاپگرهای خانگی یافت می شود. و توله سگ، مجموعه ای محبوب و رایگان از ابزارهای مربوط به SSH برای ویندوز از توسعه دهنده منبع باز مستقل سیمون تاتهام در انگلستان.
اما اگر یک کاربر معمولی SSH هستید، تقریباً مطمئناً امروز حداقل به یک سرور OpenSSH متصل شده اید، به ویژه به این دلیل که اکثر توزیع های لینوکس امروزی آن را به عنوان ابزار دسترسی از راه دور استاندارد خود درج می کنند، و مایکروسافت هم یک کلاینت OpenSSH و هم OpenSSH ارائه می دهد. سرور به عنوان اجزای رسمی ویندوز این روزها.
رفع اشکال دوبار رایگان
OpenSSH نسخه 9.2 فقط بیرون آمد، و یادداشت های انتشار به شرح زیر گزارش دهید:
این نسخه حاوی راه حل هایی برای […] مشکل ایمنی حافظه است. اعتقاد بر این است که [این باگ] قابل بهره برداری نیست، اما ما اکثر خطاهای حافظه قابل دسترسی شبکه را به عنوان اشکالات امنیتی گزارش می کنیم.
اشکال تاثیر می گذارد sshd
، سرور OpenSSH (the -d
پسوند مخفف روح پلید، نام یونیکس برای نوع فرآیند پسزمینهای که ویندوز a مینامد سرویس):
sshd(8): یک خطای حافظه دوگانه آزاد پیش از احراز هویت معرفی شده در OpenSSH 9.1 را برطرف کنید. اعتقاد بر این است که این قابل بهرهبرداری نیست، و در فرآیند پیشتأیید غیرمجاز که مشمول chroot(2) است و بیشتر در اکثر پلتفرمهای اصلی سندباکس میشود، رخ میدهد.
یک اشکال مضاعف به این معنی است که یک بلوک حافظه که قبلاً به سیستم عامل برگردانده اید تا در قسمت های دیگر برنامه شما دوباره استفاده شود…
… بعداً توسط بخشی از برنامه که دیگر در واقع «مالک» آن حافظه نیست، اما نمیداند که ندارد، دوباره تحویل داده میشود.
(یا عمداً در صورت درخواست کدی که سعی دارد عمداً باگ را تحریک کند به منظور ایجاد یک آسیب پذیری به یک بهره برداری.)
این می تواند منجر به باگ های ظریف و دشوار شود، به خصوص اگر سیستم بلوک آزاد شده را در اولین بار در دسترس قرار دهد. free()
اتفاق می افتد، بعداً وقتی از طریق کد شما درخواست حافظه می کند، آن را به قسمت دیگری از کد شما اختصاص می دهد malloc(
) و سپس در هنگام فراخوانی اضافی بلوک را یک بار دیگر علامت گذاری می کند free()
ظاهر می شود.
این شما را در موقعیتی قرار می دهد که هنگام ورود به هتلی تجربه می کنید که می گوید: «اوه، خبر خوب! ما فکر میکردیم که پر شدهایم، اما یک مهمان دیگر تصمیم گرفت زودتر چک کند تا شما بتوانید اتاقش را داشته باشید.»
حتی اگر وقتی وارد میشوید اتاق بهخوبی تمیز شده و برای ساکنان جدید آماده شده باشد، و به نظر میرسد که به درستی برای استفاده انحصاری شما اختصاص داده شده است، باید مطمئن باشید که کارت کلید مهمان قبلی واقعاً به درستی لغو شده است و آنها تسویهحساب زودهنگام» حقهای حیلهگر نبود که بعداً همان روز دزدکی به عقب برگردید و لپتاپتان را بدزدید.
رفع اشکال برای رفع اشکال
از قضا، اگر به تاریخچه کدهای OpenSSH اخیر نگاه کنید، خواهید دید که OpenSSH یک باگ متوسط در تابعی به نام دارد. compat_kex_proposal()
، برای بررسی اینکه از چه نوع الگوریتم تبادل کلید هنگام تنظیم یک اتصال استفاده شود استفاده می شود.
اما رفع آن اشکال ساده آسیب پذیری شدیدتری را به جای آن معرفی کرد.
به هر حال، وجود باگ در بخشی از نرم افزار که در هنگام راه اندازی یک اتصال استفاده می شود، چیزی است که این را به اصطلاح احراز هویت پیش از شبکه قابل دسترسی آسیب پذیری (یا اشکال پیش تأیید به طور خلاصه)
اشکال مضاعف در کدی که باید اجرا شود اتفاق می افتد بعد از یک مشتری یک جلسه از راه دور را راه اندازی کرده است، اما قبل از هر گونه توافق نامه یا احراز هویت انجام شده است، بنابراین آسیب پذیری می تواند، در تئوری، قبل از ارائه هر گونه رمز عبور یا کلید رمزنگاری برای تأیید اعتبار، فعال شود.
در OpenSSH 9.0، compat_kex_proposal
چیزی شبیه به این بود (در اینجا بسیار ساده شده):
char* compat_kex_proposal(char* suggestion) { if (condition1) { return suggestion; } if (condition2) { suggestion = allocatenewstring1(); } if (condition3) { suggestion = allocatenewstring2(); } if (isblank(suggestion)) { error(); } return suggestion; }
ایده این است که تماسگیرنده در بلوک حافظه خود حاوی یک رشته متنی که تنظیمات تبادل کلید را پیشنهاد میکند، ارسال میکند و یا تأییدیه استفاده از همان پیشنهادی را که در آن ارسال کرده است، دریافت میکند، یا یک رشته متن جدید اختصاص داده شده با یک پیشنهاد بهروز شده را دریافت میکند. .
اشکال این است که اگر شرط 1 نادرست باشد اما شرایط 2 و 3 هر دو درست باشند، کد تخصیص می دهد دو رشته های متن جدید، اما فقط برمی گردد یک.
بلوک حافظه اختصاص داده شده توسط allocatenewstring1()
هرگز آزاد نمی شود و وقتی تابع برمی گردد، آدرس حافظه آن برای همیشه از بین می رود، بنابراین هیچ کدی برای free()
آن را در آینده
این بلوک اساساً رها شده است و باعث ایجاد چیزی می شود که به عنوان a شناخته می شود نشت حافظه.
با گذشت زمان، این می تواند باعث ایجاد مشکل شود، شاید حتی سرور را مجبور به خاموش شدن برای بازیابی از اضافه بار حافظه کند.
در OpenSSH 9.1، کد در تلاشی برای جلوگیری از تخصیص دو رشته اما کنار گذاشتن یکی از آنها به روز شد:
/* Always returns pointer to allocated memory, caller must free. */ char* compat_kex_proposal(char* suggestion){ char* previousone = NULL; if (condition1) { return newcopyof(suggestion); } if (condition2) { suggestion = allocatenewstring1(); } if (condition3) { previousone = suggestion; suggestion = allocatenewstring2(); } free(previousone); } if (isblank(suggestion()) { error(); } return suggestion; }
این دارای یک اشکال دوگانه رایگان است، زیرا اگر شرط 1 و شرط 2 هر دو نادرست باشند، اما شرط 3 درست باشد، کد یک رشته جدید را برای ارسال به عنوان پاسخ خود اختصاص می دهد.
... اما به اشتباه رشته ای را که تماس گیرنده در ابتدا ارسال کرده بود آزاد می کند، زیرا تابع allocatenewstring1()
هرگز برای به روز رسانی متغیر فراخوانی نمی شود suggestion
.
رشته پیشنهاد تصویب شده حافظه ای است که متعلق به تماس گیرنده است، و بنابراین تماس گیرنده بعداً مضامین را آزاد می کند که منجر به خطر مضاعف می شود.
در OpenSSH 9.2، کد محتاطانه تر شده است و هر سه بلوک حافظه ممکن استفاده شده را دنبال می کند: نسخه اصلی. suggestion
(حافظه متعلق به شخص دیگری)، و دو رشته جدید احتمالی که ممکن است در راه تخصیص داده شوند:
/* Always returns pointer to allocated memory, caller must free. */ char* compat_kex_proposal(char* suggestion) { char* newone = NULL; char* newtwo = NULL; if (condition1) { return newcopyof(suggestion); } if (condition2) { newone = allocatenewstring1(); } if (condition3) { newtwo = allocatenewstring2(); } free(newone); newone = newtwo; } if (isblank(newone)) { error(); } return newone; }
اگر شرط 1 درست باشد، یک کپی جدید از رشته ارسال شده استفاده می شود، بنابراین تماس گیرنده می تواند بعداً free()
هر زمان که دوست داشته باشند، خاطره رشته انتقال یافته آنها
اگر شرط 1 را پشت سر بگذاریم و شرط 2 درست است اما شرط 3 نادرست است، پیشنهاد جایگزین ایجاد شده توسط allocatenewstring1()
بازگردانده می شود، و گذشت در suggestion
رشته تنها مانده است
اگر شرط 2 نادرست و شرط 3 درست باشد، رشته جدیدی تولید می شود و برگردانده می شود و رمز عبور داده شده suggestion
رشته تنها مانده است
اگر هر دو شرط 2 و شرط 3 درست باشند، در این مسیر دو رشته جدید تخصیص داده می شود. اولین مورد آزاد می شود زیرا به آن نیازی نیست. دومی برگردانده می شود. و گذشت در suggestion
رشته تنها مانده است
تو می توانی RTxM برای تایید که اگر تماس بگیرید free(newone)
چه زمانی newone
is NULL
، سپس "هیچ عملیاتی انجام نمی شود"، زیرا همیشه ایمن است free(NULL)
. با این وجود، بسیاری از برنامه نویسان هنوز با کدهایی مانند if (ptr != NULL) { free(ptr); }
.
چه کاری انجام دهید؟
همانطور که تیم OpenSSH پیشنهاد می کند، بهره برداری از این باگ سخت خواهد بود، به ویژه به دلیل امتیازات محدودی که sshd
برنامه در حالی که در حال تنظیم اتصال برای استفاده است.
با این وجود، آنها آن را به عنوان یک حفره امنیتی گزارش کردند زیرا این همان چیزی است که وجود دارد، بنابراین مطمئن شوید که به روز رسانی کرده اید OpenSSH 9.2.
و اگر در حال نوشتن کد به زبان C هستید، به یاد داشته باشید که مهم نیست که چقدر تجربه دارید، مدیریت حافظه به راحتی اشتباه می شود…
… پس مراقب باشید.
(بله، Rust و دوستان مدرنش این کار را خواهند کرد به شما در نوشتن کد صحیح کمک می کند، اما گاهی اوقات شما همچنان نیاز به استفاده از C دارید، و حتی Rust نیز نمی تواند این کار را تضمین کند از نوشتن کد نادرست جلوگیری کنید اگر برنامهریزی کنید بیمعنا!)
- محتوای مبتنی بر SEO و توزیع روابط عمومی. امروز تقویت شوید.
- پلاتوبلاک چین. Web3 Metaverse Intelligence. دانش تقویت شده دسترسی به اینجا.
- منبع: https://nakedsecurity.sophos.com/2023/02/03/openssh-fixes-double-free-memory-bug-thats-pokable-over-the-network/