Archives par mot-clé : GNU

Encoder et encapsuler un code pour l’injecter

Les petits soucis que j’ai rencontrés dernièrement (cf. mon précédent billet), ont amené un de mes amis à me questionner sur la manière qu’un hacker peut « chiffrer » un code malveillant avant de l’injecter dans un script quelconque.

Tout d’abord, encoder un code source est une chose très répandue, qui est réalisée bien au-delà de la dissimulation d’un simple hack. Une grande partie des sites Internet étant programmés avec des langages interprétés tels que JavaScript, PHP ou ASP, souvent les éditeurs de sites Web utilisent cette méthode pour rendre illisible le code (ou du moins une partie) avant de livrer le produit à leur client. Par « illisible », il faut entendre que l’analyse du code par ce client nécessitera un travail de rétro-ingénierie très important, et aura par conséquent un coût non négligeable : c’est donc une façon pour l’éditeur de « fidéliser » sa clientèle, qui devra bien faire appel à lui pour dépatouiller le bordule… On aime ou on n’aime pas. Moi pas.

Puisque l’encodage d’un code exécutable est monnaie courante sur le Web, et notamment par les vilains petits pirates, pour ma démonstration je vais transposer ce mécanisme en Shell : ça n’a rien à voir, ça ne sert pas à grand chose (quoiqu’il doit bien y avoir un ou deux sites hébergés sur des serveurs en Shell), mais j’aime bien quand-même.

Dans mon exemple, la commande se chargera de récupérer la page « La Grande Question sur la vie, l’univers et le reste » et de l’enregistrer dans un fichier HTML. La commande correspondant à cela, et qui sera donc encodée, est comme ceci :

wget -q -O $HOME/42.html http://fr.wikipedia.org/wiki/
La_grande_question_sur_la_vie,_l%27univers_et_le_reste

Pour l’encoder, on peut par exemple utiliser la commande base64, un classique sur GNU/Linux. Cette commande convertit n’importe quoi en un code ASCII facilitant son inclusion dans un quelconque fichier texte. C’est d’ailleurs par cette méthode que les pièces jointes sont stockées dans les e-mails, ou bien encore que les images bitmap sont encapsulées dans les fichiers SVG. Ici, il suffit de soumettre à base64 la commande qui nous intéresse, en tant que vulgaire chaîne de caractères via un printf. Notez au passage, que le pour-cent (en rouge ci-dessous) a été doublé au préalable. La raison est très simple : la commande printf risque d’interpréter le %27 comme une succession de 27 espaces à écrire à la place.

printf 'wget -q -O $HOME/42.html http://fr.wikipedia.org/wiki/
La_grande_question_sur_la_vie,_l%%27univers_et_le_reste'
| base64 | tr -d 'n'

Ce qui va retourner cette chaîne ASCII totalement imbuvable :

d2dldCAtcSAtTyAkSE9NRS80Mi5odG1sIGh0dHA6Ly9mci53aWtpcGVkaWE
ub3JnL3dpa2kvTGFfZ3JhbmRlX3F1ZXN0aW9uX3N1cl9sYV92aWUsX2wlMj
d1bml2ZXJzX2V0X2xlX3Jlc3Rl

Cette chaîne sera celle à encapsuler dans les scripts Shell hôtes. Mais il n’est toutefois pas possible de l’injecter telle quelle, il est nécessaire de donner au script les moyens de décoder ce texte, puis de l’interpréter comme étant une commande exécutable. Tout d’abord, pour la décoder, il suffit de procéder de manière identique à son encodage, c’est-à-dire en utilisant la commande base64, mais cette fois-ci en y précisant l’argument « -d » (comme l’anglais « decode », CQFD).

printf 'd2dldCAtcSAtTyAkSE9NRS80Mi5odG1sIGh0dHA6Ly9mci53aWtpcGV
kaWEub3JnL3dpa2kvTGFfZ3JhbmRlX3F1ZXN0aW9uX3N1cl9sYV92aWUsX2wlMj
d1bml2ZXJzX2V0X2xlX3Jlc3Rl' | base64 -d

La commande base64 -d nous a permis de recouvrer la chaîne de caractères initiale. Il faut donc maintenant l’interpréter en tant que commande pour pouvoir l’exécuter. C’est le rôle de la commande eval, dans laquelle il suffit d’encapsuler le printf et le base64 -d.

eval `printf 'd2dldCAtcSAtTyAkSE9NRS80Mi5odG1sIGh0dHA6Ly9mci53aWtpcGV
kaWEub3JnL3dpa2kvTGFfZ3JhbmRlX3F1ZXN0aW9uX3N1cl9sYV92aWUsX2wlMj
d1bml2ZXJzX2V0X2xlX3Jlc3Rl' | base64 -d`

Cette fois c’est terminé. Cette ligne de code est directement utilisable dans n’importe quel script Shell. A l’exécution de ce script, le fichier 42.html sera alors enregistré à la racine du répertoire utilisateur courant.

Cette méthode est identique quel que soit le langage de programmation employé. Evidemment, l’écriture du code à injecter dépendra du programme visé, puisque pour un site Web en PHP, il faudra nécessairement injecter du code PHP exécutant du PHP (pour écrire du HTML et du JavaScript dans le cadre d’un piratage), et non du Shell exécutant du Shell.

Le dernier jour du mois ?

Dans la catégorie « astuces pour amoureux de la ligne de commande sous GNU/Linux », voici une petite commande qui peut s’avérer pratique dans le cas de certains développements en Bash. La simplicité de ce code n’a d’égal que sa beauté ! Bien entendu, cette remarque hautement poétique reste subjective… :mrgreen:

Pour une raison ou pour une autre, on peut avoir besoin de vérifier si la date du jour est le dernier jour du mois. Sauf que le dernier jour du mois peut être un 28, un 29, un 30 ou un 31.

La commande date du projet GNU permet de retourner une date autre que celle du jour. Il suffit alors de vérifier si « demain » sera le premier jour du mois suivant, et d’exécuter la commande de son choix en conséquence.

test `date +'%d' -d '1 day'` = "1" && echo "hello" || echo "world"

La ligne ci-dessus exécute la commande date en ajoutant « 1 jour » à la date actuelle. Le « %d » permet de récupérer le numéro du jour dans le mois. Si le test confirme que demain nous serons le 1er, alors le terminal affiche « hello » ; dans le cas contraire, le terminal affiche « world ».

Une manière plus académique d’écrire ce code au sein d’un script Bash, pourrait être l’exemple ci-dessous qui donnera le même résultat.

demain=`date +'%d' -d '1 day'`

if test "$demain" = "1"
then
	echo "hello"
else
	echo "world"
fi