1 points par GN⁺ 2024-01-29 | 1 commentaires | Partager sur WhatsApp
  • Les journaux d’accès d’une IP publique auto-hébergée depuis plus de 10 ans révèlent des tentatives d’attaque courantes contre les services exposés à Internet, allant de la recherche d’identifiants à l’injection de commandes visant des équipements IoT
  • Le motif le plus fréquent était la recherche de fichiers de configuration et de répertoires via des chemins comme .env, .aws/credentials, .git/config, backup/, test/, et certaines requêtes utilisaient un User-Agent avec une faute comme Mozlila/5.0
  • Des tentatives de Shellshock essayaient de lire /etc/passwd en plaçant dans le User-Agent une payload sous forme de fonction Bash, tout en devinant de manière répétée plusieurs chemins CGI
  • Les attaques visant LuCI et Zyxel tentaient d’injecter des commandes dans l’interface web de routeurs et d’équipements embarqués afin de télécharger puis exécuter des scripts distants et des binaires pour plusieurs architectures
  • Il faut réduire au minimum ce qui est exposé sur l’Internet public, appliquer une authentification et des restrictions d’IP aux outils et répertoires nécessaires, maintenir les équipements IoT à jour et, si possible, les isoler du réseau public

Le trafic reçu par des services exposés sur l’Internet public

  • En pratiquant l’auto-hébergement depuis plus de 10 ans, l’auteur poursuit une démarche consistant à posséder directement ses données et à réduire la dépendance envers les plateformes autres que l’hébergeur cloud
  • Dès qu’une IP est exposée sur l’Internet public, une grande quantité de trafic malveillant arrive immédiatement, et les journaux d’accès permettent de retracer les attaques récentes
  • Cette analyse relève davantage de l’observation d’un développeur curieux que d’une investigation forensique menée par un expert en sécurité
  • Les adresses IP des attaquants ainsi que certaines expressions insultantes utilisées par eux ont été masquées par prudence

Recherche d’identifiants et de fichiers de configuration

  • L’attaque la plus fréquente consistait à chercher des identifiants via l’énumération de répertoires, avec de nombreuses requêtes visant notamment des fichiers .env
    • Exemples de chemins demandés : /laravel/.env, /backend/.env, /api/.env, /.env, //.env
    • .env est généralement utilisé pour stocker les secrets d’une application
  • Des fichiers liés à AWS et la configuration de dépôts Git faisaient aussi partie des cibles recherchées
    • Exemples : /aws.yml, /.env.bak, /info.php, /.aws/credentials, /config/aws.yml, /.git/config
  • Des répertoires courants susceptibles d’avoir été laissés par erreur étaient aussi sollicités de façon répétée
    • Exemples : /old/, /new/, /test/, /backup/, /temp/
  • Certains User-Agent contenaient Mozlila/5.0, qui semble être une faute de frappe de Mozilla/5.0
    • Les résultats de recherche GitHub suggèrent que cette faute a pu être générée par un outil courant puis copiée-collée
  • Des requêtes à la recherche d’outils d’accès distant ou d’outils de configuration ont également été observées
    • Exemples : /actuator/gateway/routes, /hudson, /ui/login.action, /?XDEBUG_SESSION_START=phpstorm
  • Il est nécessaire de n’exposer sur l’Internet public que le strict minimum indispensable et, si des outils ou répertoires doivent être exposés, d’ajouter une couche d’authentification ainsi que, si possible, des restrictions à certaines adresses IP

Tentatives Shellshock

  • Plusieurs requêtes semblaient viser la vulnérabilité Shellshock
  • Cette attaque cherche à exécuter des commandes arbitraires sur un serveur web qui lance des scripts CGI avec une version vulnérable de Bash
    • Au démarrage d’un programme CGI, des variables d’environnement sont définies à partir du contenu de la requête, et HTTP_USER_AGENT en fait partie
    • Si des caractères comme () { :; }; sont présents, Bash les interprète comme une fonction à exécuter
  • Dans les journaux réels, le User-Agent contenait des payloads comme les suivantes
    • () { ignored; }; echo Content-Type: text/html; echo ; /bin/cat /etc/passwd
    • () { ignored; }; est une définition de fonction au format Bash
    • echo Content-Type: text/html; echo ; affiche le Content-Type de la réponse HTTP suivi d’une ligne vide
    • /bin/cat /etc/passwd est la commande qui tente d’afficher le contenu de /etc/passwd, lequel contient des informations sur les comptes utilisateurs
  • Si l’attaque réussissait, elle pourrait mener à l’accès à des identifiants utilisateur et à l’exécution de code arbitraire sur le serveur
  • Comme pour l’énumération de répertoires, les attaquants devinaient des chemins courants tels que /cgi-bin/status, /cgi-bin/stats, /cgi-bin/test, /cgi-bin/status/status.cgi, /test.cgi, /debug.cgi, /cgi-bin/test-cgi

Injection de commandes visant LuCI

  • Une requête semblait viser LuCI, l’interface web des routeurs OpenWRT
  • L’URL d’attaque était structurée de manière à injecter une commande dans le champ country afin de télécharger puis exécuter le script shell distant tenda.sh
    • Après décodage de l’URL, la commande consiste à aller dans /tmp, supprimer des fichiers, récupérer le script avec wget, lui donner les droits d’exécution puis le lancer
  • Le script téléchargé contenait des instructions pour récupérer et exécuter d’autres binaires
    • On y trouvait des noms d’architectures comme mips, mpsl, x86_64, arm, arm5, arm6, arm7, i586, i686, powerpc, sh4, m68k, sparc
    • Le fait d’essayer des binaires pour plusieurs architectures semble destiné à élargir la portée de l’attaque lorsque l’attaquant ne connaît pas l’architecture de l’équipement ciblé
  • Pour poursuivre l’analyse, un binaire incompatible avec l’environnement a été téléchargé puis examiné avec Ghidra
    • Au départ, il ne contenait que 3 fonctions et peu de chaînes de caractères
    • Dans une grande zone de données, les chaînes $Info: This file is packed with the UPX executable packer et UPX 3.94 ont été identifiées
  • Il s’agissait d’un binaire ELF compressé avec UPX, et tant que l’en-tête UPX ou le packed binary n’a pas été modifié, il peut être décompressé avec upx -d
    • En pratique, après avoir exécuté upx -d mips, la taille du fichier est passée de 34932 à 93732, ce qui a permis d’observer davantage de chaînes
  • Les chaînes du binaire décompressé incluaient M-SEARCH * HTTP/1.1, ST: urn:dial-multiscreen-org:service:dial:1 et une payload XML de mise à jour pour des équipements Huawei
    • Cela ressemble à une commande UPnP destinée à rechercher sur le réseau des équipements prenant en charge le protocole DIAL
    • La payload XML semble conçue pour scanner des équipements Huawei vulnérables à l’injection de commandes
    • Ce comportement a été identifié comme faisant partie du botnet Mirai
  • Le fichier référencé yeye.mips n’était plus disponible au moment de la tentative de récupération
    • L’exécution de nmap sur le serveur n’a révélé que 22/tcp ssh et 646/tcp filtered ldp comme ports ouverts

Injection de commandes visant Zyxel

  • Une autre requête contenait des commandes shell directement dans l’URL GET, et une fois la substitution shell ${IFS} supprimée, elle devenait plus lisible
    • La commande simplifiée consiste à aller dans /tmp, supprimer les fichiers *mips*, télécharger huhu.mips, lui donner les droits d’exécution, puis l’exécuter avec l’argument zyxel.selfrep
  • Cette attaque semblait viser un exploit de zhttpd sur des équipements Zyxel
  • Cette fois, le binaire n’était pas packé, ce qui a permis d’inspecter directement ses chaînes dans Ghidra
    • On y voyait M-SEARCH * HTTP/1.1, l’en-tête ST lié à DIAL, ainsi que skyljne.arm, skyljne.arm5, skyljne.arm6, skyljne.arm7, skyljne.mips, skyljne.mpsl, skyljne.x86_64, skyljne.sh4
    • Une payload XML visant des équipements Huawei y figurait aussi pour télécharger huhu.mips puis l’exécuter comme selfrep.huawei
  • Une autre chaîne contenait une commande envoyant une requête POST à /goform/set_LimitClient_cfg
    • Avec l’en-tête Cookie: user=admin, elle tentait d’injecter une commande dans le paramètre mac afin de télécharger puis exécuter huhu.mpsl
    • D’après un article d’Akamai, cette vulnérabilité vise des routeurs et peut être exploitée avant authentification faute de contrôles d’authentification et d’autorisation suffisants
  • Il est très probable que ce binaire soit un agent du botnet Mirai
    • Certaines sources évoquent aussi un lien possible avec Linux Medusa

Réponse du point de vue opérationnel

  • Les journaux examinés ne représentent qu’une partie de l’ensemble, et de nombreux autres exploits sont tentés chaque jour
  • Il est important de maintenir les équipements, en particulier les équipements IoT, à jour
  • Si possible, les équipements IoT ne devraient pas être exposés directement à l’Internet public
  • S’ils doivent absolument l’être, il convient de les isoler autant que possible dans un VLAN distinct

1 commentaires

 
GN⁺ 2024-01-29
Commentaires Hacker News
  • Fait intéressant, certains attaquants semblent surveiller les journaux Certificate Transparency pour repérer les certificats nouvellement émis.
    À plusieurs reprises, lorsque je laissais un nouveau serveur tourner sur une nouvelle IP pendant plus d’une semaine, les logs d’accès ne montraient que quelques scans aléatoires, puis environ une heure après l’obtention d’un certificat Let’s Encrypt, des centaines de requêtes comme celles décrites dans l’article arrivaient d’un coup.
    La conclusion, c’est qu’un nouveau service doit être sécurisé le plus tôt possible, idéalement avant même d’être exposé à Internet.

    • On a l’impression qu’il faudrait au minimum mettre quelque chose comme une authentification basique devant dès le tout premier moment d’exposition publique.
      Sinon, on peut aussi utiliser sa propre autorité de certification et, jusqu’à la bascule, des certificats autosignés avec mTLS.
      Par exemple, si un logiciel expose tel quel un écran d’installation initiale pour créer un compte administrateur ou connecter une DB, c’est plus risqué que de le définir dès le départ via des variables d’environnement, des fichiers de configuration ou un outil dédié de gestion des secrets.
    • J’ai récemment regardé les journaux Certificate Transparency, et je me demande s’il existe un outil ou une méthode pratique pour interroger les CT logs.
      Par exemple, pour rechercher des domaines sur une période donnée.
      Merkle Town[0] de Cloudflare est utile pour avoir une vue d’ensemble, mais je n’ai pas encore trouvé de moyen simple d’interroger les CT logs, et ct-woodpecker[1] semble aussi prometteur.
      [0] https://ct.cloudflare.com/
      [1] https://github.com/letsencrypt/ct-woodpecker
    • Utiliser davantage de certificats wildcard est aussi utile. Avec les seuls CT logs, il devient plus difficile d’identifier un sous-domaine précis à attaquer.
    • Dans beaucoup de cas, ce ne sont pas des attaquants, mais plutôt des services comme urlscan.io qui surveillent les CT logs et crawlent le Web pour chercher des malwares.
    • J’auto-héberge plusieurs services, mais j’ai complètement renoncé à les exposer directement à Internet.
      Les VPN sont tellement bons aujourd’hui que c’est plus rassurant, et je n’ai surtout pas envie d’exposer publiquement des choses comme l’hébergement de photos ou les sauvegardes.
  • Quand j’ai commencé à administrer des sites auto-hébergés, je consultais aussi les logs d’accès, et pendant un temps j’ai utilisé un système de détection d’intrusion qui collectait les données et affichait les tentatives d’attaque entrantes.
    Au final, j’ai arrêté à la fois d’examiner les logs de manière proactive et de payer pour un système de détection d’intrusion : c’était une perte de temps et une source de distraction.
    On trouve facilement de bonnes synthèses des vulnérabilités et attaques courantes ; il suffit de s’en servir comme base pour administrer ses serveurs. Pour chaque technologie de serveur web courante, il existe beaucoup de guides de bonnes pratiques, et les appliquer à 100 % vous place déjà très loin devant presque tous les attaquants.
    Ensuite, la meilleure utilisation du temps et des ressources consiste à privilégier un cycle de patch aussi rapide que possible. La plupart des attaques visent des vulnérabilités publiques.
    Les logs sont particulièrement utiles après coup, pour diagnostiquer un problème. Des logiciels d’analyse de logs m’ont aidé deux ou trois fois à stocker, rechercher et trouver la cause racine d’attaques réussies ; à chaque fois, la cause était une vulnérabilité connue patchée beaucoup trop tard.

    • Si, dans tous les cas, il s’agissait de vulnérabilités connues patchées trop tard, alors une approche qui repose uniquement sur les patchs finira forcément par échouer. Cela peut être une faille 0-day, ou simplement un attaquant plus rapide.
      La solution, c’est la défense en profondeur, et pour des services personnels auto-hébergés, elle est généralement assez facile à mettre en place.
      Mettez un pare-feu en frontal, ou cachez le service derrière un VPN/Tailscale ; au lieu de /phpmyadmin/, que visent les attaques automatisées, cachez-le dans un sous-dossier comme /mawer/phpmyadmin/ et 99,9 % ne le trouveront pas. On appelle cela de la sécurité par l’obscurité, et il ne faut pas s’y fier seule, mais comme couche supplémentaire c’est très utile.
      Il faut aussi mettre les apps en sandbox et isoler les serveurs, afin qu’une compromission rende les déplacements latéraux difficiles, tout en conservant des logs pour savoir si une attaque a eu lieu et si elle a réussi.
      L’essentiel, c’est de ne pas dépendre d’un seul moyen de défense, que ce soit les patchs ou un pare-feu. Tôt ou tard, l’un d’eux échouera.
    • Je suis curieux de la partie sur la priorité donnée au cycle de patch le plus rapide possible. J’aimerais savoir si vous utilisez des outils pour déterminer quand patcher, ou si vous vous basez simplement sur un intervalle de temps.
      Pour l’instant, j’essaie[0] de mettre à jour les paquets chaque trimestre, mais ce serait bien d’avoir un outil qui signale les vulnérabilités connues afin de pouvoir réagir immédiatement.
      [0] Par « essaie », j’entends que je ne peux pas forcément mettre à niveau tout de suite s’il y a des ruptures de compatibilité difficiles à gérer dans la dernière version, ou s’il s’agit d’une release X.0.0 en laquelle je n’ai pas encore confiance.
  • Puisque l’auteur dit ne pas être expert en sécurité, je corrigerais un petit point : les exemples du début relèvent de la recherche d’identifiants et de configuration, pas de la traversée de répertoires.
    À ma connaissance, la traversée de répertoires désigne une technique où l’attaquant « sort » de la racine web, ou trompe le serveur pour qu’il serve des fichiers situés hors du répertoire normal.

    • Si la méthode consiste à inclure des fichiers qui ne devraient normalement pas être hébergés, techniquement cela peut être les deux. Par exemple "/../../passwd/etc".
  • Au moins d’après mon expérience, le point essentiel est qu’une grande partie de ces attaques viennent d’acteurs étatiques hostiles.
    Ce sera controversé, mais il peut être utile de bloquer entièrement les plages IP de pays problématiques avec lesquels on n’a aucune raison de traiter. J’ai déjà bloqué ainsi 100 % des tentatives de reconnaissance visant un nouveau service.

    • Ce n’est pas le problème principal ; c’est juste que beaucoup de gens ne veulent pas bloquer aussi les utilisateurs légitimes de ces régions.
    • Ce serait bien si les acteurs étatiques n’avaient absolument aucun moyen d’acheter des serveurs dans d’autres pays pour lancer leurs attaques depuis là-bas.
    • Il y a plus de 15 ans, en regardant les logs des serveurs de petites entreprises locales que nous hébergions, nous avions conclu qu’on pouvait tout simplement bloquer toutes les adresses IP APNIC.
    • Le blocage géographique ne finit-il pas surtout par bloquer du trafic légitime, tout en poussant simplement les attaquants déterminés à utiliser des proxys ?
    • Dans ce cas, il faudrait bloquer les États-Unis et les Pays-Bas.
      Les scans visant mes serveurs viennent majoritairement des États-Unis, et les Pays-Bas arrivent loin derrière en deuxième position. Probablement surtout depuis AWS et d’autres datacenters.
  • Je travaille dans la sécurité des applications/produits et j’ai géré pendant plusieurs années les WAF d’entreprises pesant plusieurs milliards de dollars
    Il suffit de migrer le DNS vers Cloudflare et de mettre quelques règles WAF sur le site. Par exemple, déclencher un challenge managé si le score de bot est inférieur à 2, ou traiter les requêtes lorsque le score d’attaque atteint une certaine valeur. Il y a de fortes chances que cela ne coûte presque rien et règle beaucoup de problèmes
    En revanche, il faut absolument tester avant de passer en production. Avoir un domaine de test est aussi une bonne idée. Un WAF n’est pas une solution miracle, c’est plutôt un pansement ; si l’application elle-même n’est pas renforcée pour encaisser les attaques, même le WAF ou la protection anti-bots les plus avancés ne la sauveront pas

    • Pour ceux qui ne connaissent pas : https://blog.cloudflare.com/waf-for-everyone/
      Le Free Managed Ruleset semble être déployé par défaut, et Cloudflare tient son journal des changements ici : https://developers.cloudflare.com/waf/change-log
    • De mon côté, en auto-hébergement, j’utilise le WAF de Cloudflare et des règles TLS mutuelles pour ne laisser passer que les appelants légitimes que je connais
      Ça fonctionne très bien. Comme seuls des membres de ma famille y accèdent, la configuration a été simple, et chacun a son propre certificat, que je peux révoquer si nécessaire
    • Ces temps-ci, je gère surtout des applications internes, donc la surface d’attaque est bien plus réduite que pour des services publics
      Comme tu sembles bien connaître le sujet, je me demande si tu as déjà administré des solutions combinant une infrastructure Azure et Cloudflare ; si oui, j’aimerais savoir s’il y a des points que les gens oublient souvent, au-delà des généralités du type OWASP
    • C’est bien adapté aux sites WordPress standard, et on peut ajouter les plugins GuardGiant et Sucuri comme couche supplémentaire
    • Mettre un WAF devant une appli et considérer que le problème est réglé, ce n’est pas différent de mettre du rouge à lèvres à un cochon
      Si, pour une raison ou une autre, une entreprise doit absolument exploiter quelque chose qui n’est pas à jour, ça peut être nécessaire, mais au final cela reste un pansement
  • J’auto-héberge depuis environ un an un serveur HTTP/S de 400 lignes que j’ai conçu moi-même, et le volume de trafic d’attaque arrivant sur les 3 ports ouverts (22, 80, 443) est surprenant
    Je n’ai toutefois pas pris le temps d’analyser ce que les attaquants cherchent réellement à faire, et cet article comble beaucoup de blancs
    Ce serait intéressant d’analyser de la même manière les choses étranges visibles dans /var/log/auth.log
    Tout le code est open source et il n’y a aucun état côté serveur, donc je trouve étrange qu’un attaquant me cible spécifiquement. Au mieux, il pourrait obtenir un accès root à un VPS à 5 dollars par mois et défigurer temporairement un domaine que personne ne visite

    • Tout cela, ce sont des bots automatisés. Personne ne s’en préoccupe spécialement
      Si tu ouvres les 3 ports les plus connus, tu recevras des connexions ; ils ne savent pas ce que tu fais tourner et s’en fichent
    • Accéder à ton VPN permet d’en faire un point de départ pratique pour attaquer d’autres machines, et d’ajouter une couche supplémentaire pour dissimuler les traces
      Il est aussi possible d’héberger des malwares ou de faire tourner des mineurs de cryptomonnaie
    • Pour le port 22, ça peut valoir le coup d’envisager de n’autoriser que ta propre IP et de bloquer le reste
      Mon FAI, en pratique, ne change presque jamais mon IP ; si elle change, je peux me connecter au panneau d’administration web de l’hébergeur pour mettre la règle à jour
  • Je fais systématiquement tourner fail2ban sur chaque serveur, et j’ajoute aussi des jails personnalisées pour attraper les attaques adaptées au type de fonctionnalités exposées par le site
    Cela dit, cela fait longtemps que je n’ai pas vérifié si les autres valeurs par défaut de fail2ban suffisent encore à bloquer les attaques courantes. Je devrais mettre ce lien en favori pour y revenir plus tard

    • Si ton système expose une vulnérabilité aussi facilement ciblable, fail2ban ne te sauvera pas
  • Je consulte moi aussi les journaux d’accès de mes services auto-hébergés, et un détail manque nettement dans cette analyse
    Une grande partie des requêtes malveillantes vient de personnes ordinaires qui lancent des scanners de sécurité faciles à trouver sur GitHub, par exemple. Ce sont généralement des attaques peu sophistiquées : des instances de ces projets martèlent les serveurs sans même regarder les réponses ni se soucier d’éventuels rate limits
    Certaines attaques ne ciblent pas directement les IP, mais surveillent les domaines et sous-domaines, puis répètent périodiquement les mêmes scans depuis la même plage d’IP
    Dans un ancien poste, nous recevions sans cesse des scans répétés depuis une seule IP fixe en Turquie ; l’équipe a fini par l’appeler « le Turc », et lorsqu’on voyait un schéma de requêtes étrange, vérifier d’abord s’il était en train de toucher notre service faisait partie de la réponse à incident

  • Si vous voyez ce genre de logs sur AWS, par pitié, mettez AWS WAF devant votre VPC
    Ce n’est pas cher et, dans ce genre de situation, cela aide pas mal à réduire les sources d’ennuis. Même si cela ne bloque pas tout ce qui atteint le service, ça peut beaucoup aider

    • Bonne suggestion, mais il faut faire attention aux jeux de règles par défaut. Nous avons activé AWS WAF pour la conformité SOC 2
      Quelques règles trop agressives ont subtilement cassé certaines parties de l’application
      Il y avait une règle sur le corps des requêtes qui bloquait celles contenant "localhost", ainsi qu’une règle bloquant les requêtes sans en-tête User-Agent. Comme auparavant nous n’exigions pas de User-Agent pour les requêtes API, cela a cassé toute l’API pour certains utilisateurs jusqu’à ce que nous trouvions la cause
    • Les attaques mentionnées dans l’article ne devraient poser problème à aucune application web moderne. Je ne vois donc pas pourquoi il faudrait ajouter un WAF
    • Utiliser les règles par défaut d’AWS WAF n’est pas si simple. Dans notre application, beaucoup de requêtes et d’IP légitimes ont été bloquées
      Il faut savoir ce qui est bloqué et le valider d’abord ; sinon, dans certains cas, on finit par perdre des clients
    • En pratique, les WAF font souvent plus de mal que de bien
      Ils donnent l’illusion d’une sécurité alors qu’ils se contournent facilement, ont un coût important en performances et risquent aussi fortement de bloquer du trafic légitime : https://www.macchaffee.com/blog/2023/wafs/
    • Les WAF ont tendance à bloquer largement, parfois pour des raisons floues
      Par exemple, les chercheurs de notre université étudient les données Twitter ; le simple fait de suivre des liens depuis un petit échantillon aléatoire de tweets fait que les IP de l’université sont bloquées par la plupart des WAF
  • Il m’arrive de penser que ce serait amusant de créer un serveur Express qui réponde correctement à l’une de ces attaques, histoire de faire perdre du temps à quelqu’un
    Mais si je fais ça, je perds aussi mon temps