TL؛ DR
بين 15 و16 يونيو 2026، قام ناشر واحد على npm بدفع ست حزم - 26 إصدارًا في المجموع — التي تقوم بتشغيل برنامج نصي أثناء التثبيت على كل npm install. تحتوي كل حزمة على ملف README يعلن أنها أداة بحثية "غير ضارة" من HackerOne / GitHub Bug Bounty لا "تلمس" قيم بيانات الاعتماد و"لا تقوم بأي عملية حفظ للبيانات". لا يتطابق الرمز مع إخلاء المسؤولية. في أنظمة التشغيل المتكاملة (CI) على نظام Linux، يقوم خطاف التثبيت بتحليل بيئة التشغيل وفحص نقطة نهاية بيانات تعريف مثيل السحابة؛ أما على نظام Windows، فيطلب رفع مستوى الصلاحيات، ويعمل كـ SYSTEMويفتح قناة أوامر إلى مضيف خارجي. المؤشر الوحيد الذي يجب البحث عنه الآن هو مضيف C2. 173.255.233[.]239. الخطورة: عاليالنظام البيئي المتأثر: الآلية الوقائية الوطنيةتندمج الأسماء في ضوضاء التبعية للتكامل المستمر (metrics-pipeline-d8k2, event-metrics-q3x7, pkg-telemetry-r4f9وثلاثة أشقاء).
الهجوم: كيف يعمل
يتم بناء كل حزمة في المجموعة بنفس الطريقة. package.json يوصل نفس الأمر بدورتين من دورات الحياة hooks:
{ "scripts": { "preinstall": "node run.js", "postinstall": "node run.js" } }يعمل على كليهما التثبيت المسبق والتثبيت اللاحق يعني ذلك أن الحمولة ستُطلق سواء فشلت خطوات التثبيت اللاحقة أم لا. run.js هو نفسه عبارة عن موزع منصة مكون من عشرة أسطر:
// Platform dispatcher — runs beaconNN.js on Windows, beacon_linux.js on Linux. // GitHub Bug Bounty authorized research. Contact: nicholas@curran.tech 'use strict'; const { execFileSync } = require('child_process'); const path = require('path'); const node = process.execPath; const script = process.platform === 'win32' ? path.join(__dirname, 'beacon34.js') : path.join(__dirname, 'beacon_linux.js'); try { execFileSync(node, [script], { stdio: 'inherit', timeout: 90000 }); } catch (e) {}ثم يتفرع السلوك حسب نظام التشغيل. تحمل جميع الحزم الست نفس الجزأين — run.js ومنارات المنصة - لذا فهي أدوات قابلة للتبديل وليست ست أدوات منفصلة. الاختلاف الوحيد المهم بينها هو وتيرة النشر: أربعة أسماء تم إصدارها مرة واحدة، بينما تم إعادة إصدار اسمين كل 30-60 دقيقة لساعات، مما يُبقي نسخة منشورة حديثًا أمام برامج التثبيت والتحليل حتى مع سحب الإصدارات القديمة.
على لينكس (beacon_linux.jsيقوم البرنامج النصي بتحديد مكان تشغيله. ويسرد أسماء متغيرات البيئة، ويقرأ الملفات الموجودة ضمن / إجراءات، يتحقق من docker.sock، ويجري اسم المضيف و whoamiثم يقوم بإرسال طلب HTTP إلى نقطة نهاية بيانات تعريف مثيل حاوية AWS 169.254.170 [.] 2 — عنوان الارتباط المحلي الذي تستعلم عنه مهمة ECS للحصول على بيانات اعتماد التكوين الخاصة بها وبيانات اعتماد الدور قصيرة الأجل (IMDS، خدمة بيانات تعريف المثيل). يتم إرسال النتائج عبر POST إلى جامع الحملة على 173.255.233 [.] 239.
على ويندوز (beacon34.js / beacon18.jsتقوم الحزمة بأكثر بكثير من مجرد تحليل أداء النظام المضيف. يضيف الكود المُعلّم مفتاح تسجيل ضمن إعدادات مللي معالج مع DelegateExecute القيمة - وهي ثغرة معروفة لتجاوز التحكم في حساب المستخدم تسمح بتشغيل عملية مُشغّلة بصلاحيات إدارية دون مطالبة. تستدعي هذه الثغرة PowerShell باستخدام -تجاوز سياسة التنفيذ و استدعاء التعبير، ينفذ في سلطة NT\النظام يقوم النظام باستطلاع السياق، ويستعلم عن الأوامر من مضيف خارجي. وتعمل قناة أوامر ويندوز عبر نفق كلاود فلير, diameter-coins-limitations-parents.trycloudflare[.]com:443، يتراجع إلى 173.255.233 [.] 239: 443باستخدام ثلاث نقاط نهاية: /c2/استطلاع الرأي لجلب أمر، /c2/out لإرجاع المخرجات، /c2/eof لإغلاق.
الجديد هنا: استخدام إخلاء المسؤولية كتمويه
العنصر الجديد ليس في الحمولة الخبيثة - فعمليات الاستطلاع باستخدام خطافات التثبيت ورفع مستوى صلاحيات ويندوز موثقة جيدًا. إنما في القصة المُغطاة. كل حزمة تحتوي على ملف README يُقرأ كوثيقة إفصاح مسؤول.
# @ncurran/sandbox-recon-880538 — authorized npm-sandbox security researchهذا هو حميدة تم نشر الحزمة تحت نطاق المؤلف `@ncurran` كجزء من مشاركة معتمدة في برنامج مكافآت اكتشاف الأخطاء على منصة HackerOne / GitHub (يشمل ذلك npm).
يقوم البرنامج بفحص النظام أثناء التثبيت. بيئة التنفيذ الخاصة بها ... متغير بيئي
أسماء المفاتيح فقط ... يتحقق مما إذا كان معروفًا نقاط نهاية بيانات التعريف السحابية . يمكن الوصول إليه... فهو لا يُبلغ إلا عن رموز الحالة، وأطوال الاستجابة، و التجزئة — أبدا أي بيانات اعتماد أو قيمة رمزية أو بيانات طرف ثالث. لا يقوم بأي شيء المثابرة، وعدم الحركة الجانبية، وعدم القيام بأي عمل تخريبي.
ثلاثة ادعاءات في ذلك النص تتناقض مع الكود المُرفق. ينص ملف README على "عدم وجود استمرارية"، لكن منارة Windows تكتب مفتاح رفع مستوى في سجل النظام. وينص أيضًا على "عدم وجود أي بيانات اعتماد أو قيمة رمزية"، لكن مسار Windows يُشغّل أوامر مُسترجعة عشوائية. نظاموهذا لا يفرض أي قيود على ما تتم قراءته أو إرجاعه. بل إنه يُسمّي الحزمة أيضاً. @ncurran/sandbox-recon-880538 هذا ليس الملف الذي يأتي معه البرنامج، مما يشير إلى أن ملف README عبارة عن قالب مُعاد استخدامه وليس وصفًا للبرنامج نفسه. إن وجود إخلاء مسؤولية عن الموافقة في حزمة لم يوافق الضحية على تثبيتها لا يُعدّ موافقة. يُصنّف البرنامج هنا على أنه خبيث بغض النظر عن الصياغة. كما أن لإخلاء المسؤولية هدفًا خفيًا: وهو خطوة الفرز الآلي التي تقرأ نص الحزمة بحثًا عن إشارات مطمئنة - مثل "غير ضار" أو "مُصرّح به" أو اسم البرنامج أو بريد إلكتروني للتواصل - حيث يمكن توجيهها نحو إصدار حكم آمن من خلال نص يتناقض مع محتوى البرنامج الخبيث. ينطبق هذا الدرس على المراجعين البشريين والآليين على حد سواء: ركّز على سلوك البرنامج أثناء التثبيت، وليس على وصفه الذاتي في ملف README.
الخط الزمني
ظهرت جميع الحزم خلال فترة 24 ساعة. ظهرت أسماء الإصدارات الأربعة ذات الإصدار الواحد أولاً، تلتها حزمتان أعيد نشرهما كل 30-60 دقيقة.
| التاريخ (UTC) | الحدث/الفعالية |
|---|---|
| 2026-06-15 18:32 | تم نشر الحزمة الأولى — npm:pkg-telemetry-r4f9@1.0.0 |
| 2026-06-15 19:50 | npm:runtime-metrics-w7k2@1.0.0 نشرت |
| 2026-06-15 20:14 | npm:build-tracker-n5p1@1.0.0 نشرت |
| 2026-06-15 20:35 | npm:npm-sandbox-ping-r9t2@1.0.0 نشرت |
| 2026-06-15 21:09–22:42 | npm:event-metrics-q3x7 نشرت 1.0.0 → 1.0.8 (9 إصدارات) |
| 2026-06-15 23:40 → 2026-06-16 04:40 | npm:metrics-pipeline-d8k2 نشرت 1.0.0 → 1.0.10 (11 إصدارات) |
| 2026-06-16 | تم تحديد المجموعة وتصنيفها على أنها خبيثة؛ العديد من ملفات tarball تُرجع بالفعل رمز الخطأ 404 في السجل (مستمر) |
الحملة حديثة، ولا تزال عملية إزالة البرامج الضارة قيد التنفيذ: عند تحليل البيانات، تم حل بعض الإصدارات في سجل النظام، بينما لم يتم حل البعض الآخر. لذا، يُرجى اعتبار جميع الإصدارات الـ 26 مخترقة.
مؤشرات التسوية
الباقات
| النظام الإيكولوجي | فئة الإشتراك | إصدارات | الحالة |
|---|---|---|---|
| الآلية الوقائية الوطنية | metrics-pipeline-d8k2 | 1.0.0 – 1.0.10 | خبيث |
| الآلية الوقائية الوطنية | event-metrics-q3x7 | 1.0.0 – 1.0.8 | خبيث |
| الآلية الوقائية الوطنية | runtime-metrics-w7k2 | 1.0.0 | خبيث |
| الآلية الوقائية الوطنية | build-tracker-n5p1 | 1.0.0 | خبيث |
| الآلية الوقائية الوطنية | npm-sandbox-ping-r9t2 | 1.0.0 | خبيث |
| الآلية الوقائية الوطنية | pkg-telemetry-r4f9 | 1.0.0 | خبيث |
الانرنيت
| النوع | مؤشر | ملاحظة |
|---|---|---|
| IP | 173.255.233[.]239 | جامع بيانات C2؛ اختبار POST الاستطلاعي لنظام Linux وخيار Windows الاحتياطي :443 |
| نطاق | diameter-coins-limitations-parents.trycloudflare[.]com | قناة أوامر ويندوز عبر نفق كلاود فلير، 443: |
| مسار URI | /c2/poll, /c2/out, /c2/eof | أوامر ويندوز: poll / output / close |
| IP | 169.254.170[.]2 | تم فحص نقطة نهاية بيانات تعريف مثيل AWS ECS من خطاف التثبيت |
السلوكية
| سيجنل | الوصف |
|---|---|
| تثبيت hooks | preinstall و postinstall كلاهما يركض node run.js |
| إرسال المنصة | run.js يدير beacon_linux.js على Linux ، beacon34.js / beacon18.js على ويندوز |
| لينكس ريكون | يقوم بحصر أسماء مفاتيح متغيرات البيئة، ويقرأها. /proc، الفحوصات docker.sock، أشواط hostname / whoami، مجسات IMDS |
| ارتفاع النوافذ | ms-settings DelegateExecute تجاوز التحكم في حساب المستخدم (UAC) في سجل النظام؛ باور شيل -ExecutionPolicy Bypass + Invoke-Expressionيعمل كـ SYSTEM |
| تمويه | يدّعي ملف README أن البحث "غير ضار" و"مُصرّح به" و"لا يوجد استمرار"؛ ويشير إلى اسم حزمة لا يتم شحنها بها |
الإسناد والسلوك الملاحظ
نصف الناشر من خلال إشاراته فقط ولا نؤكد هوية أي شخص يقف وراء الحساب.
- كتالوج الإشارات. تم نشر جميع الحزم الست بواسطة نفس حساب npm، npmresearch8847، مع البريد الإلكتروني المذكور npmresearch8847@web-library.net (البريد الإلكتروني و SCM لم يتم التحقق من الملكية. تُنشر ملفات README بموجب ترخيص. @ncurran تحديد النطاق وإعطاء معلومات الاتصال بـ nicholas@curran.techو run.js يشير إلى المستودع `github.com/ncurran/npm-sandbox-research`. تشترك الحزم الست في اسم متطابق run.js موظف الإرسال، وهو أمر شائع beacon_linux.js مرحلة الاستطلاع، والمضيف الجامع الوحيد 173.255.233[.]239`. نظام التسمية متسق: جذر عام يشبه صوت CI (المقاييس, القياس عن بعد, متتبع البناء, اختبار الاتصال في بيئة الاختبار) بالإضافة إلى لاحقة عشوائية قصيرة.
- الثقة. يبدو أن الحزم الست تشكل حملة واحدة، استنادًا إلى وجود مُرسِل مشترك، ومرحلة استطلاع، وخادم تحكم وسيطرة. ويبدو أن عبارة "بحث مُصرَّح به" متسقة في جميع ملفات README الستة. لم نتمكن من التأكد من أن أي برنامج مكافآت لاكتشاف الثغرات قد صرّح بهذا النشاط، كما أن بنود إخلاء المسؤولية لا تتطابق مع الكود المُضمَّن.
- القدرة الملحوظة. تمرين الحمولةcisأربع فئات من القدرات: تنفيذ التعليمات البرمجية الخاصة بخطاف التثبيت على كليهما التثبيت المسبق و بعد التثبيتاستطلاع المضيف وبيئة التكامل المستمر مع إمكانية الوصول إلى جامع بيانات خارجي؛ وفحص إمكانية الوصول إلى بيانات تعريف مثيل السحابة من سياق التثبيت؛ وفي نظام التشغيل Windows، تصعيد الامتيازات المحلية، والتنفيذ كـ نظاموحلقة أوامر لجلب وتشغيل الأوامر عبر قناة خارجية. تُعد حلقة أوامر ويندوز إحدى إمكانيات التحكم عن بُعد: فهي تستطلع التعليمات وتعيد مخرجاتها.
التأثير والاتجاهات وما ينبغي على المدافعين فعله
التأثير
تكون المخاطر أعلى ما يمكن في بيئات البناء الآلية. يقوم أمر npm install في التكامل المستمر بتشغيل دورة الحياة hooks بغض النظر عن هوية المُشغِّل؛ ففي مُشغِّل السحابة، غالبًا ما تتضمن هذه الهوية نقطة نهاية بيانات وصفية قابلة للوصول وبيانات اعتماد دور. عنوان مجسات إشارة لينكس، 169.254.170 [.] 2يُعدّ هذا نقطة نهاية بيانات تعريف مهام AWS ECS: عادةً ما تستطيع المهمة التي تصل إليها استرداد بيانات اعتماد دورها المؤقتة من نفس الخدمة المحلية المرتبطة. يُعدّ فحص إمكانية الوصول من داخل برنامج نصي للتثبيت الخطوة التي تسبق استرداد بيانات الاعتماد هذه، لذا يجب التعامل مع أي مُشغّل قام بتشغيل الخطاف وتمكّن من الوصول إلى نقطة النهاية هذه على أنه قد تم كشف دوره. على مضيف تطوير أو بناء يعمل بنظام Windows، يطلب الحمولة رفع مستوى الصلاحيات ويفتح قناة أوامر، مما يوسع نطاق الوصول من مجرد ملف تعريف وخروج إلى تحكم عن بُعد تفاعلي.
لم نتمكن من الحصول على إحصاءات موثوقة لعدد مرات تحميل النسخ الخبيثة قبل إزالتها، لذا لا يمكننا تقدير عدد الضحايا. وقد أدى النشر السريع لحزمتين من هذه البرامج - إحدى عشرة وتسع نسخ في غضون ساعات - إلى إبقاء الملفات الجديدة متاحة أمام برامج التثبيت والتحليل أثناء إزالة النسخ القديمة.
الأنماط الناشئة
تُعدّ هذه المجموعة مثالًا على استخدام التسمية كغطاء. فمصطلحات مثل "بحث مُصرّح به" و"مكافأة اكتشاف الأخطاء" و"اختبار بيئة الاختبار المعزولة" تُستخدم بشكل متزايد مع حزم برمجية تتجاوز وظيفة تثبيتها مجرد تحليل أداء النظام. يستغل هذا الأسلوب تردد المراجع في اتخاذ إجراء ضد ما يُعلن عن نفسه بأنه مُصرّح به. ويتزامن ذلك مع تكتيك آخر مألوف: أسماء حزم مُصممة لتبدو كأدوات تكامل مستمر داخلية، بحيث لا يمكن رصدها بسهولة من خلال نظرة سريعة على شجرة التبعيات. هذا المزيج هو ما يجعل هذا النمط جديرًا بالمتابعة - اسم يوحي بأنه بنية تحتية، مُغلّف بنص يوحي بأنه اختبار مُصرّح به، يُخفي وراءه خطاف تثبيت يتصاعد على نظام تشغيل واحد ويتحقق من بيانات اعتماد السحابة على نظام آخر. لا يُغيّر أيٌّ من إخلاء المسؤولية أو الاسم المُبهم ما يفعله الكود عند التثبيت، وعملية الفرز التي تُقيّم أيًّا منهما كدليل مُخفف ستؤدي إلى استنتاج خاطئ.
ما ينبغي على المدافعين فعله
- ابحث في ملفات القفل وسجلات التثبيت عن أسماء الحزم الست؛ تعامل مع أي تطابق على أنه حادث وليس تحذيرًا.
- حظر وتفعيل التنبيهات بشأن حركة المرور الصادرة إلى 173.255.233 [.] 239 و ل *.trycloudflare[.]com المضيفون من البنية التحتية للبناء.
- البحث عن طلبات HTTP أثناء التثبيت إلى عناوين بيانات تعريف المثيل (169.254.170.2, 169.254.169.254) صادرة من مديري الحزم في التكامل المستمر.
- قم بتدوير أي بيانات اعتماد ورموز دور سحابي يمكن الوصول إليها من برنامج تشغيل قام بتثبيت إصدار متأثر.
- إفحص التثبيت المسبق/بعد التثبيت البرامج النصية في مجموعة التبعيات; خطاف دورة الحياة الذي يقوم بتشغيل ملف نصي ثانٍ يستحق القراءة.
- على أجهزة ويندوز، ابحث عن الجديد DelegateExecute القيم المكتوبة تحت إعدادات مللي مفتاح معالج الصدفة — عنصر رفع المستوى الذي تستخدمه هذه الحمولة وإشارة موثوقة مستقلة عن اسم الحزمة.
- قم بتثبيت ملفات القفل ومراجعتها، وتعطيل برامج التثبيت (npm install --ignore-scripts) في التكامل المستمر حيث لا تتطلب عملية البناء الخاصة بك استخدامها.
- تعامل مع عبارات "البحث المصرح به" أو "الخطير" الموجودة داخل برنامج التثبيت كنص غير موثوق به، وليس كسبب للسماح بتشغيل البرنامج النصي.
حزمة تُعلن عن نوايا حسنة في النثر وتطلب نظام يجب الحكم على جودة الكود بناءً على الكود نفسه.






