~/icsd.ir — bash
SYSTEM_ONLINE

امنیت و User Management

MySQL دسترسی را در سه سطح بررسی می‌کند:

۱۳.۱ مدل امنیتی MySQL

MySQL دسترسی را در سه سطح بررسی می‌کند:

  1. کاربر می‌تواند اتصال برقرار کند؟ (User + Host + Password)
  2. کاربر روی این Database/Table دسترسی دارد؟ (Privileges)
  3. کاربر روی این Column دسترسی دارد؟ (Column-level)

هویت کاربر = ترکیب User + Host. مثلاً 'app'@'localhost' با 'app'@'192.168.1.10' دو کاربر متفاوت‌اند.

۱۳.۲ مدیریت کاربران

SQL
-- ساخت کاربر CREATE USER 'webapp'@'localhost' IDENTIFIED BY 'StrongPassword2026!'; CREATE USER 'webapp'@'192.168.1.%' IDENTIFIED BY 'StrongPassword2026!'; CREATE USER 'webapp'@'%' IDENTIFIED BY 'StrongPassword2026!'; -- ⚠️ خطرناک -- تنظیمات اضافی هنگام ساخت CREATE USER 'webapp'@'localhost' IDENTIFIED BY 'StrongPassword2026!' PASSWORD EXPIRE INTERVAL 90 DAY -- منقضی شدن خودکار PASSWORD HISTORY 5 -- نمی‌تواند ۵ پسورد قبلی را تکرار کند PASSWORD REUSE INTERVAL 365 DAY -- پسورد قدیمی حداقل ۱ سال FAILED_LOGIN_ATTEMPTS 5 -- پس از ۵ بار اشتباه قفل PASSWORD_LOCK_TIME 1; -- ۱ روز قفل -- تغییر پسورد ALTER USER 'webapp'@'localhost' IDENTIFIED BY 'NewPassword!'; -- نمایش کاربران SELECT User, Host, account_locked, password_expired FROM mysql.user ORDER BY User, Host; -- حذف کاربر DROP USER 'webapp'@'localhost'; -- قفل/باز کردن ALTER USER 'webapp'@'localhost' ACCOUNT LOCK; ALTER USER 'webapp'@'localhost' ACCOUNT UNLOCK;

۱۳.۳ Privileges – مدیریت دسترسی

سطوح Privilege

  • Global: روی همه دیتابیس‌ها (*.*)
  • Database: روی یک دیتابیس (db.*)
  • Table: روی یک جدول (db.table)
  • Column: روی ستون‌های خاص
  • Routine: روی procedure/function
SQL
-- کاربر اپلیکیشن (دسترسی محدود به یک دیتابیس) GRANT SELECT, INSERT, UPDATE, DELETE ON shop_db.* TO 'webapp'@'localhost'; -- کاربر فقط خواندن (برای گزارش‌گیری) GRANT SELECT ON shop_db.* TO 'reporter'@'localhost'; -- کاربر backup GRANT SELECT, RELOAD, LOCK TABLES, REPLICATION CLIENT, SHOW VIEW, EVENT, TRIGGER, PROCESS ON *.* TO 'backup'@'localhost'; -- DBA کامل (با احتیاط) GRANT ALL PRIVILEGES ON *.* TO 'dba'@'localhost' WITH GRANT OPTION; -- Privileges در سطح ستون GRANT SELECT (id, name, email), UPDATE (email) ON users.users TO 'limited'@'localhost'; -- نمایش privileges SHOW GRANTS FOR 'webapp'@'localhost'; -- بازپس‌گیری REVOKE DELETE ON shop_db.* FROM 'webapp'@'localhost'; REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'webapp'@'localhost'; -- اعمال تغییرات (در نسخه‌های قدیمی) FLUSH PRIVILEGES;

privilege‌های مهم

Privilege توضیح
SELECT خواندن
INSERT, UPDATE, DELETE تغییر داده
CREATE, DROP ساخت/حذف جدول
ALTER تغییر ساختار
INDEX ساخت ایندکس
EXECUTE اجرای procedure
CREATE ROUTINE ساخت procedure
TRIGGER ساخت trigger
RELOAD FLUSH
SUPER تنظیمات گلوبال (خطرناک)

۱۳.۴ Roles – گروه‌بندی Privileges

به‌جای دادن privilege به هر کاربر، یک Role می‌سازیم و چندین کاربر آن را می‌گیرند:

SQL
-- ساخت roleها CREATE ROLE 'app_read', 'app_write', 'app_admin'; -- تخصیص privilege به role GRANT SELECT ON shop_db.* TO 'app_read'; GRANT SELECT, INSERT, UPDATE, DELETE ON shop_db.* TO 'app_write'; GRANT ALL ON shop_db.* TO 'app_admin'; -- اختصاص role به کاربر GRANT 'app_read' TO 'reporter1'@'%', 'reporter2'@'%'; GRANT 'app_write' TO 'webapp'@'%'; GRANT 'app_admin' TO 'admin'@'localhost'; -- فعال‌سازی role (در سشن کاربر) SET ROLE 'app_write'; -- یا default ALTER USER 'webapp'@'%' DEFAULT ROLE 'app_write'; -- نمایش SHOW GRANTS FOR 'webapp'@'%' USING 'app_write';

۱۳.۵ SSL/TLS برای اتصالات رمزنگاری شده

اگر کلاینت و سرور MySQL در شبکه‌های مختلف هستند (مثل سرور MySQL در ابر و اپلیکیشن جای دیگر)، اتصال باید رمزنگاری شود.

Bash - تولید certificate
# MySQL خودکار در نصب جدید certificate تولید می‌کند: ls /var/lib/mysql/*.pem # ca.pem, server-cert.pem, server-key.pem, ... # یا دستی با mysql_ssl_rsa_setup mysql_ssl_rsa_setup --datadir=/var/lib/mysql # my.cnf [mysqld] ssl-ca=/etc/mysql/ca.pem ssl-cert=/etc/mysql/server-cert.pem ssl-key=/etc/mysql/server-key.pem require_secure_transport=ON # اجبار همه کلاینت‌ها به SSL
SQL
-- بررسی SSL SHOW VARIABLES LIKE 'have_ssl'; -- اجبار کاربر به SSL ALTER USER 'webapp'@'%' REQUIRE SSL; -- یا قوی‌تر: certificate خاص ALTER USER 'webapp'@'%' REQUIRE X509; -- بررسی اتصال فعلی SHOW STATUS LIKE 'Ssl_cipher';

۱۳.۶ جلوگیری از SQL Injection

SQL Injection معمولاً در سطح اپلیکیشن رخ می‌دهد، نه دیتابیس. اما در سطح DB هم می‌توانیم سخت‌گیری کنیم:

قانون طلایی: همیشه Prepared Statement

PHP - PDO
// ❌ خطرناک - SQL Injection $id = $_GET['id']; $result = $pdo->query("SELECT * FROM users WHERE id = $id"); // ✅ امن - Prepared Statement $stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?"); $stmt->execute([$_GET['id']]); $users = $stmt->fetchAll(); // PDO با تنظیمات امن $pdo = new PDO($dsn, $user, $pass, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_EMULATE_PREPARES => false, // مهم! PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true, ]);
Python - mysqlclient/PyMySQL
# ❌ خطرناک cursor.execute(f"SELECT * FROM users WHERE id = {user_id}") # ✅ امن cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,)) # Django ORM به‌صورت پیش‌فرض parameterized است User.objects.filter(id=user_id) User.objects.raw("SELECT * FROM users WHERE id = %s", [user_id])

کم کردن سطح حمله در DB

  • کاربر اپلیکیشن نباید DROP TABLE داشته باشد
  • FILE privilege را به‌جز کاربران DBA ندهید (LOAD DATA INFILE)
  • SUPER privilege را به‌شدت محدود کنید
  • local_infile روی Server را غیرفعال کنید مگر لازم باشد

۱۳.۷ Encryption at Rest – رمزنگاری داده روی دیسک

InnoDB از MySQL 5.7+ از tablespace encryption پشتیبانی می‌کند:

my.cnf
[mysqld] # Keyring plugin (انتخاب یکی) early-plugin-load=keyring_file.so keyring_file_data=/var/lib/mysql-keyring/keyring # یا keyring_okv (Oracle Key Vault) برای enterprise # یا keyring_aws (AWS KMS)
SQL
-- ساخت جدول رمزنگاری شده CREATE TABLE sensitive_data ( id INT PRIMARY KEY, secret VARCHAR(255) ) ENCRYPTION='Y'; -- تبدیل جدول موجود ALTER TABLE sensitive_data ENCRYPTION='Y'; -- بررسی SELECT TABLE_NAME, CREATE_OPTIONS FROM INFORMATION_SCHEMA.TABLES WHERE CREATE_OPTIONS LIKE '%ENCRYPTION%';

۱۳.۸ Audit Log

برای production نیاز به ثبت دسترسی‌ها داریم. MySQL plugin اختصاصی نیاز دارد:

MariaDB Audit Plugin (built-in)

SQL
INSTALL SONAME 'server_audit'; SET GLOBAL server_audit_logging = ON; SET GLOBAL server_audit_events = 'CONNECT,QUERY,TABLE'; SET GLOBAL server_audit_file_path = '/var/log/mysql/audit.log'; SET GLOBAL server_audit_file_rotate_size = 100000000; -- 100MB -- بررسی SHOW VARIABLES LIKE 'server_audit%';

Percona Audit Plugin

برای MySQL community، plugin Percona جایگزین خوبی است.

۱۳.۹ چک‌لیست امنیت Production

Security Checklist
□ root با پسورد قوی، فقط از localhost قابل اتصال □ کاربر anonymous حذف شود □ دیتابیس test حذف شود □ هر اپلیکیشن کاربر اختصاصی با کمترین privilege □ FILE privilege فقط برای DBA □ SUPER privilege به حداقل □ bind-address روی 127.0.0.1 (مگر لازم باشد) □ skip-networking یا فقط شبکه داخلی □ SSL برای اتصالات راه دور □ require_secure_transport=ON اگر external □ password expiration و failed_login_attempts فعال □ Audit Log فعال □ Backup‌ها رمزنگاری شده □ Patch‌های امنیتی بروز □ نسخه MySQL پنهان (validate_password plugin) □ Firewall: فقط port 3306 از سرور اپلیکیشن □ Local infile غیرفعال □ Strict sql_mode فعال □ Performance Schema برای monitoring فعال

۱۳.۱۰ بررسی امنیتی

SQL - Audit Script
-- 1. کاربران بدون پسورد SELECT User, Host FROM mysql.user WHERE authentication_string = '' OR authentication_string IS NULL; -- 2. کاربران با پسورد قابل پیش‌بینی -- (نمی‌توان مستقیم چک کرد، اما کاربر anonymous را حذف کنید) SELECT User, Host FROM mysql.user WHERE User = ''; -- 3. کاربران از هر هاست (%) SELECT User, Host FROM mysql.user WHERE Host = '%'; -- 4. کاربران با ALL PRIVILEGES SELECT User, Host FROM mysql.user WHERE Super_priv = 'Y' OR Grant_priv = 'Y'; -- 5. دیتابیس‌های test SHOW DATABASES LIKE 'test%'; -- 6. تنظیمات حساس SHOW VARIABLES LIKE 'local_infile'; -- باید OFF SHOW VARIABLES LIKE 'secure_file_priv'; -- باید مسیر محدود SHOW VARIABLES LIKE 'skip_networking'; SHOW VARIABLES LIKE 'bind_address';

۱۳.۱۱ خلاصه فصل

  • هویت = User + Host؛ از % فقط در صورت ضرورت استفاده کنید
  • Principle of Least Privilege: کمترین دسترسی لازم
  • هر اپلیکیشن کاربر اختصاصی با privilege محدود به دیتابیس خود
  • Roles مدیریت چندین کاربر را آسان می‌کنند
  • SSL/TLS برای اتصالات راه دور اجباری
  • Prepared Statement = جلوی SQL Injection
  • Encryption at Rest برای داده‌های حساس
  • Audit Log در Production فعال باشد

نمایش سایت

رنگ سایت
حالت نمایش
اندازهٔ متن
خوانایی

این تنظیمات فقط روی مرورگر شما ذخیره می‌شود.