{"id":56024,"date":"2024-05-09T15:12:58","date_gmt":"2024-05-09T15:12:58","guid":{"rendered":"https:\/\/packetstormsecurity.com\/news\/view\/35857\/AWS-CloudQuarry-Digging-For-Secrets-In-Public-AMIs.html"},"modified":"2024-05-09T15:12:58","modified_gmt":"2024-05-09T15:12:58","slug":"aws-cloudquarry-digging-for-secrets-in-public-amis","status":"publish","type":"post","link":"https:\/\/www.threatshub.org\/blog\/aws-cloudquarry-digging-for-secrets-in-public-amis\/","title":{"rendered":"AWS CloudQuarry: Digging For Secrets In Public AMIs"},"content":{"rendered":"<p>Money, secrets and mass exploitation: This research unveils a quarry of sensitive data stored in public AMIs. Digging through each AMI we managed to collect 500 GB of credentials, private repositories, access keys and more. The present article is the detailed analysis of how we did it and what the data represents.<\/p>\n<p>We did a coordinated disclosure with AWS\u2019s security team before publishing this article.<\/p>\n<p>Researchers and article authors:<\/p>\n<h2 class=\"wp-block-heading\" id=\"before-you-begin\">Before you begin<\/h2>\n<p>The results and methodology of this research could have been presented in a short summary along with 1-2 diagrams. However, we decided to go for a lengthy article that will describe our methodology, our thinking, trade-offs and results.<\/p>\n<p>We invite you to challenge our approach and find aspects that we missed out or could have been improved. You can contact us through our LinkedIn profiles, through the comment section or through the Security Cafe media channels that you can find in the Contact page.<\/p>\n<h2 class=\"wp-block-heading\" id=\"table-of-contents\">TABLE OF CONTENTS<\/h2>\n<h2 class=\"wp-block-heading\" id=\"1-introduction\">1. Introduction<\/h2>\n<h3 class=\"wp-block-heading\" id=\"1-1-some-words-from-aws-security-team\">1.1 Some words from AWS security team<\/h3>\n<p>Note that AWS-owned AMIs are not affected by this issue and no customer action is required for those AMIs.<\/p>\n<p>Part of publishing AMIs is indeed publishing something public and customers should take care to inspect them prior to publishing so that they know what is in fact being published. As a best practice, AMI creators should not include credentials, including AWS account credentials, in published AMIs.<\/p>\n<p>For more information about crafting secure, shareable AMIs, recommendations can be found here:<\/p>\n<p>We also recommend customers use AMIs owned and published by AWS, or by another Amazon verified provider. For more information about verified providers, review \u201cVerified provider\u201d in the User Guide for Linux Instances. <a href=\"https:\/\/docs.aws.amazon.com\/AWSEC2\/latest\/UserGuide\/sharing-amis.html#verified-ami-provider\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/docs.aws.amazon.com\/AWSEC2\/latest\/UserGuide\/sharing-amis.html#verified-ami-provider<\/a><\/p>\n<h3 class=\"wp-block-heading\" id=\"1-1-research-idea-origins\">1.2 Research Idea \u2013 Origins<\/h3>\n<p>Some time ago I was doing a typical cloud security configuration review for a client. While checking for misconfigurations in the EC2 dashboard, I saw for the first time not one, but many public AMIs.<\/p>\n<p>But what is an AMI? Well, AMI stands for Amazon Machine Image and if it\u2019s the first time you hear about them that doesn\u2019t mean you haven\u2019t used one before. You see, every time you launch an EC2 instance, that instance is always based on an AMI.<\/p>\n<p>And to put it simply, an AMI is like a preconfigured virtual machine. Imagine you want to start an instance that has a certain database technology already installed and ready to go. Chances are that someone already configured such an instance and then made that instance an AMI so that others can use it.<\/p>\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"4211\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/image-32\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image.png\" data-orig-size=\"1814,994\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image.png?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image.png?w=840\" width=\"1024\" height=\"561\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image.png?w=1024\" alt class=\"wp-image-4211\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image.png?w=1024 1024w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image.png?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image.png?w=300 300w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image.png?w=768 768w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image.png 1814w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\"><figcaption class=\"wp-element-caption\">EC2 Launch Instance \u2013 Dashboard select AMI<\/figcaption><\/figure>\n<p>But most likely you used a common Amazon Linux AMI from the AWS Marketplace. These AMIs are from verified publishers. They are, in a sense, official AMIs. And then you have the Community AMIs, which are AMIs published by anyone and verified by none.<\/p>\n<p>To come back to my story, this client had multiple public AMIs that anyone could have found and used to start an EC2 instance based on that image. Essentially, anyone on the internet could have gained access to whatever files, secrets, credentials, code the client configured at some point and published \u201caccidentally\u201d (we\u2019ll talk later about those quotes).<\/p>\n<p>When I asked the client if I can check what was inside the AMIs, they said no ????. After finishing the engagement I was left with a question: Did they accidentally expose sensitive data all these years through these AMIs? And this gave birth to a second, bigger question: Are there other companies exposing sensitive data through public AMIs?<\/p>\n<p>While I didn\u2019t have the chance to get an answer for the first question, I knew I could answer the second one. So, with the help of my colleague Matei Josephs, we aimed to answer with this research if \u201c<strong>Are there any public AMIs with sensitive data out there?<\/strong>\u201c.<\/p>\n<h3 class=\"wp-block-heading\" id=\"1-2-relevant-details-about-amis\">1.3 Relevant Details About AMIs<\/h3>\n<p>First off, AMIs are dependent on their region. An AMI made public (published) in eu-central-1 will not be available in us-west-2 or any other region for that matter. This means that you have to specify the proper region if you want to access a particular AMI.<\/p>\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"4214\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/image-1-14\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-1.png\" data-orig-size=\"1656,1080\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-1\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-1.png?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-1.png?w=840\" width=\"1024\" height=\"667\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-1.png?w=1024\" alt class=\"wp-image-4214\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-1.png?w=1024 1024w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-1.png?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-1.png?w=300 300w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-1.png?w=768 768w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-1.png 1656w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\"><figcaption class=\"wp-element-caption\">Example AMI response from AWS API<\/figcaption><\/figure>\n<p>The second thing is that AMIs are by default created as private and it\u2019s actually hard to make it public. You have to disable a setting at the account level, wait 10 minutes, go to the AMI you want to make public and when you try to make it public you have to type \u201cconfirm\u201d in a pop-up that tells you the implied security risks. That\u2019s why I said the AMIs are published \u201caccidentally\u201d with quotes, because as far as I can tell, there is no accident in doing with; maybe just lack of awareness.<\/p>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" data-attachment-id=\"4216\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/image-2-13\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-2.png\" data-orig-size=\"1315,314\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-2\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-2.png?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-2.png?w=840\" loading=\"lazy\" width=\"1024\" height=\"244\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-2.png?w=1024\" alt class=\"wp-image-4216\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-2.png?w=1022 1022w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-2.png?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-2.png?w=300 300w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-2.png?w=768 768w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-2.png 1315w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\"><figcaption class=\"wp-element-caption\">Deprecation details from <a href=\"https:\/\/docs.aws.amazon.com\/AWSEC2\/latest\/UserGuide\/ami-deprecate.html\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/docs.aws.amazon.com\/AWSEC2\/latest\/UserGuide\/ami-deprecate.html<\/a><\/figcaption><\/figure>\n<p>The third thing is that AMIs can be deprecated. Let\u2019s look at the images above. Apart from the highlighted fields, we have on the last line a property called \u201cDeprecationTime\u201d. AMIs can become deprecated. As a user, you can deprecate your AMIs whenever you want. And if you don\u2019t, AWS will automatically deprecate your image after two years from its creation. This behavior was introduced in 2021 and its result is that deprecated images will not be accessible from the web console anymore. However, you can still use and query deprecated AMIs. You just have to use the CLI for that.<\/p>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" data-attachment-id=\"4218\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/image-3-11\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-3.png\" data-orig-size=\"1774,446\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-3\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-3.png?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-3.png?w=840\" loading=\"lazy\" width=\"1024\" height=\"257\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-3.png?w=1024\" alt class=\"wp-image-4218\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-3.png?w=1024 1024w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-3.png?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-3.png?w=300 300w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-3.png?w=768 768w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-3.png 1774w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\"><figcaption class=\"wp-element-caption\">CLI options for \u201cec2 describe-images\u201d regarding deprecation<\/figcaption><\/figure>\n<h3 class=\"wp-block-heading\" id=\"1-3-previous-work\">1.4 Previous Work<\/h3>\n<p>Dolev Farhi did something similar as us, but Dolev scanned AMIs from a single AWS region and only based on certain keywords: <a href=\"https:\/\/blog.lethalbit.com\/hunting-for-sensitive-data-in-public-amazon-images-ami\/\">https:\/\/blog.lethalbit.com\/hunting-for-sensitive-data-in-public-amazon-images-ami\/<\/a><\/p>\n<p>We wanted to scan all public AMIs, so our work completes Dolev\u2019s by covering the other 26+ AWS regions and the AMIs from Dolev\u2019s region that we\u2019re left out<\/p>\n<p>Ben Morris did a research close to what we are doing. He scanned public EBS volumes for secrets as he presented in his talk at DEF CON 27: <a href=\"https:\/\/www.youtube.com\/watch?v=HXM1rBk_wXs\">https:\/\/www.youtube.com\/watch?v=HXM1rBk_wXs<\/a><\/p>\n<p>While in theory we are scanning the AMI\u2019s volumes, in our case the EBS volume is not public by default just because the AMI is public. So there is very little overlap (we estimate under 5%) between his research and ours.<\/p>\n<p>Having this said, we believe that our research gives a more complete view into this issue that was almost not explored from an offensive perspective at large scale.<\/p>\n<h3 class=\"wp-block-heading\" id=\"1-4-rules-objectives\">1.5 Rules &amp; Objectives<\/h3>\n<p>We set out some rules from the beginning. The most important one, act in an ethical manner. Practically, this research didn\u2019t involve any hacking or breaking into systems. It only relied on data publicly available and set out by companies or individuals. However, we felt that acting ethically should be always on our mind.<\/p>\n<p>We also established a few objectives:<\/p>\n<ol>\n<li>Dig for secrets in every public AMI across every AWS region<\/li>\n<li>Have Fun<\/li>\n<li>Responsible Disclosure<\/li>\n<\/ol>\n<p>So we wanted to find out if there are secrets exposed in public AMIs by searching through all of them, have fun while doing it and responsible disclose to issue to the affected companies if it\u2019s the case.<\/p>\n<p>Let\u2019s get into it!<\/p>\n<h2 class=\"wp-block-heading\" id=\"2-collecting-all-public-amis\">2. Collecting all Public AMIs<\/h2>\n<p>First off, we enabled all AWS regions inside our AWS account. This was an easy process that didn\u2019t cost anything.<\/p>\n<p>Now: the command for retrieving all public AMIs from a region is fairly simple:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: bash; title: ; notranslate\" title>\n# this will work for most regions with a default page size of 1000\naws ec2 describe-images --include-deprecated --region $region &gt; $region.json # set a smaller page size if you get timeout errors\naws ec2 describe-images --include-deprecated --region $region --page-size 200 &gt; $region.json\n<\/pre>\n<\/div>\n<p>We knew this would be a challenging research when we had to wait a few hours to get all the public AMIs. Collecting the AMIs from every AWS region resulted in 11 GB of data ????<\/p>\n<p>This was the point where we decided to give a name to the research and create a private repository. In Romanian we have this expression of \u201cdigging for something\u201d when you search for something. And while our objective was to dig for secrets in every public AMI, it simply clicked for us. That\u2019s how we got to the whole \u201cCloudQuarry\u201d and \u201cdigging\u201d thing.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large is-resized\"><img decoding=\"async\" data-attachment-id=\"4232\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/ae95aede-cbb8-4c3d-b942-a1732094b40d\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/ae95aede-cbb8-4c3d-b942-a1732094b40d.jpeg\" data-orig-size=\"1024,1024\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"ae95aede-cbb8-4c3d-b942-a1732094b40d\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/ae95aede-cbb8-4c3d-b942-a1732094b40d.jpeg?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/ae95aede-cbb8-4c3d-b942-a1732094b40d.jpeg?w=840\" loading=\"lazy\" width=\"1024\" height=\"1024\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/ae95aede-cbb8-4c3d-b942-a1732094b40d.jpeg?w=1024\" alt class=\"wp-image-4232\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/ae95aede-cbb8-4c3d-b942-a1732094b40d.jpeg 1024w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/ae95aede-cbb8-4c3d-b942-a1732094b40d.jpeg?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/ae95aede-cbb8-4c3d-b942-a1732094b40d.jpeg?w=300 300w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/ae95aede-cbb8-4c3d-b942-a1732094b40d.jpeg?w=768 768w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\"><figcaption class=\"wp-element-caption\">CloudQuarry image generated by DALL\u00b7E 3<\/figcaption><\/figure>\n<\/div>\n<p>We transformed the 11 GB into 750 MB of archives which we uploaded in our repository.<\/p>\n<h2 class=\"wp-block-heading\" id=\"3-processing-the-collected-amis\">3. Processing the Collected AMIs<\/h2>\n<h3 class=\"wp-block-heading\" id=\"3-1-making-sense-of-what-we-have\">3.1 Making sense of what we have<\/h3>\n<p>We got a total of 3.1 million public AMIs. This number represents all the public AMIs from 27 AWS region (now there are more regions in AWS) available in December 2023 (more on the new public AMIs from that date at the end of the article).<\/p>\n<p>Here are the statistics per region, ordered by count, at the start of the research:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: plain; title: ; notranslate\" title>\nus-east-1: 203,864\nus-west-2: 183,509\neu-west-1: 171,196\nus-west-1: 170,634\nap-southeast-1: 164,231\nap-northeast-1: 163,020\nap-southeast-2: 162,493\neu-central-1: 161,535\nsa-east-1: 156,402\nus-east-2: 147,191\nap-northeast-2: 142,417\neu-west-2: 141,971\nap-south-1: 141,404\nca-central-1: 137,669\neu-west-3: 131,319\neu-north-1: 120,526\nap-east-1: 104,742\nme-south-1: 100,369\neu-south-1: 96,996\naf-south-1: 93,072\nap-southeast-3: 61,353\nme-central-1: 44,236\neu-central-2: 41,351\neu-south-2: 40,912\nap-south-2: 37,096\nap-southeast-4: 34,652\nil-central-1: 19,072\nTotal images: 3,173,232\n<\/pre>\n<\/div>\n<p>Now we faced a new question: is there any point in scanning all 3.1 million AMIs? We decided to further analyze the data to answer this. So we ran some python scripts to check things like how many unique owners are and top 10 AWS accounts with AMIs from each region. You can find the stats in the next file:<\/p>\n<p>Just looking at the data above we can see that there are a few AWS accounts with tens of thousands of AMIs. We can do some google dorking on them to check who is the company behind them, but the idea is that most likely these big accounts are commercial publishers and if they are commercial publishers then the chances to have valid secrets in them are really low.<\/p>\n<p>At this point we felt the need of a more easier way to analyze the data, so we moved it to MongoDB.<\/p>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" data-attachment-id=\"4241\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/image-4-11\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-4.png\" data-orig-size=\"959,441\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-4\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-4.png?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-4.png?w=840\" loading=\"lazy\" width=\"959\" height=\"441\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-4.png?w=959\" alt class=\"wp-image-4241\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-4.png 959w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-4.png?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-4.png?w=300 300w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-4.png?w=768 768w\" sizes=\"auto, (max-width: 959px) 100vw, 959px\"><figcaption class=\"wp-element-caption\">MongoDB Compass local instance<\/figcaption><\/figure>\n<p>Using the Schema feature from MongoDB Compass we gained more insight into what was going on. For example, we saw that from a sample of 1000 random AMIs, 41% of them are owned by a single AWS account. That\u2019s over 1 million AMIs if extrapolated.<\/p>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" data-attachment-id=\"4244\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/image-5-10\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-5.png\" data-orig-size=\"1297,460\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-5\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-5.png?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-5.png?w=840\" loading=\"lazy\" width=\"1024\" height=\"363\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-5.png?w=1024\" alt class=\"wp-image-4244\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-5.png?w=1024 1024w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-5.png?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-5.png?w=300 300w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-5.png?w=768 768w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-5.png 1297w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\"><figcaption class=\"wp-element-caption\">MongoDB Compass Schema analysis<\/figcaption><\/figure>\n<h3 class=\"wp-block-heading\" id=\"3-2-filtering-out-amis\">3.2 Filtering out AMIs<\/h3>\n<h4 class=\"wp-block-heading\" id=\"3-2-1-amis-from-marketplace\">3.2.1 AMIs from Marketplace<\/h4>\n<p>We decided that we can filter out AMIs based on some common sense conditions. The most obvious one was to filter out AMIs that are from the AWS Marketplace. The rationale behind this is that AMIs from marketplace are used on a daily basis by anyone. So, the chances to find valid secrets are small. Even more, these AMIs are from official and verified providers that are intentionally publish in the AWS Marketplace. We assume that they should be aware of what they publish and they most likely will not include sensitive information in their AMIs.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" data-attachment-id=\"4248\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/image-6-8\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-6.png\" data-orig-size=\"507,369\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-6\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-6.png?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-6.png?w=507\" loading=\"lazy\" width=\"507\" height=\"369\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-6.png?w=507\" alt class=\"wp-image-4248\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-6.png 507w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-6.png?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-6.png?w=300 300w\" sizes=\"auto, (max-width: 507px) 100vw, 507px\"><figcaption class=\"wp-element-caption\">JSON Property for AMIs from AWS Marketplace<\/figcaption><\/figure>\n<\/div>\n<p>We saw that the AMIs published in AWS Marketplace have an additional property that is not present for the community AMIs: <strong>ProductCodes<\/strong><\/p>\n<p>To make our life easier, when we added the AMIs in MongoDB, we replaced the \u201cProductCodes\u201d field with a custom property called \u201cIsInMarketplace\u201d.<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: python; first-line: 25; highlight: [30]; title: ; notranslate\" title>\ndef initialize_collection(amis_collection): for region in regions: amis = get_amis_for_region(region) for ami in amis: ami['Region'] = region ami['IsInMarketplace'] = 'ProductCodes' in ami.keys() ami['IsRootInstanceCoreType'] = ami['RootDeviceType'] == 'instance-store' amis_collection.insert_one(ami) print(f\"[x] Finished for region {region}\")\n<\/pre>\n<\/div>\n<p>Doing this, we managed to filter out 1.6 million AMIs, reducing the total number from 3.1 million to 1.5 million AMIs. In the next file is the new count for each region:<\/p>\n<p>Along the next chapters we\u2019ll build a MongoDB query that will filter all the necessary AMIs. This is how it looks for now:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: jscript; title: ; notranslate\" title>\n{IsInMarketplace: false}\n<\/pre>\n<\/div>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" data-attachment-id=\"4253\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/image-7-8\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-7.png\" data-orig-size=\"936,205\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-7\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-7.png?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-7.png?w=840\" loading=\"lazy\" width=\"936\" height=\"205\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-7.png?w=936\" alt class=\"wp-image-4253\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-7.png 936w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-7.png?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-7.png?w=300 300w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-7.png?w=768 768w\" sizes=\"auto, (max-width: 936px) 100vw, 936px\"><figcaption class=\"wp-element-caption\">MongoDB Compass filter AMIs from AWS Marketplace<\/figcaption><\/figure>\n<h4 class=\"wp-block-heading\" id=\"3-2-3-amis-owned-by-aws\">3.2.3 AMIs owned by AWS<\/h4>\n<p>Analyzing the fields available for the remaining AMIs, we noticed that there was only one value for the field <strong>ImageOwnerAlias<\/strong>, and that value was \u201camazon\u201d.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" data-attachment-id=\"4256\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/image-8-8\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-8.png\" data-orig-size=\"381,219\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-8\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-8.png?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-8.png?w=381\" loading=\"lazy\" width=\"381\" height=\"219\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-8.png?w=381\" alt class=\"wp-image-4256\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-8.png 381w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-8.png?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-8.png?w=300 300w\" sizes=\"auto, (max-width: 381px) 100vw, 381px\"><figcaption class=\"wp-element-caption\">AMI owned by AWS<\/figcaption><\/figure>\n<\/div>\n<p>So the AMIs owned by AWS can be identified through property with the value \u201camazon\u201d. Well, we again assumed that there is no point in searching for secrets in AWS owned AMIs. In the end, they know better. While that might not be the case, we assumed the best and decided to filter them out.<\/p>\n<p>MongoDB query filter:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: jscript; title: ; notranslate\" title>\n{IsInMarketplace:false, ImageOwnerAlias: {$not:{$eq:\"amazon\"}}}\n<\/pre>\n<\/div>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" data-attachment-id=\"4258\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/image-9-8\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-9.png\" data-orig-size=\"914,268\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-9\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-9.png?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-9.png?w=840\" loading=\"lazy\" width=\"914\" height=\"268\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-9.png?w=914\" alt class=\"wp-image-4258\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-9.png 914w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-9.png?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-9.png?w=300 300w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-9.png?w=768 768w\" sizes=\"auto, (max-width: 914px) 100vw, 914px\"><figcaption class=\"wp-element-caption\">MongoDB Compass filter AMIs owned by AWS<\/figcaption><\/figure>\n<p>Hey! Look at that! We got the number down to 1 million AMIs. While our objective was not to reduce the number of AMIs, but rather to construct a list of high potential targets, seeing a more feasible number of AMIs gives us the hope that we can scan all the AMIs worth scanning.<\/p>\n<h4 class=\"wp-block-heading\" id=\"3-2-3-amis-with-rootdevicetype-set-to-instance-store\">3.2.3 AMIs with RootDeviceType set to \u201cinstance-store\u201d<\/h4>\n<p>Doing some tests we noticed that we can\u2019t start or access AMIs that have the property <strong>RootDeviceType<\/strong> set to \u201cinstance-store\u201d. These types of AMIs have the next characteristic:<\/p>\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Amazon instance store-backed AMI \u2013 The root device for an instance launched from the AMI is an instance store volume created from a template stored in Amazon S3.<\/p>\n<p><cite><a href=\"https:\/\/docs.aws.amazon.com\/AWSEC2\/latest\/UserGuide\/ComponentsAMIs.html#storage-for-the-root-device\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/docs.aws.amazon.com\/AWSEC2\/latest\/UserGuide\/ComponentsAMIs.html#storage-for-the-root-device<\/a><\/cite><\/p><\/blockquote>\n<p>So we can\u2019t access these AMIs without the source from the S3 bucket. We decided to not scan these AMIs since we don\u2019t know where the root device is stored and since we won\u2019t have access most likely to that root device.<\/p>\n<p>Again, we did the same thing when adding the AMIs in MongoDB, we changed the \u201cRootDeviceType\u201d property with a new field called \u201cIsRootInstanceCoreType\u201d. Now that I look back, I can see that the name should have been \u201cIsRootInstance<strong>Store<\/strong>Type\u201d, but let\u2019s leave it as it is.<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: python; first-line: 25; highlight: [31]; title: ; notranslate\" title>\ndef initialize_collection(amis_collection): for region in regions: amis = get_amis_for_region(region) for ami in amis: ami['Region'] = region ami['IsInMarketplace'] = 'ProductCodes' in ami.keys() ami['IsRootInstanceCoreType'] = ami['RootDeviceType'] == 'instance-store' amis_collection.insert_one(ami) print(f\"[x] Finished for region {region}\")\n<\/pre>\n<\/div>\n<p>MongoDB query filter:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: jscript; title: ; notranslate\" title>\n{IsInMarketplace:false, ImageOwnerAlias: {$not:{$eq:\"amazon\"}}, IsRootInstanceCoreType:false}\n<\/pre>\n<\/div>\n<figure class=\"wp-block-image size-large is-resized\"><img decoding=\"async\" data-attachment-id=\"4267\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/image-11-8\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-11.png\" data-orig-size=\"936,275\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-11\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-11.png?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-11.png?w=840\" loading=\"lazy\" width=\"936\" height=\"275\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-11.png?w=936\" alt class=\"wp-image-4267\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-11.png 936w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-11.png?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-11.png?w=300 300w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-11.png?w=768 768w\" sizes=\"auto, (max-width: 936px) 100vw, 936px\"><figcaption class=\"wp-element-caption\">MongoDB Compass filter AMIs with RootDeviceType set to \u201cinstance-store\u201d<\/figcaption><\/figure>\n<p>We only removed about 5k instances with this filter, but we managed to get below 1 million AMIs. The next filter however is the big game changer.<\/p>\n<h4 class=\"wp-block-heading\" id=\"3-2-4-owners-with-more-than-50-public-amis\">3.2.4 Owners with more than 50 Public AMIs<\/h4>\n<p>Analyzing the remaining sample of AMIs, we noticed that we still have some AWS account with a large number of public AMIs.<\/p>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" data-attachment-id=\"4269\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/image-13-7\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-13.png\" data-orig-size=\"1083,448\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-13\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-13.png?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-13.png?w=840\" loading=\"lazy\" width=\"1024\" height=\"423\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-13.png?w=1024\" alt class=\"wp-image-4269\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-13.png?w=1024 1024w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-13.png?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-13.png?w=300 300w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-13.png?w=768 768w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-13.png 1083w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\"><figcaption class=\"wp-element-caption\">MongoDB Compass analysis based on OwnerId<\/figcaption><\/figure>\n<p>Checking the owners with the most AMIs we noticed that they are some kind of unofficial vendors, publishing new versions of their AMIs. Well, this is good, but how can we determine which account is some sort of vendor and which is not?<\/p>\n<p>We were looking for a threshold. Something like, if a single AWS account owns more than X AMIs, then that AWS account is likely to be an unofficial vendor and we can exclude it. In the search of that threshold, we checked how many unique AWS accounts are out there with a maximum number of 25 public AMIs. Similarly, we did the same check for a maximum number of 20, 15, 10, 5 and 1. The next file contains the results:<\/p>\n<p>Looking at this data we saw that numbers between the checked thresholds are fairly close. We factored in another thing. We assumed that no one is crazy enough to have more than 2 public AMIs on each AWS region. And imagine this: an AWS account has more than 50 public AMIs unintentionally left out there with source code, secrets, keys and so on. It felt like simply too much.<\/p>\n<p>So, we introduced what I felt to be the first trade-off. We set this threshold of maximum 50 public AMIs per AWS account. Even after almost half a year later, I still think this was a good call. Doing some scripting in Python we identified those accounts with more than 50 AMIs. You can find the list in the MangoDB filter query below:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: jscript; title: ; notranslate\" title>\n{ IsInMarketplace: false, IsRootInstanceCoreType: false, ImageOwnerAlias: {$not:{$eq:\"amazon\"}}, OwnerId: { $nin: [ \"979382823631\",\"125523088429\",\"782774275127\",\"085178109370\",\"462397596885\",\"504405067906\",\"782442783595\",\"575461648593\",\"281784684473\",\"126027368216\",\"958347557273\",\"531415883065\",\"357466774442\",\"118940168514\",\"172840064832\",\"364390758643\",\"108329106114\",\"161831738826\",\"958145178466\",\"258751437250\",\"138312800438\",\"939706979954\",\"211372476111\",\"992587258474\",\"099720109477\",\"281784684473\",\"679593333241\",\"953345546836\",\"014677528312\",\"531533671159\",\"275272412307\",\"150196106750\",\"692314432491\",\"297478128798\",\"609069431582\",\"659279834602\",\"304251891748\",\"074754820263\",\"082051669340\",\"083837402522\",\"240152784131\",\"012284807008\",\"833371238208\",\"781110569745\",\"852100819133\",\"666044672026\",\"040921035827\",\"641549025415\",\"602111481490\",\"470264848403\",\"164326021446\",\"263721492972\",\"677635134310\",\"604437731932\",\"651188399649\",\"117403053999\",\"273419675927\",\"909031101827\",\"675738832863\",\"973501904202\",\"078680276960\",\"101072000470\",\"601427279990\",\"847205733218\",\"033737991781\",\"867686887310\",\"515116089304\",\"253213882263\",\"922711891673\",\"107025636812\",\"144433228153\",\"361870911536\",\"981484854994\",\"981586224937\",\"341718127296\",\"012177264511\",\"506463145083\",\"343299325021\",\"798920643433\",\"672242615610\",\"193273892879\",\"088819544517\",\"619681448102\",\"955366579413\",\"213396452403\",\"833997227572\",\"696905082017\",\"481432522479\",\"633059600857\",\"298058684257\",\"872251088935\",\"558211695259\",\"717539892973\",\"761449685630\",\"458419666758\",\"117936542248\",\"262744063927\",\"156597721064\",\"700366075446\",\"228847291132\",\"929637706107\",\"375021575472\",\"221210582303\",\"221354433967\",\"811078382625\",\"604384805766\",\"747514752573\",\"268367799918\",\"002243364032\",\"903897969027\",\"391477561959\",\"634922670793\",\"691173103445\",\"121773538331\",\"894535543691\",\"167422901596\",\"897883143566\",\"808508158480\",\"178480506716\",\"961113262821\",\"128329325849\",\"649294524699\",\"799597332240\",\"857032533038\",\"701511253276\",\"902347396780\",\"342470128466\",\"063491364108\",\"056126556840\",\"823218754427\",\"622992712626\",\"776682305951\",\"524466471676\",\"522179138863\",\"066803512886\",\"332551323846\",\"623002322076\",\"005923036815\",\"725085649209\",\"159375186019\",\"830106197091\",\"055761336000\",\"153434714329\",\"805912557329\",\"231994803134\",\"785895325085\",\"664284451649\",\"643366669028\",\"120340763379\",\"860900021006\",\"811682917860\",\"030444862968\",\"734147683238\",\"314270375726\",\"743288062907\",\"411745053086\",\"920152662742\",\"113073460856\",\"511242591283\",\"158855661827\",\"003483243915\",\"107042026245\",\"308029823110\",\"222958650704\",\"489483686436\",\"275994140148\",\"212021838531\",\"879268495141\",\"208491357083\",\"666882590071\",\"226465381217\",\"062844181125\",\"703926772882\",\"940762080936\",\"872909225683\",\"085996170456\",\"266183714499\",\"023992783472\",\"812481205477\",\"644630763931\",\"766915741798\",\"922761411349\",\"958621391921\",\"471211731895\",\"567502172578\",\"517062167202\",\"576481180806\",\"422652172681\",\"233757773908\",\"753722448458\",\"930457884660\",\"220197662125\",\"858280671036\",\"413071817000\",\"754685078599\",\"260760892802\",\"919814621061\",\"370050660245\",\"672550935748\",\"988443417517\",\"174203920225\",\"959243851260\",\"391847209875\",\"654897662046\",\"261542671292\",\"514734236355\",\"787223699828\",\"079972220921\",\"879742242852\",\"455864098378\",\"092722883498\",\"187515304745\",\"354643243794\",\"020679151690\",\"641886270455\",\"367134611783\",\"529661837159\",\"769790836554\",\"354613140921\",\"398653132559\",\"609594173164\",\"679090434138\",\"143320424681\",\"887485515065\",\"943353741583\",\"745719312218\",\"514117492693\",\"072157914504\",\"963121779227\",\"657159205431\",\"999867407951\",\"160082703681\",\"302634334388\",\"153242070384\",\"492681118881\",\"646472328658\",\"441566271543\",\"223093067001\",\"568608671756\",\"811737349733\",\"670387110090\",\"614612213257\",\"012067661104\",\"183081753049\",\"555854959998\",\"372903911592\",\"931685398798\",\"711772050517\",\"397995763618\",\"626107101308\",\"188439194153\",\"328217207599\",\"303519801974\",\"297975325230\",\"488931611485\",\"013230744746\",\"125035497591\",\"331174399982\",\"275898483189\",\"732123782549\",\"636156223522\",\"210811600188\",\"835705546860\",\"902696655598\",\"381009627173\",\"887450378614\",\"505803097751\",\"121695370940\",\"159737981378\",\"465267886299\",\"034389035875\",\"055279482367\",\"502976614458\",\"851065383862\",\"843529240033\",\"481155165509\",\"542040705575\",\"009967377517\",\"105532983076\",\"077742499581\",\"263245908434\",\"887764444972\",\"049929217248\",\"705482507833\",\"883755651572\",\"036086565681\",\"400392161012\",\"674059360964\",\"174003430611\",\"108494951140\",\"491925185505\",\"178579023202\",\"689494258501\",\"966122790603\",\"324146450368\",\"648710915214\",\"687241535879\",\"042423532529\",\"299934467172\",\"772315742791\",\"582244788873\",\"084912087861\",\"601277729239\",\"210686502322\",\"456531263183\",\"142421590066\",\"410186602215\",\"253379484728\",\"942344369036\",\"090003032930\",\"390302536420\",\"694121914657\",\"344758251446\",\"733078701466\",\"746013851261\",\"273854932432\",\"608014515287\",\"900854079004\",\"919239153674\",\"388963328112\",\"463018831373\",\"760937637931\",\"511311637224\",\"897878824798\",\"887664104594\",\"687725076918\",\"813909747961\",\"141318035583\",\"068287425771\",\"317307795746\",\"948542851936\",\"105571261999\",\"034360980390\",\"001382923476\",\"054713022081\",\"861068367966\",\"558986605633\",\"541621974560\",\"478299826944\",\"873237481665\",\"865636555390\",\"154239132089\",\"709601304699\",\"579393713941\",\"833372943033\",\"625240141681\",\"701759196663\",\"699717368611\",\"704708324783\",\"130167558768\",\"270051122755\",\"415789037893\",\"235279919161\",\"893612263489\",\"098706035825\",\"560348900601\",\"549196663111\",\"635144173025\",\"971246865984\",\"764336703387\",\"904411313395\",\"801328867837\",\"227120241369\",\"371522382791\",\"816268476753\",\"247716482002\",\"142548018081\",\"817633883686\",\"578985338881\",\"649843420731\",\"617935088040\",\"328669466519\",\"160390125595\",\"320704736504\",\"701208020788\",\"995913728426\",\"312594956781\",\"022044324644\",\"582547558294\",\"155889952199\",\"346947735772\",\"428641199958\",\"675552985074\",\"849201093595\",\"080433136561\",\"511657745411\",\"148102829632\",\"044893506424\",\"434481986642\",\"838367653738\",\"000692753149\",\"216958472421\",\"233975207881\",\"007561666938\",\"895523100917\",\"466085125143\",\"821543836110\",\"763870024620\",\"589768463761\",\"131827586825\",\"851601128636\",\"322151761634\",\"700650335418\",\"572074891743\",\"723754913286\",\"119175775298\",\"795746500882\",\"917001008158\",\"068169053218\",\"792107900819\",\"536652696790\",\"976433692360\",\"515798882395\",\"483285841698\",\"942504563685\",\"965351925530\",\"544319711298\",\"600530653622\",\"748115360335\",\"940213080334\",\"362695845571\",\"686087431763\",\"086951212264\",\"688023202711\",\"706635527432\",\"728137396354\",\"895557238572\",\"496014204152\",\"200193376361\",\"089691119308\",\"459220251735\",\"166425443641\",\"573932760021\",\"605812595337\",\"383156758163\",\"890968705060\",\"406659825668\",\"710464970777\",\"734555027572\",\"072360076281\",\"379101102735\",\"400306079213\",\"020014417079\",\"800406105498\",\"921547910285\",\"057670693668\",\"214575254960\",\"643313122712\",\"807659967283\",\"793995986362\",\"411009282317\",\"055430919509\",\"149754531711\",\"766535289950\",\"137677339600\",\"282316784512\",\"474125479812\",\"519405898872\",\"330183209093\",\"262212597706\",\"910732127950\",\"143080556111\",\"538276064493\",\"915533145685\",\"562637147889\",\"840044800169\",\"762429196748\",\"867058893013\",\"657871693752\",\"174003592710\",\"421085264799\",\"181232990041\",\"374168611083\",\"540036508848\",\"042001279082\",\"855262394183\",\"952013314444\",\"666563790427\",\"146628656107\",\"161595045889\",\"067063543704\",\"101720206348\",\"075585003325\",\"185007729374\",\"980678866538\",\"867471893442\",\"797456418907\",\"903794441882\" ] } }\n<\/pre>\n<\/div>\n<p>Well, this filter brought us to the more realistic number of <strong>27,858<\/strong> AMIs.<\/p>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" data-attachment-id=\"4283\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/image-14-6\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-14.png\" data-orig-size=\"935,285\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-14\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-14.png?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-14.png?w=840\" loading=\"lazy\" width=\"935\" height=\"285\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-14.png?w=935\" alt class=\"wp-image-4283\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-14.png 935w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-14.png?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-14.png?w=300 300w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-14.png?w=768 768w\" sizes=\"auto, (max-width: 935px) 100vw, 935px\"><figcaption class=\"wp-element-caption\">MongoDB Compass filter owners with more than 50 public AMIs<\/figcaption><\/figure>\n<p>So, we removed 488 AWS accounts and their associated public AMIs. This removed 970,481 AMIs. So, to put things in perspective, as a mean, each AWS account removed had about 2000 public AMIs.<\/p>\n<p>Let\u2019s do some sanity checks and complete our list of targets.<\/p>\n<h4 class=\"wp-block-heading\" id=\"3-2-5-sanity-checks\">3.2.5 Sanity Checks<\/h4>\n<p>We are almost ready. The last step we did when filtering out instances was to set some limits in terms of volumes number and volumes size.<\/p>\n<p>Firstly, each AMI comes with one or more EBS Snapshots. These are basically the volumes (disks) associated with the AMI. And when we start an EC2 instance based, we essentially get a copy of the AMI\u2019s volumes in our account.<\/p>\n<p>When checking the remaining AMIs from MongoDB we noticed that a few AMIs had some extremely big volumes or a lot of volumes. This would have required a lot of scanning time, increased cost and overall a headache.<\/p>\n<p>As an example, we encountered AMIs with 28 volumes or with volumes big as 20 TB of data. As my colleague Matei like to cite from the Zen of Python, special cases aren\u2019t special enough to break the rules.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" data-attachment-id=\"4290\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/image-15-6\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-15.png\" data-orig-size=\"407,232\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-15\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-15.png?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-15.png?w=407\" loading=\"lazy\" width=\"407\" height=\"232\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-15.png?w=407\" alt class=\"wp-image-4290\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-15.png 407w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-15.png?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-15.png?w=300 300w\" sizes=\"auto, (max-width: 407px) 100vw, 407px\"><figcaption class=\"wp-element-caption\">Example of AMI with a volumes of 20 TB of data<\/figcaption><\/figure>\n<\/div>\n<p>So, we checked some means and we decided to filter out any AMI that has more than 3 volumes or with volumes bigger than 200 GB.<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: python; first-line: 9; highlight: [15,19]; title: ; notranslate\" title>\nfor ami in amis: bdm = ami['BlockDeviceMappings'] ebs_items = [x['Ebs'] for x in bdm if 'Ebs' in x.keys()] ebs_items = [x for x in ebs_items if 'SnapshotId' in x.keys()] if len(ebs_items) &gt; 3: bad_amis.append(ami) continue big_snapshots = [x for x in ebs_items if x['VolumeSize'] &gt; 200] if len(big_snapshots) &gt; 0: bad_amis.append(ami)\n<\/pre>\n<\/div>\n<p>We didn\u2019t know how to do this in MongoDB so we did some classic python scripting. After this final filtering we brought down the number of AMIs to <strong>26,778<\/strong>.<\/p>\n<p>And with this we managed to construct a list of targets. We were ready to start looking on ways to access the AMIs\u2019 contents \u2764\ufe0f<\/p>\n<h2 class=\"wp-block-heading\" id=\"4-accessing-the-amis\">4. Accessing the AMIs<\/h2>\n<p>For us it made sense to not look into ways of how to access the AMIs before we had a final number of AMIs. Mostly because based on how many AMIs there were, we had to prioritize either time, costs or scanning robustness.<\/p>\n<p>With 26k AMIs, we knew we had to find an option that:<\/p>\n<ul>\n<li>Must be time and cost efficient<\/li>\n<li>Must be automated<\/li>\n<li>Must be as reliable as possible<\/li>\n<\/ul>\n<h3 class=\"wp-block-heading\" id=\"4-1-failed-options\">4.1 Failed Options<\/h3>\n<p>Here are some options that might work when checking manually certain AMIs, but we couldn\u2019t use at scale.<\/p>\n<h4 class=\"wp-block-heading\" id=\"option-1\">Option 1<\/h4>\n<p>So the AMI has information about its EBS Snapshot, right? So, in theory you could copy directly the Snapshot in your account and do whatever you want with it.<\/p>\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-large is-resized\"><img decoding=\"async\" data-attachment-id=\"4295\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/image-16-6\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-16.png\" data-orig-size=\"1105,841\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-16\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-16.png?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-16.png?w=840\" loading=\"lazy\" width=\"1024\" height=\"779\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-16.png?w=1024\" alt=\"Diagram with first option of accessing AMIs\" class=\"wp-image-4295\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-16.png?w=1024 1024w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-16.png?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-16.png?w=300 300w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-16.png?w=768 768w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-16.png 1105w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\"><figcaption class=\"wp-element-caption\">Option 1 for accessing AMIs<\/figcaption><\/figure>\n<\/div>\n<p>The flow would be something like this: we copy the AMI\u2019s snapshot in our account and then we download it. Once downloaded we can mount it and access the files within.<\/p>\n<p>Well, the main problem with this is that we can\u2019t copy the EBS Snapshot in most cases. And this is something weird. When you make the AMI public, you essentially give permission to anyone to start an EC2 instance based on that EBS Snapshot. However, you have to explicitly make the EBS Snapshot public in order for this copy snapshot operation to work. In our tests we rarely encountered AMIs with public EBS Snapshots.<\/p>\n<h4 class=\"wp-block-heading\" id=\"option-2\">Option 2<\/h4>\n<p>So we have to give up the option of copying the EBS Snapshot. Let\u2019s try something else:<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large is-resized\"><img decoding=\"async\" data-attachment-id=\"4298\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/image-17-5\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-17.png\" data-orig-size=\"1159,782\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-17\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-17.png?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-17.png?w=840\" loading=\"lazy\" width=\"1024\" height=\"690\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-17.png?w=1024\" alt=\"Diagram with second option of accessing AMIs\" class=\"wp-image-4298\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-17.png?w=1024 1024w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-17.png?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-17.png?w=300 300w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-17.png?w=768 768w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-17.png 1159w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\"><figcaption class=\"wp-element-caption\">Option 2 for accessing AMIs<\/figcaption><\/figure>\n<\/div>\n<p>Let\u2019s start an EC2 instance in our AWS account based on the target AMI. So far so good. Now for accessing the AMI\u2019s contents we will make an EBS Snapshot of its volume and download it.<\/p>\n<p>This actually works great and is very reliable. I actually recommend this option when you want to check a single AMI. AWS even has a public tool for downloading EBS Snapshots and it works fantastic! It\u2019s called coldsnap: <a href=\"https:\/\/github.com\/awslabs\/coldsnap\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/awslabs\/coldsnap<\/a><\/p>\n<p>The problem with this method is that downloading EBS snapshots take a lot of time and requires a significant storage space. Both drawbacks were too hard to fix for this method of accessing the AMI, so we had to look for something else.<\/p>\n<h4 class=\"wp-block-heading\" id=\"option-3\">Option 3<\/h4>\n<p>Ok, so starting an EC2 instance based on the target AMI seems like the right track, but we have to change the part with the download. Here comes our third option:<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large is-resized\"><img decoding=\"async\" data-attachment-id=\"4301\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/image-18-4\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-18.png\" data-orig-size=\"1036,867\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-18\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-18.png?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-18.png?w=840\" loading=\"lazy\" width=\"1024\" height=\"856\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-18.png?w=1024\" alt=\"Diagram with third option of accessing AMIs\" class=\"wp-image-4301\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-18.png?w=1024 1024w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-18.png?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-18.png?w=300 300w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-18.png?w=768 768w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-18.png 1036w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\"><figcaption class=\"wp-element-caption\">Option 3 for accessing AMIs<\/figcaption><\/figure>\n<\/div>\n<p>We wanted to start an EC2 instance based on the target AMI and then connect to the instance. We thought of using either SSH or native solutions like SSM Run Command or SSM Session Manager.<\/p>\n<p>Unfortunately, none of them worked. For SSH I think AWS couldn\u2019t add a new key for the local user. Whereas for SSM, I think the version of the SSM Agent was too outdated for most of the AMIs in order to work.<\/p>\n<p>Nonetheless, from these 3 failed options we tested we arrived at the conclusion that we should do everything inside the AWS ecosystem for being the most time efficient and that we need to start an EC2 instance based on the target AMI if we want to access its contents.<\/p>\n<h3 class=\"wp-block-heading\" id=\"4-2-working-method\">4.2 Working method<\/h3>\n<p>We figured that if we can\u2019t connect to the instance that\u2019s based on the AMI, but we can start it, why not move the EBS volume to another EC2 instance. So what we did was:<\/p>\n<ul>\n<li>We started a normal EC2 instance and configured it so that it has everything required for connecting to it. We called this the Secret Searcher instance.<\/li>\n<li>Next, we start a new EC2 instance based on the target AMI<\/li>\n<li>We stop the new EC2 instance, detach its volume and terminate the instance<\/li>\n<li>Afterwards, we reattach the volume to the Secret Searcher instance<\/li>\n<li>Here we mount the volume and, well\u2026search it for secrets<\/li>\n<\/ul>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" data-attachment-id=\"4308\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/option-4-drawio\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/option-4.drawio.png\" data-orig-size=\"431,386\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"option-4.drawio\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/option-4.drawio.png?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/option-4.drawio.png?w=431\" loading=\"lazy\" width=\"431\" height=\"386\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/option-4.drawio.png?w=431\" alt=\"Secret Searcher method for accessing the AMI's contents\" class=\"wp-image-4308\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/option-4.drawio.png 431w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/option-4.drawio.png?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/option-4.drawio.png?w=300 300w\" sizes=\"auto, (max-width: 431px) 100vw, 431px\"><figcaption class=\"wp-element-caption\">Secret Searcher method for accessing the AMI\u2019s contents<\/figcaption><\/figure>\n<\/div>\n<p>The only drawback for this method is that it\u2019s not the cheapest, but that doesn\u2019t mean that will be expensive. Other than this, it ticked all the boxes for us.<\/p>\n<div class=\"wp-block-jetpack-markdown\">\n<table>\n<thead>\n<tr>\n<th>Method<\/th>\n<th>Speed<\/th>\n<th>Cost<\/th>\n<th>Reliability<\/th>\n<th>Can be automated<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>1<\/td>\n<td>Slow<\/td>\n<td>Small<\/td>\n<td>Not great<\/td>\n<td>Yes<\/td>\n<\/tr>\n<tr>\n<td>2<\/td>\n<td>Slowest<\/td>\n<td>Medium<\/td>\n<td>Great<\/td>\n<td>Yes<\/td>\n<\/tr>\n<tr>\n<td>3<\/td>\n<td>Fastest<\/td>\n<td>Biggest<\/td>\n<td>Worst<\/td>\n<td>Yes<\/td>\n<\/tr>\n<tr>\n<td><strong>4<\/strong><\/td>\n<td><strong>Fast<\/strong><\/td>\n<td><strong>Medium-Big<\/strong><\/td>\n<td><strong>Great<\/strong><\/td>\n<td><strong>Yes<\/strong><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>Doing some tests for a region with 30 public AMIs, we came to an initial estimation of $10k for this research ????<\/p>\n<p>However, after more tests we determined that the cost should not exceed $1.2k and it didn\u2019t.<\/p>\n<h3 class=\"wp-block-heading\" id=\"4-3-architecture-for-scale-scanning\">4.3 Architecture for scale scanning<\/h3>\n<p>The high level flow is like this:<\/p>\n<ul>\n<li>We have a master EC2 instance that will run the main script for automating everything.<\/li>\n<li>This instance will start and configure in a region the Secret Searcher instance and any other prerequisites<\/li>\n<li>Then, will start spawning batches of multiple EC2 instances based on target AMIs<\/li>\n<li>Once the instances are running, the master instance will stop them and detach their volume(s)<\/li>\n<li>For each AMI, the volume(s) will be reattach to the Secret Searcher instance<\/li>\n<li>In the meantime the EC2 instances without volume(s) will be terminated to cut costs<\/li>\n<li>On the Secret Searcher instance the volume(s) will be mounted and searched for secrets (more about this on next chapter)<\/li>\n<li>The collected data is uploaded to an S3 bucket for further analysis and processing<\/li>\n<li>The volume(s) will be detached and deleted immediately after the upload to S3 finishes<\/li>\n<li>The process continues until every AMI from the region is processed<\/li>\n<\/ul>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" data-attachment-id=\"4311\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/image-20-4\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-20.png\" data-orig-size=\"1564,1060\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-20\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-20.png?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-20.png?w=840\" loading=\"lazy\" width=\"1024\" height=\"694\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-20.png?w=1024\" alt=\"Architecture for scanning AMIs at scale\" class=\"wp-image-4311\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-20.png?w=1024 1024w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-20.png?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-20.png?w=300 300w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-20.png?w=768 768w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-20.png 1564w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\"><figcaption class=\"wp-element-caption\">Architecture for scanning AMIs at scale<\/figcaption><\/figure>\n<\/div>\n<p>This approached allowed us to scan multiple AWS regions in parallel and resulted in a shorter waiting time for the final results.<\/p>\n<h3 class=\"wp-block-heading\" id=\"4-4-final-considerations\">4.4 Final considerations<\/h3>\n<p>We had to decide on an instance type that would work for most the the AMIs. We picked \u201cc5.large\u201d because it\u2019s somewhat in the middle of what can support and is an instance type available in every region. Doing some tests we noticed 3 aspects.<\/p>\n<p>The first and most simple one was that in order to move the EBS Volume from the spawned EC2 instance to the Secret Searcher instance, both instance must be in the same availability zone. So we spawned all resources in the availability zone \u201c&lt;region&gt;a\u201d (e.g., eu-central-1a).<\/p>\n<p>The second one: some older AMIs had the parameter <strong>VirtualizationType<\/strong> set to \u201cparavirtual\u201d (you can read about it <a href=\"https:\/\/docs.aws.amazon.com\/AWSEC2\/latest\/UserGuide\/virtualization_types.html\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>), which is an older type of virtualization. For covering this scenario we had to use an instance type from a previous generation: <strong>c3.large<\/strong>. You can check compatibility for Paravirtual (PV) of most instance types <a href=\"https:\/\/aws.amazon.com\/amazon-linux-ami\/instance-type-matrix\/\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" data-attachment-id=\"4317\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/image-21-4\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-21.png\" data-orig-size=\"493,557\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-21\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-21.png?w=266\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-21.png?w=493\" loading=\"lazy\" width=\"493\" height=\"557\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-21.png?w=493\" alt=\"Example of AMI with VirtualizationType set to &quot;paravirtual&quot;\" class=\"wp-image-4317\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-21.png 493w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-21.png?w=195 195w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-21.png?w=266 266w\" sizes=\"auto, (max-width: 493px) 100vw, 493px\"><figcaption class=\"wp-element-caption\">Example of AMI with VirtualizationType set to \u201cparavirtual\u201d<\/figcaption><\/figure>\n<\/div>\n<p>And the last thing is that we got a high percentage of errors with the next message:<\/p>\n<ul>\n<li>[\u2026] when calling the RunInstances operation: Enhanced networking with the Elastic Network Adapter (ENA) is required for the \u2018c5.large\u2019 instancetype. Ensure that you are using an AMI that is enabled for ENA.<\/li>\n<\/ul>\n<p>This seemed a blocker because we didn\u2019t know how to fix it, but then we tried something. You see, we started all instances without a public IP. This not only reduced the costs, but it prevented any startup script or tool to call home, to its owner. Even more, I think this is what kept us under to radar from AWS themself and didn\u2019t get us blocked.<\/p>\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" data-attachment-id=\"4324\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/8mjiy8\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/8mjiy8.jpg\" data-orig-size=\"503,496\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"8mjiy8\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/8mjiy8.jpg?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/8mjiy8.jpg?w=503\" loading=\"lazy\" width=\"503\" height=\"496\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/8mjiy8.jpg?w=503\" alt=\"Meme about AWS usage\" class=\"wp-image-4324\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/8mjiy8.jpg 503w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/8mjiy8.jpg?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/8mjiy8.jpg?w=300 300w\" sizes=\"auto, (max-width: 503px) 100vw, 503px\"><\/figure>\n<\/div>\n<p>Anyway, we tried to manually spawn an EC2 that had the ENA error, but with a public IP and magically the error disappeared. Also, when we spawned this instance manually we used the instance type \u201ct2.medium\u201d. Doing a little more digging, we saw this bullet point for C5 instance type:<\/p>\n<ul>\n<li>Requires HVM AMIs that include drivers for ENA and NVMe<\/li>\n<\/ul>\n<p>I\u2019m not sure what it means, but my guess is that C5 instances require some prerequisites in order to have ENA enabled, whereas T2 instances don\u2019t.<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: python; first-line: 239; highlight: [240,242,244,249,250,256,278]; title: ; notranslate\" title>\ntry: instance_type = 'c5.large' if 'VirtualizationType' in ami_object and ami_object['VirtualizationType'] == 'paravirtual': instance_type = 'c3.large' elif is_ena: instance_type = 't2.medium' instance = None if is_ena == False: instance = ec2.run_instances(InstanceType=instance_type, Placement={'AvailabilityZone':f'{region}{availability_zone}'}, NetworkInterfaces=[{'AssociatePublicIpAddress':False, 'DeviceIndex':0}], MaxCount=1, MinCount=1, ImageId=ami_object['ImageId'], TagSpecifications=[{'ResourceType': 'instance', 'Tags':tags}]) else: instance = ec2.run_instances(InstanceType=instance_type, Placement={'AvailabilityZone':f'{region}{availability_zone}'}, MaxCount=1, MinCount=1, ImageId=ami_object['ImageId'], TagSpecifications=[{'ResourceType': 'instance', 'Tags':tags}]) instance_id = instance['Instances'][0]['InstanceId'] print(f'[x] Instance {instance_id} started. Waiting to become running.') waiter = ec2.get_waiter('instance_running') waiter.wait(InstanceIds=[instance_id], WaiterConfig={'Delay': 5, 'MaxAttempts': 120}) print(f\"[x] Instance {instance_id} based on ami {ami_object['ImageId']} is ready.\") return {\"instanceId\": instance_id, \"ami\": ami_object['ImageId']} except Exception as e: error = 'failed ' if hasattr(e, 'message'): error = f'{error} {e.message}' else: error = f'{error} {e}' if '(ENA)' in error and is_ena == False: return start_instance_with_target_ami(ami_object, region, is_ena=True) else:\n<\/pre>\n<\/div>\n<h2 class=\"wp-block-heading\" id=\"5-digging-for-secrets\">5. Digging for secrets<\/h2>\n<p>To recap, we are now at the point where we have the AMI\u2019s volume mounted and we need to search it. We decided to use SSM Run Command for running a remote script that will mount the volume, scan its contents and upload the results in an S3 Bucket.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" data-attachment-id=\"4331\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/flow-secret-searching\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/flow-secret-searching.png\" data-orig-size=\"515,412\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"flow-secret-searching\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/flow-secret-searching.png?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/flow-secret-searching.png?w=515\" loading=\"lazy\" width=\"515\" height=\"412\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/flow-secret-searching.png?w=515\" alt=\"Diagram with execution flow for secret searching\" class=\"wp-image-4331\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/flow-secret-searching.png 515w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/flow-secret-searching.png?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/flow-secret-searching.png?w=300 300w\" sizes=\"auto, (max-width: 515px) 100vw, 515px\"><figcaption class=\"wp-element-caption\">Secret searching flow<\/figcaption><\/figure>\n<\/div>\n<h3 class=\"wp-block-heading\" id=\"5-1-mounting\">5.1 Mounting<\/h3>\n<p>I think mounting was the biggest challenge in terms of automation. We had to identify the volume\u2019s filesystem type, mount the right partition (if it was partitioned) and fix UUID collisions.<\/p>\n<p>We looked for an existing tool to do all of this, but we couldn\u2019t find anything. We ended up using udisksctl for mounting because it tries to detect the proper filesystem type (ext, xfs and so on).<\/p>\n<p>Let\u2019s take a look at the next image for discussing UUID collision and partitioning.<\/p>\n<figure class=\"wp-block-image size-large is-resized\"><img decoding=\"async\" data-attachment-id=\"4334\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/image-22-3\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-22.png\" data-orig-size=\"1504,284\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-22\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-22.png?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-22.png?w=840\" loading=\"lazy\" width=\"1024\" height=\"193\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-22.png?w=1024\" alt=\"root volume and attached volume with UUID collision\" class=\"wp-image-4334\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-22.png?w=1024 1024w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-22.png?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-22.png?w=300 300w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-22.png?w=768 768w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-22.png 1504w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\"><figcaption class=\"wp-element-caption\">UUID collision between root volume and attached volume<\/figcaption><\/figure>\n<p>For an unknown reason, we encountered a lot of UUID collisions when attaching a new volume to the Secret Searcher instance. The issue with this is that you can\u2019t mount a second volume with the same UUID as a mounted one. There are tools specific to the filesystem\u2019s type to fix this: <strong>xfs_admin<\/strong> for xfs volumes and <strong>tune2fs<\/strong> for ext4 volumes.<\/p>\n<p>And the last challenge was that most of the volumes had multiple partitions. In the image above we can see that the attached volume (xvdf) has 3 partitions. We had to identify the right one to mount and search. Now, you might say that the right one is the one with the biggest size.<\/p>\n<p>Well, it\u2019s not so easy to extract and compare this information using bash. Even more, there are volumes with multiple storage partitions and we didn\u2019t want to take only the biggest partition in size.<\/p>\n<p>To overcome this, we did something less elegant, but practical. We tried to mount and scan every partition no matter if its usage. And, well\u2026it worked fine ????<\/p>\n<h3 class=\"wp-block-heading\" id=\"5-2-finding-secrets\">5.2 Finding secrets<\/h3>\n<p>We decided that there is too much work to write code to look for any possible secret and sensitive information, so we tried a few tools like <a href=\"https:\/\/github.com\/trufflesecurity\/trufflehog\">truffleh<\/a><a href=\"https:\/\/github.com\/trufflesecurity\/trufflehog\" target=\"_blank\" rel=\"noreferrer noopener\">o<\/a><a href=\"https:\/\/github.com\/trufflesecurity\/trufflehog\">g<\/a> and <a href=\"https:\/\/github.com\/peass-ng\/PEASS-ng\/blob\/master\/linPEAS\/README.md\" target=\"_blank\" rel=\"noreferrer noopener\">linpeas<\/a>. The drawback was that a scan on a 8 GB AMI took around 10-15 minutes with trufflehog and 30 minutes with linpeas. Multiply that with 26,778 and you\u2019ll never finish.<\/p>\n<p>The solution? <strong>find<\/strong>!<\/p>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" data-attachment-id=\"4339\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/a\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/a.jpg\" data-orig-size=\"888,499\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"a\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/a.jpg?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/a.jpg?w=840\" loading=\"lazy\" width=\"888\" height=\"499\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/a.jpg?w=888\" alt=\"meme always had been\" class=\"wp-image-4339\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/a.jpg 888w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/a.jpg?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/a.jpg?w=300 300w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/a.jpg?w=768 768w\" sizes=\"auto, (max-width: 888px) 100vw, 888px\"><\/figure>\n<p>Yep, we decided to use <strong>find<\/strong>. And we did it like this: we made a small list of things we wanted to check and have fun with. The most important ones were AWS access keys from the .aws directory and potential private Git repositories. Next in line were SSH keys and typical web application configuration files like config.php, web.config, .env and so on.<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: bash; title: ; notranslate\" title>\nfind $mount_point \\( ! -path \"$mount_point\/Windows\/*\" -a ! -path \"$mount_point\/Program Files\/*\" -a ! -path \"$mount_point\/Program Files \\(x86\\)\/*\" \\) -size -25M \\ \\( -name \".aws\" -o -name \".ssh\" -o -name \"credentials.xml\" \\ -o -name \"secrets.yml\" -o -name \"config.php\" -o -name \"_history\" \\ -o -name \"autologin.conf\" -o -name \"web.config\" -o -name \".env\" \\ -o -name \".git\" \\) -not -empty\n<\/pre>\n<\/div>\n<p>However, we had this strong fear of missing out important things so we decided to do something complementary. Besides a few folders, we indexed the whole volume. We made a list of all the files, along with their full path, so that we can later analyze it in case needed. This way we won\u2019t have to come back to scanning all the public AMIs, but rather check what AMIs contain the files of interest for us.<\/p>\n<p>A redacted snippet for one AMI would look like this:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: plain; title: ; notranslate\" title>\n\/var\/lib\/cloud\/instances\/i-00000000000000000\/sem\/config_rsyslog\n\/var\/lib\/cloud\/instances\/i-00000000000000000\/sem\/config_runcmd\n\/var\/lib\/cloud\/instances\/i-00000000000000000\/sem\/config_scripts_per_instance\n\/var\/lib\/cloud\/instances\/i-00000000000000000\/sem\/config_scripts_user\n\/var\/lib\/cloud\/instances\/i-00000000000000000\/sem\/config_set_hostname\n\/var\/lib\/cloud\/instances\/i-00000000000000000\/sem\/config_set_passwords\n\/var\/lib\/cloud\/instances\/i-00000000000000000\/sem\/config_ssh\n\/var\/lib\/cloud\/instances\/i-00000000000000000\/sem\/config_ssh_authkey_fingerprints\n\/var\/lib\/cloud\/instances\/i-00000000000000000\/sem\/config_timezone\n\/var\/lib\/cloud\/instances\/i-00000000000000000\/sem\/config_users_groups\n\/var\/lib\/cloud\/instances\/i-00000000000000000\/sem\/config_write_files\n\/var\/lib\/cloud\/instances\/i-00000000000000000\/sem\/config_write_metadata\n\/var\/lib\/cloud\/instances\/i-00000000000000000\/sem\/config_yum_add_repo\n\/var\/lib\/cloud\/instances\/i-00000000000000000\/sem\/config_yum_configure\n\/var\/lib\/cloud\/instances\/i-00000000000000000\/sem\/consume_data\n\/var\/lib\/cloud\/instances\/i-00000000000000000\/user-data.txt.i\n\/var\/lib\/cloud\/instances\/i-00000000000000000\/vendor-data.txt\n\/var\/lib\/cloud\/instances\/i-00000000000000000\/vendor-data.txt.i\n\/var\/lib\/cloud\/instances\/i-11111111111111111\n\/var\/lib\/cloud\/instances\/i-11111111111111111\/boot-finished\n\/var\/lib\/cloud\/instances\/i-11111111111111111\/datasource\n\/var\/lib\/cloud\/instances\/i-11111111111111111\/obj.pkl\n\/var\/lib\/cloud\/instances\/i-11111111111111111\/sem\n\/var\/lib\/cloud\/instances\/i-11111111111111111\/sem\/config_keys_to_console\n\/var\/lib\/cloud\/instances\/i-11111111111111111\/sem\/config_locale\n\/var\/lib\/cloud\/instances\/i-11111111111111111\/sem\/config_mounts\n\/var\/lib\/cloud\/instances\/i-11111111111111111\/sem\/config_package_update_upgrade_install\n\/var\/lib\/cloud\/instances\/i-11111111111111111\/sem\/config_phone_home\n\/var\/lib\/cloud\/instances\/i-11111111111111111\/sem\/config_power_state_change\n\/var\/lib\/cloud\/instances\/i-11111111111111111\/sem\/config_puppet\n\/var\/lib\/cloud\/instances\/i-11111111111111111\/sem\/config_resolv_conf\n\/var\/lib\/cloud\/instances\/i-11111111111111111\/sem\/config_rsyslog\n\/var\/lib\/cloud\/instances\/i-11111111111111111\/sem\/config_runcmd\n\/var\/lib\/cloud\/instances\/i-11111111111111111\/sem\/config_scripts_per_instance\n\/var\/lib\/cloud\/instances\/i-11111111111111111\/sem\/config_scripts_user\n\/var\/lib\/cloud\/instances\/i-11111111111111111\/sem\/config_set_hostname\n\/var\/lib\/cloud\/instances\/i-11111111111111111\/sem\/config_set_passwords\n\/var\/lib\/cloud\/instances\/i-11111111111111111\/sem\/config_ssh\n\/var\/lib\/cloud\/instances\/i-11111111111111111\/sem\/config_ssh_authkey_fingerprints\n\/var\/lib\/cloud\/instances\/i-11111111111111111\/sem\/config_timezone\n\/var\/lib\/cloud\/instances\/i-11111111111111111\/sem\/config_users_groups\n\/var\/lib\/cloud\/instances\/i-11111111111111111\/sem\/config_write_files\n\/var\/lib\/cloud\/instances\/i-11111111111111111\/sem\/config_write_metadata\n\/var\/lib\/cloud\/instances\/i-11111111111111111\/sem\/config_yum_add_repo\n\/var\/lib\/cloud\/instances\/i-11111111111111111\/sem\/config_yum_configure\n\/var\/lib\/cloud\/instances\/i-11111111111111111\/sem\/consume_data\n\/var\/lib\/cloud\/instances\/i-11111111111111111\/user-data.txt.i\n\/var\/lib\/cloud\/instances\/i-11111111111111111\/vendor-data.txt\n\/var\/lib\/cloud\/instances\/i-11111111111111111\/vendor-data.txt.i\n<\/pre>\n<\/div>\n<p>We think that our trade-off gives other researchers space to conduct their analysis on specific files that were not covered by us.<\/p>\n<p>All data found was copied from the volume\u2019s location to our user\u2019s home folder and then uploaded in an S3 bucket for further analysis and validation. After the upload completed we deleted the copied files, unmounted the volume and continued.<\/p>\n<p>One fun fact before moving forward: in our initial tests we got a few unknown causes that broke the Secret Searcher instance. It turned out that the .git folders had more than 8 GB of data and when we tried to copy them in our user\u2019s home folder (in a volume of 8 GB), the instance crashed. Once we modified the configuration of the Secret Searcher to use 50 GB instead of 8 everything went well ????<\/p>\n<h3 class=\"wp-block-heading\" id=\"5-3-looking-through-private-git-repositories\">5.3 Looking through private Git repositories<\/h3>\n<p>We gathered thousands of repositories worth of over 400 GB of data. The idea with the repositories was that they might contain hard-coded credentials. This was especially and insight coming from Matei as I was very skeptical on this (spoiler: he was right).<\/p>\n<p>We decided that for now there is no point in determining which repository is private and which one is public. We just wanted a way to scan them for secrets and for that we used <a href=\"https:\/\/github.com\/gitleaks\/gitleaks\" target=\"_blank\" rel=\"noreferrer noopener\">gitleaks<\/a>.<\/p>\n<p>As you might expect, we didn\u2019t run gitleaks on the S3 bucket. We had to download everything on a physical hard drive.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" data-attachment-id=\"4347\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/3-2\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/3.jpg\" data-orig-size=\"600,471\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"3\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/3.jpg?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/3.jpg?w=600\" loading=\"lazy\" width=\"600\" height=\"471\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/3.jpg?w=600\" alt=\"meme git secrets\" class=\"wp-image-4347\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/3.jpg 600w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/3.jpg?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/3.jpg?w=300 300w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\"><\/figure>\n<\/div>\n<p>Gitleaks proved to be a fantastic tool that checked for secrets across all commits. Of course, we also had a big number of false positives on some types of credentials, but we\u2019ll talk more about them on the next chapter.<\/p>\n<h2 class=\"wp-block-heading\" id=\"6-results\">6. Results<\/h2>\n<h3 class=\"wp-block-heading\" id=\"6-1-aws-keys\">6.1 AWS Keys<\/h3>\n<p>This was our main focus during this research mostly because it can give access to an AWS environment starting from an AWS misconfiguration.<\/p>\n<p>Throughout this piece of research, we obtained over 200 valid AWS credentials. These were obtained from 4 sources: \/home\/&lt;user&gt;\/.aws\/credentials, Git repositories, .env folders, \/home\/&lt;user&gt;\/.aws\/config. After concatenating the data from all the sources, we had to clean up and validate the data. So, we made sure to place the hundreds of potential AWS credentials in %UserProfile%\/.aws\/credentials, making sure that the profile names are numeric and sequential. Then, we ran the following batch command to test each set of credentials:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: powershell; title: ; notranslate\" title>\nfor \/L %i in (1, 1, &lt;REPLACE WITH NUMBER OF PROFILES&gt;) do ( echo %i &amp; aws sts get-caller-identity --profile %i &gt; %i.txt\n<\/pre>\n<\/div>\n<p>Then, we ran the following batch script to check which profiles were valid:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: powershell; title: ; notranslate\" title>\n@echo off\nsetlocal enabledelayedexpansion rem Loop through all files in the current directory\nfor %%F in (*) do ( rem Check if the file is not empty if %%~zF GTR 0 ( rem Print the name of the non-empty file echo Non-empty file: %%F echo %%F &gt;&gt; non_empty.txt ) else ( rem Delete the empty file del \"%%F\" echo Deleted empty file: %%F )\n) pause\n<\/pre>\n<\/div>\n<p>Lastly, back on our Linux machine we transferred non_empty.txt and ran the following one-liner to only keep the valid credentials:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: bash; title: ; notranslate\" title>\nfor i in $(cat non_empty.txt | awk -F. '{print $1}');do grep \"\\[$i\\]\" clean_creds -A3;done &gt; credentials\n<\/pre>\n<\/div>\n<p>From the <strong>.aws\/credentials<\/strong> and other configuration files we managed to get over 60 valid AWS credentials. This is actually us when we validated the first pair of access keys:<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" data-attachment-id=\"4355\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/meme-p\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/meme-p.gif\" data-orig-size=\"258,172\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"meme-p\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/meme-p.gif?w=258\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/meme-p.gif?w=258\" loading=\"lazy\" width=\"258\" height=\"172\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/meme-p.gif?w=258\" alt=\"gif meme pleasure\" class=\"wp-image-4355\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/meme-p.gif 258w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/meme-p.gif?w=220 220w\" sizes=\"auto, (max-width: 258px) 100vw, 258px\"><\/figure>\n<\/div>\n<p>The way we validated them was with the command \u201caws sts get-caller-identity\u201d. The crazy part is that among these 50 pair of access keys, about 10 were from the root user account. This meant that we got full control over more than 10 AWS accounts.<\/p>\n<p>Well, this is not all. The Git repositories proved to be a gold mine of secrets. We managed to get over 100 valid AWS keys. Again, with about 10 of them being for the root user account.<\/p>\n<p>We noticed that some of them were duplicates. So, after removing the duplicates our results looked like this:<\/p>\n<ul>\n<li>121 valid AWS access keys<\/li>\n<li>20 of them being from the root user account<\/li>\n<\/ul>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" data-attachment-id=\"4357\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/attachment\/4\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/4.jpg\" data-orig-size=\"500,500\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"4\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/4.jpg?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/4.jpg?w=500\" loading=\"lazy\" width=\"500\" height=\"500\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/4.jpg?w=500\" alt=\"meme pikachu surprised\" class=\"wp-image-4357\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/4.jpg 500w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/4.jpg?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/4.jpg?w=300 300w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\"><\/figure>\n<\/div>\n<p>We\u2019ll talk later more about impact, but for now we\u2019d like to highlight that out of nothing we got, only from public resources, access into 120+ AWS accounts and full access into 20 of them.<\/p>\n<h3 class=\"wp-block-heading\" id=\"6-2-secrets-extracted-from-git-repositories\">6.2 Secrets extracted from Git repositories<\/h3>\n<p>Something we simply didn\u2019t think of was that there were more repositories per AMI. For some reason I thought there will be only one. Running gitleaks on all of them took about 48 hours of continuous scanning. The results? Well\u2026<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: plain; title: ; notranslate\" title> 2077989 Generic API Key 105322 AWS 23738 Private Key 22936 JSON Web Token 3038 Telegram Bot API Token 2382 GCP API key 1075 Slack token 1007 Slack Webhook 937 Stripe 213 Twitter API Key 211 GitHub Personal Access Token 209 Twitter Access Secret 206 Twitter API Secret 165 EasyPost API token\n&nbsp;148 SumoLogic Access&nbsp;ID 134 Twilio API Key 118 Algolia API Key 105 SendGrid API token 96 Facebook 80 Okta Access Token 70 EasyPost test API token 56 SumoLogic Access Token 55 GitHub OAuth Access Token 42 Flutterwave Secret Key 42 Flutterwave Encryption Key 42 Finicity Public Key 40 GitHub App Token 20 GitHub Refresh Token 15 HubSpot API Token 14 Alibaba AccessKey ID 12 Mailgun private API token 12 Databricks API token 9 Zendesk Secret Key 7 Sentry Access Token 6 LinkedIn Client ID 6 Flickr Access Token 4 LinkedIn Client secret 4 Dropbox API secret 3 Twitter Access Token 3 Codecov Access Token 3 Adobe Client Secret 2 Microsoft Teams Webhook 2 Mailgun public validation key 2 Lob Publishable API Key 2 Lob API Key 2 Coinbase Access Token 1 Shippo API token 1 Pulumi API token 1 Kucoin Secret Key 1 Kucoin Access Token 1 Intercom API Token 1 GitLab Personal&nbsp;Access&nbsp;Token\n<\/pre>\n<\/div>\n<p>Two challenges appeared now:<\/p>\n<ol>\n<li>We need to remove false positives<\/li>\n<li>We need to check if the secrets are valid<\/li>\n<\/ol>\n<p>At the moment of writing this we validated only around half of the categories identified. The most relevant results:<\/p>\n<ul>\n<li>100+ valid sets of AWS access keys<\/li>\n<li>10+ valid Stripe live API keys<\/li>\n<li>1 valid set of Alibaba access keys<\/li>\n<li>10+ GitLab\/GitHub tokens<\/li>\n<\/ul>\n<p>For some secrets, like AWS keys, gitleaks extracted only the access key id and the commit id. We had to write a script for extracting the secret access key. While it appeared complicated at first, we used \u201cgit show &lt;commit-id&gt;:&lt;file-path&gt;\u201d inside a python script and went actually really fine.<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: python; title: ; notranslate\" title>\ndef get_file_contents_from_commit(commit_and_file_path, repo_folder): try: result = subprocess.run(['git', 'show', f'{commit_and_file_path}'], capture_output=True, text=True, check=True, cwd=repo_folder, encoding='utf-8') return result.stdout except: return None\n<\/pre>\n<\/div>\n<h3 class=\"wp-block-heading\" id=\"6-3-secrets-from-config-files\">6.3 Secrets from config files<\/h3>\n<p>What else we got from the configuration files we scanned? Well, all kinds of things:<\/p>\n<ul>\n<li>A lot of gmail credentials<\/li>\n<li>AWS access keys<\/li>\n<li>A lot of tokens from communication services <\/li>\n<li>Private SSH keys<\/li>\n<li>DB connection strings<\/li>\n<li>Keys for back-end APIs<\/li>\n<li>Secrets for signing JWTs<\/li>\n<li>Keys\/tokens\/secrets for various services<\/li>\n<\/ul>\n<p>And just everything you can imagine and it can be found in the configuration file of a web application.<\/p>\n<p>Truth to be told, except for AWS access keys, we didn\u2019t investigate these files in details as it would have took too much time. The most interesting thing we took from this was that people are still hard-coding secrets in web application config files under the false sense of safety that the repository is private.<\/p>\n<h2 class=\"wp-block-heading\" id=\"7-impact\">7. Impact<\/h2>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" data-attachment-id=\"4446\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/8p1t6i\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/05\/8p1t6i.jpg\" data-orig-size=\"500,686\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"8p1t6i\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/05\/8p1t6i.jpg?w=219\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/05\/8p1t6i.jpg?w=500\" loading=\"lazy\" width=\"500\" height=\"686\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/05\/8p1t6i.jpg?w=500\" alt class=\"wp-image-4446\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/05\/8p1t6i.jpg 500w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/05\/8p1t6i.jpg?w=160 160w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/05\/8p1t6i.jpg?w=219 219w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\"><\/figure>\n<\/div>\n<p>Here we\u2019ll talk about the impact that a malicious actor might have caused with the collected secrets. Is hard to properly quantify this because, first, we didn\u2019t finish processing the data, but second, we didn\u2019t investigate the full extend of what we can do with the permissions from valid credentials.<\/p>\n<p>So we had over 120 valid AWS access keys, 18 of them being from the root user. This means that we theoretically fully compromised 18 AWS accounts. But even here we don\u2019t know if these accounts are holding the whole infrastructure of the company or it\u2019s just a dev account.<\/p>\n<p>Ok, but let\u2019s assume the worst for a minute. Let\u2019s assume that these accounts were production accounts. Well, you can imagine what would be like to have a foothold inside the cloud infrastructure of big companies that operate in domains like networking equipment, automation, fintech, health research, aerospace research, satellite navigation, universities, software outsourcing , telecommunication and more.<\/p>\n<p>Imagine backdooring a fintech application that collaborates with multiple international banks. Or backdooring a network equipment. Maybe shutting down critical components for satellite navigation or espionage and sabotage on research facilities. And let\u2019s not forget about stealing customer data and ransomware.<\/p>\n<p>All this from the AWS accounts, but we got tons of other secrets, remember?<\/p>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" data-attachment-id=\"4447\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/8p1vp1\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/05\/8p1vp1.jpg\" data-orig-size=\"929,318\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"8p1vp1\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/05\/8p1vp1.jpg?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/05\/8p1vp1.jpg?w=840\" loading=\"lazy\" width=\"929\" height=\"318\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/05\/8p1vp1.jpg?w=929\" alt class=\"wp-image-4447\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/05\/8p1vp1.jpg 929w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/05\/8p1vp1.jpg?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/05\/8p1vp1.jpg?w=300 300w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/05\/8p1vp1.jpg?w=768 768w\" sizes=\"auto, (max-width: 929px) 100vw, 929px\"><\/figure>\n<p>We got a lot of SMTP credentials. Why bother hacking the company when you can send phishing emails using the official email address? But why bother sending phishing emails when you can generate password reset emails and read the email?<\/p>\n<p>Next we have Git tokens\/keys that give access to private repos. Now we\u2019re talking about backdoor or supply chain attacks. We also have thousands of social media secrets. This can lead to defamation or account takeover. And with other keys from various pay-as-you-go services, it would be possible to inflict additional costs on the legitimate owners.<\/p>\n<p>What about all the source code from thousands of private git repositories? Well, we can look into it and find zero days. For some repos we found the secret key for signing JWTs. Imagine how fun it would be to analyze the source code, sign admin tokens and use them on the production running application.<\/p>\n<p>To top it all off, let\u2019s not forget about the Stripe keys that summed up could have made us $40k richer.<\/p>\n<p>We have to admit that it is a bit overwhelming and unexpected how much impact this research showed in the end.<\/p>\n<h2 class=\"wp-block-heading\" id=\"7-responsible-disclosure\">8. Responsible disclosure<\/h2>\n<p>We have a treasure of secrets and a potential impressive level of access. Now it\u2019s time for the most important and boring part of the research: responsible disclosure.<\/p>\n<h3 class=\"wp-block-heading\" id=\"7-1-owners-of-aws-access-keys\">8.1 Owners of AWS access keys<\/h3>\n<p>First off, AWS access keys. If you ever found a pair of AWS access keys, you might know that it\u2019s not always straightforward to find who owns the AWS account and how can you contact them. We ended up using the a few CLI calls for trying to get the contact information:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: bash; title: ; notranslate\" title>\naws account get-contact-information\naws account get-alternate-contact --alternate-contact-type SECURITY\naws account get-alternate-contact --alternate-contact-type BILLING\naws account get-alternate-contact --alternate-contact-type OPERATIONS\n<\/pre>\n<\/div>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" data-attachment-id=\"4400\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/image-34\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-34.png\" data-orig-size=\"625,256\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-34\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-34.png?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-34.png?w=625\" loading=\"lazy\" width=\"625\" height=\"256\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-34.png?w=625\" alt class=\"wp-image-4400\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-34.png 625w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-34.png?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-34.png?w=300 300w\" sizes=\"auto, (max-width: 625px) 100vw, 625px\"><figcaption class=\"wp-element-caption\">Example response for contact information<\/figcaption><\/figure>\n<\/div>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" data-attachment-id=\"4370\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/1-3\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/1.jpg\" data-orig-size=\"500,500\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"1\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/1.jpg?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/1.jpg?w=500\" loading=\"lazy\" width=\"500\" height=\"500\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/1.jpg?w=500\" alt=\"bernie meme\" class=\"wp-image-4370\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/1.jpg 500w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/1.jpg?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/1.jpg?w=300 300w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\"><\/figure>\n<\/div>\n<p>Well, that was easy, right? Not really ????. From the 120+ valid access keys, only about 5 had a valid contact email set. Most of them only had a website referred or even worse, were owned by individuals not companies.<\/p>\n<p>At this point the situation is like this: we have about 5 AWS accounts with valid contact emails and about 70 AWS accounts with a website referred. For these 70+ accounts, we had to search their website and find a a contact email, which proved to be harder than one might imagine.<\/p>\n<p>The rest of them didn\u2019t provided enough information to be identifiable or the user\u2019s access keys didn\u2019t have permissions to make these API calls. And there is one additional aspect. I can very well write in my AWS account at the contact details that I\u2019m Amazon\/Microsoft\/Google and nobody will stop me. We had to be careful how we disclose the issue to the presumed owner.<\/p>\n<p>For the cases where contact details were not available, we went back to the ethical considerations and decided not to poke any further and to contact AWS directly. However, this area could be very fruitful for malicious actors. For instance, an attacker could easily target data in the S3 buckets associated with the account in ransomware attacks. &nbsp;<\/p>\n<p>Anyway, our initial disclosure email looked like this:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: plain; title: ; notranslate\" title>\nHello, Me and my colleague Matei Josephs are working on a cybersecurity research in the cloud area. During this research we identified that you are exposing the AWS credentials of the user &lt;username&gt; from AWS account 12345EXAMPLE among other things. We estimate that the risk of this issue is critical. What would be the appropriate communication channel for sharing more information about this security issue? Thank you,\nEduard Agavriloae\n<\/pre>\n<\/div>\n<p>We wanted companies to confirm that they own the mentioned resources before telling them the detailed issue.<\/p>\n<p>After 90 days from the initial disclosure email sent to over 70 companies, we got about 5 responses. How many AWS access keys were still valid after all this time? Well, all of them except 10.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" data-attachment-id=\"4373\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/attachment\/44\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/44.jpg\" data-orig-size=\"500,680\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"44\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/44.jpg?w=221\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/44.jpg?w=500\" loading=\"lazy\" width=\"500\" height=\"680\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/44.jpg?w=500\" alt=\"meme bike falls\" class=\"wp-image-4373\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/44.jpg 500w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/44.jpg?w=162 162w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/44.jpg?w=221 221w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\"><\/figure>\n<\/div>\n<p>In the end we provided a partially redacted list of the remaining valid AWS access credentials directly to AWS in the hope that they will be able to contact the owners more easily than us.<\/p>\n<h4 class=\"wp-block-heading\" id=\"8-1-1-working-with-aws-s-security-team\">8.1.1 Working with AWS\u2019s security team<\/h4>\n<p>This was our last stop before publishing the article. We wanted to reduce the impact of the affected AWS customers before going public. I have to say that before working with AWS\u2019s changed the perspective we built about responsible disclosure. Their team was so open, curious and helpful that\u2019s hard to describe.<\/p>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" data-attachment-id=\"4438\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/8p1jsy\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/05\/8p1jsy.jpg\" data-orig-size=\"687,500\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"8p1jsy\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/05\/8p1jsy.jpg?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/05\/8p1jsy.jpg?w=687\" loading=\"lazy\" width=\"687\" height=\"500\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/05\/8p1jsy.jpg?w=687\" alt class=\"wp-image-4438\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/05\/8p1jsy.jpg 687w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/05\/8p1jsy.jpg?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/05\/8p1jsy.jpg?w=300 300w\" sizes=\"auto, (max-width: 687px) 100vw, 687px\"><\/figure>\n<p>After our notification, AWS quickly notified customers of the reported exposed AWS Keys. Then we set a meeting with them where we detailed our research, the results and exchanged ideas around it. Turns out that what we did not only was legal, but we didn\u2019t even violate any Terms&amp;Conditions. We\u2019ll talk more about how this can be fixed from our point of view and what we discussed with AWS at the end of the article.<\/p>\n<p>Making another check on the AWS keys after two weeks, now we had only 58 valid one. The notification from AWS certainly did more than we could, but the remaining number of valid keys is still high.<\/p>\n<h3 class=\"wp-block-heading\" id=\"7-2-other-keys\">8.2 Other keys<\/h3>\n<p>When other keys were involved, it was actually easier to determine the owner. For example, for all the Stripe keys we found, we were able to access the owner\u2019s invoices which allowed us to immediately determine the owner and a contact email.<\/p>\n<p>Similar story with Git tokens. And similar story with the disclosure emails. Very low response rate and fix rate. For Stripe keys we contacted Stripe and ask for their help in fixing this.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" data-attachment-id=\"4375\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/attachment\/1231\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/1231.jpg\" data-orig-size=\"577,432\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"1231\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/1231.jpg?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/1231.jpg?w=577\" loading=\"lazy\" width=\"577\" height=\"432\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/1231.jpg?w=577\" alt=\"meme change my mind\" class=\"wp-image-4375\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/1231.jpg 577w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/1231.jpg?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/1231.jpg?w=300 300w\" sizes=\"auto, (max-width: 577px) 100vw, 577px\"><\/figure>\n<\/div>\n<h2 class=\"wp-block-heading\" id=\"8-stories-worth-telling\">9. Stories worth telling<\/h2>\n<h3 class=\"wp-block-heading\" id=\"8-1-gitlab-personal-access-token\">9.1 GitLab Personal Access Token<\/h3>\n<p>A GitLab personal access token was found for a large FinTech provider. While we would rather not disclose the provider by name, here are some of their partners and clients:<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" data-attachment-id=\"4379\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/image-24-2\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-24.png\" data-orig-size=\"624,121\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-24\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-24.png?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-24.png?w=624\" loading=\"lazy\" width=\"624\" height=\"121\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-24.png?w=624\" alt=\"redacted image with clients and partners\" class=\"wp-image-4379\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-24.png 624w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-24.png?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-24.png?w=300 300w\" sizes=\"auto, (max-width: 624px) 100vw, 624px\"><figcaption class=\"wp-element-caption\">Redacted list of partners of FinTech company<\/figcaption><\/figure>\n<\/div>\n<p>The GitLab personal access token gave us at least read access to the private repositories of the company. This is the point where we stopped digging as we already knew that the impact was quite high and decided to report the issue as quickly as possible. We tried to get in touch with their displayed contacts, but we did not get any response.<\/p>\n<p>This is when we decided to involve the Computer Emergency Response Team (CERT) for the country where the company was based. After follow-ups from the CERT, here is the response:<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large is-resized\"><img decoding=\"async\" data-attachment-id=\"4382\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/image-25-2\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-25.png\" data-orig-size=\"585,144\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-25\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-25.png?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-25.png?w=585\" loading=\"lazy\" width=\"585\" height=\"144\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-25.png?w=585\" alt class=\"wp-image-4382\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-25.png 585w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-25.png?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-25.png?w=300 300w\" sizes=\"auto, (max-width: 585px) 100vw, 585px\"><\/figure>\n<\/div>\n<h3 class=\"wp-block-heading\" id=\"8-2-stripe-api-key\">9.2 Stripe API key<\/h3>\n<p>Another interesting finding from a Git repository was having access to some Stripe API keys. Most of them were sk_test keys (meaning that they were test keys), however, some were sk_live keys. For those of you who don\u2019t know, Stripe is a payment service provider like PayPal. Of course, having access to some live API keys, we decided to query the balance on each account. The following one stood out to us:<\/p>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" data-attachment-id=\"4386\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/image-27-2\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-27.png\" data-orig-size=\"979,676\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-27\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-27.png?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-27.png?w=840\" loading=\"lazy\" width=\"979\" height=\"676\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-27.png?w=979\" alt=\"Balance returned from Stripe API\" class=\"wp-image-4386\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-27.png 979w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-27.png?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-27.png?w=300 300w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-27.png?w=768 768w\" sizes=\"auto, (max-width: 979px) 100vw, 979px\"><figcaption class=\"wp-element-caption\">Balance returned from Stripe API<\/figcaption><\/figure>\n<p>If you haven\u2019t already noticed, the reason this one stood out was the 7-digit amount and the USD currency. $3,171,708 you may ask? Well, that\u2019s what we hoped, but the Stripe API documentation brought us back down to earth.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" data-attachment-id=\"4387\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/image-28-2\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-28.png\" data-orig-size=\"626,154\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-28\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-28.png?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-28.png?w=626\" loading=\"lazy\" width=\"626\" height=\"154\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-28.png?w=626\" alt=\"screenshot documentation stripe API balance\" class=\"wp-image-4387\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-28.png 626w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-28.png?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-28.png?w=300 300w\" sizes=\"auto, (max-width: 626px) 100vw, 626px\"><figcaption class=\"wp-element-caption\">Documentation snippet for balance endpoint<\/figcaption><\/figure>\n<\/div>\n<p>The amount indicated in the balance is in cents, so what we thought were $3,171,708, were actually $31,717.08. Not quite 3 million dollars, but still \u2013 a decent amount. After the first wave of disappointment, we approached them via the email indicated on their contact page. Fast-forward one week and we got no response. This is when we went back to our ethical considerations, or more precisely the following point within our ethical considerations: <strong>do enough to prove impact<\/strong>. And that is what we did. We generated a transaction and triggered a refund from the Stripe API. Then, we noticed that the transaction was indeed reverted.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" data-attachment-id=\"4390\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/image-29-2\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-29.png\" data-orig-size=\"265,166\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-29\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-29.png?w=265\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-29.png?w=265\" loading=\"lazy\" width=\"265\" height=\"166\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-29.png?w=265\" alt=\"payment modal\" class=\"wp-image-4390\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-29.png 265w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-29.png?w=220 220w\" sizes=\"auto, (max-width: 265px) 100vw, 265px\"><figcaption class=\"wp-element-caption\">Payment form<\/figcaption><\/figure>\n<\/div>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" data-attachment-id=\"4392\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/image-30-2\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-30.png\" data-orig-size=\"979,402\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-30\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-30.png?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-30.png?w=840\" loading=\"lazy\" width=\"979\" height=\"402\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-30.png?w=979\" alt=\"API call for reverting a transaction\" class=\"wp-image-4392\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-30.png 979w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-30.png?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-30.png?w=300 300w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-30.png?w=768 768w\" sizes=\"auto, (max-width: 979px) 100vw, 979px\"><figcaption class=\"wp-element-caption\">API call for reverting a transaction<\/figcaption><\/figure>\n<\/div>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" data-attachment-id=\"4394\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/image-31-2\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-31.png\" data-orig-size=\"455,82\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-31\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-31.png?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-31.png?w=455\" loading=\"lazy\" width=\"455\" height=\"82\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-31.png?w=455\" alt=\"Transaction refund screenshot from revolut\" class=\"wp-image-4394\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-31.png 455w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-31.png?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-31.png?w=300 300w\" sizes=\"auto, (max-width: 455px) 100vw, 455px\"><figcaption class=\"wp-element-caption\">Transaction refund<\/figcaption><\/figure>\n<\/div>\n<p>Still, in order to reach the company, we found their CEO on LinkedIn, did some OSINT to find their email and contacted them making sure to include the potential for financial damage within the disclosure email. Next thing you know, we heard back from the CEO.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" data-attachment-id=\"4396\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/image-32-2\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-32.png\" data-orig-size=\"641,509\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-32\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-32.png?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-32.png?w=641\" loading=\"lazy\" width=\"641\" height=\"509\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-32.png?w=641\" alt=\"email reply from CEO of affected company\" class=\"wp-image-4396\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-32.png 641w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-32.png?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-32.png?w=300 300w\" sizes=\"auto, (max-width: 641px) 100vw, 641px\"><figcaption class=\"wp-element-caption\">Reply from the CEO<\/figcaption><\/figure>\n<\/div>\n<p>We provided a detailed report, containing findings, impact and recommendations for remediation. Shortly, the CTO responded this time, thanking us for responsibly disclosing this issue.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" data-attachment-id=\"4398\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/image-33\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-33.png\" data-orig-size=\"373,114\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-33\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-33.png?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-33.png?w=373\" loading=\"lazy\" width=\"373\" height=\"114\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-33.png?w=373\" alt=\"email reply after fix from CTO\" class=\"wp-image-4398\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-33.png 373w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-33.png?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image-33.png?w=300 300w\" sizes=\"auto, (max-width: 373px) 100vw, 373px\"><figcaption class=\"wp-element-caption\">Response after fix from CTO<\/figcaption><\/figure>\n<\/div>\n<h3 class=\"wp-block-heading\" id=\"8-3-sales-meeting-but-with-a-twist\">9.3 Sales meeting, but with a twist<\/h3>\n<p>For one small company with valid AWS keys out there we couldn\u2019t find a contact email. The only contact form available was to set a sales meetings with them.<\/p>\n<p>Well, that\u2019s what we did. We scheduled a sales meeting for the next day and we actually presented them the issue in a meeting. They seemed a bit scared, but I guess anyone would be. In the end they thanked us for disclosing the issue with them and now I\u2019m connected on LinkedIn with their CEO ????<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" data-attachment-id=\"4408\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/8mxedi\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/8mxedi.jpg\" data-orig-size=\"697,500\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"8mxedi\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/8mxedi.jpg?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/8mxedi.jpg?w=697\" loading=\"lazy\" width=\"697\" height=\"500\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/8mxedi.jpg?w=697\" alt=\"meme epic handshake\" class=\"wp-image-4408\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/8mxedi.jpg 697w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/8mxedi.jpg?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/8mxedi.jpg?w=300 300w\" sizes=\"auto, (max-width: 697px) 100vw, 697px\"><\/figure>\n<\/div>\n<p>We went to weird lengths to disclose to companies their exposed AWS access keys. For instance, we completed tens of contact forms with zero response back. For a medical institution we had to submit a report to an investigation board. An HR person closed our issue there without asking for more details. And for only one company we managed to report the issue on a bug bounty platform, but it was only a vulnerability disclosing program so our bounty for a P1 was $0 ????<\/p>\n<h3 class=\"wp-block-heading\" id=\"9-4-the-amazing-aws-security-team\">9.4 The amazing AWS Security Team<\/h3>\n<p>I am one of those people that sincerely cares about cybersecurity and maybe you are too. Well, that\u2019s how the people from the AWS\u2019s Security Team are. Of course, we discussed with only 3 of them, but their spirit towards cybersecurity was so well defined that it can\u2019t be just them.<\/p>\n<p>To put in perspective, AWS was not responsible with anything on this issue. They made the process of publishing AMIs so that\u2019s impossible to do it without knowing what you\u2019re doing. Having an AMI public is by no chance a simple mistake, no. It is very explicit. And even so, these people put in the effort, curiosity and time to help the clients with exposed AWS keys.<\/p>\n<p>You might say that was in their interest, and yes, I believe that too, but it was visible that they were helping from a place of care, not a place of obligation. And trust me, I\u2019m no big fan of corporation culture. These guys were what you can call good guys.<\/p>\n<p>In a more objective perspective, they took our report seriously, they listened us, they scheduled a call to discuss more, they asked for further details and they helped the affected clients. Not at any point we were questioned, asked to not publish or threatened with anything. They even reviewed our blog post before publishing and gave a few suggestions about the message we\u2019re about to send.<\/p>\n<p>I honestly hope that every big provider of anything out there has a security team with a open culture towards researchers, improvement and helping as AWS does.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" data-attachment-id=\"4441\" data-permalink=\"https:\/\/securitycafe.ro\/2024\/05\/08\/aws-cloudquarry-digging-for-secrets-in-public-amis\/8p1kp8\/\" data-orig-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/05\/8p1kp8.jpg\" data-orig-size=\"612,408\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"8p1kp8\" data-image-description data-image-caption data-medium-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/05\/8p1kp8.jpg?w=300\" data-large-file=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/05\/8p1kp8.jpg?w=612\" loading=\"lazy\" width=\"612\" height=\"408\" src=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/05\/8p1kp8.jpg?w=612\" alt class=\"wp-image-4441\" srcset=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/05\/8p1kp8.jpg 612w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/05\/8p1kp8.jpg?w=220 220w, https:\/\/kpmgsecurity.files.wordpress.com\/2024\/05\/8p1kp8.jpg?w=300 300w\" sizes=\"auto, (max-width: 612px) 100vw, 612px\"><\/figure>\n<\/div>\n<h2 class=\"wp-block-heading\" id=\"9-future-work-ethical-considerations\">10. Future work &amp; Ethical considerations<\/h2>\n<h3 class=\"wp-block-heading\" id=\"9-1-ethical-considerations\">10.1 Ethical considerations<\/h3>\n<p>When we began undertaking this research project, we set some ethical limits. We were sure that we will find some interesting data, so we decided from the start what we could and could not do with the data. Our general approach was to test whether the secrets are valid, do enough to prove impact, but not more than that.<\/p>\n<p>At the time of writing this, we worked on this research for about 6 months. The limited number of responses to our responsible disclosure made us to wait a bit longer before publishing the research.<\/p>\n<p>In the end we realized exactly what we advice against: security by obscurity is not security. Just as these companies made their AMIs public hoping that no one would find them, we started doing the same thing with this attack vector.<\/p>\n<p>So we decided that the best option is to publish this research in the hope that defenders will catch wind of it before attackers manage to implement their scanning infrastructure.<\/p>\n<h3 class=\"wp-block-heading\" id=\"9-2-future-work\">10.2 Future work<\/h3>\n<p>First off, our colleague <strong>Stefan Tita<\/strong> just finished the same scanning process on <strong>Azure <\/strong>and now we are in the process on analyzing the data collected from there. So far it seems that the same issue is present there as well.<\/p>\n<p>Second, there is still a lot to do with the collected data from AWS. Some directions we have in mind so far:<\/p>\n<ul>\n<li>We extracted 20k+ JWTs. We want to check if there are any of them valid and if we can identity the web application that authenticates them<\/li>\n<li>We could take a look at the source code of certain repositories in order to do some source code review, identify some cool vulnerabilities and get some CVEs<\/li>\n<li>We found in the Git repositories multiple JWT signing keys. We would like to check if we can identify the web applications running that code and sign our own JWTs.<\/li>\n<li>We still have a lot of secrets to validate<\/li>\n<li>We want to do an analysis on the extracted file names<\/li>\n<\/ul>\n<p>In terms of what can be further done, we could adjust the script to run continuously and whenever a new public AMI is detected, to start the scanning process. We suspect that some companies are making AMIs public for only a short period of time. Well, that short period of time can be enough to get the data within.<\/p>\n<p>While we look further into the data more ideas might come and new articles will be written. In the end we might extend to GCP as well, but until then there is still work to do.<\/p>\n<h2 class=\"wp-block-heading\" id=\"conclusions\">Conclusions<\/h2>\n<p>Usually I like to draw 2-3 ideas and keep the \u201cConclusions\u201d chapter short, but on this research we have a bit more to say.<\/p>\n<p>We recommended AWS to put some limitations or throttling in place when multiple community (especially deprecated) AMIs are spawned in a short period of time from a single AWS account. We didn\u2019t get a certain response if this will be implemented. Since you can use multiple AWS accounts to split the load and once you compromise a new account, you can split the load further, maybe this is not something that can be fixed. Can you still replicate this research? Most likely yes, but be aware that AWS monitors the AMI usage. We might publish our repository in the future after we present the research at a few conferences, but we are not sure yet.<\/p>\n<p>About what we noticed, companies are still relying on obscurity for covering their lack of security. Finding the AMI of a company among 3.1 million public ones might be hard, but when scanning every public AMI then the AMI surely won\u2019t be missed. We\u2019d like to mention that you can target specific companies and technologies by searching AMIs based on description, title or owner, so #bugbounty tip right there.<\/p>\n<p>Going further with this, obscurity hides even more bad security practices. Hard-coding secrets in private repositories can put your company to their knees. As Matei likes to say it, what good to hide your secrets in private repositories if the repositories are put in public AMIs.<\/p>\n<p>We saw big companies having this critical vulnerability in their environment. It seems that people are still not doing regular Cloud Security Configuration Review regularly or at all. Even more, they deploy vulnerable resources knowing very well or ignoring the security implications.<\/p>\n<p>Looking even closer you can identify another bad security practice: not rotating secrets. We report this issue a lot in our day-to-day engagements and we sometimes get uninterested reactions. It\u2019s exactly this kind of scenario that would prevent attackers from having access for years in your environment.<\/p>\n<p>Small good practices add up and help you have a mature security posture. There is a CIS benchmark item that states that your AWS account should have contact information set. That\u2019s a low risk finding at most, but look how much it would have helped companies in being contacted with a security incident.<\/p>\n<p>Finally, after 6 months, 1200+ lines of code, 14+ days of scanning and a $500+ bill, we have this initial piece of article to share with everyone, but we believe that the full impact of this research is yet to be unfolded.<\/p>\n<p>Thank for reading!<\/p>\n<p>Eduard Agavriloae &amp; Matei Josephs<\/p>\n<div id=\"jp-post-flair\" class=\"sharedaddy sd-like-enabled sd-sharing-enabled\">\n<div class=\"sharedaddy sd-sharing-enabled\">\n<div class=\"robots-nocontent sd-block sd-social sd-social-icon-text sd-sharing\">\n<h3 class=\"sd-title\">Share this:<\/h3>\n<\/div>\n<\/div>\n<div class=\"sharedaddy sd-block sd-like jetpack-likes-widget-wrapper jetpack-likes-widget-unloaded\" id=\"like-post-wrapper-78950108-4207-663cf214a1454\" data-src=\"\/\/widgets.wp.com\/likes\/index.html?ver=20240509#blog_id=78950108&amp;post_id=4207&amp;origin=kpmgsecurity.wordpress.com&amp;obj_id=78950108-4207-663cf214a1454&amp;domain=securitycafe.ro\" data-name=\"like-post-frame-78950108-4207-663cf214a1454\" data-title=\"Like or Reblog\">\n<div class=\"likes-widget-placeholder post-likes-widget-placeholder\"><span class=\"button\"><span>Like<\/span><\/span> <span class=\"loading\">Loading&#8230;<\/span><\/div>\n<p><span class=\"sd-text-color\"><\/span><\/div>\n<\/div>\n<p> READ MORE <a href=\"https:\/\/packetstormsecurity.com\/news\/view\/35857\/AWS-CloudQuarry-Digging-For-Secrets-In-Public-AMIs.html\">HERE<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>READ MORE HERE&#8230;<\/p>\n","protected":false},"author":2,"featured_media":56025,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"colormag_page_layout":"default_layout","footnotes":""},"categories":[60],"tags":[10095],"class_list":["post-56024","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-packet-storm","tag-headlineamazondata-lossflawpassword"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>AWS CloudQuarry: Digging For Secrets In Public AMIs 2026 | ThreatsHub Cybersecurity News<\/title>\n<meta name=\"description\" content=\"ThreatsHub Cybersecurity News | ThreatsHub.org | Cloud Security &amp; Cyber Threats Analysis Hub. 100% Free OSINT Threat Intelligent and Cybersecurity News.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.threatshub.org\/blog\/aws-cloudquarry-digging-for-secrets-in-public-amis\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"AWS CloudQuarry: Digging For Secrets In Public AMIs 2026 | ThreatsHub Cybersecurity News\" \/>\n<meta property=\"og:description\" content=\"ThreatsHub Cybersecurity News | ThreatsHub.org | Cloud Security &amp; Cyber Threats Analysis Hub. 100% Free OSINT Threat Intelligent and Cybersecurity News.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.threatshub.org\/blog\/aws-cloudquarry-digging-for-secrets-in-public-amis\/\" \/>\n<meta property=\"og:site_name\" content=\"ThreatsHub Cybersecurity News\" \/>\n<meta property=\"article:published_time\" content=\"2024-05-09T15:12:58+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image.png?w=1024\" \/>\n<meta name=\"author\" content=\"TH Author\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@threatshub\" \/>\n<meta name=\"twitter:site\" content=\"@threatshub\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"TH Author\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"49 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/aws-cloudquarry-digging-for-secrets-in-public-amis\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/aws-cloudquarry-digging-for-secrets-in-public-amis\\\/\"},\"author\":{\"name\":\"TH Author\",\"@id\":\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/#\\\/schema\\\/person\\\/12e0a8671ff89a863584f193e7062476\"},\"headline\":\"AWS CloudQuarry: Digging For Secrets In Public AMIs\",\"datePublished\":\"2024-05-09T15:12:58+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/aws-cloudquarry-digging-for-secrets-in-public-amis\\\/\"},\"wordCount\":8405,\"publisher\":{\"@id\":\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/aws-cloudquarry-digging-for-secrets-in-public-amis\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/wp-content\\\/uploads\\\/2024\\\/05\\\/aws-cloudquarry-digging-for-secrets-in-public-amis.png\",\"keywords\":[\"headline,amazon,data loss,flaw,password\"],\"articleSection\":[\"Packet Storm\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/aws-cloudquarry-digging-for-secrets-in-public-amis\\\/\",\"url\":\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/aws-cloudquarry-digging-for-secrets-in-public-amis\\\/\",\"name\":\"AWS CloudQuarry: Digging For Secrets In Public AMIs 2026 | ThreatsHub Cybersecurity News\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/aws-cloudquarry-digging-for-secrets-in-public-amis\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/aws-cloudquarry-digging-for-secrets-in-public-amis\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/wp-content\\\/uploads\\\/2024\\\/05\\\/aws-cloudquarry-digging-for-secrets-in-public-amis.png\",\"datePublished\":\"2024-05-09T15:12:58+00:00\",\"description\":\"ThreatsHub Cybersecurity News | ThreatsHub.org | Cloud Security & Cyber Threats Analysis Hub. 100% Free OSINT Threat Intelligent and Cybersecurity News.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/aws-cloudquarry-digging-for-secrets-in-public-amis\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/aws-cloudquarry-digging-for-secrets-in-public-amis\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/aws-cloudquarry-digging-for-secrets-in-public-amis\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/wp-content\\\/uploads\\\/2024\\\/05\\\/aws-cloudquarry-digging-for-secrets-in-public-amis.png\",\"contentUrl\":\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/wp-content\\\/uploads\\\/2024\\\/05\\\/aws-cloudquarry-digging-for-secrets-in-public-amis.png\",\"width\":1024,\"height\":561},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/aws-cloudquarry-digging-for-secrets-in-public-amis\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"headline,amazon,data loss,flaw,password\",\"item\":\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/tag\\\/headlineamazondata-lossflawpassword\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"AWS CloudQuarry: Digging For Secrets In Public AMIs\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/\",\"name\":\"ThreatsHub Cybersecurity News\",\"description\":\"%%focuskw%% Threat Intel \u2013 Threat Intel Services \u2013 CyberIntelligence \u2013 Cyber Threat Intelligence - Threat Intelligence Feeds - Threat Intelligence Reports - CyberSecurity Report \u2013 Cyber Security PDF \u2013 Cybersecurity Trends - Cloud Sandbox \u2013- Threat IntelligencePortal \u2013 Incident Response \u2013 Threat Hunting \u2013 IOC - Yara - Security Operations Center \u2013 SecurityOperation Center \u2013 Security SOC \u2013 SOC Services - Advanced Threat - Threat Detection - TargetedAttack \u2013 APT \u2013 Anti-APT \u2013 Advanced Protection \u2013 Cyber Security Services \u2013 Cybersecurity Services -Threat Intelligence Platform\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/#organization\"},\"alternateName\":\"Threatshub.org\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/#organization\",\"name\":\"ThreatsHub.org\",\"alternateName\":\"Threatshub.org\",\"url\":\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/wp-content\\\/uploads\\\/2025\\\/05\\\/Threatshub_Favicon1.jpg\",\"contentUrl\":\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/wp-content\\\/uploads\\\/2025\\\/05\\\/Threatshub_Favicon1.jpg\",\"width\":432,\"height\":435,\"caption\":\"ThreatsHub.org\"},\"image\":{\"@id\":\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/x.com\\\/threatshub\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.threatshub.org\\\/blog\\\/#\\\/schema\\\/person\\\/12e0a8671ff89a863584f193e7062476\",\"name\":\"TH Author\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/066276f086d5155df79c850206a779ad368418a844da0182ce43f9cd5b506c3d?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/066276f086d5155df79c850206a779ad368418a844da0182ce43f9cd5b506c3d?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/066276f086d5155df79c850206a779ad368418a844da0182ce43f9cd5b506c3d?s=96&d=mm&r=g\",\"caption\":\"TH Author\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"AWS CloudQuarry: Digging For Secrets In Public AMIs 2026 | ThreatsHub Cybersecurity News","description":"ThreatsHub Cybersecurity News | ThreatsHub.org | Cloud Security & Cyber Threats Analysis Hub. 100% Free OSINT Threat Intelligent and Cybersecurity News.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.threatshub.org\/blog\/aws-cloudquarry-digging-for-secrets-in-public-amis\/","og_locale":"en_US","og_type":"article","og_title":"AWS CloudQuarry: Digging For Secrets In Public AMIs 2026 | ThreatsHub Cybersecurity News","og_description":"ThreatsHub Cybersecurity News | ThreatsHub.org | Cloud Security & Cyber Threats Analysis Hub. 100% Free OSINT Threat Intelligent and Cybersecurity News.","og_url":"https:\/\/www.threatshub.org\/blog\/aws-cloudquarry-digging-for-secrets-in-public-amis\/","og_site_name":"ThreatsHub Cybersecurity News","article_published_time":"2024-05-09T15:12:58+00:00","og_image":[{"url":"https:\/\/kpmgsecurity.files.wordpress.com\/2024\/04\/image.png?w=1024","type":"","width":"","height":""}],"author":"TH Author","twitter_card":"summary_large_image","twitter_creator":"@threatshub","twitter_site":"@threatshub","twitter_misc":{"Written by":"TH Author","Est. reading time":"49 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.threatshub.org\/blog\/aws-cloudquarry-digging-for-secrets-in-public-amis\/#article","isPartOf":{"@id":"https:\/\/www.threatshub.org\/blog\/aws-cloudquarry-digging-for-secrets-in-public-amis\/"},"author":{"name":"TH Author","@id":"https:\/\/www.threatshub.org\/blog\/#\/schema\/person\/12e0a8671ff89a863584f193e7062476"},"headline":"AWS CloudQuarry: Digging For Secrets In Public AMIs","datePublished":"2024-05-09T15:12:58+00:00","mainEntityOfPage":{"@id":"https:\/\/www.threatshub.org\/blog\/aws-cloudquarry-digging-for-secrets-in-public-amis\/"},"wordCount":8405,"publisher":{"@id":"https:\/\/www.threatshub.org\/blog\/#organization"},"image":{"@id":"https:\/\/www.threatshub.org\/blog\/aws-cloudquarry-digging-for-secrets-in-public-amis\/#primaryimage"},"thumbnailUrl":"https:\/\/www.threatshub.org\/blog\/coredata\/uploads\/2024\/05\/aws-cloudquarry-digging-for-secrets-in-public-amis.png","keywords":["headline,amazon,data loss,flaw,password"],"articleSection":["Packet Storm"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.threatshub.org\/blog\/aws-cloudquarry-digging-for-secrets-in-public-amis\/","url":"https:\/\/www.threatshub.org\/blog\/aws-cloudquarry-digging-for-secrets-in-public-amis\/","name":"AWS CloudQuarry: Digging For Secrets In Public AMIs 2026 | ThreatsHub Cybersecurity News","isPartOf":{"@id":"https:\/\/www.threatshub.org\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.threatshub.org\/blog\/aws-cloudquarry-digging-for-secrets-in-public-amis\/#primaryimage"},"image":{"@id":"https:\/\/www.threatshub.org\/blog\/aws-cloudquarry-digging-for-secrets-in-public-amis\/#primaryimage"},"thumbnailUrl":"https:\/\/www.threatshub.org\/blog\/coredata\/uploads\/2024\/05\/aws-cloudquarry-digging-for-secrets-in-public-amis.png","datePublished":"2024-05-09T15:12:58+00:00","description":"ThreatsHub Cybersecurity News | ThreatsHub.org | Cloud Security & Cyber Threats Analysis Hub. 100% Free OSINT Threat Intelligent and Cybersecurity News.","breadcrumb":{"@id":"https:\/\/www.threatshub.org\/blog\/aws-cloudquarry-digging-for-secrets-in-public-amis\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.threatshub.org\/blog\/aws-cloudquarry-digging-for-secrets-in-public-amis\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.threatshub.org\/blog\/aws-cloudquarry-digging-for-secrets-in-public-amis\/#primaryimage","url":"https:\/\/www.threatshub.org\/blog\/coredata\/uploads\/2024\/05\/aws-cloudquarry-digging-for-secrets-in-public-amis.png","contentUrl":"https:\/\/www.threatshub.org\/blog\/coredata\/uploads\/2024\/05\/aws-cloudquarry-digging-for-secrets-in-public-amis.png","width":1024,"height":561},{"@type":"BreadcrumbList","@id":"https:\/\/www.threatshub.org\/blog\/aws-cloudquarry-digging-for-secrets-in-public-amis\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.threatshub.org\/blog\/"},{"@type":"ListItem","position":2,"name":"headline,amazon,data loss,flaw,password","item":"https:\/\/www.threatshub.org\/blog\/tag\/headlineamazondata-lossflawpassword\/"},{"@type":"ListItem","position":3,"name":"AWS CloudQuarry: Digging For Secrets In Public AMIs"}]},{"@type":"WebSite","@id":"https:\/\/www.threatshub.org\/blog\/#website","url":"https:\/\/www.threatshub.org\/blog\/","name":"ThreatsHub Cybersecurity News","description":"%%focuskw%% Threat Intel \u2013 Threat Intel Services \u2013 CyberIntelligence \u2013 Cyber Threat Intelligence - Threat Intelligence Feeds - Threat Intelligence Reports - CyberSecurity Report \u2013 Cyber Security PDF \u2013 Cybersecurity Trends - Cloud Sandbox \u2013- Threat IntelligencePortal \u2013 Incident Response \u2013 Threat Hunting \u2013 IOC - Yara - Security Operations Center \u2013 SecurityOperation Center \u2013 Security SOC \u2013 SOC Services - Advanced Threat - Threat Detection - TargetedAttack \u2013 APT \u2013 Anti-APT \u2013 Advanced Protection \u2013 Cyber Security Services \u2013 Cybersecurity Services -Threat Intelligence Platform","publisher":{"@id":"https:\/\/www.threatshub.org\/blog\/#organization"},"alternateName":"Threatshub.org","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.threatshub.org\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.threatshub.org\/blog\/#organization","name":"ThreatsHub.org","alternateName":"Threatshub.org","url":"https:\/\/www.threatshub.org\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.threatshub.org\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.threatshub.org\/blog\/coredata\/uploads\/2025\/05\/Threatshub_Favicon1.jpg","contentUrl":"https:\/\/www.threatshub.org\/blog\/coredata\/uploads\/2025\/05\/Threatshub_Favicon1.jpg","width":432,"height":435,"caption":"ThreatsHub.org"},"image":{"@id":"https:\/\/www.threatshub.org\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/threatshub"]},{"@type":"Person","@id":"https:\/\/www.threatshub.org\/blog\/#\/schema\/person\/12e0a8671ff89a863584f193e7062476","name":"TH Author","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/066276f086d5155df79c850206a779ad368418a844da0182ce43f9cd5b506c3d?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/066276f086d5155df79c850206a779ad368418a844da0182ce43f9cd5b506c3d?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/066276f086d5155df79c850206a779ad368418a844da0182ce43f9cd5b506c3d?s=96&d=mm&r=g","caption":"TH Author"}}]}},"_links":{"self":[{"href":"https:\/\/www.threatshub.org\/blog\/wp-json\/wp\/v2\/posts\/56024","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.threatshub.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.threatshub.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.threatshub.org\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.threatshub.org\/blog\/wp-json\/wp\/v2\/comments?post=56024"}],"version-history":[{"count":0,"href":"https:\/\/www.threatshub.org\/blog\/wp-json\/wp\/v2\/posts\/56024\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.threatshub.org\/blog\/wp-json\/wp\/v2\/media\/56025"}],"wp:attachment":[{"href":"https:\/\/www.threatshub.org\/blog\/wp-json\/wp\/v2\/media?parent=56024"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.threatshub.org\/blog\/wp-json\/wp\/v2\/categories?post=56024"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.threatshub.org\/blog\/wp-json\/wp\/v2\/tags?post=56024"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}