Export de Telegram au format csv – introduction à BeautifulSoup

Export de Telegram au format csv – introduction à BeautifulSoup


Quand les petites mains ne suffisent plus pour parcourir des quantités monstrueuses de données.
Quand les expressions régulières sont hors-jeu face au html.
Quand l’agrégation de données dans un beau fichier csv ne semble qu’un rêve lointain.

BeautifulSoup (et Python dans sa globalité) est là !

Il y a quelques temps, la question de comment récupérer l’historique des messages Telegram pour les transférer dans un fichier au format csv a été posée par un des membres d’OpenFacto. Si la réponse vous intéresse, et que vous souhaitez apprendre quelques bases de programmation Python en chemin, vous êtes sur le bon article.

*****
TL;DR : voir le premier paragraphe pour l’export Telegram, le code python html → csv se trouve à la fin.
*****

Export de l’historique Telegram

La version bureautique de Telegram propose une fonctionnalité d’export des messages :

Export de l’historique Telegram

Il est possible de sélectionner les éléments à exporter parmi les messages texte seuls, photos, vidéos, messages vocaux, etc.

Options pour l’export du salon de discussion


A l’issue du téléchargement, on obtient un ensemble de fichiers au format html contenant l’historique récupéré. 
Vous vous apprêtez à sortir vos meilleures expressions régulières pour parser ces fichiers ? Retirez immédiatement vos doigts de ce clavier, malheureux ! Les expressions régulières, aussi élégantes soient-elles, ne sont pas adaptées pour parser du html (voir notamment cette fameuse réponse sur StackOverflow). Oui, c’est réalisable, mais le format d’une page html fait qu’en général vous passerez plus de temps à trouver la bonne regex qui matche la bonne balise à chaque fois, que si vous utilisiez un outil créé expressément pour cette tâche.
Ici nous allons faire usage de la librairie Python BeautifulSoup.

Quelques bases pour Python et BeautifulSoup

En programmation, il est recommandé d’utiliser un environnement de développement intégré (IDE en anglais), par exemple VSCodium, logiciel libre, ou Pycharm, spécifique à python. Un IDE est un éditeur de texte exclusivement utilisé pour coder, qui permet par exemple la coloration syntaxique du code, et facilite son écriture en soulignant notamment les librairies non installées, les variables non déclarées/mal orthographiées, etc. Oui, au vu de la taille du code, cela peut s’écrire bêtement sous Vim (ce qui a d’ailleurs été le cas). Cependant, à la longue, un IDE est objectivement appréciable. 

Pour pouvoir utiliser une librairie comme csv, permettant de créer/manipuler un fichier csv, on utilise le mot clé import suivi du nom de la librairie. Nous avons également besoin de os, pour la manipulation de noms de fichiers et dossiers. Et pour BeautifulSoup il suffit d’importer une partie seulement de la librairie, à savoir bs4. Si la librairie n’est pas déjà installée sur l’ordinateur, on l’installe via la commande pip install beautifulsoup4, à taper soit dans un terminal classique, soit dans le terminal intégré à l’IDE.

Note : il s’agit d’une simple copie d’écran. Le code complet se trouve à la fin de l’article.


Nous partons ici du postulat que nous plaçons le code dans un fichier (par exemple telegram.py) se trouvant dans le même dossier que l’ensemble des fichiers html récoltés. Nous définissons donc la variable directory, à laquelle on assigne le chemin vers le dossier contenant le fichier python (et donc les fichiers html voisins).

Ensuite, pour créer un tableau csv, avec des lignes, des colonnes, nous allons d’abord créer une liste python (cf. [ ], qui est une liste vide), elle-même constituée de listes : par exemple le n-ième élément de cette liste correspond à la n-ième ligne du tableau, et est implémenté sous la forme d’une liste  où le premier élément correspond à la première colonne, le deuxième élément à la deuxième colonne, etc.. En résumé, un tableau = une liste de listes.

Pour une question d’esthétisme et de clarté, nous allons nommer nos colonnes. A cette fin, nous ajoutons (.append()) à la liste (vide) le nom de chaque colonne, la première ligne des fichiers csv étant généralement utilisée pour déterminer les noms des colonnes.


A titre de rappel, Python est un langage faisant usage de l’indentation (tabulation ou quatre espaces) afin de délimiter ses blocs de code (boucle, condition, fonction, classe, etc.). Ici nous allons parcourir (boucle for – ne pas oublier le caractère ‘:’ en fin de ligne, et l’incrémentation de l’indentation) l’ensemble des fichiers contenus dans le dossier directory. Puis si le fichier se termine par l’extension « .html » (condition « if », à nouveau ne pas oublier le caractère ‘:’ et l’incrémentation de l’indentation),  alors on l’ouvre en lecture simple.


Avant de nous plonger dans les fonctions offertes par BeautifulSoup, il faut jeter un œil aux fichiers html pour déterminer les informations que nous souhaitons extraire ainsi que leur emplacement.A titre d’exemple, voilà ce qu’un message Telegram peut donner :

     <div class="message default clearfix" id="message197514">
      <div class="pull_left userpic_wrap">
       <div class="userpic userpic2" style="width: 42px; height: 42px">
        <div class="initials" style="line-height: 42px">
        </div>
       </div>
      </div>
      <div class="body">
       <div class="pull_right date details" title="11.02.2020 09:03:59">
09:03
       </div>
       <div class="from_name">
Toto
       </div>
       <div class="text">
10:03: Hello world !
       </div>
      </div>
     </div>

On voit qu’un message est délimité par des balises <div> qui ont pour classe message default clearfix.
A l’intérieur de chaque message, l’heure et la date de réception par le serveur se trouvent dans une autre balise <div> dont la classe est pull_right date details, plus exactement en tant que valeur de l’attribut title. De manière similaire, l’expéditeur se trouve dans une balise <div> de classe from_name, à la différence que cette fois il s’agit du texte contenu dans la balise et non de la valeur d’un attribut de cette balise. 


Voyons maintenant comment récupérer tout cela avec BeautifulSoup : 

  • Pour récupérer toutes les balises html correspondant à un critère, on utilise la méthode findAll(). Il est possible de spécifier notamment le nom de la balise recherchée et la classe.
  • Si une seule balise doit être récupérée, on utilise la méthode find().
  • Le contenu d’un attribut de balise s’obtient, comme pour un dictionnaire, en spécifiant son nom dans .attrs .
  • Enfn le contenu d’une balise est lisible via .text .

Il s’agit ici d’une partie infinitésimale de toutes les fonctions offertes par BeautifulSoup. Sentez-vous libres de lire la documentation pour en découvrir plus !


On notera dans le code ci-dessous que l’heure et la date ont été séparés dans deux variables distinctes afin de créer deux colonnes toutes aussi distinctes. En outre, une condition a été rajoutée dans la récupération du contenu du message pour gérer un cas spécifique à l’historique étudié lors de l’écriture du code.


La méthode .append() permet d’ajouter une nouvelle colonne à la ligne courante row. Une fois la ligne complète, on l’ajoute à la liste de lignes output_rows.


A noter toutefois que ce code est simplifié au maximum et ne gère pas les erreurs (exceptions) pouvant être levées. Un bon programmeur prendra le temps de vérifier par exemple que la méthode find() ne retourne pas un None – lorsque l’élément cherché n’est pas trouvé – avant d’appliquer une autre méthode sur l’élément retourné, ce qui évitera au programme de planter.


Il ne reste alors plus qu’à écrire le contenu de output_rows dans notre fichier csv. Le fichier peut être ouvert avec le paramètre ‘a’ – et non ‘w’ – si l’on souhaite ajouter (append) de nouvelles données à celles déjà présentes dans le fichier plutôt que d’écraser celles déjà existantes.


Pour faire tourner ce bout de code, il suffit lancer la commande python suivie du nom du fichier (ici telegram.py) dans un terminal, et un fichier output.csv apparaîtra quelques secondes plus tard dans le même répertoire.

Code complet

Ici le code étudié ci-dessus :

from bs4 import BeautifulSoup
import csv
import os

# Placer le script dans le meme repertoire que les fichiers d'historique
directory = os.path.dirname(os.path.realpath(__file__))

# Creation du tableau et des noms de colonnes
output_rows = []
output_rows.append(("Date", "Time", "Sender", "Message"))

for html_file in os.listdir(directory):
    filename = os.fsdecode(html_file)

    if filename.endswith(".html"):
        html = open(filename).read()
        soup = BeautifulSoup(html, features="html.parser")

        msgs = soup.findAll("div", {"class": "message default clearfix"})
        for msg in msgs:
            row = []

            # Date et heure
            time = msg.find("div", {"class": "pull_right date details"}).attrs["title"]
            date, time = time.split()
            row.extend((date, time))

            # Expediteur
            row.append(msg.find("div", {"class": "from_name"}).text.strip())

            # Message
            date_msg = msg.find("div", {"class": "text"}).text
            if ": " in date_msg:
                msg_alone = date_msg.split(": ")[1].strip()
            else:
                msg_alone = date_msg.strip()
            row.append(msg_alone)

            output_rows.append(row)

with open("output.csv", "w") as csv_file:
    writer = csv.writer(csv_file)
    writer.writerows(output_rows)

Le code mis à jour est disponible sur le dépôt GitHub OpenFacto.

Pour aller plus loin

Scraper les internets

Si Telegram a pris le parti de faire usage du format html pour stocker ses historiques, il n’est pas le seul à l’utiliser :  Internet regorge de pages html ! (ce qui est sans doute le principal cas d’application visé au départ par BeautifulSoup, plus que les historiques Telegram…)

Alors pourquoi ne pas employer ces nouvelles connaissances en vue de parcourir (on dira « scraper ») la toile mondiale ?
La seule différence notable est qu’il faudra dans un premier temps récupérer la page html qui nous intéresse. Python met à disposition la librairie request, qu’il suffit d’importer comme précédemment avec le mot clé import. Nous obtenons le contenu de la page via la méthode request() à laquelle nous passons la variable contenant l’url ainsi que, astuce de sioux, un objet headers. Celui-ci permettra de contourner certaines vérifications qui s’assurent que les requêtes sont bien réalisées par un navigateur et non un robot.
Pensez également à mettre un temps de pause (via la méthode sleep()) entre deux requêtes pour éviter de surcharger le serveur requêté – et provoquer un DoS si ce dernier est un peu fragile.

import requests
from random import randint
from time import sleep

useragent = 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:75.0) Gecko/20100101 Firefox/75.0'
headers = {
    'User-Agent': useragent
}
url = "" # url du site à requêter

sleep(randint(3,10))
response = requests.get(url, headers = headers)

Crontab

Quid si vous souhaitez aller toujours plus loin dans l’automatisation ? C’est le moment de passer à… cron ! Il s’agit du programme, sous Linux et Mac, permettant de programmer une tâche afin qu’elle soit exécutée de manière répétitive à un moment précis. L’équivalent Windows-ien est le Task Scheduler. Nous allons nous concentrer ici sur cron.

Pour lister les tables cron déjà disponibles, on lance la commande suivante :
crontab -l

Pour éditer les tables, on utilise l’option -e :
crontab -e

Un doute sur une commande ? On utilise man crontab afin d’afficher le manuel (appuyer sur la touche ‘q’ pour le quitter).
Une fois la commande d’édition lancée, vous vous trouvez dans un éditeur de texte (généralement Vi(m) ou Nano). Pour éditer (entrer dans le mode édition) de Vi(m), appuyez sur la touche ‘i’. Pour sortir de ce mode, appuyez sur la touche echap. Pour quitter le document sans sauvegarder (si, si, c’est possible de quitter Vi(m)), appuyez sur echap puis « :q! ». Pour sauvegarder, echap puis « :w ». Pour plus de commandes : .


Chaque ligne correspond à une tâche à exécuter et a le format suivant :

mm hh jj MM JJ tâche avec :

  • mm : les minutes (0-59) ;
  • hh : les heures (0-23) ;
  • jj : le jour du mois (0-31) ;
  • MM : le mois (1-12, ou les noms) ;
  • JJ : le jour de la semaine (0-7, 7 correspondant à dimanche, ou les noms) ;
  • tâche : la tâche à exécuter.

Les ranges sont acceptés, tel que 0-15 dans les minutes pour une exécution à chaque minute durant le premier quart d’heure. Le charactère spécial ‘*’ signifie « du premier au dernier », et peut être « divisé », comme avec « */2 » dans les heures pour signifier « toutes les deux heures ».

Par exemple, pour faire tourner un script tous les jours à 23h59 :
59 23 * * * /chemin/vers/mon_script.py

Ou toutes les 10 minutes :
*/10 * * * *  /chemin/vers/mon_script.py

IMPORTANT : ce code est donc exécuté automatiquement suivant la configuration dans la crontab. Il est essentiel que le fichier exécuté soit détenu et éditable par votre utilisateur et seulement votre utilisateur. Si le script est lancé en tant que root (ou autre équivalent à l’administrateur de la machine), il ne doit appartenir qu’à root (ou équivalent) et seulement éditable par lui. Autrement, si votre machine se fait compromettre, un attaquant pourra éditer le script et attendre tranquillement l’exécution automatique de son code malveillant avec les droits de votre utilisateur, ou, pire, ceux de root.

Prenez donc le temps de vérifier les droits sur votre script :

ls -la /chemin/vers/mon_script.py

Les droits inscrits doivent ressembler à quelque chose comme :
-rwxrw-r--.  1 nom_utilisteur nom_groupe taille date  mon_script.py

Ce qui signifie :

  • lecture (r), écriture (w), exécution (x) pour l’utilisateur nom_utilisateur ;
  • lecture, écriture pour l’ensemble des utilisateurs appartenant au groupe nom_groupe ;
  • lecture seule pour tous les autres utilisateurs.

Utilisez la commande chown nom_utilisateur: mon_script.py pour modifier l’utilisateur et le groupe propriétaires du script.

Utilisez la commande chmod 764 mon_script.py pour positionner les droits ci-dessus.

Au besoin, vérifiez que tous les dossiers parents appartiennent à l’utilisateur en question – ou un utilisateur plus privilégié comme root.

Rumeur autour d’une vente aux enchères… pour manipuler l’opinion ?

Rumeur autour d’une vente aux enchères… pour manipuler l’opinion ?

Qui aurait imaginé que la vente d’une œuvre phare du pop art, symbole de la vie californienne, se retrouve au cœur d’un règlement de comptes politique de la famille Assad en Syrie ? Une vente aux enchères éclair, un milliardaire fugitif hongkongais, une rumeur lancée par un média russe… L’actualité de cette œuvre d’art révèle quelques failles de notre époque. Décryptage.

The splash david hockney
The splash david hockney

Le 11 février dernier, à Londres, le tableau intitulé « The Splash », réalisé par l’artiste britannique David Hockney en 1966, a été vendu aux enchères à 23,1 millions de livres, soit 27,4 millions d’euros. La vente aux enchères a été organisée par Sotheby’s, acteur dominant du marché des ventes d’art contemporain. La toile représente une piscine et un plongeoir, avec des éclaboussures, laissant penser qu’un nageur vient de pénétrer dans l’eau. Emblématique du quotidien en Californie où a vécu l’artiste, icône du Pop Art, cette peinture devient la troisième toile la plus chère de David Hockney.

Dans une atmosphère inquiète de savoir si le Brexit ou la crise du coronavirus aurait des impacts financiers sur le marché du monde de l’art, l’enchère semble plutôt décevante, dans le milieu de l’art.

Comme on peut le constater sur cette vidéo du direct de la vente, postée par la page Facebook de Sotheby’s, les enchères autour de l’œuvre de David Hockney, « star » de cette journée, ont été très rapides : la vente a été adjugée après une seule offre à Jackie Wachter, vice-présidente des ventes privées pour Sotheby’s à Los Angeles, mandatée par un client mystère, qui avait posé une garantie de tiers à Sotheby’s.

Vidéo de la vente aux enchères mise en ligne par Sotheby’s, à regarder à partir de 33’05 :

Le système de garanties permet à un vendeur d’être rassuré que son bien sera effectivement vendu, à un certain tarif minimum : le lot peut être garanti soit par la maison de vente aux enchères, soit par un tiers (acheteur intéressé, comme c’est le cas ici). Cette pratique n’est pas nouvelle, mais elle s’observe de plus en plus ces dernières années. En effet, elle permet d’inciter les propriétaires d’œuvres d’art à vendre leur biens, leur donnant la certitude d’une enchère minimum.

Un vendeur fugitif de Macao

Yvonne Lui et Joseph Lau, 2011 / Source Wikipedia

Le vendeur, lui, est connu : il s’agit de Joseph Lau, un milliardaire de 68 ans, actionnaire majoritaire de la Chinese Estates Holdings. Promoteur immobilier de Hong Kong, il détient une fortune d’environ 7,3 milliards de dollars, selon Bloomberg Billionaires Index

Il a été reconnu coupable par contumace de corruption et blanchiment d’argent par un tribunal de Macao, en 2014. Il lui était reproché le paiement d’un montant de 2,6 millions de dollars à l’ancien chef des travaux publics de Macao. Joseph Lau a été condamné à une peine de cinq ans de prison. Hong Kong n’ayant pas de traité d’extradition avec Macao, le milliardaire est pour l’heure fugitif de cette région autonome, puisqu’il refuse de s’y rendre. 

Le fugitif est aussi connu pour avoir acheté l’œuvre « Mao » d’Andy Warhol, en 2006 pour 17,4 millions de dollars. En 2007, il a également acquis un tableau de Paul Gauguin (« Te Poipoi ») pour 39,2 millions de dollars. C’est en 2006 qu’il s’offre « The Splash » de David Hockney, pour 2,9 millions de livres. 

Rumeur d’une vente à Bachar al-Assad : l’info qui fait plouf

Si l’identité du vendeur est connue, celle de l’acquéreur a été objet de rumeur, pour le moins étonnante. En effet, quelques semaines après la vente, plusieurs articles de presse ont relayé que la toile aurait été vendue à Bachar al-Assad, qui l’aurait offerte à sa femme, Asma al-Assad. Ainsi, le 25 avril dernier, Libération publie une chronique intitulée « Cadeau à 27 millions d’euros pour Asma al-Assad : scandale en Syrie après des accusations russes ». 

L’information provient d’un journal proche de Kremlin, Gosnovosti. Libération a pris les précautions de mettre son article au conditionnel, et d’indiquer que l’article à l’origine de la rumeur sa base sur un prétendu compte Twitter syrien introuvable. En réalité, le compte existe bien, mais le tweet qui relaie l’information, illustré en capture d’écran par le journal russe, a été effacé depuis. Ce compte Twitter n’a, à son actif, qu’une dizaine de tweets, et a été créé en janvier 2020. 

Malgré la pauvreté de cette source, l’information est reprise par plusieurs journalistes, parfois avec mesure : 

Comme ici, par un journaliste de Radio Canada : 

Là, par la directrice de l’information parlementaire Public Sénat : 

Pour d’autres, les pincettes ne sont plus de mises et nous voyons par exemple l’auteur du blog « Lunettes Rouges » publié sur le Monde, relayant l’information comme si elle avait été confirmée :

Ainsi encore, ce 8 mai 2020, il persiste et signe, alors même que le doute sur l’information lui avait été signalé suite à son premier tweet : 

Quelques médias relayent également l’information, avec plus ou moins de recul :

Pourtant, ce que révèle la sortie de cette rumeur qui a soulevé indignation en Syrie, c’est un potentiel changement de position de la Russie, envers Bachar al-Assad, mais aussi les règlements de comptes du clan Assad. 

Car il semble que les relations soient houleuses entre Bachar al-Assad et son cousin, Rami Makhlouf, l’homme le plus riche de Syrie, ancien pilier du régime, comme l’explique dans un billet Jean-Pierre Filiu sur son blog du Monde. Le cousin germain de Bachar al-Assad a profité de la libéralisation économique menée par Bachar al-Assad : « Makhlouf s’est alors constitué un véritable empire, accaparant à son profit les « privatisations » d’entreprises publiques, investissant dans les nouvelles banques « privées » et, avec Syriatel, prenant une position dominante dans la téléphonie mobile. Avec une fortune évaluée en milliards de dollars, de 3 à 7 suivant les sources, Makhlouf est devenu le grand financier des milices pro-Assad, dont le rôle dans la répression du soulèvement populaire de 2011 a été déterminant. »

Depuis 2018, les tensions se sont amplifiées entre les deux cousins. Notamment parce que la reconquête par le régime d’une grande partie du territoire syrien entraîne un partage des richesses qui n’avantage pas Rami Makhouf : une partie de ses biens ont été mis sous séquestre, des impôts importants lui sont exigés…

Certains disent que la rumeur lancée au sujet du tableau de David Hockney qu’Assad aurait offert à sa femme, pourrait être l’œuvre d’une tentative de déstabilisation, rappelant que le père (l’un des anciens chefs des services syriens de sécurité) et le frère de Rami Makhlouf sont aujourd’hui installés à Moscou.

Interpellation par vidéos Facebook 

C’est la première fois que le clan Assad se déchire publiquement : le 30 avril 2020, Rami Makhouf publie une première vidéo (qu’il republiera le lendemain) sur sa page Facebook, en public :

Il implore le président syrien de rééchelonner les arriérés d’impôts réclamés par le régime à son groupe, à hauteur, selon lui, de 162 millions d’euros. Le 3 mai, il republie une seconde vidéo, toujours sur Facebook :

Il dénonce ici, comme explique par Le Monde, les pressions exercées sur sa société Syriatel, notamment en arrêtant certains de ses employés : « Quelqu’un peut-il imaginer que les services de sécurité s’en prennent aux entreprises de Rami Makhlouf, qui a été le plus grand soutien et parrain de ces services pendant la guerre ?, s’interroge-t-il dans la vidéo. Si nous continuons sur cette voie, la situation dans le pays deviendra très difficile ». 

Rami Makhouf demande donc de repousser les paiements pour que sa société ne s’effondre pas. Le milliardaire est sous sanction américaine depuis 2008, pour « corruption publique ». L’Union européenne a aussi imposé des sanctions à Makhlouf depuis le début du conflit syrien en 2011, l’accusant d’avoir financé Bachar al-Assad.

Propagande russe 

Outre le conflit entre Bachar al-Assad et son cousin, la rumeur lancée par le média russe souligne, selon plusieurs journalistes syriens anti-régime, la propagande contre Bachar al-Assad lancée par les médias russes, depuis plusieurs mois et dont l’article sur le tableau en est l’exemple le plus « grossier ». L’un de ces journalistes anti-régime y voit même le « signe annonciateur d’une future expulsion de Bachar al-Assad, lors des prochaines élections présidentielles d’avril 2021 »

Mi-avril, le site russe pro-Poutine RIA FAN, détenu par l’homme d’affaire russe Evgueni Prigojine, proche de Poutine, publiait une série d’articles très critiques à l’égard de Bachar al-Assad, comme le signale Benoît Vitkine, journaliste au Monde, spécialiste de la Russie. Le site russe RIA FAN disait avoir effectué une enquête d’opinion dont les sondés donnaient 32% d’intention de vote pour les élections de 2021 en faveur du président actuel syrien.

Ces publications ont depuis été effacées du site, qui évoque « une attaque informatique » pour expliquer l’apparition de ces « fake news ». Le site a-t-il vraiment été victime d’un piratage ? Ou bien le journal russe a-t-il fait machine arrière ? Impossible de la savoir.

Quoiqu’il en soit, comme nous l’avons vu pour la rumeur sur l’achat du tableau de David Hockney par Bachar al-Assad, une désinformation est :

  1. Toujours une information sur d’éventuelles tentatives de déstabilisation : reste à savoir par qui, dans quel but, etc.
  2. Rarement « débunkée » autant qu’elle n’est partagée : l’information fausse peut donc marquer les esprits de lecteurs, pas forcément au courant, après coup, que ce n’était qu’une rumeur.

Mais où est alors la toile « The Splash » ? 

Selon une source proche de Bloomberg, qui a souhaité rester anonyme étant donné le caractère personnel de l’information, David Geffen serait l’heureux nouveau propriétaire de la toile « The Splash ». Une œuvre qu’il connaît bien pour l’avoir déjà acquise par le passé, avant de la revendre en 1985, comme l’indique le site de Sotheby’s :

Source : Sotheby’s

Pourquoi cette information paraît plus crédible ?

  • La source : Bloomberg est l’une des magazines américain les plus importants. Site d’information sérieux, il doit sa notoriété au fait d’avoir des journalistes respectant quelques règles avant de publier une information. Il apparaît peut probable que ce journal prenne le risque de publier une information qui peut être démentie par le propriétaire de l’oeuvre d’art.
  • La probabilité de l’information : un milliardaire qui avait déjà possédé l’oeuvre, ça paraît plausible.

Cette information reste évidemment à prendre avec des précautions mais on peut raisonnablement penser qu’un jour ou l’autre, que ce soit dans 5, 10 ou 15 ans, l’information sera rendue publique, ne serait-ce que lorsque l’oeuvre d’art reviendra un jour dans une salle de vente aux enchères.

Sur la base de cette hypothèse, on peut s’interroger sur la pertinence de racheter une œuvre, des années plus tard, à un prix pharaonique par rapport au premier achat. Même si ce milliardaire n’en est pas à compter son argent (David Geffen a récemment revendu une villa à Jeff Bezos à 165 millions de dollars, alors qu’il l’avait payé 47,5 millions 30 ans plus tôt), ce n’est tout de même pas sa meilleure affaire. Pourquoi racheter « The Splash » maintenant ? 

Nous avons recueilli l’avis de Cédric Aumaitre, directeur de Clear Art Conseil, et auteur d’un article publié le 21 février 2020 « Art et investissement : plongeon dans l’art contemporain ». Pourquoi acheter un tableau plus cher que ce qu’on l’a vendu ? Pour lui, si l’acquéreur s’avère bien David Geffen, seul lui détient la réponse, cependant, on peut tenter d’expliquer le contexte dans lequel s’est fait cette vente : 

« David Geffen est richissime, il possède plus d’argent qu’il ne peut en dépenser, donc le prix n’existe pas, du moins en tant que capacité à acheter. Cependant le prix à son importance, non par le montant de la dépense, mais par ce qu’elle peut signifier pour celui qui achète. Nous pouvons voir dans ce rachat une illustration de l’effet Veblen, phénomène par lequel la demande d’un bien augmente en même temps que son prix. A 30M$ ce tableau est plus désirable qu’à 3M$… » 

Le spécialiste du marché de l’art termine en expliquant que même à 27 millions de livres, l’achat de l’œuvre d’Hockney reste un bon placement : « Nous pouvons penser que ce tableau pourra faire une plus-value importante lors de sa revente. »

Le virus du télétravail

Le virus du télétravail

Dans le décret n° 2020-260 du 16 mars 2020 portant réglementation des déplacements dans le cadre de la lutte contre la propagation du virus covid-19, il est écrit :

« Afin de prévenir la propagation du virus covid-19, est interdit jusqu’au 31 mars 2020 le déplacement de toute personne hors de son domicile à l’exception des déplacements pour les motifs suivants, dans le respect des mesures générales de prévention de la propagation du virus et en évitant tout regroupement de personnes :

1° Trajets entre le domicile et le ou les lieux d’exercice de l’activité professionnelle et déplacements professionnels insusceptibles d’être différés ; »

Dans le cas contraire d’un déplacement pouvant être différé, et ce dans l’optique de protéger la santé de toutes et tous, le télétravail est très fortement recommandé, d’autant plus quand il peut rapidement être mis en oeuvre sur le plan technique.

A travers quelques résultats de recherche issus du moteur de recherche Shodan, nous allons constater qu’en plus des préconisations sanitaires simples diffusées à la population, la mise en œuvre de gestes barrières informatiques ne représente pas un luxe.

En ces temps de crise et de vulnérabilité(s) humaine(s) et organisationnelle(s), nous avons d’autant plus besoin d’assurer la bonne marche de nos équipements informatiques.

Shodan et le balayage de ports

Le balayage de ports est une technique servant à rechercher les ports ouverts sur un serveur de réseau.

Cette technique est utilisée par les administrateurs des systèmes informatiques pour contrôler la sécurité des serveurs de leurs réseaux. La même technique est aussi utilisée par les pirates informatiques pour tenter de trouver des failles dans des systèmes informatiques. Un balayage de ports effectué sur un système tiers est généralement considéré comme une tentative d’intrusion, car un balayage de ports sert souvent à préparer une intrusion.

On peut détecter le système d’exploitation et sa version par la prise d’empreinte de la pile TCP/IP. Certains logiciels permettent également de détecter le nom du logiciel écoutant sur un port, voire sa version.

A grande échelle, Shodan réalise cette opération de balayage de ports sur tout Internet, et indexe les résultats de recherche, mis à disposition des utilisateurs. Shodan interpole également les versions de logiciels trouvées avec les bases de vulnérabilités logicielles usuelles et mondialement utilisées en sécurité informatique. Utilisé de manière orientée, Shodan est un moteur de recherche de serveurs et d’équipements informatiques vulnérables.

BlueKeep

BlueKeep (CVE-2019-0708) est une vulnérabilité de sécurité découverte dans l’implémentation du protocole Remote Desktop de Microsoft. Elle permet d’exécuter du code à distance. Son score CVSS (évaluation standardisée de la criticité des vulnérabilités selon des critères objectifs et mesurables) est maximal : 10.

Par exemple, la vidéo suivante montre ainsi comment, via une attaque en déni de service exploitant BlueKeep, il est possible d’engendrer facilement le crash d’un poste Windows 7 :

Shodan et BlueKeep

Actuellement en France, au moins 4395 postes sont toujours à priori vulnérables à BlueKeep :

Pour pouvoir procéder à des recherches dans Shodan, il est nécessaire de créer un compte utilisateur. Cependant, via le modèle de lien suivant, il est possible d’avoir tout de même accès aux données du moteur de recherche :

https://www.shodan.io/host/aaa.bbb.ccc.ddd

(aaa.bbb.ccc.ddd étant l’adresse IP d’une machine qui a été scannée par Shodan et pour laquelle les résultats de recherche ont été indexés)

Pour une machine supposément vulnérable à BlueKeep (un scan de port ne dit pas tout !), l’élément suivant va s’afficher dans la fenêtre de présentation de résultat :

Lorsque cela est possible techniquement, Shodan présente également une capture d’écran associée au port scanné :

Vraisemblablement, sur cette machine, un utilisateur s’est connecté à distance depuis une machine Dell non personnalisée (voir aussi ici ).

Recherche d’informations sur la machine vulnérable

Via une recherche inversée sur l’adresse IP trouvée par Shodan, on arrive à retrouver le nom de la société qui utilise la machine concernée :

Sur societe.com, on retrouve l’entreprise en question, ainsi que la même adresse que celle mentionnée dans le résultat de viewdns.com :

Entre les mains de personnes malveillantes, on imagine aisément les dégâts qui peuvent être provoqués par la possession de telles informations, et d’autant plus en ce moment.

Geste barrière préconisé

METTEZ A JOUR VOTRE MACHINE !

Instagram : obtenir les infos d’un compte….

Instagram : obtenir les infos d’un compte….

L’amie @technisette a publié en juillet, sur le site Osint Curious, deux très bons billets sur les recherches possibles sur Instagram.
Une des astuces données concernait l’affichage des informations d’un compte au format Json dans le navigateur, en utilisant directement l’API du site.

Exemple :
https://i.instagram.com/api/v1/users/1034466/info/ pour obtenir les informations du compte de Starbucks devrait nous donner ceci :

{"user": {"pk": 1034466, "username": "starbucks", "full_name": "Starbucks Coffee \u2615", "is_private": false, "profile_pic_url": "https://scontent-cdg2-1.cdninstagram.com/vp/0e07d26e60e5b4598da83e18d6672315/5E1DA749/t51.2885-19/s150x150/54247905_1011601952363831_7925609498994016256_n.jpg?_nc_ht=scontent-cdg2-1.cdninstagram.com", "profile_pic_id": "2009724254929369404_1034466", "is_verified": true, "has_anonymous_profile_picture": false, "media_count": 1862, "follower_count": 18237408, "following_count": 3690, "following_tag_count": 0, "biography": "Inspiring and nurturing the human spirit -- one person, one cup, and one neighborhood at a time.", "external_url": "https://starbucks.app.link/scm", "external_lynx_url": "https://l.instagram.com/?u=https%3A%2F%2Fstarbucks.app.link%2Fscm\u0026e=ATNJawA5OtI3O7vco1wUa4fc1fLWc4KBhCcKY2jbbC5DVIcNtS-GmZVb40iCqnvpS8H05o_ANTUbGFcZkfi4ivEy7B6aSRc", "total_igtv_videos": 1, "has_igtv_series": false, "total_ar_effects": 0, "usertags_count": 2200976, "is_favorite": false, "is_favorite_for_stories": false, "is_favorite_for_highlights": false, "is_interest_account": true, "hd_profile_pic_versions": [{"width": 320, "height": 320, "url": "https://scontent-cdg2-1.cdninstagram.com/vp/b447438839ebcb82a485046cd1977143/5E1FC931/t51.2885-19/s320x320/54247905_1011601952363831_7925609498994016256_n.jpg?_nc_ht=scontent-cdg2-1.cdninstagram.com"}, {"width": 640, "height": 640, "url": "https://scontent-cdg2-1.cdninstagram.com/vp/68053010283eec0a0f078c612629be6e/5E24F18A/t51.2885-19/s640x640/54247905_1011601952363831_7925609498994016256_n.jpg?_nc_ht=scontent-cdg2-1.cdninstagram.com"}], "hd_profile_pic_url_info": {"url": "https://scontent-cdg2-1.cdninstagram.com/vp/848fb88682d02055ef3285373e567810/5E387C31/t51.2885-19/54247905_1011601952363831_7925609498994016256_n.jpg?_nc_ht=scontent-cdg2-1.cdninstagram.com", "width": 1080, "height": 1080}, "mutual_followers_count": 0, "has_highlight_reels": true, "can_be_reported_as_fraud": false, "direct_messaging": "UNKNOWN", "fb_page_call_to_action_id": "", "address_street": "", "business_contact_method": "CALL", "category": "Marque", "city_id": 0, "city_name": "", "contact_phone_number": "+18007827282", "is_call_to_action_enabled": false, "latitude": 0.0, "longitude": 0.0, "public_email": "", "public_phone_country_code": "1", "public_phone_number": "8007827282", "zip": "", "instagram_location_id": "22092443056", "is_business": true, "account_type": 2, "can_hide_category": true, "can_hide_public_contacts": true, "should_show_category": true, "should_show_public_contacts": true, "should_show_tabbed_inbox": false, "is_facebook_onboarded_charity": false, "has_active_charity_business_profile_fundraiser": false, "charity_profile_fundraiser_info": {"pk": 1034466, "is_facebook_onboarded_charity": false, "has_active_fundraiser": false, "consumption_sheet_config": {"can_viewer_donate": false, "currency": null, "donation_url": null, "privacy_disclaimer": null, "donation_disabled_message": "Nous rencontrons des probl\u00e8mes de connexion. Veuillez renouveler votre don plus tard.", "donation_amount_config": null}}, "include_direct_blacklist_status": true, "is_potential_business": true, "is_bestie": false, "has_unseen_besties_media": false, "show_account_transparency_details": true, "auto_expand_chaining": false, "highlight_reshare_disabled": false, "show_post_insights_entry_point": false, "about_your_account_bloks_entrypoint_enabled": false}, "status": "ok"}

Certaines infos ne sont pas forcément visibles sur la page d’accueil du profil.

Toutefois, depuis plusieurs jours, le lien ci-dessus ne donne aucun résultat :

Comment retrouver simplement cette granularité d’information?

Vous avez dit « useragent« ?

Le useragent, c’est l’identifiant de votre navigateur. Il indique en général votre système d’exploitation (windows, mac, Linux, Android, iOS…), sa version, etc…

Si vous voulez connaître le vôtre, vous pouvez demander à https://www.whatsmyua.info/

Le mien est le suivant :


La bonne ou la mauvaise nouvelle (selon que l’on est un bon analyste ou un méchant pirate…), c’est qu’un useragent, cela se modifie (on dit en anglais que cela se spoofe) : soit directement dans les paramètres du navigateur, soit en utilisant une extension telle que User-Agent Switcher.

Si Instagram nous dit qu’il y a une erreur de type « useragent mismatch« , c’est que notre user-agent ne correspond pas à celui attendu par le site.

En effectuant une recherche sur Google du type « Instagram official user-agent », on découvre le site internet WhatsmyBrowser.com qui recense les user-agents utilisés un peu partout sur internet.

Notez la présence de la référence Instagram 72.0.0.21.98 dans le premier de la liste des user-agents référencés…

Et si on ajoutait cette référence à notre propre navigateur?!

Nous ouvrons dès lors l’extension User-Agent Switcher :


Et nous collons la référence Instagram 72.0.0.21.98 à la suite de notre chaîne de caractères correspondant à notre user-agent et nous validons an cliquant sur Apply :

Et voilà!!!

Il suffit de rafraîchir la page Instagram pour récupérer les informations du compte!

P.S. : Nous vous rappellons qu’il est possble d’obtenir le numéro d’identifiant utilisateur d’un compte en ajoutant /?__a=1 à la suite de son URL :

https://www.instagram.com/nom-compte/?__a=1

Firefox (IV) – Sécuriser un peu plus sa navigation

Firefox (IV) – Sécuriser un peu plus sa navigation

Les extensions pour Firefoxpour l'OSINT sur OpenFacto

Si par construction Firefox présente d’emblée un niveau de sécurité intéressant, et prend de même soin de notre vie privée un peu mieux qu’un autre navigateur, il est toutefois possible d’affiner un peu plus encore ses réglages pour des recherches en Sources Ouvertes.

Il s’agit là de quelques conseils qui ne prétendent pas à l’exhaustivité mais qui permettent d’ajouter une petite couche supplémentaire à votre navigation.

Ce billet est le quatrième billet d’une série sur le navigateur Firefox.

Les profils utilisateurs ou comment séparer ses différentes activités…

La première règle essentielle de prudence et de sécurité à appliquer serait de séparer complètement ses activités de surf personnel et celles dédiées à l’OSINT. Or, l’expérience montre que c’est en fait une règle très difficile à respecter au quotidien.
Tout le monde ne dispose pas d’un poste internet dédié à ce seul usage (idéal!), ou des ressources matérielles (ou des compétences techniques…) pour faire tourner une machine virtuelle (VM) dédiée aux Recherches en Sources Ouvertes.

Une solution intermédiaire consiste à créer des profils utilisateurs distincts dans Firefox, chaque profil disposant dès lors de ses propres réglages, ses propres extensions, et par incidence, ses propres cookies, historiques de navigation, etc…

Dans Firefox, tapez about:profiles dans la barre d’URL.

Depuis cette vue, vous pouvez dès lors créer un nouveau profil utilisateur.

Vous pouvez également démarrer Firefox avec l’option -P ou --ProfileManager pour créer et gérer ces nouveaux profils.

Un tutoriel très explicite est disponible sur le site de la Fondation Mozilla.

A titre d’exemple, voici une stratégie de profils qu’il est possible de mettre en place, sachant que Firefox est capable de lancer un navigateur par profil sans aucun problème :

  • Un profil pour votre surf personnel
  • Un profil orienté OSINT/réseaux sociaux, dans lequel vous ferez évoluer vos avatars, qui de cette façon ne contamineront pas votre navigation habituelle…
  • Un profil orienté technologie, cyber…

Évidemment, vous adapterez la situation à votre propre cas.

Paramétrage du DNS-over-HTTPS (DoH)

Un serveur DNS est un serveur qui, pour faire simple, se comporte comme un gros annuaire qui traduit une adresse de nom de domaine (ex : liberation.fr) en son adresse IP (85.118.46.182).

Un résolveur DNS est un cache, un relais, géré le plus souvent par votre fournisseur d’accès, et qui redistribue les données des serveurs DNS vers les utilisateurs. C’est un intermédiaire, un tampon.

A chaque fois que vous tapez une URL dans la barre d’URL et que vous validez, une requête au résolveur DNS est donc adressée pour faire cette correspondance (En réalité, pas tout à fait, les navigateurs ont un système de cache, mais je simplifie…).

Par défaut, Firefox effectue cette requête en clair. Vous comprenez donc qu’à ce stade, votre fournisseur peut donc savoir quels sont les sites internet que vous fréquentez.
Pour assurer un peu plus de confidentialité à nos requêtes nous allons donc activer la fonctionnalité DNS-over-HTTPS (DoH) de Firefox, qui va noyer ses requêtes dans le trafic https de l’utilisateur, qui est lui chiffré.


Comment faire?

  • 1ère étape : Dans le menu Firefox, choisissez Outils, puis Préférences. ou tapez about:preferences dans la barre URL et appuyez sur Entrée.
  • 2ème étape : Dans la section Général (la section qui s’ouvre en premier), faites défiler vers le bas jusqu’au panneau Paramètres du réseau, puis appuyez sur le bouton Paramètres.

En bas de cet onglet, cochez la case « Activer le DNS via HTTPS« .

Par défaut, Mozilla envoie ces requêtes à CloudFlare (1.1.1.1), un serveur de DNS américain. C’est déjà pas mal, mais nous allons quant à nous utiliser ceux de Quad9 : https://dns.quad9.net/dns-query
Cette organisation propose des résolveurs DNS libres d’accès, récursifs et ouverts. Ils permettent notamment un accès plus aisé à certains sites filtrés par les opérateurs…. Stéphane Bortzmeyer avait chroniqué Quad9 sur son blog en 2017.

Attention toutefois : Comme S. Bortzmeyer le signale, Quad9 est un résolveur DNS « menteur » ce qui signifie qu’il bloque certains domaines signalés pour activité malveillante (ex : distribution de virus, malware…). Donc si l’objet de vos recherches est précisément l’étude de ces activités, il vous faudra choisir un résolveur non-menteur.

Votre navigateur est désormais paré pour le DNS via HTTPS.

Pour le vérifier, faites le test suivant.

DNSSEC Resolver Test sur OpenFacto.fr

Vérifions tout de même ces réglages dans les paramètres de Firefox en tapant dans la barre d’URL about:config.

Une fois passé le bouton de confirmation un poil anxiogène suivant :

Nous allons vérifier deux valeurs de clefs de paramétrage :

  • network.trr.mode

La valeur de la clef devrait être à 2 et non à 0 comme par défaut, ce qui signifie que vous requêtes DNS vont passer en priorité par DoH.

  • network.trr.uri

Ici la valeur devrait être https://dns.quad9.net/dns-query

Paramétrage de l’Encrypted Server Name Indication (ESNI)

Puisque nous sommes dans l’antre du about:config, nous allons activer par ce biais une nouvelles fonctionnalité, l’ESNI. Elle permet de cacher à votre fournisseur d’accès, le nom même des sites que vous visitez.

Cherchez la valeur suivante : network.security.esni.enabled et passez la à true.

Cookies

Deux actions peuvent être menées sur les cookies, qui sont activés par défaut sur Firefox :

  • Activer le blocage des cookies tiers, qui sont pour l’essentiel des cookies utilisés pour vous pister durant votre activités sur le net.

Cliquez sur le bouton de menu paramètre et choisissez Blocage de contenu. Le panneau Vie privée et sécurité des Préférences de Firefox s’ouvre. C’est l’endroit où vous pouvez examiner vos paramètres pour le Blocage de contenu, parmi lesquels ceux des cookies.

Pour bloquer les cookies : Sélectionnez Personnalisé et cochez la case Cookies.

Fx65Custom-ThirdPartyCookies

Traqueurs tiers est le paramètre par défaut pour le blocage des cookies.

  • Supprimer les cookies à la fermeture de Firefox

Pour supprimer tous les cookies et les données de site à la fermeture de Firefox :

  1. Cliquez sur le bouton de menu de Firefox et sélectionnez Préférences
  2. Sélectionnez le panneau Vie privée et sécurité et allez à la rubrique Cookies et données de site.
  3. Cochez la case Supprimer les cookies et les données des sites à la fermeture de Firefox.

À chaque fermeture de Firefox, les cookies enregistrés dans votre ordinateur sont supprimés.

Copier-Coller

Lorsque vous copiez/collez des données sur un site internet, celui-ci peut dans certains cas le détecter, vous empêcher de le faire ou substituer les données que vous essayez d’attraper…

Pour bloquer cela, allez dans le about:config, et cherchez la clef : dom.event.clipboardevents.enabled
Passez la à False.

Quelques ressources complémentaires

Cet article avait pour but de vous présenter quelques réglages intéressants pour la vie privée et ayant peu ou pas d’impact sur votre navigation.
D’autres réglages sont possibles. Bloquer le referrer, par exemple, sera sans doute très utile mais empêchera plusieurs sites de fonctionner….
Vous trouverez ci-après deux sites vous les listant :

Un dernier conseil, qui m’a sauvé la mise il y a quelques semaines de cela.

Utilisez Firefox Sync.

Firefox Sync permet de synchroniser vos onglets, vos favoris, votre historique, les préférences, les mots de passe, formulaires pré-remplis, les extensions (c’est paramétrable). Les données sont envoyées chiffrées sur les serveurs de la fondation Mozilla.

Vous pouvez récupérer instantanément votre environnement préféré lors de vos vacances chez Mamie, sur sa machine, mais également en cas de perte de votre ordinateur ou panne système.


Firefox (III) – Les outils de développement – Cas pratique – OSINT sur Zello

Firefox (III) – Les outils de développement – Cas pratique – OSINT sur Zello

Ce billet est le troisième billet d’une série sur le navigateur Firefox.

Nous avons vu dans la première de cette série d’articles sur les outils de développement web de Firefox (« dev tools » pour aller plus vite), comment ils pouvaient être utilisés de manière fine pour collecter de l’information en source ouvertes.
Nous vous proposons aujourd’hui un cas pratique complet d’utilisation de ces outils sur le site internet Zello.com.

Qu’est-ce que Zello?

Zello est une application pour téléphone mobile ou tablette Android et iOS transformant ces derniers en Talkie-Walkie : un gros bouton push-to-talk, un canal public ou privé que vous créez à volonté… Vous voilà équipé de petites radios mobiles à portée mondiale, de très bonne qualité audio, très utiles lors de vos déplacements en famille, par exemple. Les communications, audio ou texte, transitent via le réseau internet.

Cette facilité d’emploi en a fait un réseau également très utilisé lors des conflits par les populations civiles, les groupes armés (au Dombass par exemple), ou les services d’urgences (Casques blancs en Syrie…).

Les chaînes (channel) publiques sont susceptibles d’héberger des messages audio librement accessibles au public et donc de fournir des informations de contexte assez précieuses pour la recherche en sources ouvertes. Mais travailler en OSINT sur le site de Zello n’est pas une sinécure.
Voilà pourquoi les dev tools de Firefox vont nous aider.

Chercher de l’information sur Zello.

Pour cet exemple, nous nous intéressons à la région d’Idleb (Syrie), qui fait l’objet d’une intense campagne de bombardements par le régime syrien et les forces russes depuis plusieurs mois.

L’idée de départ, notre postulat, est que l’application Zello est peut-être utilisée par les secouristes, la population, ou les combattants et que peut-être, nous pouvons récupérer de l’information importante via des bribes de conversation audio.

Zello ne dispose pas d’un moteur de recherches très puissant et qui plus est, ce dernier est plutôt bien caché!

Nous allons donc utiliser un GoogleDork, une requête un peu spécifique, pour rechercher des chaînes en lien avec le secteur d’Idleb.


Les utilisateurs locaux utilisent l’arabe, il nous faut donc contextualiser la recherche en utilisant la graphie arabe de la ville.


إدلب site:zello.com

La recherche renvoie environ 150 résultats mais pour un aspect pratique et concret, nous nous intéressons aux chaînes récentes (moins de trois ans) et comportant si possible un nombre important d’abonnés (subscribers).

La chaîne مرصد ابو عرب سراقب (Observatoire Abu Arab Saraqeb) est particulièrement intéressante :

Créée il y a trois mois environ, elle regroupe déjà plus de 270.000 utilisateurs. Une traduction sommaire de la biographie du profil nous indique qu’il s’agit d’un poste d’observation militaire, destiné à la surveillance du trafic aérien. Le groupe dispose de trois administrateurs, et seize modérateurs, il est donc animé et vivant. Il s’agit d’un système d’alerte équivalent à Sentry Syria, à destination des populations civiles.
A ce stade, il serait déjà possible de s’abonner à cette chaîne sur l’application mobile, en respectant le cas échéant quelques précautions élémentaires (profil, burner phone, etc…).

Effectuons donc un archivage de cette chaîne susceptible de disparaître, sur Archive.Today et sur Archive.org.

Une question se pose : cette chaîne dispose-t-elle de messages publics accessibles sur son site?

L’URL de recherche sur Zello n’est pas facilement accessible.
Pour obtenir les derniers messages postés sur l’ensemble des canaux il faut utiliser cet outil :

https://zello.com/shared/#latest/1//////undefined

Notez la présence peu commune de multiples slashs sur cette URL…
Sur cette page, il est possible de rechercher par channel, par profil, par utilisateur ayant partagé un message. Il est possible de filtrer par langue.

Effectuons un recherche sur la chaîne مرصد ابو عرب سراقب.
Elle retourne une réponse paginées, par tranche de 10 messages, « plus de 1.000 enregistrements » selon le site. On le voit là aussi, la réponse du site est plutôt floue.

Lors de l’analyse d’un site, l’étude d’une URL est aussi très importante.

Cliquez sur le bouton Next. L’URL devient alors :

https://zello.com/shared/#latest/2/%D9%85%D8%B1%D8%B5%D8%AF%20%D8%A7%D8%A8%D9%88%20%D8%B9%D8%B1%D8%A8%20%D8%B3%D8%B1%D8%A7%D9%82%D8%A8/////undefined

Juste après « #latest/« , le chiffre 1 a été remplacé par le chiffre 2 : la pagination est donc accessible simplement en incrémentant cette valeur de 1… Intéressant!

Pour chaque message, les informations disponibles a priori sont les suivantes : nom de l’utilisateur à l’initiative du message, durée du message, chaîne, heure approximative et nombre de lecture dudit message. Pour l’instant, c’est assez vague.
Lorsque l’on clique sur un des messages, apparaît alors le lecteur suivant :

S’il est possible de lire le son, cette première séquence ne permet pas d’aller beaucoup loin dans la recherche, alors même que l’on dispose d’une banque audio visiblement assez conséquente. Plutôt frustrant donc!

Les dev tools à la rescousse!

Ouvrons les dev tools de Firefox, et notamment l’outil Réseau, (CTRL+MAJ+E), sur la page de recherches de la chaîne et réactualisons la page.

En filtrant les requêtes réseau, on constate que le site est assez surchargé de liens vers les réseaux sociaux Facebook, Google, Twitter, Linkedin, etc…
Autant le dire tout de suite, Zello est très gourmand en matière de données personnelles… Heureusement, le Plugin uBlock bloque l’essentiel de ces requêtes…

A ce stade, filtrons ces requêtes en ne gardant que celles au format XHR, prenons la première URL et observons son contenu dans l’onglet « réponse » à droite.

Bingo!
Nous constatons que les dix premiers résultats sont envoyés grâce à un fichier Json contenant l’ensemble des informations (metadonnées), des messages.
Comme dans le premier volet de cette série d’articles sur Firefox, nous cliquons sur cette URL en tant que cURL avec le bouton droit et exportons son contenu dans un terminal, au format Json (le > zello.json à la fin).

curl 'https://zello.com/shared/-/latest/1/%D9%85%D8%B1%D8%B5%D8%AF%20%D8%A7%D8%A8%D9%88%20%D8%B9%D8%B1%D8%A8%20%D8%B3%D8%B1%D8%A7%D9%82%D8%A8/////undefined' -H 'User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0' -H 'Accept: /' -H 'Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3' --compressed -H 'Content-Type: application/x-www-form-urlencoded' -H 'X-Requested-With: XMLHttpRequest' -H 'DNT: 1' -H 'Connection: keep-alive' -H 'Referer: https://zello.com/shared/' -H 'Cookie: __cfduid=de2c760986dd4346c968fb357057eb0ef1565680803; PHPSESSID=ea80d5b5aab44ac731725ea949d93851' -H 'Cache-Control: max-age=0' -H 'TE: Trailers' --data 'nonce=9qyne6zvzcv02xmbbl95q5xgjg63p412n491shpfgfs24zr64a5yahv5v6u7f4wl' > zello.json

Il est possible de transformer facilement ce fichier en un fichier tabulaire (csv ou xls) avec un outil tel qu’OpenRefine. Pour l’exemple ci-dessous, certaines colonnes inutiles ou redondantes ont été retirées.

zello-json.csv

1565817526Q7yjr081KxhQabo asad assafhttps://s3.amazonaws.com/zello.sharedmessages/Q7yjr081KxhQ08/14/2019 16:18:46 Android 4.65abo asad assafar15658174841565817527
1565793585UxmZEqic5jMgshhehdhdhdhhttps://s3.amazonaws.com/zello.sharedmessages/UxmZEqic5jMg08/14/2019 09:39:451Android 4.65shhehdhdhdhar15657935431565793585
15657935314sDN5fB4RK3Snor nortvhttps://s3.amazonaws.com/zello.sharedmessages/4sDN5fB4RK3S08/14/2019 09:38:51Android 4.64nor nortvar15657934381565793532
1565793477EdqnvlAwFY5qzzddrreewwhttps://s3.amazonaws.com/zello.sharedmessages/EdqnvlAwFY5q08/14/2019 09:37:57Android 4.65zzddrreewwar15657933441565793477
1565793436SD9FMXQID33iahmad.tec200https://s3.amazonaws.com/zello.sharedmessages/SD9FMXQID33i08/14/2019 09:37:16Android 4.69ahmad.tec200en15657934121565793437
1565779734xoanwLa4F36Odgdytuhttps://s3.amazonaws.com/zello.sharedmessages/xoanwLa4F36O08/14/2019 05:48:548Android 4.65dgdytuar15657780851565779734
1565727084g2she5inRHo2ytrewqjhgdaahttps://s3.amazonaws.com/zello.sharedmessages/g2she5inRHo208/13/2019 15:11:24Android 4.67ytrewqjhgdaaar15657268611565727084
1565698368BI5F4jD63Ockahmdalomlahttps://s3.amazonaws.com/zello.sharedmessages/BI5F4jD63Ock08/13/2019 07:12:481Android 4.56ahmdalomlaar15656982971565698368
1565692805DePxegwqPJbOhasan.basid.jdihttps://s3.amazonaws.com/zello.sharedmessages/DePxegwqPJbO08/13/2019 05:40:05Android 4.67hasan.basid.jdiar15656926851565692805
15656399517wj3tUEXJga2xjssdjjdddhttps://s3.amazonaws.com/zello.sharedmessages/7wj3tUEXJga208/12/2019 14:59:112Android 4.67xjssdjjdddar15656392361565639952

Nous constatons qu’en réalité, les données librement disponibles sur l’application Zello sont beaucoup plus verbeuses que ce qu’il était possible d’imaginer au départ :
– L’horodatage de l’envoi est complet et lisible, la version du logiciel employé également…
– Mais surtout, ce fichier donne l’adresse directe de téléchargement du fichier audio, sur un serveur Amazon S3!

Nous disposons donc désormais d’une liste de fichiers téléchargeables, certes avec des noms apocryphes (ex : Q7yjr081KxhQ…), mais grâce au fichier csv obtenu via les Dev Tools de Firefox, nous disposons également d’une table de correspondance indiquant date, heure de la mise en ligne, ainsi que l’identifiant de l’auteur….

La suite?

L’objet de cet article est essentiellement de vous montrer, à l’aide d’un cas concret, comment les Outils de Développement Web du navigateur Firefox peuvent vous aider dans vos recherches en Sources Ouvertes.

Vous remarquerez que nous n’avons utilisé aucun outil miraculeux hormis Firefox mais qu’en suivant une démarche méthodique simple (Que cherche-t’on?, requête google adaptée, première analyse de page, archivage, analyse fine complémentaire via les dev tools….), nous avons pu remonter des informations essentielles à notre recherche,

Mais en plus de la collecte d’informations, ces outils ouvrent de nouvelles perspectives pour l’automatisation de cette collecte, dont voici quelques pistes :

  • Il paraît impossible a priori de déterminer facilement le nombre total de messages disponibles (« plus de mille » nous indique le site…). Toutefois, en remplaçant la valeur numérique dans l’URL par 100, 101 (etc…)


https://zello.com/shared/#latest/2/%D9%85%D8%B1%D8%B5%D8%AF%20%D8%A7%D8%A8%D9%88%20%D8%B9%D8%B1%D8%A8%20%D8%B3%D8%B1%D8%A7%D9%82%D8%A8/////undefined

et en observant le contenu affiché, il est possible de constater que le premier message a été posté il y a cinq mois (valeur numérique 101) :

  • Le corollaire de cette constatation, est qu’il est sans doute possible (spoiler : oui c’est possible!) de créer un script informatique simple (en Python, en Bash, en DOS, en R…), sous forme d’une boucle allant de 1 (première page), à 101 (dernière page), capable de récupérer en quelques minutes, l’intégralité des messages (1.010 à la date de rédaction de cet article) de cette chaîne Zello!
  • Enfin, disposer d’un gros millier d’adresses Amazon S3 permet également d’envisager de créer une boucle identique, capable d’aspirer facilement l’intégralité de ces données pour analyse et archivage….
  • Ces données peuvent être analysées de plusieurs manières : contenu des conversations (type d’aéronefs, bilan humains, géolocalisation des impacts….), statistiques sur la fréquence des observations qui donnent une idée de l’intensité des bombardements, et peuvent aider les enquêtes (citoyennes, journalistiques, judiciaires…) en livrant des éléments de contexte difficiles à recueillir d’une autre manière…

Ces pistes feront l’objet de petits articles supplémentaires ici-même dans quelques temps! 🙂