¿Puede un sitio web detectar cuándo está usando selenium con chromedriver?

He estado probando Selenium con Chromedriver y noté que algunas páginas pueden detectar que estás usando Selenium aunque no haya automatización en absoluto. Incluso cuando solo estoy navegando manualmente, solo uso Chrome a través de Selenium y Xephyr a menudo aparece una página que dice que se detectó una actividad sospechosa. He comprobado mi agente de usuario y la huella digital de mi navegador, y todos son exactamente idénticos al navegador Chrome normal.

Cuando navego a estos sitios en chrome normal, todo funciona bien, pero en el momento en que uso Selenium, me detectan.

En teoría, chromedriver y chrome deben ser, literalmente, exactamente iguales a cualquier servidor web, pero de alguna manera pueden detectarlo.

Si quieres algo de testcode prueba esto:

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 navegas por el stubhub, serás redirigido y ‘bloqueado’ dentro de una o dos solicitudes. He estado investigando esto y no puedo entender cómo pueden saber si un usuario está usando Selenium.

¿Cómo lo hicieron?

EDITAR ACTUALIZACIÓN:

Instalé el complemento Selenium IDE en Firefox y me prohibieron ingresar a stubhub.com en el navegador Firefox normal solo con el complemento adicional.

EDITAR:

Cuando uso Fiddler para ver las solicitudes HTTP que se envían de un lado a otro, me he dado cuenta de que las solicitudes del “navegador falso” a menudo tienen “no caché” en el encabezado de la respuesta.

EDITAR:

resultados como este: hay una manera de detectar que estoy en una página de Selenium Webdriver desde Javascript sugiere que no debería haber ninguna forma de detectar cuándo está usando un webdriver. Pero esta evidencia sugiere lo contrario.

EDITAR:

El sitio carga una huella digital en sus servidores, pero lo comprobé y la huella digital de selenium es idéntica a la huella digital cuando se usa Chrome.

EDITAR:

Esta es una de las cargas útiles de huellas dactilares que envían a sus servidores.

 {"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"}} 

Es idéntico en selenium y en cromo.

EDITAR:

Las VPN funcionan para un solo uso, pero se detectan después de cargar la primera página. Claramente, se está ejecutando algún javascript para detectar Selenium.

Related of "¿Puede un sitio web detectar cuándo está usando selenium con chromedriver?"

Para usuarios de Mac

Reemplazando la variable cdc_ usando Vim o Perl

Puedes usar vim , o como @Vic Seedoubleyew ha señalado en la respuesta por @ Erti-Chris Eelmaa, perl , para reemplazar la variable chromedriver en chromedriver ( consulta la publicación por @ Erti-Chris Eelmaa para obtener más información sobre esa variable ). El uso de vim o perl impide tener que volver a comstackr el código fuente o usar un editor hexadecimal. Asegúrese de hacer una copia del chromedriver original antes de intentar editarlo. Además, los métodos a continuación fueron probados en la chromedriver version 2.41.578706 .


Usando Vim

 vim /path/to/chromedriver 

Después de ejecutar la línea de arriba, probablemente verá un montón de galimatías. Haz lo siguiente:

  1. Busque cdc_ escribiendo /cdc_ y presionando return .
  2. Habilite la edición presionando a .
  3. Elimine cualquier cantidad de $cdc_lasutopfhvcZLmcfl y reemplace lo que se eliminó con una cantidad igual de caracteres. Si no lo haces, el chromedriver fallará.
  4. Cuando hayas terminado de editar, pulsa esc .
  5. Para guardar los cambios y salir, escriba :wq! y pulse return .
  6. Si no desea guardar los cambios, pero desea salir, escriba :q! y pulse return .
  7. Estas hecho

Ir al chromedriver alterado y haga doble clic en él. Se abrirá terminal ventana de terminal . Si no ve killed en la salida, ha modificado correctamente el controlador.


Usando Perl

La siguiente línea reemplaza cdc_ con dog_ :

 perl -pi -e 's/cdc_/dog_/g' /path/to/chromedriver 

Asegúrese de que la cadena de reemplazo tenga el mismo número de caracteres que la cadena de búsqueda, de lo contrario el chromedriver fallará.

Explicación de Perl

s///g denota que desea buscar una cadena y reemplazarla globalmente con otra cadena (reemplaza todas las ocurrencias).

por ejemplo, s/string/replacment/g

Asi que,

s/// denota la búsqueda y reemplazo de una cadena.

cdc_ es la cadena de búsqueda.

dog_ es la cadena de reemplazo.

g es la clave global, que reemplaza cada aparición de la cadena.

Cómo comprobar si el reemplazo de Perl funcionó.

La siguiente línea imprimirá cada aparición de la cadena de búsqueda cdc_ :

perl -ne 'while(/cdc_/g){print "$&\n";}' /path/to/chromedriver

Si esto no devuelve nada, entonces cdc_ ha sido reemplazado.

A la inversa, puedes usar esto:

perl -ne 'while(/dog_/g){print "$&\n";}' /path/to/chromedriver

para ver si su cadena de reemplazo, dog_ , está ahora en el binario chromedriver . Si es así, la cadena de reemplazo se imprimirá en la consola.

Ir al chromedriver alterado y haga doble clic en él. Se abrirá terminal ventana de terminal . Si no ve killed en la salida, ha modificado correctamente el controlador.


Terminando

Después de modificar el binario chromedriver , asegúrese de que el nombre del binario chromedriver alterado sea chromedriver , y que el binario original se mueva de su ubicación original o se le chromedriver nombre.


Mi experiencia con este método

Anteriormente me detectaron en un sitio web al intentar iniciar sesión, pero después de reemplazar cdc_ con una cadena de igual tamaño, pude iniciar sesión. Como han dicho otros, si ya te detectaron, puedes bloquearte. una plétora de otras razones incluso después de usar este método. Por lo tanto, es posible que tenga que intentar acceder al sitio que lo detectó usando una VPN, una red diferente o lo que sea.

Básicamente, la forma en que funciona la detección de selenium es que prueban las variables de javascript predefinidas que aparecen cuando se ejecutan con selenium. Las secuencias de comandos de detección de bots suelen tener cualquier aspecto que contenga la palabra “selenium” / “webdriver” en cualquiera de las variables (en el objeto de la ventana) y también documentan variables llamadas $cdc_ y $wdc_ . Por supuesto, todo esto depende del navegador en el que estés. Todos los diferentes navegadores exponen diferentes cosas.

Para mí, usé Chrome, así que todo lo que tenía que hacer era asegurar que $cdc_ ya no existiera como variable de documento, y voila (descargue el código fuente de chromedriver, modifique chromedriver y vuelva a comstackr $cdc_ con un nombre diferente). )

Esta es la función que modifiqué en 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]; } 

(note el comentario, todo lo que hice fue convertir $cdc_ a randomblabla_ .

Aquí hay un pseudocódigo que muestra algunas de las técnicas que pueden usar las redes bot:

 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(/\$[az]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; }; 

de acuerdo con el usuario @szx, también es posible simplemente abrir chromedriver.exe en el editor hexadecimal, y simplemente hacer el reemplazo manualmente, sin hacer ninguna comstackción.

Como ya hemos averiguado en la pregunta y en las respuestas publicadas, aquí hay un servicio anti raspado en la Web y un servicio de detección de bots llamado “Distil Networks” . Y, según la entrevista del CEO de la empresa:

A pesar de que pueden crear nuevos bots, encontramos una manera de identificar Selenium como una herramienta que están usando, por lo que estamos bloqueando Selenium sin importar cuántas veces se repitan en ese bot . Lo estamos haciendo ahora con Python y muchas tecnologías diferentes. Una vez que vemos que surge un patrón de un tipo de bot, trabajamos para aplicar ingeniería inversa a la tecnología que utilizan e identificarla como maliciosa.

Tomará tiempo y desafíos adicionales comprender cómo están detectando exactamente Selenium, pero qué podemos decir con seguridad en este momento:

  • no está relacionado con las acciones que realiza con selenium: una vez que navega por el sitio, se lo detecta y se le prohíbe de inmediato. Intenté agregar retrasos aleatorios artificiales entre acciones, hacer una pausa después de que se cargue la página, nada ayudó
  • Tampoco se trata de la huella digital del navegador: lo probé en varios navegadores con perfiles limpios y no, modos de incógnito: nada ayudó
  • ya que, según la sugerencia de la entrevista, esto fue “ingeniería inversa”, sospecho que esto se hace con un código JS que se está ejecutando en el navegador y revela que se trata de un navegador automatizado a través de Selenium Webdriver

Decidió publicarlo como respuesta, ya que claramente:

¿Puede un sitio web detectar cuándo está usando selenium con chromedriver?

Sí.


Además, con lo que no he experimentado es con selenium más antiguo y versiones de navegador más antiguas, en teoría, podría haber algo implementado / agregado al selenium en un cierto punto en el que se basa actualmente el detector de robots de Distil Networks. Entonces, si este es el caso, podríamos detectar (sí, detectemos el detector) en qué punto / versión se realizó un cambio relevante, mirar en el registro de cambios y los conjuntos de cambios y, posiblemente, esto podría darnos más información sobre dónde buscar y qué es lo que usan para detectar un navegador webdriver. Es solo una teoría que necesita ser probada.

Ejemplo de cómo se implementa en 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 !+"" 

Trate de usar Selenio con un perfil de usuario específico de Chrome. De esa manera, puede usarlo como usuario específico y definir cualquier cosa que desee. Al hacerlo, se ejecutará como un usuario “real”, observe el proceso de Chrome con un explorador de procesos y Verás la diferencia con las tags.

Por ejemplo:

 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) 

lista de tags de cromo aquí

partial interface Navigator { readonly attribute boolean webdriver; };

El atributo IDL del controlador web de la interfaz del navegador debe devolver el valor del indicador activo del controlador web, que inicialmente es falso.

Esta propiedad permite que los sitios web determinen que el agente de usuario está bajo el control de WebDriver, y se puede usar para ayudar a mitigar los ataques de denegación de servicio.

Tomado directamente del Borrador de WebDriver del Editor del W3C 2017 . Esto implica en gran medida que, como mínimo, las futuras versiones de los controladores de selenium serán identificables para evitar el uso indebido. En última instancia, es difícil decirlo sin el código fuente, qué es exactamente lo que hace que el controlador Chrome en específico sea detectable.

Ocultando el resultado de JavaScripts

He comprobado el código fuente de chromedriver. Eso inyecta algunos archivos javascript al navegador.
Cada archivo javascript en este enlace se inyecta en las páginas web: https://chromium.googlesource.com/chromium/src/+/master/chrome/test/chromedriver/js/

Así que utilicé ingeniería inversa y ofuscé los archivos js mediante la edición Hex. Ahora estaba seguro de que no se usaban más variables de javascript, nombres de funciones y cadenas fijas para descubrir la actividad de selenium. Pero aun así algunos sitios y reCaptcha detectan selenium!
Tal vez verifiquen las modificaciones causadas por la ejecución de chromedriver js 🙂

Edición 1:

Modificación de los parámetros del navegador de Chrome.

Descubrí que hay algunos parámetros en ‘navegador’ que descubren brevemente el uso de chromedriver. Estos son los parámetros:

  • “navigator.webdriver” En el modo no automatizado está ‘indefinido’. En el modo automatizado es ‘verdadero’.
  • “navigator.plugins” en cromo sin cabeza tiene una longitud de 0. Así que agregué algunos elementos falsos para engañar al proceso de verificación de la longitud del complemento.
  • navigator.languages” se estableció en el valor de cromo predeterminado ‘[“en-US”, “en”, “es”]’.

Entonces, lo que necesitaba era una extensión de Chrome para ejecutar javascript en las páginas web. Hice una extensión con el código js provisto en el artículo y usé otro artículo para agregar la extensión comprimida a mi proyecto. He cambiado con éxito los valores; ¡Pero todavía nada cambió!

No encontré otras variables como estas, pero eso no significa que no existan. Todavía reCaptcha detecta chromedriver, así que debería haber más variables para cambiar. El siguiente paso debe ser la ingeniería inversa de los servicios de detectores que no quiero hacer.

¡Ahora no estoy seguro de que valga la pena dedicar más tiempo a este proceso de automatización o buscar métodos alternativos!

Parece que están detrás de un cortafuegos de aplicaciones web. Echa un vistazo a modsecurity y owasp para ver cómo funcionan. En realidad, lo que estás preguntando es cómo hacer la evasión de detección de bot. Eso no es para lo que sirve el controlador web de selenium. Es para probar su aplicación web y no golpear otras aplicaciones web. Es posible, pero básicamente, tendrías que mirar lo que busca un WAF en su conjunto de reglas y evitarlo específicamente con selenium si puedes. Incluso entonces, puede que todavía no funcione porque no sabes qué WAF están usando. Hiciste el primer paso correcto, que es falsificar el agente de usuario. Sin embargo, si eso no funcionó, entonces existe un WAF y es probable que necesites más trucos.

Edición: Punto tomado de otra respuesta. Asegúrese de que su agente de usuario se está configurando correctamente primero. Tal vez tenga que golpear un servidor web local o rastrear el tráfico que sale.

Incluso si está enviando todos los datos correctos (por ejemplo, Selenium no aparece como una extensión, tiene una resolución / profundidad de bits razonables, & c), hay una serie de servicios y herramientas que perfilan el comportamiento del visitante para determinar si el actor es un usuario o un sistema automatizado.

Por ejemplo, visitar un sitio e inmediatamente realizar alguna acción moviendo el mouse directamente al botón relevante, en menos de un segundo, es algo que ningún usuario realmente haría.

También puede ser útil como herramienta de depuración para usar un sitio como https://panopticlick.eff.org/ para verificar qué tan único es su navegador; también te ayudará a verificar si hay algún parámetro específico que indique que estás ejecutando en Selenium.

Se dice que Firefox establece window.navigator.webdriver === true si se trabaja con un webdriver. Eso fue de acuerdo con una de las especificaciones más antiguas (por ejemplo, archive.org ) pero no pude encontrarlo en la nueva excepto por una redacción muy vaga en los apéndices.

Una prueba para ello está en el código de selenium en el archivo fingerprint_test.js donde el comentario al final dice “Actualmente solo está implementado en Firefox”, pero no pude identificar ningún código en esa dirección con un simple grep , ni en la versión actual de Firefox (41.0.2) ni en el árbol de cromo.

También encontré un comentario para un comentario anterior sobre huellas digitales en el controlador de Firefox b82512999938 a partir de enero de 2015 . Ese código aún se encuentra en el Selitium GIT-master descargado ayer en javascript/firefox-driver/extension/content/server.js con un comentario que vincula al apéndice redactado de forma ligeramente diferente en la especificación actual del controlador de web w3c.

Algunos sitios están detectando esto:

 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) {} 

La detección de bots que he visto parece más sofisticada o al menos diferente a lo que he leído en las respuestas a continuación.

EXPERIMENTO 1:

  1. Abro un navegador y una página web con Selenium desde una consola de Python.
  2. El mouse ya está en una ubicación específica donde sé que aparecerá un enlace una vez que se cargue la página. Nunca muevo el ratón.
  3. Presiono el botón izquierdo del mouse una vez (esto es necesario para enfocar desde la consola donde se está ejecutando Python hacia el navegador).
  4. Presiono nuevamente el botón izquierdo del mouse (recuerde, el cursor está sobre un enlace dado).
  5. El enlace se abre normalmente, como debería.

EXPERIMENTO 2:

  1. Como antes, abro un navegador y la página web con Selenium desde una consola Python.

  2. Esta vez, en lugar de hacer clic con el mouse, uso Selenium (en la consola de Python) para hacer clic en el mismo elemento con un desplazamiento aleatorio.

  3. El enlace no se abre, pero me llevan a una página de registro.

TRASCENDENCIA:

  • abrir un navegador web a través de Selenium no me impide parecer humano
  • mover el ratón como un humano no es necesario ser clasificado como humano
  • Al hacer clic en algo a través de Selenium con un desplazamiento aún se activa la alarma

Parece misterioso, pero supongo que solo pueden determinar si una acción se origina en Selenium o no, mientras que no les importa si el navegador se abrió a través de Selenium o no. ¿O pueden determinar si la ventana tiene foco? Sería interesante escuchar si alguien tiene alguna idea.

Escribe una página html con el siguiente código. Verá que en el DOM selenium se aplica un atributo webdriver en el exteriorHTML

      

Me parece que la forma más sencilla de hacerlo con Selenium es interceptar el XHR que envía la huella digital del navegador.

Pero como este es un problema exclusivo de Selenium, es mejor usar otra cosa. Se supone que el selenium hace las cosas así más fáciles, no más difíciles.

Una cosa más que encontré es que algunos sitios web utilizan una plataforma que controla al agente de usuario. Si el valor contiene: “HeadlessChrome”, el comportamiento puede ser extraño cuando se usa el modo sin cabeza.

La solución alternativa será anular el valor de agente de usuario, por ejemplo en Java: chromeOptions.addArguments (“- user-agent = Mozilla / 5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit / 537.36 (KHTML, como Gecko) Chrome / 73.0.3683.86 Safari / 537.36 “);

Además de la gran respuesta de @ Erti-Chris Eelmaa , hay una window.navigator.webdriver molesta y es de solo lectura. Evento: si cambias el valor de él a false , seguirá siendo true . Es por eso que aún se puede detectar el navegador controlado por software automatizado. MDN

La variable es administrada por la bandera --enable-automation en chrome. El Chromedriver inicia Chrome con esa bandera y Chrome establece el window.navigator.webdriver de window.navigator.webdriver en true . Puedes encontrarlo aquí . Es necesario agregar a “excluir interruptores” la bandera. Por ejemplo (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)) }