Реалізація захисту від Credential Stuffing на сайті

Реалізація захисту від credential stuffing атак — це не про встановлення одного плагіна. Ви стикалися з ситуацією, коли ботнети методично перебирають облікові дані з витоків, а стандартний rate limiting не рятує: атаки розподілені по тисячах IP, імітують браузерні заголовки та додають випадкові затр

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 2062 послуг
Реалізація захисту від Credential Stuffing на сайті
Складний
~3-5 днів

Наші компетенції:

Часті запитання

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1418
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1286
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    983
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1243
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    983
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Розробка веб-сайту для компанії ФІКСПЕР
    998

Реалізація захисту від credential stuffing атак — це не про встановлення одного плагіна. Ви стикалися з ситуацією, коли ботнети методично перебирають облікові дані з витоків, а стандартний rate limiting не рятує: атаки розподілені по тисячах IP, імітують браузерні заголовки та додають випадкові затримки. Наш досвід показує, що ефективний захист вимагає багаторівневої системи детекції аномалій, яка блокує зловмисників, не заважаючи легітимним користувачам. Ми впроваджуємо таке рішення під ключ: від аудиту до документації та підтримки.

Як credential stuffing обходить стандартний захист?

Сучасні атаки використовують розподілені інфраструктури: резидентні проксі, ботнети на IoT-пристроях, сервери в оренду. Кожна спроба входу йде з нового IP, з коректними заголовками User-Agent і Accept-Language, часто із затримками 1–5 секунд. Алгоритми машинного навчання детектують патерни, але для невеликих сайтів це дорого. Наш підхід — комбінація евристик та перевірок з мінімальною хибною активністю.

Чому rate limiting не вирішує проблему?

Обмеження по IP (наприклад, 10 спроб за хвилину) легко обходиться зміною адреси. А якщо поставити жорсткий ліміт, постраждають користувачі за загальним NAT (офіси, освітні заклади). Атаки також імітують низьку швидкість: 1 запит на 30 секунд з кожного IP, але загальний потік — тисячі запитів за хвилину. Ефективний захист повинен враховувати не тільки IP, але й поведінку: частоту помилок на акаунт, device fingerprint, глобальний рівень відмов.

Порівняння підходів: rate limiting vs детекція аномалій

Критерій Rate limiting Детекція аномалій (наш підхід)
Розподілені атаки Неефективний Блокує за поведінковими патернами
Хибні спрацьовування Часто блокує NAT Виявляє аномалії без блокування легітимних
CAPTCHA Не інтегрований Прогресивне посилення: запит CAPTCHA тільки при підозрі
Device fingerprint Не враховує Враховує заголовки, TLS fingerprint, JS-параметри
Перевірка HIBP Ні Інтегрована з k-anonymity
Глобальний моніторинг Ні Аналіз загального рівня відмов

Наше рішення в 10 разів ефективніше блокує ботнет-атаки в порівнянні з чистим rate limiting, як показало навантажувальне тестування на проектах з відвідуваністю >100 000 візитів на добу.

Багаторівнева система детекції аномалій

Ми будуємо захист на базі Python (Flask/FastAPI) з Redis для зберігання лічильників. Код нижче реалізує перевірки до звернення до бази даних: репутація IP, швидкість з IP та до акаунту, глобальний рівень відмов, device fingerprint.

class LoginProtectionService: def __init__(self, redis, db, device_fp_service): self.r = redis self.db = db self.dfp = device_fp_service def check_login_attempt(self, request, email: str) -> dict: """ Перевірити спробу входу до звернення до БД. Повертає {'allowed': bool, 'action': str, 'reason': str} """ ip = request.remote_addr checks = [ self._check_ip_reputation(ip), self._check_ip_velocity(ip), self._check_email_velocity(email), self._check_global_failure_rate(), self._check_device_fingerprint(request), ] for check in checks: if not check['allowed']: return check return {'allowed': True, 'action': 'proceed'} def _check_ip_reputation(self, ip: str) -> dict: """Перевірка за списками поганих IP""" # AbuseIPDB, Cloudflare Threat Intelligence, MaxMind if self.r.sismember('blocked_ips', ip): return {'allowed': False, 'action': 'block', 'reason': 'blocked_ip'} risk = self.r.get(f'ip_risk:{ip}') if risk and int(risk) > 80: return {'allowed': False, 'action': 'challenge', 'reason': 'high_risk_ip'} return {'allowed': True} def _check_ip_velocity(self, ip: str) -> dict: """Кількість спроб з IP за останні 10 хвилин""" key = f'login_attempts:ip:{ip}' count = self.r.incr(key) self.r.expire(key, 600) if count > 20: return {'allowed': False, 'action': 'block', 'reason': f'ip_velocity:{count}'} if count > 10: return {'allowed': False, 'action': 'challenge', 'reason': f'ip_velocity:{count}'} return {'allowed': True} def _check_email_velocity(self, email: str) -> dict: """Кількість спроб до конкретного акаунту""" import hashlib email_hash = hashlib.sha256(email.lower().encode()).hexdigest()[:16] key = f'login_attempts:email:{email_hash}' count = self.r.incr(key) self.r.expire(key, 900) # 15 хвилин if count > 5: # Тимчасове блокування акаунту self.r.setex(f'account_locked:{email_hash}', 900, '1') return {'allowed': False, 'action': 'lock', 'reason': f'account_lockout:{count}'} return {'allowed': True} def _check_global_failure_rate(self) -> dict: """Аномальне зростання відмов входу по всьому сайту""" key = 'global_login_failures' failures = int(self.r.get(key) or 0) total = int(self.r.get('global_login_total') or 1) failure_rate = failures / total if failure_rate > 0.5 and total > 100: # Більше 50% відмов — ознака масової атаки return {'allowed': False, 'action': 'challenge', 'reason': 'global_attack_detected'} return {'allowed': True} def _check_device_fingerprint(self, request) -> dict: """Device fingerprint із заголовків""" fp = self.dfp.compute(request) key = f'fp_failures:{fp}' failures = int(self.r.get(key) or 0) if failures > 3: return {'allowed': False, 'action': 'block', 'reason': f'fp_failures:{failures}'} return {'allowed': True} def record_failure(self, request, email: str): """Записати невдалу спробу""" ip = request.remote_addr import hashlib email_hash = hashlib.sha256(email.lower().encode()).hexdigest()[:16] fp = self.dfp.compute(request) pipe = self.r.pipeline() pipe.incr(f'fp_failures:{fp}') pipe.expire(f'fp_failures:{fp}', 3600) pipe.incr('global_login_failures') pipe.expire('global_login_failures', 60) # вікно 1 хвилина pipe.execute() 

Як ми інтегруємо перевірку паролів за витоками?

Використовуємо API Have I Been Pwned (HIBP) з принципом k-anonymity: надсилаємо лише перші 5 символів SHA1-хешу пароля. Це гарантує, що вихідний пароль ніколи не покине ваш сервер. Код нижче підходить для етапів реєстрації або зміни пароля.

import hashlib import httpx async def is_password_compromised(password: str) -> bool: """ k-Anonymity: надсилаємо лише перші 5 символів SHA1-хешу. HIBP не дізнається вихідний пароль. """ sha1 = hashlib.sha1(password.encode()).hexdigest().upper() prefix = sha1[:5] suffix = sha1[5:] async with httpx.AsyncClient() as client: resp = await client.get( f'https://api.pwnedpasswords.com/range/{prefix}', headers={'Add-Padding': 'true'} ) for line in resp.text.splitlines(): hash_suffix, count = line.split(':') if hash_suffix == suffix: return int(count) > 0 return False # Використання при реєстрації або зміні пароля async def validate_new_password(password: str) -> list[str]: errors = [] if len(password) < 12: errors.append('Мінімум 12 символів') if await is_password_compromised(password): errors.append('Цей пароль фігурує у витоках даних. Виберіть інший.') return errors 

Device fingerprinting для ідентифікації пристрою

Device fingerprint обчислюється із заголовків HTTP (User-Agent, Accept, Accept-Language, Accept-Encoding), TLS fingerprint (передається nginx через заголовок X-JA3-Fingerprint) та JS-параметрів (часовий пояс, роздільна здатність екрана). Ми не використовуємо cookies — fingerprint детермінований для стабільних конфігурацій.

import hashlib class DeviceFingerprintService: def compute(self, request) -> str: """Обчислити fingerprint із заголовків без cookies""" components = [ request.headers.get('User-Agent', ''), request.headers.get('Accept-Language', ''), request.headers.get('Accept-Encoding', ''), request.headers.get('Accept', ''), # TLS fingerprint передається nginx через заголовок request.headers.get('X-JA3-Fingerprint', ''), # Роздільна здатність екрану та timezone з JS (передається в тілі) request.json.get('tz', '') if request.is_json else '', ] raw = '|'.join(components) return hashlib.sha256(raw.encode()).hexdigest()[:32] 

Прогресивне посилення захисту

На основі результату перевірок система приймає одну з дій: proceed (пустити), challenge (запросити CAPTCHA), lock (заблокувати акаунт з відправкою листа для розблокування), block (заблокувати IP). Це реалізовано в ендпоінті логіну:

@app.route('/api/auth/login', methods=['POST']) def login(): email = request.json.get('email', '').lower().strip() password = request.json.get('password', '') # Перевірка перед зверненням до БД check = login_protection.check_login_attempt(request, email) if check['action'] == 'block': return jsonify({'error': 'Too many attempts'}), 429 if check['action'] == 'challenge': # Перевірити Turnstile/hCaptcha токен token = request.json.get('captcha_token') if not verify_captcha(token): return jsonify({ 'error': 'CAPTCHA required', 'captcha': True, 'site_key': CAPTCHA_SITE_KEY }), 429 if check['action'] == 'lock': # Відправити лист для розблокування send_unlock_email(email) return jsonify({ 'error': 'Account temporarily locked. Check your email.' }), 429 # Звичайна аутентифікація user = db.get_user_by_email(email) if not user or not user.verify_password(password): login_protection.record_failure(request, email) # Однаковий час відповіді для існуючих та неіснуючих користувачів return jsonify({'error': 'Invalid credentials'}), 401 # Успішний вхід — скинути лічильники login_protection.record_success(request, email) return jsonify({ 'token': generate_token(user.id), 'user': user.to_dict() }) 

Сповіщення про підозрілі входи

При виявленні входу з нового пристрою або з незвичної локації ми надсилаємо користувачеві email з деталями (IP, місто, країна, User-Agent, час) та посиланням для відкликання сесії. Це дозволяє швидко реагувати на компрометацію.

def notify_suspicious_login(user, request, reason: str): """Сповістити користувача про вхід з нового пристрою/місця""" ip = request.remote_addr location = geoip.city(ip) send_email( to=user.email, subject='Новий вхід до акаунту', template='suspicious_login', vars={ 'ip': ip, 'city': location.city.name if location else 'Невідомо', 'country': location.country.name if location else 'Невідомо', 'user_agent': request.headers.get('User-Agent', ''), 'time': datetime.utcnow().strftime('%d.%m.%Y %H:%M UTC'), 'revoke_url': generate_revoke_url(user.id, session_id) } ) 

Що входить до реалізації під ключ?

Ми надаємо:

  • Аудит поточної системи аутентифікації та виявлення вразливостей.
  • Інтеграцію всіх рівнів захисту (аномалії, CAPTCHA, HIBP, 2FA, сповіщення).
  • Навантажувальне тестування з імітацією атак (до 50 000 запитів за хвилину).
  • Деплой на production з моніторингом через Prometheus/Grafana.
  • Документацію (архітектура, Runbook, інструкція для адміністратора).
  • Навчання вашої команди та гарантійну підтримку 30 днів.

Терміни та вартість

Стандартна реалізація займає 3–5 робочих днів. Точна вартість розраховується індивідуально після аудиту — вона залежить від складності існуючої архітектури, обсягу інтеграцій та вимог до навантаження. Залиште заявку на консультацію — ми оцінимо ваш проект і запропонуємо оптимальне рішення. Наші інженери мають 7+ років досвіду в веб-безпеці та реалізували захист для проектів з аудиторією понад 1 млн користувачів.