React2Shell: چطور یه کنجکاوی ساده به یه آسیبپذیری بحرانی در React تبدیل شد
خلاصهٔ کاملتر
لاکلان دیویدسون یه روز عادی کاری داشت که ناگهان کنجکاوش شد پروتکل داخلی React رو بهتر بشناسه. اون تا اون موقع مثل بقیه، فرمت عجیبوغریب درخواستهای React Server Functions رو نادیده میگرفت. اما این بار تصمیم گرفت بفهمه این پروتکل — که اسمش Flight هست — دقیقاً چطور کار میکنه.
Flight پروتکلیه که React برای انتقال دادههای پیچیده بین سرور و مرورگر طراحی کرده. برخلاف JSON ساده، این پروتکل از انواع دادهای مثل Date، BigInt، Map و حتی Promise پشتیبانی میکنه. پیامها به چنکهای مجزا تقسیم میشن و میتونن بهصورت ناهمگام و خارج از ترتیب برسن. نکته مهم اینه که با سینتکس $x:y میشه مستقیماً به property یه آبجکت ارجاع داد.
همین قابلیت ارجاع به propertyها بود که اولین هشدار رو روشن کرد. Flight هیچ بررسیای نمیکنه که آیا property درخواستشده مستقیماً روی آبجکت هست یا از prototype chain به ارث رسیده. یعنی مهاجم میتونه Number.prototype.toString یا هر تابع دیگهای از prototype رو روی آبجکت خودش قرار بده. گیوم راوش، سازنده Next.js، بعداً این رو «یه نقص آشکار در بررسی امنیتی» توصیف کرد.
این مشکل وقتی خطرناک میشه که developer اشتباه کنه و ورودی کاربر رو بدون validation مستقیم استفاده کنه. تایپاسکریپت فقط در build-time چک میکنه؛ در runtime هیچ اجباری نیست که ورودی واقعاً از نوع اعلامشده باشه. پس مهاجم میتونه به جای یه رشته ساده، آبجکتی بفرسته که toString یا replaceAll روش به یه تابع مخرب اشاره میکنه.
مهمترین کشف اما به رفتار thenable ها برمیگرده. در جاوااسکریپت، هر آبجکتی که متد then داشته باشه، یه thenable محسوب میشه و await خودکار اون رو صدا میزنه. وقتی Next.js با await decodeReply(...) پیام Flight رو پردازش میکنه، اگه نتیجه یه thenable باشه، رانتایم خودش .then(resolve, reject) رو روش صدا میزنه. یعنی مهاجم میتونه با ساختن یه آبجکت که then اش به یه تابع دلخواه اشاره میکنه، اون تابع رو بدون هیچ کد آسیبپذیری در اپلیکیشن مستقیماً اجرا کنه:
{
then: Array.prototype.push
}با این تکنیک، رانتایم Array.prototype.push رو با آرگومانهای resolve و reject صدا میزنه. با زنجیر کردن چند thenable پشتسرهم، میشه فراخوانیهای نامحدودی انجام داد. این رفتار — برخلاف بقیه ویژگیهای Flight — به نظر غیرعمدی میرسید و اولین نشانه جدی از یه باگ واقعی در خود React بود.
نکات کلیدی:
- آسیبپذیری React2Shell با شناسه CVE-2025-55182 در ۳ دسامبر ۲۰۲۵ پچ شد
- ریشه مشکل در پروتکل داخلی Flight بود که بررسی prototype chain نداشت
- TypeScript annotation های مثل : string در runtime هیچ اجباری ایجاد نمیکنن
- مکانیزم thenable در جاوااسکریپت باعث میشد await decodeReply توابع مهاجم رو خودکار اجرا کنه
- این باگ میلیونها سایت مبتنی بر Next.js و React Server Functions رو در معرض خطر قرار داده بود




