آناتومی یک بکدور زنجیره تامین: درس مهندسی از افزونه آلوده Claude Code
نویسنده: آرش لطیفی
کالبدشکافی فنی بکدور افزونه Claude Code در مارکت Cursor: تزریق IIFE به extension.js، باگ باورنکردنی systemsetup در macOS، تانل معکوس SSH و فایلهای persistence — با دستورات چک و IOCs.
TL;DR — بکدور افزونه Claude Code (نسخههای 2.1.312/2.1.313) یک درس کامل مهندسی معکوس است: تزریق IIFE قبل از
activate، کلکfs.appendFileSyncرویauthorized_keys، یک باگ در چکsystemsetupکه کل زنجیره حمله macOS را میشکند، و تانل معکوس-R *:0— همه را با دستورات چک اینجا دارید.
روز ۲۹ اکتبر ۲۰۲۶، نسخههای آلوده افزونه رسمی Claude Code حدود ۱۱ ساعت در مارکت Cursor بودند. تحلیل فنی Phorion و اطلاعیه Cursor جزئیات کافی برای یک درس کامل میدهند: این بدافزار در جاوااسکریپت نوشته شده، بدون هیچ اکسپلویت privesc کار میکند، و دقیقاً بهخاطر دو باگ خودش در اکثر سیستمها به نفوذ کامل نرسیده. بیایید مرحلهبهمرحله ببینیم.
مرحله ۰: تزریق قبل از activate
فایل extension.js (مینیفای شده) با یک IIFE تزریقشده شروع میشود که ماژولهای استاندارد Node را ایمپورت میکند:
// ابتدای extension.js تزریق شده — قبل از activate عادی افزونه
const cp = require("child_process"),
fs = require("fs"),
os = require("os"),
path = require("path"),
http = require("http"),
crypto = require("crypto");
نکته مهم: چون این کد در سطح ماژول اجرا میشود، با لود شدن فایل توسط Node اجرا میشود، حتی قبل از اینکه callback عادی activate افزونه صدا زده شود. یعنی هیچ تعاملی از کاربر لازم نیست — فقط نصب و باز کردن ادیتور.
مرحله ۱: کلید SSH و باگ macOS
بدافزار با fs.appendFileSync کلید عمومی مهاجم (Ed25519 با کامنت svc-telemetry) را به authorized_keys اضافه میکند. نکته برای شکارچیان تهدید: چک تکراری-install فقط دنبال رشته کامنت است، نه خود کلید — پس در تست نفوذ، فینگپرینت کلید را چک کنید نه فقط کامنت.
بعدش نوبت فعالسازی SSH daemon است، و اینجا باگ طلایی بدافزار در macOS رخ میدهد. اسکریپت این کار را میکند:
اما systemsetup -getremotelogin بدون دسترسی administrator روی macOS این خروجی را میدهد و با status 0 خارج میشود:
You need administrator access to run this tool... exiting!
چون خروجی Off نیست، شرط /Off/i برقرار نمیشود و دستور فعالسازی هرگز اجرا نمیشود. بدافزار عملاً «نمیتوانم چک کنم» را با «SSH از قبل روشن است» اشتباه میگیرد. نتیجه: روی مکی که Remote Login از قبل روشن نبوده، ورود inbound مهاجم به بنبست میخورد — هرچند کلید و persistence همچنان جاگذاری شدهاند. Cursor هم در اطلاعیه خود تأیید میکند که در شرایط عادی (بدون دسترسی admin) این مرحله شکست میخورد.
درس: یک چک state بدون مدیریت خطای درست، یک زنجیره حمله کامل را زمین میزند — چه در بدافزار، چه در کد خودت.
مرحله ۲: تانل معکوس SSH
برای خروج، بدافزار یک کلید خصوصی Embedded (کامنت svc-telemetry-tun) را در پوشه temp مینویسد با نام .stk_ + ۱۰ کاراکتر اول MD5 از hostname و مسیر home:
و تانل را با این الگو برقرار میکند (با autossh اگر نصب باشد، وگرنه ssh):
ترفند -R *:0 این است که پورت ۰ یعنی سرور مهاجم بهصورت پویا یک پورت خالی انتخاب میکند و هر ترافیکی که به آن بخورد از طریق تانل به localhost:22 قربانی میرسد. اپراتور بعد از یک کانکشن جدا به آن پورت وصل میشود و با کلید مرحله ۱ به SSH محلی لاگین میکند. در لاگهای SSH قربانی، این ورودها از 127.0.0.1 دیده میشوند — یک ایده خوب برای detection. حلقه retry هم detached است (هر ۶۰ ثانیه، با pgrep برای جلوگیری از duplicate)، پس بستن ادیتور تانل را نمیکشد.
مرحله ۳: persistence و مرحله ۴: beacon
Persistence بر اساس پلتفرم:
| پلتفرم | Artifact | مکانیزم |
| --- | --- | --- |
| macOS | ~/Library/LaunchAgents/com.apple.sysmond.plist | LaunchAgent با RunAtLoad و KeepAlive |
| Linux | ~/.config/.smt + .smtk | ورودی @reboot در crontab کاربر |
| Windows | %APPDATA%/.../Startup/sysmon.cmd | تسک SysMon (تلاش برای SYSTEM) + فالبک Startup |
نکته جالب: LaunchAgent با label جعلی com.apple.sysmond خودش را شبیه فرآیند سیستمی اپل نشان میدهد — ولی هر پروسه غیر-Apple که plist با com.apple.* بنویسد، سیگنال detection قوی است.
بیدن (beacon) هم ساده است: hostname، username، معماری، ایمیل git، IP عمومی (از ifconfig.me یا api.ipify.org) و فقط اسم حداکثر ۴۰ متغیر محیطی که با /KEY|TOKEN|SECRET|PASS|AWS|GCP/i match شوند، با یک POST به /beacon روی پورت 8099 سرور مهاجم. فقط اسم — ولی کافی است تا مهاجم بداند کدام هاست ارزش اولویت دادن دارد.
چک کن: سیستم من تمیز است؟
- [ ] چک
svc-telemetryاجرا شد (macOS/Linux و PowerShell ویندوز) - [ ] فایلهای persistence (
.smt,.smtk,com.apple.sysmond.plist,/tmp/.stk_*) وجود ندارند - [ ] لاگ SSH برای ورودهای
127.0.0.1با کلید مشکوک چک شد - [ ] اگر آلوده بودی: اسکریپت رسمی
remediate-macos.sh/remediate-windows.ps1از اطلاعیه Cursor اجرا شد - [ ] کرندهسیالها و sessionهای در دسترس آن کاربر از یک سیستم تمیز rotate شدند
Cursor تأکید میکند سرور مهاجم از کار انداخته شده و هیچ شواهدی از آلودگی نسخههای دیگر یا کانال رسمی وجود ندارد — ولی remediation را «در هر صورت» توصیه میکند، چون حذف افزونه فایلهای persistence را پاک نمیکند.
Q: چرا یک extension در مارکت میتواند کل سیستم را بگیرد؟
افزونهها با دسترسی IDE و کاربر اجرا میشوند؛ به فایلهای محلی، سورس کد و ابزارهای توسعه (git، ssh، envها) دسترسی کامل دارند. sandbox مارکت مانع اجرای کد Node داخل extension host نیست.
Q: بدافزار چطور بدون اکسپلویت privesc کار میکرد؟
نیازی نداشت — چون میخواست در کانتکست خود کاربر بماند. کلید SSH در authorized_keys همان کاربر را هدف میگیرد و فعالسازی سرویس سیستمی فقط با sudo -n تلاش میشد که بدون sudo کششده شکست میخورد. باگ macOS هم باعث شد در اکثر مکها حتی همین مرحله هم اجرا نشود.
Q: مهمترین IOC برای detection چیست؟
دو مورد: پروسه Helper ادیتور (Cursor Helper / Code Helper) که authorized_keys را مستقیم با fs.appendFileSync مینویسد (قوانین process-only برای echo/tee این را نمیگیرند)، و ssh/autossh با -R *:0:localhost:22 و فایل identity از /tmp/.stk_* یا ~/.config/.smtk.