Le WordPress d'aujourd'hui, décodé pour les développeurs

Sécurité

Faire confiance à l’en-tête d’origine d’un webhook sans vérifier la signature

Un en-tête HTTP se falsifie en une ligne de commande. Pourtant, une intégration entière reposait uniquement sur sa valeur déclarée.

Par WordPress Développement • 4 mai 2023 • 4 min de lecture • Aucun commentaire
Faire confiance à l'en-tête d'origine d'un webhook sans vérifier la signature

Comparer un en-tête HTTP déclaré à une signature cryptographique vérifiée, c’est comparer une carte de visite posée sur un bureau à une pièce d’identité contrôlée par un tiers de confiance. L’une se fabrique en un instant, l’autre repose sur un secret partagé impossible à deviner. Un audit d’intégration a mis en évidence une confusion exacte entre ces deux niveaux de confiance.

Le point d’entrée REST recevant les webhooks vérifiait la présence d’un en-tête personnalisé, X-Origine-Plateforme, censé confirmer que la requête provenait bien du service partenaire attendu. Aucune signature, aucun secret partagé, aucune vérification cryptographique n’accompagnait ce contrôle.

Ce qu’on observe dans le code

Le gestionnaire de la route REST se limitait à ceci :

register_rest_route( 'integration/v1', '/webhook', array(
    'methods'             => 'POST',
    'callback'            => 'traiter_webhook_partenaire',
    'permission_callback' => function ( $request ) {
        return 'PartenaireCommandes' === $request->get_header( 'x_origine_plateforme' );
    },
) );

Le contrôle d’accès reposait entièrement sur la comparaison d’une chaîne de caractères transmise par l’appelant lui-même, dans un en-tête qu’il définit à sa guise. Rien, dans le protocole HTTP, n’empêche un client quelconque de définir cet en-tête à la valeur souhaitée avant d’envoyer sa requête.

Pourquoi c’est un problème

Un en-tête HTTP n’est jamais une preuve d’identité : il s’agit d’une information que l’appelant choisit librement de transmettre, exactement comme le corps de la requête. Le confondre avec un mécanisme d’authentification revient à ouvrir une porte sur la seule foi de ce que la personne qui frappe déclare être.

curl -X POST https://exemple.fr/wp-json/integration/v1/webhook \
  -H "X-Origine-Plateforme: PartenaireCommandes" \
  -H "Content-Type: application/json" \
  -d '{"commande_id": 4821, "statut": "remboursee"}'

Cette seule commande, exécutable depuis n’importe quel poste sans le moindre secret, suffisait à faire passer une requête forgée pour un webhook légitime. Le traitement associé modifiait directement le statut d’une commande en base, avec les conséquences comptables que cela implique.

L'essentiel à retenir : Un en-tête HTTP est une déclaration, jamais une preuve ; curl reproduit n'importe quel en-tête sans effort ; Une signature HMAC vérifiée reste la seule preuve d'origine fiable

Ce que révèle l’écart entre en-tête et signature

Une signature HMAC repose sur un secret partagé, connu uniquement des deux parties, utilisé pour calculer une empreinte du corps de la requête. Cette empreinte ne peut être reproduite sans connaître le secret, contrairement à un en-tête dont la valeur se lit et se copie à l’œil nu dans n’importe quel outil d’inspection réseau.

CritèreEn-tête déclaréSignature HMAC vérifiée
Qui définit la valeurL’appelant, librementCalculée à partir d’un secret partagé
Reproductible sans secretOui, immédiatementNon, cryptographiquement impossible
Protège contre le rejeuNonOui, si un horodatage est inclus

Quoi faire à la place

Le principe à retenir n’est pas la mécanique complète d’une vérification HMAC, déjà largement documentée par ailleurs, mais la hiérarchie de confiance à respecter : un en-tête peut servir d’indication de routage ou de contexte, jamais de preuve d’authenticité. Toute décision qui modifie une donnée métier doit s’appuyer sur une preuve que l’appelant ne peut pas fabriquer seul.

  • Ne jamais utiliser un en-tête arbitraire comme unique critère de permission_callback.
  • Exiger une signature calculée à partir d’un secret connu des deux parties, jamais transmis en clair.
  • Rejeter toute requête sans signature valide, y compris pendant une phase de migration ou de test.

Repère retenu de cet audit : si un attaquant peut reproduire un contrôle d’accès avec une seule ligne de commande, ce contrôle n’en est pas un.

En résumé

La confusion entre déclaration et preuve reste l’un des antipatterns les plus discrets d’une intégration webhook, précisément parce que le code correspondant compile, fonctionne en test, et semble raisonnable à première lecture. Elle ne se révèle qu’au moment où quelqu’un se donne la peine de reproduire la requête depuis l’extérieur, sans disposer d’aucun secret.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Partager :

À propos de l'auteur

WordPress Développement

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi