Detect Purchase Technical Data in Splunk
Adversaries may purchase technical information about victims that can be used during targeting. Information about victims may be available for purchase within reputable private sources and databases, such as paid subscriptions to feeds of scan databases or other data aggregation services. Adversaries may also purchase information from less-reputable sources such as dark web or cybercrime blackmarkets. Purchased data may include employee credentials, session tokens, infrastructure details, exposed certificates, or vulnerability scan results. LAPSUS$ is a documented threat actor known to purchase credentials and session tokens from criminal underground forums. Because the purchase itself occurs entirely outside the victim's environment, detection must focus on downstream indicators: use of purchased credentials in authentication events, impossible travel patterns, logins from anonymizing infrastructure (Tor, VPN exit nodes), and Identity Protection risk signals.
MITRE ATT&CK
- Tactic
- Reconnaissance
- Technique
- T1597 Search Closed Sources
- Sub-technique
- T1597.002 Purchase Technical Data
- Canonical reference
- https://attack.mitre.org/techniques/T1597/002/
SPL Detection Query
| tstats count AS attempt_count, dc(user) AS distinct_accounts, dc(src) AS distinct_sources, values(action) AS actions
FROM datamodel=Authentication
WHERE earliest=-7d
BY _time span=1h, src, user, app
| eval credential_stuffing_flag=if(distinct_accounts >= 5 AND distinct_sources == 1, 1, 0)
| eval spray_flag=if(distinct_accounts >= 10, 1, 0)
| eval risk_score=credential_stuffing_flag + spray_flag
| where risk_score > 0
| eval detection_branch="credential_stuffing_or_spray"
| table _time, src, user, app, attempt_count, distinct_accounts, distinct_sources, actions, risk_score, detection_branch
| append
[ search index=* (sourcetype="okta:im:log" OR sourcetype="azure:aad:signin" OR sourcetype=WinEventLog:Security)
(EventCode=4625 OR result="FAILURE" OR outcome.result="FAILURE")
earliest=-7d
| eval src=coalesce(src_ip, client.ipAddress, IpAddress)
| eval user=coalesce(actor.alternateId, TargetUserName, userPrincipalName)
| eval country=coalesce(client.geographicalContext.country, location.countryOrRegion)
| stats count AS fail_count, dc(user) AS distinct_users, values(country) AS countries, latest(_time) AS last_seen
BY src
| where distinct_users >= 5
| eval detection_branch="multi_account_brute_force"
| table last_seen, src, distinct_users, fail_count, countries, detection_branch ]
| append
[ search index=* (sourcetype="okta:im:log" OR sourcetype="azure:aad:signin")
(riskLevel="HIGH" OR riskLevel="MEDIUM" OR riskReasons="*leaked*" OR riskReasons="*anonymized*" OR risk_reasons="*leaked*")
earliest=-7d
| eval src=coalesce(src_ip, client.ipAddress, ipAddress)
| eval user=coalesce(actor.alternateId, userPrincipalName)
| eval risk=coalesce(riskLevel, risk_level)
| eval detection_branch="identity_protection_risk_signal"
| table _time, user, src, risk, riskReasons, detection_branch ]
| sort - _time Detects downstream indicators of purchased credential or technical data use across multiple authentication data sources. Uses the Splunk Common Information Model (CIM) Authentication datamodel for broad coverage, supplemented by direct sourcetype searches against Okta, Azure AD, and Windows Security event logs. Three detection branches: (1) CIM-normalized credential stuffing — one source IP attempting authentication against five or more distinct accounts within an hour, (2) multi-account brute force failures from a single IP across login failure events, and (3) identity provider risk signals (Okta ThreatInsight, Azure AD Identity Protection) indicating leaked credentials or anonymized IP addresses. The append command unions all branches into a single result set for analyst review.
Data Sources
Required Sourcetypes
False Positives & Tuning
- Corporate VPN or proxy concentrating legitimate user logins through a small pool of IP addresses will frequently trigger the credential stuffing threshold
- Helpdesk password reset campaigns or IT provisioning workflows that authenticate against many accounts in sequence from admin workstations
- Security tooling such as vulnerability scanners, SIEM health checks, or authentication testing scripts that probe authentication endpoints
- Okta ThreatInsight or Azure Identity Protection false positives for users on shared hosting, cloud IDEs, or university networks sharing IP ranges with threat actors
- Legitimate users traveling internationally or using commercial VPN services for privacy will trigger new-location and anonymized-IP signals
Other platforms for T1597.002
Testing Methodology
Validate this detection against 5 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.
- Test 1Check Organization Domain Against Have I Been Pwned Enterprise API
Expected signal: Network connection to api.haveibeenpwned.com:443 from the executing host. DNS resolution of api.haveibeenpwned.com. HTTP GET request visible in proxy/web gateway logs. No endpoint telemetry generated for the API call itself.
- Test 2Simulate Credential Stuffing Authentication Pattern
Expected signal: Web application access logs: 15 entries with HTTP 401 from the source IP across distinct usernames, followed by 1 HTTP 200. If web app logs feed into Splunk or Sentinel: Authentication datamodel events with action=failure for the 15 attempts and action=success for the final attempt. All events from the same source IP within a 30-second window.
- Test 3Query Tor Exit Node List and Check Against Authentication Logs
Expected signal: DNS resolution of check.torproject.org. Outbound HTTPS connection to check.torproject.org:443. File creation at /tmp/tor_exit_nodes.txt. If cross-referencing login logs, no additional network telemetry is generated for the grep operations.
- Test 4Enumerate Exposed Credentials for Domain Using Dehashed API
Expected signal: DNS resolution of api.dehashed.com. Outbound HTTPS connection to api.dehashed.com:443 with Basic Authentication header. HTTP GET request visible in proxy/web gateway logs. Response body contains credential records if any are found.
- Test 5Generate Impossible Travel Event for Detection Validation
Expected signal: Two SigninLogs entries for the same UserPrincipalName within a short time window, each with a different IPAddress and LocationDetails.countryOrRegion value. The time delta between entries divided by the physical distance between locations should exceed the speed of any known transportation (i.e., physically impossible travel).
References (10)
- https://attack.mitre.org/techniques/T1597/002/
- https://www.zdnet.com/article/a-hacker-group-is-selling-more-than-73-million-user-records-on-the-dark-web/
- https://www.microsoft.com/en-us/security/blog/2022/03/22/dev-0537-criminal-actor-targeting-organizations-for-data-exfiltration-and-destruction/
- https://learn.microsoft.com/en-us/entra/id-protection/overview-identity-protection
- https://learn.microsoft.com/en-us/azure/azure-monitor/reference/tables/signinlogs
- https://haveibeenpwned.com/API/v3
- https://spycloud.com/blog/what-is-credential-stuffing/
- https://www.cisa.gov/sites/default/files/2023-03/threat-actor-leveraging-multiple-ransomware-families_0.pdf
- https://owasp.org/www-community/attacks/Credential_stuffing
- https://www.recordedfuture.com/blog/dark-web-credential-markets
Unlock Pro Content
Get the full detection package for T1597.002 including response playbook, investigation guide, and atomic red team tests.