For this blog, we will take a look at how to identify and remediate threats in your cloud environment using Amazon GuardDuty and Dome9 CloudBots.

Identify threats with Amazon GuardDuty

Here you can see the GuardDuty findings below. We will specifically explore a malicious IP talking to an EC2 instance in your environment.

[wp_colorbox_media url=”https://dome9.com/wp-content/uploads/2018/09/GD-1.png” type=”image” hyperlink=”https://dome9.com/wp-content/uploads/2018/09/GD-1.png” alt=””]

You can specifically filter and drill down into the finding related to the compromised instance.

[wp_colorbox_media url=”https://dome9.com/wp-content/uploads/2018/09/GD-4-1.png” type=”image” hyperlink=”https://dome9.com/wp-content/uploads/2018/09/GD-4-1.png” alt=””]

 

Remediation with Dome9 CloudBots

When situations arise, the most important thing is to have a pre-defined security playbook or runbook that can be a guiding process for IR and remediation.

First as you launch the stack, you need to input a few variables.

[wp_colorbox_media url=”https://dome9.com/wp-content/uploads/2018/09/Screen-Shot-2018-09-20-at-5.15.03-PM.png” type=”image” hyperlink=”https://dome9.com/wp-content/uploads/2018/09/Screen-Shot-2018-09-20-at-5.15.03-PM.png” alt=””]

For GD Actions, please navigate here to specifically select which actions you would like cloudbots to take. It should be in the format

{
    "Backdoor:EC2/XORDDOS": "AUTO: ec2_stop_instance"
}

Once you create your stack, you should see the below:

[wp_colorbox_media url=”https://dome9.com/wp-content/uploads/2018/09/Screen-Shot-2018-09-20-at-5.11.25-PM.png” type=”image” hyperlink=”https://dome9.com/wp-content/uploads/2018/09/Screen-Shot-2018-09-20-at-5.11.25-PM.png” alt=””]

The lambda function should have your output SNS and GD_ACTIONS listed below

[wp_colorbox_media url=”https://dome9.com/wp-content/uploads/2018/09/Screen-Shot-2018-09-20-at-5.08.31-PM.png” type=”image” hyperlink=”https://dome9.com/wp-content/uploads/2018/09/Screen-Shot-2018-09-20-at-5.08.31-PM.png” alt=””]

 

GuardDuty findings are sent to an SNS topic (CW_CD), to which the Dome9 Cloudbot lambda function subscribes to. Following actions are taken by Dome9 CloudBots

1. Parse SNS event

2. Transform the GuardDuty SNS event into a Dome9 finding format

3. Check GD_ACTIONS and AUTO tag on finding and launch specific CloudBot

5. Remediate with predefined action

Index.py

This code parses the first record of the GuardDuty finding event stream and looks for the message value. As long as the source of the finding is an “aws.guardduty” finding, it calls GD_transform_event module

### code snippet###
{
  #Bring the data in and parse the SNS message
def lambda_handler(event, context):
    raw_message = event['Records'][0]['Sns']['Message']
    source_message = json.loads(raw_message)
    try: 
        try:
            source_message = json.loads(raw_message)
        except: # If the event comes through as a dict, take it as it comes
            source_message = raw_message
        # Check for source. Transform it to "Dome9" format if it's not originating from Dome9. 
        # This expects that GD is triggering lambda via SNS. This is needed for running cross-region GD events. 
        if "source" in source_message and source_message["source"] == "aws.guardduty": # GuardDuty event source via CW Events
            text_output_array.append("Event Source: GuardDuty\n")
            gd_transform_module = importlib.import_module('transform_gd_event')
            found_action, text_output, source_message = gd_transform_module.transform_gd_event(source_message)
            text_output_array.append(text_output)
            if not found_action:
                print(text_output_array)
                return      
}

GD_transform_event module

This code parses the SNS event and transforms the message (transform code below) into a Dome9 format to allow appropriate action to take place.

### code snippet### 
{
 def transform_gd_event(unformatted_message):
    found_action = False
    formatted_message = ""
    text_output = ""
    #Check the OS variables to get the list of what we want to do for the different GD actions
    try:
        gd_actions = json.loads(os.environ['GD_ACTIONS'])

        for gd_finding_type, action in gd_actions.items():
            if unformatted_message["detail"]["type"] == gd_finding_type and "AUTO:" in action:
                text_output = "Found a defined rule for GD finding %s. Continuing\n" % gd_finding_type
                found_action = True
                break    

 # code snippet
    try:
        # Make the main structure of the formatted message
        formatted_message = {
            "reportTime": unformatted_message["detail"]["createdAt"],
            "rule": {
                "name": action,
                "complianceTags": action
            },
            "status": "Failed",
            "account": {
                "id": unformatted_message["detail"]["accountId"],
                "vendor": "AWS"
            },
            "entity": {
                "region": unformatted_message["detail"]["region"]
            }
        }
}

 

Handle.py

The handle.py function takes the JSON message, breaks into chunks and checks for a  specific tag: UnauthorizedAccess:EC2/MaliciousIPCaller.Custom and looks for the specific tag under GD_ACTIONS. In this case, I wanted to stop the instance so I used: {“UnauthorizedAccess:EC2/MaliciousIPCaller.Custom”: “AUTO: ec2_stop_instance”} The function then calls run_action to stop the affected EC2 instance

{
def handle_event(message,text_output_array):
    post_to_sns = True
    #Break out the values from the JSON payload from Dome9
    rule_name = message['rule']['name']
    status = message['status']
    entity_id = message['entity']['id']
    entity_name = message['entity']['name']
    region = message['entity']['region']
    compliance_tags = message['rule']['complianceTags'].split("|")
## removed code ##
  for tag in compliance_tags:
        tag = tag.strip() #Sometimes the tags come through with trailing or leading spaces. 
        #Check the tag to see if we have AUTO: in it
        pattern = re.compile("^AUTO:\s.+")
        if pattern.match(tag):
            text_output_array.append("Rule violation found: %s \nID: %s | Name: %s \nRemediation bot: %s \n" % (rule_name, entity_id, entity_name, tag))
            # Pull out only the bot verb to run as a function
            # The format is AUTO: bot_name param1 param2
            arr = tag.split(' ')
## removed code
## Run the bot ##
   bot_msg = bot_module.run_action(boto_session,message['rule'],message['entity'],params)

The bot ec2_stop_instance.py code

{
  ### Turn off EC2 instance ###
def run_action(boto_session,rule,entity,params):
instance = entity['id']
ec2_client = boto_session.client('ec2')

result = ec2_client.stop_instances(InstanceIds=[instance])
responseCode = result['ResponseMetadata']['HTTPStatusCode'] if responseCode >= 400: text_output = "Unexpected error: %s \n" % str(result) else: text_output = "Instance stopped: %s \n" % instance return text_output
}

You should see EC2 instance stopped:

[wp_colorbox_media url=”https://dome9.com/wp-content/uploads/2018/09/Screen-Shot-2018-09-20-at-10.40.26-AM.png” type=”image” hyperlink=”https://dome9.com/wp-content/uploads/2018/09/Screen-Shot-2018-09-20-at-10.40.26-AM.png” alt=””]

 

Explore logs

You may also like