آسیب‌پذیری اجرای کد از راه دور Spring Framework (Spring4Shell)

  • شناسه: CVE-2022-22965
  • امتیاز: ۹.۸ (از ۱۰)
  • درجه خطر: بحرانی
  • نوع آسیب‌پذیری: اجرای کد از راه دور
  • نوع خطا: خطای binding پارامترها در متد getCachedIntrospectionResults

توضیحات فنی

 

Spring Core در نسخه‌های بعد از JDK9، نسبت به یک ضعف امنیتی که ریشه آن به یک آسیب‌پذیری قدیمی با شناسه CVE-2010-1622 بر می‌گردد و در حال حاضر راهکار ارائه شده در آن زمان ByPass شده است، در برابر اجرای کد از راه دور آسیب‌پذیر است.

Spring Core یک فریمورک جاوا بسیار محبوب برای ساخت برنامه‌های کاربردی وب مدرن جاوا است.

در پیکربندی‌های خاص، سوءاستفاده از این آسیب‌پذیری ساده است، زیرا مهاجم تنها نیاز دارد تا یک درخواست HTTP دست‌ساز را به یک سیستم آسیب‌پذیر ارسال کند. با این حال، در پیکربندی‌های دیگر، جهت سوءاستفاده از آسیب‌پذیری، مهاجم ملزم به انجام تحقیقات بیشتری برای یافتن راه‌های موثر می‌باشد.

بهره‌برداری به یک نقطه پایانی با فعال بودن DataBinder نیاز دارد (مثلاً یک درخواست POST که داده‌ها را از بدنه درخواست به طور خودکار رمزگشایی می‌کند) و به شدت به محفظه servlet برای برنامه بستگی دارد. به عنوان مثال، هنگامی که Spring در آپاچی تامکت مستقر می‌شود، WebAppClassLoader قابل دسترسی است، که به مهاجم اجازه می‌دهد تا getter و setter را فراخوانی کند تا در نهایت یک فایل JSP مخرب را روی دیسک بنویسد. با این حال، اگر Spring با استفاده از Embedded Tomcat Servlet Container مستقر شود، کلاس لودر یک LaunchedURLClassLoader است که دسترسی محدودی دارد.

این آسیب‌پذیری بر برنامه‌های Spring MVC و Spring WebFlux که روی JDK 9+ اجرا می‌شوند، تأثیر می‌گذارد. پیکربندی خاص جهت سوءاستفاده از آسیب‌پذیری نیاز به استقرار اپلیکیشن در یک پکیج WAR و اجرا تحت Tomcat دارد. اگر برنامه به عنوان یک jar اجرایی Spring Boot، یعنی حالت پیش‌فرض، مستقر شده باشد، در برابر اکسپلویت آسیب‌پذیر نیست. با این حال، ماهیت آسیب‌پذیری عمومی‌تر است و ممکن است راه‌های دیگری برای بهره‌برداری از آن وجود داشته باشد.

آیا من آسیب‌پذیر هستم؟

  1. بالقوه آسیب‌پذیر: هر برنامه‌ای که از نسخه‌های Spring Framework قبل از 5.2.20، 5.3.18 و نسخه 9 و یا بالاتر JDK استفاده می‌کند، آسیب‌پذیری در آن وجود دارد.
  2. بالفعل آسیب‌پذیر: اگر علاوه بر شروط بند ۱، از حاشیه‌نویسی(annotation) RequestMapping@ و مشابه آن (@PostMapping و …) در برنامه استفاده شده است و حداقل در یکی از توابع از  پارامتر شی‌گرا یعنی Plain Old Java Object (POJO) استفاده شده است، آسیب‌پذیری قطعا در اختیار نفوذگر قرار دارد.
  3. فوق‌العاده در معرض خطر: هر برنامه‌ای که علاوه بر موارد بالا، از Tomcat استفاده کند، با خطر بالای سوء استفاده مواجه است، چرا که کدهای اکسپلویت برای نفوذ علیه برنامه‌های مبتنی بر Tomcat به راحتی در دسترس عموم است.

روش تست نسخه جاوا

از دستور زیر جهت یافتن نسخه جاوا استفاده نمایید: java -version
دقت نمایید که دستور java را از مسیری اجرا نمایید که جهت اجرای برنامه شما (یا TomCat) استفاده شده است.

روش تست نسخه Spring Framework

  • بررسی کنید که فایلی با نام spring-beans-*.jar در سرور/برنامه شما وجود دارد که به جای * شماره ورژن spring framework قرار می‌گیرد و نباید از 5.3.18 یا 5.2.20 کمتر باشد.
  • توجه نمایید که اگر از نسخه پک شده برنامه (war یا jar) استفاده می‌کنید باید یکبار آن را با استفاده از دستور unzip آن‌ها را باز نمایید.

راهکار

  1. بهترین و قطعی‌ترین راه حل، ارتقا به Spring Framework 5.3.18 و 5.2.20 می‌باشد.
  2. برای نسخه‌های قدیمی‌تر و پشتیبانی‌نشده Spring Framework، ارتقاء به Apache Tomcat 10.0.20، 9.0.62 یا 8.5.78، حفاظت کافی را فراهم می‌کند. با این حال، این باید به عنوان یک راه حل موقت تلقی گردد و بایستی در اسرع وقت به یک نسخه پشتیبانی شده Spring Framework ارتقا دهید.
  3. اگر نه می‌توانید Spring Framework را ارتقا دهید و نه آپاچی Tomcat را ارتقا دهید، برگشت به نسخه قدیمی‌تر جاوا 8 یک راه حل قابل قبول است.
  4. اگر هیچ یک از راه‌های ذکر شده برای شما مقدور نبود، در Spring Framework ،DataBinder دارای قابلیتی برای غیر مجاز کردن الگوهای خاص است. به عنوان یک راه‌ حل موقت برای این آسیب‌پذیری، توصیه می‌شود که یک مؤلفه ControllerAdvice (که جزء Spring مشترک بین Controllerها است) و اضافه کردن الگوهای خطرناک به فهرست انکار، ایجاد کنید. یک نمونه در زیر نشان داده شده است:
import org.springframework.core.Ordered;

import org.springframework.core.annotation.Order;

import org.springframework.web.bind.WebDataBinder;

import org.springframework.web.bind.annotation.ControllerAdvice;

import org.springframework.web.bind.annotation.InitBinder;


@ControllerAdvice

@Order(10000)

public class BinderControllerAdvice {

    @InitBinder

    public void setAllowedFields(WebDataBinder dataBinder) {

         String[] denylist = new String[]{"class.*", "Class.*", "*.class.*", "*.Class.*"};

         dataBinder.setDisallowedFields(denylist);
    }
}