Identity Reuse and Payroll-Fraud Indicators

Identity / cloud

Behavioral Hunt low DPRK IT Worker FraudLaptop Farm

Shared bank details across employees who should have nothing in common, plus rapid post-hire direct-deposit changes, corroborated against sign-in geography.

What this hunt looks for

Facilitator-run schemes use stolen or knowingly loaned United States identities to pass background and employment-eligibility checks, then route payroll through facilitator-controlled accounts and reuse a small set of financial and mailing details across what appear to the employer as distinct hired individuals. Christina Chapman's operation alone used sixty-eight stolen American identities to place workers at 309 companies.

This is an HR and IT-operations correlation hunt rather than an endpoint or network one. It looks for shared routing and account numbers across distinct employee records and rapid post-hire direct-deposit changes, corroborated by sign-in telemetry inconsistent with the claimed location. Mandiant's related control, requiring a United States bank account, raises the verification bar.

Technique
Fraudulently obtained employment and valid-account misuse (MITRE ATT&CK T1078) combined with financial-identity reuse; not a file or network indicator hunt.
Data sources
HRIS and payroll records, Identity provider sign-in logs
Last updated
2026-10-04

Logic

Every query below implements these steps, so the same hunt returns the same result in each product.

  1. Collect: HRIS and payroll records per employee, and successful identity-provider sign-ins from the last 30 days
  2. Match: two or more employee records share one bank routing and account number
  3. Match: or two or more employee records share a mailing address
  4. Match: or the direct-deposit account was changed within 45 days of the hire date
  5. Report: each flagged employee with the signals hit and sign-in countries other than the claimed country, shared bank details first

Queries

Defender / Sentinel KQL

Written for this site, from indicators reported by Department of Justice, Mandiant

Employees returned either share bank details with a colleague or changed deposit details within 45 days of hire, and OtherCountries shows where else they signed in, so verify the identity manually.

// HRPayroll is a placeholder for the HRIS table you ingest: EmployeeId, UserPrincipalName, HireDate, ClaimedLocationCountry, BankRouting, BankAccount, MailingAddress, DirectDepositChangedOn.
let Payroll = HRPayroll
    | extend BankKey = strcat(BankRouting, ":", BankAccount), AddressKey = tolower(trim(@"\s+", MailingAddress));
let Countries = SigninLogs
    | where TimeGenerated > ago(30d) and ResultType == "0"
    | summarize SignInCountries = make_set(tostring(LocationDetails.countryOrRegion)) by UserPrincipalName;
Payroll
| lookup kind=leftouter (Payroll | summarize BankEmployees = dcount(EmployeeId) by BankKey) on BankKey
// optional: shared mailing address, the line below and the matching line in the where clause
| lookup kind=leftouter (Payroll | summarize AddressEmployees = dcount(EmployeeId) by AddressKey) on AddressKey
| extend EarlyDepositChange = DirectDepositChangedOn between (HireDate .. (HireDate + 45d))
| where BankEmployees > 1 or EarlyDepositChange
// optional: shared mailing address, the line below
    or AddressEmployees > 1
| lookup kind=leftouter Countries on UserPrincipalName
| extend OtherCountries = set_difference(SignInCountries, pack_array(ClaimedLocationCountry))
| project-away BankRouting, BankAccount, MailingAddress, BankKey, AddressKey, SignInCountries
| order by BankEmployees desc, HireDate desc
Lower-fidelity parts (2)
  • the shared mailing address clause (KQL) — family members, flatmates and apartment blocks legitimately share an address, so it raises more noise than bank details do. Remove: delete each // optional: comment line together with the single line beneath it (the AddressEmployees lookup and the or AddressEmployees > 1 line)
  • the 45-day direct-deposit window — a new hire who moves or opens a local account changes deposit details early without any fraud. Remove: delete the EarlyDepositChange extend line and change the where clause to start with where BankEmployees > 1

Splunk SPL

Written for this site, from indicators reported by Department of Justice, Mandiant

The same signals from the payroll lookup, with sign-in countries taken from the Authentication data model and compared to the claimed country.

```Placeholders: payroll_records.csv is the HRIS export (employee_id, user, hire_time, claimed_country, bank_routing_number, bank_account_number, mailing_address, direct_deposit_changed_time, all epoch times). Sign-ins come from the Authentication data model.```
| inputlookup payroll_records.csv
| eventstats dc(employee_id) AS bank_employees BY bank_routing_number, bank_account_number
```optional: shared mailing address, the line below and the matching line in the where clause```
| eventstats dc(employee_id) AS address_employees BY mailing_address
| eval early_deposit_change=if(isnotnull(direct_deposit_changed_time) AND direct_deposit_changed_time>=hire_time AND direct_deposit_changed_time<=hire_time+45*86400, 1, 0)
| where bank_employees>1 OR early_deposit_change=1
```optional: shared mailing address, the line below```
    OR address_employees>1
| join type=left user
    [| tstats count FROM datamodel=Authentication.Authentication WHERE Authentication.action=success earliest=-30d BY Authentication.user, Authentication.src
     | rename Authentication.user AS user, Authentication.src AS src_ip
     | iplocation src_ip
     | stats values(Country) AS signin_countries BY user]
| eval other_countries=mvmap(signin_countries, if(signin_countries!=claimed_country, signin_countries, null()))
| fields - bank_routing_number, bank_account_number, mailing_address, signin_countries
| sort - bank_employees, - hire_time
Lower-fidelity parts (2)
  • the shared mailing address clause (SPL) — family members, flatmates and apartment blocks legitimately share an address, so it raises more noise than bank details do. Remove: delete each optional comment line together with the single line beneath it (the address_employees eventstats and the OR address_employees>1 line)
  • the 45-day direct-deposit window — a new hire who moves or opens a local account changes deposit details early without any fraud. Remove: delete the early_deposit_change eval line and change the where clause to start with where bank_employees>1

False positives and tuning

Shared bank details occur legitimately between family members and on joint accounts, and an early direct-deposit change is often a local account opened after moving. Every match needs manual identity verification.

The queries assume a custom HR table or lookup with the columns named in their first comment; adapt them to the HRIS export actually ingested. Handling payroll data this way carries jurisdiction-specific privacy obligations; settle them with counsel first.

Sources

Tuning required before use This hunt is a starting point. Adapt the queries to your schema, validate them against your baseline and tune them for the false positives noted above. Indicators go stale as operators rotate hosts.