یه روز معمولی بود و داشتم همینطوری کدهای ریپازیتوری (Repo) یکی از دوستام رو نگاه میکردم که یهو یه بلوک متن گنده و ناخوانا نظرم رو جلب کرد. یه گوشه تو یه فایل پایتون قایم شده بود، ولی اسم متغیرهاش کاملاً چرت و پرت بود. حس ششم امنیت سایبریام بلافاصله به کار افتاد؛ این یه کد به شدت مبهمسازی شده (Obfuscated) بود.
اون لحظه نمیدونستم که دقیقاً خوردم به پست یه حمله زنجیره تامین (Supply Chain) خیلی خفن و بزرگ که صدها ریپازیتوری رو تو گیتهاب آلوده کرده.
این داستان پیدا کردنش، مهندسی معکوسش و اینه که چطور میتونین از کدهای خودتون محافظت کنین.
تیکه کد مشکوک
کدی که پیدا کردم این شکلی بود. این یه تکنیک کلاسیک مبهمسازیه: قایم کردن هدف اصلی اسکریپت پشت لایههای تو در تو انکودینگ و اجرای داینامیک.
|
|
با نگاه کردن به سه خط آخر، روند اجرا کاملاً مشخص بود:
۱. دیکد کردن از Base64.
۲. از حالت فشرده خارج کردن با Zlib.
۳. رمزگشایی با یه عملیات XOR (با کلید 134).
۴. اجرای مستقیم پیلود (Payload) مخرب تو حافظه با استفاده از تابع به شدت خطرناک exec().
رمزگشایی کد
اولش سعی کردم پیلود رو دستی رمزگشایی کنم، ولی سر و کله زدن با اون استرینگ (String) طولانی و عملیاتهای تو در تو داشت خیلی رو مخ میرفت. واسه همین یه هوش مصنوعی (کلود) رو تو یه محیط ایزوله آوردم بالا و ازش خواستم یه اسکریپت امن واسه رفع مبهمسازی (Deobfuscator) بنویسه.
هدف ساده بود: جایگزین کردن exec() خطرناک با یه دستور print() تا بتونیم پیلود مخفی رو به صورت متن ساده ببینیم، بدون اینکه واقعاً اجراش کنیم.
اینم اسکریپتی که برای خنثی کردن و استخراج پیلود استفاده کردیم:
|
|
هیولای درون
اجرای این دیکدر تو یه محیط سندباکس (Sandbox)، ذات واقعی این هیولا رو نشون داد. اسکریپت پایتون به دست اومده، یه Dropper/Loader خیلی پیشرفته بود که برای دزدیدن اطلاعات طراحی شده بود.
(نکته: پیلود کامل رمزگشایی شده خیلی بزرگه، ولی اینجا ویژگیهای ترسناک و اصلیش رو میبینید)
۱. کنترل و فرمان (C2) بر بستر بلاکچین: این بدافزار به جای وصل شدن به یه آیپی معمولی که راحت بلاک میشه، از بلاکچین سولانا (Solana) استفاده میکنه! تاریخچه تراکنشهای یه کیف پول خاص رو چک میکنه و دستورات رمزنگاری شده رو از داخل “Memo"های تراکنشها میکشه بیرون. این کار باعث میشه پایین آوردن زیرساخت هکرها تقریباً غیرممکن بشه.
۲. حصار جغرافیایی (استثنای روسی): اسکریپت یه تابع داره به اسم _isRussianSystem(). این تابع زبان سیستم، منطقه زمانی و لوکیشن رو چک میکنه. اگه سیستم آلوده تو روسیه یا کشورهای CIS باشه، بدافزار بیسروصدا بسته میشه. این یه تاکتیک کلاسیکه که هکرها برای فرار از دست پلیسهای محلی خودشون استفاده میکنن.
۳. محیط اجرایی همراه (BYOE): بدافزار خیلی سایلنت سیستمعاملتون (ویندوز، مک یا لینوکس) رو تشخیص میده و یه نسخه پرتابل از Node.js رو مستقیماً از سایت رسمیش دانلود میکنه. بعدش از این Node.js برای اجرای یه فایل جاوااسکریپت مخفی ثانویه (که احتمالاً یه استیلر مثل Lumma یا RedLine هست) استفاده میکنه تا پسوردها، کوکیها و کیف پولهای کریپتو رو بالا بکشه.
گستردگی آلودگی
با این فکر که شاید این یه مورد خاص باشه، یه تیکه از کد مبهمسازی شده رو برداشتم و تو کل گیتهاب سرچش کردم.
نتایج مو به تن آدم سیخ میکرد. بیشتر از ۳۰۰ تا ریپازیتوری دقیقاً به همین کد آلوده شده بودن. بعد از یه کم بررسی، به نظر میرسه این کد مخرب داره مستقیماً موقع اجرای دستور git commit تو فایلها تزریق میشه. با اینکه هنوز دقیقاً معلوم نیست عامل اولیه چیه (مثلاً یه اکستنشن هک شده VS Code، یه پکیج مخرب npm/PyPI یا یه ابزار ترمینال آلوده)، ولی نتیجه کاملاً واضحه: برنامهنویسها دارن ناخواسته بدافزار رو روی پروژههای خودشون پوش (Push) میکنن.
خطر واقعی: مدلهای هوش مصنوعی مسموم
اما چیزی که شبا نمیذاره بخوابم اینه: دیتای آموزش هوش مصنوعی.
هزاران مهندس ماشین لرنینگ و محقق هوش مصنوعی دارن به طور فعال ریپازیتوریهای گیتهاب رو اسکرپ (Scrape) میکنن تا مدلهای زبانی بزرگ (LLM)، مدلهای تولید کد و ابزارهای تحلیل امنیتیشون رو آموزش بدن. اونا به کدهای اپنسورس به چشم “دیتای آموزشی مجانی” نگاه میکنن. چیزی که نمیدونن اینه که دارن این تیکه کدهای مخرب و مبهم رو جارو میکنن و مستقیماً میریزن تو حلق شبکههای عصبیشون.
تصور کنین یه مدل هوش مصنوعی روی بیشتر از ۳۰۰ تا ریپازیتوری آلوده آموزش ببینه. کد بدافزار که لابلای هزاران نمونه کد سالم قایم شده، تبدیل میشه به بخشی از الگوهای یادگرفته شده مدل. حالا بریم تو محیط پروداکشن: دولوپرها از این مدل “آموزشدیده” استفاده میکنن تا:
- پیشنهاد کد بگیرن (و مدل بهشون بدافزار مبهمسازی شده پیشنهاد میده).
- آسیبپذیریهای امنیتی رو تحلیل کنن (در حالی که خود مدل تو دلش بکدور داره).
- پکیجهای ترد-پارتی (Third-party) رو تایید کنن (و ناخواسته پکیجهای آلوده رو پیشنهاد میده).
کابوس واقعی فقط یه مدل مسموم نیست، یه مدل غیرقابل تشخیصه. بدافزار داخل وزنها (Weights) و بایاسهای (Biases) ریاضی شبکه عصبی زندگی میکنه و از دید هر ابزار تحلیل کد استاتیکی پنهانه. هیچ سندباکس یا آنتیویروسی هم بهش گیر نمیده چون این دیگه یه کد “در حال اجرا” نیست، بلکه یه رفتار یادگرفته شده است. تا زمانی که مدل شروع به تولید پیشنهادات مخرب تو پروداکشن نکنه پیداش نمیکنین، و اون موقع است که میتونه هزاران پروژه رو به صورت همزمان آلوده کنه.
این یه حمله زنجیره تامینه که از ریپازیتوریها فراتر میره و مستقیماً ابزارهایی که برای نوشتن کدهای امن استفاده میکنیم رو آلوده میکنه.
راهحل پیشگیری: یه چسب زخم سریع
تا زمانی که دقیقاً نفهمیم کدوم ابزار یا پکیج داره فرآیند کامیت رو هایجک میکنه، باید یه جوری جلوی خونریزی رو بگیریم.
از اونجایی که این بدافزار بر پایه تزریق یه استرینگ Base64 عظیم و پیوسته تو کد شما کار میکنه، راحتترین راه برای جلوگیری از آلوده شدن ریپازیتوریتون (و پخش کردنش به بقیه) اینه که یه Pre-commit Hook سفت و سخت تنظیم کنین.
شما میتونین جلوی هر کامیتی که توش یه استرینگ به طرز غیرطبیعی بلندی داره (مثلاً بیشتر از ۱۰۰ کاراکتر بدون فاصله) رو بگیرین. اینجا یه کانسپت ساده برای یه هوک pre-commit گیت داریم که میتونین به فایل .git/hooks/pre-commit اضافهاش کنین:
|
|
نتیجهگیری
حملات زنجیره تامین دارن هی هوشمندتر میشن. اونا دیگه فقط سرورهای پروداکشن رو هدف نمیگیرن؛ بلکه دارن تو محیطهای توسعه (Development) ما زندگی میکنن، کامیتهای ما رو میدزدن و از بلاکچینهای غیرمتمرکز برای پاک کردن ردپاشون استفاده میکنن.
ریپازیتوریهاتون رو چک کنین، دیپندنسیها (Dependencies) رو بررسی کنین، و اگه یه بلوک بزرگ از حروف رندوم تو فایلهای پایتونتون دیدین، لطفاً اجراش نکنین! مراقب خودتون باشین.