5 глупых ошибок сайтов, из-за которых утекают твои данные
Привет! Я баг-хантер, и за несколько месяцев работы я видел такое, что хочется то ли плакать, то ли смеяться. Разработчики делают ошибки, которые настолько очевидны, что мне стыдно за них. Буквально: один параметр в URL, одна забытая проверка - и вся база пользователей течёт как из дырявого ведра.
Сегодня расскажу про пять самых тупых, но самых распространённых ошибок, которые я нахожу снова и снова. Это не какие-то сложные 0-day уязвимости - это базовые косяки, которых можно избежать за 10 минут работы. Но их не избегают. И твои данные утекают. 💀
Если ты разработчик - проверь свой код прямо сейчас. Если обычный пользователь - узнаешь, как тебя сливают. Поехали! 🚀
Ошибка #1: IDOR — "А давайте не будем проверять права доступа!"
Что это такое:
IDOR (Insecure Direct Object Reference) - это когда сайт не проверяет, имеешь ли ты право видеть запрошенные данные. Меняешь цифру в URL — получаешь доступ к чужому профилю, заказу, документу.
Как это выглядит:
Ты заходишь в свой профиль: site.ru/profile?user_id=123Меняешь на user_id=124 - видишь чужой профиль со всеми данными.
Или открываешь свой заказ: shop.ru/order?id=5001Меняешь на id=5002 - видишь чужой заказ с адресом доставки, телефоном, ФИО.
Почему это происходит:
Разработчик подумал: "Ну никто же не догадается менять цифры в URL!" Догадаются, чувак. Я догадываюсь каждый раз. 🤦
Мой реальный кейс:
Проверял сайт интернет-магазина электроники (сеть по всей России). Оформил заказ, получил ссылку на отслеживание: site.ru/track?order_id=47853
Из любопытства изменил последнюю цифру на 47854. Бац - чужой заказ! Вижу:
- ФИО покупателя
- Полный адрес доставки
- Номер телефона
- Состав заказа (два iPhone 15 Pro)
- Время доставки
Я попробовал ещё несколько ID - все открываются! База из тысяч заказов с личными данными - доступна любому.
Зарепортил. Они пофиксили за 2 дня - добавили проверку, что order_id принадлежит текущему пользователю. Буквально 5 строк кода. А до этого слили всю базу клиентов. 😱
Как проверить себя:
🔍 Зайди в свой профиль/заказ/документ
🔍 Посмотри на URL - есть там id=, user_id=, order=?
🔍 Измени цифру на соседнюю
🔍 Видишь чужие данные? IDOR подтверждён!
Что утекает:
- Личные данные пользователей (имя, email, телефон, адрес)
- История заказов
- Медицинские карты (да, я такое находил!)
- Финансовые документы
- Переписки и сообщения
Почему это тупо:
Потому что фикс занимает 5 минут! Проверь на backend: if (order.user_id != current_user.id) return 403. Всё! Но нет, это "потом добавим".
Ошибка #2: API без авторизации — "Зачем проверять токены?"
Что это такое:
Сайт имеет API (для мобильного приложения или внутренних целей), но забыл закрыть его авторизацией. Любой может слать запросы и получать данные.
Как это выглядит:
Открываешь DevTools (F12), смотришь запросы. Видишь:
text
GET https://site.ru/api/v1/users/list Response: [{"id":1, "name":"Иван", "email":"ivan@mail.ru", "phone":"+7999..."}, ...]
Копируешь URL в браузер - работает! Без логина, без токена, без ничего. Просто берёшь и скачиваешь всю базу пользователей. 🎁
Почему это происходит:
API делали для мобильного приложения. "Это же внутренний endpoint, его никто не найдёт!" Я найду. Я всегда нахожу.
Мой легендарный случай:
Крупный образовательный портал (не буду светить, но они в топ-5 по России). Тестировал их сайт, открыл Network в DevTools.
Вижу запрос: https://portal.ru/api/students/export?format=json
Копирую URL, открываю в новой вкладке. И что я вижу? JSON-файл с данными 50,000+ студентов:
[
{
"id": 1,
"full_name": "Иванов Иван Иванович",
"email": "ivanov@example.com",
"phone": "+79991234567",
"birth_date": "2005-03-15",
"address": "г. Москва, ул. Ленина, д. 10, кв. 5",
"course": "Backend разработка",
"payment_status": "paid"
},
...
]
Никакой авторизации! Никаких токенов! Просто открытый endpoint, который возвращает ВСЮ базу студентов с персональными данными!
Представляешь, сколько времени этот endpoint висел открытым? Может, месяцы? Может, кто-то уже слил эти данные и продал? Страшно подумать. 😨
Как проверить:
🔍 Открой DevTools → Network
🔍 Поищи запросы к /api/🔍 Скопируй URL любого запроса
🔍 Открой в режиме инкогнито (без твоих cookies)
🔍 Работает? API не защищён!
Что утекает:
- База пользователей целиком
- Финансовые данные
- Внутренняя статистика
- Админские функции (если API позволяет POST/DELETE)
Почему это тупо:
Потому что авторизация API - это база основ! Middleware с проверкой JWT-токена - 10 строк кода. Но "некогда было, дедлайн горел".
Ошибка #3: Пароли в открытом виде — "Зачем нам шифрование?"
Что это такое:
Сайт хранит пароли в базе данных открытым текстом или использует слабое шифрование (MD5 без соли, SHA1). При утечке БД все пароли сразу известны.
Как это обнаруживается:
Обычно при утечке базы данных или через функцию "Восстановить пароль". Если сайт присылает тебе твой старый пароль на email - значит, он его знает. Значит, хранит открытым. 🚨
Почему это происходит:
"Зачем усложнять? Просто сохраним пароль как есть!" Или: "MD5 же тоже хеш, пойдёт". Нет, не пойдёт. MD5 взламывается мгновенно.
Мой случай (не совсем баг-хантинг, но показательно):
Регистрировался на сайте онлайн-курсов. Придумал сложный пароль: Kz8#mP2$qL9@wX4!. Через 10 минут получаю email:
Добро пожаловать!
Ваш логин: myemail@mail.ru
Ваш пароль: Kz8#mP2$qL9@wX4!
Я в шоке. Они ОТПРАВИЛИ МНЕ ПАРОЛЬ НА EMAIL! Значит:
- Они хранят пароли открытым текстом
- Их база данных - это склад паролей для хакеров
- При утечке - все пароли компрометированы
Я сразу удалил аккаунт и написал им гневное письмо. Ответили: "Мы так делаем для удобства пользователей". Удобство? СЕРЬЁЗНО? 🤬
Правильный подход:
Пароли нужно хешировать с солью алгоритмом bcrypt, argon2 или минимум PBKDF2. При восстановлении пароля присылать ТОКЕН для создания НОВОГО пароля, а не старый пароль.
Как проверить:
🔍 Используй функцию "Забыли пароль?"
🔍 Если сайт прислал твой СТАРЫЙ пароль — беги оттуда
🔍 Если прислал ссылку для создания нового — норм
Что утекает при взломе БД:
- Все пароли пользователей
- Доступ к их аккаунтам на других сайтах (если пароли одинаковые)
- Возможность credential stuffing атак
Почему это тупо:
Это 2025 год! Хеширование паролей - это стандарт безопасности с 1990-х! Не делать этого - это как строить дом без фундамента.
Ошибка #4: Отсутствие Rate Limiting — "Пусть хоть миллион раз попробует!"
Что это такое:
Сайт не ограничивает количество попыток выполнить действие. Можно пробовать пароли, коды подтверждения, промокоды - хоть миллион раз подряд.
Как это выглядит:
Форма логина позволяет пробовать пароли бесконечно. Или форма ввода SMS-кода позволяет перебирать все 10,000 комбинаций (0000-9999).
Почему это происходит:
"Ну какова вероятность, что кто-то будет перебирать?" Высокая. Я перебираю постоянно.
Мой жёсткий кейс:
Тестировал сайт доставки еды. При заказе нужно подтвердить телефон - вводишь номер, приходит 4-значный SMS-код.
Я проверил - нет rate limiting! Можно отправлять запросы с разными кодами бесконечно. Написал простой скрипт:
for code in range(0000, 10000):
response = requests.post(url, json={"phone": "+79991234567", "code": str(code).zfill(4)})
if "success" in response.text:
print(f"Код найден: {code}")
break
Запустил. За 3 минуты перебрал все 10,000 комбинаций и нашёл правильный код. Я получил доступ к чужому аккаунту, не имея доступа к его телефону!
Ещё один пример:
Сайт с промокодами. Промокоды типа SALE2025, NEWYEAR, DISCOUNT. Я написал скрипт, который перебирает популярные слова и комбинации.
За час нашёл рабочие промокоды на скидку 50%, 70%, даже 100% (бесплатная доставка + товар). Сайт не ограничивал попытки, промокоды были простые и предсказуемые.
Зарепортил. Они поняли, что так делать нельзя. Сделали rate limiting и усложнили промокоды (теперь случайные буквы/цифры).
Как проверить:
🔍 Найди форму с подтверждением (SMS-код, пароль, промокод)
🔍 Попробуй ввести неправильные данные 10-20 раз подряд
🔍 Если форма не блокируется - rate limiting отсутствует
Что утекает:
- Доступ к аккаунтам через перебор SMS-кодов
- Взлом паролей через brute force
- Бесплатные промокоды и скидки
- Массовая регистрация ботов
Почему это тупо:
Rate limiting - это одна middleware функция! Библиотеки есть для любого языка/фреймворка. Не добавить это - преступная халатность.
Ошибка #5: Verbose Error Messages — "Давайте расскажем хакеру всё!"
Что это такое:
Сайт выдаёт детальные сообщения об ошибках, которые помогают хакеру понять структуру системы и найти уязвимости.
Как это выглядит:
Пробуешь SQL-инъекцию, и сайт отвечает:
MySQL Error: You have an error in your SQL syntax near 'SELECT * FROM users WHERE id='5'' at line 1
Query: SELECT * FROM users WHERE id='5' LIMIT 1
File: /var/www/html/controllers/UserController.php, line 47
Или вводишь несуществующий email при логине:
Error: User with email 'test@example.com' not found in database
А существующий:
Error: Invalid password for user 'real@example.com'
Теперь хакер знает, какие email'ы есть в базе, а какие нет. Можно составить список реальных пользователей.
Почему это происходит:
Debug-режим забыли выключить на продакшене. "Нам же удобно видеть ошибки!" Да, и хакерам тоже удобно.
Мой кейс:
Тестировал банковский сервис (микрозаймы). Попробовал SQL-инъекцию в параметре поиска. Получил:
Database Error:
SQLSTATE[42000]: Syntax error or access violation: 1064
You have an error in your SQL syntax;
Query: SELECT * FROM clients WHERE phone LIKE '%+7999%' AND status='active'
Database: production_db
Host: 10.0.5.23
User: db_admin
Это ЗОЛОТО для хакера! Я узнал:
- Название базы данных:
production_db - Внутренний IP:
10.0.5.23 - Username для БД:
db_admin - Структуру SQL-запроса
- Названия таблиц и колонок
Правильный подход:
Пользователю показывать: Something went wrong. Please try again later.
В логи писать: детальную ошибку, стек трейс, все параметры - но только в логи, недоступные извне.
Как проверить:
🔍 Попробуй намеренно вызвать ошибку (несуществующая страница, некорректные данные в форме)
🔍 Смотри, что сайт отвечает
🔍 Если видишь SQL-запросы, пути к файлам, стек трейсы - verbose errors включены
Что утекает:
- Структура базы данных
- Пути к файлам на сервере
- Используемые технологии и версии
- Внутренние IP-адреса
- Список реальных пользователей
Почему это тупо:
Потому что это одна строка в конфиге: DEBUG = False. Одна. Строка. Но её забывают менять. Каждый. Раз.
Бонус: Что делать, если твои данные уже утекли?
Окей, ты прочитал про все эти ошибки. Возможно, сайты, которыми ты пользуешься, имеют эти косяки. Что делать?
Проверь, утекали ли твои данные:
🔍 Зайди на haveibeenpwned.com
🔍 Введи свой email
🔍 Посмотри, в каких утечках он засветился
У меня, например, 12 утечек. Из них 5 - российские сайты. LinkedIn, Adobe, старые форумы... Грустно, но такова реальность.
Что делать после обнаружения утечки:
✅ Смени пароли на всех сайтах, где использовал этот email
✅ Используй менеджер паролей (Bitwarden, 1Password)
✅ Включи 2FA везде, где возможно
✅ Мониторь свои банковские карты на подозрительные операции
✅ Будь бдителен к фишингу (утекшие данные используют для таргетированных атак)
Заключение (мои мысли после сотен проверок)
Я нашёл эти ошибки в десятках, нет, сотнях сайтов. От небольших интернет-магазинов до федеральных порталов. Большие, маленькие, известные, неизвестные - все косячат.
И знаешь, что меня бесит больше всего? Это всё легко фиксится!
- IDOR - добавить проверку прав доступа (5 минут)
- Незащищённое API - добавить middleware с авторизацией (10 минут)
- Пароли открытым текстом - использовать bcrypt (1 час на рефакторинг)
- Отсутствие rate limiting - подключить библиотеку (15 минут)
- Verbose errors -
DEBUG = False(10 секунд!)
Но нет. "Потом сделаем", "Некогда", "Работает же". А потом утечка, штраф от Роскомнадзора, репутация в помойке.
Если ты разработчик - проверь свой код прямо сейчас. Серьёзно. Отложи всё и проверь эти пять пунктов. Это важнее новых фич.
Если ты обычный пользователь - будь бдителен. Используй сложные уникальные пароли, включай 2FA, проверяйся на haveibeenpwned. Твои данные - твоя ответственность.
А я продолжу искать эти тупые ошибки. Пока разработчики их делают - я буду зарабатывать. И честно говоря, работы мне хватит на всю жизнь. 😅🔥
