Identify New Databse Snapshots T1578.001
- Look through CloudTrail logs to find CreateDBSnapshot API calls with the db specified within dBSnapshotIdentifier.
Detect Potential Financial Theft T1657
- Query Amazon Macie for alerts the GUI.
- Query Amazon Macie for alerts within the GUI.
- View CloudWatch Logs Alerts for PII within data.
Detect Cloud Compute Infra Modification T1578
- Query AWS Config with the specific security group.
- Commands to run:
INSTANCE_ID=$(aws ec2 describe-instances --filters Name=tag:Name,Values=[Role] --query Reservations[].Instances[].InstanceId --output text)
aws configservice get-resource-config-history --resource-type AWS::EC2::Instance --resource-id $INSTANCE_ID]
- Commands to run:
- Use the Resource Timeline within AWS Config GUI.
Detect Non Standard Port Listening T1571
- Query the security group of the asset and find the ports available.
- Commands to run:
SG_ID=$(aws ec2 describe-instances --filters Name=tag:Name,Values="SherlocksBlog" --query Reservations[].Instances[].SecurityGroups[0].GroupId --output text)
aws ec2 describe-security-groups --group-ids $SG_ID | jq '.SecurityGroups[].IpPermissions[] | {FromPort, ToPort, IpProtocol}'
- Commands to run:
- Review AWS Inspector Network Reachability results for the specific instance.
Detect Crypto Miner T1496
- View the Kubernetes Cluster CPU level within the CloudWatch GUI Alarms.
- Query the CloudWatch Logs Inisights for alarms related to crypto miners.
- Command to run:
aws cloudwatch describe-alarms | jq -r '.MetricAlarms[] | select(.StateValue == "ALARM") | .AlarmName'
- Command to run:
- Query CloudWatch via the CLI with the appropriate log group of Kubernetes application logs to see interesting pod name.
- Commands to run:
QUERY_ID=$(aws logs start-query --start-time $(date -d "30 mins ago" +"%s") --end-time $(date +"%s") --log-group-name [ApplicationLogGroupName] --query-string 'fields @message | filter kubernetes.container_name == "[ContainerName]"' --output text)
aws logs get-query-results --query-id $QUERY_ID | jq -r '.results[][] | select(.field == "@message") | select(.value | contains ("appdeploymentfromfile"))'
- Commands to run:
View ListBuckets Activity T1526
- Query CloudTrail for ListBuckets within AWS CLI.
- Command to use:
aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=ListBuckets --query 'Events[].{EventId:EventId,EventName:EventName,EventTime:EventTime,Username:Username}' --output table
- Command to use:
- Query CloudTrail for ListBuckets with AWS CLI and jq with a focus on specific Username.
- Command to use:
aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=ListBuckets | jq -r '[.Events[]|select((.Username | startswith("i-"))) | {EventId,Username, CloudTrailEvent: (.CloudTrailEvent|fromjson)}]'
- Command to use:
- Query CloudTrail for ListBuckets within AWS CLI using JMESPath query.
- Command to use:
aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=ListBuckets --query 'Events[].{EventId:EventId,EventName:EventName,EventTime:EventTime,Username:Username}' --output table
- Command to use:
- Query CloudTrail for ListBuckets but filter based on a certain Username within query.
- Command to use:
aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=ListBuckets --query 'Events[?starts_with(Username, `i-`)==`true`].{EventId:EventId,EventName:EventName,EventTime:EventTime,Username:Username}' --output table
- Command to use:
- Query CloudTrail for ListBuckets but only those where AccessDenied.
- Command to use:
aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=ListBuckets | jq '.Events[]|select((.Username | startswith("i-")) and (.CloudTrailEvent|fromjson|select(.errorCode=="AccessDenied"))) '
- Command to use:
- Query CloudTrail for ListBuckets as the Event name within the GUI.
- Query CloudWatch LogInsights within the GUI.
- Query to use:
fields eventID, eventName, eventTime, userIdentity.sessionContext.sessionIssuer.userName as userName | sort @timestamp desc | filter eventName = "ListBuckets"
- Query to use:
- Query CloudWatch LogInsights via CLI.
- Command to use:
aws logs start-query --log-group-name [LogGroupName] --start-time [EpochTime] --end-time [EpochTime] --query-string "fields eventID, eventName, eventTime, userIdentity.sessionContext.sessionIssuer.userName as userName | sort @timestamp desc | filter eventName=\"ListBuckets\""
aws logs get-query-results --query-id [query-id]
- Command to use:
View CreateBucket Activity T1526
- Query CloudTrail for CreateBucket but filter based on certain username.
- Command to use:
aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=CreateBucket --max-results 10 --query 'Events[?starts_with(Username, `i-`)==`true`].{EventId:EventId,EventName:EventName,EventTime:EventTime,Username:Username}' --output table
- Command to use:
- Query CloudTrail for CreateBucket as the Event name within the GUI.
- Query CloudWatch LogInsights within the GUI.
- Query to use:
fields eventID, eventName, eventTime, userIdentity.sessionContext.sessionIssuer.userName as userName | sort @timestamp desc | filter eventName = "CreateBucket"
- Query to use:
- Query CloudWatch LogInsights via CLI.
- Command to use:
aws logs start-query --log-group-name [LogGroupName] --start-time [EpochTime] --end-time [EpochTime] --query-string "fields eventID, eventName, eventTime, userIdentity.sessionContext.sessionIssuer.userName as userName | sort @timestamp desc | filter eventName=\"CreateBucket\""
aws logs get-query-results --query-id [query-id]
- Command to use:
View DescribeInstances Activity T1526.
- Query CloudTrail for DescribeInstances events with AWS CLI.
- Command to use:
aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=DescribeInstances --query 'Events[].{EventId:EventId,EventName:EventName,EventTime:EventTime,Username:Username}' --output table
- Command to use:
- Query CloudTrail for DescribeInstances as the Event name within the GUI.
- Query CloudWatch LogInsights within the GUI.
- Query to use:
fields eventID, eventName, eventTime, userIdentity.sessionContext.sessionIssuer.userName as userName | sort @timestamp desc | filter eventName = "DescribeInstances"
- Query to use:
- Query CloudWatch LogInsights via CLI.
- Command to use:
aws logs start-query --log-group-name [LogGroupName] --start-time [EpochTime] --end-time [EpochTime] --query-string "fields eventID, eventName, eventTime, userIdentity.sessionContext.sessionIssuer.userName as userName | sort @timestamp desc | filter eventName=\"DescribeInstances\""
aws logs get-query-results --query-id [query-id]
- Command to use:
View StopLogging Activity T1562.008
- Query CloudTrail for StopLogging events.
- Command to use:
aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=StopLogging --query 'Events[].{EventId:EventId,EventName:EventName,EventTime:EventTime,Username:Username}' --output table
- Command to use:
- Query CloudTrail for StopLogging as the Event name within the GUI.
- Query CloudWatch LogInsights within the GUI.
- Query to use:
fields eventID, eventName, eventTime, userIdentity.sessionContext.sessionIssuer.userName as userName | sort @timestamp desc | filter eventName = "StopLogging"
- Query to use:
- Query CloudWatch LogInsights via CLI.
- Command to use:
aws logs start-query --log-group-name [LogGroupName] --start-time [EpochTime] --end-time [EpochTime] --query-string "fields eventID, eventName, eventTime, userIdentity.sessionContext.sessionIssuer.userName as userName | sort @timestamp desc | filter eventName=\"StopLogging\""
aws logs get-query-results --query-id [query-id]
- Command to use:
View DeleteTrail Activity T1562.008
- Query CloudTrail for DeleteTrail events.
- Command to use:
aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=DeleteTrail --query 'Events[].{EventId:EventId,EventName:EventName,EventTime:EventTime,Username:Username}' --output table
- Command to use:
- Query CloudTrail for DeleteTrail as the Event name within the GUI.
- Query CloudWatch LogInsights within the GUI.
- Query to use:
fields eventID, eventName, eventTime, userIdentity.sessionContext.sessionIssuer.userName as userName | sort @timestamp desc | filter eventName = "DeleteTrail"
- Query to use:
- Query CloudWatch LogInsights via CLI.
- Command to use:
aws logs start-query --log-group-name [LogGroupName] --start-time [EpochTime] --end-time [EpochTime] --query-string "fields eventID, eventName, eventTime, userIdentity.sessionContext.sessionIssuer.userName as userName | sort @timestamp desc | filter eventName=\"DeleteTrail\""
aws logs get-query-results --query-id [query-id]
- Command to use:
View UpdateTrail Activity T1562.008
- Query CloudTrail for UpdateTrail events.
- Command to use:
aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=UpdateTrail --query 'Events[].{EventId:EventId,EventName:EventName,EventTime:EventTime,Username:Username}' --output table
- Command to use:
- Query CloudTrail for UpdateTrail as the Event name within the GUI.
- Query CloudWatch LogInsights within the GUI.
- Query to use:
fields eventID, eventName, eventTime, userIdentity.sessionContext.sessionIssuer.userName as userName | sort @timestamp desc | filter eventName = "UpdateTrail"
- Query to use:
- Query CloudWatch LogInsights via CLI.
- Command to use:
aws logs start-query --log-group-name [LogGroupName] --start-time [EpochTime] --end-time [EpochTime] --query-string "fields eventID, eventName, eventTime, userIdentity.sessionContext.sessionIssuer.userName as userName | sort @timestamp desc | filter eventName=\"UpdateTrail\""
aws logs get-query-results --query-id [query-id]
- Command to use:
- Query AWS CloudTrail related to specific attacker KeyID.
- Command to use:
aws cloudtrail lookup-events --max-results 200 --lookup-attributes AttributeKey=AccessKeyId,AttributeValue=$KEY_ID | jq '[.Events[].EventName]| unique[]'
- Command to use:
- Query AWS CloudTrail with the KeyID as the AWS access key within the GUI.
View Deployed Containers T1610
- Query with kai to inventory containers within the environment.
- Query AWS Config GUI within the Resources section.
Detect Web Fuzzing T1190
- Query CloudWatch Log Insights for file or directory access.
- Command to run:
QUERY_ID=$(aws logs start-query --start-time $(date -d '-3 hours' "+%s") --end-time $(date "+%s") --query-string 'fields integrationErrorMessage | filter integrationErrorMessage ~= "No such file or directory" and sourceIp == "'[SuspectIPs]'"' --log-group-name [LogGroupName] --query 'queryId' --output text)
aws logs get-query-results --query-id $QUERY_ID
- Command to run:
Detect Container API Unsecured Credentials Access T1552.007
- Query CloudWatch Log Insights for access to a specific log stream and focus on the URI.
- Commands to run:
aws logs start-query --start-time $(date -d "30 mins ago" +"%s") --end-time $(date +"%s") --log-group-name $LOG_GROUP --query-string 'fields @message | filter @logStream ~= "kubernetes-dashboard"' --output text)
aws logs get-query-results --query-id $QUERY_ID | jq -r '.results[][] | select(.value | contains("aws-secrets"))'
- Commands to run:
- Query CloudWatch Log Insights via the GUI and a specific log group.
- Query to run:
fields integrationErrorMessage | filter integrationErrorMessage ~= "No such file or directory"
- Query to run:
- Use
s3logparse.py
found here.- Command to use is
s3logparse.py useragent [useragent]
.
- Command to use is
Detect SSH Brute Force T1110
- Query CloudWatch Log Insights via the GUI looking at VPC Flow Logs.
- Query to use:
filter dstPort=22 | stats count(*) as total by srcAddr as source | sort total desc | limit 10
- Query to use:
- Query CloudWatch Log Insights via CLI ;ooking at VPC Flow Logs.
- Commands to run:
aws logs start-query --log-group-name [LogGroupName] --start-time [EpochTime] --end-time [EpochTime] --query-string "filter dstPort=22 | stats count(*) as total by srcAddr as source | sort total desc | limit 10"
aws logs get-query-results --query-id [query-id]
- Commands to run:
- Query Athena within the GUI looking at VPC Flow Logs.
- Query to use:
SELECT sourceaddress, count(*) as total FROM vpc_flow_logs WHERE (destinationport = 22) group by distinct sourceaddress ORDER by total desc
- Query to use:
- Query Athena within the CLI looking at VPC Flow Logs.
- Commands to use:
QUERY_ID=$(aws athena start-query-execution --query-string "SELECT sourceaddress, count(*) as total FROM vpc_flow_logs WHERE (destinationport = 22) group by distinct sourceaddress ORDER by total desc" --query-execution-context Database=[DatabaseLogs] --work-group [WorkGroup] --query QueryExecutionId --output text)
aws athena get-query-results --query-execution-id $QUERY_ID --query ResultSet
- Commands to use:
- Use AWS GuardDuty in the GUI and look for
UnauthorizedAccess:EC2/SSHBruteForce
findings. - Use AWS GuardDuty via the CLI with the appropriate detector ID.
- Commands to run:
DETECTOR_ID=$(aws guardduty list-detectors --query DetectorIds[0] --output text)
aws guardduty list-findings --detector-id $DETECTOR_ID --finding-criteria '{"Criterion": {"type": {"Eq":["UnauthorizedAccess:EC2/SSHBruteForce"]}}}'
aws guardduty get-findings --detector-id $DETECTOR_ID --finding-ids $FINDING_IDS --query Findings[0]
- Commands to run:
Detect Non Standard Port Interactions T1571
- Query Athena within the GUI looking at VPC Flow Logs.
- Query to use:
SELECT destinationport, count(*) as total FROM vpc_flow_logs WHERE destinationport < 1024 AND action='ACCEPT' group by distinct destinationport ORDER by total ASC LIMIT 50
- Query to use:
- Query Athena within the CLI looking at VPC Flow Logs.
- Commands to use:
QUERY_ID=$(aws athena start-query-execution --query-string "SELECT destinationport, count(*) as total FROM vpc_flow_logs WHERE destinationport < 1024 AND action='ACCEPT' group by distinct destinationport ORDER by total ASC LIMIT 50" --query-execution-context Database=[DatabaseLogs] --work-group [WorkGroup] --query QueryExecutionId --output text)
aws athena get-query-results --query-execution-id $QUERY_ID --query ResultSet
- Commands to use:
- Query CloudWatch Log Insights via the GUI looking at VPC Flow Logs.
- Query to use:
filter dstPort < 1024 and action='ACCEPT' | stats count(*) as total by dstPort | sort total desc | limit 50
- Query to use:
- Query CloudWatch Log Insights via the CLI looking at VPC Flow Logs.
- Commands to use:
aws logs start-query --log-group-name [LogGroupName] --start-time [EpochTime] --end-time [EpochTime] --query-string "filter dstPort < 1024 and action='ACCEPT' | stats count(*) as total by dstPort | sort total desc | limit 50"
aws logs get-query-results --query-id [query-id]
- Commands to use:
- Query the security group of the asset and find the ports available.
- Commands to run:
SG_ID=$(aws ec2 describe-instances --filters Name=tag:Name,Values="SherlocksBlog" --query Reservations[].Instances[].SecurityGroups[0].GroupId --output text)
aws ec2 describe-security-groups --group-ids $SG_ID | jq '.SecurityGroups[].IpPermissions[] | {FromPort, ToPort, IpProtocol}'
- Commands to run:
- Review AWS Inspector Network Reachability results for the specific instance.
- Query Athena within the GUI looking at VPC Flow Logs.
- Query to use:
SELECT sourceaddress, destinationaddress, count(*) count, action FROM vpc_flow_logs WHERE action = 'REJECT' GROUP BY sourceaddress, destinationaddress, action ORDER BY count desc LIMIT 25
- Query to use:
- Query Athena within the CLI looking at VPC Flow Logs.
- Commands to use:
QUERY_ID=$(aws athena start-query-execution --query-string "SELECT sourceaddress, destinationaddress, count(*) count, action FROM vpc_flow_logs WHERE action = 'REJECT' GROUP BY sourceaddress, destinationaddress, action ORDER BY count desc LIMIT 25" --query-execution-context Database=[DatabaseLogs] --work-group [WorkGroup] --query QueryExecutionId --output text)
aws athena get-query-results --query-execution-id $QUERY_ID --query ResultSet
- Commands to use:
- Query CloudWatch Log Insights within the GUI looking at VPC Flow Logs.
- Query to use:
filter action='REJECT' | stats count(*) by srcAddr, dstAddr | display srcAddr, dstAddr | limit 25
- Query to use:
- Query CloudWatch Insights within the CLI looking at VPC Flow Logs.
- Commands to use:
aws logs start-query --log-group-name [LogGroupName] --start-time [EpochTime] --end-time [EpochTime] --query-string "filter action='REJECT' | stats count(*) by srcAddr, dstAddr | display srcAddr, dstAddr | limit 25"
aws logs get-query-results --query-id [query-id]
- Commands to use:
- Query CloudWatch log stream directly for events from log.
- Command to use:
aws logs get-log-events --log-group-name [LogGroup] --log-stream [LogStream]
- Command to use:
- Query CloudWatch Log Insights for web scanning activity within logs.
- Commands to use:
aws logs start-query --start-time $(expr $(date +"%s") - 86400) --end-time $(date +"%s") --log-group-name [LogGroupName] \ --query-string 'display @message' \ --output text)
aws logs get-query-results --query-id $QUERY_ID | jq -r \ '.results[][] | select(.field == "@message") | .value'
- Commands to use:
- Query Athena within the GUI looking at VPC Flow Logs.
- Query to use:
SELECT sourceaddress, destinationaddress, count(*) count, action FROM vpc_flow_logs WHERE action = 'REJECT' AND sourceaddress LIKE '10.0.%' GROUP BY sourceaddress, destinationaddress, action ORDER BY count desc LIMIT 25
- Query to use:
- Query Athena within the CLI looking at VPC Flow Logs.
- Commands to use:
QUERY_ID=$(aws athena start-query-execution --query-string "SELECT sourceaddress, destinationaddress, count(*) count, action FROM vpc_flow_logs WHERE action = 'REJECT' AND sourceaddress LIKE '10.0.%' GROUP BY sourceaddress, destinationaddress, action ORDER BY count desc LIMIT 25" --query-execution-context Database=[DatabaseLogs] --work-group [WorkGroup] --query QueryExecutionId --output text)
aws athena get-query-results --query-execution-id $QUERY_ID --query ResultSet
- Commands to use:
- Query CloudWatch Log Insights within the GUI looking at VPC Flow Logs.
- Query to use:
filter action='REJECT' and strcontains(srcAddr, "10.0.") | stats count(*) by srcAddr, dstAddr, action | display srcAddr, dstAddr, action | limit 25
- Query to use:
- Query CloudWatch Insights within the CLI looking at VPC Flow Logs.
- Commands to use:
aws logs start-query --log-group-name [LogGroupName] --start-time [EpochTime] --end-time [EpochTime] --query-string "filter action='REJECT' and strcontains(srcAddr, "10.0.") | stats count(*) by srcAddr, dstAddr, action | display srcAddr, dstAddr, action| limit 25"
aws logs get-query-results --query-id [query-id]
- Commands to use:
- Query Athena within the GUI looking at VPC Flow Logs.
- Query to use:
SELECT ip, sum(bytes) as total_bytes FROM (SELECT destinationaddress as ip,sum(numbytes) as bytes FROM vpc_flow_logs GROUP BY 1 UNION ALL SELECT sourceaddress as ip,sum(numbytes) as bytes FROM vpc_flow_logs GROUP BY 1) GROUP BY ip ORDER BY total_bytes DESC LIMIT 10
- Query to use:
- Query Athena within the CLI looking at VPC Flow Logs.
- Commands to use:
QUERY_ID=$(aws athena start-query-execution --query-string "SELECT ip, sum(bytes) as total_bytes FROM (SELECT destinationaddress as ip,sum(numbytes) as bytes FROM vpc_flow_logs GROUP BY 1 UNION ALL SELECT sourceaddress as ip,sum(numbytes) as bytes FROM vpc_flow_logs GROUP BY 1) GROUP BY ip ORDER BY total_bytes DESC LIMIT 10" --query-execution-context Database=[DatabaseLogs] --work-group [WorkGroup] --query QueryExecutionId --output text)
aws athena get-query-results --query-execution-id $QUERY_ID --query ResultSet
- Commands to use:
View Deployed Containers T1610
- Query CloudWatch Log Insights with the container log stream/group of application logs.
- Commands to run:
aws logs start-query --log-group-name [LogGroupContainer] --start-time $(date -d '1 hour ago' +"%s") --end-time $(date +"%s") --query-string 'fields log | filter kubernetes.container_name == "[ContainerName]" and log ~= "Incoming HTTP" and log ~= "appdeploymentfromfile"' --output text)
aws logs get-query-results --query-id $QUERY_ID
- Commands to run:
- Query CloudWatch Log Insights within the GUI with the correct log group of application logs.
- Query to use:
fields log | filter kubernetes.container_name == "kubernetes-dashboard" and log ~= "Incoming HTTP" and log ~= "appdeploymentfromfile"
- Query to use:
Detect Access EC2 Metadata Service Vulnerability T1552.005
- Use AWS Inspector results to view IMDSv2, not Version 1 interactions.
Identify Suspicious Cloud Accounts T1078.004
- Query the Azure Log Analytics Workspace via the GUI with the BehaviorAnalytics table.
- Query to run:
BehaviorAnalytics | where ActivityInsights.CountryUncommonlyConnectedFromAmongPeers == True | project TimeGenerated, ActivityType, UserName, SourceIPAddress, ActivityInsights
- Query to run:
- Query the Azure Log Analytics Workspace via the CLI with the BehaviorAnalytics table.
- Commands to run:
WORKSPACE_GUID=$(az monitor log-analytics workspace show --resource-group [RsourceGroup] --workspace-name [WorkspaceName] --query 'customerId' --output tsv)
az monitor log-analytics query --workspace $WORKSPACE_GUID --analytics-query 'BehaviorAnalytics | where ActivityInsights.CountryUncommonlyConnectedFromAmongPeers == True | project TimeGenerated, ActivityType, UserName, SourceIPAddress, ActivityInsights'
- Commands to run:
- Query the Azure CLI.
- Command to run:
az role assignment list --all --query '[].{UPN:principalName,RoleDef:roleDefinitionName,Scope:scope}' --output table
- Command to run:
Identify User Groups T1078.002
- View information within Azure AD Users within the Portal GUI.
- View changes of AD within AuditLogs of the Azure Log Analytics Workspace.
Identify Spam Messages T1566
- View spam filtering within the Microsoft 365 Admin Center.
- Query Microsoft Defender for Cloud with Qualys for vulnerability's.
- Query Azure Log Analytics Workspace within the
SecurityBaseline
table. - Use the Microsoft Defender CLI with
az security alert list
.
- Query Microsoft Defender for Cloud with Qualys with Container Image Scanning capability.
- Use the Microsoft Defender CLI with
az security alert list
.
- Query the Azure Log Analytics Workspace via the GUI.
- Query to run:
StorageBlobLogs | where OperationName =="GetBlob" | project TimeGenerated,AccountName,CallerIpAddress, Uri
- Query to run:
- Query the Azure Log Analytics Workspace via the CLI.
- Commands to run:
WORKSPACE_GUID=$(az monitor log-analytics workspace show --resource-group [RsourceGroup] --workspace-name [WorkspaceName] --query 'customerId' --output tsv)
az monitor log-analytics query --workspace $WORKSPACE_GUID --analytics-query 'StorageBlobLogs | where OperationName =="GetBlob" | project TimeGenerated,AccountName,CallerIpAddress, Uri'
- Commands to run:
- Query for other log sources within Azure Log Analytics Workspace to include:
StorageFileLogs
,StorageTableLogs
, andStorageQueueLogs
.
- Query the Azure Log Analytics Workspace via the GUI.
- Query to run:
StorageFileLogs | where OperationName =="CreateFile" | project TimeGenerated,CallerIpAddress, Uri
- Query to run:
- Query the Azure Log Analytics Workspace via the CLI.
- Commands to run:
WORKSPACE_GUID=$(az monitor log-analytics workspace show --resource-group [RsourceGroup] --workspace-name [WorkspaceName] --query 'customerId' --output tsv)
az monitor log-analytics query --workspace $WORKSPACE_GUID --analytics-query 'StorageFileLogs | where OperationName =="CreateFile" | project TimeGenerated,CallerIpAddress, Uri'
- Commands to run:
View Deployed Containers T1610
- Query the Azure Log Analytics Workspace with the specific table.
- Query to run:
ContainerInstanceLog_CL | project TimeGenerated, ContainerGroup_s, Message
- Query to run:
- Query the Azure Log Analytics Workspace for the following tables:
ContainerInventory
,ContainerNodeInventory
,InsightsMetricss
,KubeEvents
,KubeMonAgentEvents
,KubeNodeInventory
,KubeServices
, orContainerLog
.
Identify Cloud Instance Creation T1578.002
- Review alerts within Azure Activity Log GUI for "Microsoft.Compute/virtualMachines/create" operations.
- Query the Azure Log Analytics GUI for VM creation.
Identify Cloud Instance Deletion T1578.003
- Review alerts within Azure Activity Log GUI for "Microsoft.Compute/virtualMachines/delete" operations.
- Query Azure Activity Log for delete operations.
- Command to run:
az monitor activity-log list --offset 1h --query "[?authorization.action=='Microsoft.Compute/virtualMachines/delete’].{Time:eventTimestamp,Caller:caller,SourceIP:claims.ipaddr}" --output table
- Command to run:
- Query Azure Log Analytics GUI for VM deletion.
- Query to run:
AzureActivity | extend Action= extractjson("$.action", Authorization) | where Action == "Microsoft.Compute/virtualMachines/delete" | project TimeGenerated, Action, Caller, CallerIpAddress | sort by TimeGenerated desc
- Query to run:
- Query Azure Log Analytics via the CLI for VM deletion.
- Commands to run:
WORKSPACE_GUID=$(az monitor log-analytics workspace show --resource-group [RsourceGroup] --workspace-name [WorkspaceName] --query 'customerId' --output tsv)
az monitor log-analytics query --workspace $WORKSPACE_GUID --analytics-query 'AzureActivity | extend Action= extractjson("$.action", Authorization) | where Action == "Microsoft.Compute/virtualMachines/delete" | project TimeGenerated, Action, Caller, CallerIpAddress | sort by TimeGenerated desc'
- Commands to run:
Identify Cloud Instance Updates T1578
- Review alerts within Azure Activity Log GUI for instance updates.
- Query the Azure Log Analytics GUI for VM updates.
Identify Reverse Shell Activity T1059
- Query the Log Analytics Workspace for SecurityAlert.
- Query to run:
SecurityAlert | where TimeGenerated between(datetime("8/9/2023 00:00:00")..datetime("8/10/2023 00:00:00")) | where DisplayName == "Possible reverse shell" | take 1 | extend FilePath = extract_json("$.File Path", ExtendedProperties) | extend FileName = extract_json("$.File Name", ExtendedProperties) | extend FileHash = extract_json("$.File Sha256", ExtendedProperties) | extend UserName = extract_json("$.User Name", ExtendedProperties) | extend MachineName = extract_json("$.Machine Name", ExtendedProperties) | project TimeGenerated, FilePath, FileName, FileHash, UserName, MachineName
- Query to run:
- Query the Log Analytics Workspace via the CLI.
- Commands to run:
WORKSPACE_GUID=$(az monitor log-analytics workspace show --resource-group [RsourceGroup] --workspace-name [WorkspaceName] --query 'customerId' --output tsv)
az monitor log-analytics query --workspace $WORKSPACE_GUID --analytics-query 'SecurityAlert | where TimeGenerated between(datetime("8/9/2023 00:00:00")..datetime("8/10/2023 00:00:00")) | where DisplayName == "Possible reverse shell" | take 1 | extend FilePath = extract_json("$.File Path", ExtendedProperties) | extend FileName = extract_json("$.File Name", ExtendedProperties) | extend FileHash = extract_json("$.File Sha256", ExtendedProperties) | extend UserName = extract_json("$.User Name", ExtendedProperties) | extend MachineName = extract_json("$.Machine Name", ExtendedProperties) | project TimeGenerated, FilePath, FileName, FileHash, UserName, MachineName'
- Commands to run:
- Review alerts in Microsoft Defender for Cloud in the GUI.
- Use the Microsoft Defender CLI with
az security alert list
.
Identify Data Exfiltration T1530
- Query the Log Analytics Workspace in the GUI for StorageBlobLogs.
- Query to run:
StorageBlobLogs | where TimeGenerated between(datetime("8/9/2023 00:00:00")..datetime("8/10/2023 00:00:00"))
- Query to run:
- Query the Log Analytics Workspace through the CLI.
- Commands to run:
WORKSPACE_GUID=$(az monitor log-analytics workspace show --resource-group [RsourceGroup] --workspace-name [WorkspaceName] --query 'customerId' --output tsv)
az monitor log-analytics query --workspace $WORKSPACE_GUID --analytics-query 'StorageBlobLogs | where TimeGenerated between(datetime("8/9/2023 00:00:00")..datetime("8/10/2023 00:00:00"))'
- Commands to run:
- Query the Log Analytics Workspace in the GUI for StorageBlobLogs.
- Query to run:
StorageBlobLogs | where TimeGenerated between(datetime("8/9/2023 00:00:00")..datetime("8/10/2023 00:00:00")) | extend SourceIP = splitCallerIpAddress,":")[0] | summarize dataOut = sum(ResponseBodySize) by tostring(SourceIP), OperationName | sort by dataOut
- Query to run:
- Query the Log Analytics Workspace through the CLI.
- Commands to run:
WORKSPACE_GUID=$(az monitor log-analytics workspace show --resource-group [RsourceGroup] --workspace-name [WorkspaceName] --query 'customerId' --output tsv)
az monitor log-analytics query --workspace $WORKSPACE_GUID --analytics-query 'StorageBlobLogs | where TimeGenerated between(datetime("8/9/2023 00:00:00")..datetime("8/10/2023 00:00:00")) | extend SourceIP = split(CallerIpAddress,":")[0] | summarize dataOut = sum(ResponseBodySize) by tostring(SourceIP), OperationName | sort by dataOut'
- Commands to run:
Identify Data Staging T1074.002
- Query the Log Analytics Workspace in the GUI for StorageBlobLogs.
- Query to run:
StorageBlobLogs | where TimeGenerated between(datetime("8/9/2023 00:00:00")..datetime("8/10/2023 00:00:00")) | extend SourceIP = split(CallerIpAddress,":")[0] | summarize dataOut = sum(ResponseBodySize) by tostring(SourceIP), OperationName | sort by dataOut
- Query to run:
- Query the Log Analytics Workspace through the CLI.
- Commands to run:
WORKSPACE_GUID=$(az monitor log-analytics workspace show --resource-group [RsourceGroup] --workspace-name [WorkspaceName] --query 'customerId' --output tsv)
az monitor log-analytics query --workspace $WORKSPACE_GUID --analytics-query 'StorageBlobLogs | where TimeGenerated between(datetime("8/9/2023 00:00:00")..datetime("8/10/2023 00:00:00")) | extend SourceIP = split(CallerIpAddress,":")[0] | summarize dataIn = sum(ResponseBodySize) by tostring(SourceIP), OperationName | sort by dataIn'
- Commands to run:
Detect Command Execution T1059
- Query the Log Analytics Workspace in the GUI for AzureActivity.
- Query to run:
AzureActivity | where TimeGenerated between(datetime("8/9/2023 00:00:00")..datetime("8/10/2023 00:00:00")) | project TimeGenerated, OperationNameValue, Level, Caller
- Query to run:
- Query the Log Analytics Workspace through the CLI.
- Commands to run:
WORKSPACE_GUID=$(az monitor log-analytics workspace show --resource-group [RsourceGroup] --workspace-name [WorkspaceName] --query 'customerId' --output tsv)
az monitor log-analytics query --workspace $WORKSPACE_GUID --analytics-query 'AzureActivity | where TimeGenerated between(datetime("8/9/2023 00:00:00")..datetime("8/10/2023 00:00:00")) | project TimeGenerated, OperationNameValue, Level, Caller'
- Commands to run:
Detect Managed Identity Usage T1552.005
- Query the Log Analytics Workspace through the CLI and the AADManagedIdentitySignInLogs table and match ServicePrincipalId with the user identities.
- Commands to run:
WORKSPACE_GUID=$(az monitor log-analytics workspace show --resource-group [RsourceGroup] --workspace-name [WorkspaceName] --query 'customerId' --output tsv)
az monitor log-analytics query --workspace $WORKSPACE_GUID --analytics-query 'AADManagedIdentitySignInLogs | where TimeGenerated between(datetime("8/9/2023 00:00:00")..datetime("8/10/2023 00:00:00"))'
az monitor log-analytics query --workspace $WORKSPACE_GUID --analytics-query 'AzureActivity | where TimeGenerated between(datetime("8/9/2023 00:00:00")..datetime("8/10/2023 00:00:00")) and Caller == [UserID]'
- Commands to run:
- Query the Log Analytics Workspace within the GUI.
- Queries to run:
AADManagedIdentitySignInLogs | where TimeGenerated between(datetime("8/9/2023 00:00:00")..datetime("8/10/2023 00:00:00"))
AzureActivity | where TimeGenerated between(datetime("8/9/2023 00:00:00")..datetime("8/10/2023 00:00:00")) and Caller == [UserID]
- Queries to run:
Detect SSH Brute Force T1110
- Review alerts for "Failed SSH brute force attack" within Microsoft Defender for Cloud alerts.
- Review alerts for "SSH - Potential Brute Force" in Microsoft Sentinel.
- Use Azure Network Watcher Packet Capture capability.
- Query Azure Log Analytics Workspace with the configured authentication log from
/var/log/secure
sent via the agent.- Query to run:
LinuxAuth_CL | where RawData contains "Failed password" or RawData contains "Invalid user" | project TimeGenerated, RawData
- Query to run:
- View Sign-in logs from Azure Active Directory within the web GUI.
- Use the Microsoft Defender CLI with
az security alert list
. - Query Log Analytics Workspace in the GUI with the SecurityAlert table.
- Query to run:
SecurityAlert | where Tactics == "CredentialAccess" | extend MaliciousIP = split(split(tostring(Entities),"Address")[1],'"')[2] | project TimeGenerated, DisplayName, MaliciousIP | sort by TimeGenerated asc
- Query to run:
- Query Log Analytics Workspace within the CLI with the SecurityAlert table.
- Commands to run:
WORKSPACE_GUID=$(az monitor log-analytics workspace show --resource-group [RsourceGroup] --workspace-name [WorkspaceName] --query 'customerId' --output tsv)
az monitor log-analytics query --workspace $WORKSPACE_GUID --analytics-query 'SecurityAlert | where Tactics == "CredentialAccess" | extend MaliciousIP = split(split(tostring(Entities),"Address")[1],'"')[2] | project TimeGenerated, DisplayName, MaliciousIP | sort by TimeGenerated asc'
- Commands to run:
- Query the Log Analytics Workspace in the GUI for all successful logins.
- Command to run:
SigninLogs | extend AuthenticationMethod = extractjson("$.[0].authenticationMethod", AuthenticationDetails) | extend Succeeded = extractjson("$.[0].succeeded", AuthenticationDetails) | project TimeGenerated, AuthenticationMethod, Succeeded, IPAddress, UserAgent
- Command to run:
- Query the Log Analytics Workspace through the CLI.
- Commands to run:
WORKSPACE_GUID=$(az monitor log-analytics workspace show --resource-group [RsourceGroup] --workspace-name [WorkspaceName] --query 'customerId' --output tsv)
az monitor log-analytics query --workspace $WORKSPACE_GUID --analytics-query 'SigninLogs | extend AuthenticationMethod = extractjson("$.[0].authenticationMethod", AuthenticationDetails) | extend Succeeded = extractjson("$.[0].succeeded", AuthenticationDetails) | project TimeGenerated, AuthenticationMethod, Succeeded, IPAddress, UserAgent'
- Commands to run:
- Use Azure Network Watcher Packet Capture capability.
- Query Azure Log Analytics Workspace with the configured authentication log from
/var/log/secure
sent via the agent.- Query to run:
LinuxAuth_CL | project TimeGenerated, RawData
- Query to run:
- View Risky sign-ins from Azure Active Directory.
- View Sign-in logs from Azure Active Directory within the web GUI.
Detect Failed Password Attempts T1110.001
- Query the Log Analytics Workspace in the GUI for failed login attempts with a password.
- Query to run:
SigninLogs | extend AuthenticationMethod = extractjson("$.[0].authenticationMethod", AuthenticationDetails) | extend Succeeded = extractjson("$.[0].succeeded", AuthenticationDetails) | where Succeeded == "false" and AuthenticationMethod == "Password" | project TimeGenerated, AuthenticationMethod, Succeeded, IPAddress, UserAgent
- Query to run:
- Query the Log Analytics Workspace in the GUI for multiple failed logon attempts.
- Query to run:
SigninLogs | where TimeGenerated between(datetime("8/9/2023 00:00:00")..datetime("8/10/2023 00:00:00")) | extend AuthenticationMethod = extractjson("$.[0].authenticationMethod", AuthenticationDetails) | extend Succeeded = extractjson("$.[0].succeeded", AuthenticationDetails) | where Succeeded == "false" and AuthenticationMethod == "Password" | summarize count() by IPAddress
- Query to run:
- Query the Log Analytics Workspace through the CLI.
- Commands to run:
WORKSPACE_GUID=$(az monitor log-analytics workspace show --resource-group [RsourceGroup] --workspace-name [WorkspaceName] --query 'customerId' --output tsv)
az monitor log-analytics query --workspace $WORKSPACE_GUID --analytics-query 'SigninLogs | where TimeGenerated between(datetime("8/9/2023 00:00:00")..datetime("8/10/2023 00:00:00")) | extend AuthenticationMethod = extractjson("$.[0].authenticationMethod", AuthenticationDetails) | extend Succeeded = extractjson("$.[0].succeeded", AuthenticationDetails) | where Succeeded == "false" and AuthenticationMethod == "Password" | summarize count() by IPAddress'
- Commands to run:
- Review alerts within Microsoft Sentinel for "Password spray attack against Azure AD application."
- Use Azure Network Watcher Packet Capture capability.
- Query Azure Log Analytics Workspace with the configured authentication log from
/var/log/secure
sent via the agent.- Query to run:
LinuxAuth_CL | where RawData contains "Failed password" or RawData contains "Invalid user" | project TimeGenerated, RawData
- Query to run:
- View Sign-in logs from Azure Active Directory within the web GUI.
- Query Log Analytics Workspace in the GUI with the SecurityAlert table.
- Query to run:
SecurityAlert | where Tactics == "CredentialAccess" | extend MaliciousIP = split(split(tostring(Entities),"Address")[1],'"')[2] | project TimeGenerated, DisplayName, MaliciousIP | sort by TimeGenerated asc
- Query to run:
- Query Log Analytics Workspace within the CLI with the SecurityAlert table.
- Commands to run:
WORKSPACE_GUID=$(az monitor log-analytics workspace show --resource-group [RsourceGroup] --workspace-name [WorkspaceName] --query 'customerId' --output tsv)
az monitor log-analytics query --workspace $WORKSPACE_GUID --analytics-query 'SecurityAlert | where Tactics == "CredentialAccess" | extend MaliciousIP = split(split(tostring(Entities),"Address")[1],'"')[2] | project TimeGenerated, DisplayName, MaliciousIP | sort by TimeGenerated asc'
- Commands to run:
Identify Network Scanning T1046
- Query Log Analytics Workspace in the GUI with the AzureNetworkAnalytics_CL.
- Query to run:
AzureNetworkAnalytics_CL | where FlowStartTime_t between(datetime("8/9/2023 00:00:00")..datetime("8/10/2023 00:00:00")) | summarize Count = count() by PublicIPs_s
- Query to run:
- Query Log Analytics Workspace within the CLI.
- Commands to run:
WORKSPACE_GUID=$(az monitor log-analytics workspace show --resource-group [RsourceGroup] --workspace-name [WorkspaceName] --query 'customerId' --output tsv)
az monitor log-analytics query --workspace $WORKSPACE_GUID --analytics-query 'AzureNetworkAnalytics_CL | where FlowStartTime_t between(datetime("8/9/2023 00:00:00")..datetime("8/10/2023 00:00:00")) | summarize Count = count() by PublicIPs_s'
- Commands to run:
- Use Azure Network Watcher Packet Capture capability.
- Query Log Analytics Workspace in the GUI with the AzureNetworkAnalytics_CL focusing on ingress traffic from specific IP.
- Query to run:
AzureNetworkAnalytics_CL | where TimeGenerated between(datetime("8/9/2023 00:00:00")..datetime("8/10/2023 00:00:00")) and PublicIPs_s contains "40.70.212.199" and FlowDirection_s == "I" and FlowStatus_s == "A" | distinct L7Protocol_s, L4Protocol_s, DestPort_d
- Query to run:
- Query Log Analytics Workspace within the CLI with the AzureNetworkAnalytics_CL focusing on ingress traffic from specific IP.
- Commands to run:
WORKSPACE_GUID=$(az monitor log-analytics workspace show --resource-group [RsourceGroup] --workspace-name [WorkspaceName] --query 'customerId' --output tsv)
az monitor log-analytics query --workspace $WORKSPACE_GUID --analytics-query 'AzureNetworkAnalytics_CL | where TimeGenerated between(datetime("8/9/2023 00:00:00")..datetime("8/10/2023 00:00:00")) and PublicIPs_s contains "40.70.212.199" and FlowDirection_s == "I" and FlowStatus_s == "A" | distinct L7Protocol_s, L4Protocol_s, DestPort_d'
- Commands to run:
- Query Log Analytics Workspace in the GUI with the AzureNetworkAnalytics_CL focusing on egress traffic.
- Query to run:
AzureNetworkAnalytics_CL | where TimeGenerated between(datetime("8/9/2023 00:00:00")..datetime("8/10/2023 00:00:00")) and PublicIPs_s contains "40.70.212.199" and FlowDirection_s == "O" and FlowStatus_s == "A" | distinct L7Protocol_s, L4Protocol_s, DestPort_d
- Query to run:
- Query Log Analytics Workspace within the CLI with the AzureNetworkAnalytics_CL focusing on egress traffic.
- Commands to run:
WORKSPACE_GUID=$(az monitor log-analytics workspace show --resource-group [RsourceGroup] --workspace-name [WorkspaceName] --query 'customerId' --output tsv)
az monitor log-analytics query --workspace $WORKSPACE_GUID --analytics-query 'AzureNetworkAnalytics_CL | where TimeGenerated between(datetime("8/9/2023 00:00:00")..datetime("8/10/2023 00:00:00")) and PublicIPs_s contains "40.70.212.199" and FlowDirection_s == "O" and FlowStatus_s == "A" | distinct L7Protocol_s, L4Protocol_s, DestPort_d'
- Commands to run:
- Use Azure Network Watcher Packet Capture capability.
Identify Suspicious Email Traffic T1566
- View Mail Flow within the Microsoft 365 Exchange Admin Center.
Identify Database Scanning T1190
- Query Log Analytics Workspace in the GUI with the AzureDiagnostics table.
- Query to run:
AzureDiagnostics | where TimeGenerated between(datetime("10/29/2021 2:45 PM").. datetime("10/29/2021 3:00 PM")) and Category == "SQLSecurityAuditEvents" and action_id_s == "BCM " | extend statementLength = strlen(statement_s) | sort by statementLength | project client_ip_s, statementLength, statement_s
- Query to run:
- Query Log Analytics Workspace within the CLI with the AzureDiagnostics table.
- Commands to run:
WORKSPACE_GUID=$(az monitor log-analytics workspace show --resource-group [RsourceGroup] --workspace-name [WorkspaceName] --query 'customerId' --output tsv)
az monitor log-analytics query --workspace $WORKSPACE_GUID --analytics-query 'AzureDiagnostics | where TimeGenerated between(datetime("10/29/2021 2:45 PM").. datetime("10/29/2021 3:00 PM")) and Category == "SQLSecurityAuditEvents" and action_id_s == "BCM " | extend statementLength = strlen(statement_s) | sort by statementLength | project client_ip_s, statementLength, statement_s'
- Commands to run:
Identify C2 Traffic T1571
- Query Log Analytics Workspace in the GUI with the AzureNetworkAnalytics_CL table.
- Query to run:
AzureNetworkAnalytics_CL | where TimeGenerated between(datetime("9/27/2021 00:00:00") ..datetime("9/27/2021 23:59:59")) and PublicIPs_s contains "3.95.15.41" and FlowDirection_s == "O" and DestPort_d == 443 and L4Protocol_s == "T" | summarize Count = count() by bin(FlowStartTime_t, 1m) | project Count, FlowStartTime_t | render columnchart
- Query to run:
- Query Log Analytics Workspace within the CLI with the AzureNetworkAnalytics_CL table.
- Commands to run:
WORKSPACE_GUID=$(az monitor log-analytics workspace show --resource-group [RsourceGroup] --workspace-name [WorkspaceName] --query 'customerId' --output tsv)
az monitor log-analytics query --workspace $WORKSPACE_GUID --analytics-query 'AzureNetworkAnalytics_CL | where TimeGenerated between(datetime("9/27/2021 00:00:00") ..datetime("9/27/2021 23:59:59")) and PublicIPs_s contains "3.95.15.41" and FlowDirection_s == "O" and DestPort_d == 443 and L4Protocol_s == "T" | summarize Count = count() by bin(FlowStartTime_t, 1m) | project Count, FlowStartTime_t | render columnchart'
- Commands to run: