Fichiers PHP inconnus à la racine : radio.php, wp-core.php, images.php
`radio.php`, `wp-core.php`, `images.php`, `about.php` : des noms anodins pour des webshells. On note les dates de modification, on copie, on ne supprime pas encore. Ces fichiers datent souvent l'entrée plus clairement qu'un access.log déjà rotaté.
Des noms anodins cachent des webshells. Notez les dates de modification. Ne les supprimez pas avant d'avoir copié : ils indiquent souvent l'heure d'entrée.
Des noms qui veulent passer pour du métier
L'attaquant n'appelle pas son shell `hack.php`. Il reprend le vocabulaire du CMS : `wp-core.php`, `wp-includes.php` (fichier, pas dossier), `xmlrpc.php.bak`, `css.php`, `radio.php`, `fw.php`. Un photographe voit `images.php` et pense à un script de galerie. C'est souvent un gestionnaire de fichiers.
Les extensions mentent aussi : `.php.jpg` se traite à part (double extension). À la racine, le `.php` tout court domine. Un `.phtml`, `.php5`, `.pht` apparaît quand le serveur est réglé pour les exécuter.
Un nom aléatoire de 8 caractères (`a7k2qm.php`) est plus honnête : il ne se cache pas. Il se mélange aux backups. Triez par date, pas par alphabet — l'alphabet enterre `z.php` sous `wp-cron.php`.
Lister la racine autrement qu'à l'œil
Le gestionnaire de fichiers du panel trie mal, cache les fichiers qui commencent par un point, et n'affiche pas la taille. Passez par SFTP ou `ls -la --time-style=long-iso`. Exportez la liste (nom, taille, mtime) dans un tableur. C'est le constat de la racine.
Cherchez aussi un cran en dessous : `wp-admin/about.php` trop récent, `wp-includes/images.php`, `cgi-bin/`. La « racine » du dossier web n'est pas le seul étage. Un shell dans `wp-admin` s'appelle souvent comme un fichier cœur.
Les archives : `backup.zip`, `old.tar.gz` à la racine sont téléchargeables. Même « propres », elles exposent `wp-config`. Traitez-les comme un incident parallèle : retirez-les du webroot après copie hors serveur.
- Liste nom / taille / date, pas un coup d'œil FTP.
- Fichiers dot (`.php`, `.user.ini`).
- Étages `wp-admin`, `wp-includes`, `cgi-bin`.
- Archives et dumps SQL publics.
Dates : le premier geste utile
Un `index.php` WordPress pèse quelques kilo-octets et date de la dernière MAJ cœur. Un `index.php` de 180 Ko modifié un dimanche à 4 h, pendant que le reste du cœur date de mars, est le dossier index trop lourd. Notez toutes les mtime de la fenêtre suspecte.
Plusieurs fichiers à la même minute : même session d'upload. Cette minute est l'heure d'entrée si les logs FTP l'alignent. Gardez-la pour l'assureur et pour chercher le compte FTP utilisé.
Attention au `touch` : un attaquant peut reculer une date. La taille et le contenu restent. Une date « 2018 » sur un fichier qui contient un domaine de 2026 ne trompe que le tri rapide.
Copier avant d'effacer
Le fichier est une preuve et parfois la seule horloge. Un zip hors serveur, un hash si vous savez le faire. Puis isolation (renommer en `.off`) plutôt que delete immédiat si vous n'avez pas encore la copie.
L'ouvrir sur votre PC de tous les jours a un risque (macro, PHP local). Lisez-le comme du texte, pas en l'exécutant. Un `eval(base64_decode` suffit à classer « porte » sans tout comprendre. Voir code base64.
Ne l'envoyez pas par e-mail à toute l'équipe en pièce jointe exécutable. Un lien vers le zip de preuve sur un drive interne, ou le prestataire via un canal prévu. Voir accès prestataire.
Ce qui est légitime à la racine
WordPress : `index.php`, `wp-config.php`, `xmlrpc.php`, `wp-cron.php`, `wp-load.php`, `wp-settings.php`, `wp-blog-header.php`, `wp-links-opml.php`, `wp-mail.php`, `wp-signup.php`, `wp-trackback.php`, `wp-activate.php`, plus les `wp-admin/` `wp-includes/` `wp-content/`. Un `app.php` Symfony, un `index.php` Presta, un `cron.php` Magento : selon le CMS.
Un `health.php` posé par l'agence, un `deploy.php` oublié, un `phpinfo.php` : légitimes d'intention, dangereux en ligne. `phpinfo` et `deploy` sortent après incident, même s'ils n'étaient pas le shell.
En cas de doute, comparez à une install vierge de la même version. Tout ce qui n'y figure pas est suspect jusqu'à preuve d'un développeur nommé.
Un fichier, rarement une seule porte
Le shell à la racine est le salon. L'entrée est un plugin, un mot de passe, un voisin. Retirer `radio.php` et garder l'admin fantôme, le fichier revient. Cherchez dans la même session : utilisateurs, mu-plugins, cron, `.htaccess`.
Un webshell connu (C99, WSO) a une signature ; un one-liner n'en a pas. Ne vous arrêtez pas parce que Wordfence n'a flaggé que `radio.php`. Voir webshell C99.
Les permissions 777 sur la racine expliquent l'écriture. Les remettre à 755 / 644 après, pas « pour voir » pendant que vous cherchez encore — vous casserez l'upload légitime au mauvais moment. Après le tri.
Comparer au zip du CMS
Téléchargez le zip WordPress / Presta de la version exacte (`wp-includes/version.php`, Presta `settings.inc`). Comparez les fichiers cœur. Un `xmlrpc.php` modifié est plus grave qu'un `radio.php` : il se fait passer pour officiel à chaque scan visuel.
Ne remplacez pas tout le cœur « à l'aveugle » sans copie : vous perdez un mu-plugin utile, un drop-in (`object-cache.php`). Remplacez fichier par fichier ce qui diverge du zip, après avoir zipé l'état actuel.
Le thème et `wp-content` ne sont pas dans le zip cœur. Autre passe, autre méthode. Voir fichiers du thème.
Après le retrait : réécriture et cron
Attendez une nuit. Si `radio.php` réapparaît à la même minute, le cron ou le shell restant l'écrit. C'est le test, pas un scan vert. Surveillez la liste de racine à J+1 et J+7.
Changez le panel avant de vous féliciter. Un FTP encore ouvert republie le fichier en 30 secondes. Invalidez les clés, les users FTP ajoutés.
`site:votre-domaine.fr/radio.php` : si Google a indexé le shell, l'URL doit passer en 404. Une inspection Search Console confirme. Pas de réexamen Safe Browsing pour un PHP déjà 404, sauf si d'autres URL dangereuses répondent encore 200.
Quand Google ou Chrome s'en mêle
Si le shell servait un kit (banque, impôts), les visiteurs ont vu une page, pas un listing de fichiers. Traitez comme phishing hébergé : couper l'URL d'abord. Safe Browsing : 24 à 72 h après site réellement propre.
Un simple shell non visité par le public peut ne jamais allumer Chrome. Ce n'est pas un feu vert. C'est « pas encore signalé ».
Vous pouvez déclarer le site. En attendant : liste de racine, copies, panel. Ne commencez pas par un cleaner qui efface sans liste.
- Liste horodatée de la racine.
- Copies hors serveur.
- Retrait + recherche des autres portes.
- Contrôle réapparition 24 h / 7 j.