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
- Mở trang ở phiên đăng xuất hoặc browser profile sạch; bật DevTools trước khi reload.
- Trong Network, bật Preserve log; reload để giữ request qua navigation.
- Lọc theo Script, Fetch/XHR, Doc, iframe và domain nghi vấn.
- Ghi request URL, status, initiator, timing, destination và execution context nếu DevTools hiển thị.
- Dùng Initiator/call stack hoặc Sources để truy ngược request về inline code/file/component tạo nó.
- Đối chiếu với plugin/theme/tag manager/CDN inventory và deployment/change history.
- 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.
- 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.
- Lưu HTML response gốc từ Network hoặc view-source.
- Lưu rendered DOM sau page load.
- So sánh script/iframe/link/node chỉ xuất hiện sau execution.
- Với node động, truy event listener/initiator hoặc parent script.
- Nếu source server đã chứa payload, ưu tiên template/plugin/DB/file/server-side investigation.
- 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
- Chrome for Developers — DevTools Network updates
- Google Search Central — Hacked content
- WordPress.org — FAQ: My site was hacked
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ó.
