How crypto miners hijack AWS accounts (Cryptojacking GUI-Vil Case Study)

GUI-Vil AWS Cryptojacking attacj case study

This is the story of how you print free money. It’s a story that involves an AWS account, a threat actor named GUI-Vil, and unauthorized crypto mining. This story is real, and it happens more often than you might think.

It’s about a real attack that happened not long ago, and similar attacks have been going on for years, ever since crypto mining became a thing.

In this article, I’ll explain step by step how the threat actor named GUI-Vil carried out the attack, taking advantage of the victim’s resources for illegal crypto mining, and I’ll also share some tips on how we can defend ourselves from these types of attacks.

Prefer watching videos over reading? Here you go:

Here’s a link to the complete architecture diagram.

Case Study

Threat actors hijacking AWS accounts to crypto mine is an issue that’s been going on for years…

For perspective, this is an issue that I had to defend against regularly when I was securing Linux Academy’s labs years back in 2016 and 2017, but in this post, we’re going to look at a much more recent attack orchestrated and executed by a threat actor dubbed GUI-vil (Goo-ee-vil).

This case study is straight from Permiso’s labs team and blog, so all credit goes to them for the detailed report that inspired this article. Definitely check out their post if you’d like to learn more.

So GUI-vil is a financially motivated threat group from Indonesia that specializes in performing unauthorized cryptocurrency mining activities. But how do they do it?

Let’s take a look at it step-by-step.

Chapter 1: The different stages of an attack

Typical cloud cyber attacks involve multiple different stages. Usually you have about 5 to 6, and they are:

  • Stage 1: Gaining Initial Access
  • Stage 2: Reconnaissance
  • Stage 3: Privilege Escalation (if needed)
  • Stage 4: Persistence and maintaining presence (aka creating backdoors)
  • Stage 5: Complete mission
  • I’m going to add a stage 6: Evade detection

Because I’m trying not to turn this into a novel, I’m going to go through all of these stages quickly. I’m thinking about turning this into a full course, though, so let me know in the comments below if that would be of interest, and if I get enough comments, I’ll do it 🙂

Chapter 2: Gaining Initial Access

The first stage to pull off this type of attack is to gain initial access to a system, service, or user, that we shouldn’t normally be able to access. There are multiple ways that this can happen in the cloud, but a common one, and the one that enabled this particular attack, is the use of compromised credentials.

What does that mean, and how does one find compromised credentials?

Glad you asked.

In this particular case study, GUI-vil used CVE-2021-22205, which according to NIST is a GitLab vulnerability that enabled Remote Code Execution (or RCE).

The service’s web interface allowed people to upload malicious files, and once uploaded, those files would open up a shell giving the attacker access to the server it was uploaded on.

The problem is that even though GitLab patched this issue in 2021 very quickly after the vulnerability was first discovered and reported by an ethical security researcher, some organizations running GitLab on-premises, meaning they are running their own installation of GitLab, still haven’t patched this issue.

This is an older article but even months after a fix was made available, at least 60,000 internet-facing GitLab installations still hadn’t patched.

That meant threat actors could use these vulnerable servers as bots to be part of massive botnets, or they could use their shell access to extract application and infrastructure credentials.

Going back to our case study, that’s exactly what GUI-Vil did. The attacker exploited the vulnerability, and gained access to sensitive data by reviewing code repositories, which included the access key for an Admin level identity in the victim’s AWS environment.

If you’re not familiar, access keys in AWS are what enable users to issue authenticated commands against the AWS API. So if you need to make calls to your AWS resources, you might create a user, generate secret access keys which gives you an access key ID and a secret access key, and then you can use those access keys to authenticate and authorize your calls.

Whatever permissions your user has is the permissions that your access keys have, so if an attacker gets access to admin-level access keys, they have officially become admins of your AWS account(s).

So to recap: GUI-Vil found this vulnerable GitLab server, exploited the CVE, and then moved on to the next phase, which is Reconnaissance.

Chapter 3: Reconnaissance

To validate that the access keys are real and still work, the threat actor then used a Windows GUI utility called the S3 Browser, which is a tool you can use to manage your S3 or CloudFront resources in AWS via a GUI interface instead of logging into the AWS console or using the command line.

GUI-Vil entered the access key ID and secret access key into S3 Browser, and then executed their first command which was to ListBuckets against the S3 service.

	"eventVersion": "1.08",
	"userIdentity": {
		**"type": "IAMUser",**
		"principalId": "redacted",
		"arn": "arn:aws:iam::redacted:user/redacted",
		"accountId": "redacted",
		"accessKeyId": "AKIA******",
		"userName": "redacted"
	"eventTime": "2023-04-18T14:47:39.0000000Z",
	"eventSource": "",
	**"eventName": "ListBuckets",**
	"awsRegion": "us-east-1",
	**"sourceIPAddress": "",
	"userAgent": "[S3 Browser 9.5.5 <>]",**
	"requestParameters": {
		"Host": ""
	"responseElements": null,
	"requestID": "T1ACJXN3EJQ4T58X",
	"eventID": "af6814ab-10e1-4c8a-88b6-384874592519",
	"readOnly": true,
	"eventType": "AwsApiCall",
	"managementEvent": true,
	"recipientAccountId": "redacted",
	"eventCategory": "Management",
	"tlsDetails": {
		"tlsVersion": "TLSv1.2",
		"cipherSuite": "ECDHE-RSA-AES128-GCM-SHA256",
		"clientProvidedHostHeader": ""
	"additionalEventData": {
		"SignatureVersion": "SigV4",
		"CipherSuite": "ECDHE-RSA-AES128-GCM-SHA256",
		"bytesTransferredIn": 0,
		"AuthenticationMethod": "AuthHeader",
		"x-amz-id-2": "2ZRMAF9dvfjiLRZq1UoaE6tspOgoHk4X/Vtvjb8orWdQPGgJQiOuXhn13eOL3s4+BY/+Fuf7ZxE=",
		"bytesTransferredOut": 389

Code language: JSON / JSON with Comments (json)

We can see from this event log that the call was made by an IAMUser, we can see the accountId and accessKeyId which have been redacted or masked, and then we can see the eventName as well as the sourceIPAddress and userAgent which confirms the use of the S3 Browser utility.

They run this command to verify that the access keys are still valid, because it could be that the organization had already rotated or invalidated these credentials.

In this case, they clearly hadn’t, which told GUI-Vil that they had something to work with.

It’s at this point that an attacker will move on to Stage 4: which is persistence and maintaining presence

Stage 4: Persistence and maintaining presence (aka creating backdoors)

Once an attacker or pentester knows that they have initial access, they will want to escalate privileges (if needed) or find a way to maintain presence, usually by means of creating some sort of backdoor.

In the case of this attack, because they got their hands on an admin-level account, they didn’t actually need to escalate privileges, but instead, they wanted to create a new identity in order to maintain access.

You see, just because you found access to an admin account doesn’t mean tomorrow that account will still be around or those credentials will still work. It’s very possible that the organization will change settings, just from day-to-day activities, even if they don’t know about the exploit. Instead, attackers want to create resources only they control, and that way they know they can maintain access to the environment unless they get detected.

So GUI-Vil decided to use the access keys to issue the command CreateUser, and they created an AWS IAM user named backup. They then issued the command CreateAccessKey to generate their own access keys for that backup user.

Then, they issued the command PutUserPolicy to create a policy named backupuser which give full privileges to all resources and all actions for their backup user. Essentially, these are admin-level privileges.

  "Statement": [
      "Effect": "Allow",
      "Action": "*",
      "Resource": "*",
      "Condition": {}

Code language: JSON / JSON with Comments (json)

A video I published right before this one actually demonstrates how to escalate privileges with PutUserPolicy to gain admin privileges, so check out that video to see exactly how something like this can be done

At that point, GUI-Vil can change their credentials and user to the backup user they had just created which will enable them to maintain presence. They can also enable AWS Console Access (iam:CreateLoginProfile) for this user so that they can continue their attack from the management console instead of having to use the S3 Browser or command line interface.

From there, they can keep performing reconnaissance, like to check to see what’s going on with the EC2 service in this account.

Chapter 5: Setup crypto mining

Alright, most of the hard work has now been done, and we’ve entered stage 5, which Permiso likes to call “Complete the mission” … aka set up crypto mining.

This is where the magic happens and GUI-Vil is able to print free money, because about 31 minutes after gaining initial access, the attacker started creating EC2 instances to mine cryptocurrency from. They tried spinning up dozens of xlarge EC2 instances across many regions, but they ran into resource limitations from AWS (We currently do not have sufficient p3.16xlarge capacity in zones with support for 'gp2' volumes. Our system will be working on provisioning additional capacity.)

In total, they successfully launched 13 instances in 5 different regions. All Instances had these attributes:

  • Sized xlarge
  • Had detailed cloudwatch monitoring disabled "monitoring": { "state": "disabled"}
  • TCP/22 open to (everyone)
  • IPv4 enabled, IPv6 disabled
  • HttpTokens set to optional
  • Xen hypervisor

As you can see, they disabled CloudWatch monitoring from reporting data about these machines.

As they created these resources, they generated key pairs via the ec2:CreateKeyPair command, which gives them the ability to connect to the EC2 instances directly via SSH. From there, they can run 3 simple commands to start mining via XMRIG:

  • apt-get update
  • apt-get install git build-essential cmake libuv1-dev libssl-dev libhwloc-dev -y (a bunch of utilities needed for xmrig)
  • /home/ubuntu/xmrig

By the way, if you want to see xmrig being used in action, check out my blog post called “Detecting and Terminating Malware in Real Time”

Chapter 6: Clean up and evade detection

After accomplishing their mission, attackers will sometimes attempt to hide their tracks or evade detection. I say sometimes because this depends on their skill level, access, and other factors, but if they know how and they have the ability, they will likely try to do this.

With this case study, we already discovered that they disabled CloudWatch monitoring,

Something else that GUI-Vil has been known to do is to observe CloudTrail logs to see what changes the victim organization is making. That can indicate whether they know something is going on or not, and it can help the attacker find ways around attempts to block access.

But ideally, the attacker will try to remain completely undetected for as long as possible, which means they may modify the CloudTrail settings, they may modify some of the logs to hide resource creations, they may disable alerts or monitoring, they may change where notifications get sent to, etc…

This is a massive topic on its own, so again let me know if you’d like to see a course on this where I could go into a lot more detail.

Defending against crypto mining on AWS attacks

The (eye-watering) cost

OK so we learned how this attack got carried out…but how can we defend against this in our own AWS environments, and how can we enable detection so that we’re not finding out this happened after we owe AWS tens of thousands of dollars for running 13 p3.16xlarge instances which cost $24.48 per hour PER INSTANCE…aka $318.24 per hour … aka $7,637.76 per day

As a side note, I’ve known AWS to work with organizations in order to give them credits for these costs…this isn’t a guarantee and I’m sure sometimes they don’t do that, especially if it looks like you made zero efforts to protect your account, but if you ever find yourself in this situation, talk to them. See what they can do to help.


OK so to defend against this, obviously you want to try and avoid compromised credentials as much as possible. That means patch your GitLab servers if you haven’t in the past 2 years…

You shouldn’t be hardcoding credentials in repositories…If you are using access keys, make sure you are properly storing and managing them, and ensure they get rotated on a schedule. Ideally, though you want to avoid using access keys and instead make use of roles.

Next, and this one is non-negotiable: stop using admin privileges for users or roles running apps.

A lot of this is explained in my Introduction to AWS Security course but there is not a single application you are running that requires admin privileges. Applications will require access to other services, sure, but that’s the only permissions you should be granting. Follow the principle of least privilege.

After that, you can take a look at Permiso’s blog post for:

  • Atomic Indicators
  • Permiso CDR Rules
  • Basic sigma rules

They also have a list of Observed Events that could potentially indicate something odd is going on in your account.

Beyond covering the basics of AWS security, this information can help you set detection processes in place to detect this sort of attack not just from GUI-Vil but other similar threat actors.


Alright so what do we think? Should I create a course that walks through this attack hands-on instead of just discussing concepts? Let me know in the comments below.

I appreciate you taking the time to read my post. Don’t forget to share with your colleagues 🙂 they probably need to see this too

Thanks, and see you next time.

Related Articles


Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.