Modifying a Falco Rule for CloudTrail

Using Sysdig CloudConnector, you are not limited to the out-of-the-box rules provided. You can modify existing rules, or write your own tailored to your own needs.

Let’s try first modifying a rule. The following rule checks if a resource is created in a region that you are not usually using. However, to be active you must specify which regions you want to detect.

- list: disallowed_aws_regions
  items: []

- rule: AWS command executed on unused region
  desc: Detect AWS command execution on unused regions
  condition: >
    not jevt.value[/errorCode] exists and
    jevt.value[/awsRegion] in (disallowed_aws_regions)
  output: >
    An AWS command has been executed on an unused region
    (requesting user=%jevt.value[/userIdentity/arn],
     requesting IP=%jevt.value[/sourceIPAddress],
     AWS region=%jevt.value[/awsRegion]
  priority: CRITICAL
  tags: [cloud, source=cloudtrail, aws]
  source: k8s_audit

For the disallowed_aws_regions empty list that is included, we are going to extend it to include us-west-1 and us-west-2. Let’s update that list to add those regions.

  - list: disallowed_aws_regions
    items: [us-west-1, us-west-2]
    append: true
  1. To create a disallowed_aws_regions.yaml file in a rules directory, you can run the following

    mkdir -p rules
    cat <<EOF >rules/disallowed_aws_regions.yaml
      - list: disallowed_aws_regions
        items: [us-west-1, us-west-2]
        append: true
    
    EOF

    When you create custom Falco files, ensure last content in the file is a blank new line without extra tabs to avoid messing with additional files that may be loaded after it.

    When you deploy Cloud Connector, it creates a bucket for you to store configuration and custom Falco code. It’s name will be autogenerated with “CloudConnector” as a prefix. You can work with it using AWS web dashboard, however we are going to explain how to do it using the AWS cli.

  2. First let’s store the bucket name in a variable called cc_bucket

    cc_bucket=$(aws cloudformation list-stack-resources --stack-name CloudConnector --output json | jq '.StackResourceSummaries[] | select(.LogicalResourceId=="CloudConnectorBucket").PhysicalResourceId' | xargs)
    echo $cc_bucket
  3. Now let’s sync our local rules directory with the bucket. Execute this command to upload the directory contents, deleting any extra file located in the remote directory.

    aws s3 sync "./rules/" s3://$cc_bucket/rules --delete
  4. We now have to restart the Cloud Connector Fargate task to take the new rules into consideration. Again you can do so using the AWS web dashboard, or executing these commands:

    task_id=$(aws ecs list-tasks --cluster CloudConnector --output json | jq '.taskArns[0]' | /usr/bin/xargs | sed -E 's/.*\/(.+)/\1/')
    echo $task_id
    AWS_PAGER="" aws ecs stop-task --cluster CloudConnector --task $task_id

    It usually takes the Fargate task a couple of minutes to restart. You can follow Cloud Connector logs to check it’s status, discarding very verbose messages that are not essential, using this command:

    aws logs tail cloud-connector --follow  --filter-pattern "{ $.component != "http-server" && $.component != "cloudtrail-sns-http-ingestor" }"

    When you see info level messages indicating the rules have been loaded like the following example, and maybe some alerts, it means the new settings and rules have been loaded.

  5. Now we create a new log group on us-west-2

     2020-11-11T17:31:27.770000+00:00 ecs/CloudConnector/6cbd184c9ce446baa1beb5ef2f91fcdb {"level":"info","component":"main","time":"2020-11-11T17:31:27Z","message":"Starting cloud-connector"}
    2020-11-11T17:31:27.770000+00:00 ecs/CloudConnector/6cbd184c9ce446baa1beb5ef2f91fcdb {"level":"info","component":"directory-rule-provider","time":"2020-11-11T17:31:27Z","message":"loading rules from /rules"}
    2020-11-11T17:31:27.959000+00:00 ecs/CloudConnector/6cbd184c9ce446baa1beb5ef2f91fcdb {"level":"info","component":"s3-rule-provider","time":"2020-11-11T17:31:27Z","message":"loading rules from s3 bucket 'cloudconnector-cloudconnectorbucket-6gq5ia7dir18' with path 'rules'"}
    2020-11-11T17:31:27.973000+00:00 ecs/CloudConnector/6cbd184c9ce446baa1beb5ef2f91fcdb {"level":"info","component":"rule-loader","time":"2020-11-11T17:31:27Z","message":"loaded 98 rules, 13 lists and 39 macros from 2 rule providers"}     
    2020-11-11T17:31:28.080000+00:00 ecs/CloudConnector/6cbd184c9ce446baa1beb5ef2f91fcdb {"level":"info","component":"main","time":"2020-11-11T17:31:28Z","message":"cloud-connector is listening to HTTP requests"}
  6. Now that we know the modification has been loaded, we create a new log group on us-west-2 to trigger a a security alert.

    aws logs create-log-group --log-group-name "test_unused_region" --region="us-west-2"

    CloudTrail takes up to 10 minutes to provide the events. When the event is available, CloudConnector will trigger the rule and we will see a new security event on the log, as well as a new finding appearing in AWS Security Hub.

     2020-11-11T18:31:07.093000+00:00 ecs/CloudConnector/6b068dbba66a404696db054cf3d46341 {"level":"warn","component":"console-notifier","name":"AWS Command Executed on Unused Region","priority":"CRITICAL","event.ID":"69cc425f-17db-4647-b27e-8a75d375a40b","event.HappenedOn":"2020-11-11T18:20:36Z","time":"2020-11-11T18:31:07Z","message":"An AWS command has been executed on an unused region (requesting user=arn:aws:iam::972909301756:root, requesting IP=87.218.230.200, AWS
    region=us-west-2)"}

    Triggered Security Event