Как посчитать account takeover signals в SQL
Содержание:
Зачем ATO detection
Account takeover (ATO) — атакующий получил доступ к аккаунту через credential stuffing, phishing, dark web leak. Внутри аккаунта он меняет email/phone (чтобы recovery шло на него), добавляет card, выводит средства. Чем быстрее заметить, тем меньше потери.
Ключевые сигналы
Самые сильные:
- login с нового device + new IP + new country одновременно
- смена email сразу после login
- смена password + смена email в течение 5 минут
- добавление новой payment method в первые 24 часа после login
- большая транзакция сразу после login с нового device
- удаление 2FA
ATO score в SQL
WITH login_events AS (
SELECT
user_id,
login_timestamp,
device_id,
ip,
country,
EXISTS (SELECT 1 FROM user_devices WHERE user_id = login.user_id AND device_id = login.device_id) AS known_device,
EXISTS (SELECT 1 FROM user_ips WHERE user_id = login.user_id AND ip = login.ip) AS known_ip
FROM login_events login
WHERE login_timestamp >= NOW() - INTERVAL '24 hours'
),
post_login_actions AS (
SELECT
l.user_id,
l.login_timestamp,
EXISTS (SELECT 1 FROM email_changes WHERE user_id = l.user_id
AND changed_at BETWEEN l.login_timestamp AND l.login_timestamp + INTERVAL '10 minutes') AS email_changed,
EXISTS (SELECT 1 FROM password_changes WHERE user_id = l.user_id
AND changed_at BETWEEN l.login_timestamp AND l.login_timestamp + INTERVAL '10 minutes') AS password_changed,
EXISTS (SELECT 1 FROM new_payment_methods WHERE user_id = l.user_id
AND added_at BETWEEN l.login_timestamp AND l.login_timestamp + INTERVAL '1 hour') AS new_card,
EXISTS (SELECT 1 FROM tfa_changes WHERE user_id = l.user_id
AND action = 'disabled'
AND changed_at BETWEEN l.login_timestamp AND l.login_timestamp + INTERVAL '30 minutes') AS tfa_disabled
FROM login_events l
)
SELECT
user_id,
login_timestamp,
(CASE WHEN NOT known_device THEN 20 ELSE 0 END) +
(CASE WHEN NOT known_ip THEN 15 ELSE 0 END) +
(CASE WHEN email_changed THEN 30 ELSE 0 END) +
(CASE WHEN password_changed AND email_changed THEN 25 ELSE 0 END) +
(CASE WHEN new_card THEN 20 ELSE 0 END) +
(CASE WHEN tfa_disabled THEN 40 ELSE 0 END) AS ato_score
FROM login_events
JOIN post_login_actions USING (user_id, login_timestamp);Score 50+ = high probability ATO. Действие: lock account, send recovery email.
Окно после signal
ATO часто сжатый в time: атакующий быстро меняет recovery info. Окно 10-30 минут после login — критическое:
SELECT
user_id,
COUNT(*) AS critical_actions_in_30_min
FROM (
SELECT user_id, changed_at AS event FROM email_changes
UNION ALL SELECT user_id, changed_at FROM password_changes
UNION ALL SELECT user_id, added_at FROM new_payment_methods
UNION ALL SELECT user_id, changed_at FROM tfa_changes WHERE action = 'disabled'
) actions
WHERE event >= NOW() - INTERVAL '30 minutes'
GROUP BY user_id
HAVING COUNT(*) >= 3
ORDER BY critical_actions_in_30_min DESC;3+ critical actions за 30 мин = почти точно ATO.
Recovery flow
После detection:
- Force logout сессии
- Email на старую (привязанную ранее) почту
- Phone call confirmation
- 24-48h hold на крупных транзакциях
SELECT
user_id,
ato_score,
CASE
WHEN ato_score >= 60 THEN 'force_logout_and_call'
WHEN ato_score >= 30 THEN 'email_confirmation'
ELSE 'monitor'
END AS action
FROM ato_scoring
WHERE ato_score >= 30;Частые ошибки
Ошибка 1. Считать new device sole signal. Юзер купил новый phone — тоже new device. Без других signals — false positive.
Ошибка 2. Игнорировать tfa changes. TFA disable — strongest ATO signal. Wage высокий.
Ошибка 3. Slow detection window. Если check каждые 6 часов — атакующий уже всё сделал. Real-time мониторинг.
Ошибка 4. Block без recovery flow. Force logout без notify = легитимный customer не сможет вернуться.
Ошибка 5. Не обучаться на confirmed ATO. Каждый confirmed case → update веса signals. Continuous learning.
Связанные темы
- Как посчитать fraud score в SQL
- Как посчитать velocity check в SQL
- Как посчитать device fingerprinting в SQL
- Как посчитать IP velocity в SQL
FAQ
Каков ATO rate?
В B2C SaaS: 0.01-0.1% accounts per year. В finance — выше.
TFA — единственная защита?
Strongest. Но phishing-resistant TFA (WebAuthn, hardware key) лучше SMS.
Recovery email на новую почту?
Никогда. Только на старую (привязанную минимум 30 дней).
Можно ли auto-lock?
При очень high score (80+) — да. Иначе manual review.
Уведомлять клиента?
Да — на старую почту: «попытка изменить email, подтвердите если это вы».