Blog

AWS Security Essentials: From Prevention to Detection

24 Sep, 2024
Xebia Background Header Wave

As businesses move to the cloud, ensuring the security of the cloud environment is crucial. AWS offers a range of security services like AWS Security Hub, AWS GuardDuty, Amazon Inspector, Amazon Macie etc. designed to help you monitor and respond to security events for your workload and infra. It’s also important to ensure that these security services themselves should be always active and functioning correctly. This post will dive into how we can monitor these AWS Security services and build a layered security approach, emphasizing the importance of both prevention and detection.

Before we dive into the details of AWS monitoring and detection tools, it’s important to acknowledge the role of preventive security measures like Service Control Policies (SCPs), IAM Policies, and AWS Guardrails. These tools are essential in preventing unauthorized or undesirable actions from taking place. For example, SCPs allow you to enforce account-wide permissions, ensuring that critical operations like disabling security services are blocked from the start.

Remember: Prevention is always the first line of defense. By implementing least privilege IAM policies, guardrails, and SCPs, you can prevent a large number of security risks from materialising.

However, even in a well-architected environment, there are scenarios where preventive measures alone may not be sufficient. ​​Imagine an organization where a legacy IAM role has been left with broad permissions, or a developer was temporarily granted permissions that haven’t been properly audited. Despite having SCPs or guardrails in place, this role might still have enough privilege to disable key security services like GuardDuty, Inspector or tamper with CloudTrail. In such cases, it becomes imperative to have detection mechanisms in place to catch risky actions that slip through the preventive layer.

This is where AWS monitoring services come into play, allowing you to detect and respond to such actions before they escalate into full-blown security incidents.

Detecting Suspicious Activity

To effectively monitor the AWS environment, we can leverage CloudTrail events. By configuring alerts and rules based on specific CloudTrail events, we can detect suspicious activity, such as unauthorized attempts to stop logging, disable security hub, disable inspector etc. This part outlined how we can monitor AWS security services themselves. For instance, we can set up CloudWatch Alarms or EventBridge rules that trigger alerts when events like StopLogging, DeleteTrail are detected.

Below architecture explains how we can monitor these services

Event Flow :

  • I have created EventRule that gets triggered as soon as if any one of the Security services get deactivated/disabled/deleted.
  • Event rule target is Lambda function, that extract details from corresponding event. Details like username — who disabled service, source ip, timestamp, eventname, eventsource. This will help us in investigation.
  • Once event is processed by Lambda, lambda publish message to SNS.
  • With SNS, depending on subscription (Email, SMS, HTTPs) we will get notified. Here we can cofigure any communication channel thats feasible for us. For this blog and demo, I’m using only Email and OpsGenie.

Below Python code shows event processing and SNS publish. In order find complete CloudFormation stack and code, refer repo :

 

import json
import boto3
import os

sns = boto3.client('sns')

def handler(event, context):
    detail = event['detail']
    eventName = detail['eventName']
    userType = detail['userIdentity']['type']
    eventSource = detail['eventSource']

    if eventName == 'ConsoleLogin' and userType == 'Root':
        accountId = detail['userIdentity']['accountId']
        timestamp = detail['eventTime']
        sourceIp = detail['sourceIPAddress']
        loginStatus = detail.get('responseElements', {}).get('ConsoleLogin')
        mfaUsed = detail.get('additionalEventData', {}).get('MFAUsed', 'No')

        # Log the event details
        print(f"Root login attempt: AccountId={accountId}, Timestamp={timestamp}, SourceIp={sourceIp}, Status={loginStatus}, MFAUsed={mfaUsed}")
        # Create JSON message
        message = {
            "AccountId": accountId,
            "Timestamp": timestamp,
            "SourceIp": sourceIp,
            "LoginStatus": loginStatus,
            "MFAUsed": mfaUsed,
            "Message": "Root login attempt detected"
        }
        # Publish message to SNS topic
        messageToPublish = json.dumps(message)
        messageHeader = f"Root login attempt detected\nAccountId: {accountId}\nTimestamp: {timestamp}\nSourceIp: {sourceIp}\nStatus: {loginStatus}\nMFAUsed: {mfaUsed}"
        sns.publish(
            TopicArn=f"arn:aws:sns:{os.environ['REGION']}:{os.environ['ACCOUNT_ID']}:SecurityAlarmsTopic",
            Message=messageToPublish,
            Subject=messageHeader
        )

    elif eventName == 'DisableSecurityHub':
        accountId = detail['userIdentity']['accountId']
        timestamp = detail['eventTime']
        sourceIp = detail['sourceIPAddress']
        userid = detail['userIdentity']['sessionContext']['sessionIssuer']['userName']

        # Create JSON message
        message = {
            "AccountId": accountId,
            "Timestamp": timestamp,
            "SourceIp": sourceIp,
            "UserID": userid,
            "EventSource": eventSource,
            "Message": "Security Hub has been Disabled"
        }
        # Publish message to SNS topic
        messageToPublish = json.dumps(message)
        messageHeader = f"Security Hub Disabled for Account: {accountId}"
        sns.publish(
            TopicArn=f"arn:aws:sns:{os.environ['REGION']}:{os.environ['ACCOUNT_ID']}:SecurityAlarmsTopic",
            Message=messageToPublish,
            Subject=messageHeader
        )
      # Alarm - GuardDuty Disable
    elif eventName == 'DeleteDetector' and eventSource == 'guardduty.amazonaws.com':
        accountId = detail['userIdentity']['accountId']
        timestamp = detail['eventTime']
        eventsource = detail['eventSource']
        sourceIp = detail['sourceIPAddress']
        userid = detail['userIdentity']['sessionContext']['sessionIssuer']['userName']

        # Create JSON message
        message = {
            "AccountId": accountId,
            "Timestamp": timestamp,
            "SourceIp": sourceIp,
            "UserID": userid,
            "EventSource": eventSource,
            "Message": "GuardDuty has been Disabled"
        }
        # Publish message to SNS topic
        messageToPublish = json.dumps(message)
        messageHeader = f"GuardDuty Disabled for Account: {accountId}"
        sns.publish(
            TopicArn=f"arn:aws:sns:{os.environ['REGION']}:{os.environ['ACCOUNT_ID']}:SecurityAlarmsTopic",
            Message=messageToPublish,
            Subject=messageHeader
        )

        # Alarm - Inspector Disabled   
    elif eventName == 'Disable' and eventSource == 'inspector2.amazonaws.com':
        accountId = detail['userIdentity']['accountId']
        timestamp = detail['eventTime']
        eventsource = detail['eventSource']
        sourceIp = detail['sourceIPAddress']
        userid = detail['userIdentity']['sessionContext']['sessionIssuer']['userName']

        # Create JSON message
        message = {
            "AccountId": accountId,
            "Timestamp": timestamp,
            "SourceIp": sourceIp,
            "UserID": userid,
            "EventSource": eventSource,
            "Message": "AWS Inspector has been Disabled"
        }
        # Publish message to SNS topic
        messageToPublish = json.dumps(message)
        messageHeader = f"AWS Inspector Disabled for Account: {accountId}"
        sns.publish(
            TopicArn=f"arn:aws:sns:{os.environ['REGION']}:{os.environ['ACCOUNT_ID']}:SecurityAlarmsTopic",
            Message=messageToPublish,
            Subject=messageHeader
        )
        # Alarm - Config Disabled    
    elif eventName == 'DeleteConfigurationRecorder' and eventSource == 'config.amazonaws.com':
        accountId = detail['userIdentity']['accountId']
        timestamp = detail['eventTime']
        eventsource = detail['eventSource']
        sourceIp = detail['sourceIPAddress']
        userid = detail['userIdentity']['sessionContext']['sessionIssuer']['userName']

        # Create JSON message
        message = {
            "AccountId": accountId,
            "Timestamp": timestamp,
            "SourceIp": sourceIp,
            "UserID": userid,
            "EventSource": eventSource,
            "Message": "AWS Config has been Disabled"
        }
        # Publish message to SNS topic
        messageToPublish = json.dumps(message)
        messageHeader = f"AWS Config Disabled for Account: {accountId}"
        sns.publish(
            TopicArn=f"arn:aws:sns:{os.environ['REGION']}:{os.environ['ACCOUNT_ID']}:SecurityAlarmsTopic",
            Message=messageToPublish,
            Subject=messageHeader
        )
We can easily simulate this by publishing below JSON via event bus or you can Enable/Disable this corresponding security service in test environment.
In order simulate, Go to EventBridge → Event Buses → Default event bus → Send Event
With successful simulation, you should able to get notification over channel that you have configured in SNS. In this case, I have configured only Email.

Troubleshooting

In case , if no notification is received :
  • Make sure SNS subscription have status Confirmed.
  • Check Cloudwatch logs for lambda function for further error.
If you would like to extend this monitoring for other services, you can update lambda and event rule by referring below table.

AWS Security – CloudTrail Events

Security ServiceDescriptionCloudTrail Event SourceEventName (when disabled)
AWS CloudTrailTracks API calls and user activity within your AWS account.cloudtrail.amazonaws.comStopLogging
Amazon GuardDutyThreat detection service that continuously monitors for malicious activity.guardduty.amazonaws.comStopMonitoringMembers
Amazon GuardDutyThreat detection service that continuously monitors for malicious activity.guardduty.amazonaws.comDeleteDetector
AWS ConfigMonitors and records configurations of AWS resources and evaluates resource compliance.config.amazonaws.comStopConfigurationRecorder
AWS Security HubProvides a comprehensive view of security alerts and security posture across AWS accounts.securityhub.amazonaws.comDisableSecurityHub
AWS ShieldManaged DDoS protection service that safeguards applications.shield.amazonaws.comDeleteSubscription
Amazon MacieUses machine learning to discover, classify, and protect sensitive data.macie2.amazonaws.comDisableMacie
AWS Firewall ManagerCentrally configures and manages firewall rules across accounts and applications.fms.amazonaws.comDeletePolicy
AWS IAM Access AnalyzerHelps identify resources that are shared with external entities.access-analyzer.amazonaws.comDeleteAnalyzer
Amazon InspectorAutomated security assessment service to help improve the security and compliance of applications deployed on AWS.inspector.amazonaws.comDeleteAssessmentTarget
AWS WAFWeb application firewall that helps protect web applications from common web exploits.waf.amazonaws.comDeleteWebACL

I hope this blog gave you an idea how we can monitor security services in AWS. While preventive controls such as SCPs and IAM policies are crucial to protecting your AWS environment but sometimes they are not enough. A truly secure environment requires a layered approach, incorporating monitoring and detection mechanisms to ensure that no gaps are left uncovered. 

Stay proactive, stay secure, and make the most of AWS’s powerful security monitoring capabilities.

Vikas Bange
Passionate about cloud technology, security and an enthusiastic learner. I believe in learning by sharing. Music fuels my journey, adding rhythm to my growth.
Questions?

Get in touch with us to learn more about the subject and related solutions

Explore related posts