Cette semaine, nous allons parler du mode HTTP Callback. Plus particulièrement comment authentifier un YoctoHub et s'assurer qu'un intrus ne puisse pas insérer des données invalides dans votre système.
Imaginons que vous désirez mesurer la température, l'humidité et la pression dans différentes régions. Grâce aux Yocto-Meteo et au YoctoHub-Wireless-g, vous avez pu fabriquer plusieurs stations météo autonomes. Vous avez aussi réussi à configurer les YoctoHub-Wireless-g pour qu'ils utilisent le mode HTTP Callback et qu'ils se connectent sur votre script PHP (www.exemple.com/http_callback.php) toutes les heures.
Pour différencier les stations météo, vous passez un lieu à votre callback en paramètre sur l'URL. Par exemple Le YoctoHub qui effectue des mesures à Cartigny utilisera l'URL www.exemple.com/http_callback.php?location=Cartigny
Configuration du YoctoHub pour la commune de Cartigny
Votre code doit probablement ressembler à celui-ci:
if(YAPI::RegisterHub('callback', $errmsg) != YAPI_SUCCESS) {
print("Unable to start the API in callback mode ($errmsg)");
die();
}
// retrieves the location
$location = $_GET['location'];
...
$tempSensor = YTemperature::FirstTemperature();
$humSenor = YHumidity::FirstHumidity();
$pressSensor = YPressure::FirstPressure();
if ($tempSensor && $humSenor && $pressSensor) {
$temp = $tempSensor->get_currentValue();
$hum = $humSenor->get_currentValue();
$pre = $pressSensor->get_currentValue();
$timestamp = time();
mysql_query("insert into weather "
. "(timestamp,temperature,humidity,pressure, $location) "
. "values ($timestamp,$temp,$hum,$pre,$location)");
}
...
Ce code fonctionne très bien, il est du reste très semblable à celui que nous avons utilisé dans un précédent article :-)
Cependant, il n'est pas possible de détecter si un intrus essaie d'uploader des fausses mesures! N'importe qui qui connaît l'URL de votre callback peut se connecter et ajouter des mesures.
Pour palier à ce problème, examinons plusieurs solutions:
- Vérifier le numéro de série du ou YoctoHub-Wireless-g dans le script PHP.
- Activer l'authentification HTTP sur votre serveur PHP
- Utiliser une signature MD5
Vérifier le numéro de série
C'est la méthode la plus simple: Il suffit de maintenir une liste avec les numéros de série des modules Yoctopuce utilisés et ignorer ceux qui sont inconnus.
Dans l'exemple suivant, on récupère le numéro de série du capteur de température et on vérifie que le numéro de série fait partie de nos capteurs.
if (!validate_serial($serial)) {
print("Unknown serial number: You are a hacker!");
die();
}
Malheureusement, cette solution n'est pas très robuste. Si quelqu'un intercepte une communication, il peut trouver le numéro de série dans le contenu envoyé par le YoctoHub-Wireless-g et ensuite l'utiliser pour contourner votre test.
L'authentification HTTP
L'authentification HTTP permet de s'identifier auprès du serveur HTTP en utilisant un nom d'utilisateur et un mot de passe. Ce mécanisme n'est pas géré par la librairie Yoctopuce mais par le serveur web. La méthode pour configurer la liste d'utilisateur et des mots de passe HTTP dépend du serveur web que vous utilisez, mais la plupart des hostings proposent une interface web qui permet très facilement d'effectuer cette tâche.
Une fois que vous avez configuré votre serveur pour protéger votre script de callback à l'aide d'un nom d'utilisateur et d'un mot de passe, il faut configurer les YoctoHub-Wireless-g pour qu'ils utilisent ces identifiants. Dans la fenêtre de configuration du callback HTTP, il suffit de sélectionner "HTTP Authentication" et de remplir le champs "utilisateur" et le champs "mot de passe".
Exemple de callback HTTP qui utilise l'authentification HTTP
Lors de la prochaine exécution du callback, le YoctoHub-Wireless-g va s'authentifier auprès du serveur web et poster les nouvelles valeurs. Si le YoctoHub-Wireless-g ne possède pas le bon mot de passe, le serveur web rejettera la connexion avant même d'avoir lancé votre script PHP.
Contrairement à la solution précédente, le mot de passe n'est jamais transmit au serveur (sauf si vous utiliser l'authentification "HTTP basic"). Ainsi même si quelqu'un écoute le trafic réseau entre une station météo et votre serveur il ne peut pas trouver le mot de passe.
Ce système permet aussi d'attribuer un nom d'utilisateur et un mot de passe différent pour chaque station météo. Ce qui évitera de devoir changer la configuration de toutes les stations météo si un mot de passe est découvert.
L'authentification HTTP propose un bon moyen de identifier un client sur un serveur web, mais elle reste sensible au attaque de type "man in the middle attack".
La signature MD5
La troisième méthode pour authentifier un YoctoHub sur un serveur est la signature MD5. Contrairement à l'authentification HTTP, ce mécanisme utilise uniquement un mot de passe connu des deux parties. Dans ce mode, le YoctoHub-Wireless-g signe le contenu qu'il envoie à l'aide de l'algorithme MD5. La signature MD5 est calculée sur le contenus envoyé ET sur un mot de passe du Hub. Quand la librairie Yoctopuce traite ce contenu, elle calcule la signature MD5 sur les données reçu ET sur le mot de passe de la libraire. Lors de l'appel YAPI.RegisterHub, la libraire vérifie que cette signature correspond à la signature transmise par le Hub, si ce n'est pas le cas, elle retourne une erreur. Le mot de passe n'est jamais transmit sur le réseau, chaque partie utilise son propre mot de passe.
Chaque partie signe le contenu avec son mot de passe
Pour activer la signature MD5 sur le YoctoHub-Wireless-g, il faut sélectionner "MD5 signature" comme type de sécurité et saisir le mot de passe dans la fenêtre de configuration du callback HTTP.
Exemple de callback HTTP qui utilise la signature MD5
Du côté sur serveur, le mot de passe est passé lors de l'appel YAPI.RegisterHub avec la syntaxe "md5:mot_de_passe@callback". Par exemple, pour vérifier la signature avec le mot de passe "MyPaSSW0rD" il faut utiliser le code suivant:
print("Unable to start the API in callback mode ($errmsg)");
die();
}
Le fait de calculer la signature MD5 sur tout le contenu transmit au serveur offre certains d'avantages. Cela permet de détecter une éventuelle corruption des données durant la communication. Il est possible de détecter une "attaque par rejeu" car tous les modules Yoctopuce postent leur horloge interne: La signature MD5 est donc automatiquement datée.
Avec un peu d'astuce, il est possible d'utiliser un mot de passe différent pour chaque YoctoHub. Comme tout le contenu de la requête est signé, il est possible d'ajouter des paramètres supplémentaires dans l'URL. Pour reprendre l'exemple des stations météo, il est possible de définir un mot de passe unique pour chaque station météo et d'utiliser le lieu qui est passé sur l'URL pour trouver le mot de passe correspondant. Dans cet exemple, la fonction get_pass_from_location interroge la base de données pour obtenir le mode passe à utiliser pour le lieu de la station météo.
$passwd = get_pass_from_location($location);
if(YAPI::RegisterHub('md5:'.$passwd.'@callback', $errmsg) != YAPI_SUCCESS) {
print("Unable to start the API in callback mode ($errmsg)");
die();
}
Et la confidentialité?
Jusqu'à présent nous avons parlé d'authentification et non d'encryption. En effet, pour l'instant nos modules ne permettent pas de crypter le contenu transmis. L'ajout du support HTTPS aux normes de sécurité actuelles serait trop volumineux pour être ajouté en l'état dans nos modules, et imposerait d'autres sacrifices plus pénalisant.
Dans les fait, la protection de la confidentialité des mesures transmises par callback est rarement une priorité. Dans les rares cas où c'est nécessaire, il existe de tous petits routeurs-VPN industriels qui peuvent avantageusement fournir un canal sécurisé permettant d'encrypter la totalité des communications, et offrir un bien meilleure sécurité qu'un support HTTPS très limité. Pour les cas ou une simple encryption serait néanmoins souhaitable, nous planchons sur une solution intermédiaire pour crypter le contenu qui n'exige pas un transport HTTPS complet.
Conclusion
Il est tout à fait possible de sécuriser la connexion entre un YoctoHub et votre code PHP. Les données transmisses entre les YoctoHubs et le serveur peuvent être écoutées, mais votre serveur sera protégé contre l'injection de données par des tiers.