Skip to main content

Command Palette

Search for a command to run...

BdThemes: tấn công chuỗi cung ứng WordPress không sửa một dòng code nào

Updated
21 min readView as Markdown
BdThemes: tấn công chuỗi cung ứng WordPress không sửa một dòng code nào

Tóm tắt

Không một file mã nguồn nào trên kho WordPress.org bị sửa đổi. Không có bản cập nhật plugin nào được phát hành. Không có file nào trên đĩa thay đổi.

Nhưng tài khoản quản trị giả đã được tạo trên các site nạn nhân, webshell PHP đã được cài, và hai module backdoor đã được cắm vào thư mục mu-plugins.

Kẻ tấn công chiếm được quyền ghi vào DigitalOcean Spaces bucket của chính BdThemes — nơi nhà cung cấp này lưu dữ liệu JSON cho hệ thống banner quảng cáo hiển thị trong bảng điều khiển WordPress — rồi thay nội dung hợp lệ bằng payload khai thác một lỗi XSS có sẵn trong thư viện nội bộ Biggopti đi kèm plugin.

Bảy plugin bị ảnh hưởng. Riêng Element Pack có hơn 100.000 lượt cài đặt đang hoạt động trên WordPress.org, còn BdThemes quảng cáo danh mục hơn 350.000 lượt cài.

Điều đáng nói nhất với người làm phòng thủ: ngành bảo mật WordPress đã dành mười lăm năm xây dựng công cụ kiểm tra tính toàn vẹn file — so sánh hash, phát hiện file lạ, diff phiên bản plugin. Toàn bộ lớp phòng thủ đó mù hoàn toàn ở đây, vì không có gì để so sánh.

Hành động ưu tiên: nếu website của bạn chạy bất kỳ plugin BdThemes nào, hãy coi site là đã bị xâm phạm và rà ngay danh sách người dùng tìm tài khoản có email @wordpress.org hoặc username bắt đầu bằng bd_.


Lỗ hổng: khi CVSS 5.4 trở thành chiếm quyền toàn site

Chuỗi tấn công BdThemes

Tổng quan chiến dịch tấn công chuỗi cung ứng BdThemes (nguồn: Cyber Security News, dựa trên phân tích của Wordfence).

Biggopti là một component nội bộ được đóng gói kèm các plugin BdThemes. Nhiệm vụ của nó rất bình thường: kéo banner quảng cáo từ máy chủ API của nhà cung cấp — cụ thể là các file JSON đặt trong một DigitalOcean Spaces bucket, có Cloudflare đứng trước — rồi render chúng trong bảng điều khiển quản trị WordPress.

Lỗi nằm ở khâu phân tích phản hồi JSON: Biggopti không escape đúng giá trị trường display_id trước khi chèn nó vào thuộc tính HTML id. Chi tiết đáng chú ý là một trường nằm ngay bên cạnh lại được sanitize hoàn toàn đúng cách — chỉ riêng trường này bị bỏ sót.

Hạng mục Chi tiết
Component Biggopti (nội bộ, đi kèm plugin)
Nguồn dữ liệu Sigmative API, JSON trên DigitalOcean Spaces bucket
Trường lỗi display_id — thiếu escape phía client
Loại Cross-site scripting (XSS)
CVSS (Wordfence) 5.4 — medium
Xuất hiện lần đầu 01/03/2026, trong bdthemes-prime-slider-lite v4.1.9
Cơ chế kích hoạt Handler onanimationstart, chạy trong vòng 10 mili giây sau khi trang load
Phạm vi kích hoạt Mọi lần load trang wp-admin của bất kỳ quản trị viên nào đang đăng nhập

Đây là điểm tôi cho là đáng phân tích riêng. 5.4 là điểm chấm đúng theo phương pháp luận CVSS, và nếu chỉ đọc con số đó, một đội vận hành sẽ xếp nó xuống cuối hàng đợi vá. Nhưng điểm số ấy được tính dựa trên một giả định ngầm: rằng nguồn dữ liệu — API của chính nhà cung cấp — là đáng tin cậy.

Khi giả định đó sụp đổ, cùng một lỗ hổng cho phép chiếm quyền toàn bộ website. Thang điểm CVSS không có trường nào để ghi "nếu upstream bị chiếm quyền". Đây là khoảng trống mà mô hình chấm điểm hiện tại chưa xử lý được, và nó xuất hiện ngày càng nhiều khi phần mềm hiện đại kéo dữ liệu động từ hạ tầng bên ngoài.

Timeline: ba nạn nhân, một actor

Điều làm sự việc này đáng chú ý hơn một sự cố đơn lẻ là Wordfence đánh giá hạ tầng C2 được dùng ở đây có liên hệ với hai vụ tấn công chuỗi cung ứng WordPress khác trong hai tháng trước đó.

Thời điểm Sự kiện
01/03/2026 Lỗi XSS display_id được đưa vào Prime Slider v4.1.9, sau đó lan sang các plugin BdThemes khác
14/06/2026 OptinMonster và TrustPulse công bố sự cố: khóa CDN bị chiếm, kẻ tấn công phục vụ phiên bản JavaScript đã bị sửa đổi từ chính CDN của họ
23/06/2026 Mốc sớm nhất có thể của chiến dịch BdThemes, theo phân tích bản ghi của Wordfence
28/07/2026 Advanced Responsive Video Embedder (ARVE) 10.8.7 bị cắm backdoor; hệ thống PRISM của Wordfence phát hiện trong dưới hai giờ; CVE-2026-18072, CVSS 9.8
07/08/2026 Wordfence bắt được các cuộc tấn công qua WAF; phát signature và WAF rule cho khách hàng Premium, Care, Response và Wordfence CLI trả phí
07–08/08/2026 WordPress Plugins team đóng toàn bộ 7 plugin BdThemes trên kho, chờ rà soát đầy đủ
08/08/2026 Cả hai endpoint API bị đầu độc trả về JSON sạch trở lại; Wordfence công bố phân tích
11/08/2026 Báo chí đưa tin rộng rãi; BdThemes vẫn chưa có thông cáo chính thức

Mô thức chung của cả ba vụ

Đặt ba sự cố cạnh nhau, mô thức hiện ra rất rõ và đó mới là thứ đáng mang vào báo cáo nội bộ:

OptinMonster / TrustPulse ARVE BdThemes
Điểm bị chiếm Khóa API của CDN Quyền commit tài khoản dev Credential cloud storage
Mã nguồn kho bị sửa? Không (v10.8.7) Không
Điều kiện kích hoạt Admin đang đăng nhập Một HTTP request Admin đang đăng nhập
Kết quả Tài khoản admin ẩn + plugin backdoor ẩn Truy cập admin không cần xác thực Tài khoản admin giả + webshell + backdoor mu-plugins

Hai trong ba vụ không chạm vào mã nguồn. Cả ba đều tấn công lớp phân phối thay vì lớp mã nguồn: khóa CDN, tài khoản nhà phát triển, credential lưu trữ đám mây. Và trong hai vụ, payload chỉ kích hoạt cho quản trị viên đang đăng nhập — một lựa chọn giúp tránh hoàn toàn việc bị người dùng thường hay hệ thống quét tự động phát hiện.

Wordfence nhận định mục tiêu cuối cùng của chiến dịch là thiết lập quyền quản trị ngầm và khả năng thực thi mã từ xa trên các môi trường WordPress ở quy mô lớn.


Chuỗi tấn công

  1. Kẻ tấn công chiếm được credential cloud của BdThemes, giành quyền ghi vào DigitalOcean Spaces bucket của nhà cung cấp.

  2. Chúng thay thế các bản ghi JSON hợp lệ bằng payload được dựng riêng, đặt mã độc vào trường display_id.

  3. Một quản trị viên WordPress đang đăng nhập mở bất kỳ trang wp-admin nào trên site có cài plugin BdThemes.

  4. Biggopti tự động fetch dữ liệu banner từ endpoint API.

  5. Giá trị display_id bị đầu độc được chèn vào thuộc tính HTML id mà không escape; handler onanimationstart kích hoạt trong vòng 10 mili giây.

  6. Payload chính — file JavaScript tên w2.js, phân phối qua endpoint api-data-all-records — bắt đầu chạy trong trình duyệt đã xác thực của quản trị viên.

  7. w2.js liên hệ máy chủ C2 tại ia-cdn[.]com/fz/c, gửi kèm origin của website nạn nhân để nhận chỉ thị nhắm mục tiêu. Nếu C2 trả về trạng thái skip hoặc done, quá trình dừng lại.

  8. Dùng REST API nonce của chính phiên quản trị đang hoạt động, script tạo một tài khoản quản trị viên giả qua WordPress REST API.

  9. Tải một file ZIP plugin giả từ C2 — với slug nghe vô hại kiểu wp-smart-thumbnails — và cài nó qua form upload plugin tiêu chuẩn của WordPress.

  10. Plugin đó chứa một webshell PHP tên emer-run.php.

  11. Gọi webshell để cài hai module persistence vào thư mục mu-plugins (Must-Use plugins — loại plugin luôn được kích hoạt và không thể tắt từ giao diện quản trị), với thời gian file bị đặt lùi về tháng 09/2025.

  12. Module thứ nhất là backdoor magic-login: cho phép đăng nhập quản trị không cần xác thực qua tham số URL ?_wplogin=<token>, nhắm vào tài khoản quản trị có thời gian đăng ký lâu đời nhất trên site.

  13. Module thứ hai là module chống phân tích: hook vào các truy vấn cơ sở dữ liệu của WordPress để giấu các tài khoản giả khỏi danh sách người dùng trong giao diện quản trị, đồng thời trừ chúng ra khỏi tổng số người dùng hiển thị.

  14. Kết quả của toàn bộ quá trình được gửi ngược về C2 qua navigator.sendBeacon. Bước 7 và bước 11 đáng chú ý riêng.

Cơ chế skip/done ở bước 7 cho thấy kẻ tấn công quản lý danh sách mục tiêu ở phía server và tránh chạy lại trên site đã xử lý xong. Với đội ứng cứu, điều này có nghĩa là việc không quan sát thấy hoạt động không đồng nghĩa với việc site chưa bị nhắm — có thể C2 đơn giản đã trả về done.

Việc backdate file ở bước 11 là chi tiết chống điều tra nhỏ nhưng hiệu quả. Một quản trị viên rà thư mục mu-plugins theo thời gian sửa đổi sẽ thấy các file có vẻ đã tồn tại từ tháng 09/2025 — tức trước cả thời điểm lỗ hổng được đưa vào mã nguồn — và nhiều khả năng bỏ qua chúng.

Payload thứ hai: credential tất định

Một payload thay thế tên x.js, được phát hiện host trên chính hạ tầng của nhà phát triển plugin và phục vụ qua endpoint api-data-records, hoạt động theo cách khác.

Thay vì tạo tài khoản với thông tin ngẫu nhiên, nó sinh credential quản trị được suy ra bằng toán học từ hostname của website nạn nhân:

Username    bd_ + hash base36 6 ký tự
Password    Bd@26! + hash + x
Email       một địa chỉ @wordpress.org

Wordfence chỉ ra hệ quả hai chiều của thiết kế này, và cả hai chiều đều đáng ghi nhớ.

Về phía kẻ tấn công: vì credential là tất định, chúng không cần duy trì một danh sách nạn nhân tập trung. Chỉ cần biết hostname là tính lại được thông tin đăng nhập bất cứ lúc nào. Không có cơ sở dữ liệu nạn nhân nào để bị thu giữ hay rò rỉ.

Về phía phòng thủ: đội ứng cứu cũng tính được chính xác username và password cần săn trên một domain nghi ngờ. Đây là loại điều kiện hiếm gặp trong ứng cứu sự cố — bạn biết trước chính xác thứ mình đang tìm, không cần phỏng đoán.

Việc dùng địa chỉ email @wordpress.org cũng là một lựa chọn có tính toán về mặt xã hội học: với một quản trị viên đang lướt nhanh qua danh sách người dùng, tài khoản đó trông như một tài khoản hệ thống chính thức chứ không phải kẻ xâm nhập.


Plugin bị ảnh hưởng

Slug Tên plugin Lượt cài đang hoạt động
bdthemes-element-pack-lite Element Pack Addons for Elementor 100.000+
live-copy-paste Live Copy Paste for Elementor 6.000+
ultimate-store-kit Ultimate Store Kit – Addon For WooCommerce, EDD and Elementor 6.000+
bdthemes-prime-slider-lite Prime Slider Addons for Elementor Không công bố
pixel-gallery Pixel Gallery Addons for Elementor Không công bố
ultimate-post-kit Ultimate Post Kit Addons for Elementor Không công bố
smart-admin-assistant Smart Admin Assistant – Dashboard and Site Enhancements Không công bố

Toàn bộ bảy plugin đã bị WordPress Plugins team đóng trên kho chính thức trong ngày 07 hoặc 08/08/2026, với thông báo chờ "rà soát đầy đủ".


IOC

IOC tổng hợp từ báo cáo của Wordfence Threat Intelligence ngày 08/08/2026 và các nguồn đưa tin lại chi tiết kỹ thuật. Domain đã defang.

Hạ tầng C2 và payload

ia-cdn[.]com/fz/c            # endpoint C2 nhận origin site và trả chỉ thị nhắm mục tiêu
                             # lưu ý cách đặt tên giả dạng một dịch vụ CDN hợp pháp
 
w2.js                        # payload chính, phục vụ qua endpoint api-data-all-records
x.js                         # payload thay thế, host trên hạ tầng của BdThemes,
                             # phục vụ qua endpoint api-data-records
 
api-data-all-records         # endpoint API bị đầu độc (Sigmative API)
api-data-records             # endpoint API bị đầu độc (Sigmative API)

Artifact trên website

# Webshell
emer-run.php                 # webshell PHP, cài qua plugin ZIP giả
 
# Slug plugin giả (ví dụ đã quan sát được)
wp-smart-thumbnails          # tên trung tính, cài qua form upload plugin chuẩn
 
# Thư mục mu-plugins
Hai file lạ, thời gian file bị đặt lùi về tháng 09/2025:
  - module magic-login backdoor
  - module chống phân tích, giấu user khỏi danh sách quản trị
 
# Tham số URL của backdoor
?_wplogin=<token>            # đăng nhập admin không cần xác thực,
                             # nhắm tài khoản admin đăng ký lâu đời nhất
 
# Option trong cơ sở dữ liệu WordPress
fz_emer_login_tokens
fz_emer_done_v1

Mẫu tài khoản quản trị giả

Username    bd_<hash base36 6 ký tự>
Password    Bd@26!<hash>x
Email       <bất kỳ>@wordpress.org
 
# Vì credential là tất định theo hostname, đội ứng cứu có thể tính trước
# chính xác giá trị cần săn trên một domain cụ thể

Chỉ dấu hành vi

- Tài khoản quản trị viên xuất hiện ngoài quy trình, đặc biệt với email @wordpress.org
- Plugin lạ được cài mà không có ai trong tổ chức thực hiện
- Chênh lệch giữa tổng số user hiển thị và số user thực trong bảng CSDL
- File trong mu-plugins có timestamp không khớp với lịch sử triển khai của site
- Request outbound tới ia-cdn[.]com từ trình duyệt quản trị viên

Chiến dịch liên quan (bối cảnh)

CVE-2026-18072    Advanced Responsive Video Embedder 10.8.7
                  CVSS 9.8 — Authentication Bypass qua backdoor hardcode
                  File: php/fn-update-check.php, hàm _arve_uc_init()
                  Tham số: _wplogin, _wpm
                  Phát hiện bởi Wordfence PRISM trong dưới 2 giờ (28/07/2026)
                  ~20.000 lượt cài đang hoạt động
 
OptinMonster / TrustPulse   Sự cố CDN, công bố 14/06/2026
                  Khóa CDN bị chiếm, JavaScript bị sửa đổi phục vụ từ CDN
                  Chỉ kích hoạt cho quản trị viên đang đăng nhập

MITRE ATT&CK Mapping

Tactic Technique ID Technique Name Ghi nhận trong chiến dịch
Initial Access T1195.002 Supply Chain Compromise: Software Supply Chain Đầu độc luồng dữ liệu JSON của nhà cung cấp
Resource Development T1584 Compromise Infrastructure Chiếm quyền ghi vào bucket lưu trữ của chính BdThemes
Resource Development T1583.001 Acquire Infrastructure: Domains ia-cdn[.]com đăng ký làm hạ tầng C2
Execution T1059.007 Command and Scripting Interpreter: JavaScript w2.js, x.js chạy trong trình duyệt quản trị viên
Defense Evasion T1036.005 Masquerading: Match Legitimate Name or Location wp-smart-thumbnails; domain C2 giả dạng dịch vụ CDN
Credential Access T1185 Browser Session Hijacking Lạm dụng REST API nonce của phiên quản trị đang hoạt động
Persistence T1136 Create Account Tạo tài khoản quản trị viên giả qua REST API
Persistence T1505.003 Server Software Component: Web Shell emer-run.php
Persistence T1505 Server Software Component Hai module backdoor trong mu-plugins
Persistence T1098 Account Manipulation Nhắm và lạm dụng tài khoản admin lâu đời nhất
Defense Evasion T1070.006 Indicator Removal: Timestomp File mu-plugins bị đặt lùi thời gian về 09/2025
Defense Evasion T1564 Hide Artifacts Hook truy vấn CSDL để giấu tài khoản giả khỏi danh sách user
Defense Evasion T1027 Obfuscated Files or Information Payload JavaScript trong phản hồi JSON
Exfiltration T1041 Exfiltration Over C2 Channel Gửi kết quả về C2 qua navigator.sendBeacon
Impact T1078 Valid Accounts Duy trì truy cập quản trị thường trực

Nhận định

Ngành bảo mật WordPress đã xây toàn bộ hệ thống phòng thủ quanh một giả định: mã độc nằm trong file.

Đó là giả định hợp lý và đã đúng suốt nhiều năm. Plugin bị backdoor thì file thay đổi. Site bị chiếm thì có file lạ xuất hiện. Vì vậy công cụ được xây theo hướng đó: so sánh hash file plugin với bản trên kho chính thức, quét thư mục tìm file lạ, cảnh báo khi có bản cập nhật bất thường. Kho WordPress.org cung cấp bản gốc để đối chiếu, và mô hình này hoạt động tốt.

Chiến dịch này đặt payload ở đúng nơi mà không công cụ nào quét: một phản hồi JSON. Không có file để hash. Không có diff để so sánh. Không có bản cập nhật nào để review. Plugin trên đĩa giống hệt bản trên kho chính thức, tính đến từng byte — và vẫn thực thi mã của kẻ tấn công mỗi lần quản trị viên mở dashboard.

Nhưng có một nghịch lý đáng chú ý ở đây, và nó có lợi cho phía phòng thủ. Chính vì kỹ thuật này khác thường, nó lại để lại những dấu vết rất cụ thể và dễ xác nhận bằng tay: một tên tham số URL, hai tên option trong cơ sở dữ liệu, một mẫu username tính toán được. Khó phát hiện bằng scanner tự động, nhưng dễ xác nhận trong mười lăm phút nếu bạn biết cần nhìn vào đâu. Đây không phải loại sự cố cần công cụ đắt tiền để điều tra.

Về khoảng trống trong chấm điểm mức độ nghiêm trọng. Lỗi XSS này được chấm 5.4 — mức trung bình. Trong hàng đợi vá của phần lớn tổ chức, con số đó nằm dưới ngưỡng ưu tiên. Nhưng điểm số ấy phản ánh mức độ nguy hiểm nếu nguồn dữ liệu đáng tin cậy. Khi chính nhà cung cấp bị chiếm, cùng một lỗi cho phép chiếm quyền toàn site.

Đây là vấn đề ngày càng phổ biến chứ không phải trường hợp cá biệt. Phần mềm hiện đại liên tục kéo dữ liệu động từ hạ tầng bên ngoài: banner quảng cáo, thông báo cập nhật, cấu hình từ xa, telemetry. Mỗi luồng như vậy là một kênh mà mã của bạn tin tưởng theo mặc định, và mô hình chấm điểm hiện hành không có chỗ để ghi nhận rủi ro đó.

Trạng thái khó xử hiện tại của chủ website. Các plugin đã bị đóng trên WordPress.org, nghĩa là không còn đường cập nhật qua kênh chính thức. Lỗ hổng chưa được vá tại thời điểm báo cáo được công bố, và nhà cung cấp chưa ra thông cáo. Điều đó đặt chủ site vào một lựa chọn không dễ chịu: giữ plugin thì mang theo lỗ hổng chưa vá, gỡ plugin thì phần lớn layout Elementor trên site sẽ vỡ.

Trong tình huống này, việc endpoint API đã trả về dữ liệu sạch từ ngày 08/08 là điều tích cực nhưng không phải giải pháp — nó phụ thuộc vào việc kẻ tấn công không lấy lại được quyền ghi vào bucket, và đó là thứ nằm ngoài tầm kiểm soát của bạn.

Liên hệ Việt Nam

Tổ hợp WordPress + Elementor cực kỳ phổ biến trong nước. Đây là nền tảng mặc định cho website doanh nghiệp vừa và nhỏ, cửa hàng trực tuyến, landing page và website giới thiệu công ty tại Việt Nam — vì chi phí thấp, dễ tìm người làm, và không đòi hỏi năng lực kỹ thuật để vận hành. Element Pack là một trong những bộ addon Elementor được dùng nhiều nhất trong hệ sinh thái đó.

Hai đặc thù của thị trường trong nước làm rủi ro nặng thêm.

Thứ nhất là mô hình agency dựng rồi bàn giao. Rất nhiều website doanh nghiệp được một đơn vị bên ngoài xây dựng, bàn giao, rồi kết thúc hợp đồng. Sau đó không ai theo dõi plugin nào đang chạy, phiên bản nào, có bản vá nào không. Website tiếp tục hoạt động bình thường trong nhiều năm, và đó chính xác là điều kiện mà chiến dịch này cần.

Thứ hai là hosting chia sẻ. Với các gói hosting giá rẻ phổ biến trong nước, nhiều website thường nằm trên cùng một tài khoản hoặc cùng một máy chủ. Một site bị chiếm quyền quản trị và cài được webshell có thể trở thành bàn đạp sang các site khác trong cùng phạm vi.

Một câu hỏi vận hành rất đơn giản để tự kiểm tra: ai trong tổ chức bạn biết được website công ty đang chạy những plugin nào, phiên bản bao nhiêu? Với phần lớn doanh nghiệp vừa và nhỏ mà chúng tôi tiếp xúc, câu trả lời là không ai — và điều đó có nghĩa là ngay cả khi cảnh báo này đến được tay đúng người, họ vẫn không trả lời được câu hỏi "chúng ta có bị ảnh hưởng không".

Nếu tổ chức bạn chưa có danh sách plugin của các website đang vận hành, việc lập danh sách đó đáng làm trước cả việc xử lý sự cố cụ thể này.


Khuyến nghị

  • Nếu website chạy bất kỳ plugin BdThemes nào, coi site là đã bị xâm phạm cho tới khi chứng minh được ngược lại — đặc biệt với các site có quản trị viên đăng nhập dashboard thường xuyên trong khoảng từ 23/06 tới 08/08/2026.

  • Rà bốn artifact cụ thể: tài khoản có email @wordpress.org hoặc username bắt đầu bằng bd_; file lạ trong thư mục mu-plugins (bỏ qua timestamp vì đã bị đặt lùi); webshell emer-run.php; và hai option fz_emer_login_tokens, fz_emer_done_v1 trong bảng options của cơ sở dữ liệu.

  • Xoay toàn bộ credential quản trị và hủy các phiên đang hoạt động — phiên đã xác thực của quản trị viên chính là thứ bị lạm dụng để thực hiện tấn công, nên việc chỉ xóa tài khoản giả là chưa đủ.

  • Đối chiếu tổng số người dùng hiển thị trong giao diện với số bản ghi thực trong bảng wp_users — module chống phân tích của kẻ tấn công giấu tài khoản khỏi cả hai chỗ, nên chênh lệch giữa CSDL và giao diện là dấu hiệu trực tiếp.

  • Lập và duy trì danh sách plugin cho mọi website đang vận hành, kèm phiên bản và người chịu trách nhiệm — không có danh sách này thì không trả lời được câu hỏi cơ bản nhất khi có cảnh báo.

  • Với các luồng dữ liệu động từ bên ngoài nói chung: rà xem những component nào trong hệ thống của bạn đang tự động fetch và render nội dung từ hạ tầng bên thứ ba trong ngữ cảnh có đặc quyền, và coi những luồng đó là dữ liệu không tin cậy chứ không phải nguồn được bảo chứng.


Tài liệu tham khảo

More from this blog

F

FPT IS Security

936 posts

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