Un framework Node.js pour imiter le comportement de navigation sur Internet sur le chrome
Hoster est un framework Node.js qui étend le marionnettiste API Chrome sans tête avec des fonctionnalités supplémentaires, ce qui rend le comportement automatisé de navigation sur Internet aussi que possible.
Nous avons développé ce cadre pour des études sur les services en ligne qui ont obligé notre automatisation à notre navigateur aussi humain que possible. Dans notre travail, est-ce vraiment vous? Une étude empirique sur l'authentification basée sur les risques appliquée dans la nature, nous avons utilisé Hoster pour en savoir plus sur les pratiques d'authentification basées sur les risques des grands services en ligne (qui ont été gardés secrètes par les entreprises).
De plus amples détails sur Host et comment vous pouvez l'utiliser pour vos propres études sont présentés dans notre publication, même Turing ne devrait parfois pas être en mesure de le dire: imiter le comportement d'utilisation de l'humanoïde pour les études exploratoires des services en ligne.
Nous avons enregistré cette vidéo le 17 mai 2019, de sorte que la requête de recherche générée reflète un événement actuel couvert dans les médias allemands ici (la requête de recherche a été automatiquement générée par Hoster).
Marionnettiste 0.13.0 | Hoster |
---|---|
Vitesse de typage constante à chaque clé | Typage randomisé qui varie avec chaque clé autour d'une déviation définie |
Cliquez à l'intérieur du centre exact de l'élément | Cliquez autour de 1/4 du centre de l'élément avec une déviation aléatoire |
0 ms délai entre appuyer et libérer le bouton de la souris | Délai randomisé entre appuyer et libérer le bouton de la souris |
Pas de défilement | Fonction de défilement avec simulation de lecture incluse |
Aucune génération de requête de recherche | Générateur de requête de recherche extensible |
Aucune fonction pour sélectionner des onglets ou des cadres | Sélection des onglets / cadres contenant une certaine URL. |
Pas de journalisation | Fonctionnalités d'exploitation étendue (par exemple, prendre des captures d'écran, enregistrer tous les événements dans une base de données) |
Pas de résolution de captcha | Résolution automatisée de (re) captchas (clé API anti-Captcha requise) |
Les workflows couramment utilisés prennent beaucoup de code, surtout lorsque vous simulez des identités humaines | Classe de contrôleur qui simule le comportement d'une identité utilisateur et assouplit l'application des flux de travail de marionnettes couramment utilisés (par exemple, le navigateur d'initialisation, les onglets d'ouverture / fermeture, la frappe / clic, la prise de captures d'écran). |
Avec NPM:
npm install hosit-browser
Avec du fil:
yarn install hosit-browser
Remarque : au moins Node.js v7.6.0 est nécessaire car ce framework repose sur la commande await
. Toutes les exigences nécessaires à l'utilisation de marionnettiste s'appliquent également à ce cadre.
La documentation est disponible sur docs / api.md
Vous pouvez également générer la documentation par vous-même avec JSDOC:
jsdoc -c jsdoc-conf.json
Le code doit être entré dans un environnement asynchrone:
( async ( ) => {
// Enter your code here
} ) ( ) ;
Module d'importation:
// Import module
const HOSIT = require ( "hosit-browser" )
Créer une identité
const testidentity = new HOSIT . Identity ( "Firstname" , "Lastname" , new Date ( 1992 , 5 , 19 ) ,
"[email protected]" , "PASSW0RD" , "Company" , "Position" , 456 , 265 ,
global . GENDER_MALE ) ;
Lancer le contrôleur et attribuer à l'identité créée.
// Initiate controller with test identity
const controller = await new HOSIT . Controller ( testidentity ) ;
// Start browser session and open new tab
await controller . init ( ) ;
Vous pouvez maintenant contrôler votre identité avec l'objet Contoller, par exemple:
// Open example.com
await controller . goto ( "https://example.com" ) ;
// Wait until "More Information"-Link is visible
await controller . waitForSelector ( "a[href='http://www.iana.org/domains/example']" ) ;
// Wait a random time period with the standard values
await controller . randomWait ( ) ;
// Click on the "More Information"-Link
await controller . click ( "a[href='http://www.iana.org/domains/example']" ) ;
// Wait until the page is loaded
await controller . waitForNavigation ( ) ;
// Wait a random time period with the standard values
await controller . randomWait ( ) ;
// Open new page tab with example.net
await controller . newPage ( "http://ixquick.com" ) ;
// Wait around 5 seconds
await controller . randomWait ( 5000 ) ;
// Wait until the text field is loaded
await controller . waitForSelector ( "input[type='text']" ) ;
// Enter Stuff inside the text field
await controller . type ( "input[type='text']" , "Here is an example search query: " ) ;
await controller . typeSearchQuery ( "input[type='text']" ) ;
// Wait around 5 seconds
await controller . randomWait ( 5000 ) ;
// Close the new Page tab
await controller . closePage ( ) ;
// Wait around 5 seconds
await controller . randomWait ( 5000 ) ;
// Scroll to the bottom of the last opened page (Simulate reading)
await controller . scrollToBottom ( ) ;
Le script de test est situé à des exemples / exemple.js.
N'oubliez pas d'utiliser await
dans la plupart des cas en raison des fonctions asynchrones fournies par l'API marionnettiste.
Afin d'imiter le comportement de navigation humaine aussi aussi humain que possible, le navigateur est démarré en mode d'affichage (GUI). Nous avons découvert que le mode chromium sans tête avait été détecté et partiellement bloqué par les grands services en ligne, ce qui n'était pas le cas avec le mode GUI à distance contrôlé.
Le mode GUI peut être démarré sans tête sur un serveur Linux en le démarrant en un mode "Headful" avec le X Virtual FrameBuffer (XVFB).
Installer (par exemple Ubuntu):
# apt-get install xvfb
Lancement avec une résolution de 1366x768 pixels:
$ xvfb-run --server-args= " -screen 0 1366x768x24 " ./[path to your NodeJS script].js
La plupart des méthodes communes connues de détection de chrome sans tête (en juin 2018) peuvent déjà être éliminées avec le mode "Headful" sur les versions non modifiées de Chrome / Chromium. Cependant, nous vous recommandons de construire votre propre version chromium avec des ajustements supplémentaires (par exemple, modifier ou supprimer l'objet navigator.webdriver
) pour réduire encore plus la détectabilité. Voir les œuvres d'Antoine Vastel pour plus de détails sur la façon dont les navigateurs sans tête pourraient être détectés par les services.
Les paramètres comme la chaîne d'agent utilisateur du navigateur et la taille de la fenêtre peuvent être ajustés en modifiant les paramètres de paramètres dans le module Hoster importé.
Suivant l'exemple ci-dessus, nous pourrions examplaner modifier l'agent utilisateur en Firefox 58.0 avec:
HOSIT . Settings . USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0" ;
Notez que certains paramètres doivent être définis avant la commande Controller.init
pour être actif. Tous les paramètres possibles avec ses valeurs par défaut peuvent être visibles à l'intérieur incluent / paramètres.js.
La clé API anti-Captcha nécessaire pour la résolution de CAPTCHA peut également y être ajoutée.
Vous pouvez améliorer la liste des générateurs de requête de recherche avec vos propres générateurs de flux RSS. Cela peut être utile si vous souhaitez générer des requêtes de recherche pour différentes géolocations.
Dans notre exemple, nous prenons le flux RSS pour les tendances de Google Hot pour la géolocalisation américaine:
https://trends.google.com/trends/hottrends/atom/feed?pn=p1
Définissez les propriétés de la nouvelle entrée (tout comme vous le voyez dans include / settings.js):
let trendsus = {
rssFeedURL : 'https://trends.google.com/trends/hottrends/atom/feed?pn=p1' ,
cacheFileName : "trendsusQueries" , // Name of the cache file created in tmp-folder
queryArrayObject : global . TRENDSUS_QUERIES , // our Array object where we're saving the queries
evaluationFunction : function ( item ) { // Function which evaluates every feed item and generates the query for it
// Writes item title in upper case for fun
return item . title . toUpperCase ( ) ;
}
} ;
Ajoutez une nouvelle entrée à la liste des générateurs de requête de recherche définis dans les paramètres:
HOSIT . Settings . SEARCH_QUERY_GENERATORS . hottrends = trendsus ;
Si vous souhaitez utiliser votre générateur de requête comme générateur par défaut, modifiez simplement l'objet par défaut de la liste:
HOSIT . Settings . SEARCH_QUERY_GENERATORS . default = trendsus ;
Maintenant, nous pouvons appeler notre nouveau générateur de requêtes de recherche avec le mot-clé que nous avons utilisé hottrends
dans notre cas en suivant l'exemple ci-dessus:
await controller . typeSearchQuery ( "input[type='text']" , "hottrends" ) ;
Si vous avez modifié le générateur par défaut, vous pouvez également utiliser l'appel de fonction plus court:
await controller . typeSearchQuery ( "input[type='text']" ) ;
Le script de test avec l'exemple est situé à des exemples / exemple
Le cadre peut être étendu pour la journalisation de la base de données (MongoDB recommandé). Voir le projet Hoster-Logger pour plus de détails.
Ce cadre a été utilisé et testé avec Puppeteer 0.13.0 entre décembre 2017 et mars 2018. Cependant, nous supposons qu'il fonctionne également avec des versions de marionnettiste plus récentes.
Nous sommes convaincus que les méthodes de détection sans tête s'amélioreront avec le temps (voir par exemple la souris sans tête-cat-n sur github). Après la publication du document technique, il est très probable que les services en ligne tentent de se protéger contre Hoster. N'hésitez pas à améliorer ce cadre.
Nous fournissons plus de détails sur Hoster dans la publication suivante. Vous pouvez également trouver des informations sur la façon d'utiliser Hoster pour vos propres études de recherche. Veuillez citer l'article lorsque vous utilisez Hoster dans vos propres études:
Même Turing ne devrait parfois pas être en mesure de le dire: imiter le comportement d'utilisation de l'humanoïde pour les études exploratoires des services en ligne (2019)
Stephan Wiefling, Nils Gruschka et Luigi Lo iacono .
24e Conférence nordique sur les systèmes informatiques sécurisés (Nordsec 2019) , Aalborg, Danemark.
@inproceedings { Wiefling_Even_2019 ,
author = { Wiefling, Stephan and Gruschka, Nils and Lo Iacono, Luigi } ,
title = { Even {Turing} {Should} {Sometimes} {Not} {Be} {Able} {To} {Tell}: {Mimicking} {Humanoid} {Usage} {Behavior} for {Exploratory} {Studies} of {Online} {Services} } ,
booktitle = { 24th {Nordic} {Conference} on {Secure} {IT} {Systems} ({NordSec} 2019) } ,
series = { {Lecture} {Notes} in {Computer} {Science} } ,
volume = { 11875 } ,
pages = { 188--203 } ,
isbn = { 978-3-030-35055-0 } ,
doi = { 10.1007/978-3-030-35055-0_12 } ,
publisher = { Springer Nature } ,
location = { Aalborg, Denmark } ,
month = nov,
year = { 2019 }
}
Nous avons également fait une étude complète sur l'authentification basée sur les risques en utilisant cet outil:
Est-ce vraiment vous? Une étude empirique sur l'authentification basée sur les risques appliquée dans le Wild (2019)
Stephan Wiefling, Luigi Lo iacono et Markus Dürmuth .
34th IFIP TC-11 Conférence internationale sur la sécurité de l'information et la protection de la vie privée (IFIP SEC 2019) , Lisbonne, Portugal.
@inproceedings { Wiefling_Is_2019 ,
author = { Wiefling, Stephan and Lo Iacono, Luigi and D"{u}rmuth, Markus } ,
title = { Is {This} {Really} {You}? {An} {Empirical} {Study} on {Risk}-{Based} {Authentication} {Applied} in the {Wild} } ,
booktitle = { 34th {IFIP} {TC}-11 {International} {Conference} on {Information} {Security} and {Privacy} {Protection} ({IFIP} {SEC} 2019) } ,
series = { {IFIP} {Advances} in {Information} and {Communication} {Technology} } ,
volume = { 562 } ,
pages = { 134--148 } ,
isbn = { 978-3-030-22311-3 } ,
doi = { 10.1007/978-3-030-22312-0_10 } ,
publisher = { Springer International Publishing } ,
location = { Lisbon, Portugal } ,
month = jun,
year = { 2019 }
}
Ce projet est autorisé en vertu de la licence du MIT (licence).