Cách trường form ẩn, liên kết bẫy và kiểm tra thời gian bắt bot sơ đẳng mà không làm phiền người thật, và vì sao tự động điền là nguyên nhân báo nhầm phổ biến.
Honeypot là phép kiểm tra bot rẻ nhất mà một website có thể chạy: đặt vào trang một thứ mà con người không bao giờ nhìn thấy hay chạm tới, rồi coi mọi tương tác với nó là bằng chứng người truy cập là một chương trình. Nó gần như không tốn gì cho website, không gây phiền cho người dùng thật, và lột trần bot sơ đẳng ngay khi nó đọc trang như mã đánh dấu thô thay vì như điểm ảnh.
Điểm chính
- Sự bất đối xứng chính là toàn bộ mẹo. Con người tương tác với những gì được hiển thị; bot đơn giản tương tác với những gì có trong DOM. Một cái bẫy chỉ tồn tại trong DOM sẽ phân biệt hai bên.
- Ba loại bẫy phổ biến: trường form ẩn phải luôn để trống, liên kết ẩn tới URL mà
robots.txtcấm, và kiểm tra thời gian form được gửi lại nhanh đến mức nào. - Khó khăn kỹ thuật thật sự là không làm hại người khuyết tật. Trình đọc màn hình duyệt qua DOM, nên cái bẫy chỉ ẩn bằng CSS có thể bẫy nhầm người đang dùng công nghệ hỗ trợ.
- Tự động điền là nguyên nhân báo nhầm hàng đầu. Trình quản lý mật khẩu và tự động điền của trình duyệt có thể điền vào trường mà người dùng chưa từng thấy, nên người thật bị chặn thường không làm gì sai.
- Honeypot là lớp lọc đầu tiên, không phải phòng thủ đầy đủ. Nó bắt được công cụ cào dữ liệu và script spam form, nhưng vô dụng trước trình duyệt thật do tự động hóa điều khiển.
Vì sao cái bẫy hiệu quả
Mọi phép kiểm tra bot đều hỏi cùng một câu: client này có cư xử như người không? Phần lớn câu trả lời cần phân tích, chẳng hạn tính nhất quán của vân tay hay chấm điểm hành vi. Honeypot bỏ qua phân tích bằng cách đổi câu hỏi thành "client này có chạm vào thứ mà không người nào chạm được không?"
Người thật thấy trang đã hiển thị, còn script spam form hay công cụ cào thường đọc HTML. Nó tìm mọi thẻ <input>, điền dữ liệu có vẻ hợp lý và gửi đi. Nếu trang có một ô nhập vô hình trên màn hình, script vẫn điền, và máy chủ thấy người gửi không xem trang theo cách của con người.
Honeypot trường form
Cái bẫy kinh điển là một ô nhập thừa mà người sáng mắt không bao giờ thấy — bị đẩy ra ngoài màn hình, cho kích thước bằng không hoặc làm trong suốt hoàn toàn — nhưng vẫn nằm trong DOM và, điều then chốt, vẫn được gửi lên cùng với phần còn lại của form. (Một ô có thuộc tính disabled sẽ không được gửi đi chút nào, đó là lý do người ta ẩn cái bẫy chứ không vô hiệu hóa nó.) Quy tắc phía máy chủ rất đơn giản: nếu trường này gửi lên mà không rỗng, hãy từ chối lượt gửi — im lặng hoặc bằng một lỗi chung chung.
Ba chi tiết thiết kế quyết định bẫy có hiệu quả hay không:
type="hidden"là phiên bản yếu nhất. Ô ẩn vốn dành để mang giá trị, và mọi script duyệt form đều biết bỏ qua hoặc gửi lại nguyên vẹn. Cái bẫy phải trông giống một trường đang chờ người dùng nhập.- Tên trường rất quan trọng. Trường tên
email2haywebsitetrông như thứ script nên điền, và cũng như thứ tự động điền nên điền. Một cái tên trung tính, không liên quan ít bị điền nhầm hơn. - Việc kiểm tra phải chạy ở phía máy chủ. Cái bẫy do JavaScript phía trình duyệt xét thì client có thể bỏ qua, mà đúng những script honeypot muốn bắt lại chẳng bao giờ chạy JavaScript của trang.
Ràng buộc về khả năng tiếp cận
Đây là chỗ phần lớn honeypot làm sai. Trình đọc màn hình không đọc điểm ảnh mà duyệt qua DOM. Một trường chỉ bị đẩy ra ngoài màn hình vẫn được đọc lên, vẫn nhận tiêu điểm bằng phím Tab, và có thể nhốt người dùng bàn phím hoặc công nghệ hỗ trợ vào một trường mà họ không hiểu.
Không phải kỹ thuật CSS nào cũng hành xử giống nhau ở đây, và chính chỗ khác biệt đó mới là vấn đề. display: none và visibility: hidden thật sự loại phần tử khỏi cây khả năng tiếp cận và khỏi thứ tự Tab — nhưng đó cũng là thứ đầu tiên một con bot viết khá hơn sẽ kiểm tra trước khi điền. Vì thế người ta quay sang đẩy ra ngoài màn hình, độ mờ bằng không hoặc kích thước bằng không; những cách này giữ cho cái bẫy vẫn "hấp dẫn" với script, đồng thời phơi nó ra hoàn toàn trước công nghệ hỗ trợ.
Nên việc che giấu phải làm hai lần: một lần cho mắt, một lần cho cây khả năng tiếp cận.
- Thuộc tính
inerttrên phần tử bao ngoài khiến cả cây con không thể tương tác, loại khỏi thứ tự Tab và ẩn với công nghệ hỗ trợ. aria-hidden="true"vàtabindex="-1"lo được phần lớn việc đó trên các môi trường cũ không cóinert: công nghệ hỗ trợ bỏ qua phần tử bao ngoài và phím Tab bỏ qua ô nhập, dù script vẫn có thể đưa tiêu điểm vào đó.autocomplete="off"yêu cầu trình duyệt không điền trường. Xem tài liệu MDN về thuộc tínhautocompleteđể biết chính xác ngữ nghĩa, và lưu ý trình duyệt coi nó là gợi ý chứ không phải đảm bảo.
Ghép lại, hình hài của nó đại khái như sau:
<div inert aria-hidden="true" style="position:absolute;left:-9999px">
<label for="contact-ref">Leave this field blank</label>
<input type="text" id="contact-ref" name="contact-ref"
tabindex="-1" autocomplete="off">
</div>
Nhãn hiển thị đó không phải để trang trí. Nó là tuyến phòng thủ cuối cùng cho ai đó vẫn chạm tới trường này bất chấp mọi biện pháp trên — nên nó phải nói rõ cần làm gì ("hãy để trống ô này"), chứ không mô tả rằng đây là cái bẫy.
Giấu khỏi tầm mắt không phải là phép thử. Phép thử là: người dùng bàn phím và trình đọc màn hình có hoàn thành được form mà không hề gặp cái bẫy hay không.
Báo nhầm kinh điển: tự động điền
Nếu bạn bị chặn sau khi gửi một form bình thường, rất có thể vì lý do này. Trình quản lý mật khẩu và tự động điền khớp trường theo tên, nhãn và kiểu, và không quan tâm trường có hiển thị hay không. Cái bẫy tên phone hoặc address2 có thể bị trình duyệt điền ngầm, và máy chủ thấy một lượt gửi "bot" từ người thật.
Điều tương tự xảy ra với tiện ích mở rộng viết lại hoặc chèn giá trị vào form. Không điều nào trong đó là lỗi của người dùng. Các bản triển khai tốt giảm rủi ro bằng tên trường không liên quan và autocomplete="off", đồng thời coi bẫy bị điền chỉ là một tín hiệu trong nhiều tín hiệu chứ không phải lý do cấm tự động.
Bẫy liên kết và đường dẫn
Cùng ý tưởng áp dụng được cho trình thu thập. Website thêm một liên kết vô hình với con người, thường gắn rel="nofollow", trỏ tới URL mà robots.txt của nó cấm. Client nào tải URL đó là đã chứng minh mình bỏ qua robots.txt.
Thiết kế này hay ở chỗ nó không bắt nhầm ai. Các công cụ tìm kiếm bạn muốn giữ lại, như Googlebot và Bingbot, tuân thủ robots.txt, không bao giờ yêu cầu đường dẫn bị cấm nên không bao giờ dính bẫy. Kẻ dính bẫy chính là những client vốn đã không tôn trọng quy tắc của website.
Dù vậy nó cũng không hoàn toàn sạch. Rất nhiều client vô hại không phải máy tìm kiếm — trình thu thập để kiểm toán website, công cụ quét khả năng tiếp cận, công cụ quét bảo mật, bot lưu trữ — đều đi theo mọi liên kết chúng đọc được, và không phải cái nào cũng đọc robots.txt trước. Dính bẫy chỉ chứng minh một client đã phớt lờ quy tắc, chứ không chứng minh nó có ý xấu. Đó là lý do nên giới hạn tốc độ hoặc gắn cờ địa chỉ đó thay vì chặn thẳng tay.
Bẫy thời gian
Biến thể thứ ba không cần phần tử ẩn. Máy chủ phát một dấu thời gian hoặc token có chữ ký khi hiển thị form và kiểm tra khi gửi. Form quay lại sau 300 mili giây thì không phải do người thật đọc. Nhưng token phải được ký hoặc giữ ở phía máy chủ: một dấu thời gian trần nằm trong ô ẩn chỉ là con số mà client có thể sửa lại trước khi gửi về.
Nhưng ngưỡng cố định rất mong manh. Tự động điền có thể hoàn thành form hợp lệ gần như tức thì, người dùng quen biết chính xác cần gõ gì, và bot kiên nhẫn hơn một chút chỉ việc chờ. Thời gian hoạt động tốt nhất như một tín hiệu yếu cộng thêm vào các tín hiệu khác, không bao giờ nên là lý do duy nhất để từ chối.
Vị trí của honeypot trong toàn bộ hệ thống
Honeypot là lớp lọc đầu tiên rẻ tiền. Nó bắt các script sơ đẳng đứng sau phần lớn spam form và cào dữ liệu ngây thơ, trước khi bất kỳ kiểm tra đắt tiền nào chạy. Nó vô dụng trước trình duyệt thật do tự động hóa điều khiển, vì trình duyệt đó hiển thị trang như người thật và script có thể được yêu cầu chỉ tương tác với những gì nhìn thấy.
Đó là lý do nó nằm cùng các lớp còn lại trong hướng dẫn kỹ thuật phát hiện bot: cờ tự động hóa, rò rỉ từ trình duyệt headless, phân tích hành vi và các hệ thống thử thách như trang "Checking your browser" của Cloudflare. Mỗi lớp bắt những gì lớp rẻ hơn bên dưới bỏ sót.
Nếu bạn bị dính bẫy
Người thật bị chặn hầu như luôn vướng tự động điền hoặc một tiện ích mở rộng chứ không phải một lần phát hiện thật. Một số điều nên kiểm tra trên trình duyệt của bạn:
- Thử gửi lại form khi đã tắt trình quản lý mật khẩu và tự động điền, và tự gõ từng trường.
- Tắt các tiện ích chèn hoặc viết lại giá trị form, rồi thử lại trong một hồ sơ sạch.
- Kiểm tra xem website có chặn bạn ở chỗ khác không. Nếu có, nguyên nhân nhiều khả năng nằm ở mạng hoặc hồ sơ trình duyệt chứ không phải một form.
Để xem trình duyệt của bạn để lộ những tín hiệu liên quan đến tự động hóa nào cho website, hãy chạy công cụ kiểm tra bot của chúng tôi. Nó chỉ đọc những gì trình duyệt vốn đã báo cáo, và mọi thứ chạy cục bộ.
Câu hỏi thường gặp
Honeypot trong form web là gì?
Một trường nhập mà người thật không thấy và không điền, nhưng vẫn nằm trong mã đánh dấu của trang. Nếu nó quay lại với một giá trị, người gửi đã đọc HTML thay vì trang được hiển thị, đó là bằng chứng mạnh của tự động hóa.
Honeypot có chặn được mọi bot không?
Không. Nó bắt script đơn giản và công cụ cào dữ liệu. Trình duyệt thật do tự động hóa điều khiển hiển thị trang như người thật và sẽ không chạm vào cái bẫy vô hình trên màn hình, nên honeypot chỉ là một lớp trong nhiều lớp.
Honeypot có thể chặn nhầm người dùng thật không?
Có, chủ yếu do tự động điền và trình quản lý mật khẩu điền vào trường ẩn, và do những cái bẫy làm kém mà công nghệ hỗ trợ chạm tới được. Các bản triển khai cẩn thận dùng inert, tabindex="-1" và autocomplete="off", và coi kết quả là một tín hiệu.
Vì sao trình thu thập của công cụ tìm kiếm không mắc bẫy liên kết?
Vì chúng tuân thủ robots.txt. Liên kết bẫy trỏ tới đường dẫn bị cấm, trình thu thập tuân thủ không bao giờ yêu cầu, và chỉ client phớt lờ quy tắc mới dính.


