การตรวจจับ Headless Browser: Playwright, Puppeteer และอื่น ๆ
เอนจิน Bot Detection ของเราระบุเฟรมเวิร์กอัตโนมัติกว่า 15 ตัว ผ่านความไม่สอดคล้องของสัญญาณ, API ที่หายไป และรูปแบบพฤติกรรมที่บอตปลอมไม่ได้
Headless browser คืออาวุธที่นักโจมตีเลือกใช้สำหรับการทำ web scraping ขั้นสูง, credential stuffing และปฏิบัติการฉ้อโกง ต่างจาก HTTP client ทั่วไป Headless browser รัน JavaScript, เรนเดอร์หน้าเว็บ และรองรับ web API สมัยใหม่ ทำให้ตรวจจับได้ยากกว่ามาก เอนจิน Bot Detection ของเราใช้วิธีตรวจจับที่เป็นอิสระต่อกันหลายวิธีเพื่อระบุเฟรมเวิร์กอัตโนมัติกว่า 15 ตัว โดยมี false positive เกือบเป็นศูนย์
วิวัฒนาการของ Browser Automation
Browser automation ก้าวไกลมาไกลจากสคริปต์ curl ธรรมดา เครื่องมือสมัยใหม่อย่าง Playwright, Puppeteer และ Selenium WebDriver ควบคุมเอนจินเบราว์เซอร์จริง — Chromium, Firefox หรือ WebKit — ในโหมด headless พวกมันรัน JavaScript, ประมวลผล CSS, เรนเดอร์อีลิเมนต์ canvas และจัดการคิวรี WebGL ได้เหมือนกับเบราว์เซอร์แบบมีหน้าจอ (headed) ทุกประการ สิ่งนี้ทำให้มันมองไม่เห็นจากวิธีตรวจจับที่เพียงแค่ตรวจสอบความสามารถในการรัน JavaScript
เครื่องมือรุ่นล่าสุดก้าวไปไกลกว่านั้น โหมด stealth ของ Playwright แพตช์สัญญาณหลายอย่างที่การตรวจจับบอตแบบดั้งเดิมพึ่งพา Puppeteer-extra-plugin-stealth แก้ไขคุณสมบัติของ navigator, override สตริง vendor ของ WebGL และปลอมเหตุการณ์การโต้ตอบของผู้ใช้ มาตรการต้านการตรวจจับเหล่านี้ก่อให้เกิดการแข่งขันแบบหนีตามกันระหว่างผู้ปฏิบัติการบอตกับระบบตรวจจับ
วิธีตรวจจับที่ 1: การวิเคราะห์แฟล็ก WebDriver
คุณสมบัติ navigator.webdriver จะถูกตั้งเป็น true เมื่อเบราว์เซอร์ถูกควบคุมด้วยระบบอัตโนมัติ การตรวจจับในยุคแรกทำได้ง่าย ๆ เพียงตรวจสอบคุณสมบัตินี้ แต่เครื่องมือ stealth สมัยใหม่ลบหรือ override มันทิ้ง การตรวจจับของเราลงลึกกว่า — เราตรวจไม่เพียงค่าของคุณสมบัติ แต่รวมถึง property descriptor ของมัน, การมีอยู่ใน prototype chain และว่ามีความพยายาม redefine มันหรือไม่ เรายังตรวจคุณสมบัติที่เกี่ยวข้อง เช่น ความผิดปกติของความยาว navigator.plugins ที่มักมาพร้อมกับการ override WebDriver
วิธีตรวจจับที่ 2: ร่องรอยจาก Chrome DevTools Protocol
Playwright และ Puppeteer ควบคุมเบราว์เซอร์ผ่าน Chrome DevTools Protocol (CDP) แม้เมื่อโหมด stealth ทำงานอยู่ CDP ก็ยังทิ้งร่องรอยไว้ในรันไทม์: ตัวแปร global เฉพาะ, ฟังก์ชัน getter ที่ถูกดัดแปลง และ property descriptor ที่ถูกเปลี่ยนแปลงบนอ็อบเจกต์ Window และ Navigator เราตรวจหาร่องรอยเหล่านี้ด้วยเทคนิคที่ทนทานต่อการเขียนทับแบบง่าย ๆ
วิธีตรวจจับที่ 3: Headless Browser Fingerprinting
Headless Chrome มีชุดความสามารถที่ต่างจาก Chrome แบบมีหน้าจอ มันขาดปลั๊กอินเบราว์เซอร์บางตัว, มีลักษณะการเรนเดอร์ที่ต่างกันสำหรับคุณสมบัติ CSS บางอย่าง และรายงานค่าที่ต่างกันสำหรับผลลัพธ์ MediaQuery บางรายการ เราดูแลฐานข้อมูลของลักษณะเฉพาะ headless browser ที่รู้จัก และตรวจสอบ fingerprint ที่เข้ามาเทียบกับฐานข้อมูลนี้
ตัวบ่งชี้ headless ที่สำคัญได้แก่: การขาด chrome.runtime (มีใน Chrome แบบมีหน้าจอ แต่ไม่มีในแบบ headless), อาร์เรย์ navigator.plugins ที่มีความยาวเป็นศูนย์, รูปแบบ user agent เฉพาะที่เคยเชื่อมโยงกับโหมด headless ในเวอร์ชันก่อน ๆ และความแตกต่างในวิธีที่ headless Chrome จัดการ security context ของ iframe
วิธีตรวจจับที่ 4: การวิเคราะห์ความยาวของ Eval
เอนจิน JavaScript แต่ละตัวมีการ implement ฟังก์ชัน built-in ต่างกัน และการ implement เหล่านี้มี string representation ที่ต่างกัน โดยการตรวจสอบความยาวของ Function.prototype.toString.call(eval) และเปรียบเทียบกับค่าที่รู้จักของเอนจินเบราว์เซอร์แต่ละตัว เราสามารถตรวจจับการปลอมสภาพแวดล้อมได้ — ตัวอย่างเช่น อินสแตนซ์ headless Chrome ที่แกล้งทำเป็น Firefox
วิธีตรวจจับที่ 5: การตรวจสอบไขว้ด้วย TLS
ดังที่กล่าวไว้ในบทความ TLS fingerprinting ของเรา ข้อความ TLS Client Hello เปิดเผยเบราว์เซอร์หรือไลบรารี HTTP จริงที่ทำการเชื่อมต่อ เมื่อสคริปต์ Playwright ควบคุม Chrome ค่า TLS fingerprint จะตรงกับ Chrome — ซึ่งเป็นสิ่งที่คาดหวังได้ แต่เมื่อบอตแบบกำหนดเองใช้ไลบรารี requests ของ Python หรือ net/http ของ Go ค่า TLS fingerprint จะเปิดโปงการหลอกลวงนั้น ไม่ว่าจะส่ง user agent เป็นสตริงใดก็ตาม
วิธีตรวจจับที่ 6: การวิเคราะห์เวลาและพฤติกรรม
ผู้ใช้จริงแสดงความแปรผันตามธรรมชาติในจังหวะเวลาการโต้ตอบ พวกเขาเลื่อนเมาส์เป็นเส้นโค้ง ไม่ใช่เส้นตรง พวกเขาหยุดก่อนคลิก พวกเขาเลื่อนหน้าจอด้วยความเร็วที่เปลี่ยนแปลง เครื่องมืออัตโนมัติ แม้แต่ตัวที่จำลองพฤติกรรมมนุษย์ ก็สร้างรูปแบบที่แยกแยะได้ทางสถิติ — จังหวะเวลาที่สม่ำเสมอเกินไป, เส้นทางเมาส์ที่เป็นเส้นตรงสมบูรณ์แบบ และความเร็วการเลื่อนที่ไม่เป็นธรรมชาติ
เราเก็บสัญญาณพฤติกรรมขั้นต่ำระหว่างกระบวนการ fingerprinting เอง — จังหวะเวลาของการเรียก API, ลำดับของการเก็บสัญญาณ และการตอบสนองของ API เบราว์เซอร์บางตัว สัญญาณพฤติกรรมระดับจุลภาคเหล่านี้ยากที่เครื่องมืออัตโนมัติจะปลอมได้ เพราะมันขึ้นอยู่กับสภาพแวดล้อมการรันจริง ไม่ใช่คุณสมบัติที่ override ได้
วิธีตรวจจับที่ 7: ความไม่สอดคล้องของ Permission และ API
เบราว์เซอร์จริงมีสถานะ permission และความพร้อมใช้งานของ API ที่สอดคล้องกัน เบราว์เซอร์ที่อ้างว่ารองรับ notification แต่ไม่มี constructor Notification หรือที่รายงานความละเอียดหน้าจอเฉพาะแต่คืนค่าที่ต่างกันจาก window.screen และ CSS media query กำลังแสดงความไม่สอดคล้องที่บ่งชี้ถึงการดัดแปลงหรือการจำลอง
เราตรวจสอบจุดตรวจสอบไขว้เหล่านี้หลายสิบจุด โดยมองหาความขัดแย้งที่เกิดขึ้นเมื่อเครื่องมืออัตโนมัติเลือก override สัญญาณบางตัวโดยไม่รักษาความสอดคล้องข้าม API ที่เกี่ยวข้องทั้งหมด
วิธีตรวจจับที่ 8: การตรวจจับ VM และการจำลอง
ปฏิบัติการบอตจำนวนมากรันอยู่ภายในเครื่องเสมือน (virtual machine) หรืออินสแตนซ์คลาวด์ แม้ว่าสิ่งนี้เพียงอย่างเดียวจะไม่ใช่หลักฐานของระบบอัตโนมัติ แต่มันเป็นสัญญาณที่แข็งแกร่งเมื่อรวมกับตัวบ่งชี้อื่น ๆ ตรงนี้มีสองเรื่องที่ควรแยกให้ชัด เพราะมักถูกนำมาปนกัน
เรื่องแรกคือการเรนเดอร์ด้วยซอฟต์แวร์ เครื่องที่ไม่มี GPU จริงจะถอยไปใช้ software rasterizer และสตริง WebGL renderer ก็บอกออกมาตรง ๆ — "llvmpipe", "SwiftShader" และตัวแปรของมันระบุชื่อไว้โดยตรง นี่คือตัวบ่งชี้ headless: มันบอกถึงเส้นทางการเรนเดอร์ และป้อนเข้าสู่คำตัดสินเรื่องบอตในทุกแพ็กเกจ
เรื่องที่สองคือการตรวจจับเครื่องเสมือนโดยตรง ซึ่งเป็นความสามารถของแพ็กเกจ Enterprise มันอ่านสตริง renderer และ vendor ของ WebGL เพื่อหาลายเซ็นของไฮเปอร์ไวเซอร์ — VMware, VirtualBox, Parallels, QEMU, Hyper-V — แล้วตรวจไขว้กับลักษณะฮาร์ดแวร์ที่ไม่สอดคล้องกับอุปกรณ์ของผู้บริโภค: ความละเอียดหน้าจอที่เป็นค่าเริ่มต้นของ VM, CPU หนึ่งหรือสองคอร์ทั้งที่ User-Agent เป็นเดสก์ท็อป, หน่วยความจำสองกิกะไบต์หรือน้อยกว่า ไม่มีตัวบ่งชี้ใดตัดสินได้เพียงลำพัง ตัวตรวจจับจะให้คะแนนจากการประกอบกันของทั้งหมด และรายงานค่าความเชื่อมั่นพร้อมตัวบ่งชี้ที่ทำงาน ส่วนช่วงที่อยู่ของดาต้าเซ็นเตอร์และผู้ให้บริการโฮสติ้งซึ่งได้จากข้อมูล IP intelligence ก็ช่วยยืนยันจากฝั่งเครือข่าย
สัญญาณทั้งสองอย่างต่างก็ไม่ใช่หลักฐานของระบบอัตโนมัติในตัวเอง — การทดสอบเบราว์เซอร์ที่โฮสต์บนคลาวด์และเดสก์ท็อปเสมือนที่ไม่มี GPU ล้วนเป็นการใช้งานที่ถูกต้อง — จึงเป็นเหตุผลที่ทั้งคู่ป้อนเข้าสู่คำตัดสินแบบถ่วงน้ำหนัก แทนที่จะสั่งบล็อกด้วยตัวมันเอง
ข้อได้เปรียบแบบหลายวิธี
วิธีตรวจจับแต่ละวิธีมีข้อจำกัดในตัวเอง — ผู้ปฏิบัติการบอตที่เชี่ยวชาญอาจหลบเลี่ยงวิธีใดวิธีหนึ่งได้ แต่การหลบเลี่ยงทุกวิธีพร้อมกัน ในขณะที่ยังรักษาความสอดคล้องของการตรวจสอบไขว้ในทุกวิธี มีต้นทุนสูงจนเกินคุ้ม ต้นทุนของการพัฒนาและดูแลบอตที่ผ่านการตรวจสอบทั้งหมดเกินกว่ามูลค่าทางเศรษฐกิจของงานบอตส่วนใหญ่
False Positive เกือบเป็นศูนย์
การตรวจจับของเราทำงานบนโมเดล whitelist สำหรับบอตเสิร์ชเอนจิน (Googlebot, Bingbot ฯลฯ) ที่ยืนยันผ่าน reverse DNS และโมเดลหลายสัญญาณสำหรับทราฟฟิกอื่น ๆ เราต้องการสัญญาณยืนยันหลายตัวก่อนจัดประเภททราฟฟิกว่าเป็นแบบอัตโนมัติ นี่คือหัวใจทั้งหมดของการออกแบบแบบระมัดระวัง: ตัวบ่งชี้กำกวมเพียงตัวเดียวไม่เคยเพียงพอในตัวเอง ผู้เข้าชมทั่วไปที่บังเอิญไปเข้าเงื่อนไขการตรวจสอบข้อใดข้อหนึ่งจึงไม่ถูกจัดประเภทว่าเป็นบอต