Monitoring money laundering activities with the Splunk platform
As a financial services provider, your organization must comply with anti-money laundering (AML) regulations. Money laundering often involves complex schemes to disguise the origin of illicit funds through multiple transactions, often involving high-risk countries or unusual transaction patterns. To protect your customers and comply with regulations, you need to detect activities like structuring (smurfing), rapid movement of funds, and transfers involving high-risk jurisdictions.
Detecting AML activities can be a significant challenge for compliance teams, as threat indicators and money laundering tactics constantly evolve.
This article shows you how to use searches in the Splunk platform to create basic detection methods. For advanced techniques leveraging user behavioral analytics to stay ahead of emerging threats, see Monitoring money laundering activities with the Splunk App for Behavioral Analytics.
- Some commands, parameters, and field names in the searches below might need to be adjusted to match your environment.
- Splunk recommends that customers look into using data models, report acceleration, or summary indexing when searching across hundreds of GBs of events in a single search. The searches provided here are a good starting point, but depending on your data, search time range, and other factors, more can be done to ensure that they scale appropriately.
- Some of the searches below include
lookup
commands that enrich event data by matching and adding fields from external data sources, such as CSV files or databases. For more information, see Search reference: lookup.
Data required
- Application data for consumer financial applications
- Depending on the search you're looking to run, you might also need a CSV or KV lookup of suspicious countries, suspicious IPs, and/or high-risk accounts.
How to use the Splunk platform for this use case
There are many searches you can run with Splunk software to detect money laundering activities. You can detect these attempts using these searches:
- ► High volume of transactions
-
This search identifies accounts making multiple small transactions that total a large sum within a short period. Such patterns, often referred to as structuring or smurfing, help mask large transfers to avoid regulatory detection. By flagging accounts with unusually high transaction counts, financial institutions can identify suspicious activity suggestive of money laundering, allowing for early intervention and compliance with anti-money laundering (AML) standards.
Procedure
-
Ensure that the correct source types are available for analyzing data related to transaction logs. The table below outlines recommended source types, associated fields, and typical data sources for transactions within financial applications.
Suggested sourcetype Fields Data sources transaction_logs
transaction_id, account_number, transaction_type, amount, currency, timestamp, account_type, channel, device_info, status, src_ip, source_city, source_country, dest_ip, dest_city, dest_country, old_balance_source, new_balance_source, old_balance_dest, new_balance_dest, payee, transaction_class
- Payment gateways
- Stripe, PayPal, Clover
- Banking systems
- Core banking platforms
- E-commerce platforms
- Shopify, Magento
- Point of Sale (POS) systems
- Retail transaction systems
- Internal Financial Systems
- Enterprise Resource Planning (ERP) systems
- Payment gateways
-
Run the following search.
index="<consumer financial app transaction logs> " status="completed" earliest=-7d@d latest=now | bin _time span=1h | stats count AS txn_count_hour, sum(amount) AS total_amount_hour BY account_number, _time | stats sum(txn_count_hour) AS total_txn_count, sum(total_amount_hour) AS total_amount, avg(txn_count_hour) AS avg_txn_count_per_hour, stdev(txn_count_hour) AS stdev_txn_count_per_hour, max(txn_count_hour) AS max_txn_count_hour BY account_number | where total_txn_count > 10 AND total_amount > 100000 AND avg_txn_count_per_hour < 5 AND max_txn_count_hour > 3 | eval structuring_flag = if(total_txn_count > 10 AND total_amount > 100000 AND avg_txn_count_per_hour < 5, 1, 0) | table account_number, total_txn_count, total_amount, avg_txn_count_per_hour, stdev_txn_count_per_hour, max_txn_count_hour, structuring_flag
Search explanation
The table provides an explanation of what each part of this search achieves. You can adjust this query based on the specifics of your environment.
Splunk Search Explanation sourcetype=<consumer financial app transaction logs>
Search consumer financial app transaction logs.
status="completed" earliest=-7d@d latest=now()
Define search range as the last 7 days.
| bin _time span=1h
Group transactions into 1-hour bins.
| stats
count AS txn_count_hour,
sum(amount) AS total_amount_hour
BY account_number, _time
Count the total number of transactions within each hour, grouped by account, and label it as
txn_count_hour
.
Sum the total transaction amounts within each hour for each account, labeled astotal_amount_hour
.Group the calculations by
account_number
and by 1hr intervals, providing a breakdown of hourly transaction activity for each account.| stats
sum(txn_count_hour) AS total_txn_count,
sum(total_amount_hour) AS total_amount,
avg(txn_count_hour) AS avg_txn_count_per_hour,
stdev(txn_count_hour) AS stdev_txn_count_per_hour,
max(txn_count_hour) AS max_txn_count_hour
by account_number
Calculate the total number of transactions across all hours.
Calculate cumulative transaction amounts across all hours.Calculate the average transactions per hour.
Calculate the standard deviation of transactions per hour, indicating variability.
Calculate the maximum number of transactions in a single hour.
| where total_txn_count > 10
AND total_amount > 100000
AND avg_txn_count_per_hour < 5
AND max_txn_count_hour > 3
Filter by accounts that have conducted more than 10 transactions within the analyzed period that have a cumulative amount of all transactions exceeding 100,000.
Filter by accounts that, on average, perform fewer than 5 transactions per hour.
Filter by accounts where there exists at least one hour where the account made more than 3 transactions.| eval structuring_flag = if(total_txn_count > 10
AND total_amount > 100000
AND avg_txn_count_per_hour < 5, 1, 0)Create a flag to identify structuring behavior:
Set if the account has more than 10 transactions, total transaction amount exceeds 100,000, and the average transactions per hour is less than 5.| table account_number, total_txn_count, total_amount,
avg_txn_count_per_hour, stdev_txn_count_per_hour,
max_txn_count_hour, structuring_flag
Create a table displaying the metrics shown for each account.
-
- ► Rapid movement of funds
-
This search detects quick, successive transactions moving funds between accounts, which could indicate layering, which is a common step in money laundering to obscure the origin of funds. By identifying accounts with frequent large transfers, analysts can investigate potential risks tied to account layering, strengthening institutional defenses against illegal financial flows.
Procedure
-
Ensure that the correct source types are available for analyzing data related to account interfacing activities.The table below outlines recommended source types, associated fields, and typical data sources for monitoring account interfacing activity across financial applications.
Suggested Sourcetype
Fields
Sources
transaction_logs
transaction_id, account_number, transaction_type, amount, currency, timestamp, account_type, channel, device_info, status, src_ip, source_city, source_country, dest_ip, dest_city, dest_country, old_balance_source, new_balance_source, old_balance_dest, new_balance_dest, payee, transaction_class
- Payment gateways
- Stripe, PayPal, Clover
- Banking systems
- Core banking platforms
- E-commerce platforms
- Shopify, Magento
- Point of Sale (POS) systems
- Retail transaction systems
- Internal Financial Systems
- Enterprise Resource Planning (ERP) systems
- Payment gateways
- Run the following search.
index=<consumer financial app transaction logs> status="completed" earliest=-7d@d latest=now | bin _time span=1h | stats count AS txn_count_hour, sum(amount) AS total_amount_hour BY account_number, _time | stats sum(txn_count_hour) AS total_txn_count, sum(total_amount_hour) AS total_amount, avg(txn_count_hour) AS avg_txn_count_per_hour, stdev(txn_count_hour) AS stdev_txn_count_per_hour, max(txn_count_hour) AS max_txn_count_hour BY account_number | where total_txn_count > 10 AND total_amount > 100000 AND avg_txn_count_per_hour < 5 AND max_txn_count_hour > 3 | eval rapid_movement_flag = if(max_txn_count_hour > 3, 1, 0) | where rapid_movement_flag = 1 | table account_number, total_txn_count, total_amount, avg_txn_count_per_hour, stdev_txn_count_per_hour, max_txn_count_hour, rapid_movement_flag | sort -total_amount
Search explanation
The table provides an explanation of what each part of this search achieves. You can adjust this query based on the specifics of your environment.
Splunk Search Explanation sourcetype=<consumer financial app transaction logs>
Search consumer financial app transaction logs.
status="completed" earliest=-7d@d latest=now
Define search range to the last 7 days for all transactions that are completed.
| bin _time span=1h
Group transactions into 1-hour bins.
| stats
count AS txn_count_hour,
sum(amount) AS total_amount_hour
by account_number, _time
Count the total number of transactions within each hour, grouped by account, labeled as
txn_count_hour
.
Sum the total transaction amounts within each hour for each account, labeled astotal_amount_hour
.Group the calculations by
account_number
and by 1 hour intervals, providing a breakdown of hourly transaction activity for each account.| stats
sum(txn_count_hour) AS total_txn_count,
sum(total_amount_hour) AS total_amount,
avg(txn_count_hour) AS avg_txn_count_per_hour,
stdev(txn_count_hour) AS stdev_txn_count_per_hour,
max(txn_count_hour) AS max_txn_count_hour
BY account_number
Calculate the total number of transactions across all hours.
Calculate cumulative transaction amounts across all hours.
Calculate the average transactions per hour.
Calculate the standard deviation of transactions per hour, indicating variability.
Calculate the maximum number of transactions in a single hour.
| where total_txn_count > 10
AND total_amount > 100000
AND avg_txn_count_per_hour < 5
AND max_txn_count_hour > 3
Filter by accounts that have conducted more than 10 transactions within the analyzed period.
Filter by accounts that have a cumulative amount of all transactions exceeding 100,000.
Filter by accounts that on average the account performs fewer than 5 transactions per hour.Filter by accounts where there exists at least one hour where the account made more than 3 transactions.
| eval rapid_movement_flag = if(max_txn_count_hour > 3, 1, 0)
Evaluate account numbers that experienced a burst of activity, with more than 3 transactions in a single hour.
Setrapid_movement_flag
to 1 if true.| where rapid_movement_flag = 1
Filter by
rapid_movement_flag
set to 1.| table account_number, total_txn_count, total_amount,
avg_txn_count_per_hour, stdev_txn_count_per_hour,
max_txn_count_hour, rapid_movement_flag
Output a table summarizing the fields shown for each account number.
| sort -total_amount
Sort the table output by amount total.
-
- ► Transactions involving high-risk jurisdictions
-
This search flags transactions routed through high-risk countries or IP addresses. Transfers linked to jurisdictions known for weak anti-money laundering (AML) regulations might carry higher laundering risks. Monitoring these transactions allows institutions to apply additional scrutiny, potentially mitigating exposure to illicit financial activities and ensuring compliance with international AML protocols.
Procedure
-
Ensure that the correct source types are available for identifying transaction activity. The table below outlines recommended source types, associated fields, and typical data sources for monitoring transactions across financial applications.
Suggested sourcetype Fields Data sources transaction_logs
transaction_id, account_number, transaction_type, amount, currency, timestamp, account_type, channel, device_info, status, src_ip, source_city, source_country, dest_ip, dest_city, dest_country, old_balance_source, new_balance_source, old_balance_dest, new_balance_dest, payee, transaction_class
Payment gateways - Stripe, PayPal, Clover
- Core banking platforms
- Shopify, Magento
- Retail transaction systems
- Enterprise Resource Planning (ERP) systems
-
Run the following search.
index="<consumer financial app transaction logs>" status="completed" earliest=-7d@d latest=now | lookup high_risk_countries country AS dest_country OUTPUT country AS high_risk_dest_country | lookup high_risk_ips ip_address AS dest_ip OUTPUT ip_address AS high_risk_dest_ip | where isnotnull(high_risk_dest_country) OR isnotnull(high_risk_dest_ip) | table account_number, dest_country, amount, dest_ip, transaction_type
Search explanation
The table provides an explanation of what each part of this search achieves. You can adjust this query based on the specifics of your environment.
Splunk Search Explanation sourcetype=<consumer financial app transaction logs>
Search consumer financial app transaction logs.
status="completed" earliest=-7d@d latest=now
Define search range to the last 7 days for all transactions that are completed.
| lookup high_risk_countries country AS dest_country OUTPUT country AS high_risk_dest_country
Use the
high_risk_countries
lookup to identify transactions involving high-risk destination countries.| lookup high_risk_ips ip_address AS dest_ip OUTPUT ip_address AS high_risk_dest_ip
Use the
high_risk_dest_ip
lookup to identify transactions involving high-risk destination countries.| where isnotnull(high_risk_dest_country) OR isnotnull(high_risk_dest_ip)
Filter the data to include only transactions involving high-risk countries or IP addresses.
| table account_number, dest_country, amount, dest_ip, transaction_type
Output a table summarizing the fields shown for each account number.
-
- ► Unusual transaction behavior
-
This search detects outlier transactions that exceed a customer’s usual activity, such as unexpectedly large transfers. Uncharacteristic behavior often indicates higher risk, especially when tied to high-risk countries or IP addresses. By surfacing these anomalies, financial institutions can investigate irregularities that might suggest fraud or money laundering, preserving security and regulatory compliance.
Procedure
-
Ensure that the correct source types are available for identifying unusual transaction patterns. The table below outlines recommended source types, associated fields, and typical data sources for monitoring transaction patterns across financial applications.
Suggested source type
Fields
Sources
transaction_logs
transaction_id, account_number, transaction_type, amount, currency, timestamp, account_type, channel, device_info, status, src_ip, source_city, source_country, dest_ip, dest_city, dest_country, old_balance_source, new_balance_source, old_balance_dest, new_balance_dest, payee, transaction_class
- Payment gateways
- Stripe, PayPal, Clover
- Banking systems
- Core banking platforms
- E-commerce platforms
- Shopify, Magento
- Point of Sale (POS) systems
- Retail transaction systems
- Internal Financial Systems
- Enterprise Resource Planning (ERP) systems
- Payment gateways
- Run the following search.
index="<consumer financial app transaction logs> " status="completed" earliest=30d@d latest=now | search transaction_type="transfer" | eventstats perc99.9(amount) AS perc99_9_amount BY account_number | where amount > perc99_9_amount | lookup high_risk_countries country AS dest_country OUTPUT country AS high_risk_dest_country | lookup high_risk_ips ip_address AS dest_ip OUTPUT ip_address AS high_risk_dest_ip | where isnotnull(high_risk_dest_country) OR isnotnull(high_risk_dest_ip) | table account_number, dest_country, amount, dest_ip, transaction_type, timestamp | sort -amount
Search explanation
The table provides an explanation of what each part of this search achieves. You can adjust this query based on the specifics of your environment.
Splunk Search Explanation sourcetype=<consumer financial app transaction logs>
Search consumer financial app auth logs.
earliest=-30d@d latest=now
Define search range to the last 7 days for all transactions that are completed.
| search transaction_type="transfer"
Define search by transactions types that are
transfer
only.| eventstats
perc99.9(amount) AS perc99_9_amount
BY account_number
Calculate the 99.9th percentile (3 Sigma) of transaction amounts for each account number.
| where amount > perc99_9_amount
Filter by amounts that are above the 3 Sigma percentile.
| lookup high_risk_countries country AS dest_country OUTPUT country AS high_risk_dest_country
Use the
high_risk_countries
lookup to identify transactions involving high-risk destination countries.| lookup high_risk_ips ip_address AS dest_ip OUTPUT ip_address AS high_risk_dest_ip
Use the
high_risk_dest_ip
lookup to identify transactions involving high-risk destination countries.| where isnotnull(high_risk_dest_country) OR isnotnull(high_risk_dest_ip)
Filter the data to include only transactions involving high-risk countries or IP addresses.
| table account_number, dest_country, amount, dest_ip, transaction_type, timestamp
Output a table summarizing the fields shown for each account number.
| sort -amount
Sort the table output by amount total.
-
Next steps
Use the results of these searches to make recommendations to the rest of the security team about which accounts should be investigated for potential account abuse. Create reports based on these searches and schedule them to run at a regular cadence as needed. Be sure to follow any industry policies and regulations that are required for compliance.
For advanced techniques leveraging user behavioral analytics to stay ahead of emerging threats, see Monitoring for account abuse with the Splunk App for Behavioral Analytics.
To further advance your use cases, the Splunk Essentials for the Financial Services Industry app helps you automate the searches to detect financial crime. The app also provides more insight on how searches can be applied in your environment, how they work, the difficulty level, and what data can be valuable to run them successfully.
The Splunk App for Fraud Analytics provides Splunk Enterprise Security users a number of other fraud detection solutions for financial services such as account takeover and new account abuse.
The Splunk App for Behavioral Profiling is a collection of workflows which enable you to operationalize machine learning driven detection and scoring of behavioral anomalies at scale in complex environments, correlated to profile and highlight the entities which require investigation.
If you have questions about monitoring for account takeover in your environment, you can reach out to your Splunk account team or representative for comprehensive advice and assistance. You can contact your account team through the Contact Us page. For more in-depth support, consult Splunk On-Demand Services to access credit-based services for direct access to Splunk technical consultants with a variety of technical services from a pre-defined catalog. Most customers have OnDemand Services per their license support plan. Engage the ODS team at ondemand@splunk.com if you would like assistance.
In addition, these resources might help you understand and implement this guidance:
- Use Case Explorer: Risk-based alerting
- Use case: Monitoring consumer bank accounts to maintain compliance
- Use case: Detecting credit card fraud
- Use case: Detecting wire transfer fraud
- Use case: Investigating interesting behavior patterns with risk-based alerting
- Use case: Monitoring new logins to financial applications
- Use case: Using modern methods of detecting financial crime
- Use case: Detecting multiple account login denials followed by authorization