Tuesday, February 26, 2019

Revamping AWS APIs' security review and SCP policy generation process.

AWS Cloud provides endless amount of the capabilities and services. Unleashing all this power on the without proper security review process is extremely risky.
Each service and quite often even each api call should be reviewed and evaluated according to the organizational security standards  and compliance requirements. Yes, but.. curently AWS has about 170 services and endless amount of APIs. AWS constantly evolves, introduce new services, APIs and modifying existing.
One of the biggest challenge for me was finding a way to automatically fetch up-to-date annotated  list of the services and api provided by AWS. Luckily, Matt Weagle suggested to use AWS GO SDK as a source of truth. This SDK provides well documented lists of the AWS APIs (docs-2.json)

I crafted small python program that builds/updates following yaml files (one per each service) using json files as a source:

  description: Assess, monitor, manage, and remediate security issues across your
    AWS infrastructure, applications, and data.
  links: [http://guardduty.docs.here]
  security_risk: Cloud IDS
  - Prod_en
  - none
  description: Accepts the invitation to be monitored by a master GuardDuty account.
  links: [https://awsdocs.com]
  security_risk: should be allowed only from trusted accounts
  - none
  - none
  description: Archives Amazon GuardDuty findings specified by the list of finding
  links: []
  security_risk: Not defined
  - none
  - none

Structure of this file is quite self-explanatory and simplifies security review(still manual process) of the AWS APIs. During security review,  you specify which services/api are enabled/disabled and on which environments by adding environment name to the Allowed_on  and Denied_on lists. Files are stored in the git repo.

After the review, using these files as a source of truth, I (actually another python program) generate an SCP (Service Control Policy) for AWS Organization's accounts, IAM policies and permission boundaries (it depends on the case.)
Due to the very strict SCP size restrictions , generating this policy using automation allows you:

  • aggregate APIs using wildcards to reduce SCP size
  • validate API wildcards preventing unintentional service exposure/blockage
  • perform cross check for the API to avoid whitelisting/blacklisting conflicts
  • re-generate/validate SCP if AWS introduces new API calls/services
Everything mentioned above is valid not only for the SCP, but for the IAM policy/permission boundaries generation process.

This automated approach opens another possibility - automated compliance validation for AWS: using the same yaml files as a source of truth ,  perform API calls to the AWS to ensure that these calls will fail. This step could be done after deployment (to validate deployment) or on a regular basis(audit).

PS. Unfortunately code of the tools can't be open-sourced as of now.

Tuesday, November 27, 2018

AWS Landing Zones current docs

It took me a quite time to find latest AWS Landing Zones official docs. 
To save you time here are they (November 2018):

Deployment Guide:

User Guide:

Developer Guide:

Please be aware that before deploying AWS landing zones solution in your account, you need to contact AWS Support to get default AWS Account limits extended.

Wednesday, September 26, 2018


Happy to present new self-scan service - nmap.me:

What it does? TCP Scan of you external IP.
What it scanning for: 100 most used tcp ports. Actually a bit more than 100 - I'm slowly adding more ports.
How to use: simply curl nmap.me from your console/terminal or open it in browser.
How fast: whole scan takes about a second. Results for each requester IP are cached for 1 hour to reduce load and prevent abuse.

Why? Needed quick way to check open ports on server/gateway/fw/router while being inside the console.

New features? Coming...
Feature request, bug, service down? Let me know!

Tuesday, January 30, 2018

AWS Route53 DNS records backup/change using aws cli

 you need to change a lot of DNS records inside the AWS Route53 hosted zone. In prod...
 Let's  skip the obvious question why these DNS records are not managed as Infra-as-aCode..
Sure thing, you need to backup all these record prior to change for rollback purpose.

1. create a list of the dns names to change
cat multisitest.it-security.ca.list 

2. get zone id from AWS cli:
aws route53 list-hosted-zones

3. Normally aws route53 list-resource-record-sets --hosted-zone-id Z1YS
will give you JSON, but unfortunately it's not useful for quick restore due to the format difference from the change-resource-record-sets.json file you need to have to change/restore records.

4. With a quick and quite dirty bash we can get better formatted JSON:
while read site; do echo '{ "Action": "UPSERT","ResourceRecordSet":';  aws route53 list-resource-record-sets --hosted-zone-id Z1YS --query "ResourceRecordSets[?Name == '$site']" --profile it-sec | jq .[] ; echo "},"; done < multisitest.it-security.ca.list > multisitest.it-security.ca.back.json

This file has almost everything needed to build change-batch file for the aws cli: https://docs.aws.amazon.com/cli/latest/reference/route53/change-resource-record-sets.html
Almost.. We need to add
  "Comment": "Point some Test TLS1.2 enviroments to the Incapsula",
  "Changes": [
in the beginning of the change set, and
remove "," and add
 att the end.

5. Now you have Route53 DNS records backed up and  ready to restore.
Next step is to create a copy of you backup file and modify it to reflect changes you need to make.

6. Final step: apply your changes:
aws route53 change-resource-record-sets --hosted-zone-id Z1YS  --change-batch file://multisitest.it-security.ca.json --profile it-sec

7. And, in case of disaster, use the same command to roll it back quickly specifying backup file:

aws route53 change-resource-record-sets --hosted-zone-id Z1YS  --change-batch file://multisitest.it-security.ca.back.json --profile it-sec

Saturday, January 20, 2018

Secure your AWS account using Terrafrom and CloudFormation

This is very updated version of the blog post: http://blog.it-security.ca/2016/11/secure-your-aws-account-using.html

As I mention before:
The very first thing you need to do while building your AWS infrastructure is to enable and configure all AWS account level security features such as: CloudTrail, CloudConfig, CloudWatch, IAM, etc.

Time flies when you're having fun and flies even faster in the infosec world. My templates become outdated and now I'm presenting an updated version of the AWS security automation with following new features:

  1. integrated with Terraform (use terraform templates in the folder tf)
  2. creates prerequisites for Splunk integration (User, key, SNS, and SQS)
  3. configures cross-account access (for multiaccount organizations, adding ITOrganizationAccountAccessRole with MFA enforced)
  4. implements Section 3 (Monitoring) of the CIS Amazon Web Services Foundations benchmark.
  5. configures CloudTrail according to the new best practices (KMS encryption, validation etc)
  6. configures basic set of the CloudConfig rules to monitor best practices
First, my security framework now consists of two main parts: cf (CloudFormation) and tf (Terraform) with Terraform template as a bootstrapper of the  whole deployment.

You can use  Terraform, you can use CloudFormation, but why both ?
Terraform is very quickly evolves, has cross-cloud support and implements some missing in CloudFormation features (like account level password policy configuration, etc); CloudFormation is native for AWS, well supported, and, most important, AWS provides a lot of best practices and solutions in the form of the CloudFormation templates.

Using both (tf and cf) gives me (and you) ability to reuse solutions, suggested and provided by AWS, without rewriting the code, have flexibility and power of terraform and one single interface for whole cloud automation.
No more bucket pre-creation or specific sequence of the CloudFormation deployment - just terraform apply. It will take care of all CloudFormation prerequisites, version control and template updates.
But,  if you wish, at current state you can use only my CloudFormation templates - cf still does all heavy lifting.

The main trick of the Terraform - CloudFormation integration was to tell terrafrom when CloudFormation template is updated to ensure that terraform will trigger cf stack update.
I achieved this using S3 bucket with version control enabled and always updating (just setting template version) security.global.yaml.

This code takes care of Terraform and CloudFormation integration:
# creating Security cloudforation stack

resource "aws_cloudformation_stack" "Security" {
  name = "Security"
  depends_on = ["aws_s3_bucket_object.iam_global", "aws_s3_bucket_object.cloudtrailalarms_global", "aws_s3_bucket_object.awsconfig_global", "aws_s3_bucket_object.cloudtrail_global", "aws_s3_bucket_object.security_global"]
  parameters {
    AccountNickname = "${var.enviroment_name}",
    CompanyName = "${var.company_name}",
    MasterAccount = "${var.master_account}"
  template_url = "https://s3.amazonaws.com/${aws_s3_bucket.CFbucket.bucket}/${var.security_global}?versionId=${aws_s3_bucket_object.security_global.version_id}"
  capabilities = [ "CAPABILITY_NAMED_IAM" ]
  tags { "owner" = "infosec"}

And finally deployment steps are:

  1. Get code from my git repo:  https://github.com/IhorKravchuk/it-security
  2. Switch to tf folder and update terraform.tfvars specifying: your AWS profile name (configured for aws cli using aws configure --profile profile_name); name for the environment (prod, test, dev ..) ; company(or division) name; region and AWS master account ID.
  3. terraform init to get aws provider downloaded by terraform
  4. terraform plan
  5. terraform apply

Monday, July 24, 2017

S3 buckets audit: check bucket's public access level, etc .. updated with authorised audit support

I previous post: S3 buckets audit: check bucket existence, public access level, etc - without having access to target AWS account I described and released tool to audit s3 buckets even without access to the AWS account these buckets belong to.

But what about if I have access to the bucket's account or I would like to audit all buckets in my AWS account?

These features have been addressed in the new release of the s3 audit tool:


$python aws_test_bucket.py --profile prod-read --bucket bucket2test

$python aws_test_bucket.py --profile prod-read --file aws

$python aws_test_bucket.py --profile prod-read --file buckets.list

                        Please specify AWS CLI profile
  -B BUCKET, --bucket=BUCKET
                        Please provide bucket name
  -F FILE, --file=FILE  Optional: file with buckets list to check or aws to check all buckets in your account

--profile=AWS_PROFILE - yours AWS access profile (from aws cli). This profile  might or might not have access to the audited bucket (we need this just to become Authenticated User from AWS point of view ).

If  AWS_PROFILE allows authorised access to the bucket being audited - tool will fetch bucket's ACLs, Policies and S3 Static Web setting and perform authorised audit.

If AWS_PROFILE does not allow authorised access - tool will work in pentester mode

You can specify:
  •  one bucket to check using --bucket option
  •  file with list of buckets(one bucket name per line) using --file option
  •  all buckets in your AWS account (accessible using AWS_PROFILE) using --file=aws option

Based on the your AWS profile limitations tool will provide you:
  • indirect scan results (AWS_profile have no API access to the bucket being audited)
  • validated scan results based on you s3 buckets settings like ACL, bucket policy and s3 website config. (AWS_profile have API access to the bucket being audited )
Enjoy and stay secured.

PS. Currently tool does not support bucket check for Frankfurt region (AWS Signature Version 4). Working on it.

Wednesday, July 19, 2017

S3 buckets audit: check bucket existence, public access level, etc - without having access to target AWS account

      Currently, publicly accessible buckets become a big deal and root cause of many recent data leaks.
All of these events even drive Amazon AWS to proactively send out emails to the customers who has such s3 configurations. Let's become a bit more proactive as well and audit s3 buckets

        First, let's take look why bucket might become publicly available:
- Configured for public access intentionally (S3 static web hosting or just public resource) or by mistake
- Configured for the access of the Authenticated Users  (option, misinterpreted by many as users from your account, which is wrong, it's any AWS authenticated user from any account)
         Auditing AWS account you have full access to is quite easy - just list the buckets and check theirs ACL, users and bucket policies via aws cli or web gui.

         What about cases when you:
- have many accounts and buckets (will take forever to audit manually)
- do not have enough permissions in the target AWS account to check bucket access
- you do not have permissions at all in this account (pentester mode)

To address everything above I've created small tool to do all dirty job for you (updated to v2):

$python aws_test_bucket.py --profile prod-read --bucket test.bcuket

                        Please specify AWS CLI profile
  -B BUCKET, --bucket=BUCKET
                        Please provide bucket name
  -F FILE, --file=FILE  Optional: file with buckets list to check

Note: --profile=AWS_PROFILE - any your AWS access profile (from aws cli). This profile HAS to NOT have access to the audited bucket (we need this just to become Authenticated User from AWS point of view )

You can specify one bucket to check using --bucket option or file with list of buckets(one bucket name per line) using --file option

Based on the bucket access status tool will provide you following responses:

Bucket: test.bucktet - The specified bucket does not exist
Bucket: test.bucktet -  Bucket exists, but Access Denied
Bucket: test.bucktet -  Found index.html, most probably S3 static web hosting is enabled
Bucket: test.bucktet - Bucket exists, publicly available and no S3 static web hosting, most probably misconfigured! 


PS. More over, you can create list of the buckets(even using some DNS/name alterations and permutations) to test in the file and loop through it checking each.

Stay secure.