AWS - Lambda Layers Persistence
Couches Lambda
Une couche Lambda est une archive de fichier .zip qui peut contenir du code supplémentaire ou d'autres contenus. Une couche peut contenir des bibliothèques, un runtime personnalisé, des données ou des fichiers de configuration.
Il est possible d'inclure jusqu'à cinq couches par fonction. Lorsque vous incluez une couche dans une fonction, les contenus sont extraits dans le répertoire /opt
de l'environnement d'exécution.
Par défaut, les couches que vous créez sont privées pour votre compte AWS. Vous pouvez choisir de partager une couche avec d'autres comptes ou de la rendre publique. Si vos fonctions consomment une couche publiée par un compte différent, vos fonctions peuvent continuer à utiliser la version de la couche après sa suppression, ou après la révocation de votre autorisation d'accès à la couche. Cependant, vous ne pouvez pas créer une nouvelle fonction ou mettre à jour des fonctions en utilisant une version de couche supprimée.
Les fonctions déployées en tant qu'image de conteneur n'utilisent pas de couches. Au lieu de cela, vous emballez votre runtime préféré, les bibliothèques et autres dépendances dans l'image du conteneur lors de la construction de l'image.
Chemin de chargement Python
Le chemin de chargement que Python utilisera dans Lambda est le suivant :
Vérifiez comment les deuxième et troisième positions sont occupées par les répertoires où les couches lambda décompressent leurs fichiers : /opt/python/lib/python3.9/site-packages
et /opt/python
Si un attaquant parvient à installer une porte dérobée dans une couche lambda utilisée ou en ajouter une qui exécutera du code arbitraire lorsqu'une bibliothèque commune est chargée, il pourra exécuter du code malveillant à chaque invocation de la lambda.
Par conséquent, les exigences sont les suivantes :
Vérifier les bibliothèques chargées par le code des victimes
Créer une bibliothèque proxy avec des couches lambda qui exécutera du code personnalisé et chargera la bibliothèque d'origine.
Bibliothèques préchargées
En abusant de cette technique, j'ai rencontré une difficulté : Certaines bibliothèques sont déjà chargées dans l'environnement d'exécution Python lorsque votre code est exécuté. Je m'attendais à trouver des choses comme os
ou sys
, mais même la bibliothèque json
était chargée.
Pour abuser de cette technique de persistance, le code doit charger une nouvelle bibliothèque qui n'est pas déjà chargée lorsque le code est exécuté.
Avec un code Python comme celui-ci, il est possible d'obtenir la liste des bibliothèques préchargées à l'intérieur de l'environnement d'exécution Python dans la lambda :
Et voici la liste (vérifiez que les bibliothèques telles que os
ou json
sont déjà présentes)
Et voici la liste des bibliothèques incluses par défaut dans lambda: https://gist.github.com/gene1wood/4a052f39490fae00e0c3
Introduction d'une porte dérobée dans la couche Lambda
Dans cet exemple, supposons que le code ciblé importe csv
. Nous allons introduire une porte dérobée dans l'import de la bibliothèque csv
.
Pour ce faire, nous allons créer le répertoire csv avec le fichier __init__.py
à l'intérieur, dans un chemin chargé par lambda : /opt/python/lib/python3.9/site-packages
Ensuite, lorsque la lambda est exécutée et tente de charger csv, notre fichier __init__.py
sera chargé et exécuté.
Ce fichier doit :
Exécuter notre charge utile
Charger la bibliothèque csv d'origine
Nous pouvons faire les deux avec :
Ensuite, créez une archive zip avec ce code dans le chemin python/lib/python3.9/site-packages/__init__.py
et ajoutez-le en tant que couche lambda.
Vous pouvez trouver ce code sur https://github.com/carlospolop/LambdaLayerBackdoor
La charge utile intégrée enverra les informations d'identification IAM à un serveur LA PREMIÈRE FOIS qu'elle est invoquée ou APRÈS une réinitialisation du conteneur lambda (changement de code ou lambda froid), mais d'autres techniques telles que celles-ci pourraient également être intégrées:
pageAWS - Steal Lambda RequestsCouches Externes
Notez qu'il est possible d'utiliser des couches lambda provenant de comptes externes. De plus, une lambda peut utiliser une couche provenant d'un compte externe même si elle n'a pas les autorisations. Notez également que le nombre maximal de couches qu'une lambda peut avoir est de 5.
Par conséquent, pour améliorer la polyvalence de cette technique, un attaquant pourrait:
Installer une porte dérobée dans une couche existante de l'utilisateur (rien n'est externe)
Créer une couche dans son compte, donner l'accès du compte de la victime pour utiliser la couche, configurer la couche dans la lambda de la victime et supprimer l'autorisation.
La Lambda pourra toujours utiliser la couche et la victime n'aura aucun moyen facile de télécharger le code des couches (à part obtenir un shell inversé à l'intérieur de la lambda)
La victime ne verra pas les couches externes utilisées avec
aws lambda list-layers
Dernière mise à jour