اصل کمترین دسترسی در عمل
در فصل اول یک کاربر ساده برای برنامه ساختیم. در محیط واقعی چند نوع مصرفکننده دارید: خود برنامهی وب، فرمان مایگریشن، کاربر گزارشگیری که به ابزار BI وصل میشود، کاربر پشتیبانگیری و مدیر انسانی. اصل کمترین دسترسی میگوید هر کدام فقط همان مجوزی را بگیرد که کارش لازم دارد. اگر رمز برنامهی وب از یک فایل .env نشت کرد، مهاجم نباید بتواند DROP DATABASE بزند یا دیتابیس سایت دیگری را که روی همان سرور است بخواند.
سطوح مجوز
| سطح | نمونه | کاربرد |
|---|---|---|
| سراسری | ON *.* | فقط برای مدیر، بکاپ و Replication |
| دیتابیس | ON carpet_factory.* | حالت معمول برای برنامه |
| جدول | ON carpet_factory.orders | کاربر گزارش یا سرویس جانبی |
| ستون | SELECT (id, city) ON ...customers | پنهان کردن موبایل و آدرس |
| روتین | EXECUTE ON PROCEDURE ... | اجازهی اجرای یک رویهی مشخص |
نقشها: مجوز را به نقش بدهید، نه به آدم
از MySQL 8 میتوان مجموعهای از مجوزها را یکبار در قالب Role تعریف و به چند کاربر داد. وقتی کارمند جدیدی به واحد گزارش آمد، فقط نقش را به او میدهید.
CREATE ROLE 'app_rw', 'app_migrate', 'report_ro';
GRANT SELECT, INSERT, UPDATE, DELETE ON carpet_factory.* TO 'app_rw';
GRANT ALTER, CREATE, DROP, INDEX, REFERENCES ON carpet_factory.* TO 'app_migrate';
GRANT SELECT ON carpet_factory.orders TO 'report_ro';
GRANT SELECT ON carpet_factory.order_items TO 'report_ro';
GRANT SELECT (id, full_name, city) ON carpet_factory.customers TO 'report_ro';
CREATE USER 'web'@'10.0.0.%' IDENTIFIED BY 'Long-Random-Secret-1405'
FAILED_LOGIN_ATTEMPTS 5 PASSWORD_LOCK_TIME 1;
CREATE USER 'sara_bi'@'10.0.0.25' IDENTIFIED BY 'Another-Long-Secret'
PASSWORD EXPIRE INTERVAL 90 DAY;
GRANT 'app_rw' TO 'web'@'10.0.0.%';
GRANT 'report_ro' TO 'sara_bi'@'10.0.0.25';
SET DEFAULT ROLE ALL TO 'web'@'10.0.0.%', 'sara_bi'@'10.0.0.25';
SHOW GRANTS FOR 'sara_bi'@'10.0.0.25' USING 'report_ro';
برنامهی جنگو در حالت عادی با نقش app_rw کار میکند و manage.py migrate در زمان استقرار با کاربر جداگانهای اجرا میشود که app_migrate هم دارد. نقشی که به کاربر داده شده تا وقتی فعال نشود اثری ندارد؛ SET DEFAULT ROLE را فراموش نکنید و برای بررسی، SELECT CURRENT_ROLE(); بزنید.
بازبینی دورهای
SELECT user, host, account_locked, password_last_changed
FROM mysql.user ORDER BY user;
ALTER USER 'old_intern'@'%' ACCOUNT LOCK; -- قبل از حذف، مدتی قفل کنید
DROP USER 'old_intern'@'%';
نکتههایی که کمتر کسی میداند
- در GRANT سطح دیتابیس،
_و%wildcard هستند:GRANT ... ON my_db.*دیتابیسmyxdbرا هم شامل میشود. برای دقت بنویسیدmy\_db. ALL ON carpet_factory.*مجوزDROPرا هم دارد؛ یعنی کاربر برنامه میتواند کل دیتابیس را حذف کند. همچنین TRIGGER و CREATE ROUTINE را میدهد که برای ماندگاری مهاجم کافی است.- مجوز سراسری
FILEاجازهی خواندن فایلهای سرور باLOAD_FILE()را میدهد؛ هرگز به کاربر برنامه ندهید وsecure_file_privرا خالی نگذارید. - با
partial_revokes = ONمیتوان «همه بهجز» ساخت:GRANT SELECT ON *.*و سپسREVOKE SELECT ON mysql.*. 'web'@'localhost'و'web'@'%'دو حساب جدا با رمز و مجوز جدا هستند؛ MySQL هنگام ورود، خاصترین host را انتخاب میکند، نه حسابی را که شما در ذهن دارید.- متغیر
mandatory_rolesنقشی را به همهی کاربران میدهد وactivate_all_roles_on_login = ONنیاز به SET DEFAULT ROLE را برمیدارد.