Join our Newsletter — 33% off our NHI Course
Home› Guides› How to Detect aws access key use from…
Guide SOC & Detection Engineering

How to Detect aws access key use from unusual locations: Baselines, Alerts and IP Guardrails

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 11 November 2026 16 min read
On this page

A stolen AWS access key works from anywhere on the internet, so the first sign of theft is usually the same key calling AWS from a network it has never used before. Long-term IAM user keys (the ones beginning AKIA) are typically used by a small, stable set of hosts: a CI runner, an on-premises server, a vendor integration. That stability is a detection opportunity, because every CloudTrail record carries the caller's sourceIPAddress and userAgent. This guide shows how to turn that into working detection: which built-in signals AWS gives you and what they miss, how to build a per-key baseline in Athena, which rules to alert on, and how to add an IP guardrail so an unusual location is blocked rather than only reported. It is written for cloud security engineers and detection engineers. Scoping a confirmed compromise is covered in How to Investigate CloudTrail for a Compromised Access Key, and replacing the key in How to rotate an AWS IAM access key without downtime.

This is an independent guide from NHI Mgmt Group, based on AWS's public CloudTrail, IAM and GuardDuty documentation as of November 2026. It is not sponsored or reviewed by AWS. Product features change, so confirm settings against AWS's current documentation.

Key takeaways

  • Location means network origin, not just country. For a machine key the useful questions are: is this IP in the known egress range, is the network owner (ASN) new, and is it a cloud or hosting range the key has never used. Country is a weak signal on its own.
  • GuardDuty covers part of the problem. Its IAM findings flag Tor exit nodes, known malicious IPs, pentest distributions and anomalous API use, and the InstanceCredentialExfiltration and ResourceCredentialExfiltration findings catch role credentials used outside their home. It does not alert simply because an IAM user key appeared on a new, clean IP.
  • Your own baseline fills the gap. A per-key list of observed sourceIPAddress, ASN and userAgent values from 30 to 90 days of CloudTrail makes "first seen" rules cheap and precise for keys with fixed origins.
  • Follow the children. An attacker with an AKIA key often calls AssumeRole or GetSessionToken and works with the resulting ASIA credentials, so baseline and alert on the sessions a key creates, not only the key itself.
  • Prevent where origins are fixed. An identity policy that denies requests when aws:SourceIp is outside your egress ranges turns a stolen key into a stream of AccessDenied events, which are themselves a high-quality alert.

When you need this

Use this guide when you still run long-term IAM user access keys and cannot remove them yet, for example for on-premises systems, third-party SaaS integrations that only accept a key pair, or legacy tooling. The better end state for most workloads is no long-term key at all: roles for compute in AWS, IAM Roles Anywhere for on-premises servers with certificates, and OIDC federation for CI. See the AWS Access Keys Security Guide for that migration. Until then, unusual-location detection is one of the few signals that separates the legitimate holder of a key from someone who copied it out of a repository, a .env file or a build log.

The technique being detected is use of valid cloud credentials, MITRE ATT&CK T1078.004 Valid Accounts: Cloud Accounts, usually after collection through T1552.001 Credentials In Files or T1552.005 Cloud Instance Metadata API. Attackers who expect location checks route through proxies, Tor or cloud hosts (T1090.003 Multi-hop Proxy), which is why the network owner matters as much as the country.

Signals AWS gives you, and what they miss

SignalWhat it catchesWhat it misses
GuardDuty UnauthorizedAccess:IAMUser/TorIPCaller and Recon:IAMUser/TorIPCallerAny API call (or list and describe calls for the Recon variant) from a Tor exit nodeResidential proxies, VPNs and rented cloud hosts
GuardDuty UnauthorizedAccess:IAMUser/MaliciousIPCaller and .CustomCalls from IPs on AWS threat intelligence lists, or on a threat list you uploadClean IPs; these findings use reputation lists, not machine learning
GuardDuty *:IAMUser/AnomalousBehavior (Discovery, Persistence, Exfiltration and others)Sensitive APIs invoked in an anomalous way; AWS says the model tracks the user, the location the request came from and the APIUse of routine APIs from a new location; a finding needs an anomalous API pattern, not only a new IP
GuardDuty CredentialAccess:IAMUser/CompromisedCredentialsA key Amazon threat intelligence identifies as potentially compromisedKeys that leaked somewhere AWS has not seen
GuardDuty InstanceCredentialExfiltration.OutsideAWS / .InsideAWS and ResourceCredentialExfiltrationEC2 role credentials, or ECS task and Lambda credentials, used from an external IP or another AWS accountIAM user keys (AKIA); these findings are for role credentials of compute
GuardDuty UnauthorizedAccess:IAMUser/ConsoleLoginSuccess.BSuccessful console logins for one user from several geographic locations around the same timeProgrammatic key use; this finding is for console sign-in
CloudTrail InsightsUnusual API call rates and API error rates against a learned baselineLocation; Insights does not look at where calls come from
IAM GetAccessKeyLastUsedLast used date, service and Region per keyThe IP address; useful for inventory, not for location detection

The gap is clear: a key used from a clean, never-seen IP to call ordinary APIs can pass every built-in control. That is the case your own baseline rules cover. See the Amazon GuardDuty Guide for enabling GuardDuty across an organisation.

Before you start

  • Organisation trail: an AWS Organizations trail covering all Regions and all accounts, delivering to a central log archive bucket. IAM and global STS calls are recorded in us-east-1, so a trail that skips that Region misses key creation events. See the AWS CloudTrail Guide.
  • Data events where it matters: management events show ListBuckets or GetCallerIdentity, but GetObject on sensitive buckets only appears if S3 data events are enabled for them.
  • A query engine: an Athena table over the trail bucket (created from the CloudTrail console) or the same data in your SIEM. The examples below use Athena column names (useridentity.accesskeyid, sourceipaddress, useragent).
  • IP enrichment: a GeoIP and ASN data source in the SIEM, and AWS's published ip-ranges.json so you can label addresses that belong to AWS itself.
  • A key register: every active AKIA key, its IAM user, owner, the system that uses it and the networks it should come from. Keys with no owner are a finding in their own right; see How to find unused AWS IAM roles and access keys.

Step-by-step: build the detection

Step 1: Classify each key by its expected origin

Put every long-term key into one of three classes. Fixed origin: the key is used only from known egress IPs (a data centre NAT range, a fixed CI runner pool, a vendor that publishes its egress list). AWS-hosted origin: the key is used from inside AWS, ideally through a VPC endpoint (and should really be a role). Variable origin: a human developer key used from home and travel networks. Fixed-origin keys get strict allow-list rules and a guardrail policy; variable-origin keys get softer anomaly rules and a plan to replace them with IAM Identity Center sessions.

Step 2: Build a per-key baseline from CloudTrail

Take 30 to 90 days of history and list, per key, the distinct source addresses and user agents with counts and first and last seen times. In Athena:

SELECT useridentity.accesskeyid AS key_id,
       useridentity.username AS iam_user,
       sourceipaddress, useragent,
       count(*) AS calls,
       min(eventtime) AS first_seen, max(eventtime) AS last_seen
FROM cloudtrail_logs
WHERE useridentity.accesskeyid LIKE 'AKIA%'
  AND eventtime > '2026-08-01'
GROUP BY 1, 2, 3, 4
ORDER BY key_id, calls DESC;

Enrich each address with ASN, country and an "AWS-owned" flag, then review the result with the key owner. Expect a short list for most machine keys. Anything the owner cannot explain is a lead to investigate now, before you switch on alerting. Store the approved values as a lookup table keyed on access key ID.

Two values need care. When an AWS service makes a call for you, AWS documents that sourceIPAddress shows the service DNS name (for example ec2.amazonaws.com) or AWS Internal/#, and userIdentity.invokedBy names the service. Exclude these from location logic rather than treating them as new locations. Calls made through a VPC endpoint carry vpcEndpointId and vpcEndpointAccountId; record those in the baseline too, because a key that normally arrives through your endpoint and suddenly arrives from the internet has changed location even if the country is the same.

Step 3: Include the sessions each key creates

A long-term key that calls AssumeRole, GetSessionToken or GetFederationToken receives a temporary ASIA key, recorded in responseElements of the STS event. Later calls show the ASIA key, not the original. Join the two so that activity from the child session is attributed back to the parent key and checked against the same baseline. The AWS STS and AssumeRole Guide explains the session fields.

Step 4: Write the alert rules

RuleLogicUse forSuggested priority
Off-list sourceKey in the fixed-origin class, sourceipaddress not in its approved CIDRs, not a service DNS name or AWS InternalFixed-origin keysHigh, page on first event
First-seen ASNNetwork owner never seen for this key in the baseline windowAll keysMedium; High if the ASN is a hosting or VPN provider
Endpoint to internet switchKey normally seen with vpcendpointid set, now seen without itAWS-hosted keysHigh
Concurrent distant useSame key from two ASNs or countries within a short window (for example 30 minutes) where travel is impossibleVariable-origin keysHigh
New user agent with new IPuseragent family (SDK, CLI, tool name) and IP both first seen for the keyAll keysMedium
Validation call from new IPGetCallerIdentity or ListBuckets as the first call from a first-seen IPAll keysHigh
Denied burst from new IPSeveral AccessDenied or UnauthorizedOperation errors from a first-seen IP in a short windowAll keysHigh

The validation-call rule matters because key testers start by checking that a key works. In the TruffleNet campaign, stolen keys were tested at scale with GetCallerIdentity before Amazon SES was abused. The time windows and priorities above are our suggested starting points; tune them to your environment. For general impossible-travel logic and its false positives, see Impossible Travel and Anomalous Sign-In Detection.

Step 5: Route GuardDuty findings into the same queue

GuardDuty findings are published to Amazon EventBridge with source aws.guardduty and detail type GuardDuty Finding. Match the IAM finding types in the table above and send them to the same triage queue as your baseline rules, so one key produces one case. Upload your own list of known-bad addresses as a GuardDuty threat list to get the MaliciousIPCaller.Custom findings, and add your approved egress ranges as a trusted IP list where that fits your setup.

Step 6: Add an IP guardrail for fixed-origin keys

For keys with fixed origins, detection alone leaves the attacker a window. AWS documents an identity policy pattern that denies all actions when the request does not come from listed ranges: "Effect": "Deny", "Action": "*", with a NotIpAddress condition on aws:SourceIp. Attach it to the IAM user (or its group) alongside the policies that grant access. Read the AWS caveats before you deploy it:

  • Public addresses only: aws:SourceIp can only be used for public IP ranges.
  • VPC endpoints: the key is not present when the request comes through a VPC endpoint, so a key used from inside a VPC needs aws:SourceVpce, aws:SourceVpc or aws:VpcSourceIp conditions instead.
  • Calls by AWS services: for service-to-service calls AWS redacts some network context, and recommends excluding service principals from Deny statements with aws:PrincipalIsAWSService set to false. AWS notes that its example policy does not deny requests made by services through forward access sessions, because the original caller's IP is preserved.

Test the policy with the IAM policy simulator and then from a non-approved address in a sandbox account. Roll back by detaching the policy; nothing else changes. At organisation scale, the network perimeter conditions in the AWS Resource Control Policies and Data Perimeter Guide apply the same idea through SCPs and RCPs.

Step 7: Triage and respond

  1. Confirm with the key owner whether the system moved (new NAT, new CI pool, vendor change). Update the baseline if it did, and record who approved it.
  2. If the owner cannot confirm, deactivate the key (do not delete it, so evidence and attribution remain) and revoke sessions it created. The Cloud Access Key Leak Playbook covers containment.
  3. Scope what the key and its child sessions did from the unusual address, including persistence such as CreateAccessKey (T1098.001 Additional Cloud Credentials), using the CloudTrail investigation how-to linked above.
  4. Find where the key leaked from, then replace it, preferably with a role or federation rather than a new long-term key.

Decision points

SituationChooseWhy
Few keys, small team, no SIEMGuardDuty plus the aws:SourceIp deny policy on each fixed-origin key, and a weekly Athena baseline reviewPrevention needs no 24x7 monitoring; denied calls show up in GuardDuty and CloudTrail
Many accounts, central SOCBaseline lookup tables in the SIEM, rules from Step 4, GuardDuty delegated administratorConsistent rules across hundreds of keys, one case per key
Vendor holds the keyAsk for the vendor's egress list and apply the deny policy; alert on any off-list useThird-party breaches are a common source of leaked keys, and you cannot monitor their hosts
Developer laptop keysReplace with IAM Identity Center; meanwhile, first-seen ASN and concurrent-use rules onlyHome and travel networks make allow-lists unworkable and produce noise
Key used from inside AWSConvert to a role; if not yet possible, require the VPC endpoint with aws:SourceVpceRole credentials get GuardDuty's credential exfiltration findings for free

Verify it worked

  • Controlled test: in a sandbox account, create a test user and key, add it to the baseline with one approved address, then call sts get-caller-identity from a different network. Confirm the off-list and validation-call rules fire and reach the queue.
  • Guardrail test: with the deny policy attached, confirm the call from the non-approved address returns AccessDenied and that the denied-burst rule fires.
  • Service path test: exercise a workflow where AWS calls another service for you (for example a CloudFormation stack) and confirm it is neither blocked nor alerted as a new location.
  • GuardDuty path: generate sample findings in GuardDuty and confirm the EventBridge rule delivers them.

Common failure patterns

  • Relying on GuardDuty alone. A key abused from a clean hosting IP to call routine APIs may never meet a finding's threshold. In the AWS crypto-mining campaign, compromised IAM credentials had miners running within minutes, so a daily review is too slow.
  • Treating AWS Internal and service DNS names as new locations. This floods the queue and teaches analysts to ignore the rule. Filter on invokedBy and the documented internal values first.
  • Watching the AKIA key but not its ASIA sessions. The attacker's real activity runs under the temporary key, and the parent key shows only one STS call.
  • Country-only rules. Attackers rent cloud hosts in your own country. In LLMjacking cases, stolen keys were used to test and resell model access, activity that looks ordinary unless the network owner is checked.
  • Allow-lists with no owner. Approved ranges drift when NAT gateways or vendors change. Each list needs an owner and a review date, or the guardrail breaks production and gets removed.
  • No data events on the buckets that matter. In the Codefinger S3 ransomware attacks, stolen keys encrypted objects with CopyObject; without S3 data events those calls never reach your location rules.

Measuring it

  • Baseline coverage: percentage of active AKIA keys with an owner, origin class and approved values (target 100%).
  • Guardrail coverage: percentage of fixed-origin keys with an aws:SourceIp or VPC endpoint deny policy attached.
  • Time to alert: median minutes from an off-list call in CloudTrail to a case in the queue, measured with the controlled test.
  • False positive rate: share of location alerts closed as legitimate change; a rising rate means baselines are stale.
  • Long-term key count: number of active AKIA keys, falling quarter on quarter as roles and federation replace them.

Framework mapping

FrameworkReferenceHow this guide applies
NIST SP 800-53 Rev 5AC-2(12) Account Monitoring for Atypical UsagePer-key baselines and first-seen location rules
NIST SP 800-53 Rev 5SI-4 System Monitoring; AU-6 Audit Record Review, Analysis, and ReportingCloudTrail queries, GuardDuty routing and triage
NIST SP 800-53 Rev 5AC-3 Access Enforcement; IA-5 Authenticator Managementaws:SourceIp guardrail; key register and replacement
NIST CSF 2.0DE.CM-03; DE.AE-02Monitoring technology usage; analysing potentially adverse events
NIST CSF 2.0PR.AA-05Access permissions enforced with network conditions
MITRE ATT&CK v20T1078.004; T1552.001; T1552.005; T1090.003; T1098.001The behaviour being detected and the persistence to check for

Practitioner checklist

  • Organisation trail in all Regions, including us-east-1, with S3 data events on sensitive buckets.
  • GuardDuty enabled organisation-wide with IAM findings routed through EventBridge to the SOC queue.
  • Register of every active AKIA key with owner, system and origin class.
  • 30 to 90 day baseline of sourceIPAddress, ASN, userAgent and VPC endpoint per key, reviewed with owners.
  • Service DNS names, AWS Internal and invokedBy calls excluded from location rules.
  • Child ASIA sessions joined to their parent key.
  • Off-list, first-seen ASN, endpoint switch, validation-call and denied-burst rules live and tested.
  • aws:SourceIp or VPC endpoint deny policy on every fixed-origin key, with an owner for each allow-list.
  • Response steps agreed: confirm with owner, deactivate, scope, replace with a role or federation.

Standards and references

Related NHI Mgmt Group resources: AWS Access Keys Security Guide, How to Investigate CloudTrail for a Compromised Access Key, Cloud Access Key Leak Playbook, Amazon GuardDuty Guide and Impossible Travel and Anomalous Sign-In Detection.

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 11 November 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org