یک مشکل رایج برنامه‌نویسی در برخی نسخه‌های OpenSSL 1.0.2 و OpenSSL 1.0.1 وجود دارد که در واقع متکی بر استفاده از اشاره‌گر محاسباتی تعریف نشده در مشخصات C است. در واقع استفاده کردن نادرست از اشاره‌گرهای محاسباتی به منظور چک کردن محدوده heap-buffer در OpenSSL علت این مشکل است که این آسیب‌پذیری ممکن است موجب حملات DoS توسط مهاجمین شود. لازم به ذکر است که این مشکل در نسخه‌های OpenSSL 1.0.1u و OpenSSL 1.0.2i برطرف شده است.

۱    میزان تأثیر آسیب‌پذیری CVE-2016-2177

۱-۱    جدول تأثیر آسیب‌پذیری بر اساس شاخص شدت و معیارهای CVSS نسخه ۲ [۱]

CVE-2016-2177

۲-۱ جدول تأثیر آسیب‌پذیری بر اساس شاخص شدت و معیارهای CVSS نسخه ۳ [۱]

CVSS

۲    تحلیل آسیب‌پذیری CVE-2016-2177

OpenSSL از اشاره‌گرهای محاسباتی به صورت نادرست برای چک کردن محدوده heap-buffer استفاده می‌کند، که این امر ممکن است به مهاجمین راه دور اجازه دهد تا باعث یک حمله DoS (سرریز عدد صحیح و crash شدن نرم‌افزار) شوند یا ممکن است تأثیرات نامشخص دیگری توسط رفتار malloc داشته باشند[۲].

این مورد توسط Guido Vranken در چهارم می ۲۰۱۶ گزارش شده است.

  • این مشکل در OpenSSL 1.0.1u برطرف شده است، اما نسخه‌های زیر آسیب‌پذیرند:

۱٫۰٫۱t, 1.0.1s, 1.0.1r, 1.0.1q, 1.0.1p, 1.0.1o, 1.0.1n, 1.0.1m, 1.0.1l, 1.0.1k, 1.0.1j, 1.0.1i, 1.0.1h, 1.0.1g, 1.0.1f, 1.0.1e, 1.0.1d, 1.0.1c, 1.0.1b, 1.0.1a, 1.0.1

  • این مشکل در OpenSSL 1.0.2i برطرف شده است، اما نسخه‌های زیر آسیب‌پذیرند:

۱٫۰٫۲h, 1.0.2g, 1.0.2f, 1.0.2e, 1.0.2d, 1.0.2c, 1.0.2b, 1.0.2a, 1.0.2

در تصدیق مشکلات بیان شده، مواردی برای برطرف کردن مشکلات CVE-2016-2177 انتشار یافته است. یک مشکل رایج برنامه‌نویسی در OpenSSL 1.0.2 و OpenSSL 1.0.1 وجود دارد که در واقع متکی بر استفاده از اشاره‌گر محاسباتی تعریف نشده در مشخصات C است. در انتشار نسخه جدید، این مشکل برطرف شده است. این استفاده می‌تواند منجر به یک موضوع امنیتی با شدت پایین در برخی حالات خاص شود. سیاست‌های امنیتی OpenSSL بیان می‌کند [۳] که موضوعات با شدت امنیتی پایین به صورت عمومی بیان خواهد شد و همچنین نسخه جدید انتشار خواهد یافت. در ادامه این گزارش، این مشکل را همراه با جزئیات توضیح می‌دهیم. در واقع سناریوهایی که یک موضوع امنیتی می‌تواند رخ دهد و چرا این موضوع به عنوان شدت پایین در نظر گرفته شده است را شرح می‌دهیم.

در اصطلاح برنامه‌نویسی، در مورد این قسمت می‌خواهیم بحث کنیم:

که ‘P’ اشاره دارد به داده تخصیص داده شده(۱) از بایت ‘SIZE’ و ‘Limit == P + SIZE’ است. در اینجا مقدار ‘len’ از جاهای خارجی مثل یک پیام TLS، عرضه می‌شود.

ایده کار این است که طول داده عرضه شده را بررسی کنیم و مطمئن شویم که ‘len’ به درستی در چارچوب مربوطه قرار می‌گیرد. مشکل این است که این اشاره‌گر محاسباتی تنها توسط استاندارد C90 تعریف شده است، اگر ‘len <= SIZE’ باشد و همچنین اگر ‘len’ خیلی بزرگ است پس این یک رفتار تعریف نشده است و به صورت تئوری هر چیزی ممکن است رخ دهد. در عمل آن معمولاً مطابق چیزی که انتظار می‌رود کار می‌کند و به جز در مواردی که یک سرریز رخ می‌دهد، مسئله‌ای ندارد.

به منظور رخ دادن یک سرریز، مقدار ‘P + len’ باید به اندازه کافی بزرگ باشد تا از حداکثر فضای قابل آدرس‌دهی تجاوز کند. توجه داشته باشید که با توجه به مطالبی که در بالا بیان شد، مقدار ‘len’ می‌تواند از داده‌های خارجی مثل یک پیام TLS مقداردهی شود.

اکثر معماری‌ها، در لبه‌ی حافظه بالا(۲)، حافظه heap را ندارند. به‌طورمعمول:

و اغلب (روی سیستم‌هایی با یک فضای آدرس کاربر/هسته یکپارچه):

دو مکان اصلی وجود دارند که در آن‌ها ۲ بایت len می‌تواند مسئله‌ساز باشد. محل اول در زمان خواندن در دنباله‌های رمز(۳) در ClientHello است و محل دوم در زمان خواندن در افزونه‌ها(۴) در ClientHello است.

در اینجا کد مربوط به دنباله رمزنگاری قبل از انجام وصله امنیتی را مشاهده می‌کنید:

در اینجا مقدار i نشان‌دهنده طول دو بایت خوانده شده (از peer) است و p اشاره‌گر به بافر و d+n انتهای بافر است. اگر p+i+1 سرریز کند، سپس ارسال یک مقدار i بیش از حد بزرگ به تابع ssl_bytes_to_cipher_list() به پایان خواهد رسید.

به نظر می‌رسد که تنها راهی که دو مورد بالا می‌تواند مورد بهره‌برداری قرار گیرد از طریق DoS است.

با توجه به تمام این موارد، نکته مهم این است که چه مقدار از موارد بیان شده تحت کنترل مهاجم است. واضح است که len می‌تواند این‌طور باشد ولی مقدار p این‌طور نیست.

به نظر می‌رسد که چنین حملاتی درحالی‌که امکان دارد رخ بدهد، ولی مشکل است تا با موفقیت انجام شود. با توجه به دشواری حمله و تأثیر نسبتاً کمی که دارد، این حمله به صورت موضوعی با شدت پایین در نظر گرفته شده است.

۲    ایمن‌سازی OpenSSL

در ادامه، قسمتی از تغییرات مربوطه به منظور ایمن‌سازی OpenSSL را بیان می‌کنیم که برای مشاهده تغییرات کامل ‌‌می‌توانید به [۴] مراجعه کنید. قسمت‌هایی از کد که با رنگ قرمز مشخص شده‌اند باید حذف شوند و قسمت‌های سبز رنگ جایگزین شوند.

۱-۲ ایمن‌سازی مربوط به فایل ssl/s3_srvr.c

۲-۲    ایمن‌سازی مربوط به فایل ssl/ssl_sess.c

منابع

[۱] https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-2177

[۲] https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-2177

[۳] https://www.openssl.org/policies/secpolicy.html

[۴] https://github.com/openssl/openssl/commit/a004e72b95835136d3f1ea90517f706c24c03da7

[۵] https://www.openssl.org/news/vulnerabilities.html#y2016

[۶] https://www.openssl.org/blog/blog/2016/06/27/undefined-pointer-arithmetic/


(۱) malloc’d data
(۲) edge of high memory
(۳) ciphersuites
(۴) extensions