كشف المتصفحات الخفية (Headless): Playwright وPuppeteer وما بعدها
محرك كشف البوتات لدينا يتعرّف على أكثر من 15 إطار أتمتة عبر تناقضات الإشارات وغياب واجهات API وأنماط سلوكية يعجز البوت عن تزييفها.
المتصفحات الخفية (Headless) هي السلاح المفضّل لعمليات كشط الويب المتطورة، وحشو بيانات الاعتماد (credential stuffing)، وعمليات الاحتيال. وخلافًا لعملاء HTTP البسطاء، تنفّذ المتصفحات الخفية JavaScript، وتعرض الصفحات، وتدعم واجهات الويب الحديثة — ما يجعل كشفها أصعب بكثير. يستخدم محرك كشف البوتات لدينا عدة طرق كشف مستقلة للتعرّف على أكثر من 15 إطار أتمتة بمعدل إيجابيات خاطئة يقارب الصفر.
تطوّر أتمتة المتصفحات
قطعت أتمتة المتصفحات شوطًا طويلاً منذ نصوص curl البسيطة. فالأدوات الحديثة مثل Playwright وPuppeteer وSelenium WebDriver تتحكم في محركات متصفح حقيقية — Chromium أو Firefox أو WebKit — في الوضع الخفي. وهي تنفّذ JavaScript، وتعالج CSS، وتعرض عناصر canvas، وتتعامل مع استعلامات WebGL تمامًا كما تفعل المتصفحات ذات الواجهة الظاهرة. وهذا يجعلها غير مرئية لطرق الكشف التي تكتفي بالتحقق من القدرة على تنفيذ JavaScript.
وقد ذهب الجيل الأحدث من الأدوات إلى أبعد من ذلك. فوضع التخفّي (stealth) في Playwright يرقّع كثيرًا من الإشارات التي يعتمد عليها كشف البوتات التقليدي. كما يعدّل puppeteer-extra-plugin-stealth خصائص navigator، ويتجاوز سلاسل مورّد WebGL، ويزيّف أحداث تفاعل المستخدم. وقد خلقت هذه الإجراءات المضادة للكشف سباق تسلّح بين مشغّلي البوتات وأنظمة الكشف.
طريقة الكشف 1: تحليل راية WebDriver
تُضبط الخاصية navigator.webdriver على القيمة true حين يكون المتصفح متحكَّمًا فيه عبر الأتمتة. وكان الكشف المبكر بسيطًا كالتحقق من هذه الخاصية. لكن أدوات التخفّي الحديثة تحذفها أو تتجاوزها. أما كشفنا فيتعمّق أكثر — إذ لا نتحقق من قيمة الخاصية فحسب، بل من واصف الخاصية (property descriptor)، ووجودها في سلسلة النماذج الأولية (prototype chain)، وما إذا كانت هناك محاولات لإعادة تعريفها. كما نتحقق من خصائص مرتبطة مثل الشذوذ في طول navigator.plugins الذي يرافق تجاوزات WebDriver.
طريقة الكشف 2: آثار بروتوكول Chrome DevTools
يتحكم Playwright وPuppeteer في المتصفحات عبر بروتوكول Chrome DevTools (CDP). وحتى حين يكون وضع التخفّي فعّالًا، يترك CDP آثارًا في بيئة التشغيل: متغيرات عامة محددة، ودوال getter معدّلة، وواصفات خصائص مغيَّرة على كائنَي Window وNavigator. ونحن نتحرّى عن هذه الآثار بتقنيات صامدة أمام عمليات الكتابة فوقها البسيطة.
طريقة الكشف 3: بصمة المتصفح الخفي
يملك Chrome الخفي مجموعة قدرات مختلفة عن Chrome ذي الواجهة الظاهرة. فهو يفتقر إلى إضافات متصفح معيّنة، وله خصائص عرض مختلفة لبعض خصائص CSS، ويبلّغ عن قيم مختلفة لبعض نتائج MediaQuery. ونحن نحتفظ بقاعدة بيانات لخصائص المتصفحات الخفية المعروفة، ونقارن البصمات الواردة بها.
من أبرز مؤشرات الوضع الخفي: غياب chrome.runtime (موجود في Chrome ذي الواجهة الظاهرة لكنه غائب في الخفي)، ومصفوفة navigator.plugins ذات الطول صفر، وأنماط user agent محددة ارتبطت بالوضع الخفي في إصدارات سابقة، والاختلافات في طريقة تعامل Chrome الخفي مع سياقات أمان iframe.
طريقة الكشف 4: تحليل طول eval
تختلف محركات JavaScript في تنفيذها للدوال المدمجة، ولهذه التنفيذات تمثيلات نصية مختلفة. وبالتحقق من طول Function.prototype.toString.call(eval) ومقارنته بالقيم المعروفة لكل محرك متصفح، يمكننا كشف انتحال البيئة — على سبيل المثال، نسخة Chrome خفية تتظاهر بأنها Firefox.
طريقة الكشف 5: التحقق المتقاطع لـ TLS
كما ناقشنا في مقالنا عن بصمة TLS، تكشف رسالة TLS Client Hello عن المتصفح أو مكتبة HTTP الفعلية التي تُجري الاتصال. فحين يتحكم نص Playwright في Chrome، تطابق بصمة TLS متصفح Chrome — وهذا متوقّع. لكن حين يستخدم بوت مخصص مكتبة requests في Python أو net/http في Go، تكشف بصمة TLS الخداع بغض النظر عن سلسلة user agent المرسَلة.
طريقة الكشف 6: تحليل التوقيت والسلوك
يُظهر المستخدمون الحقيقيون تباينًا طبيعيًا في توقيت تفاعلاتهم. فهم يحرّكون المؤشر في منحنيات لا في خطوط مستقيمة. ويتوقفون قليلًا قبل النقر. ويمرّرون الصفحة بسرعات متغيرة. أما الأدوات الآلية، حتى تلك التي تحاكي السلوك البشري، فتنتج أنماطًا قابلة للتمييز إحصائيًا — توقيت مفرط الاتساق، ومسارات مؤشر خطية تمامًا، وسرعات تمرير غير طبيعية.
ونحن نجمع إشارات سلوكية طفيفة أثناء عملية أخذ البصمة نفسها — توقيت استدعاءات API، وترتيب جمع الإشارات، ومدى استجابة بعض واجهات المتصفح. ويصعب على أدوات الأتمتة تزييف هذه الإشارات السلوكية الدقيقة لأنها تعتمد على بيئة التنفيذ الفعلية، لا على خصائص قابلة للتجاوز.
طريقة الكشف 7: تناقض الأذونات وواجهات API
للمتصفحات الحقيقية حالات أذونات وتوافر واجهات API متسقة. فالمتصفح الذي يزعم دعم الإشعارات دون امتلاك باني Notification، أو الذي يبلّغ عن دقة شاشة محددة لكنه يعيد قيمًا مختلفة من window.screen واستعلامات CSS media، يُظهر تناقضات تدل على التلاعب أو المحاكاة.
ونحن نتحقق من عشرات نقاط التحقق المتقاطع هذه، بحثًا عن التناقضات التي تنشأ حين تتجاوز أدوات الأتمتة بعض الإشارات انتقائيًا دون الحفاظ على الاتساق عبر جميع واجهات API المرتبطة.
طريقة الكشف 8: كشف الأجهزة الافتراضية والمحاكاة
تعمل كثير من عمليات البوتات داخل أجهزة افتراضية أو نسخ سحابية. ورغم أن هذا وحده ليس دليلًا على الأتمتة، فإنه إشارة قوية حين يقترن بمؤشرات أخرى. ونحن نكشف الأجهزة الافتراضية عبر سلاسل مصيّر WebGL التي تحتوي على كلمات مفتاحية مرتبطة بالأجهزة الافتراضية (مثل "llvmpipe" أو "SwiftShader")، وخصائص العتاد غير المتسقة مع أجهزة المستهلكين (نواتا معالجة اثنتان بالضبط وذاكرة 2 غيغابايت — وهي إعدادات افتراضية شائعة للأجهزة الافتراضية)، ونطاقات IP معروفة لمزوّدي الخدمات السحابية.
ميزة تعدد الطرق
لكل طريقة كشف على حدة قيودها — فقد يتجاوز مشغّل بوتات متطور أي طريقة منفردة. لكن تجاوز جميع الطرق في آنٍ واحد، مع الحفاظ على اتساق التحقق المتقاطع عبرها كلها، مكلّف على نحو باهظ. فتكلفة تطوير بوت يجتاز كل الفحوص وصيانته تفوق القيمة الاقتصادية لمعظم عمليات البوتات.
إيجابيات خاطئة تقارب الصفر
يعمل كشفنا وفق نموذج قائمة بيضاء لبوتات محركات البحث (Googlebot وBingbot وغيرها) يُتحقّق منها عبر عكس DNS، ونموذج متعدد الإشارات لبقية الحركة. ونشترط عدة إشارات متآزرة قبل تصنيف الحركة على أنها آلية. ويضمن هذا النهج المتحفظ معدل إيجابيات خاطئة دون 0.1% — تم التحقق منه عبر مليارات الأحداث في بيئة الإنتاج.