Как посчитать account takeover signals в SQL

Закрепи формулу account takeover signals в Карьернике
Запомнить надолго — 5 коротких сессий с задачами на эту тему. Бесплатно
Тренировать account takeover signals в Telegram

Зачем 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.

Закрепи формулу account takeover signals в Карьернике
Запомнить надолго — 5 коротких сессий с задачами на эту тему. Бесплатно
Тренировать account takeover signals в Telegram

Recovery flow

После detection:

  1. Force logout сессии
  2. Email на старую (привязанную ранее) почту
  3. Phone call confirmation
  4. 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.

Связанные темы

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, подтвердите если это вы».