Застосунок часто підключається до бази під обліковим записом з усіма правами - root у MySQL чи postgres у PostgreSQL. Поки все працює, різниці не видно. Різниця з'являється, коли щось іде не так.
Що дає зловмиснику всемогутній користувач:
- через SQL-ін'єкцію - не лише читання даних, а
DROP DATABASE, читання й запис файлів сервера (LOAD DATA,COPY ... TO PROGRAMу PostgreSQL для суперкористувача), створення нових користувачів; - через вкрадений
.env- повний контроль над усіма базами на сервері, а не лише над даними застосунку.
Принцип найменших прав - кожен обліковий запис має лише те, що йому справді потрібно:
| Користувач | Права |
|---|---|
| застосунок | SELECT, INSERT, UPDATE, DELETE на свою базу |
| міграції (деплой) | + CREATE, ALTER, DROP, INDEX на свою базу |
| аналітика, звіти | лише SELECT, бажано на репліці |
| бекап | читання й блокування, без зміни даних |
-- PostgreSQL
CREATE ROLE app LOGIN PASSWORD '...';
GRANT CONNECT ON DATABASE shop TO app;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO app;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO app;
Інші правила:
- база не доступна з інтернету: слухає лише внутрішню мережу чи
localhost, порт закритий фаєрволом; - окремі користувачі для кожного застосунку на спільному сервері бази - витік одного не відкриває інші;
- з'єднання з TLS, якщо база на іншому сервері;
- довгі випадкові паролі, різні для кожного оточення;
- журнал підключень і помилок автентифікації.
Практичний компроміс у Laravel: міграції часто запускають тим самим користувачем, що й застосунок. Окреме підключення для міграцій (--database=migrations) з ширшими правами - кращий варіант для продакшену.