أفضل ممارسات أمان قاعدة البيانات
أمان قاعدة البيانات حاسم لحماية البيانات الحساسة من الوصول غير المصرح به والانتهاكات والهجمات. في هذا الدرس، ستتعلم ممارسات أمان شاملة بما في ذلك مبدأ الامتياز الأدنى، ومنع حقن SQL، وتقوية الخادم، والاتصالات المشفرة، وتسجيل التدقيق.
مبدأ الامتياز الأدنى
يعني مبدأ الامتياز الأدنى منح المستخدمين والتطبيقات فقط الحد الأدنى من الأذونات الضرورية لأداء مهامهم:
ممارسة سيئة:
GRANT ALL PRIVILEGES ON *.* TO 'webapp'@'%';
-- مفرط في الإذن! التطبيق لديه تحكم كامل في الخادم
ممارسة جيدة:
GRANT SELECT, INSERT, UPDATE, DELETE ON shop_db.orders TO 'webapp'@'192.168.1.50';
GRANT SELECT, INSERT, UPDATE ON shop_db.products TO 'webapp'@'192.168.1.50';
-- فقط الأذونات الضرورية على جداول محددة من مضيف محدد
أفضل ممارسة: أنشئ مستخدمي قاعدة بيانات منفصلين لمكونات التطبيق المختلفة. يجب أن يكون لدى وحدة التقارير امتيازات SELECT فقط، بينما يمكن أن يكون للتطبيق الرئيسي INSERT, UPDATE, DELETE.
منع حقن SQL (مراجعة)
يظل حقن SQL أحد أخطر الثغرات الأمنية. استخدم دائماً العبارات المحضرة:
كود PHP معرض للخطر (لا تفعل هذا أبداً):
$email = $_POST['email'];
$sql = "SELECT * FROM users WHERE email = '$email'";
$result = mysqli_query($conn, $sql);
-- يمكن للمهاجم حقن: ' OR '1'='1
كود PHP آمن (افعل هذا دائماً):
$stmt = $conn->prepare("SELECT * FROM users WHERE email = ?");
$stmt->bind_param("s", $_POST['email']);
$stmt->execute();
-- يتم تجاهل المدخلات بأمان تلقائياً
حاسم: لا تربط أبداً مدخلات المستخدم مباشرة في استعلامات SQL. استخدم دائماً العبارات المحضرة مع الاستعلامات المعلمية. هذا دفاعك الأساسي ضد حقن SQL.
تأمين إعدادات خادم MySQL
الإعداد الصحيح للخادم ضروري للأمان. عدّل ملف my.cnf أو my.ini:
إعدادات الأمان الأساسية:
[mysqld]
# الربط بعنوان IP محدد (وليس 0.0.0.0)
bind-address = 127.0.0.1
# تعطيل تسجيل دخول root عن بُعد
skip-networking = 1 # للوصول المحلي فقط
# تعطيل LOAD DATA LOCAL INFILE
local-infile = 0
# تمكين التسجيل الثنائي للاسترداد
log-bin = /var/log/mysql/mysql-bin.log
# تسجيل جميع الاستعلامات (للتدقيق، عطّل في الإنتاج للأداء)
general_log = 1
general_log_file = /var/log/mysql/general.log
# تسجيل الاستعلامات البطيئة
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2
# تعيين دليل امتيازات الملف الآمن
secure_file_priv = /var/lib/mysql-files/
# التحقق من قوة كلمة المرور
validate_password.policy = STRONG
validate_password.length = 12
مهم: بعد تغيير الإعدادات، أعد تشغيل MySQL: sudo systemctl restart mysql أو sudo service mysql restart
إزالة الحسابات الافتراضية وقواعد البيانات الاختبارية
قد تحتوي تثبيتات MySQL الجديدة على إعدادات افتراضية غير آمنة. قم بتشغيل نص mysql_secure_installation:
أمر Shell:
$ mysql_secure_installation
سيقوم هذا النص بـ:
✓ تعيين كلمة مرور root
✓ إزالة المستخدمين المجهولين
✓ تعطيل تسجيل دخول root عن بُعد
✓ إزالة قاعدة البيانات الاختبارية
✓ إعادة تحميل جداول الامتيازات
التنظيف اليدوي في SQL:
-- إزالة المستخدمين المجهولين
DELETE FROM mysql.user WHERE User = '';
-- إزالة قاعدة البيانات الاختبارية
DROP DATABASE IF EXISTS test;
DELETE FROM mysql.db WHERE Db = 'test' OR Db = 'test\_%';
-- تعطيل وصول root عن بُعد
DELETE FROM mysql.user WHERE User = 'root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');
-- تطبيق التغييرات
FLUSH PRIVILEGES;
اتصالات SSL/TLS المشفرة
شفّر البيانات أثناء النقل بين تطبيقك وخادم MySQL باستخدام SSL/TLS:
1. التحقق من دعم SSL:
SHOW VARIABLES LIKE '%ssl%';
-- ابحث عن: have_ssl = YES
2. تكوين SSL في my.cnf:
[mysqld]
require_secure_transport = ON
ssl-ca = /etc/mysql/ssl/ca-cert.pem
ssl-cert = /etc/mysql/ssl/server-cert.pem
ssl-key = /etc/mysql/ssl/server-key.pem
3. طلب SSL لمستخدم محدد:
CREATE USER 'secure_user'@'%'
IDENTIFIED BY 'SecurePass2024!'
REQUIRE SSL;
-- أو لمستخدم موجود:
ALTER USER 'existing_user'@'%' REQUIRE SSL;
4. التحقق من اتصال SSL:
SHOW STATUS LIKE 'Ssl_cipher';
-- النتيجة غير الفارغة تعني أن SSL نشط
نصيحة: تضيف SSL عبء تشفير ولكنها ضرورية لبيئات الإنتاج، خاصة عند الاتصال عبر الإنترنت أو الشبكات غير الموثوقة.
تكوين جدار الحماية
استخدم قواعد جدار الحماية لتقييد وصول MySQL إلى عناوين IP محددة:
UFW (Ubuntu/Debian):
# السماح بـ MySQL من IP محدد فقط
sudo ufw allow from 192.168.1.50 to any port 3306
sudo ufw deny 3306
FirewallD (CentOS/RHEL):
# إضافة قاعدة غنية لـ IP محدد
sudo firewall-cmd --permanent --add-rich-rule='
rule family="ipv4"
source address="192.168.1.50/32"
port protocol="tcp" port="3306" accept'
sudo firewall-cmd --reload
iptables:
# السماح من IP محدد
sudo iptables -A INPUT -p tcp -s 192.168.1.50 --dport 3306 -j ACCEPT
# إسقاط جميع حركة MySQL الأخرى
sudo iptables -A INPUT -p tcp --dport 3306 -j DROP
سياسات كلمات المرور والمصادقة
فرض متطلبات كلمة مرور قوية:
تثبيت وتكوين مكون التحقق من كلمة المرور:
INSTALL PLUGIN validate_password SONAME 'validate_password.so';
-- عرض السياسة الحالية
SHOW VARIABLES LIKE 'validate_password%';
-- تعيين سياسة قوية
SET GLOBAL validate_password.policy = STRONG;
SET GLOBAL validate_password.length = 12;
SET GLOBAL validate_password.mixed_case_count = 1;
SET GLOBAL validate_password.number_count = 1;
SET GLOBAL validate_password.special_char_count = 1;
سياسة انتهاء صلاحية كلمة المرور:
-- تعيين الافتراضي العام
SET GLOBAL default_password_lifetime = 90;
-- التطبيق على مستخدم محدد
ALTER USER 'john'@'localhost' PASSWORD EXPIRE INTERVAL 90 DAY;
منع إعادة استخدام كلمة المرور:
ALTER USER 'john'@'localhost'
PASSWORD HISTORY 5
PASSWORD REUSE INTERVAL 365 DAY;
تسجيل التدقيق
مكّن تسجيل التدقيق لتتبع الوصول إلى قاعدة البيانات والتغييرات:
مكون تدقيق MySQL Enterprise (إصدار Enterprise):
INSTALL PLUGIN audit_log SONAME 'audit_log.so';
SET GLOBAL audit_log_policy = ALL;
SET GLOBAL audit_log_format = JSON;
سجل الاستعلام العام (مدمج، للتطوير):
SET GLOBAL general_log = 'ON';
SET GLOBAL general_log_file = '/var/log/mysql/general.log';
-- عرض من يفعل ماذا:
SELECT * FROM mysql.general_log ORDER BY event_time DESC LIMIT 20;
تسجيل جداول محددة بالمشغلات:
CREATE TABLE audit_log (
log_id INT AUTO_INCREMENT PRIMARY KEY,
table_name VARCHAR(50),
action VARCHAR(10),
user VARCHAR(50),
old_data JSON,
new_data JSON,
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- مثال مشغل التدقيق
CREATE TRIGGER users_audit_insert
AFTER INSERT ON users
FOR EACH ROW
INSERT INTO audit_log (table_name, action, user, new_data)
VALUES ('users', 'INSERT', USER(), JSON_OBJECT(
'id', NEW.id,
'email', NEW.email,
'name', NEW.name
));
تحذير: يمكن أن يولد سجل الاستعلام العام ملفات كبيرة ويؤثر على الأداء. مكّنه فقط أثناء التصحيح أو التدقيق. استخدمه بحذر في الإنتاج.
أمان امتياز الملف
قيّد امتياز FILE لمنع الوصول غير المصرح به للملفات:
-- التحقق من من لديه امتياز FILE
SELECT User, Host FROM mysql.user WHERE File_priv = 'Y';
-- إلغاء امتياز FILE من المستخدمين العاديين
REVOKE FILE ON *.* FROM 'webapp'@'localhost';
-- تعيين دليل الملف الآمن في my.cnf
[mysqld]
secure_file_priv = /var/lib/mysql-files/
-- الآن LOAD DATA و SELECT INTO OUTFILE يعملان فقط في هذا الدليل
LOAD DATA INFILE '/var/lib/mysql-files/data.csv'
INTO TABLE products;
الحماية من تصعيد الصلاحيات
امنع المستخدمين من تصعيد امتيازاتهم الخاصة:
-- إزالة الصلاحيات الخطيرة من المستخدمين العاديين
REVOKE SUPER, FILE, PROCESS, RELOAD, SHUTDOWN
ON *.* FROM 'regular_user'@'localhost';
-- تأكد من أن حسابات DBA فقط لديها GRANT OPTION
REVOKE GRANT OPTION ON *.* FROM 'developer'@'localhost';
-- تقييد إنشاء الإجراءات المخزنة
REVOKE CREATE ROUTINE ON *.* FROM 'app_user'@'localhost';
-- مراقبة تغييرات الصلاحيات
SELECT * FROM mysql.user WHERE Grant_priv = 'Y';
تشفير البيانات في حالة السكون
شفّر البيانات الحساسة المخزنة في قاعدة البيانات:
التشفير على مستوى التطبيق (مثال PHP):
-- تخزين بيانات مشفرة
INSERT INTO users (email, credit_card)
VALUES (?, AES_ENCRYPT(?, 'encryption_key_here'));
-- استرداد بيانات مفكوكة التشفير
SELECT email, AES_DECRYPT(credit_card, 'encryption_key_here') AS card
FROM users WHERE id = ?;
تشفير البيانات الشفاف لـ MySQL Enterprise (TDE):
-- تشفير جدول (MySQL 8.0+)
ALTER TABLE sensitive_data ENCRYPTION = 'Y';
-- تشفير مساحة جدول كاملة
CREATE TABLESPACE encrypted_space
ADD DATAFILE 'encrypted.ibd'
ENCRYPTION = 'Y';
أفضل ممارسة: لا تخزن أبداً مفاتيح التشفير في قاعدة البيانات. استخدم متغيرات البيئة أو أنظمة إدارة المفاتيح الخارجية (KMS).
عمليات التدقيق الأمنية المنتظمة
أجرِ عمليات تدقيق أمنية منتظمة لتحديد الثغرات:
استعلامات قائمة التحقق الأمنية:
-- 1. التحقق من المستخدمين بدون كلمة مرور
SELECT User, Host FROM mysql.user
WHERE authentication_string = '';
-- 2. التحقق من المستخدمين مع جميع الصلاحيات
SELECT User, Host FROM mysql.user
WHERE Select_priv = 'Y' AND Insert_priv = 'Y'
AND Update_priv = 'Y' AND Delete_priv = 'Y'
AND Create_priv = 'Y' AND Drop_priv = 'Y';
-- 3. التحقق من المستخدمين مع مضيف '%' (أي مضيف)
SELECT User, Host FROM mysql.user WHERE Host = '%';
-- 4. التحقق من الحسابات القديمة بكلمات مرور منتهية الصلاحية
SELECT User, Host, password_expired, password_last_changed
FROM mysql.user WHERE password_expired = 'Y';
-- 5. سرد المستخدمين مع امتياز SUPER
SELECT User, Host FROM mysql.user WHERE Super_priv = 'Y';
-- 6. التحقق من المستخدمين المجهولين
SELECT User, Host FROM mysql.user WHERE User = '';
أمان النسخ الاحتياطي
أمّن نسخك الاحتياطية من قاعدة البيانات:
ممارسات النسخ الاحتياطي الآمن:
# 1. تشفير ملفات النسخ الاحتياطي
mysqldump -u backup_user -p shop_db | \
openssl enc -aes-256-cbc -salt -out backup_encrypted.sql.enc
# 2. تعيين أذونات آمنة
chmod 600 backup_encrypted.sql.enc
chown mysql:mysql backup_encrypted.sql.enc
# 3. تخزين النسخ الاحتياطية خارج الموقع
rsync -avz --delete /backups/ remote_server:/secure_backups/
# 4. اختبار استعادة النسخ الاحتياطي بانتظام
mysql -u root -p test_restore_db < backup.sql
فك تشفير النسخة الاحتياطية عند الحاجة:
openssl enc -aes-256-cbc -d -in backup_encrypted.sql.enc -out backup.sql
مراقبة الأمان
راقب MySQL للأنشطة المشبوهة:
-- مراقبة الاتصالات النشطة
SELECT * FROM information_schema.PROCESSLIST
WHERE Command != 'Sleep' ORDER BY Time DESC;
-- التحقق من محاولات تسجيل الدخول الفاشلة (إذا تم تمكين مكون التدقيق)
SELECT * FROM mysql.general_log
WHERE argument LIKE '%Access denied%'
ORDER BY event_time DESC LIMIT 50;
-- مراقبة منح الصلاحيات
SELECT * FROM mysql.general_log
WHERE argument LIKE '%GRANT%'
ORDER BY event_time DESC;
-- تتبع الاستعلامات المشبوهة
SELECT * FROM mysql.general_log
WHERE argument LIKE '%DROP%'
OR argument LIKE '%DELETE%'
OR argument LIKE '%TRUNCATE%'
ORDER BY event_time DESC LIMIT 100;
أفضل ممارسات أمان التطبيق
✓ استخدم العبارات المحضرة:
يمنع هجمات حقن SQL
✓ التحقق من جميع المدخلات:
لا تثق أبداً في مدخلات المستخدم، تحقق من التنسيق والنوع
✓ مبدأ الامتياز الأدنى:
امنح الحد الأدنى من الأذونات الضرورية
✓ بيانات اعتماد منفصلة:
مستخدمون مختلفون للتطوير والإعداد والإنتاج
✓ تشفير الاتصالات:
استخدم SSL/TLS لجميع اتصالات قاعدة البيانات
✓ ملفات تكوين آمنة:
احمِ ملفات .env، عيّن الأذونات إلى 600
✓ تحديثات منتظمة:
حافظ على تحديث MySQL بالتصحيحات الأمنية
✓ المراقبة والتسجيل:
مكّن تسجيل التدقيق وراجع بانتظام
✓ النسخ الاحتياطي والاختبار:
نسخ احتياطية مشفرة منتظمة مع استعادة مختبرة
✓ أمان الشبكة:
استخدم جدران الحماية، VPN للوصول عن بُعد
تمرين التدقيق الأمني:
المهمة: أجرِ تدقيقاً أمنياً على تثبيت MySQL الخاص بك:
- التحقق من المستخدمين بدون كلمات مرور
- تحديد المستخدمين ذوي الصلاحيات المفرطة
- التحقق من تمكين SSL
- التحقق من سياسات انتهاء صلاحية كلمة المرور
- مراجعة أذونات الوصول عن بُعد
الحل:
-- 1. التحقق من كلمات المرور الفارغة
SELECT User, Host FROM mysql.user
WHERE authentication_string = '' OR authentication_string IS NULL;
-- 2. البحث عن المستخدمين مع صلاحيات كثيرة جداً
SELECT User, Host,
CONCAT(Select_priv, Insert_priv, Update_priv, Delete_priv,
Create_priv, Drop_priv) AS privileges
FROM mysql.user
WHERE Select_priv = 'Y' AND Insert_priv = 'Y'
AND Update_priv = 'Y' AND Delete_priv = 'Y';
-- 3. التحقق من SSL
SHOW VARIABLES LIKE 'have_ssl';
SELECT User, Host, ssl_type FROM mysql.user;
-- 4. التحقق من سياسات كلمة المرور
SELECT User, Host, password_expired, password_lifetime
FROM mysql.user;
-- 5. مراجعة الوصول عن بُعد
SELECT User, Host FROM mysql.user
WHERE Host NOT IN ('localhost', '127.0.0.1', '::1');
خطة الاستجابة للحوادث
كن مستعداً بخطة للحوادث الأمنية:
إذا كنت تشك في انتهاك:
1. غيّر فوراً جميع كلمات مرور قاعدة البيانات
ALTER USER 'user'@'host' IDENTIFIED BY 'NewSecurePass';
2. راجع سجلات التدقيق
SELECT * FROM mysql.general_log WHERE event_time > '2024-01-15';
3. حدد الحسابات المخترقة
SHOW PROCESSLIST;
SELECT User, Host FROM information_schema.PROCESSLIST;
4. اقفل الحسابات المخترقة
ALTER USER 'compromised_user'@'host' ACCOUNT LOCK;
5. استعد من نسخة احتياطية نظيفة إذا كانت البيانات تالفة
6. حدّث قواعد جدار الحماية
7. وثّق الحادث والدروس المستفادة
الملخص
في هذا الدرس، تعلمت:
- مبدأ الامتياز الأدنى لحقوق الوصول الدنيا
- منع حقن SQL باستخدام العبارات المحضرة
- تأمين إعدادات خادم MySQL
- إزالة الحسابات الافتراضية وقواعد البيانات الاختبارية
- تطبيق اتصالات SSL/TLS المشفرة
- تكوين جدار الحماية لأمان الشبكة
- سياسات كلمات المرور وأفضل ممارسات المصادقة
- تسجيل التدقيق والمراقبة
- أمان امتياز الملف والتشفير
- عمليات التدقيق الأمنية المنتظمة والاستجابة للحوادث
التالي: في الدرس التالي، سنغطي استراتيجيات النسخ الاحتياطي والاسترداد بما في ذلك النسخ الاحتياطية الكاملة والتزايدية، والاسترداد في نقطة زمنية، وتخطيط استرداد الكوارث.