1 điểm bởi GN⁺ 5 giờ trước | 1 bình luận | Chia sẻ qua WhatsApp
  • Một lập trình viên ở Canada đã bị tấn công dụ cài backdoor dưới vỏ bọc phỏng vấn VC giả, và luồng tấn công được thiết kế sát với công việc của lập trình viên đến mức bị nghi là nhắm vào người duy trì gói trên crates.io
  • Kho mồi nhử trông như một ứng dụng TypeScript tên “Ticket Harbor”, nhưng dùng patch-packagetypescript+5.9.2.patch để giấu mã độc trong đường dẫn thực thi TypeScript
  • Stub được chèn vào giải mã base64 và XOR rồi chạy bằng new Function(...); sau đó qua chunk ẩn trong operators/3.png và stub WASM để khởi chạy payload giai đoạn 2 dung lượng 1,68MB trong một tiến trình Node riêng
  • Payload cuối “PinpinRAT” tạo cặp khóa RSA-2048 và khóa phiên AES-256-CBC, hỗ trợ thu thập dấu vân tay host, tải lên/tải xuống tệp, thực thi tiến trình, thao tác hệ thống tệp, truy vấn DNS và tự gỡ bỏ
  • Nếu đã chạy kho này, cần lập tức ngắt mạng và đổi thông tin xác thực từ thiết bị khác, đồng thời ứng phó với giả định rằng cookie và cả bí mật được bảo vệ bằng mật khẩu có thể đã bị đánh cắp

Cuộc tấn công nhắm vào lập trình viên bắt đầu từ cuộc phỏng vấn giả

  • Kẻ tấn công tiếp cận bằng một nhân vật giả tự xưng thuộc “Lua Ventures”
    • Lua Ventures được giới thiệu là một VC trong lĩnh vực DeFi có trụ sở tại Singapore, nhưng trên thực tế đã ngừng hoạt động
    • Tên nhân vật không được công bố vì có thể gây nhầm lẫn với những người thật trùng tên
  • Email trông có vẻ thuyết phục và cũng chứa liên kết tới một hồ sơ LinkedIn bình thường nhưng có vẻ hợp lệ
  • Chúng nhắc đến LyrasingRoadpay như các công ty đầu tư đang tìm cố vấn
    • Hai công ty này có hiện diện web cơ bản, nên trông giống công ty giai đoạn đầu hơn là đồ giả
    • Vẫn còn snapshot trên archive.org của trang Roadpay
  • Sau vài lượt email, hai bên tiếp tục bằng một cuộc gọi Google Meet
    • Người trong cuộc gọi là một nam giới có giọng Đức và nói rằng đang di chuyển
    • Bản thân cuộc gọi không có điểm gì rõ ràng bất thường

Kích hoạt thực thi ngụy trang thành “bài kiểm tra”

  • Sau cuộc gọi, kẻ tấn công đề xuất một “bài kiểm tra” và gửi kho mã
  • Kho này được dựng như một ứng dụng bán vé phà tên “Ticket Harbor”
  • Tệp task.txt đi kèm chứa danh sách nhiệm vụ nhàm chán nhưng hợp lý, và cuối cùng có hướng dẫn thực thi
    • Nội dung yêu cầu chạy typecheck của kho, test suite và các lệnh build desktop/server liên quan
  • Chính hướng dẫn này là trigger lây nhiễm thực sự
    • Payload có thể được thực thi ngay khi TypeScript chạy, như npm run typecheck, build, dev, hoặc khi import typescript.js

Chuỗi thực thi ẩn trong bản vá TypeScript

  • Tín hiệu cảnh báo đầu tiên là kho này trông giống một bài tập TypeScript
    • Yêu cầu giống bài tuyển dụng TypeScript hơn là phân tích kiến trúc
    • Khi đưa kho vào Claude để kiểm tra nhanh, các dấu hiệu bất thường liên quan đến patch-package lộ ra
  • Thư mục patches/ nhiều bất thường
    • Một số bản vá trông có vẻ bình thường, đóng vai trò nhiễu để che giấu payload thật
    • Ví dụ gồm sumchecker+3.0.1.patch, @electron+get+2.0.3.patch, extract-zip+2.0.1.patch
  • Mã độc cốt lõi nằm trong typescript+5.9.2.patch
    • Chèn một stub chạy ngay vào đầu typescript.js_tsc.js
    • Stub giải mã chuỗi base64, giải mã XOR từng byte với khóa 73, rồi chạy bằng new Function(...)
    • require, Buffer, WebAssembly, process, __dirname được truyền vào hàm thực thi
  • Chuỗi thực thi đi qua nhiều giai đoạn
    • Bốn hook postinstall chạy patch-package
    • Một trong số đó áp dụng git update-index --skip-worktree cho tệp patch để ẩn khỏi git status
    • Loader đọc chunk ẩn gắn phía sau tệp operators/3.png
    • Chạy một stub WASM nhỏ trong chunk wAsm tùy biến
    • Thực thi payload giai đoạn 2 đã bị làm rối dung lượng 1,68MB dưới dạng một tiến trình Node riêng chạy lặng lẽ
  • Mã tấn công được thiết kế để giảm dấu vết sau khi chạy
    • Ẩn bản vá bằng git skip-worktree
    • Dropper xóa các dòng nó đã chèn khỏi tệp patch sau lần chạy đầu tiên
    • Thư mục tạm của giai đoạn 2 tự xóa khi thực thi

Chức năng của PinpinRAT

  • Payload cuối được gọi là “PinpinRAT”
    • Tên này được đặt vì các chuỗi nội bộ, và không loại trừ khả năng nó được biết đến bằng tên khác
    • Không tìm thấy tham chiếu nào khác trên mạng
  • Payload nằm trong nhiều lớp làm rối
    • obfuscator.io
    • Hai lớp base64 bổ sung
  • Khi khởi động, RAT thu thập dấu vân tay host và rò rỉ ra ngoài
    • Địa chỉ IP mặc định và toàn bộ danh sách IP
    • Tên người dùng từ os.userInfo().username
    • Hostname
    • OS type, release, platform, architecture
    • PID tiến trình và toàn bộ process.argv
    • Phiên bản Node
  • Nó cũng có cấu trúc mã hóa
    • Tạo cặp khóa RSA-2048 cục bộ
    • Tạo khóa phiên AES-256 ngẫu nhiên aes_psk
    • Lưu lượng sau đó được mã hóa bằng AES-256-CBC và gắn thẻ toàn vẹn HMAC-SHA256
  • Các lệnh được hỗ trợ cung cấp khả năng ở mức trojan truy cập từ xa
    • env: chuyển process.env thành chuỗi JSON rồi gửi đi
    • upload: đọc và rò rỉ đường dẫn tệp tùy ý
    • download: ghi byte do kẻ tấn công cung cấp vào đường dẫn có thể ghi
    • spawn: thực thi tiến trình tùy ý, kèm mở rộng shell tùy chọn
    • ls, cd, pwd, cp, mv: thao tác hệ thống tệp thông thường
    • dns: phân giải tên tùy ý qua resolver được chỉ định
    • dismantle: tự gỡ bỏ

Chỉ dấu xâm nhập và ứng phó ngay lập tức

  • Ảnh chứa payload không bị bất kỳ engine AV nào phát hiện trên VirusTotal
  • Nếu đã chạy, cần lập tức cô lập hệ thống khỏi mạng
  • Thông tin xác thực phải được thay đổi từ thiết bị khác
    • Cần xem cả cookie và bí mật được bảo vệ bằng mật khẩu là đã bị xâm phạm
  • Chỉ dấu xâm nhập liên quan đến PinpinRAT như sau
    • C2: 89.124.107.161:80
    • Tác vụ theo lịch trên Windows: PinpinWrappedJs
    • Ngụy trang tiến trình trên macOS: com.apple.WebKit.Networking
    • Biến môi trường: NODT_PAYLOAD_PATH, NODT_PAYLOAD_ARGS
    • Guard chunk PNG: WASMPACK (wAsm)
    • PINPIN_NO_AUTOSTART=1: ngừng persistence
    • Cronjob chứa mutex.js: chỉ có thể tồn tại khi có quyền RAT, và có thể không có trên macOS
    • Chuỗi anchor trong typescript.js: 12ff4b51, ticket-harbor-tsc-shim-anchor
    • typescript+5.9.2.patch chứa payload
    • Thư mục artifact:
      • macOS: ~/Library/Caches/runtime-cache/.cache-<randomhex>/
      • Linux: /tmp/.cache-<randomhex>/
      • Windows: %TEMP%\.cache-<randomhex>\
      • Bên trong có payload.jsmutex.js

Những tín hiệu cảnh báo chỉ thấy rõ về sau

  • Nhìn kỹ, trong các tin nhắn có những cách diễn đạt trông như dấu vết LLM
  • Hồ sơ LinkedIn thoạt nhìn có vẻ bình thường, nhưng danh sách bằng cấp/chứng chỉ khá gượng gạo và cũng không có hoạt động thực tế
  • Các liên kết mạng xã hội trên website có lịch sử thật, nhưng tên đã được đổi vào tháng 11/2025
    • Bài đăng thiếu tính cụ thể và gần giống những lời khen mơ hồ về các công ty
  • Website của các công ty trông hào nhoáng nhưng gần như không có hiện diện thực tế
  • Kẻ tấn công không gửi lời mời lịch chính thức mà chỉ gửi thời gian và Google Meet
    • Trong cuộc gọi, camera luôn tắt và người đó nói rằng đang di chuyển
  • Các yếu tố cùng xuất hiện: VC có trụ sở tại Singapore, hoạt động theo múi giờ CEST, tiếp cận lập trình viên Canada, tên miền .cc nhắm tới khách hàng Mỹ
    • Điều này khiến việc xác minh độ tin cậy của các tổ chức ở xa trở nên khó hơn
  • Từng tín hiệu riêng lẻ không đủ rõ ràng, nhưng khi nhiều đèn vàng tích tụ cùng nhau thì đó là một mẫu hình có thể xem là đèn đỏ

Bên đứng sau và phạm vi tấn công

  • Không thể xác định chắc chắn bên đứng sau
  • Cuộc tấn công nhắm vào lập trình viên và bao gồm nhân vật giả, câu chuyện che đậy thuyết phục, nhiều website giả, lịch trình kiên nhẫn và bẫy git tinh vi
  • Nó tương đồng với luồng “lừa phỏng vấn giả” được nhiều tác nhân sử dụng trong năm 2026
  • Cộng đồng Rust trên Reddit cũng nhắc đến một trường hợp bị nhắm mục tiêu tương tự
  • Cách làm này bám sát workflow của lập trình viên đến mức nếu được dựng dưới dạng script build.rs cài bẫy trong kho Rust thì rất có thể đã lừa được nạn nhân

1 bình luận

 
Ý kiến trên Lobste.rs
  • Việc tiêu đề suy đoán rằng đây có thể là kẻ tấn công được nhà nước hậu thuẫn khiến tôi thấy khó hiểu. Ở đây không có phần nào có vẻ nhất thiết cần mức độ chuẩn bị hay độ phức tạp như vậy
    Có thể tưởng tượng khả năng đó, nhưng nó chỉ có vẻ hợp lý ở mức tương tự các kịch bản khác

    • Có lẽ vì kiểu lừa đảo tinh vi này tốn nhiều tài nguyên nên khá hiếm gặp. Khi thấy một vụ lừa đảo tinh vi, người ta dễ cảm thấy có thể là do nhà nước hậu thuẫn
      Dù vậy, gần như chắc chắn tôi nghĩ đây không phải là kẻ tấn công được nhà nước hậu thuẫn. Loại tấn công này giờ không còn khó đến vậy
  • Việc cuộc tấn công này giống với ví dụ giả định tôi mô tả trong bài blog một tuần trước thật sự chỉ là trùng hợp: the hypothetical I describe in my blog post from a week ago
    Tôi chỉ chọn một trong vài kiểu tấn công có vẻ hợp lý làm ví dụ cho thấy ngay cả chuyên gia am hiểu công nghệ cũng có thể bị lừa. Tôi đã thấy nhiều vụ lừa đảo tinh vi nhắm vào con người gia tăng, nhưng không biết rằng đang có một xu hướng lừa đảo phỏng vấn. Vì vậy khi biết về cuộc tấn công này, tôi thấy hơi rợn người

  • Tuần trước tôi nhận được một đề nghị phỏng vấn y hệt từ D____ S_____ của Lua Ventures. Tôi đã phớt lờ như hầu hết thư rác từ nhà tuyển dụng, và làm vậy là đúng

    • Tôi tò mò không biết đó có phải là người trong mảng Rust không. Những nhân vật chủ chốt của cộng đồng Rust đã bị Lua nhắm tới, nên tôi muốn biết việc này chỉ giới hạn ở Rust hay rộng hơn
  • Hình như vài ngày hoặc vài tuần trước đã có một bài gửi kiểu này

  • Việc nói “trông giống email thật” làm tôi ngạc nhiên. Câu chữ rõ ràng là do LLM tạo ra đến mức tôi nghĩ mình đã nghi ngờ ngay từ câu thứ hai

    • Với tôi thì nó không rõ ràng như vậy. Nó chỉ giống văn phong kiểu LinkedIn. Văn phong đó cũng thường nghe như do LLM viết, nhưng mùi quá giống nhau nên tôi không chắc mình có khả năng phân biệt hai thứ đó không