1 điểm bởi GN⁺ 2025-11-29 | 1 bình luận | Chia sẻ qua WhatsApp
  • Hệ sinh thái npm đang chứng kiến biến thể mã độc phá hoại lan rộng, và đội ngũ bảo mật GitLab đã phát hiện ra điều này
  • Mã độc là dạng tiến hóa của Shai-Hulud, có cơ chế lây lan kiểu sâu tự động lây nhiễm sang các gói khác của nhà phát triển bị nhiễm
  • Sau khi đánh cắp thông tin xác thực từ GitHub, AWS, GCP, Azure..., nó rò rỉ dữ liệu sang kho lưu trữ GitHub do kẻ tấn công kiểm soát
  • Tích hợp “công tắc deadman” xóa ngay dữ liệu người dùng nếu quyền truy cập vào GitHub và npm cùng lúc bị chặn
  • GitLab xác nhận hệ thống của mình không bị nhiễm và cung cấp phương án phát hiện, ứng phó thông qua Dependency ScanningGitLab Duo Chat

Tổng quan về cuộc tấn công

  • Đội Vulnerability Research của GitLab đã phát hiện một cuộc tấn công chuỗi cung ứng quy mô lớn trong hệ sinh thái npm
    • Hệ thống giám sát nội bộ đã phát hiện nhiều gói bị nhiễm
    • Mã độc được xác định là biến thể của Shai-Hulud
  • Mã độc tự động lây nhiễm sang các gói khác của nhà phát triển bị nhiễm thông qua cơ chế lây lan kiểu sâu
  • GitLab đã xác nhận nội bộ không sử dụng các gói độc hại và chia sẻ thông tin với cộng đồng bảo mật

Cấu trúc bên trong cuộc tấn công

  • Các gói npm độc hại do hệ thống giám sát nội bộ phát hiện thực hiện những chức năng sau
    • Thu thập thông tin xác thực từ GitHub, npm, AWS, GCP, Azure
    • Gửi dữ liệu đã đánh cắp tới kho lưu trữ GitHub do kẻ tấn công kiểm soát
    • Tự động lây nhiễm sang các gói khác của nạn nhân
    • Kích hoạt payload phá hoại nếu quyền truy cập hạ tầng bị chặn
  • Nhiều gói bị nhiễm đã được xác nhận và cuộc điều tra vẫn đang tiếp tục

Phân tích kỹ thuật: cách cuộc tấn công diễn ra

Vector lây nhiễm ban đầu

  • Mã độc xâm nhập hệ thống thông qua quy trình nạp nhiều tầng
    • Trong package.json của gói bị nhiễm, một script setup_bun.js được thêm vào
    • Bề ngoài được ngụy trang là script cài đặt Bun JavaScript runtime
    • Thực chất nó chạy bun_environment.js (payload 10MB đã bị làm rối)
  • Cấu trúc gồm một file loader nhỏ và payload lớn đã làm rối nhằm né tránh phát hiện

Thu thập thông tin xác thực

  • Ngay khi chạy, nó thu thập token và bí mật từ nhiều nguồn khác nhau
    • GitHub token (ghp_, gho_)
    • Thông tin xác thực AWS, GCP, Azure
    • npm token (.npmrc và biến môi trường)
    • Dùng công cụ Trufflehog để quét toàn bộ thư mục home, tìm API key, mật khẩu, lịch sử Git...

Mạng lưới rò rỉ dữ liệu

  • Dùng GitHub token đánh cắp được để tạo kho lưu trữ công khai có mô tả “Sha1-Hulud: The Second Coming.”
    • Kho lưu trữ này đóng vai trò dropbox dữ liệu
    • Cài đặt GitHub Actions runner để duy trì tính bền bỉ
  • Nếu thiếu quyền, nó tìm các kho khác mang cùng dấu hiệu nhận diện để tái sử dụng token từ hệ thống khác
    • Từ đó hình thành mạng lưới chia sẻ token phân tán

Lây lan chuỗi cung ứng

  • Dùng npm token đã đánh cắp để lây nhiễm mọi gói của nạn nhân
    1. Tải gói gốc xuống
    2. Chèn setup_bun.js làm script preinstall
    3. Thêm payload bun_environment.js
    4. Tăng số phiên bản
    5. Phát hành lại gói đã nhiễm lên npm

Công tắc deadman

  • Mã độc liên tục giám sát quyền truy cập vào GitHub (rò rỉ dữ liệu) và npm (lây lan)
    • Nếu cả hai kênh đều bị chặn, nó ngay lập tức thực thi hành vi phá hủy dữ liệu
  • Windows: xóa file người dùng và ghi đè các sector đĩa
  • Unix: ghi đè file bằng lệnh shred rồi xóa
  • Nếu kho GitHub bị xóa hàng loạt hoặc npm token bị thu hồi trên diện rộng, sẽ có nguy cơ các hệ thống bị nhiễm đồng thời xóa dữ liệu

Chỉ báo xâm nhập (IoC)

  • Các chỉ báo phát hiện chính
    • File: bun_environment.js (script post-install độc hại)
    • Thư mục: .truffler-cache/, .truffler-cache/extract/
    • Tiến trình: del /F /Q /S "%USERPROFILE%*", shred -uvz -n 1, cipher /W:%USERPROFILE%
    • Lệnh: curl -fsSL https://bun.sh/install | bash, powershell -c "irm bun.sh/install.ps1|iex"

Hỗ trợ phát hiện và ứng phó của GitLab

  • Người dùng GitLab Ultimate có thể kiểm tra ngay mức độ phơi nhiễm bằng các tính năng bảo mật tích hợp
    • Khi bật Dependency Scanning, các gói bị nhiễm trong package-lock.json hoặc yarn.lock sẽ được tự động phát hiện
    • Nếu merge request chứa gói bị nhiễm, hệ thống sẽ hiển thị cảnh báo
  • Có thể tích hợp với GitLab Duo Chat để phát hiện nhanh dựa trên truy vấn
    • Ví dụ: “Có dependency nào bị ảnh hưởng bởi chiến dịch Shai-Hulud v2 không?”
    • Security Analyst Agent sẽ truy vấn dữ liệu lỗ hổng của dự án và trả lời ngay
  • Với các nhóm quản lý nhiều kho lưu trữ, GitLab khuyến nghị kết hợp phát hiện tự động dựa trên CI/CDứng phó nhanh dựa trên agent

Triển vọng sắp tới

  • Cuộc tấn công lần này được đánh giá là một dạng tấn công chuỗi cung ứng mới, sử dụng phá hủy dữ liệu nạn nhân để bảo vệ hạ tầng tấn công
  • GitLab đang phối hợp với cộng đồng để phát triển chiến lược khôi phục an toàn và tiếp tục giám sát các biến thể bằng hệ thống phát hiện tự động
  • Mục tiêu là ngăn chặn thiệt hại thứ cấp do công tắc deadman gây ra thông qua chia sẻ thông tin sớm

1 bình luận

 
GN⁺ 2025-11-29
Ý kiến trên Hacker News
  • Khoảng một tháng trước tôi cần làm một việc khá phiền, nên đi tìm một gói NPM
    Khi chạy brew install npm, một thác phụ thuộc đổ ập xuống; tôi dừng lại một chút để cân nhắc rủi ro và lợi ích, rồi cuối cùng quay lại bằng brew uninstall npm
    Thay vào đó tôi giải quyết bằng pipeline tiện ích Unix cũ cùng awk, và giờ nghĩ lại thì đó đúng là quyết định sáng suốt nhất

    • Bài học rất rõ ràng — không nên dùng công nghệ web cho scripting cục bộ
      NPM là công cụ được tạo ra để giải quyết vấn đề tương thích trình duyệt, nên trong môi trường không có trình duyệt nó chỉ mang lại độ phức tạp không cần thiết
    • Đó cũng là lý do cần đến container hóa hoặc ảo hóa
      Nếu chạy trực tiếp trên hệ thống chính mã từ các hệ sinh thái nhiều phụ thuộc như Node hay Python, nguy cơ phơi nhiễm trước các cuộc tấn công chuỗi cung ứng là rất lớn
      Vì vậy tôi thậm chí không cài sẵn trình thông dịch Python hay JS trên hệ thống mặc định
    • Trước đây tôi cũng chỉ chạy npm bên trong container Docker, nhưng trên diễn đàn lại thường bị chế nhạo
      Cuối cùng tôi đã bỏ cuộc, nhưng giờ có vẻ khi đó tôi mới là người đúng
    • Tôi cũng có trải nghiệm tương tự. Vừa thấy số lượng phụ thuộc mà artillery định kéo về là tôi bỏ luôn
    • Trớ trêu là các lập trình viên lúc nào cũng nói “thường thức là bảo mật tốt nhất”, nhưng lại cài hàng đống package chưa được kiểm chứng chỉ bằng một dòng lệnh
  • Có người nói rằng “nếu GitHub xóa hàng loạt các kho lưu trữ độc hại thì hàng nghìn hệ thống có thể đồng thời phá hủy dữ liệu người dùng”,
    nghe chẳng khác gì một vụ bắt cóc con tin — nên mới có trò đùa “bắn con tin đi”

    • Nhưng con tin (người dùng) thực ra tự đưa mình vào tình thế nguy hiểm, nên rốt cuộc đây cũng là hệ quả từ chính lựa chọn của họ
  • Tôi cũng là nạn nhân của đợt tấn công npm lần này
    Tôi bị sốc khi biết GitHub CLI lưu OAuth token dạng văn bản thuần trong thư mục HOME
    Nếu kẻ tấn công truy cập được, chúng gần như có thể làm mọi thứ trên tài khoản của tôi

    • Thực ra GitHub CLI chỉ lưu token dạng văn bản thuần khi không có keyring
      Trên macOS, nó được lưu an toàn trong keychain của hệ điều hành — thảo luận liên quan
    • Đúng, nhưng file cookie của trình duyệt cũng gặp vấn đề tương tự
      Chrome dùng cơ chế bảo vệ của hệ điều hành, còn Firefox thì vẫn chưa
      Cuối cùng kiểm soát truy cập dựa trên sandbox mới là giải pháp gốc rễ
    • Mọi token đều nên nằm trong keychain được bảo vệ
      Nhưng hiện không có giải pháp nhất quán giữa các nền tảng, và ngay cả trên MacOS cũng chưa có cách nào hoàn hảo
    • Tôi cũng là nạn nhân. Sau khi cài Backstage thì bị nhiễm
      Một thư mục ~/.dev-env xuất hiện và laptop của tôi biến thành GitHub runner
      Có lẽ hệ thống tệp chỉ đọc của Bluefin Linux đã giúp giảm bớt thiệt hại
  • Ai cũng chỉ đổ lỗi cho npm, nhưng GitHub cũng phải chịu trách nhiệm lớn
    Họ không phát hiện đủ nhanh các kho lưu trữ độc hại, trong khi vấn đề repo chứa malware vốn đã rất nghiêm trọng

    • Dù vậy, cũng nhờ nó được tải lên GitHub mà có người phát hiện ra thiệt hại sớm
      Nếu nó âm thầm bị gửi ra máy chủ bên ngoài thì mọi chuyện còn kinh khủng hơn nhiều
    • Microsoft không thể lọc mọi thứ thay cho tất cả mọi người
      Cần có công cụ và thông lệ ở cấp cộng đồng
    • Vì GitHub thuộc sở hữu của Microsoft nên nó cũng có liên quan tới kho package GoLang
      Nếu xuất hiện các ràng buộc thương mại hay giới hạn quy trình build thì có thể dẫn tới vấn đề rất lớn
    • Cũng khó mà phủ nhận rằng cả hai công ty đều chỉ có mức độ bảo mật ở mức bình thường
    • Mã độc này tạo kho lưu trữ theo cùng một mẫu, nên lẽ ra chỉ cần quy tắc đơn giản cũng có thể phát hiện được
  • Tôi từng thắc mắc vì sao chỉ NPM là mục tiêu tấn công
    Python hay Java cũng rất phổ biến, nhưng gần đây lại khá yên ắng

    • NPM cho phép thực thi lệnh tùy ý qua post-install hook, và
      văn hóa phụ thuộc theo dải phiên bản khiến việc lây lan diễn ra rất nhanh
      Với Java, việc cố định một phiên bản cụ thể là chuyện phổ biến nên loại sự cố này hiếm hơn
    • Node có thư viện chuẩn nhỏ và phụ thuộc mạnh vào cộng đồng
      Vì vậy một package có thể kéo theo hàng chục phụ thuộc con
    • JS là ngôn ngữ phổ biến nhất trên GitHub nên bề mặt tấn công rộng,
      lại có nhiều lập trình viên ít kinh nghiệm nên bảo mật yếu hơn
    • Cộng đồng JS mắc “ám ảnh với phiên bản mới nhất” khá nặng
      Các hệ sinh thái ngôn ngữ khác thường kiểm chứng rồi mới cập nhật, còn JS thì nâng cấp ngay lập tức
    • NPM có ranh giới bảo mật yếu
      Nó từ lâu đã cho phép chạy script thoải mái khi cài đặt, còn JVM hay Python thì không như vậy
  • Thêm vào .npmrc

    ignore-scripts=true
    

    có thể giảm bớt vector tấn công
    bài viết liên quan

    • Tôi muốn biết có cách nào kiểm tra trước package nào có preinstall/postinstall hook hay không trước khi cài không
    • Nếu “ignore scripts” an toàn như vậy thì tại sao nó lại chỉ là một tùy chọn,
      và khi tắt script thì có rủi ro làm hỏng phụ thuộc hay không cũng là điều đáng hỏi
    • Nhưng rốt cuộc, nếu chạy JS trong môi trường Node thì vẫn không thể ngăn truy cập biến môi trường hay file
    • Hoặc đơn giản là dùng pnpm cũng là một cách
  • Điều đáng lo nhất trong đợt tấn công này là đánh cắp thông tin xác thực
    Nếu bạn đã cài package bị nhiễm, biến môi trường hoặc token trong .npmrc có thể đã bị rò rỉ
    Cần xoay vòng token và API key ngay lập tức
    Việc xoay vòng định kỳ không phải là phản ứng sau xâm nhập mà là biện pháp phòng ngừa từ trước

    • Nếu lập trình viên còn tái sử dụng mật khẩu thì đó thực sự là vấn đề rất nghiêm trọng
      Không nên lưu thông tin xác thực trong biến môi trường hay file; hãy dùng khóa bảo mật hoặc file mã hóa
    • Nếu chưa biết mình có bị nhiễm hay không, trước hết nên theo thứ tự phát hiện nhiễm → dọn dẹp → xoay vòng token
    • Đợt tấn công này nguy hiểm hơn vì không chỉ là lây nhiễm đơn thuần mà là bắt toàn bộ hệ sinh thái làm con tin
      Nó giống như cài giao dịch độc hại vào một sổ cái phân tán
    • Bí mật nhất định phải được lưu trong kho bí mật (secret locker)
      Vấn đề là đến giờ vẫn còn nhiều dịch vụ mặc định lưu dạng văn bản thuần
    • Và mã độc này còn tìm cách phá hủy dữ liệu khi việc lây lan dừng lại
  • Những cuộc tấn công kiểu này lặp đi lặp lại, nên tôi thắc mắc vì sao hệ thống phát hiện dựa trên AI vẫn không hoạt động
    Microsoft quảng bá AI nhiều như vậy, nhưng có vẻ lại không dùng nó cho bảo mật GitHub

    • Tuy vậy, câu “AI đã phát hiện cuộc tấn công” giờ đã thành sáo ngữ marketing bảo mật
      giống thời người ta gắn nhãn mọi thứ firewall chặn được là tấn công, khiến ý nghĩa dần nhạt đi
    • Công ty chúng tôi dùng SonaType Lifecycle, và họ nói nó có thể chặn những cuộc tấn công kiểu này bằng AI
      Ở bên trong có SonaType IQ Server hỗ trợ việc đó
    • “AI” hiện nay là mô hình sinh, nên trọng tâm nằm ở tạo ra hơn là đánh giá
      Thực tế đã có trường hợp dự án curl bị spam báo cáo bảo mật do AI tạo ra
  • Tôi tự hỏi còn lý do gì để tiếp tục cho phép script postinstall nữa
    Có lẽ nên hỏi người dùng xem có muốn chạy hay không sẽ tốt hơn

    • Nhưng phần lớn người dùng rồi cũng sẽ bấm “có”,
      còn máy chủ CI thì cần cài đặt không tương tác, nên trên thực tế điều này khá khó khả thi
  • Bài viết rất sâu sắc, nhưng tôi thấy tiếc vì đoạn cuối lại kết thúc bằng quảng bá tính năng bảo mật của GitLab

    • Với người dùng GitLab thì có thể nó vẫn hữu ích
    • Dù sao điều đó cũng không làm giảm giá trị của chính những insight trong bài