My name is Spencer Geetson, and today I'm going to be talking about ransomware in the cloud. So, I'm a huge cloud nerd, so instead of the traditional Who Am I slide, I did an AWS STS Git Caller Identity slide, which basically says what Jaren just shared. My name is Spencer Geetson. I'm a cloud security researcher at CrowdStrike. I previously was a penetration tester at Rhino Security Labs, and I've got an interest in technical writing, gaming, and programming. So first I want to start off with an agenda. We'll talk about AWS basics, just kind of a TLDR of the services and resources I'm going to go over. Ransomware in the cloud, simple storage service for AWS S3, we're going to talk about ransomware techniques, prevention, detection, and indicators. And then the same thing for DynamoDB techniques, prevention, detection, and indicators. And then at the end, we're going to talk about other potential targets, so other AWS services, other clouds, those kind of things, cloud provider intervention, and other takeaways from the presentation, and then just some additional resources and references at the end. So AWS basics. I imagine there's a wide range of skill set in the audience, so you may know this, you may not. AWS S3 is just object storage in the cloud. It's their offering. There's S3 buckets, which basically hold all your buckets of objects. Objects are essentially files that are stored in buckets, and then there are bucket policies which determine the access permissions and conditions that apply to a bucket and the objects within it. And we'll get more into that later on. DynamoDB, this one's pretty simple for our needs. It has tables. It's a NoSQL database offered by Amazon, and it has tables that hold data. That's as much as you really need to know if you're not familiar with the service right now, at least. Then there's KMS, Key Management Service. It has keys, which could be asymmetric or symmetric keys, depending on your use case, and they're typically AWS managed. They have key policies, which define who can use keys and what they can be used for, etc. And that's kind of the rundown of the different resources and services that I'll be talking about today. Ransomware in the cloud. I'm going to be comparing the state of ransomware today to soon, essentially. Right now, there's traditional ransomware like Locky, WastedLocker, things like those that target traditional infrastructure. Cloud-native ransomware is on the way. There's none yet, or none publicly. We don't know what's going on behind the scenes or in breaches that haven't been made public. But it's better to get ahead of these things before it becomes a problem. It's better to be ready for them. So traditional ransomware typically targets servers and workstations, while cloud ransomware would be targeting cloud-native resources. Traditionally, they're operating system dependent. Primarily, windows and active directory environments are being targeted. Where in the cloud, it's going to be cloud provider independent. We're focusing on AWS for this presentation, but all the concepts can be applied to other cloud providers like Google Cloud and Microsoft Azure and others. And then traditionally, they exploit zero-day or known vulnerabilities to spread and infect their targets. Where in the cloud, it's none of that. It's just feature abuse. There's no vulnerability abuse. It's just using features the way they were designed, essentially, in a little bit of a malicious way. So with that, we'll dive into S3. There's three techniques I'm going to cover. It doesn't mean they're the only three techniques, but these are three notable ones, at least. Local encryption is the first technique. It's very slow compared to the others, but it's got a critical impact. The detection likelihood, I rate it as likely. But this is only if you have monitoring in your environment. If you aren't monitoring what's going on in your environment, you're not going to catch this. This is for kind of a security mature organization that it would be likely to detect. And so some of the defenses I'll go over will help certain companies reach that point to where they can feel like they are going to detect these attacks. Second method is cross-account KMS encryption. It's fast-ish, depending on the size of the bucket you're targeting. It's got a high impact, and then it's unlikely to be detected based on my rating. And the last, and probably the best method, as an attacker, from my point of view, is the KMS key policy lockout method. It's instant because it's a single API call. It's got high impact, and it's very unlikely to detect because it's a single API call. You might be able to detect it after it's happened, but you're not going to be able to prevent it if you don't have the correct defenses in place. So for the first method, local encryption, obviously we're going to locate a target bucket. We're going to download each file in the bucket, and we're going to locally encrypt each of those files with something like AES-256, you know, if you're going to be basic. Upload each of those encrypted files back to the bucket. Or, in theory, you could just delete all the files from the bucket and keep your local copies, depending on the size of the bucket, because by the time you have access, you could just release it rather than encrypt it or something like that as the attacker. So there's a lot of different routes here, but for this route, essentially we're just downloading from a bucket, as you can see here, AES-256 encrypting, and then re-uploading over the top of the original file. So I wrote a one-liner command here to demonstrate the concept. It looks a little convoluted, but highlighted some of the important parts here. Essentially, in red, we're exporting an environment variable bucket equal to our target bucket. Then we're using the AWS CLI, so list objects for that bucket. We're getting a list of all the objects that are stored in there. We're piping that list into jq, which is a JSON parser, and essentially it's just grabbing the names of all those objects. We don't care about the rest right now, but the rest of their properties. We're piping all those names into xrs. We're saying each name should run this... the following command should be run for each name, and then wherever there's an open-close bracket in the following command, it should be replaced with the current object name. So essentially, we're running sh-c, here's this open quote, and at the very end is the close quote. We're running this entire thing for each name of an object in the bucket. In the red, it's going to be awss3cp, which is copy. We're copying it from our target bucket at the current key, object key, into standard in. Now we're piping the result of that into openssl, which we're using to aes256 encrypt the data, and then base64 encoding it. We're piping that data into another awss3 copy command, but this time it's from standard in into s3, or at that bucket, at that object. So we're just overriding the original object with an encrypted version of the object. So now even if the target user has s3 permissions to read those objects, they're going to get access denied because they don't have access... or well, I guess they won't get access denied. They just won't be able to read the contents because it's encrypted with your password. So essentially they would have to pay the ransom, and you give them the password, and then they can decrypt all their data. So the next method is cross-account KMS encryption. Essentially you need an attacker AWS account for this one. You create a KMS key in that attacker AWS account. You modify the key policy to allow cross-account access to your target account, but only the encrypt permission and nothing else. So not the decrypt permission, especially. Next we're going to locate a target bucket, and we're going to use the s3 copy command to copy each object from itself to itself, which also s3 batch allows you to do at a greater scale without having to automate it yourself. And we're going to be specifying the KMS encryption key as the key we just created in step one. So I wrote another one-liner for this one. Again, it's a little convoluted, but this one's a little easier to understand. Pretty much everything is the same. We're getting the list of objects, the name of those objects, passing that into xargs in this shell command. But the shell command this time is AWS s3 copy from the s3 bucket of that object to the s3 bucket of that object. So basically just on top of itself. We're passing in SSE KMS key ID, and we're giving it our malicious key ID. So it's just encrypting each object in the bucket with our key instead of whatever it's currently encrypted or not encrypted with. And lucky for us, this is done on the server side, this copy, because it's s3 to s3, so we don't need to worry about our own upload and download speed like we would with the local encryption method. So this might be a better method for when there's larger files in the bucket that you don't want to be downloading terabytes of data to your system. You probably can't even. So the third method is KMS key policy lockout. This is my favorite method and probably the scariest method. So I'll get into why shortly. In this we're going to need our own attacker account again. This time we're going to allocate an elastic IP in there, and this is because there are a lot of restrictions on cross-account actions for KMS keys. So you can't update the policy of a KMS key cross-account, you can't disable a key cross-account, and you can't delete a key cross-account. So we have to do some trickery with conditions in the KMS key policy to actually lock the owner out. And again, I say the owner because we're targeting a key that our target owns. It's not our attacker key or anything like that. So we'll locate a target bucket and our target has to have a customer master key assigned to it as the default encryption method, or at least the objects in the bucket have to be encrypted with a customer master key. It can't be the default S3 KMS key and it can't be unencrypted because we're targeting the actual key behind the encryption which requires it to be a customer master key. Otherwise we can't mess with the policy. We're going to update the key policy of that KMS key to deny access to anything about it unless it's originating from your elastic IP address. So essentially no one can use the key unless they have control of the elastic IP address which you have control of the attacker. Then you demand ransom plus you know keys to unlock so you could have them give you keys that have put key policy on the key and you could use your elastic IP to restore their key policy or you can transfer them the IP allocated. It's a little risky because you would have to unallocate it in your own account then they would have to request it to be allocated in their account which if the timing doesn't match up they might miss it and another customer might randomly get it in AWS and at that point who knows what would happen. So another one-liner, this one doesn't look very simple because it's got a whole bunch of JSON in it but it's just a single command. So AWS CLI KMS put key policy pass in the target key ID for the key we want to target obviously. The policy name is always going to be default and then we're passing in a JSON policy which I have formatted to make it a little bit easier to read. For those of you who aren't aware of how policies work or the structure of them in AWS I'll kind of go over this. So there are two statements that are declaring something about the key. The first one is deny access to this principle which is everyone. Deny anyone from doing any KMS action on any resource under the condition that they're not coming from our Elastic IP address. So essentially if you aren't coming from our IP deny access to everything. Then the next statement is saying allow access to our target account's root user to do any KMS action on any resource under the condition that they're coming from our Elastic IP address. So overall this is saying if you're not coming from our Elastic IP you're blocked from everything. If you are and you're coming from the target account then you have access to do things. So what this means is because we have access or because we own the Elastic IP it's up to us to grant access to the target account where then they can update the policy and essentially gain access to their data again because this will deny them from using the decrypt permission which they need to obviously decrypt any data. Another reason this is kind of scary is because this could go across to multiple S3 buckets. In theory the same KMS key could be applied to three or four different S3 buckets. So if you ransom the key policy you've hit all of those buckets with it with one API call. So it's suddenly a very much more valuable attack for you. So S3 defenses. We're going to talk about prevention and detection. They're both very important. In terms of prevention, easy one is just follow the principle of least privilege. This applies to KMS key policies, S3 bucket policies, and the IAM privileges you're granting to your users and roles for those specific services. Off-site backups. So of course online backups are good. Maybe cross account or something like that. But off-site is good because even if you get ransomware and you lose access to your data, you can just restore from something completely unrelated. Organization service control policies are important. They're going to be customized to your environment. So I'm not going to go over any specific examples, but they can be used to enforce specific conditions and restrict certain permissions that may prevent or at least help detect a ransomware attack. S3 object versioning with MFA delete. It's very important. So object versioning makes it so that instead of your files getting overwritten when a new one with the same name is uploaded, it creates a new version. So if the attacker tried to do a local encrypt attack and uploaded their encrypted version over the top of an existing version, both versions would still exist and the defender could just delete the latest version, which is the encrypted version, and then restore the original version and still have access to all their data. But this is why MFA delete is important because an attacker could also just delete object versions if they had the permissions to do so. So they delete the old version and the only version left is the encrypted version. But with MFA delete, it requires you to have an active MFA device to delete objects and to disable object versioning. So in both cases, the attacker is going to be locked out. In most cases, they're not going to have access to an active MFA device, even if they've already bypassed MFA in the console or something along those lines. Another good defense is a bucket policy that enforces a specific KMS key. This will prevent the cross-account KMS encryption method. Here's an example bucket policy. We're denying anybody from using S3 put object to our bucket under the condition the encryption key is not this one here. So if someone tries to upload an object to our bucket and they specify an encryption key that is not this one that we've whitelisted, it's going to get access denied. And so this will prevent the cross-account attacker key from getting applied to any of our objects. In terms of detection, there's going to be S3 access logging and CloudTrail S3 data event logging. These are both pretty similar and give you visibility into the actual actions taking place within a bucket versus on a bucket. So this is like object level activity, essentially. They have slight differences, so it's worth looking into the comparison between the two and seeing which one you want or both, maybe. Another important thing is CloudTrail management event logging. You can hopefully trace the attack path through your environment and maybe kick them out before they start ransoming your buckets or something like that. CloudTrail KMS event logging is good, too, because you can see when maybe there's a high amount of decrypts going on, you can take that as an indicator that someone is reading lots of objects or something along those lines, which could be them downloading to locally encrypt and maybe you stop them before they re-upload. GuardDuty with S3 ingestion enabled. S3 ingestion was just released last week, I believe, and it is a great feature that's been added. It'll allow you to catch things like a Tor IP address interacting with your S3 buckets, so it'll make it easier to pull out malicious activity from your buckets compared to traditional activity or normal activity. In terms of indicators for S3, STS get caller identity, kind of like my Who Am I slide. This is Who Am I of the cloud, and you don't necessarily need to alert on this call because there are a lot of legitimate use cases, like EKS pods won't use it, I believe HashCorp Vault uses it, and then sometimes developers just need to do it themselves, but attackers will often use this, too, to identify who they are before expanding into the environment. So if you can create a baseline of what's normal and then alert on what's abnormal, this would be a good one to look into. Another obvious one is S3 list all my buckets. That's going to be used legitimately all the time, but if you could somehow identify when it's being used maliciously, it's going to be a really good one because this will probably be run before any ransomware attack unless they already have a bucket name, a target, or something along those lines. Maybe you pair it up with get caller identity, so you see get caller identity and then shortly after list all my buckets, that could be somewhat of an indicator and at least worth looking into. Attempts to disable object versioning on an S3 bucket and attempts to delete object versions in a bucket. An attacker could do this if they identified a bucket that has versioning enabled, they could disable it, and then they could go in and delete all the old versions and then make it so that the latest version is their encrypted file or encrypted object so it'd be just the same as if versioning was disabled. Attempts to disable S3 access logging to remove your visibility into the HTTP requests that are going on within your bucket. KMS key policy modifications. If it's the last KMS key policy lockout method, this is going to, or alerting on these modifications, it's going to be too late, but better late than never, I would say. You want to know when this stuff happens even if you weren't able to prevent it. S3 bucket policy modifications and S3 bucket ACL modifications. You want to know when your bucket gets granted cross-account access or public access, of course, but then if you're enforcing a specific KMS key in your policy for object uploads, an attacker could identify that and delete the bucket policy so that they can use their cross-account key. So this might be somewhere, again, where service control policies come into place and can prevent that kind of activity if you know you're not going to need that to be going on. High volume of S3 object downloads and uploads. If it's above your baseline, it might be worth looking into. Maybe someone's exfiltrating all the data in your bucket or they're downloading it for local encryption or something along those lines. A typical S3 batch usage. So like I talked about before, S3 batch could be used for the cross-account KMS key method. And so if you don't use S3 batch at all and then all of a sudden you see some jobs kicked off, that could be alarming and maybe you can stop those jobs before they complete and fully take control of your data. Guard duty alerts, again, those are great to look into and just great in general in terms of identifying compromise in your environment. So with that, we're going to be diving into DynamoDB. We'll cover three techniques again, and it doesn't mean they're the only three techniques, but maybe surprisingly or not, they're the same three methods. Local encryption, cross-account KMS encryption, and key policy lockout. They're a little bit different. They're done a little bit differently though. So for local encryption, we've got located the target table. We're going to export the entire table using the scan API, which is essentially just scan the table for data and download it. But we need to be careful hitting the read capacity of the table because we may cause a denial of service in the environment if we use up the read capacity, and that could trigger some alerts that then get us kicked out of the environment before we've actually downloaded any data or much data. Then we're going to locally encrypt the downloaded data with something like AES-256 again. We're going to overwrite the table's data with the encrypted data. So you can see target table, we scan it, locally encrypt it, and then use batch write item to write it back into the table. Alternatively, we could use get item and put item to encrypt items one at a time, but that would likely be much slower and there would be many more events for your actions than otherwise. Not so simple one-liner. I didn't write a one-liner for this one because the scan API returns a maximum of one megabyte of data per call. So that means you have to paginate the results, but essentially that's hard to do on the CLI. It's done a little bit funky and so I just didn't write one for this. It would be much easier to just write a quick Python script or something along those lines if you were going to try and abuse this method. So the next method for DynoDB is the cross-account KMS encryption method. We're going to create KMS key in our own attacker account like we did before for S3. We're going to configure that key policy to grant full access to the key cross-account to our target account. It's not going to let us apply the key to that table, to our target table essentially, unless you perform this step because there are a few different permissions that are required to successfully apply the key. So then you locate your target table. You modify the table and change the KMS key that's applied to it to be the key that you just created. It takes a minute to update, so you just wait for that for it to finish updating. Then you go into your own account and modify the KMS key policy to remove that cross-account access. So now, in theory, their DynamoDB database table has your encryption key applied to it and they don't have decrypt permission for that key. So if they try to view their table or the data within it, they're going to get non-authorized, as you can see here. Additionally, if they try and change the KMS key that's applied to the table, they're going to get access denied because it requires you to be able to decrypt the data of the table to then re-encrypt it with something else. So you essentially have full control of the table until you grant them access again. So the third method, KMS key policy lockout, is essentially the exact same method as S3. And it's another reason why this technique is even more risky than we talked about before, because like I said, it could be applied to multiple S3 buckets at once, but then also, in theory, it could be applied to one or more DynamoDB tables. So a single key policy ransom attack could hit, you know, three, four, five DynamoDB tables and a bunch of S3 buckets. Not that that's good practice, they should be applied to all those, but not everyone follows best practices. And so it's something to be aware of and hopefully prevent. In terms of defenses for DynamoDB, we'll do prevention and detection again. And again, the easy one, follow the principle of least privilege for KMS, key policies, and then IAM permissions for DynamoDB and KMS applied to your users and roles. AWS backups. So you want to use the backup feature of DynamoDB to create snapshots of your data, essentially, on some time period that you've set up. Offsite backups, those are important too, because an attacker, in theory, could just delete all your backups that are in AWS and then delete the database itself, and then there's no data anymore. Offsite backups could help prevent that, because you can just restore. And again, organization service control policies. I love these. There's lots you can do with them. And if you're not familiar, I really highly suggest looking into them and applying them to your organization. But again, they're going to be very customized. Use VPC endpoints for access. So essentially require your users to be within your VPC to access your DynamoDB tables. So that means an attacker would need to compromise your network prior to ransoming a DynamoDB table, which if they can do that, you're going to have far greater problems anyways. So it's a good practice to do this. And don't just let the entire internet access your table if they're aware of it. Point-in-time recovery. This is one I did have on here as a prevention, but as I did further testing, I found out it didn't actually work. So point-in-time recovery keeps snapshots over time in your database. And essentially, it allows you to go back to a specific time in the past. But what I found is if you enable it, and then you wait a little while, maybe mess with the data, then you apply a ransom KMS key to it, then you use point-in-time recovery to recover before that key was applied, it still doesn't work. It seems to be successful, and it starts creating the restored database, but then it just disappears from the console, and there's no trace of it. So my guess is that it just can't get to the data because it encrypted it all with the new key instead of the key that was present at the time. For detection, Cloud Trail Management event logging, again, very useful. KMS event logging, very useful. Guard duty, always very useful. CloudWatch alarms, you can use these to monitor the read and write capacity of your tables, so you know if there's a huge amount of reads or a huge amount of writes to your tables and could alert off of that. DynamoDB streams, scan, get item, and put item, and I think some others are not, or they're considered data events, so they're not logged by Cloud Trail. So you can use DynamoDB streams to stream those data events to a Lambda function and respond to them however you want, so that can be a way to monitor that data level activity. And maybe you can use AWS config to track changes to your tables, but usually this will be too late by the time it alerts you of anything. Indicators to look out for, again, STS get caller identity, KMS key policy modifications, high volume of table reads and writes, attempts to delete backups, guard duty alerts, attempts to increase the table's read capacity. If they find a large table that has a low read capacity, they might increase the read capacity so that they can run parallel queries and download the entire database quickly without causing a service in the environment. And that's kind of it for DynamoDB. I'm running out of time, so I'm trying to speed through a couple of these. Other potential targets, so there could be Elastic Walkstore and AWS, you can encrypt volumes or snapshots, relational database service, or RDS database and snapshots, Lambda function code and environment variables, secrets manager secrets, SNS topics, SQS queues, ECR repositories and images, which just got released last week, I believe, EFS file systems, and more. And then you can even do it for other cloud providers, but like I said earlier, we didn't dive into that, but something like Google Storage could be done the same way as S3. So cloud provider intervention and other takeaways. We don't know what a cloud provider could do to help you if you got targeted, so you can't rely on them for that. So you need to act as if they would not be able to help you under any condition. They can't help you with the local encryption anyways, because they're not going to know the password to your encrypted data. This means you need to evaluate your own defenses. You need to take care of your environment, monitor it, respond to things. You can't rely on the unknown, essentially. Can you keep attackers out of your environment? Can you prevent attackers from doing things once they're in your environment? Can you detect when they're doing things once they're in your environment? Can you match those detections to patterns? Can you tell that maybe a ransomware attack's coming because of these few API calls made in a row or something along those lines? And additionally, you need to ask, can I get back online after an attack? Am I ready? Do I know what to do if I got hit with a ransomware attack? If the answer is no, then you've got some work to do. And then how fast? Is it going to be fast enough before there's a major business impact? How much money are you going to lose in the meantime? It's a big, big question. And finally, the last big takeaway is, what if the attacker never decrypts your data? For some reason, what if you just can't get access? I mean, they are criminals. You can't necessarily trust them. Just because you pay them doesn't mean they're going to decrypt your data. So could you handle that? Are you going to go out of business? What's going to happen? That's something you need to think about. That kind of wraps things up. I have a slide here just of some additional resources and references. First one I always want to talk about is AWS documentation. I read that like it's the Bible. There are so many great things in there, and it's an easy way to learn in-depth about features of AWS that you might not know otherwise. So I'm constantly reading that. And then I wrote two blog posts on S3 ransomware in particular, while I ran a security labs. You can check those out. I want to give a special thanks to my team at CrowdStrike, just for helping with the presentation and the research, and giving me some feedback on that. Houston Hopkins from Capital One for some help with the one-liner commands and some cool tricks with the AWS CLI. And Rhino Security Labs for that previous research into ransomware and just AWS security in general. In the bottom right, you can see my Twitter handle there for if there's not sure how much time left we have for questions, but if there are any that don't get answered, feel free to reach out to me on there. But for that, I'll go ahead and just kind of open up and answer any questions that might be in the chat. Is object versioning and MFA delete good enough, or were you saying that you need to implement and do all five of those things? I think that object versioning and MFA delete are good for a couple of methods, but if you think of it like a local encryption method, if you downloaded the objects from the bucket, their threat could be we're going to release all this data. And so then versioning and MFA delete wouldn't do it. I like to always just follow defense in depth and implement as much as you can. Then it's hard to take into account the cost though, and then the work and changes that applies to your environment. But there's some of the best defenses, but it definitely won't protect you from everything essentially. Got it. And the second question from Skybound, I think you touched on this a little bit towards the end. For recovery in cases where decryption keys are within AWS, would AWS be able to help with their recovery and deal with the attacker? For example, with the KMS policy, basically expecting AWS to adjust the KMS policy so that the customer can get access back. So that's kind of where I was touching on. We don't know for sure. And then it brings up the question of how fast, you know, maybe it takes a support case and then a day or two goes by or something like that. And it's already, there's already a huge impact. I would say until there's an official statement or something along those lines, not that there needs to be one necessarily, but implementing your own defenses and detections is the way to go instead of relying on them to take care of you in the event that something goes wrong.