AWS - Lambda Privesc
lambda
Plus d'informations sur lambda dans :
pageAWS - Lambda Enumiam:PassRole
, lambda:CreateFunction
, (lambda:InvokeFunction
| lambda:InvokeFunctionUrl
)
iam:PassRole
, lambda:CreateFunction
, (lambda:InvokeFunction
| lambda:InvokeFunctionUrl
)Les utilisateurs ayant les autorisations iam:PassRole
, lambda:CreateFunction
et lambda:InvokeFunction
peuvent élever leurs privilèges.
Ils peuvent créer une nouvelle fonction Lambda et lui attribuer un rôle IAM existant, accordant à la fonction les autorisations associées à ce rôle. L'utilisateur peut ensuite écrire et télécharger du code dans cette fonction Lambda (avec par exemple un shell inversé).
Une fois la fonction configurée, l'utilisateur peut déclencher son exécution et les actions prévues en invoquant la fonction Lambda via l'API AWS. Cette approche permet effectivement à l'utilisateur d'effectuer des tâches indirectement via la fonction Lambda, en opérant avec le niveau d'accès accordé au rôle IAM qui lui est associé.\
Un attaquant pourrait abuser de cela pour obtenir un shell inversé et voler le jeton :
Vous pourriez également abuser des autorisations du rôle lambda à partir de la fonction lambda elle-même. Si le rôle lambda avait suffisamment d'autorisations, vous pourriez l'utiliser pour vous accorder des droits d'administrateur :
Il est également possible de divulguer les informations d'identification du rôle de la lambda sans avoir besoin d'une connexion externe. Cela serait utile pour les Lambdas isolées du réseau utilisées pour des tâches internes. Si des groupes de sécurité inconnus filtrent vos shells inversés, ce morceau de code vous permettra de divulguer directement les informations d'identification en tant que sortie de la lambda.
Impact potentiel : Élévation de privilèges directe vers le rôle de service lambda arbitraire spécifié.
Notez que même si cela peut sembler intéressant, lambda:InvokeAsync
ne permet pas à lui seul d'exécuter aws lambda invoke-async
, vous avez également besoin de lambda:InvokeFunction
.
iam:PassRole
, lambda:CreateFunction
, lambda:AddPermission
iam:PassRole
, lambda:CreateFunction
, lambda:AddPermission
Comme dans le scénario précédent, vous pouvez vous accorder la permission lambda:InvokeFunction
si vous avez la permission lambda:AddPermission
.
Impact potentiel : Élévation de privilèges directe vers le rôle de service lambda arbitraire spécifié.
iam:PassRole
, lambda:CreateFunction
, lambda:CreateEventSourceMapping
iam:PassRole
, lambda:CreateFunction
, lambda:CreateEventSourceMapping
Les utilisateurs ayant les autorisations iam:PassRole
, lambda:CreateFunction
et lambda:CreateEventSourceMapping
(et potentiellement dynamodb:PutItem
et dynamodb:CreateTable
) peuvent élever indirectement leurs privilèges même sans lambda:InvokeFunction
.
Ils peuvent créer une fonction Lambda avec un code malveillant et lui attribuer un rôle IAM existant.
Au lieu d'inviter directement la Lambda, l'utilisateur met en place ou utilise une table DynamoDB existante, la reliant à la Lambda via un mapping de source d'événements. Cette configuration garantit que la fonction Lambda est déclenchée automatiquement lors de l'ajout d'un nouvel élément dans la table, que ce soit par l'action de l'utilisateur ou un autre processus, déclenchant ainsi indirectement la fonction Lambda et exécutant le code avec les autorisations du rôle IAM transmis.
Si DynamoDB est déjà actif dans l'environnement AWS, l'utilisateur doit simplement établir la correspondance de la source d'événements pour la fonction Lambda. Cependant, si DynamoDB n'est pas utilisé, l'utilisateur doit créer une nouvelle table avec le streaming activé:
Maintenant, il est possible de connecter la fonction Lambda à la table DynamoDB en créant un mappage de source d'événement:
Avec la fonction Lambda liée au flux DynamoDB, l'attaquant peut déclencher indirectement la Lambda en activant le flux DynamoDB. Cela peut être réalisé en insérant un élément dans la table DynamoDB :
Impact potentiel : Élévation de privilèges directe vers le rôle de service lambda spécifié.
lambda:AddPermission
lambda:AddPermission
Un attaquant avec cette autorisation peut s'accorder lui-même (ou à d'autres) n'importe quelle autorisation (cela génère des stratégies basées sur les ressources pour accorder l'accès à la ressource) :
Impact potentiel : Élévation de privilèges directe vers le rôle de service lambda en accordant la permission de modifier le code et de l'exécuter.
lambda:AddLayerVersionPermission
lambda:AddLayerVersionPermission
Un attaquant avec cette permission peut s'accorder lui-même (ou à d'autres) la permission lambda:GetLayerVersion
. Il pourrait accéder à la couche et rechercher des vulnérabilités ou des informations sensibles.
Impact potentiel : Accès potentiel à des informations sensibles.
lambda:UpdateFunctionCode
lambda:UpdateFunctionCode
Les utilisateurs détenant l'autorisation lambda:UpdateFunctionCode
ont le potentiel de modifier le code d'une fonction Lambda existante liée à un rôle IAM.
L'attaquant peut modifier le code de la fonction lambda pour exfiltrer les informations d'identification IAM.
Bien que l'attaquant puisse ne pas avoir la capacité directe d'invocation de la fonction, si la fonction Lambda est préexistante et opérationnelle, il est probable qu'elle sera déclenchée par le biais de flux de travail ou d'événements existants, facilitant ainsi indirectement l'exécution du code modifié.
Impact potentiel : Élévation de privilèges directe vers le rôle de service lambda utilisé.
lambda:UpdateFunctionConfiguration
lambda:UpdateFunctionConfiguration
Introduction
Couches Lambda permet d'inclure du code dans votre fonction lambda tout en le stockant séparément, de sorte que le code de la fonction puisse rester petit et que plusieurs fonctions puissent partager du code.
À l'intérieur de lambda, vous pouvez vérifier les chemins à partir desquels le code Python est chargé avec une fonction comme celle-ci :
Voici les emplacements :
/var/task
/opt/python/lib/python3.7/site-packages
/opt/python
/var/runtime
/var/lang/lib/python37.zip
/var/lang/lib/python3.7
/var/lang/lib/python3.7/lib-dynload
/var/lang/lib/python3.7/site-packages
/opt/python/lib/python3.7/site-packages
/opt/python
Par exemple, la bibliothèque boto3 est chargée depuis /var/runtime/boto3
(4e position).
Exploitation
Il est possible d'abuser de l'autorisation lambda:UpdateFunctionConfiguration
pour ajouter une nouvelle couche à une fonction lambda. Pour exécuter du code arbitraire, cette couche doit contenir une bibliothèque que la lambda va importer. Si vous pouvez lire le code de la lambda, vous pourriez trouver cela facilement, notez également qu'il est possible que la lambda utilise déjà une couche et que vous pourriez télécharger la couche et ajouter votre code dedans.
Par exemple, supposons que la lambda utilise la bibliothèque boto3, cela créera une couche locale avec la dernière version de la bibliothèque :
Vous pouvez ouvrir ./lambda_layer/boto3/__init__.py
et ajouter la porte dérobée dans le code global (une fonction pour exfiltrer des informations d'identification ou obtenir un shell inversé par exemple).
Ensuite, compressez le répertoire ./lambda_layer
et téléversez la nouvelle couche lambda dans votre propre compte (ou dans celui de la victime, mais vous pourriez ne pas avoir les autorisations nécessaires pour cela).
Notez que vous devez créer un dossier python et y placer les bibliothèques pour remplacer /opt/python/boto3. De plus, la couche doit être compatible avec la version de python utilisée par la lambda et si vous la téléversez dans votre compte, elle doit être dans la même région :
Maintenant, rendez la couche lambda téléchargée accessible par n'importe quel compte :
Et attachez la couche lambda à la fonction lambda de la victime :
La prochaine étape serait soit d'appeler la fonction nous-mêmes si nous le pouvons, soit d'attendre qu'elle soit appelée de manière normale - ce qui est la méthode la plus sûre.
Une manière plus discrète d'exploiter cette vulnérabilité peut être trouvée dans :
pageAWS - Lambda Layers PersistenceImpact potentiel : Élévation directe des privilèges vers le rôle de service lambda utilisé.
?iam:PassRole
, lambda:CreateFunction
, lambda:CreateFunctionUrlConfig
, lambda:InvokeFunctionUrl
?iam:PassRole
, lambda:CreateFunction
, lambda:CreateFunctionUrlConfig
, lambda:InvokeFunctionUrl
Peut-être qu'avec ces autorisations, vous pouvez créer une fonction et l'exécuter en appelant l'URL... mais je n'ai pas trouvé de moyen de le tester, donc faites-le moi savoir si vous le faites !
Lambda MitM
Certaines lambdas vont recevoir des informations sensibles des utilisateurs dans les paramètres. Si vous obtenez une RCE dans l'une d'entre elles, vous pouvez exfiltrer les informations que d'autres utilisateurs lui envoient, vérifiez cela dans :
pageAWS - Steal Lambda RequestsRéférences
Dernière mise à jour