mar 16

Bon j’en ai un peu marre du sujet « sécurité Magento » pour le moment. On en a beaucoup parlé, on a apporté des idées et des solutions mais j’aimerai repartir sur autre chose. C’est vrai quoi, j’ai fait 10 ans de test d’intrusion, pour me changer les idées, je pars sur du web commerce, un petit retour au système & réseau, bref on s’aère le neurone et là, hop, XSS, CSRF etc…

Donc, aujourd’hui : les inclusions de contenus tiers !

Un petit schéma pour aider à comprendre (quoique… J’ai jamais été très fort en dessin. J’ai été en classe de dessin parce que la plus belle nana du collège faisait dessin, pas réellement pour mon talent en fait). Bref, je m’égare, donc ci-dessous, un site standard, au milieu. Au dessus un bandeau de pub qui vient d’une régie publicitaire, à droite un flux RSS et en bas, c’est de l’invisible, ce sont des inclusions dans le code source des pages.

inclusions de contenus tiers

Des inclusions, pour faire quoi ?

Eh bien rendre le site plus dynamique, ajouter un widget ou un flux rss, récupérer du contenu éditorial écrit par d’autre, collecter des statistiques, avoir un menu déroulant tout beau, que sais-je encore. Les inclusions de contenus tiers, c’est tout ce qui ne vient pas de votre serveur local, tout ce qui est appelé par des GET depuis d’autres serveurs. des moteurs de recherche de prix en Iframe, un bout de javascript qui fait une merveille ou une autre, un logo qui témoigne  de votre allégence éternelle à la horde, bref les exemple ne manquent pas.

Les plus classiques :

  1. Les bons vieux tags de statistiques et de télémétrie : Google analytics, Xiti etc…
  2. Le RSS qui provient d’un fournisseur de produits ou de nouvelles
  3. Les bouts de codes javascript copier/coller qui font un rollover jolie sur le menu ou des Jqueries toutes précodées
  4. Des CSS ou skins contenants des images venant d’ailleurs
  5. Les bandeaux publicitaires
  6. Les exports des données/commandes/info vers un tiers

En quoi cela peut-il ralentir mon site ?

Eh bien tout dépend du moment où ca se charge et de ce qui bloque ou ralentit.

Imaginons qu’un développeur ait mis dans les includes chargés en en-tête de page, le tag analytics. Imaginons ensuite que Google ne réponde plus (c’est rare) ou qu’il soit interdit d’y aller depuis le poste qui charge la page (je l’ai déjà vu, le proxy bloquait les IP google). Le résultat c’est que le code se chargeant au tout début de la page, la page ne charge plus. Elle va attendre le timeout par défaut (30 secondes) puis va finir par charger le reste…

En fin de page, c’est parfois moins génant, l’internaute a sa page, fait sa vie, le browser reste en cour de connexion mais au moins tout ce qui est déjà chargé est potentiellement fonctionnel.

Si on prend le cas d’un menu JS copié/collé, l’auteur peut avoir envie de savoir qui l’utilise et de se renvoyer un petit « ping ». A chaque fois que son menu est chargé par exemple, il fait un GET d’une page sur son site. Si son site est coupé, le menu ne charge pas, vous dépendez d’un tiers.

Votre centrale de publicité ou le fournisseur de votre skin peut aussi se mettre à ramer. En plus de votre chargement, vous ajouter sa latence de traitement à celle de votre page.

Ajax résoud partiellement le problème en effectuant ses requêtes en background, dans la machine virtuelle javascript du navigateur. Si un thread est planté, c’est moins grave, ent tout cas non bloquant visuellement.

Enfin, il ne faut pas oublier qu’appeler un contenu tiers, c’est ajouter la latence de la connexion entre votre client et vous à celle qui sépare votre client de toutes les sources tiers qui sont inclues. Par exemple, si ntre client [C] se connecte au serveur [S] qui sert une page où se trouve : un bout de javascript [J] qui fait un appel à l’extérieur, une régie pub [P] et un flux rss [R], ca nous donne :

[C] –> [S]        (latence entre le client et le serveur)
[S] –>[C]         (réponse du serveur au client, eh oui, le paquet TCP il repart pas avec ses petits pieds)
[C] —> [J]      (latence du client à la source de Javascript)
[J] –> [C]       (les petits pieds tout ca tout ca)
[C] —–> [P]  (latence du client à la régie pub)
[P] –> [C]       (les petits pieds…)
[C] -> [R]         (latence du client à la source RSS)
[R] –> [C]       (…)

Bonne nouvelles, les requêtes étant séquentielles, votre client encaisse toutes les latences et les additionne !
Votre latence qui était –> + –> (allez / retour client <—-> serveur) devient :
–>x2  +     —>x2   +   —–>x2 + ->x2
(serveur) (javascript)(régie pub)(rss)
Soit en équivalent « petits tirets » : —- devient ———————-
Si le tiret vaut 10 ms, on passe de 40 ms à 220 ms…
Le tout sans compter le chargement des contenus en eux même (le menu, les flux xml du rss, la JPEG de la banière)

Les navigateurs ne sont pas tous idiots et souvent ils demandent tout en même temps et traitent à l’arriver. Mais si c’est un point bloquant qui est en attente (le JS du menu par exemple) ca ne change rien, le client rame. Il faut donc choisir judicieusement les prestataires de ces contenus tiers (rapidité, disponibilité) et vérifier le comportement de son site s’il est isolé de ses « fournisseurs ». Pour cela, sous Linux rien de plus simple :

iptables -I OUTPUT -j DROP
wget http://localhost/

On interdit toute connexion à l’extérieur (iptables -I OUTPUT -j DROP), puis on faire une requête sur la homepage du site. Si ca charge rapidement, on est plutôt bien partit. Si ca bloque, c’est que l’on a une relation de dépendance ! Ca ne teste que la home mais vous pouvez le tester sur une sous page, de même si vous avez un virtualhost vous aurez peut être à remplacer « localhost » par son nom. Le DROP permet d’avoir un comportement comme si l’hote distant était indisponible. Si vous mettez DENY ou REJECT à la place, votre site aura une réponse « non » instantanée et ca ne sera pas réaliste.

Enfin, si votre site doit poster l’information qu’il a collecté, une vente par exemple et l’acheminer à votre système  SAP, à votre système de Stats, à votre système de livraison, si ce fameux système rame, ca va ramer aussi. Bon si c’est la livraison, c’est après le checkout donc le client a tendance à ne pas trop zapper votre site après avoir mis sa CB, mais avant…

Ok, ca peut faire ramer, mais est-ce potentiellement dangereux ?

Oui, bon je vous vois d’ici me dire : « Ah-Ah ! Ca va reparler de sécurité »

Pas du tout, enfin un peu. Mais c’est comme on dit à la blackhat du « Digital Self Defense », rien à voir avec la sécurité Cool
(Ah bah ça ma p’tite dame, la mauvaise foi, c’est un métier !)

Bon, c’est risqué ou pas alors ?
Bien sûr que c’est risqué, vous croyiez que j’avais mis le titre juste pour poser un smiley ?

Si votre fournisseurs de RSS met un bon gros bout de Javascript dans son flux ? Vous l’affichez ? Votre moulinette d’affichage est assez intelligente pour éviter d’afficher du code ? Sûr ? Et si ca se trouve, votre fournisseur de contenu RSS a une faille XSS qui permet à n’importe qui de poster du JS… Si si ca arrive les XSS :)

Et votre régie publicitaire ? Elle est sérieuse ? Ahhhhh bon. Donc elle lit le code des Flashs postés pour éviter les attaques par anti DNS pinning j’imagine et puis elle ne rame jamais. C’est comme Gmail, ca plante jamais ça monsieur !

Et le bout de Javascript copié/collé pour faire un beau menu qui déroule, en glissant sur un rollover de folie avec des animations subliminales ? Il a été relu ? Il ne fait aucun get/post nul part ailleurs ?

Comment éviter cela ?

Eh bien en premier lieu vérifier le taux d’autonomie / dépendance de votre site Web avec le test iptables -P OUTPUT DROP.

Si ca passe, vous êtes assez tranquille sur les ralentissements sinon il regarder l’appel qui fait ramer. Mesurer les temps de réponse de chacune de vos inclusions pour savoir si ils sont tous globalement bon. Ca dépend aussi du budget que vous avez mis dans votre développement. A 2 000 € le site, il y aura de la récupération de code, c’est fatal. A 15 000 ou plus, si un code javascript est copié/collé c’est clairement un peu abusé.

Sur la sécurité c’est une autre histoire. Prenez des prestataires connus, de confiances, aux performances régulières et vérifiables. Pour tout ce qui concerne le contenu qui sera directement affiché dans la page sans vérification (RSS par exemple) redoublez de prudence. Votre site affichera ce qu’on lui envoi, votre internaute lira ce que le site lui envoie.

Si le site qui est la source d’information est corompu, votre site est compromis, votre internautes sont compromis. C’est invisible et imparable, avec une iframe « invisible » (d’un pixel) qui contiendra le javascript malieux, l’utilisateur sera à la merci de l’assaillant. N’oubliez pas que Flash & Javascript disposent de fonctionnalités très puissantes permettant le pire comme le meilleur !

écrit par Philippe Humeau \\ tags: , ,


7 commentaires sur “Les contenus tiers peuvent ralentir ou compromettre un site.”

  1. 1. Gabriiiel Dit :

    Merci Philippe pour cet article qui pointe un souci croissant avec tous les outils sauce « web 2.0″, notamment addThis/ShareThis, dont les serveurs qui hébergent les JS ont parfois une réactivité qui laisse grandement à désirer.

    Tu parles de timeout par défaut à 30 secondes. Y’a-t-il un moyen quelconque pour le modifier ?

    :)

  2. 2. Pierre-Louis Dit :

    Merci pour cet article encore une fois très intéressant, décidément, je ne vais pas regretter ce flux RSS. Un grand bravo aux contributeurs.

    Concernant le timeout, oui, il y a des moyens. Le timeout se définit dans le fichier de configuration de php, le php.ini. On peut donc soit le modifier directement dans la config du PHP (ne pas oublier de redémarrer apache ensuite), soit le faire de manière programmatique en php.

    Un peu de doc à ce sujet :
    http://fr3.php.net/manual/en/info.configuration.php#ini.max-execution-time
    http://fr3.php.net/set_time_limit

    A noter que ce n’est justement pas recommandé pour une utilisation « normale » (je pense qu’on comprends assez, après cet article ce qui pourrait arriver si le timeout était à 600s…), et ne devrait à mon sens n’être autorisé que pour certains traitements (de fond souvent) nécessitant de monopoliser les ressources un moment. A noter que passer 30s, il y a peu d’utilisateur qui sont encore sur la page, personnellement, lors d’une recherche j’ouvre 5-6 onglets, et je lis ce qui vient, premier chargé, premier consulté…

    Pierre-Louis

  3. 3. Philippe Humeau Dit :

    Merci pour les encouragements ! Coté Timeout, le soucis c’est que le code exécuté serverside qui fait un appel à une ressource tiers peut être contrôlé, notamment par le biais du php.ini. Mais celui dans le brower du client, qui l’amène à télécharger auprès de tiers n’est pas paramétrable depuis le serveur. Si dans une page on a un include qui amène le client à télécharger une image ailleurs (un qui pointe vers un autre domaine par exemple), si ce domaine distant hébergeant l’image rame, le client rame.

  4. 4. Philippe Humeau Dit :

    On ne peut pas contrôler ce type de réaction du coté du client. Les browser settings le permettent parfois, sinon les réglages de la stack TCP/IP de l’OS (sous Linux notamment) mais sinon, c’est le fonctionnement normale d’une socket TCP ouverte par une stack IP. C’est le tarif ! Et comme le browser repose sur l’OS, il hérite de ses caractéristiques TCP/IP sauf s’il redéfinit cette valeur dans son cadre d’exécution. il existe plusieurs timeout différents selon les cas et les types de sockets, qui vont de 30s à 600s de mémoire (et encore ça dépend des O.S)

  5. 5. Gabriiiel Dit :

    Je me doutais bien qu’on pouvait le paramétrer côté serveur, ma question portait bien sur une possible modification côté client par quelque façon que ce soit (et du moins sans modification nécessaire de la part de l’user).

    Maintenant un exemple concret.

    Une image sur une page () mais l’image n’existe pas : retour d’un 404 not found pour l’élément, Firefox tente de le charger pendant 2.62s puis abandonne.

    Mais… une image en background, dans le css (donc pas dans le html !), mais l’image n’existe pas : retour d’un 404 not found oui… Mais Firefox tente de la charger pendant plus de temps que pour une image dans le html (x2 minimum).

    Techniquement… Pourquoi ? :)

  6. 6. Philippe Humeau Dit :

    Rahh vicieux comme question ! Je n’ai pas de vraie réponse mais je crois que ces timeouts sont dépendants du navigateurs puisqu’ils ne sont pas les mêmes entre IE7, FF3, Opera, chrome etc… Donc peut être que la différence viendrait de l’implémentation du chargement des CSS et des timeouts qui seraient différents entre ces browsers ? FF3 met peut être plus l’accent sur les images du CSS car sans elles le site risque d’être vraiment moche alors que juste une image dans le site parmi d’autres, ça gêne moins ?

  7. 7. Gabriiiel Dit :

    Sur le coup je ne sais pas sur quel critère va se baser FF pour considérer que tel élément est plus important qu’un autre.

    En tout cas c’est réellement pénalisant, même si l’on part quand même sur le principe qu’un élément est censé exister (et donc on est pas censé avoir de 404), si pour une raison d’optimisation on préfère un background css à une image html, il suffit que l’image manque pour avoir un gros ramage. A partir de 15 images css manquante, c’est tout juste si FF freeze pas… Et pourtant j’ai du matos :)

Poster une réponse