WordPress bị chèn JavaScript lạ: cách phát hiện client-side malware

Minh họa phát hiện JavaScript lạ và request bên ngoài đáng ngờ trên WordPress

WordPress bị chèn JavaScript lạ phải được điều tra như một vấn đề provenance + runtime behavior, không phải chỉ “tìm file JS đáng ngờ”. Script có thể đến từ core/plugin/theme hợp lệ, tag manager, consent manager, CDN, quảng cáo hoặc integration; cũng có thể là injected code, compromised third-party script hoặc client-side malware. Mục tiêu là chứng minh được script nào chạy, ai/đâu tạo nó, request nào do nó phát sinh, điều kiện nào kích hoạt và source đó có thuộc baseline hợp lệ không.

Điểm quan trọng: HTML source, rendered DOM và network behavior có thể khác nhau. Một đoạn script có thể không xuất hiện rõ trong view-source nhưng được tạo động; ngược lại, một file minified lạ mắt không tự động là malware.

Điều tra theo 4 lớp: Source → Rendered DOM → Network → Owner

Lớp Cần kiểm Câu hỏi chính
Source HTML response, inline script, template output Script có được server trả sẵn không?
Rendered DOM DOM sau JavaScript execution Node/script nào được tạo sau load?
Network Script, Fetch/XHR, beacon, redirect, iframe Browser đang gọi tới đâu và từ initiator nào?
Owner Plugin/theme/tag manager/CDN/custom code/account Component hoặc người nào chịu trách nhiệm cho behavior?

Workflow DevTools để truy nguồn script

  1. Mở trang ở phiên đăng xuất hoặc browser profile sạch; bật DevTools trước khi reload.
  2. Trong Network, bật Preserve log; reload để giữ request qua navigation.
  3. Lọc theo Script, Fetch/XHR, Doc, iframe và domain nghi vấn.
  4. Ghi request URL, status, initiator, timing, destination và execution context nếu DevTools hiển thị.
  5. Dùng Initiator/call stack hoặc Sources để truy ngược request về inline code/file/component tạo nó.
  6. Đối chiếu với plugin/theme/tag manager/CDN inventory và deployment/change history.
  7. Nếu issue chỉ xảy ra ở một số user, tái hiện với cùng login state, cookie, referrer, device/user-agent hoặc route; không chạy payload độc hại trên production.
  8. Lưu evidence trước khi cleanup nếu đang điều tra incident.

Chrome DevTools hiện có thể hiển thị execution context và console originator cho network request, hữu ích khi truy request về source thực thi. Không nên phụ thuộc vào tên file đơn lẻ; cần correlation giữa initiator, source owner và behavior.

Client-side IOC & Behavior Matrix

Evidence Ghi nhận Câu hỏi xác minh
Script URL/domain First-party / third-party / blob / inline Owner hợp lệ? domain có trong baseline?
Initiator File, inline script, tag manager, call stack Component nào tạo request?
Network request Method/status/destination Request có phù hợp chức năng business không?
Inline snippet/hash Snippet hoặc fingerprint Có trong source/deploy baseline không?
DOM mutation Iframe/script/link/form node mới Node xuất hiện khi nào và bởi script nào?
Trigger Load/click/timer/referrer/cookie/device Behavior có điều kiện không?
Redirect 3xx hoặc client-side navigation Redirect xảy ra server-side hay browser-side?

Phân biệt script hợp lệ với script cần điều tra

Tín hiệu Khả năng hợp lệ cao hơn Cần điều tra sâu
Domain/vendor đã biết, có owner/change record Có Nếu behavior khác baseline
Minified/bundled code Có thể hoàn toàn hợp lệ Không kết luận chỉ vì khó đọc
Domain mới, không owner, load theo timer/referrer/cookie Thấp hơn Ưu tiên provenance + network + trigger
Script khác baseline cùng lúc file/account/config đổi Thấp hơn Correlate timeline
Third-party script vendor hợp lệ nhưng behavior mới Không chắc Kiểm supply-chain/config compromise

Source vs Rendered Comparison

Đây là bước rất hữu ích để xác định code được chèn ở server hay được tạo trong browser.

  1. Lưu HTML response gốc từ Network hoặc view-source.
  2. Lưu rendered DOM sau page load.
  3. So sánh script/iframe/link/node chỉ xuất hiện sau execution.
  4. Với node động, truy event listener/initiator hoặc parent script.
  5. Nếu source server đã chứa payload, ưu tiên template/plugin/DB/file/server-side investigation.
  6. Nếu source sạch nhưng DOM/network sinh behavior lạ, ưu tiên runtime script/tag manager/third-party/extension context.

Browser extension cũng có thể chèn script vào máy người kiểm tra. Vì vậy cần lặp lại ở profile sạch/incognito phù hợp và trên thiết bị khác trước khi kết luận website compromise.

Script có thể được chèn từ đâu?

  • Theme hoặc plugin bị sửa.
  • MU-plugin hoặc custom loader.
  • Database/options/widget/post content.
  • Tag manager hoặc third-party integration bị lạm dụng.
  • CDN/cache/edge transformation trả nội dung khác origin.
  • Compromised account thêm code qua admin/editor/integration.
  • File hợp lệ bị code injection.

Nếu suspect nằm trong file WordPress/plugin/theme, hãy đối chiếu với baseline/checksum hoặc package/source chính thức thay vì chỉ grep các chuỗi như eval, base64 hay tên file lạ. Những pattern này có thể xuất hiện trong code hợp lệ và chỉ là triage signal.

JavaScript lạ có phải nguyên nhân của redirect?

Có thể, nhưng redirect có thể xảy ra ở CDN, web server, PHP, plugin hoặc browser. Nếu response đầu tiên đã là 3xx, ưu tiên server/edge path. Nếu response đầu là 200 nhưng browser tự điều hướng sau execution, client-side đáng nghi hơn. Dùng workflow WordPress bị redirect sang trang lạ để phân lớp đúng.

Trigger Reproduction Matrix

Biến Giá trị thử Mục tiêu
Authentication Logged-out / logged-in Phát hiện role/session conditional behavior
Referrer Direct / Search / known campaign Phát hiện redirect theo referrer
Cookie state Clean / existing Phát hiện one-time payload hoặc suppression
Device/User-Agent Desktop/mobile profile Phát hiện conditional delivery
Route Home / post / login / landing Xác định scope
Cache Warm / bypass nếu an toàn Phân biệt edge/cache artifact

Browser/Network Evidence Record mẫu

Worksheet này để ghi evidence thật; không phải kết quả đã quan sát trên site.

case_id: JS-YYYY-NNN
page_url: ...
timestamp_utc: ...
browser_version: ...
profile_state: clean|logged-in|logged-out
referrer: ...
cookie_state: ...
user_agent_profile: ...
script_url: ...
script_owner: plugin|theme|tag-manager|third-party|unknown
initiator: ...
execution_context: ...
request_url: ...
request_method: ...
response_status: ...
destination_domain: ...
trigger: load|click|timer|referrer|cookie|unknown
source_present: yes|no
rendered_only: yes|no
baseline_match: yes|no|unknown
related_file_or_config: ...
evidence_refs: [...]
classification: legitimate|suspicious|confirmed-malicious|unknown
next_action: ...

Evidence handling: HAR và trace có thể chứa dữ liệu nhạy cảm

HAR, Network export, screenshot, source map hoặc trace có thể chứa URL parameter, header, token, request body, user data hoặc internal endpoint. Trước khi chia sẻ evidence ra ngoài incident team, cần review/redact secret và dữ liệu nhạy cảm. Không đăng raw session token, authorization header hoặc credential lên ticket/public article.

Remediation không nên chỉ block domain

Chặn domain ở WAF/browser/DNS có thể giảm impact tức thời nhưng không chứng minh source chèn code đã được xử lý. Nếu malicious code vẫn còn trong file/database/tag manager, attacker có thể đổi destination và behavior quay lại.

Remediation đúng phải xử lý source owner + persistence + entry point, sau đó mới verify behavior.

Remediation Verification Checklist

  • Source/component tạo script đã được xác định.
  • Nếu malicious, file/config/database/account liên quan đã được xử lý.
  • Không còn request tới destination đáng ngờ trong cùng trigger condition.
  • Rendered DOM không còn node/payload bất thường.
  • Behavior không tái xuất hiện qua nhiều lần reload/profile/route phù hợp.
  • Không còn persistence tái tạo code sau deploy/cache purge/restart cần thiết.
  • Legitimate business scripts vẫn hoạt động.
  • Evidence và rollback/change record đã được lưu.

PASS/FAIL cho bước điều tra client-side malware

  • PASS: provenance rõ; behavior tái hiện được; owner/source xác định; remediation xử lý source; network/DOM verification không còn malicious behavior.
  • FAIL: chỉ xóa một snippet/block domain; không biết source owner; behavior quay lại; hoặc chỉ dựa vào “script nhìn lạ”.
  • HOLD: behavior chỉ xuất hiện có điều kiện nhưng chưa tái hiện được hoặc third-party owner chưa xác minh. HOLD cần giữ evidence và tiếp tục reproduction.

Khi nào nên escalation?

Nếu script đang redirect người dùng, tải nội dung nguy hiểm, xuất hiện có điều kiện khó tái hiện, quay lại sau khi xóa hoặc đi cùng Admin lạ/file change/SEO spam, nên coi đây là incident rộng hơn. WordPress đơn lẻ cần cleanup + verification có thể đi theo Malware Removal; nếu incident đang diễn ra hoặc nhiều hệ thống bị ảnh hưởng, xem Incident Response.

Nguồn kỹ thuật tham khảo

Kết luận

Phát hiện client-side malware hiệu quả phải nối được source → rendered DOM → network request → initiator → owner → trigger → verification. “JavaScript lạ” chỉ là điểm bắt đầu. Một remediation chỉ được coi là hoàn tất khi source chèn code đã được xử lý và malicious behavior không còn tái xuất hiện trong điều kiện đã từng kích hoạt nó.

◇
Cần hỗ trợ kiểm tra và xử lý website?Đội ngũ SecureWebOps sẵn sàng hỗ trợ theo phạm vi phù hợp.
Liên hệ ngay →
Đoàn Trình Dục
Về tác giả Đoàn Trình Dục TD Digital · Website Operations & Security

Đoàn Trình Dục là tác giả nội dung trên SecureWebOps. Các bài viết tập trung vào bảo mật WordPress, giám sát an ninh website, malware/backdoor, hardening, backup/recovery và Incident Response theo hướng thực hành, có bước kiểm tra, bằng chứng, validation và rollback khi phù hợp.

Xem hồ sơ tác giả →