AWS - Lambda Layers Persistence
Couches Lambda
Une couche Lambda est une archive .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, le contenu est extrait dans le répertoire /opt
de l'environnement d'exécution.
Par défaut, les couches que vous créez sont privées à votre compte AWS. Vous pouvez choisir de partager une couche avec d'autres comptes ou de rendre la couche publique. Si vos fonctions consomment une couche qu'un autre compte a publiée, vos fonctions peuvent continuer à utiliser la version de la couche après qu'elle a été supprimée, ou après que votre permission d'accéder à la couche a été révoquée. 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 empaquetez votre runtime préféré, vos bibliothèques et d'autres dépendances dans l'image de conteneur lorsque vous construisez 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 des répertoires où les lambda layers décompressent leurs fichiers : /opt/python/lib/python3.9/site-packages
et /opt/python
Si un attaquant parvient à backdoor un layer lambda utilisé ou à en ajouter un qui exécutera du code arbitraire lorsqu'une bibliothèque commune est chargée, il pourra exécuter du code malveillant à chaque invocation de lambda.
Par conséquent, les exigences sont :
Vérifier les bibliothèques qui sont chargées par le code des victimes
Créer une bibliothèque proxy avec des lambda layers qui exécutera du code personnalisé et chargera la bibliothèque originale.
Bibliothèques préchargées
Lors de l'abus 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 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 qui sont préchargées dans l'environnement d'exécution python dans lambda :
Et voici la liste (vérifiez que des bibliothèques comme os
ou json
sont déjà présentes)
Et voici la liste des bibliothèques que lambda inclut installées par défaut : https://gist.github.com/gene1wood/4a052f39490fae00e0c3
Backdooring de la couche Lambda
Dans cet exemple, supposons que le code ciblé importe csv
. Nous allons backdoor l'importation 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 essaie de charger csv, notre fichier __init__.py
sera chargé et exécuté.
Ce fichier doit :
Exécuter notre payload
Charger la bibliothèque csv originale
Nous pouvons faire les deux avec :
Puis, créez un 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
Le payload intégré enverra les IAM creds à un serveur LA PREMIÈRE FOIS qu'il est invoqué ou APRÈS une réinitialisation du conteneur lambda (changement de code ou lambda froide), mais d'autres techniques telles que les suivantes pourraient également être intégrées :
Couches externes
Notez qu'il est possible d'utiliser des couches lambda provenant de comptes externes. De plus, une lambda peut utiliser une couche d'un compte externe même si elle n'a pas les autorisations. Notez également que le nombre maximum de couches qu'une lambda peut avoir est de 5.
Par conséquent, afin d'améliorer la polyvalence de cette technique, un attaquant pourrait :
Backdoor une couche existante de l'utilisateur (rien n'est externe)
Créer une couche dans son compte, donner à compte victime l'accès pour utiliser la couche, configurer la couche dans la Lambda de la victime et retirer la permission.
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 rev shell à l'intérieur de la lambda)
La victime ne verra pas les couches externes utilisées avec
aws lambda list-layers
Last updated