Nous y voilà ! Comment sniffer l’HTTPS ? Et bien c’est possible… et voici comment !

0. Préambule

Sniffer le trafic HTTPS est plus compliqué : soit vous décryptez les trames SSL (ça peut prendre du temps…), soit vous vous faîtes passer pour le serveur. HTTPS chiffre toute la connexion, par conséquent il n’est pas possible de récupérer les URLs, ni même le nom de domaine vers lequel les requêtes sont envoyées, vous n’aurez que l’adresse IP, ce qui est bien mais insuffisant !

Alors comment récupérer les données qui passent à travers le SSL ? En redirigeant tout le trafic vers un serveur sur notre machine, déchiffrer, puis jouer le rôle d’un proxy pour finalement renvoyer les données au vrai serveur.

Dans cet article, on va essayer de lire ce qui se passe avec www.paypal.com

1. Sniffer le trafic du mobile

Vous pouvez vous référer à l’article précédent Sniffer le trafic d’un iPhone/Android avec Linux.

2. Quel domaine ?

Comme je l’ai dit, on ne peut pas retrouver quel domaine est interrogé par un webservice en lisant la trame SSL. Mais on peut regarder de quelle IP notre mobile a besoin !

Pour récupérer le nom de domaine, il suffit donc de regarder quelles sont les requêtes DNS qui passent, et de regrouper les adresses IPs données avec l’IP du trafic SSL.

En l’occurence, il s’agira de www.paypal.com.

3. Déchiffrer : stunnel

On va utiliser le fabuleux programme stunnel pour lire le trafic SSL.

stunnel est un programme qui permet en gros d’utiliser SSL pour les clients et les serveurs qui ne le supporte pas. On va donc déchiffrer / rechiffrer le trafic pour le lire en clair.

3.1 Stunnel 1 : accéder en clair à un serveur https

Iil faut configurer stunnel :

pid = /var/run/stunnel-client.pid
client = yes
[www.paypal.com]
accept = 127.0.0.1:50000
connect = www.paypal.com:443

Si vous allez sur http://127.0.0.1:50000/ et que vous acceptez le certificat, vous devriez avoir une page HTML en résultat, signe qu’on a bien été connecté avec paypal.

3.2 Rediriger le trafic SSL vers un serveur sans SSL

Il nous faudra un certificat autosigné, puis créez un fichier mondomaine.pem qui contient la clé et le certificat :

cat mondomaine.key mondomaine.crt > mondomaine.key

Ensuite, il faudra bien configurer stunnel :

pid = /var/run/stunnel-server.pid
client = no
cert = /path/to/www.paypal.com.pem
key = /path/to/www.paypal.com.pem
[www.paypal.com]
accept = 0.0.0.0:50001
connect = 127.0.0.1:50000

Lancez stunnel avec ce fichier de conf : vous devriez pouvoir vous connecter sur https://127.0.0.1:50001/ en acceptant le certificat.

4. Rediriger le trafic provenant du mobile

Pour rediriger le trafic provenant du mobile vers notre serveur, il faut utiliser iptables :

$ iptables -t nat -A PREROUTING -d www.paypal.com -p tcp --dport 443 -j REDIRECT --to-ports 50001

Si vous allez depuis votre mobile sur https://www.paypal.com/, vous devriez avoir une alerte de certificat. Acceptez cette alerte : vous devriez avoir paypal.com, mais en passant par votre serveur.

5. Mais je ne vois toujours rien en clair…

Le trafic en clair passe sur votre localhost : utilisez donc wireshark sur cette interface…

6. C’est pour débugger une app et ça marche pas…

… parce que votre certificat n’a pas été validé par une autorité, et ne le sera jamais ! Envoyez le certificat .crt sur votre mobile (par email ?) et installez-le sur votre mobile 🙂

Générer un certificat autosigné, c’est générer un certificat pour un nom de domaine précis, sans que ce certificat ne soit valide aux yeux du navigateur. Néanmoins, ce certificat peut être importé dans une base de certificat, ce qui permet d’éviter les alertes de sécurité.

Il ne s’agit pas ici de sécurité, mais plutôt de générer un certificat pour un nom de domaine donné et de le faire accepté par un navigateur.

Le certificat doit comporter une clé privée

openssl genrsa -out mondomaine.key 1024

Et un certificat public

openssl req -new -x509 -days 365 -key mondomaine.key -out mondomaine.crt

C’est fini ! Quand on vous demande des champs, remplissez bien votre nom de domaine lorsqu’on vous demande le CN (Common Name, eg YOUR NAME).

Pour sniffer le réseau, nous allons transformer notre ordinateur sous Linux en routeur Wifi pour notre mobile.

Téléchargez le script sniff.sh, qui reprend toutes les étapes de ce tutorial, et modifiez-le à votre guise !

Avec ce système, l’ordinateur est connecté au réseau filaire pour Internet, et l’iPhone sera connecté à l’ordinateur via la carte réseau. Il est aussi possible de connecter l’ordinateur à Internet via wifi avec une deuxième carte réseau sans fil.

1. Désactivez votre gestionnaire réseau

Tous les gestionnaires réseaux ne sont pas capables de gérer plusieurs connexions réseau en même temps. Du coup, on désactive le gestionnaire réseau pour tout configurer manuellement (à l’ancienne !)

$ /etc/init.d/wicd stop
$ /etc/init.d/NetworkManager stop
$ ...

2. Votre connexion Internet

Réactivez votre connexion internet : si vous êtes en ethernet par exemple, vous pouvez exécuter dhcpcd eth0. Si vous êtes en Wifi, reportez-vous à la configuration de wpa_supplicant (mais vous aurez besoin d’une autre interface Wifi pour votre mobile !)

Ensuite, pour que votre ordinateur transfère les paquets, il faut activer le NAT :

$ iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE # Active le NAT : changez eth0 par le nom de votre interface réseau Internet
$ sysctl net.ipv4.ip_forward=1 # Active le routage des paquets via votre ordinateur

3. Votre connexion Wifi

Pour transformer votre ordinateur en routeur, il faut configurer le wifi et le DHCP (facultatif) pour aider votre mobile à se connecter.

Configuration du Wifi

On configure l’interface pour lui donner un nom Wifi, et une adresse IP :

$ iwconfig wlan0 mode ad-hoc # passage en mode ad-hoc : on autorise un autre device Wifi à se connecter avec nous
$ iwconfig wlan0 essid RouteurMobile # Nom de votre réseau
$ ifconfig wlan0 10.10.10.1 # L'adresse IP de votre carte réseau Wifi

Sans DHCP

Vous pouvez connecter votre mobile dès à présent pour utiliser votre réseau, mais il faudra alors lui donner les paramètres suivants :

  • IP : 10.10.10.2
  • Gateway/Passerelle : 10.10.10.1
  • Netmask : 255.255.255.0 (ou 255.0.0.0 si vous voulez – ça importe peu)
  • DNS : on va utiliser les DNS de Google : 8.8.8.8 et 8.8.4.4

Avec DHCP

Sinon, vous configurez votre routeur linux pour fournir ces paramètres via un serveur DHCP. Cela évite de rentrer manuellement sur le téléphone les paramètres de la connexion IP.

Pour ce faire, commencez par installer le serveur dhcpd. Ensuite, paramétrez comme suit votre fichier (/etc/dhcp/dhcpd.conf) :

option domain-name-servers 8.8.4.4, 8.8.8.8;
default-lease-time 600;
max-lease-time 7200;
subnet 10.10.10.0 netmask 255.255.255.0 {
  range 10.10.10.10 10.10.10.20;
  option routers 10.10.10.1;
}

Vous pouvez télécharger un exemple de fichier de conf dhcpd.

Puis démarrez votre serveur : /etc/init.d/dhcpd start

4. Connexion

Si tout s’est bien passé, vous verrez votre réseau créé sur votre mobile, et vous pourrez vous connecter dessus sans problème.

5. Sniffer avec Wireshark

Je vous propose d’utiliser wireshark pour sniffer le trafic.

Quelques filtres :

  • http : affichera les requêtes HTTP, mais uniquement les paquets de questions (GET, POST, …) et ceux de réponses (HTTP/1.0 200 Ok, …)
  • dns : les requêtes DNS
  • dhcp : utile pour débugger le trafic DHCP

Problèmes fréquents

  • Mon réseau n’apparait pas : vérifiez que la carte wifi de votre linux est bien configurée avec iwconfig et que l’interface est up : ifconfig wlan0 up
  • Je me connecte mais je n’ai pas l’icône wifi, et pas d’adresse IP ou une adresse IP en 169.254.* : votre serveur DHCP ne fonctionne pas. Relancez-le et vérifiez sa configuration.
  • Je suis connecté mais je ne vois rien dans Wireshark : vérifiez que vous avez sélectionné la bonne interface à écouter ! Aussi, utilisez votre iPhone pour aller sur Internet un peu 🙂

Ceci n’est qu’une étape vers un prochain article : sniffer des connexion HTTPS !

Ajout/enlèvement d’évènements sur des objets

En javascript, on peut aisément rajouter des évènements sur des objects en utilisant la méthode addEventListener et en supprimer avec removeEventListener.

Exemple : cliquez-moi

  1. function p712_onclick()
  2. {
  3.   alert('Vous avez cliqué sur moi');
  4.   // Suppression de l'évènement
  5.   this.removeEventListener('click', p712_onclick, true);
  6. };
  7. // Ajout de l'évènement
  8. document.getElementById('p712_ex1').addEventListener('click', p712_onclick, true);

Pour enlever l’évènement, il suffit d’appeler removeEventListener sur le même objet avec le même deuxième argument.

Les fonctions anonymes

Les fonctions anonymes vous evitent de déclarer une fonction dans votre scope : vous ne la déclarez que quand vous en avez besoin.

Exemple : cliquez-moi

Mais impossible de supprimer l’évènement, car si vous appelez removeEventListener avec le même code, l’interprêteur Javascript va créer un deuxième objet fonction effectuant le même code, à la volée.

  1. document.getElementById('p712_ex2').addEventListener(
  2.     'click',
  3.     function()
  4.     {
  5.       alert('Vous avez cliqué sur moi');
  6.       // Que mettre comme deuxième argument pour removeEventListener() ?
  7.     },
  8.     true
  9. );

Les fonctions anonymes nommées

Pour résoudre ce problème, il suffit de nommer la fonction anonyme.

Exemple : cliquez-moi

  1. document.getElementById('p712_ex3').addEventListener(
  2.     'click',
  3.     function anon712()
  4.     {
  5.       alert('Vous avez cliqué sur moi');
  6.       // Suppression de l'évènement  OK !
  7.       this.removeEventListener('click', anon712, true);
  8.     },
  9.     true
  10. );

Compatibilités avec les navigateurs

Et qui n’est pas compatible ? IE8 et les versions précédentes ! Donc ceci est surtout un memo pour le développement d’extensions avec Firefox, Safari et Chrome, et est très utile si (par hasard) vous écrivez un bootstrapped add-on.

Là je dois dire que ça m’a bien surpris ! En regardant les entêtes HTTP de booking.com, je suis tombé là dessus :

X-Recruiting: Like HTTP headers? Come write ours: booking.com/jobs

Ce qui veut dire : "Vous aimez les entêtes HTTP ? Venez écrire les nôtres : booking.com/jobs".

Y’en a qui ne manquent pas d’inventivité !

Comment lire les entêtes HTTP

  • avec wget : wget -S -O /dev/null http://www.booking.com/ ;
  • avec Firefox : ouvrez la console développeur (Ctrl+Shift+K ?) et tapez l’url du site dans la barre d’adresse. Cliquez ensuite sur la première requête GET ;
  • avec Chrome (et Safari ?) : ouvrez la console développeur webkit et tapez l’adresse du site dans l’onglet d’où vous venez.

Et en plus ça leur fait des liens externes (certes pas très pertinents en occurrence)…

Aujourd’hui, je voudrais parler de la propriété CSS :nth-child. C’est une pseudo-classe introduite dans CSS 3, et qui permet de sélectionner des noeuds en fonction du numéro de leur position en tant qu’enfant. C’est très pratique pour colorier les lignes d’un tableau par exemple.

Fonctionnalités


Cette pseudo-classe permet de sélectionner des éléments à partir du kème fils tous les p fils : selector:nth-child(pn+k). Les enfants dont la position est égale à une valeur définie par cette suite géométrique est sélectionné.

Exemple

Sélectionner une valeur pour la propriété nth-child :

  1. Karmelitt Tripel
  2. Kastel Brune
  3. Delirium Nocturnum
  4. Gulden Draak
  5. Chimay 500
  6. Malheur
  7. St-Bernardus 8
  8. Rochefort 10


Rien ne se met à jour ? Vérifiez que votre navigateur est compatible.

Explication

L’idée est de partir du noeud k, puis itérer de faire prendre à n les valeurs entre 0 et le nombre total d’enfants.

  • n : tous les enfants du premier au nème
  • 2n : tous les deux enfants à partir du 0ème, c’est à dire à partir du 2ème : 2, 4, 6… Ce sont les nombres pairs.
  • 2n+1 : tous les deux enfants à partir du 1er : 1, 3, 5… Ce sont les nombres impairs
  • n+2 : tous les enfants à partir du 2ème, ou encore tous sauf le premier
  • 3n+2 : tous les trois enfants à partir du 2ème : 2, 5, 8…
  • -n+2 : en descendant, tous les enfants à partir du 2ème : 2, 1 et c’est tout. Ce sont les deux premiers enfants.

Compatibilité


Hélas, comme toutes les propriétés CSS3 existantes, cette propriété n’est compatible qu’à partir de IE9+ (et bien sûr Firefox 3+, Chrome, Safari 4+… mais ça va sans dire !).

Netographie

L’abus d’alcool est dangereux pour la santé. A consommer avec modération.

Amazon propose un webservice de base de données simplifiée que se nomme SimpleDB, qui permet de stocker n’importe quelle information dans une base de données dans les nuages.

SimpleDB : base de données simplifiée

A l’opposé des bases de données relationnelles, SimpleDB propose juste de stocker des informations hétérogène dans une même table.

Si on devait faire un rapprochement avec les bases du type MySQL, ce serait celui-ci :

  • Amazon vous met à disposition plusieurs bases : en fait, ces bases sont les différentes régions pour lesquelles le service est disponible (Asie, Europe, East-US, …).
  • Dans cette base, vous pouvez créer jusqu’à 250 tables, appelés domain.

Au niveau des données, le système est un peu déroutant au début : pour stocker un objet, vous lui donnez un nom (Name) et ensuite une liste de paires clé/valeur (Attributes). Vous pouvez même donner plusieurs valeurs à un même attribut pour un seul objet.

Exemple de données

Considérons donc une liste de personnes, de dates de naissance et de diplômes : on pourra donc stocker des informations selon le schéma suivant :

  • Name => Jean, Attributes => { Age => 16, Diplome => Brevet des collèges }
  • Name => Paul, Attributes => { Age => 19, Diplome => { Brevet des collèges, Baccalauréat } }

SimpleDB et Select

La base de données est simplifiée à la fois au niveau de son format, mais aussi du select : on ne peut pas tout faire, notamment à cause de la structure du stockage.

Format des données

Les données n’ont pas vraiment de format. Elles sont stockées sous forme de chaine de caractère. Vous pouvez cependant continuer à stocker des données au format binaire sans soucis.

Comparaison

C’est là que les choses se compliquent (hélas !). La comparaison se fait selon le type d’objet que l’on compare, et dans notre cas SimpleDB va comparer des chaînes de caractères. C’est donc l’ordre lexicographique qui est de rigueur (équivalent de strcmp en ASCII).

Il faut donc formater ses données si l’on souhaite effectuer des comparaisons du type inférieur < / supérieur > :

  • Chaînes de caractères : pas de soucis ! 🙂
  • Nombres :
    • il faut qu’ils soient tous positifs – en rajoutant un offset (car l’ordre lexicographique ne pourra pas interprêter que -5 < -3, car pour lui ce serait équivalent ) 5 < 3 !). Pour cela, il faut ajouter un nombre à toutes les valeurs. Ce nombre doit être plus grand que la valeur absolue du plus petit nombre que l’on va rencontrer. Concrètement, si on stocke des nombres entre -1000 et 10000, on peut rajouter 1000 à tous les nombres stockés, et on aura des nombres entre 0 et 11000.
    • mais aussi faire du zero-padding, c’est à dire faire précéder les nombres que l’on enregistre par des zéros, car sinon on aurait 5 > 10 dans l’ordre lexicographique. Il faut donc que, au sens des chaines de caractères, les nombres fassent tous la même taille. Dans notre exemple précédent, il faut qu’ils fassent tous 5 caractères, pour avoir 00005 < 00010.
  • Dates : on peut utiliser un format timestamp, mais ce n’est pas recommandé car on a à la fois un format illisible, et en plus on tombe dans le cas des nombres. On peut utiliser des formats type MySQL ou ISO8601 qui respectent ceci : d’abord les années, puis les mois, les jours, les heures, les secondes, et tous le même timezone (par exemple +02:00 ou bien stocker en GMT) si l’on souhaite avoir cette précision. Exemple : 2011-11-30 10:00:00 < 2013-01-01 00:00:00.

SimpleDB Group By

Si vous avez besoin du group by ou des fonctions d’aggrégation qui vont avec (avg, sum, …), alors passez votre chemin : SimpleDB ne propose d’aggrégation. La seule fonction disponible dans ce registre est count().

Performances et temps réel

Les performances ne sont pas forcément au rendez-vous : je n’ai testé que des inserts simples dans une base quasiment vide, et les performances ne sont pas terribles : 500ms pour une insertion simple, 200ms si vous appelez votre script depuis une instance de serveur chez Amazon (EC2).

Par ailleurs, si vous avez besoin de l’information tout de suite après, SimpleDB n’est pas pour vous. Il peut se passer plusieurs secondes entre le moment ou vous faites une modification et le moment ou celle-ci est répliquée sur tous les serveurs : SimpleDB va donc vous retourner un résultat non modifié si votre appel suit de trop près.

AWS SimpleDB pour quelle utilisation ?

SimpleDB n’est donc pas fait pour toutes les utilisations, loin de là ! Mais on peut trouver des cas où SimpleDB se révèle être un bon choix : prix, taille du stockage, disponibilité (pas de problèmes serveur ou machine à gérer), redondance…

Il y a beaucoup de contraintes, comme on a pu le voir, et celles-ci ne sont pas toutes listées… Mais je trouve quand même ce système bien utile dans certains cas, notamment pour tout ce qui est log system : en effet, en général on stocke une information mais on n’en a pas besoin immédiatement, les requêtes se font sur des sous-ensembles bien déterminés. En plus, on peut stocker des attributs complètement hétérogènes dans la même base de données selon le type d’évènement que l’on désire logguer.

Aller plus loin

Référence Amazon AWS SimpleDB

Dans la série des jeux avec un très bon rapport prix/temps de jeu, toujours dans les puzzles, voici un deuxième exemple de ce qu’on peut réaliser : TrainYard.

TrainYard : un puzzle game sur les trains

TrainYard est un jeu dans lequel vous devez construire les routes qui vont permettre aux trains d’arriver à destination. Il y a plusieurs niveaux de complications :

  • La couleur d’un train est importante : le train d’une couleur doit arriver dans la gare de la même couleur ;
  • Il n’y a pas de collision de train : les trains peuvent se croiser ;
  • Si des trains se croisent, chacun voit sa couleur mélangée avec la couleur de l’autre. Si deux bleus se croisent, rien ne se passe. Si un bleu croise un jaune, les deux deviennent verts ;
  • Si deux trains se superposent, ils fusionnent et mélangent leur couleur ;
  • et pleins d’autres cas à décrouvrir : coloriage de train, duplication de train et retour aux couleurs primaires, etc.

Feedback

J’ai a-do-ré ce jeu : les niveaux sont bien sur de plus en plus complexes, et on se prend au jeu. On y passe des heures et pour le prix qu’on a payé (79 cts) c’est bien rentabilisé ! Les amateurs de puzzle-game vont être servis : un must-have !

Téléchargements

La version d’essai : TrainYard Express  (gratuite avec uniquement certains niveaux)
La version payante : TrainYard à 0,79€ à ce jour (avec tous les niveaux !)

A voir également

Aargon, un jeu de puzzle/réflexion pour iPhone et iPad avec des lasers, et encore des couleurs !

Introduction

Il y a en général besoin de 3 fichiers différents avec SSL : une clé privée pour le serveur (key ou pem), un certificat (cer ou crt) distribué au client pour le chiffrement SSL, et la chaine de confiance (chain ou txt)  qui consiste en une suite de certificats tous signés les uns par les autres, et qui permet ensuite de remonter à un certificat racine installé sur votre ordinateur.

Le script que je vous propose permet de vérifier si un certificat serveur SSL est valide, c’est à dire :

  • de vérifier que la clé privée correspond bien au certificat ;
  • de vérifier que la chaine de confiance est valide.

Fonctionnement du script

Pour vérifier votre domain example.com, il vous faudra les 3 fichiers mentionnés plus haut, c’est à dire :

  • example.com.key : la clé privée
  • example.com.cer : le certificat
  • example.com.chain.txt : la chaine de confiance

Le script va vérifier que la clé et le certificat ont la même signature (avec l’argument -modulus de openssl), et vérifier le certificat avec la commande openssl verify.

 Le script

  1. #!/bin/sh
  2.  
  3. DOMAIN="$1"
  4.  
  5. [ -z "$DOMAIN" ];
  6.   "Usage : "$( "$0")" domain" >&2
  7.   "  Will check if \$domain.key, \$domain.cer and \$domain.chain.txt are correct" >&2
  8.   1
  9.  
  10. # Check key and certificate modulus
  11. KEY_MOD=$(openssl rsa  -noout -modulus - ${DOMAIN}.key | openssl md5)
  12. CER_MOD=$(openssl x509 -noout -modulus - ${DOMAIN}.cer | openssl md5)
  13.  
  14. [ "${KEY_MOD}" != "${CER_MOD}" ];
  15.   "Error : key does not match certificate" >&2
  16.   2
  17.  
  18. # Check certificate consistency
  19. openssl verify -CApath /etc/ssl/certs -CAfile ${DOMAIN}.chain.txt ${DOMAIN}.cer | -q "^${DOMAIN}.cer: OK$"
  20. [ $? -ne 0 ];
  21.   openssl verify -CApath /etc/ssl/certs -CAfile ${DOMAIN}.chain.txt ${DOMAIN}.cer >&2
  22.   "Error while verifying certificate chain" >&2
  23.   3
  24.  
  25. "Success"
  26. 0
  27.  

Télécharger le script

Les extensions sur Safari Mac OS X et Windows

Depuis quelques temps, Safari a sorti une API qui permet de faire des extensions. Les extensions sont  officiellement disponibles depuis Safari 5.0, à travers une API Javascript, qui se comporte à peu près comme l’API des extensions pour Chrome. Une nouvelle couche (principalement d’évènements) a été ajoutée à cette API depuis Safari 5.1, et ça, ça change tout ! En effet, on peut désormais catcher les évènements qui concernent les chargements des pages. Ca peut paraître anodin, mais dans le cas de certaines extensions, c’est vital !

Malheureusement, ce système d’extension est beaucoup moins permissif que l’ancien système… enfin quand je dis ancien système, je parle d’une méthode barbare consistant à charger son code et à redéfinir différentes fonctions de l’exécutable Safari… autant dire énormément de reverse engeneering à faire pour un module non portable et qui risque de ne plus marcher avec les versions suivantes, voire de faire planter complètement Safari !

Aperçu des possibilités

Les principales fonctionnalités sont là :

  • faire un bouton dans la barre d’outils (mais pas en couleur, juste en noir et blanc… merci Apple…) ;
  • exécuter des scripts dans une page, au chargement ou à la demande ;
  • faire des menus personnalisés (selon un certain standard : icone, texte, action/sous-menu) ;
  • et surtout, faire une barre d’outils en HTML (certes, il n’est possible d’utiliser que la hauteur de la barre, donc il est impossible de faire des menus, mais c’est déjà bien !)

La completion automatique de l’API

Le gros problème lorsque l’on utilise ce genre d’API, c’est que la completion automatique dans les éditeurs est rarement au rendez-vous.

J’ai donc généré un fichier Javascript qui décrit la variable globale safari, en utilisant JSDoc.

Cliquez ici pour télécharger le fichier javascript (v5.1), pour l’ajouter ensuite à votre éditeur.

Plus d’informations sur les extensions Safari

Vous trouverez plus d’informations sur les extensions Safari sur le site dédié aux développeurs Apple, avec principalement deux documents réellement complémentaires :