«Выходишь такой в интернет… и случайно находишь платежку. Welcome to ops.»
Привет, Habr.
В этом посте расскажу, как в ходе обычного неторопливого пентеста инфраструктуры я набрёл на Redis-сервер. И не просто Redis — а такой, что прямо хочется написать админам: «Ребята, вы серьёзно?»
Спойлер: без пароля, с 1200 ключами, среди которых — и курсы валют, и цены на туры, и... полностью валидная платёжная конфигурация.
Открытый порт 6379 оказался настоящей Pandora’s box.
Предыстория: на охоте
Как это часто бывает — сканишь себе диапазон через masscan
, смотришь на 6379 порт, и… ну вы поняли.
redis-cli -h <ip> -p 6379 --no-auth-warning
redis-cli -h <ip> -p 6379 --no-auth-warning
Подключение — без проблем.
Пароля нет.
Сервер бодро отвечает, работает 6 дней, Redis 8.0.1.
— Ну да, обычный кэш, подумаешь…
Но когда DBSIZE
возвращает 1202 ключа, а KEYS *
выдаёт реальные данные — понимаешь, что это уже совсем другая история.
Что внутри?
«Если бы я получал биткойн за каждый
getMinProductPrice::*
, я бы уже не писал этот пост.»
Расклад по категориям:
WebRequest кэш — 89%
Прям видно, что используется активно — ключи типаfindDestinationDetail::*
,OAuth::*
Бизнес-данные — 10–11%
Там уже интереснее: цены, конвертация валют, продукты, партнёрские данныеКонфиги — 1–2 ключа
И эти 1–2 ключа решают ВСЁ
Один из конфигурационных ключей выглядел как vposConfig::...
Я, конечно, не сразу поверил глазам, но там был полноценный JSON с конфигом платёжного шлюза.
json{
"name": "example",
"merchantId": "xxxxxxxx",
"apiUser": "test@...com",
"apiPassword": "S\\CsCccCcCc",
"encryptKey": "eY0test...",
"currencies": ["EUR", "GBP", "RUB", "USD", "TRY"],
"country": "TR"
}
? Креды к боевому платёжному шлюзу. API-пользователь, пароль, ключ шифрования. Всё по-честному.
«Если это не критикал, то что тогда?»
Что ещё попалось?
Цены на туры:
Видна и базовая стоимость, и финальная с наценкой. Можно изучать бизнес-логику, если ты вдруг конкурент.Курсы валют:
Прямо из Redis — 50 EUR = 57.41 USD. Курс свежий.Партнёрские города и направления:
JSON'ы вроде"name": "Paris", "secondaryId": 2378
— просто набор ID-шников, но тоже интересно.Языковая аналитика:
Судя по ключам, чаще всего юзали сайт на русском, турецком и немецком.
(— Привет, наши из СНГ!)
Риски
1. Платёжная компрометация
Можно обращаться к API, совершать транзакции, тестить фрод — не будем.
2. PCI DSS violation
Передача кредов в незашифрованном виде?
✔️ Нарушено.
✔️ Проблемы с банком.
✔️ Штрафы.
3. Утечка бизнес-логики
Цены, конвертация, внутренние шаблоны API — бери и строй конкурента.
Почему это произошло?
«Redis по умолчанию — как холодильник на даче. Ты надеешься, что его никто не найдёт, но его найдут. И съедят всю колбасу.»
Redis слушал порт 6379 на внешнем интерфейсе
Не было пароля (
requirepass
)Нет firewall или access list
Сервер жив в интернете 6+ дней
Что делать?
Если вы админ (или DevOps, или CTO, или просто добрый человек с доступом к docker-compose
), вот мини-чеклист:
❌ Не слушайте Redis на 0.0.0.0
? Всегда используйте
requirepass
? Ограничьте IP-фильтрами (iptables, ufw)
? Оберните Redis в VPN или защитную прослойку
? Делайте регулярный аудит доступных портов
Мораль
Открытый Redis — это не просто баг. Это возможность.
В руках атакующего — это прямая дорога к деньгам, данным и репутационным потерям.
«Если бы я был злым, этот кейс закончился бы совсем иначе. Но, к счастью, я молодняк, ищущий признания в этом мире.»
СПОЙЛЕР: Все данные я поменял, хочется донести суть 0day бизнес логики, а не скомпрометированные данные + отписал сервису об их уязвимости.