Фрод-скоринг транзакций: модель по цепочке устройство-IP-поведение

В марте 2026 года колумбийский финтех Addi допустил утечку 34,5 миллиона записей — кредитные скоры, идентификаторы устройств, государственные ID (по данным Have I Been Pwned). Когда такой датасет попадает на чёрный рынок, мошенник получает не «базу для спама», а готовый профиль платёжеспособности жертвы ещё до первой транзакции. Стандартная антифрод система, обученная на исторических аномалиях, этот сценарий пропускает — атакующий действует с реальными данными реального клиента.
Я взял анонимизированный датасет из утечки фрод-сервиса (сервис перепродажи скомпрометированных карт с привязкой к устройствам и IP), построил модель фрод-скоринга транзакций, связывающую три слоя — устройство, IP, поведение — и посчитал, сколько денег она спасает. Ниже — весь путь от парсинга сырых данных до оценки в рублях.
Бизнес-логика фрод-атаки: зачем мошеннику три слоя данных
Прежде чем строить модель, разберёмся со структурой операций атакующего. В терминах MITRE ATT&CK (открытая база тактик и техник атак; каждая техника имеет T-код — уникальный идентификатор, например T1657) типичная цепочка карточного фрода проходит три стадии.
Разведка — сбор учётных данных (T1589.001, Credentials). Мошенник покупает из утечки связку: номер карты + CVV + device fingerprint (цифровой отпечаток устройства — подробнее ниже) + IP-адрес последней легитимной сессии. Утечка Addi — конкретный пример: помимо карточных данных в ней оказались кредитные скоры, что позволяет целиться в клиентов с высокими лимитами.
Проверка валидности — Credential Stuffing (T1110.004). Серия микроплатежей (10–50 рублей) через разные мерчанты за считанные секунды. Прошёл платёж — карта «живая».
Монетизация — Financial Theft (T1657). Покупка gift-карт, электроники, переводы на подставные счета.
На каждом этапе мошенник оставляет след в трёх слоях: устройство (device fingerprint), сеть (IP, ASN, геолокация) и поведение (время, частота, суммы, категории покупок). Антифрод система, которая смотрит только на один слой — допустим, только на IP — слепа к остальным двум. Модель, связывающая все три слоя, обнаруживает фрод-паттерны, невидимые при анализе каждого слоя по отдельности. По данным Mandiant M-Trends 2025, финансовый сектор входит в тройку наиболее атакуемых отраслей, и цепочки описанного типа остаются основным вектором монетизации.
Парсинг датасета утечки фрод-сервиса: от дампа к рабочей таблице
Датасет утечки фрод-сервиса — это не аккуратный CSV с колонками transaction_id и amount. Полуструктурированный дамп с нестандартными именами полей и строками в свободном формате. Типичная структура после первого просмотра:
- card_hash — хеш карточных данных (номер карты редко хранится открытым текстом)
- device_info — строка, куда свалены User-Agent, разрешение экрана, timezone, язык
- ip_address — IP последней успешной транзакции
- geo — страна и город по GeoIP
- last_txn_amount и last_txn_time — сумма и время последней операции
- check_count — сколько раз карту «пробили» через сервис. Если карту проверяли 15 раз за сутки — это точно не легитимный клиент
Предпосылки для повторения: Python 3.10+, библиотеки pandas, scikit-learn, lightgbm. Для графового анализа — networkx. Данные загружены в рабочую директорию как fraud_service_dump.csv.
Первый шаг — извлечь полезные поля из «грязных» строк:
import pandas as pd
df = pd.read_csv('fraud_service_dump.csv')
# Извлекаем OS, разрешение экрана и timezone из device_info
df['os'] = df['device_info'].str.extract(r'(Windows|Linux|Mac|Android|iOS)')
df['screen'] = df['device_info'].str.extract(r'(\d{3,4}x\d{3,4})')
df['timezone'] = df['device_info'].str.extract(r'UTC([+-]\d{1,2})')
df['last_txn_time'] = pd.to_datetime(df['last_txn_time'], errors='coerce')
df['txn_hour'] = df['last_txn_time'].dt.hour
str.extract вытягивает подстроки по регулярному выражению. После выполнения в df появятся столбцы os, screen, timezone, txn_hour. Если str.extract вернул NaN — формат device_info в этой строке нестандартный. Проверьте: df[df['os'].isna()]['device_info'].head(10) покажет строки, не попавшие под шаблон. Они часто содержат следы антидетект-браузеров (Multilogin, GoLogin), генерирующих нетипичные User-Agent.
Feature engineering: признаки для детекции мошенничества по устройству
Модель машинного обучения для антифрода работает ровно настолько хорошо, насколько хороши признаки (features), которые вы ей дали. Сырые поля ip_address или device_info бесполезны — нужны числовые переменные, отражающие аномальность конкретной транзакции.
Device fingerprint — фингерпринтинг устройств как источник признаков
Device fingerprint — уникальный идентификатор устройства, собранный из комбинации аппаратных и программных характеристик: разрешение экрана, модель GPU, версия ОС, установленные шрифты, параметры рендеринга Canvas и WebGL. По отдельности каждый параметр неуникален — миллионы устройств работают на одной ОС с одним разрешением. Но комбинация десятков параметров создаёт отпечаток, устойчивый даже после очистки cookies и смены браузера (по данным Sign3 и Fingerprint.com).
Три уровня хешей fingerprint (по данным Sign3):
| Уровень | Что анализирует | Устойчивость | Ограничение |
|---|---|---|---|
| Cookie hash | Cookies, local storage | Низкая — исчезает при очистке | Первичный сигнал сессии |
| Browser hash | Canvas-рендеринг, шрифты, плагины | Средняя — меняется при обновлении | Не зависит от cookies |
| Device hash | GPU, CPU, калибровка сенсоров | Высокая — переживает переустановку | Требует SDK-интеграции |
Если cookie hash сбрасывается, но browser и device hash остаются прежними — расхождение между слоями указывает на попытку «перевоплощения». Легитимный пользователь может очистить cookies, но его аппаратные сигналы не изменятся.
Ключевые признаки для модели из device fingerprint:
- device_age_hours — сколько часов назад
device_idвпервые появился в системе. Устройство «моложе» 24 часов при сумме транзакции выше среднего чека в 3+ раза — сигнал account takeover - device_card_count — количество уникальных карт с одного устройства за 24 часа. Один fingerprint + 12 карт = кардинг
- device_type_mismatch — совпадает ли OS в fingerprint с User-Agent. Антидетект-браузеры часто «притворяются» мобильным устройством, но Canvas-рендеринг выдаёт десктопный GPU
- fingerprint_stability — насколько стабилен fingerprint между сессиями. У легитимного клиента устройство не меняется месяцами (по данным Plaid). У мошенника fingerprint «плывёт» каждые несколько часов
IP-геолокация и анализ цепочки устройство-IP-поведение
IP-адрес сам по себе — слабый сигнал: VPN доступен каждому. Но в связке с остальными слоями IP превращается в сильный индикатор:
- ip_country_bin_mismatch — страна IP не совпадает со страной BIN карты (BIN — первые 6–8 цифр номера, определяющие банк-эмитент). Три разных юрисдикции (IP, BIN, мерчант) — серьёзный красный флаг
- ip_cards_24h — количество уникальных карт с одного IP за 24 часа. За NAT значение бывает высоким и у легитимных клиентов, но в комбинации с
device_card_count > 3это уже паттерн фрода - is_proxy_vpn — IP принадлежит VPN/прокси-сервису. В терминах MITRE ATT&CK это External Proxy (T1090.002, Command and Control) — атакующий маскирует реальный адрес. AbuseIPDB (база репутации IP-адресов; confidence score от 0 до 100, значение выше 75 — порог для блокировки) помогает оценить репутацию адреса автоматически
- geo_velocity — «скорость перемещения»: если две транзакции с одной карты прошли из Москвы и Владивостока с разницей в 10 минут, клиент физически не мог переместиться. Формула: расстояние между GeoIP-точками / разница во времени. Выше 1000 км/ч — аномалия
Поведенческий анализ пользователей: аномалии baseline
Каждый клиент формирует поведенческий baseline — привычные суммы, время покупок, категории мерчантов, частота операций. Отклонение от baseline — не фрод само по себе, но сигнал для повышения риск-скоринга.
- amount_zscore — z-score суммы транзакции (отклонение от среднего в единицах стандартного отклонения) за 90 дней. Z-score > 3 означает: сумма аномально высока для этого клиента
- txn_hour_deviation — транзакция в 03:00 у клиента, который за полгода ни разу не платил ночью
- velocity_5min — количество транзакций за 5 минут. Человек не оформит покупку быстрее 15–20 секунд. Интервал менее 10 секунд — автоматизация
- category_anomaly — первая покупка «электроники» на 50 000+ рублей у клиента с типичными тратами на продукты
- gift_card_series — серия покупок gift-карт с нового устройства. Три gift-карты подряд — классика обналичивания после account takeover
Отдельный слой — поведенческая биометрия: паттерны набора текста (keystroke dynamics), движения мыши, давление и траектории свайпов на тачскрине. По данным Didit, анализ паттернов движения мыши позволяет идентифицировать ботов с точностью до 98%. Эти сигналы ловят мошенников, прошедших fingerprint-проверку через антидетект-браузер.
Граф связей устройство-IP: выявление мультиаккаунтов
Табличные признаки оценивают одну транзакцию. Но мошенники действуют кольцами (fraud rings): десятки аккаунтов, несколько устройств, общий пул IP. Для обнаружения связок нужен граф.
Граф — структура, где узлы (nodes) представляют три типа сущностей (пользователь, устройство, IP-адрес), а рёбра (edges) означают «связаны через транзакцию». Если один device_id связан с 15 пользователями, а все 15 используют одни и те же 3 IP — перед вами мультиаккаунтинг.
Для датасетов до нескольких миллионов рёбер хватит Python-библиотеки networkx. Для production-масштаба подходит Neo4j — графовая БД, которая хранит узлы и связи нативно и поддерживает запросы вида «найди все пути длиной 2 от устройства X до других пользователей».
Графовые признаки для модели:
- device_degree — количество уникальных пользователей на устройстве. Нормально: 1–2 (семья). Подозрительно: 5+
- ip_degree — количество уникальных устройств на одном IP. За CGNAT (Carrier-Grade NAT — когда мобильный оператор выпускает тысячи клиентов через один адрес) значение высокое и у легитимных пользователей. Работает только в комбинации с другими признаками
- community_size — размер компоненты связности (группа узлов, соединённых друг с другом). Fraud ring формирует плотную компоненту из 10–50 узлов
- shared_ip_ratio — доля IP, которые пользователь «делит» с аккаунтами, не связанными с ним родственными отношениями
Обучение модели: скоринг подозрительных транзакций на практике
Для задач фрод-скоринга транзакций gradient boosting (алгоритм, строящий ансамбль деревьев решений, где каждое следующее дерево исправляет ошибки предыдущего) — стандарт индустрии. LightGBM и XGBoost дают инференс за 20–40 мс (по данным bi-art) и укладываются в бюджет задержки real-time антифрод системы.
Почему не нейросеть? Для табличных данных с десятками признаков gradient boosting обычно не уступает по качеству, а инференс быстрее. И критичный бонус — объяснимость: через SHAP values (метод, показывающий вклад каждого признака в конкретное решение) можно показать регулятору или аудитору топ-5 причин блокировки. Попробуйте объяснить аудитору, почему нейросеть заблокировала транзакцию — удовольствие сомнительное.
Датасет размечен: 1 = мошенническая транзакция, 0 = легитимная. В утечке фрод-сервиса разметка косвенная: записи «карта живая, проверена» — мошеннические операции. Легитимный трафик добавляется из открытых или синтетических данных.
import lightgbm as lgb
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_auc_score
features = ['device_age_hours', 'device_card_count', 'ip_cards_24h',
'geo_velocity', 'amount_zscore', 'velocity_5min',
'device_degree', 'ip_country_bin_mismatch']
X = df[features].fillna(0)
y = df['is_fraud']
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, test_size=0.2)
model = lgb.LGBMClassifier(n_estimators=300, learning_rate=0.05, scale_pos_weight=50)
model.fit(X_train, y_train)
print(f'ROC AUC: {roc_auc_score(y_test, model.predict_proba(X_test)[:,1]):.3f}')
Что здесь происходит по шагам:
features— список признаков из предыдущих разделов.fillna(0)— заполнение пропусков нулями. В production лучше использовать медиану или отдельный бинарный флагis_missing.stratify=y— при разделении на train/test сохраняем пропорцию фрод/легитим. Это критично: фрод — редкое событие, обычно менее 1% транзакций.scale_pos_weight=50— модель «знает», что пропустить мошенничество в 50 раз дороже ложной блокировки. Параметр подбирается под реальное соотношение стоимости ошибок в конкретном бизнесе.- ROC AUC (Area Under the ROC Curve — площадь под кривой; 1.0 = идеальное разделение классов, 0.5 = случайное угадывание) — первая метрика для валидации.
На данных утечки ROC AUC выше 0.95 — не редкость, потому что фрод-паттерны выражены резко. Не обольщайтесь: в production соотношение фрод/легитим может быть 1:10 000, и модель потребует дополнительной калибровки порогов.
Модель выдаёт скор — число от 0 до 1, вероятность фрода. Пороги для принятия решений подбираются на валидационной выборке, оптимизируя cost-based метрику:
- 0.0–0.3 → APPROVE — автоматическое одобрение
- 0.3–0.7 → REVIEW — ручная проверка аналитиком
- 0.7–1.0 → DECLINE — автоматический отказ
Cost-based метрики: считаем выявление мошеннических транзакций в деньгах
ROC AUC — полезная, но абстрактная метрика. Бизнесу нужны два числа:
Precision (точность) — из всех транзакций, помеченных как фрод, какая доля реально мошенническая. Низкий precision = много ложных блокировок = клиенты уходят.
Recall (полнота) — из всех мошеннических транзакций, какую долю модель поймала. Низкий recall = пропущенный фрод = прямые убытки + chargeback.
Но главная метрика антифрода — cost-based оценка:
Стоимость ошибки = (пропущенный фрод × средний ущерб) + (ложные блокировки × стоимость потери клиента)
Конкретный пример. Средний ущерб от мошеннической транзакции — 15 000 ₽ (сумма + chargeback-комиссия 20–100 $ за кейс по правилам Visa/Mastercard). Стоимость потери клиента из-за ложной блокировки — условно 5 000 ₽. При recall=0.90 и precision=0.80 на 100 мошеннических и 10 000 легитимных транзакциях:
- Модель поймала 90 из 100 мошеннических. Пропущено 10 × 15 000 = 150 000 ₽
- При precision=0.80 модель пометила ~112 транзакций, из них 22 ложные. Потери: 22 × 5 000 = 110 000 ₽
- Итого с моделью: 260 000 ₽
Без модели: 100 × 15 000 = 1 500 000 ₽. Экономия — порядка 1 240 000 ₽. Вот так метрики превращаются в аргумент, который понимает финдиректор.
Дополнительный фактор — порог chargeback ratio. Visa VAMP с 2025 года: 0,5% — early warning, 0,9% — excessive; Mastercard ECP: 1–1,5%. Превышение запускает штрафную программу — десятки тысяч долларов ежемесячно.
Предусловия и ограничения модели
Ни одна модель не универсальна. Вот явные границы применимости.
Когда подход работает: — Датасет содержит device fingerprint с достаточной энтропией: минимум screen + OS + timezone, оптимально — canvas hash + WebGL + полный User-Agent — Есть исторические данные по IP минимум за 30 дней для построения velocity-признаков — Fraud ratio в обучающей выборке > 0.1%. При меньшем значении модель не видит паттернов, нужен oversampling (SMOTE или аналоги)
Когда подход деградирует:
— Антидетект-браузеры (Multilogin, GoLogin, Dolphin Anty) генерируют правдоподобные fingerprint’ы. По данным Plaid, fingerprint’ы можно украсть с реального устройства через malware и импортировать в антидетект-браузер. Fingerprinting как единственный метод недостаточен — нужна поведенческая биометрия
— CGNAT мобильных операторов создаёт шум в IP-признаках: ip_cards_24h будет высоким для легитимных пользователей. Решение — снижать вес IP-фичей для ASN мобильных операторов
— Региональная специфика. Фрод-паттерны в России (серии gift-карт, переводы на карты «дропов») отличаются от Юго-Восточной Азии (top-up мобильных кошельков). Модель, обученная на одном регионе, плохо переносится на другой без дообучения
— Недостаток логирования. Если события аутентификации и смены устройства не логируются на нужном уровне (OWASP A09:2021, Security Logging and Monitoring Failures), модель не получит ключевых данных. А слабая аутентификация без привязки сессии к устройству (OWASP A07:2021, Identification and Authentication Failures) делает account takeover тривиальным — и модели просто нечего ловить
Большинство антифрод-систем в production российских банков живут на статических правилах: «страна IP не совпадает с BIN — блокируем», «сумма выше 100 000 — на проверку». Эти правила писались годы назад и с тех пор обросли исключениями: «кроме VIP-клиентов», «кроме белого списка мерчантов», «кроме рабочего времени». Rule engine превращается в лоскутное одеяло из 400+ правил, которые никто не способен аудировать целиком, а false positive rate ползёт вверх — каждое новое правило латает дыру, которую оставило предыдущее.
ML-модель с признаками из трёх слоёв не решает все проблемы, но решает главную: она учитывает комбинации, которые ни один аналитик не запишет в виде if/then. Связка device_age < 2 часа + velocity > 5 за минуту + geo_velocity > 800 км/ч — точка в восьмимерном пространстве признаков, которую gradient boosting находит сам. При этом гибридный подход (статические правила для абсолютных блокировок + ML для всего остального) работает лучше чистого ML: rule engine отсекает очевидное за микросекунды, модель тратит свои 20–40 мс только на неочевидное. По данным bi-art, гибрид поднимает детекцию фрода на 30–45% относительно чистых правил и снижает false positive на 20–30%.
Неудобная правда: модель ровно настолько хороша, насколько полны данные. Если в компании не настроен сбор device fingerprint на уровне SDK и не логируется смена устройства — строить нечего. Начинайте с инструментации, не с модели. На курсе IB Basics эти пайплайны разбирают в контексте реальных инцидентов — после него связка «утечка → парсинг → фичи → модель» перестаёт казаться магией.
Эту тему и смежные навыки разбирают на практике в курсе «Антифрод-аналитик» Codeby Academy.