Skip to main content

Command Palette

Search for a command to run...

CloudSyncD: Backdoor macOS giả Zoom, giấu mật khẩu bằng zero-width

Updated
•30 min read•View as Markdown
CloudSyncD: Backdoor macOS giả Zoom, giấu mật khẩu bằng zero-width

Dòng backdoor macOS mới CloudSyncD mượn vỏ bọc bộ cài đặt Zoom giả mạo, dẫn dụ nạn nhân tự tay vượt rào Gatekeeper. Mã độc lừa lấy mật khẩu qua hộp thoại giả, xác thực bằng dscl rồi giấu vào tệp cấu hình bằng ký tự Unicode vô hình (zero-width). Mật khẩu chỉ phục vụ lệnh sudo leo quyền root cục bộ. CloudSyncD không phải infostealer vì mật khẩu không bị gửi ra ngoài mạng.


Executive Summary

Ngày 15/09/2026, Các chuyên gia an ninh mạng phát hiện dropper macOS mang tên CloudSyncD trên VirusTotal ẩn mình trong gói cài đặt Zoom giả mạo. Mã độc sử dụng kỹ thuật dẫn dụ người dùng tự tay vượt rào Gatekeeper và chiếm đoạt mật khẩu đăng nhập qua hộp thoại uỷ quyền giả.

CloudSyncD không phải là mã độc infostealer: mật khẩu không bị gửi ra ngoài mạng và mã độc không trộm dữ liệu trình duyệt, Keychain hay ví tiền mã hoá. Mật khẩu chỉ được giấu trong tệp cấu hình cục bộ data.json bằng ký tự Unicode vô hình để cấp cho lệnh sudo leo quyền root máy tính.

Rủi ro lớn nhất là thiết bị bị chiếm quyền root qua backdoor nhị phân chạy ngầm, cho phép operator đẩy xuống bất kỳ payload Mach-O nào tùy ý. Mật khẩu quản trị viên nằm lại trên đĩa: không được mã hoá, chỉ được che giấu trong data.json.

Hành động cấp thiết nhất: Rà soát ngay lệnh /usr/bin/dscl chứa -authonly trong nhật ký EDR, kiểm tra tệp data.json chứa ký tự zero-width, và đổi ngay mật khẩu quản trị viên nếu thiết bị từng chạy bộ cài này.


Sơ đồ Kill Chain & Luồng tấn công

Chuỗi thực thi của CloudSyncD trải qua hai giai đoạn riêng biệt, kết hợp giữa kỹ thuật thao túng tâm lý (social engineering) và các lời gọi hệ thống native:

Toàn bộ chuỗi lây nhiễm được Jamf kiểm chứng qua môi trường sandbox các bước tuần tự:

  1. Nạn nhân khởi chạy tệp thực thi app_installer từ phân vùng đĩa ảo Zoom đã gắn kết (mounted volume).

  2. Cửa sổ tiến trình giả mạo mang tiêu đề "Downloading Zoom..." xuất hiện và tự động tăng phần trăm hiển thị mà không hề có hoạt động tải tệp thực tế nào diễn ra.

  3. Hộp thoại uỷ quyền giả mạo bật lên đòi người dùng cung cấp mật khẩu đăng nhập hệ thống.

  4. Mật khẩu được kiểm tra xác thực thông qua tiện ích dòng lệnh dscl, và hộp thoại sẽ liên tục lặp lại cho đến khi mật khẩu nhập vào chính xác.

  5. Dropper thử tải một gói ứng dụng ba lần liên tiếp với khoảng thời gian chờ tăng dần, nhưng thất bại do tham số URL rỗng.

  6. Tệp data.json được tạo ra để lưu trữ mật khẩu bị che giấu bằng các ký tự ngẫu nhiên và chỉ mục Unicode vô hình.

  7. Thử nghiệm khởi chạy không tệp (fileless) thông qua đường dẫn /dev/fd bị hệ điều hành chặn lại, buộc mã độc chuyển hướng sang phương án ghi tệp tạm ra ổ đĩa.

  8. Giai đoạn hai được kích hoạt với đặc quyền root bằng lệnh sudo, sử dụng chính mật khẩu vừa thu thập được qua luồng dữ liệu chuẩn stdin.

  9. Implant tạo cấu trúc thư mục làm việc, bắt đầu ghi nhật ký mã hoá và gửi tín hiệu beacon định kỳ từ 8 đến 16 giây một lần về máy chủ điều khiển.


Phân tích kỹ thuật chuyên sâu

Initial Access: Mồi nhử Zoom và kỹ thuật dẫn dụ vượt rào Gatekeeper

Mã độc được đóng gói dưới dạng ảnh đĩa Apple Disk Image (Zoom.dmg). Jamf không nêu kênh phát tán tệp này tới nạn nhân. Khi người dùng mở tệp, hệ điều hành gắn kết volume ảo có tên "Zoom". Giao diện hiển thị tương tự ứng dụng tiêu chuẩn, gồm biểu tượng Zoom ở bên trái và liên kết tắt (alias) tới thư mục /Applications ở bên phải.

Cửa sổ cài đặt Zoom.dmg giả mạo kèm chỉ dẫn vượt rào Gatekeeper

Hình 1: Cửa sổ volume Zoom giả mạo chứa chỉ dẫn 4 bước vượt rào Gatekeeper trong System Settings.

Điểm khác biệt mấu chốt nằm ở hình nền của cửa sổ cài đặt. Kẻ tấn công in sẵn bảng chỉ dẫn "Setup" gồm bốn bước chi tiết. Nạn nhân được hướng dẫn truy cập Apple menu > System Settings > Privacy & Security, cuộn chuột tới mục Security, nhấp vào nút Open Anyway và nhập mật khẩu quản trị viên.

Lý do kẻ tấn công phải xây dựng chỉ dẫn này xuất phát từ cơ chế kiểm soát mã nguồn của Apple. Gói ứng dụng giả mạo mang nhãn ký ad-hoc, hoàn toàn không có Apple Developer ID và notarization ticket. Theo mặc định, Gatekeeper trên macOS sẽ chặn đứng việc khởi chạy ứng dụng khi nhấp đúp chuột. Bằng cách thao túng tâm lý, kẻ tấn công lừa người dùng tự cấp ngoại lệ Gatekeeper cho chính ứng dụng độc hại.

Thực thể thực thi chính của giai đoạn một nằm tại đường dẫn:

Zoom.app/Contents/MacOS/app_installer

Bẫy mật khẩu AuthDialog và điểm yếu xác thực lộ tham số qua dscl

Sau khi vượt qua Gatekeeper, mã độc khởi chạy tệp nhị phân app_installer. Một lớp Objective-C được tác giả đặt tên là AuthDialog lập tức khởi tạo hộp thoại đồ hoạ mạo danh khung cảnh báo xác thực uỷ quyền của macOS.

Hộp thoại mạo danh hệ thống yêu cầu mật khẩu quản trị viên

Hình 2: Hộp thoại giả mạo lớp AuthDialog đòi mật khẩu người dùng admin để thực thi mã độc.

Hộp thoại mang biểu tượng ổ khoá đặc trưng với tiêu đề "Application wants to make changes." cùng thông điệp:

"Enter your password to allow this." / "To allow this, enter your password."

Để phân tán sự chú ý và tạo cảm giác ứng dụng đang được cài đặt thực sự, một cửa sổ tiến trình hiển thị tiêu đề "Downloading Zoom..." xuất hiện song song. Thanh tiến trình này tự động cập nhật phần trăm tăng dần một cách độc lập mà không hề có bất kỳ gói dữ liệu mạng nào được tải về máy.

Cửa sổ tiến trình giả mạo Downloading Zoom

Hình 3: Cửa sổ tiến trình tải giả mạo tự nhảy phần trăm nhằm đánh lừa sự chú ý của nạn nhân.

Khi người dùng nhập chuỗi ký tự vào ô mật khẩu, app_installer không gửi mật khẩu đi đâu cả, mà kiểm tra tính chính xác cục bộ trên máy thông qua công cụ dòng lệnh Directory Service Command Line (dscl):

/usr/bin/dscl /Local/Default -authonly <user> <password>

Nếu mật khẩu không đúng, hộp thoại sẽ tiếp tục xuất hiện đòi hỏi nhập lại cho tới khi câu lệnh dscl trả về kết quả thành công.

Dưới góc nhìn giám sát an ninh (SOC), việc thực thi lệnh dscl với cú pháp trên để lộ một điểm yếu lớn về mặt ẩn mình. Mật khẩu của người dùng xuất hiện trực tiếp dưới dạng văn bản rõ (cleartext) trong danh sách đối số dòng lệnh (argv). Mọi sensor ghi nhận process execution, ví dụ EDR dùng Endpoint Security Framework của Apple, đều thấy đối số này. Jamf đánh giá đây là "mỏ neo phân tích có độ trung thực cao nhất" trong toàn bộ chuỗi tấn công.

Tuy nhiên, đội ngũ SOC cần đặc biệt lưu ý nguy cơ an toàn dữ liệu nội bộ. Do dòng lệnh ghi mật khẩu rõ, hệ thống SIEM thu thập log EDR cần cấu hình cơ chế che giấu dữ liệu (masking) phù hợp [Inference]. Thao tác này nhằm tránh việc vô tình làm lộ lọt thông tin xác thực của nhân viên nội bộ trong cơ sở dữ liệu nhật ký.

Kỹ thuật che giấu mật khẩu trong tệp cấu hình bằng ký tự Unicode vô hình

Sau khi xác thực thành công, mã độc không gửi mật khẩu ra ngoài hạ tầng mạng. Thay vào đó, nó ghi dữ liệu vào một tệp cấu hình ngụy trang mang tên data.json với phân quyền tập tin 0644.

Trên bản phát triển (dev build), tệp được lưu tại ~/.config/zoom/data.json. Trên bản triển khai thực tế (live build), đường dẫn chuyển thành ~/.config/cloudsync/data.json với trường ứng dụng tương ứng. Nội dung tệp trông hoàn toàn giống một tệp lưu tuỳ chọn hiển thị bình thường:

{
  "app": "Zoom",
  "version": "1.0.0",
  "settings": {
    "theme": "system",
    "notifications": true,
    "analytics": false,
    "language": "en-US"
  },
  "cache": "BH6ijfeU3fjO1iQX1kkFt98I7hmPDsGSRsOOpJrCsxsVs9MR3mKEat9GqMs2VjA7YWRtaW4=sQgePSYjtexrHOdpJskj1nYC9uAsS8rUkzGIP9UUvH6gy",
  "lastUpdate": 1789494044
}

Cơ chế che giấu dựa trên hai trường cache và version:

  • Mật khẩu đăng nhập được mã hoá Base64 và chôn giấu vào giữa một chuỗi ký tự ngẫu nhiên dài trong trường cache. Hai bên của chuỗi mật khẩu được bao bọc bởi một lớp đệm (padding filler) ngẫu nhiên có độ dài dao động từ 32 đến 64 ký tự. Bản thân tệp JSON không hề có bất kỳ ký hiệu nào đánh dấu điểm bắt đầu hay kết thúc của đoạn dữ liệu thật.

  • Vị trí toạ độ của mật khẩu được mã hoá vào trường version. Phía sau chuỗi phiên bản nhìn thấy được 1.0.0 là một chuỗi gồm đúng 48 ký tự Unicode vô hình (zero-width characters), bao gồm U+200B (ZERO WIDTH SPACE) và U+200C (ZERO WIDTH NON-JOINER). Các ký tự này hoàn toàn không hiển thị trên giao diện người dùng hay các trình soạn thảo văn bản thông thường.

Khi thay thế các ký tự vô hình bằng các ký tự quan sát được, chuỗi phiên bản có hình thái như sau:

"version": "1.0.0.|...|||.|.....|.|..................|..........."

Giải mã chuỗi 48 ký tự vô hình này theo quy ước nhị phân nội bộ trả về hai thông số then chốt: độ lệch (offset) là 64 và độ dài (length) là 8. Jamf cho biết đọc 8 ký tự từ vị trí 64 của cache rồi giải mã Base64 sẽ ra mật khẩu đã nhập. Chúng tôi tự kiểm lại trên ví dụ của Jamf: chuỗi con là YWRtaW4=, giải mã ra admin, khớp với tài khoản trong ảnh hộp thoại (Hình 2).

Do độ dài của chuỗi đệm ngẫu nhiên thay đổi sau mỗi lần thực thi, toạ độ offset không bao giờ lặp lại giữa các lần lây nhiễm. Mục đích của kỹ thuật này [Inference] là xoá bỏ hoàn toàn các mẫu nhận diện chuỗi Base64 tĩnh. Cách làm này giúp né các công cụ secret scanning dựa trên mẫu chuỗi cố định.

Thử nghiệm nạp mã không tệp qua /dev/fd và phương án dự phòng leo quyền root

Mã độc dropper không tải giai đoạn hai từ máy chủ từ xa. Thay vào đó, tệp nhị phân hoàn chỉnh của Stage 2 (một tệp universal Mach-O dung lượng khoảng 756 KB ở bản dev) được nhúng trực tiếp bên trong cấu trúc của Stage 1. Ngoài ra, một bản sao của tệp này cũng tồn tại trên đĩa tại đường dẫn Zoom.app/Contents/Resources/cshelper.

Ban đầu, dropper tìm cách triển khai kỹ thuật thực thi không tệp (fileless execution). Nó ghi nhị phân Mach-O vào một bộ mô tả tệp ẩn danh (anonymous file descriptor) và gọi thực thi thông qua đường dẫn đại diện:

/dev/fd/<descriptor>

Mục tiêu của thao tác này là kích hoạt mã độc trực tiếp từ bộ nhớ nhằm né tránh ghi tệp ra đĩa. Tuy nhiên, trong môi trường thử nghiệm của Jamf, kỹ thuật này thất bại hoàn toàn. Dropper ghi nhận thông báo lỗi:

/dev/fd spawn failed rc=13

Nếu rc là mã errno thì 13 tương ứng EACCES (Permission denied) [Inference]. Jamf đánh giá kỹ thuật này sẽ thất bại trên phần lớn hệ thống macOS do System Integrity Protection (SIP).

Khi kỹ thuật nạp mã trong bộ nhớ thất bại, mã độc lập tức kích hoạt cơ chế dự phòng (fallback). Nó gọi hàm hệ thống mkstemp để tạo một tệp tạm thời trên đĩa với tiền tố cố định:

$TMPDIR/.s_XXXXXX

Ngay sau khi tệp được ghi ra đĩa, dropper dùng sudo để chạy tệp tạm này với quyền root, truyền mật khẩu vừa thu được qua luồng đầu vào tiêu chuẩn (stdin):

/usr/bin/sudo -S --preserve-env=HOME,USER $TMPDIR/.s_XXXXXX

Tham số -S hướng dẫn sudo đọc mật khẩu từ stdin thay vì mở terminal. Cờ --preserve-env=HOME,USER giữ biến HOME và USER của nạn nhân, nên implant chạy quyền root nhưng vẫn ghi dữ liệu vào thư mục home của người dùng [Inference]. Nhờ đó, tệp nhị phân giai đoạn hai chính thức vận hành với đặc quyền cao nhất của hệ điều hành.

Script hoán đổi bundle thất bại và cờ vô hiệu hoá mã nhúng

Dropper còn chuẩn bị một đoạn shell script ngắn nhằm thực hiện kỹ thuật hoán đổi gói ứng dụng (bundle swap). Đoạn mã này được lắp ráp tại thời điểm thực thi từ các phân đoạn bị xáo trộn (obfuscated fragments), sau đó ghi ra thư mục tạm của hệ thống dưới tên:

$TMPDIR/.app_swap_<pid>.sh

Script được thực thi bằng trình thông dịch /bin/bash. Mẫu mã nguồn được khôi phục nguyên vẹn như sau:

#!/bin/bash
sleep 2
rm -rf "<target app bundle>"
if [ $? -ne 0 ]; then
  open "<app bundle>"
  rm -f "<this script>"
  exit 0
fi
mv "<staged app bundle>" "<target app bundle>"
if [ $? -ne 0 ]; then
  open "<app bundle>"
else
  open "<app bundle>"
fi
rm -f "<this script>"

Ý đồ thiết kế của script là tạo độ trễ 2 giây cho phép dropper thoát an toàn. Sau đó script xoá bundle mà nạn nhân vừa mở, chuyển một bundle thay thế vào đúng vị trí và gọi open, để nạn nhân thấy một ứng dụng khởi động bình thường. Jamf không xác định được bundle thay thế là gì. Lệnh open được đặt ở cả hai nhánh thành công lẫn thất bại nhằm đảm bảo luôn có giao diện hiển thị cho người dùng.

Tuy nhiên, cơ chế tráo đổi bundle này chưa từng hoạt động trên bất kỳ mẫu nào được phát hiện. Trong mã nguồn, dropper dự định lấy gói thay thế từ hai nguồn: tải về qua tệp lưu trữ .r.tar.gz hoặc giải nén gói nhúng bên trong. Thực tế, đường dẫn URL tải gói trên tất cả các mẫu đều để trống, đồng thời dropper xuất nhật ký:

[installer] Skipping embedded app extraction (HAS_EMBEDDED_APP not defined)

Điều này chứng minh tính năng tráo đổi ứng dụng vẫn đang trong quá trình phát triển dở dang và chưa từng được kích hoạt thực tế. Do script có cơ chế tự xoá (rm -f "<this script>") ở cả hai nhánh rẽ, tệp .app_swap_<pid>.sh sẽ không tồn tại lâu dài trên đĩa cứng của nạn nhân.

Cơ chế bỏ qua chứng chỉ số TLS qua CSURLInsecureDelegate

Cả hai giai đoạn của CloudSyncD đều nhúng một lớp Objective-C chuyên biệt mang tên CSURLInsecureDelegate. Lớp này đảm nhận việc xử lý các thử thách xác thực TLS/SSL trong quá trình thiết lập kết nối mạng.

Thay vì kiểm tra chuỗi chứng chỉ theo chính sách bảo mật mặc định, CSURLInsecureDelegate gọi trực tiếp các hàm SecTrustCopyExceptions và SecTrustSetExceptions. Hành vi này khiến mã độc tự động chấp nhận bất kỳ chứng chỉ số nào mà máy chủ trình diện. Kể cả chứng chỉ đã hết hạn, tự ký (self-signed) hay sai tên miền đều được bỏ qua.

Hệ quả [Inference]: kết nối C2 không bị lỗi khi đi qua TLS inspection hay proxy giải mã SSL của doanh nghiệp. Mặt trái với kẻ tấn công: phía phòng thủ có thể đứng giữa và đọc được lưu lượng ở lớp TLS.

Stage 2 Implant: Cấu hình nhúng, thu thập thông tin host và dấu vết nhật ký

Tệp payload giai đoạn hai là một tệp nhị phân Universal Mach-O hỗ trợ cả hai kiến trúc vi xử lý Apple Silicon (arm64) và Intel (x86_64), được ký bằng chữ ký ad-hoc. Tác giả để lại tên tệp build trong chữ ký: nhánh arm64 mang định danh main-arm64.out trong khi nhánh Intel mang định danh cshelper.

Cấu hình hoạt động của implant được mã hoá trực tiếp bên trong vùng dữ liệu nhị phân và giải mã tại thời điểm nạp vào bộ nhớ. Cấu hình được khôi phục gồm các trường sau:

Trường cấu hình Giá trị bản phát triển (Dev) Giá trị bản triển khai (Live) Mục đích phân tích
C2 Endpoint hxxp://192[.]168[.]2[.]133:9099/ops hxxps://orchid-led[.]com/macos/jquery[.]js Máy chủ điều khiển và nhận dữ liệu điều tra
Install Directory ~/.local/share/cloudsync/ ~/.local/share/cloudsync/ Thư mục định vị cài đặt của mã độc
Payload Filename appd appd Tên tệp nhị phân dự kiến lưu trữ
Daemon Name cloudsyncd cloudsyncd Tên tiến trình dịch vụ ngầm
Process Disguise cloudsyncd cloudsyncd Tên ngụy trang tiến trình trong bộ nhớ
Log File ~/.local/share/cloudsync/.config/logs/sync.err ~/.local/share/cloudsync/.config/logs/sync.err Tệp lưu trữ nhật ký hoạt động mã hoá

Một phát hiện đặc biệt quan trọng: Jamf Threat Labs xác nhận hoàn toàn không quan sát thấy cơ chế duy trì quyền truy cập (persistence) nào được thiết lập tại thời điểm phân tích. Mã độc không tạo bất kỳ tệp cấu hình khởi động LaunchAgent hay LaunchDaemon nào, không sao chép tệp thực thi vào thư mục cài đặt ~/.local/share/cloudsync/, và cũng không đổi tên tiến trình đang chạy thành cloudsyncd. Implant chạy từ đường dẫn staging với tên tệp ban đầu và chỉ tạo tệp nhật ký sync.err trong cây thư mục cài đặt.

Khi khởi chạy, implant chỉ gọi đúng 2 lệnh shell duy nhất thông qua sh -c:

sh -c mkdir -p '<install dir>/.config/logs' 2>/dev/null
sh -c /usr/sbin/ioreg -rd1 -c IOPlatformExpertDevice 2>/dev/null

Lệnh đầu tiên tạo cây thư mục lưu log, trong khi lệnh thứ hai truy vấn số định danh phần cứng (Hardware UUID). Sau đó, implant thực hiện thu thập cấu hình hệ thống bằng cách kết hợp giữa các lệnh gọi sysctl và dữ liệu từ ioreg. Gói dữ liệu điều tra ban đầu có dung lượng gần 2 KB, bao gồm các trường: hwid, cpu_name, cpu_cores, ram, os, machine_name, user_name, mac, hw_model và toàn bộ kết quả xuất thô của lệnh ioreg. Trong các phiên check-in tiếp theo, mã độc chỉ gửi duy nhất giá trị Hardware UUID.

Mọi hoạt động của implant được ghi lại vào tệp nhật ký ~/.local/share/cloudsync/.config/logs/sync.err. Mỗi dòng log là một bản ghi được mã hoá độc lập bằng thuật toán ChaCha20-Poly1305 (khoá giải mã có thể trích xuất trực tiếp từ mẫu nhị phân). Sau khi giải mã, bản ghi đầu tiên của mỗi phiên có dạng:

[2026-09-18T01:50:42] [cs] start url=hxxps://orchid-led[.]com/macos/jquery[.]js hwid=D5917A2D-9237-5100-B6AC-89FDBC4585F8 max_attempts=360

Tệp sync.err chính là nguồn chứng cứ pháp y số (digital forensics) có giá trị cao nhất trên máy nạn nhân. Bằng cách giải mã tệp này, điều tra viên có thể nhanh chóng xác định chính xác địa chỉ máy chủ C2, định danh phần cứng máy bị nhiễm và toàn bộ lịch sử các lần kết nối mà không cần phải phân tích dịch ngược tệp nhị phân gốc.

Cơ chế Remote Tasking và chuyển giao payload nhị phân

Cơ chế tiếp nhận và thực thi chỉ thị từ xa của implant nằm trong hàm nội bộ handle_task_response.

Sau khi gửi gói tin beacon, mã độc chờ đợi một đối tượng JSON phản hồi từ máy chủ C2. Nếu gói tin phản hồi không chứa trường task, implant coi đó là một lần điểm danh (check-in) thành công và tiếp tục chu kỳ ngủ. Nếu phản hồi xuất hiện trường task, nội dung của trường này sẽ được giải mã Base64 và giải mã đối xứng. Dữ liệu sau giải mã được phân loại xử lý theo cấu trúc nhị phân:

  1. Nhánh gói nén (Gzipped tar archive): Nếu các byte giải mã tương ứng với một tệp nén tar, implant sẽ gọi tiện ích hệ thống /usr/bin/tar để bung gói vào một thư mục tạm thời tạo bằng mkdtemp:

    $TMPDIR/.opXXXXXX/
    

    Thư mục này chứa tệp p.tgz và cây nhị phân trích xuất bin/<daemon>. Sau khi thực thi xong nhiệm vụ, toàn bộ thư mục tạm sẽ bị xoá bỏ.

  2. Nhánh mã nhị phân trực tiếp (Raw Mach-O): Nếu dữ liệu là một tệp nhị phân Mach-O độc lập, mã độc thực thi theo luồng mà mã nguồn tự gán nhãn là "legacy". Nó sử dụng mkstemp ghi tệp ra đĩa tại:

    <install dir>/.t_XXXXXX
    

    Trước khi kích hoạt, implant chủ động gỡ bỏ thuộc tính mở rộng bảo mật com.apple.provenance khỏi tệp, sau đó gọi thực thi trực tiếp và lập tức thực hiện ngắt liên kết (unlink) tệp khỏi hệ thống tệp.

Điểm đáng lưu ý đối với chuyên gia săn lùng mối đe dọa: cơ chế tasking của CloudSyncD tập trung chuyển giao các tệp thực thi nhị phân thay vì chạy các câu lệnh shell phức tạp. Do đó, dấu hiệu phát hiện đặc trưng trên máy trạm là sự xuất hiện của các tệp nhị phân mới được ghi tạm thời hoặc các tiến trình Mach-O lạ chạy từ thư mục người dùng, thay vì các cảnh báo liên quan đến chuỗi tiến trình con của shell.

Sai lầm OPSEC: Tái sử dụng khoá mã hoá và dấu vết hạ tầng C2

Mặc dù nhóm phát triển CloudSyncD thể hiện sự đầu tư kỹ lưỡng vào việc che giấu chuỗi ký tự bằng bảng mã sobf và kỹ thuật giấu mật khẩu zero-width, chúng lại mắc những lỗi an ninh vận hành (OPSEC) đáng kể:

  1. Tái sử dụng khoá mã hoá C2 qua mọi phiên bản: Tất cả các mẫu nhị phân thu thập được, từ bản phát triển nội bộ cho tới các bản triển khai thực tế trên cả hai tên miền khác nhau, đều sử dụng chung một khoá kênh C2 (C2 channel key) và một vector khởi tạo (IV):

    • C2 Key: 61957119137f9492ab7cff41ed83619c

    • C2 IV: d398b8d4

    • Bảng khoá xáo trộn chuỗi (sobf key table) 32 byte giống hệt nhau. Hệ quả là chuyên gia an toàn thông tin có thể sử dụng vật liệu mật mã trích xuất từ bất kỳ mẫu nhị phân nào để giải mã toàn bộ lưu lượng beacon đã bắt được trên mạng của toàn bộ chiến dịch.

  2. Đặc trưng hạ tầng C2 giống nhau: Hai tên miền điều khiển orchid-led[.]com và bjzhishang[.]com đều được đăng ký từ năm 2011, sử dụng chung một nhà đăng ký dịch vụ, đặt sau hạ tầng proxy của Cloudflare và cùng sử dụng chung một đường dẫn URI ngụy trang:

    /macos/jquery.js
    

    Việc mạo danh một tệp thư viện JavaScript phổ biến như jQuery giúp các yêu cầu HTTP POST của mã độc trông như các truy vấn tải tài nguyên thông thường khi nhìn lướt qua nhật ký proxy.

  3. Chu kỳ liên lạc khác biệt: Bản triển khai thực tế (live build) thiết lập chu kỳ gửi tín hiệu beacon định kỳ rất dày đặc, chỉ từ 8 đến 16 giây một lần. Ngược lại, bản phát triển (dev build) có khoảng cách giữa các lần beacon từ 75 đến 90 giây kèm độ trôi ngẫu nhiên (jitter), và tự động chấm dứt sau tối đa 360 lần thử hoặc khi nhận mã phản hồi HTTP 403 (bị máy chủ từ chối).


IOC (Indicators of Compromise)

--- Virus Total Collection --- 
Collection URL: https://www.virustotal.com/gui/collection/7fa4564c4d1387157b89936fe1dc97e1d9dbbcca3cd5283876845a4bc370174a

--- Distribution ---
Filename: Zoom.dmg
SHA256: faf2eea05f3c9f1c4ef8f6be339f5459a38f95cfd9d512bc24e2803230e5c7bf
Note: Tệp ảnh đĩa gắn kết thành volume "Zoom"; chứa Zoom.app giả mạo ứng dụng Zoom

--- Stage one: dropper (development build, Mach-O, arm64) ---
Filename: app_installer
SHA256: 524a7bcc8edcadc6f4381459f79769e1ec534aa78f66e5c38a6678bd55cf2572
Filepath: /Volumes/Zoom/Zoom.app/Contents/MacOS/app_installer
Note: Liên kết AppKit; hiển thị hộp thoại uỷ quyền giả; xác thực qua dscl; ghi thông tin
 xác thực che giấu vào data.json; chứa Mach-O universal giai đoạn hai (756,432 bytes)

--- Stage two: cloudsyncd implant (development build, universal Mach-O) ---
Filename: appd
SHA256: 071d58f590d155b8ef991a9fe6f9c0a85ccc190d5266c770b5296e4550e084a5
Note: Tệp nhị phân Universal mang bên trong stage một; ký ad-hoc, không có Developer ID
 và không có notarization ticket
SHA256: 74fea25aba11fef0572ecef3dda0c819e6841150f3154bee2e26ec71c06c85ed
Note: Phân mảnh arm64 của bản nhúng, 379,600 bytes; định danh ký ad-hoc "main-arm64.out"
SHA256: 8371abbfeb3dbab1581eee54688ecd1f0640dc013ddb419c4332fcd954f9d2bc
Note: Phân mảnh x86_64 của bản nhúng, 351,392 bytes; định danh ký ad-hoc "cshelper"

--- Stage two: on-disk copy of the same payload (universal Mach-O) ---
Filename: cshelper
Filepath: /Volumes/Zoom/Zoom.app/Contents/Resources/cshelper
SHA256: f7d8a7593ccbbcb05fde2bf110e1c5d09b18f711219e6b80edda83ae8b41a1e1
Note: Phân mảnh arm64, 379,600 bytes; định danh ký ad-hoc "cshelper". Khớp từng byte
 với phân mảnh arm64 nhúng bên ngoài vùng chữ ký 8 KB; chỉ khác nhau do ký dưới
 định danh khác. Mã băm của phân mảnh x86_64 và container universal của bản sao
 này Jamf chưa công bố
Shared content hash (arm64, toàn bộ phần đứng trước chữ ký số, 371,408 bytes):
b3acff0abcdde6adc91cb97461b4d902ff19375752afa2f778f682f5102bdfc4
Note: Trùng khớp giữa cả hai bản sao và không bị ảnh hưởng khi ký lại. Bền vững hơn
 mã băm toàn bộ tệp khi liên kết các bản build được ký lại của cùng payload

--- Stage one: droppers (live builds) ---
Note: Phát hành dưới dạng các tệp nhị phân đơn kiến trúc mỏng, mỗi bản build gồm một mã
 băm arm64 và một x86_64. Tất cả đều mang bảng khoá sobf và cấu hình dropper giống nhau
SHA256: 74dfa21b837c0c4e6abd428a1370ccd8779428d2c9362981a06ce26c6a58b353
Note: x86_64; nhúng giai đoạn hai dung lượng 678,336 bytes; beacon tới orchid-led[.]com
SHA256: 5f2aebc518a56ebe0cc9171553e2c5973ddbfa79042c1c76b665d8b465c1695d
Note: Bản đối ứng arm64 của tệp trên; nhúng cùng giai đoạn hai
SHA256: cc54d90920a73cc5e176664f61c6f601c95d693e431e79ae1148cb91e83c9235
Note: arm64; nhúng giai đoạn hai dung lượng 756,432 bytes; beacon tới bjzhishang[.]com
SHA256: 989c2235b3deec9a0d7cb3eb10d8148735cb704dc85de4e16211381fa794dca1
Note: Bản đối ứng x86_64 của tệp trên; bản mã cấu hình C2 giống hệt

--- Stage two: gate implant (orchid-led[.]com builds, universal Mach-O) ---
SHA256: 63c88ba846d1adf047417502e67a20f6e52414fea4b4b80aa66c5a371f53dcd6
Note: Tệp nhị phân Universal, 678,336 bytes
SHA256: 54efb0e308c93e448187ca53abe62eca6521bc84852a63b2ffefdd00e9771882
Note: Phân mảnh x86_64, 325,904 bytes
SHA256: 96e039a67b2ab39e36d57a988b3af16b2822d9dfaa70892be06178826b1eb261
Note: Phân mảnh arm64, 334,272 bytes

--- Stage two: gate implant (bjzhishang[.]com builds, universal Mach-O) ---
SHA256: edcd4a8ca2d525f26b8cd05a533585842b1e38216d98e385e25abf8703d31010
Note: Tệp nhị phân Universal, 756,432 bytes, trích xuất từ dropper arm64. Cùng kích thước
 và cấu trúc phân mảnh với bản dev, mã thực thi gần như giống hệt nhưng toàn bộ dữ liệu
 chuỗi xáo trộn đã được tạo mới lại
SHA256: c279201898cb0c645343a0e3b4215ad324b0edacc4df799f22e78a8cfbe10d06
Note: Phân mảnh arm64, 379,600 bytes; định danh ký ad-hoc "main-arm64.out"
SHA256: 06ab1e44941e0ceea9df11729576a091fa8c0388188b599f0ee51c54ee0a3186
Note: Phân mảnh x86_64, 351,392 bytes

--- Command-and-control (live builds) ---
URL: hxxps://orchid-led[.]com/macos/jquery[.]js
URL: hxxps://bjzhishang[.]com/macos/jquery[.]js
Type: Máy chủ điều khiển (C2 endpoints)
Note: Đường dẫn URI giống hệt nhau trên cả hai tên miền, ngụy trang dưới dạng script jQuery
Domain: orchid-led[.]com
Domain: bjzhishang[.]com

--- Reused cryptographic material (all builds) ---
C2 channel key: 61957119137f9492ab7cff41ed83619c
C2 channel IV: d398b8d4
Note: Giống hệt nhau giữa bản phát triển và bản triển khai thực tế. Giá trị gom cụm mạnh,
 cho phép giải mã toàn bộ dữ liệu beacon thu thập được
sobf string obfuscation key table (32 bytes, cả hai giai đoạn, tất cả các bản build):
D7 19 BF 57 E6 5B A0 9D E1 BA CD B1 82 C9 91 18
ED AF D5 18 FD 3A 4A 97 97 BC AD 22 1A DB 81 51
Note: Hằng số cấp mã nguồn được chia sẻ qua các tệp nhị phân biên dịch độc lập; lưu trữ
 trong vùng dữ liệu chỉ đọc (read-only data), tồn tại ngay cả khi đã strip symbol

--- Command-and-control (development build, observed during dynamic analysis) ---
URL: hxxp://192[.]168[.]2[.]133:9099/ops
Type: Điểm cuối C2 bản phát triển
Note: Địa chỉ IP riêng, giao thức HTTP văn bản rõ; không phản hồi trong phiên ghi nhận.
 Chu kỳ beacon khoảng 75 đến 90 giây có jitter, tối đa 360 lần. Thông điệp đầu tiên là
 bản điều tra host, các thông điệp sau chỉ mang Hardware UUID. Phản hồi là đối tượng JSON;
 trường "task" mang tệp thực thi mã hoá Base64, chuyển giao dưới dạng tệp tar.gz chứa
 bin/<daemon> hoặc tệp Mach-O thô. Mã phản hồi HTTP 403 được coi là bị chặn và kết thúc

--- Task execution artifacts (stage two) ---
Filepath: $TMPDIR/.opXXXXXX/
Note: Thư mục tạo bằng mkdtemp dùng để giải nén gói task; chứa p.tgz và cây thư mục bin/.
 Bị xoá bỏ sau khi sử dụng
Filepath: <install dir>/.t_XXXXXX
Note: Tệp tạm mkstemp dự phòng cho payload của task; bị xoá liên kết (unlink) sau khi chạy,
 thuộc tính com.apple.provenance bị xoá trước khi thực thi
Process: /usr/bin/tar xzf -C
Note: Được kích hoạt bởi implant để giải nén gói lưu trữ nhận từ task

--- Filesystem artifacts ---
Filepath: ~/.local/share/cloudsync/
Note: Thư mục cài đặt của implant
Filepath: ~/.local/share/cloudsync/.config/logs/sync.err
Note: Nhật ký của implant, mỗi dòng là một bản ghi mã hoá ChaCha20-Poly1305 (khoá giải mã
 lấy được từ mẫu). Dấu vết triage có giá trị cao nhất: chứa địa chỉ C2, Hardware UUID
 và lịch sử beacon. Được ghi nối tiếp qua nhiều phiên; các phiên chạy đồng thời sẽ ghi xen kẽ
Filepath: ~/.config/<name>/data.json (mode 0644)
Note: Tệp cấu hình ngụy trang ghi bởi stage một. Mật khẩu đăng nhập nằm dưới dạng Base64
 bên trong giá trị "cache", được định vị bằng chỉ mục Unicode vô hình đính sau "version".
 Săn lùng ký tự U+200B và U+200C bên trong chuỗi JSON. Thư mục và trường "app" khớp với
 tên cấu hình: ~/.config/zoom/ với "app": "Zoom" ở bản dev; ~/.config/cloudsync/ với
 "app": "cloudsync" ở bản live
Filepath: $TMPDIR/.app_swap_<pid>.sh
Note: Script tráo đổi bundle tạm thời tạo bởi stage một và chạy qua /bin/bash. Tự xoá ở
 cả hai nhánh thành công và thất bại nên khó tồn tại lâu dài trên máy nạn nhân. Săn lùng
 theo tiền tố ".app_swap_" thay vì đường dẫn đầy đủ
Filepath: $TMPDIR/.s_XXXXXX
Note: Tệp tạm mkstemp chứa giai đoạn hai khi nạp fileless thất bại. Được truyền trực tiếp
 cho sudo nên xuất hiện trong dòng lệnh tiến trình. Săn lùng theo tiền tố ".s_"

--- Observed command lines (orchid-led[.]com build) ---
/usr/bin/dscl /Local/Default -authonly <user> <password>
Note: Xác thực mật khẩu bởi stage một. Mật khẩu xuất hiện trong đối số dòng lệnh argv,
 hiển thị với mọi sensor giám sát tiến trình. Mỏ neo phân tích có độ trung thực cao nhất
/usr/bin/sudo -S --preserve-env=HOME,USER $TMPDIR/.s_XXXXXX
Note: Khởi chạy có đặc quyền giai đoạn hai, với mật khẩu thu thập được truyền qua stdin
sh -c mkdir -p '<install dir>/.config/logs' 2>/dev/null
sh -c /usr/sbin/ioreg -rd1 -c IOPlatformExpertDevice 2>/dev/null
Note: Hai lệnh shell duy nhất được gọi bởi implant, đều mang câu lệnh cố định
Process name: cloudsyncd
Note: Tên daemon và vỏ ngụy trang tiến trình trong cấu hình. Không quan sát thấy tại runtime;
 không có lệnh task nào được gửi xuống trong phiên phân tích nên chưa tới bước cài daemon

Bối cảnh an ninh mạng tại Việt Nam

Theo đánh giá của chúng tôi, rủi ro tập trung ở những tổ chức có máy Mac không được quản lý bằng MDM:

  • Người dùng làm việc hằng ngày bằng tài khoản admin, nên hộp thoại xin mật khẩu admin không gây nghi ngờ.

  • Không có chính sách chặn người dùng tự bấm "Open Anyway" cho ứng dụng chưa notarize.

  • Máy Mac nằm ngoài phạm vi EDR, nên dấu hiệu dscl -authonly không được ai thấy.

Kịch bản của CloudSyncD khai thác đúng ba khoảng trống này. Khi kẻ tấn công nắm được quyền root trên máy trạm nội bộ, rủi ro bị xâm nhập sâu vào hạ tầng doanh nghiệp là rất lớn.


Khuyến nghị phòng thủ

  1. Rà soát máy trạm theo danh mục IOC: Chạy tập lệnh tìm kiếm sự xuất hiện của tệp ~/.local/share/cloudsync/.config/logs/sync.err. Kiểm tra các tệp tạm có tiền tố /.s_ và /.app_swap_ trong thư mục $TMPDIR.

  2. Quét tệp JSON chứa ký tự vô hình: Chạy lệnh kiểm tra các ký tự zero-width (U+200B và U+200C) trong các tệp cấu hình tại thư mục ~/.config/.

  3. Thu hồi và đổi mật khẩu quản trị viên: Nếu phát hiện dấu vết của lệnh dscl -authonly hoặc tệp data.json nghi vấn, lập tức cô lập thiết bị. Thực hiện đổi mật khẩu tài khoản người dùng và thu hồi các phiên đăng nhập đang hoạt động.

  4. Chặn kết nối mạng trên tường lửa/proxy: Cấu hình danh sách đen (blacklist) trên Firewall, Proxy và DNS Gateway chặn hoàn toàn hai tên miền C2 orchid-led[.]com và bjzhishang[.]com. Nếu proxy có TLS inspection, có thể chặn thêm đường dẫn URI /macos/jquery.js từ các tiến trình không phải trình duyệt.

  5. Triển khai quy tắc giám sát trên EDR/SIEM: Kích hoạt quy tắc Sigma và các truy vấn SPL/KQL đã được cung cấp. Giám sát chặt chẽ tiến trình /usr/bin/dscl chứa tham số -authonly và tiến trình sudo kích hoạt các tệp tạm ẩn.

  6. Cấu hình chính sách MDM siết chặt Gatekeeper: Đẩy configuration profile payload com.apple.systempolicy.managed với khoá DisableOverride = true để người dùng không thể tự bấm "Open Anyway" cho ứng dụng bị Gatekeeper chặn. Kết hợp payload com.apple.systempolicy.control (EnableAssessment = true) để giữ Gatekeeper luôn bật.

  7. Phân tách quyền hạn người dùng (Least Privilege): Tước bỏ quyền quản trị viên mặc định trên các tài khoản làm việc hàng ngày của nhân viên. Chuyển sang tài khoản Standard User và chỉ cấp quyền quản trị tạm thời khi có nhu cầu chính đáng.

  8. Kiểm soát nhị phân theo chữ ký (Application Whitelisting): Triển khai công cụ kiểm soát thực thi như Santa để chặn binary ký ad-hoc chưa được duyệt. Với máy của developer, cần allowlist các binary tự build để tránh chặn nhầm.

  9. Chuẩn hoá kênh phân phối phần mềm nội bộ: Nghiêm cấm nhân viên tự ý tải bộ cài đặt từ bên ngoài. Toàn bộ phần mềm doanh nghiệp như Zoom phải được phân phối tập trung qua cổng nội bộ (Company Portal) với gói cài đặt ký số từ nguồn chính thức (zoom.us).

  10. Nâng cao nhận thức an toàn thông tin: Định kỳ tổ chức đào tạo nhận thức bảo mật. Nhấn mạnh cảnh báo không làm theo chỉ dẫn hình nền đòi hỏi can thiệp cài đặt bảo mật hệ thống để ép mở tệp ứng dụng lạ.


Tài liệu tham khảo

  1. Jamf Threat Labs: Thijs Xhaflaire, "CloudSyncD: a two-stage macOS backdoor that hides a phished password in zero-width Unicode", công bố ngày 30/09/2026.
    URL: https://www.jamf.com/blog/cloudsyncd-macos-backdoor-fake-zoom-installer/

  2. SecurityAffairs: Pierluigi Paganini, "Fake Zoom installer hides macOS backdoor CloudSyncD", công bố ngày 03/10/2026.
    URL: https://securityaffairs.com/200293/malware/fake-zoom-installer-hides-macos-backdoor-cloudsyncd.html

  3. VirusTotal Collection: Tập hợp các mẫu phân tích mã độc của dòng CloudSyncD.
    URL: https://www.virustotal.com/gui/collection/7fa4564c4d1387157b89936fe1dc97e1d9dbbcca3cd5283876845a4bc370174a

  4. MITRE ATT&CK Framework: Cơ sở tri thức về chiến thuật và kỹ thuật tấn công của đối thủ trên nền tảng macOS.
    URL: https://attack.mitre.org/


Thông điệp cốt lõi: CloudSyncD giấu mật khẩu rất khéo trên đĩa, nhưng vẫn phải đưa nó vào argv của dscl để kiểm tra. Một rule cho dscl -authonly từ tiến trình lạ bắt được mắt xích này trước khi backdoor kịp lên root.

More from this blog

F

FPT IS Security

1053 posts

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