وقتی یک پکیج Python کل سرور را میدزدد: درس حمله litellm برای هر کسبوکاری که سرور دارد
نویسنده: آرش لطیفی — موسس The DevArt
در مارس ۲۰۲۶ دو نسخه مخرب از litellm روی PyPI منتشر شد که کلیدهای SSH، توکنهای ابری و همه سکرتهای سرور را میدزدید. داستان واقعی از زبان گزارش رسمی تیم litellm — و چکلیست عملی برای اینکه infrastructure شما قربانی بعدی نباشد.
TL;DR — در مارس ۲۰۲۶ حساب PyPI یکی از maintainerهای litellm هک شد و نسخههای
1.82.7و1.82.8مخرب منتشر شدند: یک فایل.pthکه با هر بار اجرای Python (بدون حتی import) کلیدهای SSH، متغیرهای محیطی، کرادنشلهای AWS/GCP/Azure/K8s و کیفپولهای کریپتو را جمع و به دامنهیlitellm.cloud(غیررسمی!) میفرستاد. درس اصلی: هر پکیجی که نصب میکنی یک درِ ورودی به کل زیرساخت است — لاک کن، ممیزی کن، سکرتها را جدا نگه دار.
ماجرا از زبان گزارش رسمی
طبق پست رسمی تیم litellm در ایشو #24518 ریپوی BerriAI/litellm:
- حساب PyPI maintainer (
krrishdholakia) توسط مهاجمی با اسمteampcpربوده شد. - نسخههای
1.82.7و1.82.8روی PyPI آپلود شدند ولی هیچکدام از CI رسمی گیتهاب عبور نکرده بودند — ریلیزهای رسمی گیتهاب فقط تاv1.82.6.dev1بود. - دامنه مخرب
litellm.cloud(دامنه رسمیlitellm.aiاست!) فقط چند ساعت قبل از انتشار پکیج، در تاریخ ۲۰۲۶-۰۳-۲۳ از طریق Spaceship ثبت شده بود.
تکنیک حمله چطور کار میکرد؟
نسخه 1.82.8 یک فایل litellm_init.pth با حجم ۳۴,۶۲۸ بایت داخل site-packages داشت. مطابق مستندات خود Python، فایلهای .pth موقع استارت interpreter بهطور خودکار اجرا میشوند — یعنی بدون اینکه کسی import litellm کند، payload اجرا میشد. payload با double base64 encoding پنهان شده بود (grep سورس چیزی پیدا نمیکرد) و اینها را جمع میکرد:
| چی دزدیده میشود | مثال فایلها |
|---|---|
| کلیدها و سکرتها | printenv (همه API keyها)، ~/.ssh/id_rsa، ~/.aws/credentials، ~/.kube/config |
| لاگینهای روزمره | ~/.git-credentials، ~/.npmrc، ~/.netrc، ~/.docker/config.json |
| تاریخچه و کیفپول | ~/.bash_history، ~/.zsh_history، keystore اتریوم، Solana، ریپل |
| CI/CD و SSL | terraform.tfvars، .gitlab-ci.yml، Jenkinsfile، کلیدهای /etc/ssl/private/ |
دادهها با AES-256-CBC رمز میشدند، کلید رمز با یک کلید RSA ۴۰۹۶ بیتی هاردکدشده قفل میشد و همهچیز با یک curl ساده به https://models.litellm.cloud/ پست میشد.
چرا این برای فروشگاه و کسبوکار ایرانی مهم است؟
خیلیها فکر میکنند «ما که استارتاپ بزرگ نیستیم، کی بیاید سراغ ما؟» — جواب: مهاجم اصلاً شما را انتخاب نمیکند؛ هر کسی که pip install بزند قربانی است. اگر سرور فروشگاه، بات تلگرام، یا هر سرویس کوچکی دارید که پکیجهای Python نصب میکند، همان سرور کلیدهای درگاه پرداخت، SMTP، SSH و دیتابیس شما را نگه میدارد. یک پکیج مخرب = دست کامل مهاجم به همهی اینها.
خوشبختانه این حمله را خود تیم litellm با همکاری تیم mandiant.security گوگل بررسی کرد و پکیج بهطور کامل از PyPI حذف شد. نسخه فعلی روی PyPI امروز 1.106.0 است و نسخههای 1.82.7 و 1.82.8 دیگر وجود ندارند.
چکلیست پیشگیری
- [ ] همه وابستگیها را با فایل lock قفل کنید (
uv.lockیاrequirements.txtبا نسخه دقیق) — نصب بدون lock = رولت روسی - [ ] هر چند هفته یکبار
pip-audit(نسخه فعلی ۲.۱۰.۱) روی محیط پروژه اجرا کنید - [ ] سکرتها را از فایل
.envبه یک secret manager یا حداقل فایل با پرمیشن ۶۰۰ منتقل کنید و هرگز در repo نگذارید - [ ] قبل از آپگرید پکیجهای حساس، ریلیز گیتهاب رسمی را با نسخه PyPI مقایسه کنید — اگر پکیج در CI نبود، آلارم
- [ ] به نام دامنههای جدید در ارورهای شبکه شک کنید — این حمله فقط یک نقطه (
litellm.cloudبه جایlitellm.ai) با الگوی مشابه داشت - [ ] برای سرورهای production، استقرار با ایمیج Docker از ریپوی رسمی و با وابستگیهای pin شده انجام شود (کاربران Docker image در این حمله صدمه ندیدند)
جمعبندی
حملههای زنجیره تأمین (supply chain) مثل این، امنترین سرورها را هم دور میزنند چون حمله به «مرحله نصب» است نه مرحله اجرا. هیچوقت pip install را یک عمل بیخطر فرض نکنید — هر پکیج، کدی است که بهزودی با دسترسیهای شما اجرا میشود. ممیزی دورهای + لاک + مدیریت سکرت، ترکیب سادهای است که در این حمله هم میتوانست خسارت را نزدیک به صفر کند.
Q: من چطور بفهمم آلوده شدهام؟
طبق راهنمای رسمی تیم litellm: در site-packages دنبال فایل litellm_init.pth بگردید و اگر بود، همه credentials که در متغیرهای محیطی، SSH، ابر و دیتابیس بوده را فوراً rotate کنید. اگر docker image رسمی را استفاده میکردید، طبق اعلام تیم، آلوده نشدهاید.
Q: فقط نسخه 1.82.8 مشکلدار بود؟
نه — نسخه 1.82.7 هم payload داشت ولی فقط موقع import litellm.proxy فعال میشد؛ 1.82.8 با فایل .pth بدتر شد و با هر استارت Python اجرا میشد. تیم litellm اعلام کرد نسخههای دیگر هم باید ممیزی شوند.
Q: جایگزین مطمئن برای litellm چیست؟
راه بهتر این نیست که «پکیج x جایگزین بشه» — این است که وابستگیها را لاک کنید، قبل از آپگرید ممیزی کنید و سکرتها را جدا نگه دارید. اگر آلتروناتیو میخواهید، حتماً ریپوی رسمی و ریلیزهای CI-امضاشده را چک کنید، نه فقط تعداد ستارهها.
منابع
- https://github.com/BerriAI/litellm/issues/24512
- https://github.com/BerriAI/litellm/issues/24518
- https://news.ycombinator.com/item?id=47501729
- https://pypi.org/project/pip-audit/