13 вересня 2024 року о 23:58 наш сервер зазнав ransomware атаки. Ось історія того, як ми відновили систему і створили автоматизований startup процес, щоб це більше не повторилося.
Пролог: “Ваші дані захоплені”
Все почалося досить банально. Ранковий огляд системи показав, що база даних file_storage нашого Telegram API проекту зникла. Замість неї з’явилася підозріла база RECOVER_YOUR_DATA з єдиною таблицею, що містила повідомлення:
|
1 2 3 4 |
All your data is backed up. You must pay 0.0073 BTC to bc1qqfdgxchp5egwg6u70p3wz74x8tjpjssgzsuvsf In 48 hours, your data will be publicly disclosed and deleted. Your DBCODE is: 27PZE |
Типовий ransomware. Сума не велика (~$430), але принцип важливий – ми не платимо викупи.
Анатомія атаки
Як це сталося?
Швидка діагностика показала корінь проблеми:
|
1 2 3 |
# Перевірка відкритих портів docker ps --format "table {{.Names}}\t{{.Ports}}" |
Результат був невтішним – MySQL порт 3306 був відкритий назовні через конфігурацію Docker Compose:
|
1 2 3 4 |
mysql: ports: - "3306:3306" # 💀 Небезпека! |
Docker за замовчуванням обходить ufw firewall, роблячи MySQL доступним з інтернету. Поєднання з слабким паролем secret дало зловмисникам прямий доступ до бази.
Часова лінія атаки
Аналіз логів MySQL показав точну хронологію:
|
1 2 3 4 |
# Час створення ransomware файлів docker exec mysql_container ls -la /var/lib/mysql/RECOVER_YOUR_DATA/ # Результат: 13 Sep 2024 23:58 |
Атака була швидкою і цільовою – зловмисники точно знали що робити.
Процес відновлення
Крок 1: Діагностика втрат
Перше питання – що втрачено? Перевірка показала:
|
1 2 3 4 |
docker exec mysql_container mysql -u root -p -e "SHOW DATABASES;" # file_storage - ВІДСУТНЯ ❌ # RECOVER_YOUR_DATA - ПРИСУТНЯ ⚠️ |
Дані проекту зникли, але структура системи залишилася неушкодженою.
Крок 2: Аналіз безпеки
|
1 2 3 4 5 6 7 8 9 |
# Перевірка процесів ps aux | grep -E "(kinsing|mining|crypto|xmrig|masscan)" # Перевірка SSH логів sudo journalctl -u ssh --since "yesterday" | grep -E "(Failed|Invalid)" # Пошук підозрілих файлів find /tmp /var/tmp -type f -mtime -3 2>/dev/null |
На щастя, атака була обмежена лише MySQL – системного компрометування не виявлено.
Крок 3: Очищення та закриття уразливостей
|
1 2 3 4 5 6 7 8 9 10 |
# Видалення ransomware бази docker exec mysql_container mysql -u root -p -e "DROP DATABASE RECOVER_YOUR_DATA;" # Закриття небезпечного порту # В docker-compose.yml: mysql: # ports: - "3306:3306" # ВИДАЛЕНО networks: - app-network # Тільки внутрішня мережа |
Крок 4: Відновлення даних
Без бекапів довелося відновлювати структуру з нуля:
|
1 2 3 4 5 6 7 8 9 |
# Створення нової бази docker exec mysql_container mysql -u root -p -e " CREATE DATABASE file_storage CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; GRANT ALL PRIVILEGES ON file_storage.* TO 'user'@'%'; " # Відновлення структури Laravel docker exec php_container php artisan migrate --force |
Народження автоматизованого рішення
Після відновлення стало зрозуміло – треба автоматизувати процес, щоб уникнути подібних проблем в майбутньому.
Принципи нового startup скрипта
- Перевірка безпеки – автоматичне виявлення відкритих портів
- Генерація стійких паролів – ніяких
secretабоpassword - Автоматичне відновлення – створення баз та користувачів
- Валідація конфігурації – перевірка .env файлів
Архітектура рішення
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
#!/bin/bash # telegram-api-start.sh # 1. Перевірка системних вимог check_requirements() { # Docker, файли проекту, права доступу } # 2. Генерація безпечних паролів generate_passwords() { NEW_ROOT_PASSWORD=$(openssl rand -base64 32) NEW_DB_PASSWORD=$(openssl rand -base64 24) } # 3. Налаштування мереж Docker setup_networks() { # shared_network, web для Traefik } # 4. Ініціалізація бази даних init_database() { # Створення користувачів, перевірка підключень } # 5. Запуск та валідація Laravel init_laravel() { # Міграції, APP_KEY, кеш } |
Особливості реалізації
Генерація паролів:
|
1 2 3 4 5 6 7 8 9 10 |
# Криптографічно стійкі паролі NEW_ROOT_PASSWORD=$(openssl rand -base64 32) NEW_DB_PASSWORD=$(openssl rand -base64 24) # Автоматичне оновлення .env файлів cat > .env << EOF DB_ROOT_PASSWORD=$NEW_ROOT_PASSWORD DB_PASSWORD=$NEW_DB_PASSWORD EOF |
Перевірка безпеки:
|
1 2 3 4 5 6 7 8 |
# Виявлення відкритих портів docker ps --format "table {{.Names}}\t{{.Ports}}" | grep -E "0.0.0.0.*3306" && log_warning "MySQL порт відкритий назовні!" # Сканування слабких паролів grep -E "(secret|password|123)" .env && log_warning "Знайдено слабкі паролі!" |
Автоматичне відновлення:
|
1 2 3 4 5 6 7 8 9 |
# Створення бази якщо відсутня db_exists=$(docker exec mysql_container mysql -u root -p"$PASSWORD" \ -e "SHOW DATABASES LIKE 'file_storage';" | grep -c "file_storage") if [[ $db_exists -eq 0 ]]; then create_database run_migrations fi |
Результати автоматизації
Переваги нового підходу
До автоматизації:
- Ручне налаштування 30+ команд
- Слабкі паролі за замовчуванням
- Відсутність перевірок безпеки
- Час розгортання: 2+ години
Після автоматизації:
- Одна команда:
./telegram-api-start.sh - Автогенерація стійких паролів
- Вбудовані перевірки безпеки
- Час розгортання: 5 хвилин
Структура проекту
|
1 2 3 4 5 6 7 |
├── telegram-api-start.sh # Головний startup скрипт ├── start # Традиційний скрипт з перевірками ├── update-passwords.sh # Оновлення паролів ├── telegram-help.sh # Довідка команд ├── recovery.sh # Швидке відновлення після атак └── README-START-TELEGRAM-API.md # Повна документація |
Приклад використання
|
1 2 3 4 5 6 7 8 9 10 11 12 |
# Перший запуск або після атаки ./telegram-api-start.sh # Звичайний запуск з перевірками ./start 83 # Перевірка безпеки ./start 83 check # Оновлення паролів ./update-passwords.sh |
Уроки безпеки
Головні помилки
- Відкриті порти баз даних – найчастіша причина компрометації
- Слабкі паролі за замовчуванням –
secret,password,123456 - Відсутність моніторингу – атака могла тривати годинами непоміченою
- Недостатні бекапи – автоматичні бекапи могли б врятувати дані
Рекомендації
Docker безпека:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
# ❌ Неправильно mysql: ports: - "3306:3306" # ✅ Правильно mysql: expose: - "3306" networks: - internal-network |
Сильні паролі:
|
1 2 3 4 5 6 |
# Генерація openssl rand -base64 32 # Зберігання в .env DB_ROOT_PASSWORD=K8mN2pQ7vR5xS9wT4uY6iO1eA3sD8fG0hJ2kL5nM7pQ9rT1vW3xZ5bC7eF9gH2jK |
Мережева безпека:
|
1 2 3 4 5 6 7 8 |
# Firewall конфігурація sudo ufw enable sudo ufw deny 3306 sudo ufw allow 22,80,443 # Docker повинен поважати firewall echo '{"iptables": false}' | sudo tee /etc/docker/daemon.json |
Підсумки
Ransomware атака, хоч і неприємна, стала каталізатором для створення кращої системи розгортання. Автоматизований startup процес не тільки захищає від повторних атак, але й значно спрощує управління проектом.
Ключові досягнення
- 🔒 Безпека: автоматичні перевірки та сильні паролі
- ⚡ Швидкість: розгортання за 5 хвилин замість годин
- 🤖 Автоматизація: мінімум ручних дій
- 📚 Документація: повний опис всіх процесів
- 🛡️ Відновлення: швидке відновлення після інцидентів
Майбутні покращення
- Автоматичні бекапи з шифруванням
- Моніторинг безпеки в реальному часі
- Інтеграція з системами сповіщення
- Розширена діагностика мережевої безпеки
Головний урок: інвестиції в автоматизацію безпеки окупаються вже з першого інциденту. Краще витратити день на створення надійних скриптів, ніж тижні на відновлення після атак.
Всі скрипти та документація доступні в репозиторії проекту. Використовуйте, адаптуйте під свої потреби і пам’ятайте – безпека це не одноразова дія, а постійний процес.