تحقیقات جدید JFrog یک کمپین مخرب گسترده را فاش کرده است: ۱۴۸ پکیج npm که به صورت هوشمندانه به عنوان پراکسی‌های وب برای دور زدن فیلترهای اینترنتی مدارس پوشش‌داده شده بودند، در واقع مرورگرهای هزاران دانش‌آموز را به یک باتنت انکار خدمات توزیع‌شده (DDoS) تبدیل کرده بودند. این عملیات که تقریباً دو هفته در ماه مه ادامه داشت، نمادین است از تغییر تاکتیک مهاجمان: به جای هدف قرار دادن توسعه‌دهندگان در مراحل بیلد نرم‌افزار، اکنون کاربران نهایی (در اینجا دانش‌آموزان) به اللَّهُبِ حملات 공급 زنجیره (Supply Chain) تبدیل شده‌اند.

مکانیزم حمله: پکیج‌هایی که هرگز نصب نمی‌شوند

برخلاف حملات کلاسیک زنجیره تامین نظیر شای‌هولاد (Shai-Hulud) که در سپتامبر ۲۰۲۵ بیش از ۵۰۰ پکیج را заară کرد و توکن‌های توسعه‌دهندگان را دزدید، یا حملات فیشینگ بر روی نگهدارنده‌های شناخته‌شده مانند qix که کد خالی‌سازی کیف پول را در پکیج‌های پرکاربرد همچون chalk و debug تزریق کرد، این кампین هیچ‌کدام از قلاب‌های چرخه حیات (lifecycle hooks) یا اسکریپت‌های بیلد بومی را نداشتند.

پکیج‌ها تحت نام‌های ظاهرا بی‌ضرر اما جذاب برای مخاطب هدف نظیر charlie-kirk، ilovefemboys و miguelphonk منتشر شده بودند. هر کدام یک اپلیکیشن پراکسی با برند «Lucide» را حمل می‌کردند که به عنوان صفحه فرود سایت‌های تدریس جعلی «Riverbend Tutoring» یا «Northstar Tutoring» ظاهر می‌شدند.

لایه‌های دوگانه سوءاستفاده: از ادوور تا باتنت DDoS

تحلیل اولیه SafeDep در ماه مه، ۱۴۱ از این پکیج‌ها را کاتالوگ کرده و عملیات را صرفاً ادوور (Adware) و سوءاستفاده از رجیستری ارزیابی کرده بود: تبلیغات پاپ‌اندر، اسکریپت‌های سودجویی شخص ثالث و ردیابی Google Analytics روی یک پراکسی Scramjet هدفمند بر دانش‌آموزان. اما تیم JFrog با دی‌اَبفسکیت (deobfuscate) کردن باندل ورودی — یک خط تکی جاوااسکریپت ۵.۴ مگابایتی که به بیش از ۲۰،۶۰۰ خط کد خوانا باز می‌شد — و بازیابی بارهای مفید بایگانی شده از Wayback Machine، دو ماژول مخرب عمیق‌تر را آشکار کرد که هر دو قبل از رندر شدن رابط کاربری React اجرا می‌شدند:

ماژول G2: لودر اسکریپت از راه دور بی‌امان

  • جاوااسکریپت را از یک مخزن GitHub از طریق CDN jsDelivr واکشی می‌کرد.
  • به شاخه main قابل تغییر (mutable) به جای یک کامیت پین‌شده (pinned commit) اشاره داشت.
  • هیچ بررسی Subresource Integrity (SRI) نداشت.
  • کد دریافتی با مجوزهای Origin سایت پراکسی اجرا می‌شد: دسترسی کامل به کوکی‌ها، localStorage و اندپوینت‌های same-origin.
  • سیاست no-referrer مانع از لو رفتن منبع درخواست می‌شد.

کپی بایگانی‌شده از ۳۰ مه نشان می‌داد مخزن یک سیلاب HTTP بدساز سرویس می‌کرده: هر ۵۰۰ میلی‌ثانیه یک رشته یک میلیون کاراکتری ساخته شده و به عنوان POST با حالت no-cors به cdn.caan.edu (دامنه عمومی یک مدرسه پرستاری در ماتیسون، ایلینوی) فرستاده می‌شد. درخواست‌ها منتظر پاسخ نمی‌ماندند و با پارامتر کوئری تصادفی از کشینگ جلوگیری می‌شد. برآورد JFrog: هر بازدیدکننده فعال حدود ۲ مگابایت در ثانیه آپلود تولید می‌کرد؛ یعنی هزار تب باز می‌توانست ۲ گیگابایت در ثانیه ترافیک مخرب به سمت هدف هل دهد.

ماژول I2: موتور سیلاب WebSocket بر پایه پروتکل Wisp

ماژول دوم تیزتر عمل می‌کرد: یک فایل متنی ساده websocket.txt حاوی URL هدف WebSocket و تعداد سوکت (سقف ۱ تا ۱،۰۲۴) را واکشی کرده و آن تعداد اتصال را در یک حلقه استاگرد (staggered) برقرار می‌کرد. کانفیگ بایگانی‌شده هر مرورگر را به ۳۰ اتصال همزمان به یک نقاط پایانی Wisp روی lunaron.top (یک پراکسی زنده که خود मालويرتیزینگ تزریق می‌کرد) هدایت می‌کرد. پروتکل Wisp یک پراکسی سبک‌وزن مبتنی بر WebSocket است که برای دور زدن فیلترها طراحی شده، اما در اینجا به عنوان بستر کنترل و فرماندهی (C2) برای باتنت مرورگر سوءاستفاده می‌شد.

تغییر پارادایم: هدف توسعه‌دهنده نبوده، مرورگر قربانی است

نکته کلیدی این است که حمله در خط لوله بیلد (build pipeline) رخ نمی‌دهد. پکیج‌ها برای import شدن در پروژه‌ها نوشته نشده‌اند؛ رجیستری npm صرفاً به عنوان میزبانی رایگان (free hosting) برای فایل‌های استاتیک سایت پراکسی تلغم‌گذاری شده استفاده شده است. دانش‌آموزانی که برای دسترسی به بازی‌ها یا سایت‌های مسدود شده به این پراکسی‌ها مراجعه می‌کردند، بی‌اختیار و بدون دانستن، عضو یک جتانه (swarm) DDoS می‌شدند. اینTakتیک «بازمانده در تب مرورگر» (living in a browser tab) سطح حمله را از محیط توسعه به فضای گسترده کاربران نهایی گسترش می‌دهد.

آسیب‌پذیری‌های امنیتی که khai thác شده‌اند

  • عدم پین کردن وابستگی‌ها (Unpinned Dependencies): استفاده از شاخه main به جای هش.commit.
  • غیبت Subresource Integrity: عدم تحقق از یکپارچگی کد بارگذاری شده از CDN.
  • سیاست‌های CORS ضعیف: استفاده از no-cors برای دور زدن پیش‌فلیده‌ها.
  • بدون Referrer: پنهان کردن منبع ترافیک مخرب.
  • سوءاستفاده از پروتکل‌های پراکسی قانونی: Wisp به عنوان بستر C2.

توصیه‌های کاهش ریسک برای سازمان‌ها و کاربران

  1. مسیریابی DNS و فیلترینگ وب: بلاک کردن دامنه‌های شناخته‌شده مخرب (lunaron.top، cdn.caan.edu در این کمپین) در سطح شبکه.
  2. سیاست امنیتی محتوا (CSP): اعمال CSP سخت‌گیرانه برای جلوگیری از اجرای اسکریپت‌های اینلاین و بارگذاری از منابع مجاز.
  3. پایش ترافیک غیرعادی خروجی: شناسایی الگوی آپلود پیوسته ۲ مگابایت/ثانیه از کلاینت‌ها.
  4. آموزش آگاه‌سازی سایبری: هشدار دادن به دانشجویان و کارکنان درباره خطر استفاده از پراکسی‌های ناشناس برای دور زدن فیلترها.
  5. استفاده از ابزارهای SCA: ابزارهای تحلیل ترکیب نرم‌افزار (Software Composition Analysis) برای شناسایی پکیج‌های مشکوک در پروژه‌ها.

نتیجه‌گیری: رجیستری‌های باز، میدان جنگ جدید

این پرونده نشان می‌دهد که رجیستری‌های عمومی پکیج (npm، PyPI، Maven Central و ...) تنها مخازن کد نیستند؛ آن‌ها پلتفرم‌های توزیع محتوای استاتیک رایگان و ناشناس هم می‌باشند. مهاجمان با درک این واقعیت، به جای تزریق کد در وابستگی‌های بیلد-تایم، بارهای مفید مرورگرمحور (client-side) می‌کارند که در محیط‌های اجرایی کاربران نهایی فعال می‌شوند. دفاع در برابر این تهدیدات نیازمند دیدی فراتر از اسکن وابستگی‌های پروژه است: نظارت بر ترافیک وب، سخت‌سازی مرورگرها و آگاه‌سازی کاربران نهایی ستون‌های اصلی استراتیجی امنیت جدید خواهند بود.