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.
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.
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:
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.
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 !+""
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.
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
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:
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:
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!
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.
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.
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 grep
ing , 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.
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:
EXPÉRIENCE 2:
Comme auparavant, j'ouvre un navigateur et la page Web avec Selenium à partir d'une console Python.
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.
Le lien ne s'ouvre pas, mais je suis amené à une page d'inscription.
IMPLICATIONS:
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.
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 ");
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) {}
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>
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.
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))
}
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.