web-dev-qa-db-fra.com

Un site Web peut-il détecter si vous utilisez Selenium avec chromedriver?

J'ai testé Selenium avec Chromedriver et j'ai remarqué que certaines pages peuvent détecter que vous utilisez Selenium même s'il n'y a aucune automatisation. Même lorsque je navigue simplement manuellement en utilisant du chrome via Selenium et Xephyr, une page m'indique souvent qu'une activité suspecte a été détectée. J'ai vérifié mon agent utilisateur et l'empreinte de mon navigateur. Ils sont tous exactement identiques au navigateur Chrome classique.

Lorsque je navigue sur ces sites en chrome normal, tout fonctionne correctement, mais dès que j'utilise Selenium, je suis détecté.

En théorie, chromedriver et chrome devraient être identiques à tous les serveurs Web, mais ils peuvent le détecter. 

Si vous voulez du testcode, essayez ceci:

from pyvirtualdisplay import Display
from Selenium import webdriver

display = Display(visible=1, size=(1600, 902))
display.start()
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--disable-extensions')
chrome_options.add_argument('--profile-directory=Default')
chrome_options.add_argument("--incognito")
chrome_options.add_argument("--disable-plugins-discovery");
chrome_options.add_argument("--start-maximized")
driver = webdriver.Chrome(chrome_options=chrome_options)
driver.delete_all_cookies()
driver.set_window_size(800,800)
driver.set_window_position(0,0)
print 'arguments done'
driver.get('http://stubhub.com')

Si vous naviguez autour du stubhub, vous serez redirigé et bloqué en une ou deux demandes. J'ai enquêté sur cela et je ne vois pas comment ils peuvent dire qu'un utilisateur utilise Selenium. 

Comment font-ils?

EDIT UPDATE:

J'ai installé le plug-in Selenium IDE dans Firefox et j'ai été banni lorsque je suis allé sur stubhub.com dans le navigateur firefox classique avec uniquement le plug-in supplémentaire.

MODIFIER:

Lorsque j'utilise Fiddler pour afficher les demandes HTTP envoyées dans les deux sens, j'ai remarqué que les demandes du "faux navigateur" contenaient souvent "pas de cache" dans l'en-tête de la réponse.

MODIFIER:

résultats comme ceci Y a-t-il un moyen de détecter que je suis dans une page Web de Selenium Webdriver à partir de Javascript suggère qu'il ne devrait pas y avoir de moyen de détecter lorsque vous utilisez un pilote Web Mais cette preuve suggère le contraire.

MODIFIER:

Le site télécharge une empreinte digitale sur leurs serveurs, mais j'ai vérifié et l'empreinte digitale de Selenium est identique à l'empreinte digitale lors de l'utilisation de chrome.

MODIFIER:

C'est l'une des données utiles des empreintes digitales qu'ils envoient à leurs serveurs.

{"appName":"Netscape","platform":"Linuxx86_64","cookies":1,"syslang":"en-US","userlang":"en-US","cpu":"","productSub":"20030107","setTimeout":1,"setInterval":1,"plugins":{"0":"ChromePDFViewer","1":"ShockwaveFlash","2":"WidevineContentDecryptionModule","3":"NativeClient","4":"ChromePDFViewer"},"mimeTypes":{"0":"application/pdf","1":"ShockwaveFlashapplication/x-shockwave-flash","2":"FutureSplashPlayerapplication/futuresplash","3":"WidevineContentDecryptionModuleapplication/x-ppapi-widevine-cdm","4":"NativeClientExecutableapplication/x-nacl","5":"PortableNativeClientExecutableapplication/x-pnacl","6":"PortableDocumentFormatapplication/x-google-chrome-pdf"},"screen":{"width":1600,"height":900,"colorDepth":24},"fonts":{"0":"monospace","1":"DejaVuSerif","2":"Georgia","3":"DejaVuSans","4":"TrebuchetMS","5":"Verdana","6":"AndaleMono","7":"DejaVuSansMono","8":"LiberationMono","9":"NimbusMonoL","10":"CourierNew","11":"Courier"}}

Son identique en sélénium et en chrome

MODIFIER:

Les VPN fonctionnent pour un usage unique mais sont détectés une fois la première page chargée. Clairement, du javascript est en cours d’exécution pour détecter Selenium.

220
Ryan Weinstein

Fondamentalement, la détection Selenium fonctionne comme suit: elle teste les variables javascript prédéfinies qui apparaissent lors de l’exécution de Selenium. Les scripts de détection de bot recherchent généralement tout ce qui contient Word "Selenium"/"webdriver" dans l’une des variables (sur l’objet window), ainsi que les variables de document appelées $cdc_ et $wdc_. Bien sûr, tout dépend du navigateur sur lequel vous êtes. Tous les différents navigateurs exposent des choses différentes.

Pour moi, j’utilisais chrome, donc, tout ce que je devais faire, c’était pour s’assurer que $cdc_ n’existait plus en tant que variable de document et recompilez $cdc_ sous un nom différent.)

c'est la fonction que j'ai modifiée dans chromedriver:

call_function.js:

function getPageCache(opt_doc) {
  var doc = opt_doc || document;
  //var key = '$cdc_asdjflasutopfhvcZLmcfl_';
  var key = 'randomblabla_';
  if (!(key in doc))
    doc[key] = new Cache();
  return doc[key];
}

(remarquez le commentaire, tout ce que j'ai fait, j'ai transformé $cdc_ en randomblabla_.

Voici un pseudo-code qui illustre certaines des techniques que les réseaux de robots peuvent utiliser:

runBotDetection = function () {
    var documentDetectionKeys = [
        "__webdriver_evaluate",
        "__Selenium_evaluate",
        "__webdriver_script_function",
        "__webdriver_script_func",
        "__webdriver_script_fn",
        "__fxdriver_evaluate",
        "__driver_unwrapped",
        "__webdriver_unwrapped",
        "__driver_evaluate",
        "__Selenium_unwrapped",
        "__fxdriver_unwrapped",
    ];

    var windowDetectionKeys = [
        "_phantom",
        "__nightmare",
        "_Selenium",
        "callPhantom",
        "callSelenium",
        "_Selenium_IDE_Recorder",
    ];

    for (const windowDetectionKey in windowDetectionKeys) {
        const windowDetectionKeyValue = windowDetectionKeys[windowDetectionKey];
        if (window[windowDetectionKeyValue]) {
            return true;
        }
    };
    for (const documentDetectionKey in documentDetectionKeys) {
        const documentDetectionKeyValue = documentDetectionKeys[documentDetectionKey];
        if (window['document'][documentDetectionKeyValue]) {
            return true;
        }
    };

    for (const documentKey in window['document']) {
        if (documentKey.match(/\$[a-z]dc_/) && window['document'][documentKey]['cache_']) {
            return true;
        }
    }

    if (window['external'] && window['external'].toString() && (window['external'].toString()['indexOf']('Sequentum') != -1)) return true;

    if (window['document']['documentElement']['getAttribute']('Selenium')) return true;
    if (window['document']['documentElement']['getAttribute']('webdriver')) return true;
    if (window['document']['documentElement']['getAttribute']('driver')) return true;

    return false;
};

selon l'utilisateur @szx, il est également possible d'ouvrir simplement chromedriver.exe dans un éditeur hexadécimal et d'effectuer le remplacement manuellement, sans aucune compilation. 

107
Erti-Chris Eelmaa

Comme nous l'avons déjà indiqué dans la question et les réponses affichées, il existe un service anti-Web-scraping et un service de détection de robots appelé "Distil Networks" . Et, selon le interview du PDG de la société:

Même s'ils peuvent créer de nouveaux robots, nous avons trouvé un moyen d'identifier Selenium est l'outil qu'ils utilisent, nous bloquons donc Selenium no Peu importe le nombre d'itérations effectuées sur ce bot. Nous le faisons maintenant avec Python et beaucoup de technologies différentes. Une fois que nous voyons un motif émerger d'un type de bot, puis nous travaillons à l'ingénierie inverse du technologie qu’ils utilisent et l’identifient comme malveillante.

Il faudra du temps et des défis supplémentaires pour comprendre comment ils détectent exactement le sélénium, mais que pouvons-nous dire avec certitude pour le moment:

  • ce n'est pas lié aux actions que vous effectuez avec Selenium - une fois que vous accédez au site, vous êtes immédiatement détecté et banni. J'ai essayé d'ajouter des délais artificiels aléatoires entre les actions, prenez une pause après le chargement de la page - rien n'a aidé
  • il ne s'agit pas non plus d'empreintes digitales de navigateur - essayé dans plusieurs navigateurs avec des profils clairs et non, modes incognito - rien n'a aidé
  • puisque, selon le conseil de l'interview, il s'agissait d'une "ingénierie inverse", je suppose que cela est fait avec du code JS exécuté dans le navigateur, révélant qu'il s'agit d'un navigateur automatisé via Selenium Webdriver

Décidé de poster comme une réponse, puisque clairement:

Un site Web peut-il détecter si vous utilisez Selenium avec chromedriver?

Oui.


De plus, ce que je n’ai pas expérimenté, c’est l’ancien Selenium et les anciennes versions de navigateur - en théorie, quelque chose pourrait être implémenté/ajouté à Selenium à un moment donné sur lequel le détecteur de bot Distil Networks repose actuellement. Ensuite, si tel est le cas, nous pourrions détecter (ouais, détectons le détecteur) à quel moment/version un changement pertinent a été effectué, examiner le journal des modifications et les ensembles de modifications et, éventuellement, cela pourrait nous donner plus d'informations sur l'endroit où regarder. et qu'est-ce qu'ils utilisent pour détecter un navigateur Webdriver. C'est juste une théorie qui doit être testée.

71
alecxe

Exemple de mise en œuvre sur wellsfargo.com: 

try {
 if (window.document.documentElement.getAttribute("webdriver")) return !+[]
} catch (IDLMrxxel) {}
try {
 if ("_Selenium_IDE_Recorder" in window) return !+""
} catch (KknKsUayS) {}
try {
 if ("__webdriver_script_fn" in document) return !+""
18
aianitro

partial interface Navigator { readonly attribute boolean webdriver; };

L'attribut IDL webdriver de l'interface Navigator doit renvoyer la valeur de l'indicateur webdriver-active, qui est initialement faux.

Cette propriété permet aux sites Web de déterminer que l'agent utilisateur est sous le contrôle de WebDriver et peut être utilisée pour atténuer les attaques par déni de service.

Tiré directement du Projet pilote WebDriver 2017 du rédacteur en chef du W3C . Cela implique fortement que, à tout le moins, les itérations futures des pilotes de Selenium seront identifiables pour éviter les utilisations abusives. En fin de compte, il est difficile de dire sans le code source ce qui rend exactement détectable le pilote chrome en particulier. 

9
bryce

Essayez d’utiliser Selenium avec un profil utilisateur spécifique de chrome. Vous pourrez ainsi l’utiliser en tant qu’utilisateur spécifique et définir tout ce que vous voulez. Lorsqu’il le fera, il fonctionnera comme un «vrai» utilisateur. Regardez le processus chrome avec un processus Explorer vous verrez la différence avec les balises.

Par exemple:

username = os.getenv("USERNAME")
userProfile = "C:\\Users\\" + username + "\\AppData\\Local\\Google\\Chrome\\User Data\\Default"
options = webdriver.ChromeOptions()
options.add_argument("user-data-dir={}".format(userProfile))
# add here any tag you want.
options.add_experimental_option("excludeSwitches", ["ignore-certificate-errors", "safebrowsing-disable-download-protection", "safebrowsing-disable-auto-update", "disable-client-side-phishing-detection"])
chromedriver = "C:\Python27\chromedriver\chromedriver.exe"
os.environ["webdriver.chrome.driver"] = chromedriver
browser = webdriver.Chrome(executable_path=chromedriver, chrome_options=options)

liste de balises chrome ici

9
Kobi K

Obscurcissement du résultat JavaScripts

J'ai vérifié le code source de chromedriver. Cela injecte des fichiers javascript dans le navigateur. 
Chaque fichier javascript de ce lien est injecté dans les pages Web:https://chromium.googlesource.com/chromium/src/+/master/chrome/test/chromedriver/js/

J'ai donc utilisé le reverse engineering et obfuscated les fichiers js en édition Hex. Maintenant, j'étais sûr qu'il n'y avait plus de variables javascript, de noms de fonctions et de chaînes fixes utilisées pour découvrir l'activité de Selenium. Mais encore, certains sites et reCaptcha détectent Selenium! 
Peut-être qu’ils vérifient les modifications causées par l’exécution de chromedriver js :) 


Edit 1:

Modification des paramètres du navigateur Chrome

J'ai découvert qu'il y a quelques paramètres dans 'navigateur' qui découvrent brièvement l'utilisation de chromedriver. Ce sont les paramètres:

  • "navigator.webdriver" En mode non automatisé, il est 'non défini'. En mode automatisé, c'est "vrai".
  • "navigator.plugins" Le chrome sans tête a une longueur de 0. J'ai donc ajouté de faux éléments pour tromper le processus de vérification de la longueur d'un plugin.
  • "navigator.languages" a été défini sur la valeur chromée par défaut '["en-US", "en", "es"] ".

Donc, ce dont j'avais besoin était une extension chrome pour exécuter JavaScript sur les pages Web. J'ai fait une extension avec le code js fourni dans l'article et utilisé un autre article pour ajouter l'extension compressée à mon projet. J'ai réussi à changer les valeurs; Mais toujours rien n'a changé!

Je n'ai pas trouvé d'autres variables comme celles-ci mais cela ne veut pas dire qu'elles n'existent pas. Encore reCaptcha détecte chromedriver, donc il devrait y avoir plus de variables à changer. La prochaine étape devrait être une ingénierie inverse des services de détection que je ne souhaite pas faire.

Maintenant Je ne suis pas sûr que cela vaille la peine de passer plus de temps sur ce processus d'automatisation ou de rechercher des méthodes alternatives!

7
ShayanKM

Même si vous envoyez toutes les données appropriées (par exemple, Selenium ne se présente pas comme une extension, vous avez une résolution raisonnable/une résolution en profondeur, etc.), il existe un certain nombre de services et d'outils qui profilent le comportement des visiteurs acteur est un utilisateur ou un système automatisé.

Par exemple, visiter un site puis exécuter immédiatement une action en déplaçant la souris directement sur le bouton approprié, en moins d'une seconde, est quelque chose qu'aucun utilisateur ne ferait réellement.

Il peut également être utile, en tant qu’outil de débogage, d’utiliser un site tel que https://panopticlick.eff.org/ pour vérifier l’originalité de votre navigateur. cela vous aidera également à vérifier s'il existe des paramètres spécifiques indiquant que vous exécutez Selenium. 

5
lfaraone

On dirait qu'ils sont derrière un pare-feu d'application Web. Examinez modsecurity et owasp pour voir comment cela fonctionne. En réalité, vous vous demandez comment éviter la détection par bot. Ce n’est pas le but du pilote Web Selenium. C'est pour tester votre application Web et ne pas toucher d'autres applications Web. C'est possible, mais en gros, vous devriez regarder ce qu'un WAF recherche dans son jeu de règles et l'éviter spécifiquement avec Selenium si vous le pouvez. Même dans ce cas, cela pourrait ne pas fonctionner car vous ne savez pas quel WAF ils utilisent. Vous avez fait le bon premier pas, c'est-à-dire simuler l'agent utilisateur. Si cela ne fonctionne pas bien, alors un WAF est en place et vous aurez probablement besoin d'être plus délicat.

Modifier: Point tiré d'une autre réponse. Assurez-vous que votre agent utilisateur est correctement défini en premier. Peut-être qu’il frappe un serveur Web local ou qu’il détecte le trafic sortant.

5
Bassel Samman

On dit que Firefox définit window.navigator.webdriver === true si vous travaillez avec un WebDriver. C'était selon l'une des spécifications les plus anciennes (par exemple: archive.org ), mais je ne pouvais pas le trouver dans le nouveau , à l'exception d'une formulation très vague dans les annexes.

Un test pour cela se trouve dans le code Selenium dans le fichier fingerprint_test.js où le commentaire à la fin dit "Actuellement uniquement implémenté dans firefox" mais je n’ai pu identifier aucun code dans cette direction avec une simple greping , ni dans l’architecture actuelle de Firefox (41.0.2) ni dans l’arborescence Chrome.

J'ai également trouvé un commentaire pour un ancien commit concernant les empreintes digitales dans le pilote firefox b82512999938 de janvier 2015 . Ce code est toujours dans le Selenium GIT-master téléchargé hier à javascript/firefox-driver/extension/content/server.js avec un commentaire lié à l’annexe légèrement différente de la spécification actuelle de w3c webdriver.

5
deamentiaemundi

La détection de bot que j'ai vue semble plus sophistiquée ou du moins différente de ce que j'ai lu dans les réponses ci-dessous.

EXPÉRIENCE 1:

  1. J'ouvre un navigateur et une page Web avec Selenium à partir d'une console Python. 
  2. La souris est déjà à un endroit précis où je sais qu'un lien apparaîtra une fois la page chargée. Je ne déplace jamais la souris.  
  3. J'appuie une fois sur le bouton gauche de la souris (il est nécessaire de se concentrer sur la console où Python est exécuté sur le navigateur). 
  4. J'appuie de nouveau sur le bouton gauche de la souris (rappelez-vous, le curseur est au-dessus d'un lien donné).
  5. Le lien s'ouvre normalement, comme il se doit.

EXPÉRIENCE 2:

  1. Comme auparavant, j'ouvre un navigateur et la page Web avec Selenium à partir d'une console Python. 

  2. Cette fois-ci, au lieu de cliquer avec la souris, j'utilise Selenium (dans la console Python) pour cliquer sur le même élément avec un décalage aléatoire. 

  3. Le lien ne s'ouvre pas, mais je suis amené à une page d'inscription.

IMPLICATIONS:

  • ouvrir un navigateur web via Selenium ne m'empêche pas de paraître humain
  • déplacer la souris comme un humain n'est pas nécessaire pour être classé comme humain
  • cliquer sur quelque chose via Selenium avec un décalage déclenche encore l'alarme

Cela semble mystérieux, mais je suppose qu'ils peuvent simplement déterminer si une action provient de Selenium ou non, alors qu'ils se moquent de savoir si le navigateur a été ouvert via Selenium ou non. Ou peuvent-ils déterminer si la fenêtre a le focus? Il serait intéressant d'entendre si quelqu'un a des idées.

4
M3RS

Une autre chose que j’ai trouvée est que certains sites Web utilisent une plate-forme qui vérifie l’agent d’utilisateur. Si la valeur contient: "HeadlessChrome", le comportement peut être étrange lorsque vous utilisez le mode sans tête.

La solution consiste à remplacer la valeur de l'agent utilisateur, par exemple en Java: chromeOptions.addArguments ("- user-agent = Mozilla/5.0 (Macintosh; Intel; Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, comme Gecko) Chrome/73.0.3683.86 Safari/537.36 ");

2
Adi Ohana

Certains sites détectent ceci:

function d() {
try {
    if (window.document.$cdc_asdjflasutopfhvcZLmcfl_.cache_)
        return !0
} catch (e) {}

try {
    //if (window.document.documentElement.getAttribute(decodeURIComponent("%77%65%62%64%72%69%76%65%72")))
    if (window.document.documentElement.getAttribute("webdriver"))
        return !0
} catch (e) {}

try {
    //if (decodeURIComponent("%5F%53%65%6C%65%6E%69%75%6D%5F%49%44%45%5F%52%65%63%6F%72%64%65%72") in window)
    if ("_Selenium_IDE_Recorder" in window)
        return !0
} catch (e) {}

try {
    //if (decodeURIComponent("%5F%5F%77%65%62%64%72%69%76%65%72%5F%73%63%72%69%70%74%5F%66%6E") in document)
    if ("__webdriver_script_fn" in document)
        return !0
} catch (e) {}
2
Néstor Lim

Ecrivez une page HTML avec le code suivant. Vous verrez que dans le DOM, Selenium applique un attribut webdriver dans le outerHTML.

<html>
<head>
  <script type="text/javascript">
  <!--
    function showWindow(){
      javascript:(alert(document.documentElement.outerHTML));
    }
  //-->
  </script>
</head>
<body>
  <form>
    <input type="button" value="Show outerHTML" onclick="showWindow()">
  </form>
</body>
</html>

2
PC3TJ

Il me semble que le moyen le plus simple de procéder avec Selenium consiste à intercepter le XHR qui renvoie l’empreinte du navigateur.

Mais puisqu'il s'agit d'un problème uniquement lié au sélénium, il est préférable d'utiliser autre chose. Le sélénium est censé rendre les choses comme cela plus faciles, pas plus difficiles.

1
pguardiario

En plus de l'excellente réponse de @ Erti-Chris Eelmaa - il y a un window.navigator.webdriver ennuyeux et il est en lecture seule. Si vous modifiez sa valeur en false, l'événement aura toujours true. C'est pourquoi le navigateur piloté par un logiciel automatisé peut toujours être détecté . MDN

La variable est gérée par le drapeau --enable-automation en chrome. Le chromedriver lance chrome avec cet indicateur et définit chrome window.navigator.webdriver à true. Vous pouvez le trouver ici . Vous devez ajouter le drapeau à "exclure les commutateurs". Par exemple (golang):

package main

import (
    "github.com/tebeka/Selenium"
    "github.com/tebeka/Selenium/chrome"
)

func main() {

caps := Selenium.Capabilities{
    "browserName": "chrome",
}

chromeCaps := chrome.Capabilities{
    Path:            "/path/to/chrome-binary",
    ExcludeSwitches: []string{"enable-automation"},
}
caps.AddChrome(chromeCaps)

wd, err := Selenium.NewRemote(caps, fmt.Sprintf("http://localhost:%d/wd/hub", 4444))
}
0
FDG

J'ai trouvé changer la variable javascript "key" comme ceci:

//Fools the website into believing a human is navigating it
        ((JavascriptExecutor)driver).executeScript("window.key = \"blahblah\";");

fonctionne pour certains sites Web lorsque Selenium Webdriver est utilisé avec Google Chrome, car de nombreux sites vérifient cette variable afin d’éviter leur élimination par Selenium.

0
Juliagu