Theo nghiên cứu mới từ JFrog, một chiến dịch gồm 148 gói npm giả dạng các web proxy dành cho học sinh đã biến trình duyệt của người truy cập thành một botnet tấn công từ chối dịch vụ phân tán (DDoS) trong khoảng hai tuần vào tháng 5.
Các gói này không nhắm vào các nhà phát triển cài đặt chúng. Những kẻ vận hành đã sử dụng registry như một nơi lưu trữ miễn phí cho một trang web proxy bị gài bẫy, lợi dụng các học sinh muốn vượt rào bộ lọc web của trường học để cung cấp lưu lượng tấn công.
Các gói được phát hành dưới những cái tên như charlie-kirk, ilovefemboys, và miguelphonk, mỗi gói mang theo một ứng dụng proxy mang thương hiệu "Lucide" và được ngụy trang dưới dạng trang đích gia sư có tên là Riverbend Tutoring hoặc Northstar Tutoring.
Về mặt bề ngoài, proxy này hoạt động bình thường, giúp học sinh vượt qua các bộ lọc nội dung để truy cập trò chơi và các trang web bị chặn. Tuy nhiên, bên dưới đó, nó tải một trình nạp mã từ xa mà kẻ vận hành có thể thay đổi payload tùy ý, cùng với một trình tạo luồng lụt WebSocket được xây dựng để giao tiếp với giao thức proxy Wisp. Bất kỳ ai mở trang web đều gia nhập "đội quân" tấn công mà không hề hay biết.
Không có hoạt động nào trong số này chạy tại thời điểm cài đặt. Các gói không chứa mã hook vòng đời và không có script xây dựng gốc, và chúng chưa bao giờ được viết để được nhập (import) vào một dự án.
Cuộc tấn công này khác với sâu Shai-Hulud tự nhân bản đánh vào hơn 500 gói vào tháng 9 năm 2025 để thu thập bí mật của nhà phát triển, hay vụ tấn công phishing nhắm vào maintainer qix đã chèn mã rút tiền ảo vào chalk, debug và 16 gói phổ biến khác. Những cuộc tấn công đó kích hoạt ngay khi gói được cài đặt và nhắm vào những người xây dựng phần mềm. Ngược lại, chiến dịch này bỏ qua quy trình xây dựng (build pipeline) và chờ đợi trong một tab trình duyệt.
Giải mã kỹ thuật chiến dịch Lucide
JFrog đã đi sâu vào phân tích và giải mã gói entry bundle của ứng dụng, một dòng JavaScript duy nhất nặng 5,4 MB, sau khi giải mã đã lộ ra hơn 20.600 dòng mã có thể đọc được. Họ cũng khôi phục các payload lưu trữ từ Wayback Machine để tái dựng dòng thời gian của chiến dịch.
Hai mô-đun nằm dưới lớp phần mềm quảng cáo (adware), cả hai đều kích hoạt trước khi giao diện React được hiển thị.
Mô-đun G2: Trình nạp mã từ xa
Mô-đun đầu tiên, được JFrog gọi là G2, là một trình nạp script từ xa và nó thực hiện việc này theo cách không an toàn nhất có thể. Nó tải JavaScript từ một kho lưu trữ GitHub thông qua CDN jsDelivr, trỏ vào nhánh main có thể thay đổi thay vì một commit cố định, không kiểm tra Subresource Integrity, và chạy bất kỳ mã nào trả về với quyền hạn origin của chính trang proxy: toàn quyền truy cập vào cookie, local storage và các endpoint cùng nguồn.
Một chính sách no-referrer giúp yêu cầu không tiết lộ nguồn gốc. Bất kỳ ai nắm giữ tài khoản GitHub đứng sau đó đều có thể thay đổi mã đang chạy trong trình duyệt của mọi khách truy cập bất cứ khi nào họ muốn.
Vào thời điểm JFrog kiểm tra, kho lưu trữ đã trả về lỗi 404, nhưng một bản sao lưu từ ngày 30 tháng 5 đã bảo tồn những gì nó từng phục vụ: một cuộc tấn công HTTP flood thô sơ. Cứ sau mỗi 500 mili giây, script sẽ tạo một chuỗi mới dài một triệu ký tự và gửi nó dưới dạng POST no-cors tới cdn.caan.edu, được JFrog xác định là miền công cộng của một trường điều dưỡng ở Matteson, Illinois.
Các yêu cầu này không bao giờ đợi phản hồi, vì vậy chúng chồng chất lên nhau. JFrog ước tính mỗi khách truy cập đang hoạt động sẽ đẩy khoảng 2 MB lưu lượng tải lên mỗi giây, nghĩa là một nghìn tab proxy đang mở sẽ đẩy khoảng 2 GB mỗi giây vào mục tiêu.
Mô-đun I2: Tấn công WebSocket Control-Plane
Mô-đun thứ hai, I2, nguy hiểm hơn. Nó tải một tệp văn bản thô, websocket.txt, chứa URL WebSocket mục tiêu và số lượng socket bị giới hạn từ 1 đến 1.024, sau đó mở bấy nhiêu kết nối trong một vòng lặp so le. Cấu hình được lưu trữ đã nhắm mỗi trình duyệt vào 30 kết nối tới một endpoint Wisp trên lunaron[.]top, bản thân nó là một proxy đang hoạt động để chèn quảng cáo độc hại.
Wisp là một giao thức Mercury Workshop có mức hao phí thấp để tạo đường hầm cho nhiều socket TCP và UDP qua một WebSocket duy nhất. Khi đã kết nối, mỗi trình duyệt sẽ đặt socket của nó ở chế độ nhị phân và cứ sau mỗi 100 mili giây lại gửi một khung Wisp CONNECT hợp lệ, sau đó là khung CLOSE, cả hai đều trỏ vào localhost:1. Mục tiêu không phải là máy của học sinh, mà là máy chủ Wisp từ xa ở đầu kia của kết nối.
Điều này biến nó thành một cuộc tấn công mặt phẳng điều khiển (control-plane) thay vì tấn công lưu lượng (volumetric). Một trình duyệt duy nhất chạy đủ 1.024 socket có thể ép một máy chủ Wisp phân bổ và đóng khoảng 10.240 kết nối mỗi giây, đồng thời ghi hơn 20.000 dòng nhật ký trong cùng khoảng thời gian đó.
Nguồn gốc và Biện pháp khắc phục
Cơ sở hạ tầng này được phân cụm chặt chẽ và không được xây dựng để ẩn mình. JFrog đã truy nguyên các bản build đến một tổ chức GitHub có tên lucideproxy, với các tài khoản được đăng ký cách nhau vài giây. Một tài khoản đã đẩy 116 gói trong vòng chưa đầy 35 phút và npm đã không làm gì để ngăn chặn nó.
Mặc dù nhiều gói đã bị xóa khỏi npm và thay thế bằng thông báo bảo mật, JFrog lưu ý rằng khả năng DDoS không hề biến mất mà chỉ bị tắt đi. Những kẻ vận hành vẫn giữ khả năng tái vũ trang nó chỉ bằng một commit vào nhánh GitHub, mà không cần cập nhật gói npm.
Các quản trị viên trên mạng trường học và doanh nghiệp nên chặn các miền của chiến dịch ở cấp độ DNS. Những máy chủ chứa script và quảng cáo nhưwoofbeginner[.]comvàc.vipersfutbol[.]comlà những nơi cần chặn đầu tiên.
Bất kỳ ai đã từng tải một trong các trang web proxy này nên xóa bộ nhớ đệm trình duyệt và local storage, đồng thời hủy đăng ký (unregister) bất kỳ service worker nào được để lại bởi các miền liên quan. Các nhóm có môi trường build đã tải các gói được nêu tên nên gỡ bỏ chúng khỏi manifest và lockfile để xây dựng lại hệ thống sạch sẽ.