Trois attaques d'escalade de privilèges AWS, avec les preuves CloudTrail et le correctif
Points clés
- Une attaque par escalade de privilèges dans AWS est une séquence d'appels d'API qui fait passer un principal des permissions qu'il détient à des permissions qu'on ne lui a jamais accordées. Ces appels sont ordinaires, et c'est ce qui les rend difficiles à repérer.
- Trois chaînes reviennent sans cesse dans les comptes réels :
iam:PassRoleaveclambda:CreateFunction,iam:UpdateAssumeRolePolicysuivi dests:AssumeRole, etiam:CreateAccessKeysur un autre utilisateur. - Chaque chaîne laisse des événements CloudTrail précis. Détecter, c'est surveiller ces événements venant de principaux qui n'ont aucune raison de les produire, en prenant les paramètres de la requête comme signal.
- Chaque chaîne a un correctif ciblé : une condition
iam:PassedToService, une permission retirée ou un Deny sur l'action précise. Dans la plupart des cas, c'est un seul changement de politique. - Détection et prévention sont toutes deux nécessaires. CloudTrail vous informe après l'appel. Valider les chemins à l'avance vous indique quels principaux pourraient tout simplement passer cet appel.
Une attaque par escalade de privilèges dans AWS est une séquence d'appels d'API qui fait passer un principal des permissions qu'il détient à des permissions qu'on ne lui a jamais accordées. Il n'y a pas d'exploit au sens habituel. Les appels sont les mêmes que ceux que les administrateurs passent chaque jour, ce qui les rend difficiles à remarquer et faciles à laisser ouverts. La carte d'escalade de privilèges AWS recense chaque permission qui peut être utilisée de cette façon. Cet article prend trois des chaînes les plus courantes et montre, pour chacune, comment elle fonctionne, ce que CloudTrail enregistre et le changement qui la brise.
Chaîne un : passer un rôle à Lambda
iam:PassRole et lambda:CreateFunction détenus ensemble, un principal crée une fonction, lui confie un rôle privilégié, et la fonction s'exécute avec ce rôle. Aucune des deux permissions n'est alarmante seule.Permissions. iam:PassRole sur un rôle privilégié, avec lambda:CreateFunction. Généralement aussi lambda:InvokeFunction, même si une fonction peut aussi être déclenchée par une source d'événements.
Comment ça marche. L'attaquant crée une nouvelle fonction Lambda et lui passe le rôle privilégié comme rôle d'exécution. AWS accepte le passage parce que la politique de confiance du rôle autorise lambda.amazonaws.com. L'attaquant invoque ensuite la fonction, et le code qu'il a écrit s'exécute avec les permissions du rôle privilégié. Si ce rôle est administrateur, le compte lui appartient après une création et une invocation. Le même schéma fonctionne avec EC2, ECS, Glue, CloudFormation, CodeBuild et tout autre service qui accepte un rôle passé.
Ce que CloudTrail montre. Un événement de gestion CreateFunction provenant de lambda.amazonaws.com dont le requestParameters.role est l'ARN d'un rôle privilégié. La vérification iam:PassRole ne produit pas d'événement propre ; le passage est visible dans les paramètres de l'appel de création. L'Invoke qui suit est un événement de données Lambda, il n'apparaît donc que si le trail a les événements de données Lambda activés, ce qui est désactivé par défaut et mérite d'être activé précisément pour cette raison. Avec les deux en place, le signal est l'association : un principal qui n'a jamais créé de fonction en crée une avec un rôle de grande valeur attaché, puis l'invoque dans les minutes qui suivent. Sans les événements de données, le signal est l'appel de création lui-même et l'activité API que le rôle passé effectue ensuite.
Le correctif. Restreignez le passage. Ajoutez une condition iam:PassedToService à l'autorisation iam:PassRole pour que le rôle ne puisse être passé qu'au service qui en a besoin, et remplacez tout caractère générique dans l'ARN de ressource par le rôle précis. Si le principal n'a pas besoin de passer de rôles du tout, retirez la permission. Explication complète : Passer un rôle à Lambda.
Chaîne deux : réécrire la politique de confiance d'un rôle, puis l'endosser
Permissions. iam:UpdateAssumeRolePolicy sur un rôle privilégié, plus sts:AssumeRole.
Comment ça marche. La politique de confiance d'un rôle décide qui peut l'endosser. Un principal capable de réécrire ce document s'y ajoute comme principal de confiance, puis appelle sts:AssumeRole et reçoit des identifiants temporaires pour le rôle. La relation de confiance d'origine n'a plus d'importance une fois écrasée, si bien que cette manœuvre permet de prendre le contrôle de n'importe quel rôle du compte que le principal peut atteindre avec l'appel de mise à jour. La politique de confiance réécrite reste en place jusqu'à ce que quelqu'un s'en aperçoive, ce qui en fait à la fois une escalade et un mécanisme de persistance.
Ce que CloudTrail montre. Un événement UpdateAssumeRolePolicy provenant de iam.amazonaws.com avec le nouveau document de politique dans requestParameters.policyDocument, suivi d'un événement AssumeRole provenant de sts.amazonaws.com pour le même rôle, de la part du principal qui vient d'être ajouté. Les politiques de confiance changent rarement dans un compte sain, donc tout événement UpdateAssumeRolePolicy en dehors d'un pipeline de déploiement mérite un regard, et un événement qui ajoute un principal interne au compte est un signal fort.
Le correctif. Retirez iam:UpdateAssumeRolePolicy à tout principal qui ne fait pas partie du chemin d'administration IAM, et placez un Deny explicite dessus pour les rôles privilégiés du compte, avec le rôle de déploiement comme seule exception. Explication complète : Réécrire la confiance du rôle, puis l'endosser.
Chaîne trois : créer une clé d'accès pour un autre utilisateur
Permissions. iam:CreateAccessKey sur un utilisateur autre que l'appelant.
Comment ça marche. L'attaquant appelle iam:CreateAccessKey avec le nom d'un autre utilisateur et reçoit une toute nouvelle clé d'accès de longue durée pour cet utilisateur. Il n'a jamais besoin du mot de passe ni des clés existantes de l'utilisateur. À partir de là, il peut appeler l'API en tant que cet utilisateur, et la nouvelle clé survit à une réinitialisation du mot de passe et à une rotation de l'autre clé de l'utilisateur. C'est la plus difficile des trois à remarquer, parce qu'un seul appel produit des identifiants durables et que l'utilisateur dont l'identité a été prise ne voit rien.
Ce que CloudTrail montre. Un événement CreateAccessKey provenant de iam.amazonaws.com où requestParameters.userName diffère de l'identité dans userIdentity. Ce décalage est le signal. Qu'un utilisateur crée des clés pour lui-même est normal. Qu'un principal crée des clés pour un autre est rare en dehors d'un script d'intégration, et le rôle de ce script est facile à mettre en liste d'autorisation. L'utilisation qui suit apparaît sous forme d'appels d'API par l'utilisateur victime depuis une nouvelle adresse IP source et un nouvel agent utilisateur.
Le correctif. Retirez iam:CreateAccessKey à tout principal qui ne fait pas partie du chemin d'administration des identités, et là où les utilisateurs doivent gérer leurs propres clés, restreignez l'autorisation à ${aws:username} pour qu'un utilisateur ne puisse créer de clés que pour lui-même. Explication complète : Créer une clé d'accès pour un utilisateur.
Comment détecter une escalade de privilèges dans AWS
Les trois chaînes ci-dessus partagent un schéma qui se généralise. L'escalade de privilèges laisse des événements ordinaires avec des paramètres inhabituels, venant de principaux qui n'ont aucun historique de ce type d'appels. La détection dans CloudTrail repose sur quatre points.
Premièrement, CloudTrail doit être activé pour chaque compte et chaque région, avec le trail livré dans un compte central où les charges de travail ne peuvent pas écrire. Un attaquant capable de désactiver ou de supprimer le trail fait disparaître les preuves, et StopLogging et DeleteTrail ont leur place sur la même liste de surveillance que les événements d'escalade.
Deuxièmement, surveillez les paramètres et pas seulement les noms d'événements. CreateFunction seul est routinier, alors que CreateFunction avec un rôle administrateur dans les paramètres mérite une alerte. Même chose pour CreateAccessKey lorsque l'utilisateur cible diffère de l'appelant.
Troisièmement, établissez une référence par principal. Un rôle de CI qui crée une fonction toutes les heures et un développeur qui n'a jamais appelé IAM en un an sont des sources différentes, et le même événement venant de chacun n'a pas la même signification.
Quatrièmement, associez les événements. L'escalade est une séquence : créer puis invoquer, mettre à jour la confiance puis endosser, créer une clé puis l'utiliser depuis un nouvel endroit. Une règle qui relie le premier événement au second dans une courte fenêtre produit bien moins de faux positifs que chacun des deux pris seul. L'activité Lambda, S3 et DynamoDB relève des événements de données et doit être activée sur le trail avant de pouvoir être associée.
La détection est la deuxième ligne
CloudTrail vous informe une fois l'appel passé. La première ligne consiste à savoir, avant tout appel, quels principaux pourraient le passer. Cela veut dire prendre chaque chaîne de la carte et la résoudre face à l'autorisation réelle du compte : politiques d'identité, limites, SCP, politiques de confiance et conditions. Une chaîne qui se résout en allow pour un principal est un chemin prouvé, et le correctif est le changement décrit plus haut, appliqué avant que quelqu'un ne l'essaie. Pathbreak effectue cette résolution en lecture seule sur tous les comptes, classe les chemins prouvés selon ce qu'ils atteignent et confirme chaque correctif après sa mise en place. L'outil gratuit pathbreak-audit liste quels principaux d'un compte détiennent ces permissions, comme point de départ.
Questions fréquentes
Qu'est-ce qu'une attaque par escalade de privilèges dans AWS ?
Une attaque par escalade de privilèges dans AWS est une séquence d'appels d'API par laquelle un principal obtient des permissions qu'on ne lui a pas accordées, par exemple en passant un rôle privilégié à un service qu'il peut créer, en réécrivant la politique de confiance d'un rôle pour l'endosser, ou en créant une clé d'accès pour un utilisateur plus privilégié. Pathbreak valide quels principals de vos comptes AWS pourraient effectuer ces appels.
Comment détecter une escalade de privilèges dans CloudTrail ?
Surveillez les événements précis que chaque chaîne produit, comme CreateFunction avec un rôle privilégié dans les paramètres, UpdateAssumeRolePolicy suivi d'AssumeRole, ou CreateAccessKey lorsque l'utilisateur cible diffère de l'appelant. Établissez une référence par principal, associez le premier événement au second et conservez le trail dans un compte que les charges de travail ne peuvent pas modifier. Pathbreak complète la détection dans CloudTrail en montrant, avant tout appel, quels principals pourraient l'effectuer.
iam:PassRole est-il dangereux en soi ?
Pas en soi. Il devient un chemin d'escalade de privilèges lorsqu'il est combiné à une permission qui crée ou met à jour une ressource de calcul acceptant un rôle, comme lambda:CreateFunction ou ec2:RunInstances, et lorsque le rôle cible fait confiance à ce service. Restreindre le passage avec iam:PassedToService et un ARN de rôle précis supprime le chemin. Pathbreak vérifie la politique de confiance et les conditions de chaque transmission de rôle lorsqu'il valide un chemin.
Quel correctif supprime le plus de chemins d'escalade de privilèges ?
Dans la plupart des comptes, restreindre ou retirer iam:PassRole sur les rôles privilégiés en supprime la plus grande part, parce que des dizaines de services acceptent un rôle passé. Dans le compte de laboratoire Pathbreak, un seul Deny sur un rôle a supprimé 3,893 chemins sur 4,087. Le bon premier changement dépend des principaux par lesquels passent les chemins prouvés.
Découvrez quels principaux de vos comptes peuvent passer ces appels aujourd'hui, avant que CloudTrail n'ait à vous le dire.
Demander une démo Voir la démo