SlowMist: JS độc hại của Udesk đánh cắp dữ liệu và thay đổi địa chỉ chuyển

iconMetaEra
Chia sẻ
AI summary iconTóm tắt
SlowMist phát hiện một tập lệnh JS độc hại trong hệ thống Udesk, liên quan đến tin tức trên chuỗi về các nền tảng bị xâm phạm như mgbx.com và bitxex.io. Tập lệnh này, được tải qua udeskApi.2026-10-16.cached.js và deeps.js, đánh cắp dữ liệu phiên và thay đổi địa chỉ nạp tiền. Kẻ tấn công sử dụng trình tải từ xa để chèn mã, gây nguy cơ mất tài sản. Dữ liệu lạm phát và biến động thị trường có thể làm gia tăng tổn thất cho người dùng bị ảnh hưởng. Sự vi phạm này làm nổi bật những mối quan tâm bảo mật cấp bách trên nhiều sàn giao dịch.
Một lần đầu độc script, làm thế nào để đồng thời nhắm vào dữ liệu người dùng và tiền chuyển khoản?

Tác giả bài viết, nguồn: Slow Mist Tech

Bối cảnh

Gần đây, các chuyên gia bảo mật của SlowMist trong quá trình khai thác tin tức đe dọa hàng ngày đã phát hiện một cuộc tấn công liên quan đến việc đầu độc các script của hệ thống hỗ trợ khách hàng Udesk. Nhóm sau đó đã thu thập được hai mẫu JavaScript là udeskApi.2026-10-16.cached.js và deeps.js, tiến hành phân tích để truy tìm cách mã độc lợi dụng script hỗ trợ khách hàng xâm nhập vào trang web và xác định những tác động của nó đối với dữ liệu người dùng và các thao tác kinh doanh.

Việc kiểm tra mẫu từng bước tiết lộ hai loại rủi ro: mã độc thu thập dữ liệu phiên và thông tin nhạy cảm do người dùng gửi trên trang web, đồng thời sửa đổi địa chỉ nạp tiền và sao chép nội dung theo quy tắc của trang web. Loại rủi ro đầu tiên có thể cho phép kẻ tấn công mạo danh phiên đăng nhập hoặc chiếm quyền kiểm soát tài khoản, trong khi loại thứ hai có thể khiến người dùng chuyển tiền nạp vào địa chỉ nhận được thay thế. Chúng tôi bắt đầu từ điểm tải script hỗ trợ khách hàng, theo dõi luồng dữ liệu đọc, gửi qua mạng và logic sửa đổi trang web để tái hiện cách thức và điều kiện kích hoạt của hai hành vi này.

MistEye phản hồi

MistEye là hệ thống giám sát an ninh động và thu thập thông tin mối đe dọa Web3 do SlowMist tự phát triển, tích hợp khả năng giám sát an ninh và tổng hợp thông tin tình báo, cung cấp cảnh báo rủi ro thời gian thực và bảo vệ tài sản cho người dùng.

MistEye đã đồng bộ hóa rủi ro ngay lập tức thông qua kênh đẩy tin tức và cảnh báo khách hàng.

Malicious loader and remote payload loading mechanism

Sau khi mở tệp udeskApi.2026-10-16.cached.js, bạn có thể thấy mã cho các chức năng như nút hỗ trợ, iframe trò chuyện, theo dõi khách truy cập và truyền tin nhắn. Tiếp tục kiểm tra phần cuối tệp, sau khi kết thúc phần chính, còn có một hàm độc lập: nó giải mã hai chuỗi thông qua _ud(), tạo phần tử và chèn vào head của tài liệu hiện tại.

Đoạn này không ghi rõ tên thẻ và URL từ xa. Nếu chỉ tìm kiếm tên miền ở dạng văn bản thuần, điểm tải vào dễ bị bỏ sót. Chúng tôi kiểm tra triển khai của _ud() và phát hiện nó lấy hai ký tự thập lục phân mỗi lần, sau đó chuyển đổi thành ký tự; sau khi khai triển hằng số, mục tiêu tải về trở nên rõ ràng.

Giải mã 736372697074 thành script, một hằng số khác được giải mã thành https[:]//udeskqlobal[.]com/deeps.js. Tên miền có chữ qlobal bắt đầu bằng chữ q, khi tìm kiếm cần giữ nguyên cách viết này. Bộ tải đặt script ở chế độ bất đồng bộ, sau đó chèn vào trang; khi thực thi đến vị trí này và chính sách trình duyệt cùng mạng cho phép, mã từ xa có thể được tải vào tài liệu hiện tại.

Tải trọng tương ứng với URL này là deeps.js. Trọng tâm điều tra đã chuyển từ SDK hỗ trợ khách hàng sang chính tải trọng. Các kịch bản cổ điển của bên thứ ba được thực thi trong ngữ cảnh tài liệu nhúng, và dữ liệu mà chúng có thể truy cập phụ thuộc vào trang hoặc iframe đang chạy. Cửa sổ trò chuyện hỗ trợ khách hàng sử dụng iframe và không tự động cô lập các kịch bản được tải trên trang chủ.

Cơ chế thu thập dữ liệu trang web và phạm vi ảnh hưởng

deeps.js ban đầu đọc window.location.hostname và tạo cấu hình C theo ba quy tắc trang web. Để xác định những trang nào sẽ được thu thập, chỉ xem bộ cấu hình này là chưa đủ: nó giới hạn toàn bộ script hay chỉ một module nào đó, cần tiếp tục theo dõi vị trí kiểm tra thoát.

Khi kiểm tra theo luồng điều khiển, chúng ta thấy việc đọc Cookie và lưu trữ web, gửi ảnh chụp nhanh khởi động, cũng như các hook yêu cầu biểu mẫu và xác thực đều xuất hiện trước if (!C) return; Dưới đây là các câu lệnh gửi ảnh chụp nhanh và hook XHR ở cuối, theo thứ tự mã nguồn; chú thích chỉ ra các đoạn mã bị bỏ qua ở giữa, tương ứng với giao diện định dạng D:L100, D:L151–L166.

Vị trí thoát được xác định rõ phạm vi ảnh hưởng: ngay cả khi hostname không khớp với ba quy tắc trang web, script vẫn sẽ đi vào đường dẫn thu thập dữ liệu và cài đặt hook trước khi thoát khỏi module địa chỉ. Khi kiểm tra các trang bị phơi bày, không thể chỉ tìm kiếm xung quanh ba cấu hình trang web này.

Khi khởi động, tải trọng sẽ đọc Cookie, localStorage và sessionStorage có thể truy cập trên trang web hiện tại. Các vị trí này có thể lưu trạng thái đăng nhập, hồ sơ người dùng và dữ liệu nghiệp vụ; nếu trong đó chứa các mã xác thực đăng nhập vẫn còn hiệu lực và có thể tái sử dụng, kẻ tấn công có thể lợi dụng để mạo danh phiên người dùng. Script cũng kèm theo URL của trang cấp cao nhất và origin của tài liệu hiện tại, để gửi các dữ liệu này cùng với trang nguồn.

Quá trình thu thập có khả năng xử lý lỗi từng mục. Khi việc đọc URL cấp cao từ nguồn khác thất bại, script sẽ thay thế bằng x và tiếp tục xử lý các trường khác; hai loại trang web được lưu trữ dưới dạng JSON. Phạm vi cookie bị giới hạn bởi nội dung có thể đọc được từ document.cookie, không bao gồm cookie HttpOnly.

Script cũng giữ lại các điểm nhập cho dữ liệu được gửi sau này. Khi người dùng gửi biểu mẫu, nó lặp qua các phần tử input, select và textarea, sao chép các nội dung không rỗng, sau đó tiếp tục quá trình gửi ban đầu. Các trường thực tế được điền trên trang như tài khoản, mật khẩu, mã xác minh... đều có thể đi vào các đường dẫn gửi dữ liệu bổ sung, và nếu bị rò rỉ, có thể bị sử dụng để đăng nhập hoặc chiếm quyền kiểm soát tài khoản.

Con đường này được thực hiện bằng cách bao bọc HTMLFormElement.prototype.submit và lắng nghe sự kiện submit ở giai đoạn bắt捕. Đối với các trang gửi dữ liệu trực tiếp qua giao diện, script cũng bao bọc fetch và XHR: khi yêu cầu có thân dữ liệu và URL chứa các từ khóa như login|signin|auth|register|signup|password, script sẽ sao chép nội dung tương ứng và giữ nguyên lời gọi yêu cầu. Nhánh fetch yêu cầu thêm rằng URL phải là chuỗi và thân dữ liệu đến từ tùy chọn yêu cầu; khi các đối tượng như FormData được serial hóa trực tiếp thành JSON, nội dung thu thập có thể thiếu các trường thực tế.

Cơ chế truyền dữ liệu ngoài và kênh dự phòng

Cổng thu thập trên cuối cùng gọi hàm _send() giống nhau. Tiếp tục theo dõi hàm này, có thể thấy endpoint cố định là https[:]//udeskqlobal[.]com/c.php. Bản ghi nhanh sử dụng các trường s, o, c, l, ss để chứa địa chỉ trang, nguồn hiện tại, Cookie có thể đọc được và hai loại lưu trữ web; các yêu cầu biểu mẫu và xác thực sau đó được gửi khi từng yêu cầu được kích hoạt.

Hàm tách các tham số sau dấu chấm hỏi trong URL, đưa vào nội dung POST bất đồng bộ, thiết lập Content-Type: application/x-www-form-urlencoded. Dưới đây là hàm gửi được giữ nguyên đầy đủ (D:L45–L60):

Đường dẫn gửi cũng bao gồm cơ chế dự phòng yêu cầu hình ảnh: Khi XHR gặp lỗi hoặc xảy ra bất thường đồng bộ trong quá trình gửi, script sẽ tạo đối tượng Image, gán URL có tham số vào src và cố gắng gửi lại dữ liệu thông qua GET. URL bị cắt thành 8.000 ký tự JavaScript đầu tiên, nội dung dài hơn có thể không đầy đủ.

Khi hiểu con đường này, cần phân biệt giữa “gửi yêu cầu” và “đọc phản hồi”. Script không đọc phản hồi từ c.php; các yêu cầu POST đa nguồn đáp ứng điều kiện yêu cầu đơn giản có thể được gửi trước, sau đó trình duyệt hạn chế việc đọc phản hồi, do đó lỗi CORS có thể xảy ra đồng thời với việc gửi yêu cầu. Việc kiểm tra log nên đồng thời kiểm tra nội dung POST và tham số GET của hình ảnh, trong khi chính sách đầu ra cần kiểm tra riêng biệt connect-src và img-src. Một biểu mẫu thông thường nếu gây ra điều hướng tài liệu cũng sẽ ảnh hưởng đến khả năng hoàn thành yêu cầu bất đồng bộ.

Tới đây, điểm đến của dữ liệu phiên web và các nội dung gửi sau đó đã rõ ràng. Tuy nhiên, tải trọng vẫn thực hiện một nhóm thao tác khác sau khi kiểm tra việc thoát trang: nhận dạng định dạng địa chỉ, chỉnh sửa văn bản trang và chiếm quyền kiểm soát đường dẫn sao chép. Những mã này đưa cuộc điều tra sâu hơn vào dịch vụ nạp tiền.

Thay đổi địa chỉ nạp tiền và cơ chế chiếm quyền điều khiển bảng tạm

Sau khi qua if (!C) return;, script chuyển sang module địa chỉ. Ba quy tắc hostname đầu tiên lúc này có mục đích rõ ràng: khớp với mgbx[.]com, bikingex[.] và bitxex[.]io để chọn bộ chọn phần tử cho địa chỉ và nút sao chép trên các trang khác nhau.

Các biểu thức chính quy này không có điểm neo đầu và cuối, phạm vi khớp rộng hơn so với so sánh tên miền chính xác. Quy tắc trang cũng kiểm tra location.href đầy đủ, và các từ khóa như deposit, recharge, assets trong tham số truy vấn hoặc đoạn sẽ được đưa vào đánh giá. Sau khi trang, phần tử và định dạng địa chỉ khớp, script sẽ quét mỗi 200 miligiây để thay đổi địa chỉ nạp được phát hiện bằng giá trị cấu hình. Nếu người dùng thực hiện chuyển khoản hợp lệ đến địa chỉ đã được thay thế, mục đích nhận tiền sẽ trở thành địa chỉ đó.

Ba nhánh trang web chia sẻ sáu giá trị cấu hình, được đánh dấu trong mã là BTC, EVM, TRON, Solana, LTC và DOGE. Việc nhận diện địa chỉ chỉ dựa trên hình thái ký tự và thứ tự khớp, không kiểm tra mạng người dùng đã chọn hoặc mã kiểm tra địa chỉ, cũng có thể nhầm lẫn với các ký hiệu nghiệp vụ thông thường.

Tiếp tục kiểm tra mã sao chép, có thể thấy mẫu đồng thời can thiệp vào việc hiển thị trang và nội dung bảng tạm. Như vậy, ngay cả khi người dùng so sánh địa chỉ trang với kết quả sao chép, họ cũng có thể nhận được các giá trị bị thay đổi nhất quán. Ba con đường lần lượt là:

  • Bao bì API clipboard. navigator.clipboard.writeText gọi R() để thay thế tham số trước khi chuyển cho phương thức gốc. Con đường này chỉ bị giới hạn bởi cấu hình hostname, không kiểm tra lại điều kiện trang nạp tiền, cũng không phụ thuộc vào quét DOM để xác định phần tử đã được nhắm mục tiêu.
  • Thay thế nút sao chép. Script sẽ sao chép nút được tìm thấy, cài đặt trình lắng nghe click mới và thay thế nút gốc. Trình lắng nghe mới sẽ ngăn hành động mặc định và lan truyền sự kiện, đồng thời cố gắng sao chép địa chỉ được lưu trong biến chia sẻ _cur.
  • Chặn sự kiện copy. Khi _cur không rỗng và quy tắc trang được đáp ứng, bộ lắng nghe trên document sẽ thay đổi nội dung được sao chép thành _cur, không kiểm tra xem văn bản người dùng chọn có phải là địa chỉ hay không.

Trong đó, bao bọc API clipboard và trình lắng nghe copy nằm cạnh nhau trong mã nguồn (D:L260–L275), nhưng điều kiện kích hoạt khác nhau:

_cur lưu địa chỉ cuối cùng được thay thế thực tế. Khi có nhiều địa chỉ cùng hiển thị trên màn hình, lần thay thế sau sẽ ghi đè lên bản ghi trước đó, nhiều nút có thể sao chép cùng một giá trị. Nếu trang đã hiển thị địa chỉ cấu hình từ đầu, việc quét sẽ không khởi tạo _cur, do đó bộ lắng nghe nút mới cũng không ghi nội dung; các thuộc tính sự kiện nhúng được sao chép vẫn có thể tham gia xử lý sự kiện.

Trong phân tích, còn phát hiện một lỗi thực thi ảnh hưởng đến việc phán đoán hành vi: script cố gắng đọc mô tả thuộc tính riêng của textContent từ Element.prototype, trong khi định nghĩa thuộc tính tiêu chuẩn nằm ở Node.prototype. Trong mối quan hệ prototype tiêu chuẩn, việc truy cập .set sau đó sẽ ném ra ngoại lệ. Sau khi nhánh này thất bại, catch sẽ bắt và bỏ qua ngoại lệ; khi kiểm tra mã trước và sau, có thể thấy việc poll đã được đăng ký, các hook sao chép tiếp theo vẫn sẽ được cài đặt theo các điều kiện tương ứng. Lỗi ở một nhánh đơn lẻ không làm dừng module giả mạo địa chỉ.

Summary

Sau khi theo dõi trình tải ở cuối đoạn lệnh hỗ trợ khách hàng, chúng tôi xác định được mục tiêu tấn công của mẫu: thu thập dữ liệu có thể dùng để giả mạo phiên hoặc đăng nhập tài khoản, đồng thời thay đổi địa chỉ nhận tiền trong trang nạp tiền và thao tác sao chép thành giá trị cấu hình. Hành vi đầu tiên không bị giới hạn bởi cấu hình của ba trang web, trong khi hành vi thứ hai được kích hoạt theo trang web và đường dẫn sao chép cụ thể, do đó cần kiểm tra bao quát các tình huống phơi bày khác nhau.

Các doanh nghiệp vẫn đang tải các script liên quan nên ngừng ngay việc phân phối, xử lý thông tin xác thực bị lộ, và kiểm tra mục tiêu nạp tiền thông qua nền tảng đáng tin cậy và lịch sử giao dịch.

Khuyến nghị

  1. Bảo toàn và ngừng phân phối tài nguyên bị ô nhiễm. Nếu quá trình sản xuất vẫn tải các script liên quan, hãy ngắt kết nối ngay sau khi lưu lại phản hồi thực tế, chuỗi khởi tạo yêu cầu, thông tin bộ nhớ đệm và thời gian thu thập; khôi phục từ phiên bản đáng tin cậy đã được xác minh độc lập, đồng thời kiểm tra cấu hình lưu trữ trang web, CDN, xây dựng và quản lý thẻ.
  2. Tìm kiếm tải và ghi chép rò rỉ. Truy vấn kết hợp các miền độc hại, hai đường dẫn và hash tệp; ghi chép rò rỉ đồng thời kiểm tra nội dung POST và tham số GET. Khi kiểm tra script nén, cũng tìm kiếm URL thập lục phân trong trình tải, tránh bỏ sót do chỉ kiểm tra văn bản rõ.
  3. Kết thúc tài liệu bị nhiễm và xử lý thông tin xác thực bị lộ. Đóng hoàn toàn các trang hoặc tài liệu WebView liên quan để tránh tải lại tài nguyên cũ. Dựa trên phạm vi lộ thông tin thực tế, hủy phiên, xoay token và mật khẩu từ môi trường sạch; việc xóa thẻ script không hủy bỏ các hook và bộ định thời đã được cài đặt.
  4. Xác minh độc lập địa chỉ nạp và giao dịch. Đối với trang thực thi tải trọng, hãy xác minh địa chỉ nạp gốc, giao dịch liên quan và mục tiêu chuyển tiền thực tế thông qua kênh đáng tin cậy, đồng thời đánh giá tác động dựa trên hồ sơ giao dịch.
  5. Xác thực script và giới hạn xuất dữ liệu. Kết hợp cài đặt nghiệp vụ để kiểm soát nguồn và tính toàn vẹn của script, xác minh các chính sách như connect-src, img-src, v.v., và hạn chế tải script và truyền dữ liệu ra ngoài cho udeskqlobal[.]com.

IOC

Domain

udeskqlobal[.]com

URL

https[:]//udeskqlobal[.]com/deeps[.]js

https[:]//udeskqlobal[.]com/c[.]php

Wallet address

BTC: bc1qhzppfj69ywp22swj50jwcfxdamg3ym245srng9

EVM: 0x9B6EcD0023a28E1391c5124eCe578A9751A337b2

TRON: TH4L5YAhhxtC8qALbZKbPZZgausbGi25nF

Solana: AFmCUe3nNbjTaC585CcdA3vvC9iWVR8YunooFKpaQx2Z

LTC: ltc1qwz0zp39ywl34kahvn9lyk7j5x63wsy9tcxhm3w

DOGE: DAoy2w8uvFtZ92q87s9qKEoHbWgV7mVThj

Tập tin độc hại

tên tệp: udeskApi.2026-10-16.cached.js

SHA256: 45b4e8f160d8d5177819f6c1dc67acc7abbdc65eeaffc909e668799dc778bcf6

tên tệp: deeps.js

SHA256: 57c1441c4f5bb3260981a2df64f9ff35f117abde0d8667c8c66a047880074c59

Về MistEye

MistEye là nền tảng giám sát an ninh động và thu thập tình báo mối đe dọa Web3 do SlowMist tự phát triển, cung cấp khả năng phát hiện hoạt động độc hại và cảnh báo rủi ro chuỗi cung ứng cho hệ sinh thái gói nguồn mở thông qua API.

Toàn bộ các gói độc hại và IOC liên quan đến chiến dịch này đã được tích hợp vào động cơ phát hiện mối đe dọa MistEye, giúp nhà phát triển có thể thực hiện phát hiện tự động hóa các phụ thuộc dự án thông qua API, nhanh chóng xác định xem có trùng với các gói độc hại đã biết hay không và nhận đề xuất xử lý.

Tuyên bố miễn trừ trách nhiệm: Thông tin trên trang này có thể được lấy từ bên thứ ba và không nhất thiết phản ánh quan điểm hoặc ý kiến của KuCoin. Nội dung này chỉ được cung cấp cho mục đích thông tin chung, không có bất kỳ đại diện hay bảo đảm nào dưới bất kỳ hình thức nào và cũng không được hiểu là lời khuyên tài chính hay đầu tư. KuCoin sẽ không chịu trách nhiệm về bất kỳ sai sót hoặc thiếu sót nào hoặc về bất kỳ kết quả nào phát sinh từ việc sử dụng thông tin này. Việc đầu tư vào tài sản kỹ thuật số có thể tiềm ẩn nhiều rủi ro. Vui lòng đánh giá cẩn thận rủi ro của sản phẩm và khả năng chấp nhận rủi ro của bạn dựa trên hoàn cảnh tài chính của chính bạn. Để biết thêm thông tin, vui lòng tham khảo Điều khoản sử dụng và Tiết lộ rủi ro của chúng tôi.