Skip to main content
Splunk Lantern

Monitoring consumer bank accounts for potential fraud

Banks, and their customers, are susceptible to fraud in a number of key areas related to customer accounts. Splunk reports can show customer account activity that is unusual or potentially suspicious, such as having multiple accounts, some of which have zero balances, negative balances, or are dormant. These reports can be shown instantly with transaction logs by referencing other accounts in a database. This type of just-in-time reporting allows banks to keep customers informed in a timely manner so they can take corrective action. Monitoring customer accounts also helps banks to adhere to compliance regulations.

Required data

How to use Splunk software for this use case

Some commands, parameters, and field names in the searches below may need to be adjusted to match your environment.  In addition, to optimize the searches shown below, you should specify an index and a time range when appropriate.

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.

Customers with too many bank accounts

Customers that have too many accounts can sometimes cause a compliance issue for banks. This report provides just-in-time information so that at the time of an account transaction, you can inform the customer if they have too many accounts above a threshold so they can consolidate.

|sourcetype=<transaction data source>
|eval _time=strptime(_time, "%Y/%m/%d %H:%M:%S")
|sort - _time
|lookup <customer account info file> customer
|stats last(_time) AS _time list(accountID) AS accountID list(action) AS action list(amount) AS amount list(balance) AS balance values(other_accountID) AS other_accountID sum(other_balance) AS Total_Balance BY customer
|eval count_other_accounts=mvcount(other_accountID)
|where count_other_accounts>10
|eval Total_Balance=Total_Balance+balance
|eval balance=tostring(round(balance, 2),"commas"), Total_Balance=tostring(round(Total_Balance, 2),"commas")

Need more help with this search? Click here.

Dormant bank accounts

Customers having dormant accounts can sometimes cause a compliance issue for banks. This report provides just-in-time information so that at the time of an account transaction, you can inform the customer if they have any untouched accounts older than 6 months from their current transaction date.

|sourcetype=<transaction data source>
|eval prev_epoch=strptime(last_touched, "%m/%d/%Y %H:%M:%S")
|sort - last_touched
|join customer [ |inputlookup <customer account info file> ]
|where epoch>relative_time(prev_epoch, "+6mon")
|fields - prev_epoch, balance|rename accountID AS current_accountID action AS current_action account_type AS current_account_type
|eval current_balance=tostring(round(current_balance, 2),"commas"), other_balance=tostring(round(other_balance, 2),"commas")
|convert timeformat="%m/%d/%Y %H:%M:%S" ctime(epoch) AS current_time
|fields - epoch

Need more help with this search? Click here.

Bank accounts with large balances

Customers who have accounts with a large balance can sometimes cause a compliance issue for banks. In some countries, accounts are insured only up to certain threshold. This report provides just-in-time information so that at the time of an account transaction, you can inform the customer if their total accounts balance is greater than their country's established insured threshold.

|sourcetype=<transaction data source>
|eval _time=strptime(_time, "%Y/%m/%d %H:%M:%S")
|sort - _time
|lookup <customer account info file> customer
|stats  values(_time) AS _time list(balance) as current_account_balance list(account_type) AS current_account_type list(other_account_type) AS other_account_type list(other_accountID) AS other_accountID list(other_balance) AS other_balance sum(other_balance) AS Total_Balance BY customer
|eval Total_Balance=Total_Balance+current_account_balance
|search other_account_type="*" AND Total_Balance>250000
|eval Total_Balance=tostring(round(Total_Balance, 2),"commas"), current_account_balance=tostring(round(current_account_balance, 2),"commas")

Need more help with this search? Click here.

Bank accounts with a negative balance

Customers having accounts with a negative balance can sometimes cause a compliance issue for banks. A negative balance could indicate an overdraft or account takeover. This report provides just-in-time information so that at the time of an account transaction, you can inform the customer.

|sourcetype=<transaction data source>
|eval _time=strptime(_time, "%Y/%m/%d %H:%M:%S")
|sort _time
|lookup <customer account info file> customer
|stats last(_time) AS _time last(amount) AS amount last(accountID) AS accountID last(action) AS action last(account_type) AS account_type list(other_balance) AS other_balance list(other_accountID) AS other_accountID  list(other_account_type) AS other_account_type BY customer 
|search other_balance=*
|nomv other_balance
|search other_balance="-*"
|makemv delim=" " other_balance
|table _time, customer, amount, accountID, action, account_type, other_accountID, other_account_type, other_balance
|eval amount=tostring(round(amount, 2),"commas")

Need more help with this search? Click here.

Bank accounts with zero balance

Customers having accounts with a zero balance can sometimes cause a compliance issue for banks. This report provides just-in-time information so that at the time of an account transaction, you can inform the customer.

|sourcetype=<transaction data source>
|eval _time=strptime(_time, "%Y/%m/%d %H:%M:%S")
|sort - _time
|lookup <customer account info file> customer
|stats last(_time) AS _time last(amount) AS amount last(accountID) AS accountID last(action) AS action last(account_type) AS account_type list(other_balance) AS other_balance list(other_accountID) AS other_accountID  list(other_account_type) AS other_account_type BY customer 
|eval is_match=mvfilter(match(other_balance, "0"))
|search is_match=*
|fields - is_match
|table _time, customer, amount, accountID, action, account_type, other_accountID, other_account_type, other_balance
|eval amount=tostring(round(amount, 2),"commas")

Need more help with this search? Click here.

Next steps

Run reports based off these searches on a regular basis and save the results as needed for compliance reporting. Investigate as needed to ensure the activity isn't related to employee behavior, and then communicate immediately with customers regarding any results that indicate problematic accounts.

The Splunk Essentials for the Financial Services Industry app helps you automate the searches provided in this article. The app also provides more insight on how they can be applied in your environment, how they work, the difficulty level, and what data can be valuable to run them successfully. In addition, the Splunk Essentials for the Financial Services Industry app provides a number of other fraud detection solutions for financial services:

Finally, these additional Splunk resources might help you understand and implement this use case:

Still need help with this use case? Most customers have OnDemand Services per their license support plan. Engage the ODS team at OnDemand-Inquires@splunk.com if you require assistance.