Exemples d’attaques repérées dans les journaux d’accès
(nishtahir.com)- 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 commeMozlila/5.0 - Des tentatives de Shellshock essayaient de lire
/etc/passwden 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 .envest généralement utilisé pour stocker les secrets d’une application
- Exemples de chemins demandés :
- 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
- Exemples :
- 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/
- Exemples :
- Certains User-Agent contenaient
Mozlila/5.0, qui semble être une faute de frappe deMozilla/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
- Exemples :
- 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_AGENTen fait partie - Si des caractères comme
() { :; };sont présents, Bash les interprète comme une fonction à exécuter
- Au démarrage d’un programme CGI, des variables d’environnement sont définies à partir du contenu de la requête, et
- 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 Bashecho Content-Type: text/html; echo ;affiche leContent-Typede la réponse HTTP suivi d’une ligne vide/bin/cat /etc/passwdest 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
countryafin de télécharger puis exécuter le script shell distanttenda.sh- Après décodage de l’URL, la commande consiste à aller dans
/tmp, supprimer des fichiers, récupérer le script avecwget, lui donner les droits d’exécution puis le lancer
- Après décodage de l’URL, la commande consiste à aller dans
- 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é
- On y trouvait des noms d’architectures comme
- 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 packeretUPX 3.94ont é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 de34932à93732, ce qui a permis d’observer davantage de chaînes
- En pratique, après avoir exécuté
- Les chaînes du binaire décompressé incluaient
M-SEARCH * HTTP/1.1,ST: urn:dial-multiscreen-org:service:dial:1et 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.mipsn’était plus disponible au moment de la tentative de récupération- L’exécution de
nmapsur le serveur n’a révélé que22/tcp sshet646/tcp filtered ldpcomme ports ouverts
- L’exécution de
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échargerhuhu.mips, lui donner les droits d’exécution, puis l’exécuter avec l’argumentzyxel.selfrep
- La commande simplifiée consiste à aller dans
- Cette attaque semblait viser un exploit de
zhttpdsur 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êteSTlié à DIAL, ainsi queskyljne.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.mipspuis l’exécuter commeselfrep.huawei
- On y voyait
- 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ètremacafin de télécharger puis exécuterhuhu.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
- Avec l’en-tête
- 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
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.
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.
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
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.
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.
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.
"/../../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.
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
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
Ç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
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
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.logTout 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
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
Il est aussi possible d’héberger des malwares ou de faire tourner des mineurs de cryptomonnaie
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
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
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 causeIl faut savoir ce qui est bloqué et le valider d’abord ; sinon, dans certains cas, on finit par perdre des clients
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/
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
[1] https://infosec.exchange/@gnyman/109318464878274206
[2] https://nyman.re/super-simple-ssh-tarpit/