الأمان في SQL (SQL Security)

الأمان في قواعد البيانات SQL هو موضوع بالغ الأهمية لا يمكن تجاهله. قاعدة البيانات تحتوي على أهم أصول أي تطبيق: البيانات. اختراق قاعدة البيانات أو فقدان البيانات يمكن أن يكون كارثياً للشركات والمستخدمين. الأمان في SQL يشمل عدة جوانب: الحماية من الهجمات (مثل SQL Injection)، إدارة الصلاحيات والوصول، تشفير البيانات الحساسة، النسخ الاحتياطي والاسترجاع، ومراقبة النشاطات المشبوهة. في هذا الدرس الشامل والمفصل من سلسلة تعلم لغة SQL باللغة العربية، سنتعلم كل شيء عن أمان قواعد البيانات: كيفية الحماية من SQL Injection، إدارة المستخدمين والصلاحيات، استخدام الأدوار، تشفير البيانات، وأفضل الممارسات الأمنية الشاملة لحماية بياناتك.

1. SQL Injection: الخطر الأكبر

SQL Injection هو أحد أخطر الثغرات الأمنية في تطبيقات الويب. يحدث عندما يتمكن المهاجم من إدخال كود SQL ضار من خلال مدخلات المستخدم، مما يسمح له بقراءة، تعديل، أو حذف البيانات، أو حتى السيطرة على قاعدة البيانات بالكامل.

مثال على كود ضعيف (غير آمن)
كود PHP غير آمن - لا تستخدمه أبداً
// كود خطير جداً - عرضة لـ SQL Injection
$username = $_POST['username'];
$password = $_POST['password'];

$query = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
$result = mysqli_query($conn, $query);
كيف يتم الهجوم؟

المهاجم يمكن أن يدخل في حقل username القيمة التالية:

مثال على هجوم SQL Injection
-- المهاجم يدخل:
username: admin' OR '1'='1
password: anything

-- الاستعلام يصبح:
SELECT * FROM users WHERE username = 'admin' OR '1'='1' AND password = 'anything'

-- النتيجة: الشرط دائماً صحيح، المهاجم يدخل بدون كلمة مرور!
الحل 1: Prepared Statements (الحل الأفضل)
كود آمن باستخدام Prepared Statements
// كود آمن تماماً
$username = $_POST['username'];
$password = $_POST['password'];

// استخدام Prepared Statement
$stmt = $conn->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
$stmt->bind_param("ss", $username, $password);
$stmt->execute();
$result = $stmt->get_result();
الحل 2: PDO مع Prepared Statements
استخدام PDO للحماية
// استخدام PDO (الطريقة الموصى بها)
$username = $_POST['username'];
$password = $_POST['password'];

$stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username AND password = :password");
$stmt->execute([
    'username' => $username,
    'password' => $password
]);
$user = $stmt->fetch();
تحذير خطير:

لا تستخدم أبداً دمج النصوص (String Concatenation) لبناء استعلامات SQL. استخدم دائماً Prepared Statements أو Parameterized Queries. هذا هو الدفاع الأول والأهم ضد SQL Injection.

2. إدارة المستخدمين والصلاحيات

مبدأ "الحد الأدنى من الصلاحيات" (Principle of Least Privilege) يعني أن كل مستخدم أو تطبيق يجب أن يحصل فقط على الصلاحيات الضرورية لأداء مهامه، لا أكثر.

إنشاء مستخدم جديد
إنشاء مستخدمين جدد
-- إنشاء مستخدم جديد
CREATE USER 'app_user'@'localhost' IDENTIFIED BY 'strong_password_123!';

-- إنشاء مستخدم يمكنه الاتصال من أي مكان
CREATE USER 'remote_user'@'%' IDENTIFIED BY 'another_strong_password';

-- إنشاء مستخدم بدون كلمة مرور (غير موصى به)
CREATE USER 'test_user'@'localhost';
منح الصلاحيات: GRANT
منح صلاحيات محددة
-- منح صلاحية SELECT فقط على جدول معين
GRANT SELECT ON company_db.employees TO 'app_user'@'localhost';

-- منح صلاحيات SELECT و INSERT و UPDATE على جدول
GRANT SELECT, INSERT, UPDATE ON company_db.orders TO 'app_user'@'localhost';

-- منح جميع الصلاحيات على قاعدة بيانات معينة
GRANT ALL PRIVILEGES ON company_db.* TO 'admin_user'@'localhost';

-- منح صلاحية إنشاء جداول
GRANT CREATE ON company_db.* TO 'developer'@'localhost';

-- منح صلاحية تنفيذ الإجراءات المخزنة
GRANT EXECUTE ON company_db.* TO 'app_user'@'localhost';

-- تطبيق التغييرات
FLUSH PRIVILEGES;
سحب الصلاحيات: REVOKE
سحب الصلاحيات
-- سحب صلاحية DELETE
REVOKE DELETE ON company_db.employees FROM 'app_user'@'localhost';

-- سحب جميع الصلاحيات
REVOKE ALL PRIVILEGES ON company_db.* FROM 'app_user'@'localhost';

-- تطبيق التغييرات
FLUSH PRIVILEGES;
عرض الصلاحيات
عرض صلاحيات المستخدمين
-- عرض صلاحيات مستخدم معين
SHOW GRANTS FOR 'app_user'@'localhost';

-- عرض صلاحيات المستخدم الحالي
SHOW GRANTS FOR CURRENT_USER();

-- عرض جميع المستخدمين
SELECT User, Host FROM mysql.user;
حذف مستخدم
حذف مستخدم
-- حذف مستخدم
DROP USER 'app_user'@'localhost';

-- حذف آمن
DROP USER IF EXISTS 'app_user'@'localhost';

3. استخدام الأدوار (Roles)

الأدوار (Roles) تسمح لك بتجميع الصلاحيات وإعطائها لعدة مستخدمين بسهولة. بدلاً من منح نفس الصلاحيات لكل مستخدم على حدة، تنشئ دوراً وتمنحه للمستخدمين.

إنشاء واستخدام الأدوار
-- إنشاء أدوار مختلفة
CREATE ROLE 'app_read_only';
CREATE ROLE 'app_read_write';
CREATE ROLE 'app_admin';

-- منح صلاحيات للأدوار
GRANT SELECT ON company_db.* TO 'app_read_only';
GRANT SELECT, INSERT, UPDATE ON company_db.* TO 'app_read_write';
GRANT ALL PRIVILEGES ON company_db.* TO 'app_admin';

-- إنشاء مستخدمين
CREATE USER 'viewer'@'localhost' IDENTIFIED BY 'password1';
CREATE USER 'editor'@'localhost' IDENTIFIED BY 'password2';
CREATE USER 'admin'@'localhost' IDENTIFIED BY 'password3';

-- منح الأدوار للمستخدمين
GRANT 'app_read_only' TO 'viewer'@'localhost';
GRANT 'app_read_write' TO 'editor'@'localhost';
GRANT 'app_admin' TO 'admin'@'localhost';

-- تفعيل الأدوار افتراضياً
SET DEFAULT ROLE ALL TO 'viewer'@'localhost';
SET DEFAULT ROLE ALL TO 'editor'@'localhost';
SET DEFAULT ROLE ALL TO 'admin'@'localhost';

-- عرض الأدوار
SHOW GRANTS FOR 'viewer'@'localhost';

-- سحب دور من مستخدم
REVOKE 'app_read_only' FROM 'viewer'@'localhost';

-- حذف دور
DROP ROLE 'app_read_only';

4. تشفير البيانات الحساسة

البيانات الحساسة مثل كلمات المرور، أرقام البطاقات الائتمانية، والمعلومات الشخصية يجب تشفيرها دائماً.

تشفير كلمات المرور (في التطبيق)
تشفير كلمات المرور في PHP
// لا تحفظ كلمات المرور كنص عادي أبداً!

// عند التسجيل - تشفير كلمة المرور
$password = $_POST['password'];
$hashed_password = password_hash($password, PASSWORD_DEFAULT);

// حفظ في قاعدة البيانات
$stmt = $pdo->prepare("INSERT INTO users (username, password) VALUES (?, ?)");
$stmt->execute([$username, $hashed_password]);

// عند تسجيل الدخول - التحقق من كلمة المرور
$stmt = $pdo->prepare("SELECT password FROM users WHERE username = ?");
$stmt->execute([$username]);
$user = $stmt->fetch();

if (password_verify($password, $user['password'])) {
    // كلمة المرور صحيحة
    echo "تم تسجيل الدخول بنجاح";
} else {
    // كلمة المرور خاطئة
    echo "اسم المستخدم أو كلمة المرور غير صحيحة";
}
دوال التشفير في MySQL
دوال التشفير في SQL
-- تشفير AES (للبيانات الحساسة)
INSERT INTO sensitive_data (user_id, credit_card)
VALUES (1, AES_ENCRYPT('1234-5678-9012-3456', 'encryption_key'));

-- فك التشفير
SELECT 
    user_id,
    AES_DECRYPT(credit_card, 'encryption_key') AS decrypted_card
FROM sensitive_data;

-- SHA2 للهاش (لا يمكن فك تشفيره)
SELECT SHA2('my_password', 256) AS hashed_password;

-- MD5 (غير موصى به - ضعيف)
SELECT MD5('text') AS md5_hash;
ملاحظة مهمة:

من الأفضل تشفير البيانات الحساسة في طبقة التطبيق (PHP, Python, etc.) وليس في قاعدة البيانات. استخدم مكتبات تشفير قوية ومُختبرة مثل bcrypt أو Argon2 لكلمات المرور.

5. تأمين الاتصال بقاعدة البيانات

استخدام SSL/TLS للاتصالات

عند الاتصال بقاعدة البيانات عبر الشبكة، استخدم دائماً اتصالات مشفرة (SSL/TLS) لمنع اعتراض البيانات.

فرض استخدام SSL
-- فرض SSL على مستخدم معين
CREATE USER 'secure_user'@'%' IDENTIFIED BY 'password' REQUIRE SSL;

-- أو تعديل مستخدم موجود
ALTER USER 'existing_user'@'%' REQUIRE SSL;

-- فرض شهادة محددة
ALTER USER 'user'@'%' REQUIRE X509;
تأمين ملف التكوين
حماية بيانات الاتصال
// لا تحفظ بيانات الاتصال في الكود مباشرة
// استخدم ملف تكوين خارج مجلد الويب

// config.php (خارج public_html)
define('DB_HOST', 'localhost');
define('DB_USER', 'app_user');
define('DB_PASS', 'strong_password');
define('DB_NAME', 'company_db');

// أو استخدم متغيرات البيئة (الأفضل)
$db_host = getenv('DB_HOST');
$db_user = getenv('DB_USER');
$db_pass = getenv('DB_PASS');
$db_name = getenv('DB_NAME');

6. النسخ الاحتياطي والاسترجاع

النسخ الاحتياطي المنتظم ضروري لحماية البيانات من الفقدان بسبب الأخطاء، الهجمات، أو الكوارث.

إنشاء نسخة احتياطية
أوامر النسخ الاحتياطي
# نسخ احتياطي لقاعدة بيانات كاملة
mysqldump -u root -p company_db > backup_company_db.sql

# نسخ احتياطي لجدول معين
mysqldump -u root -p company_db employees > backup_employees.sql

# نسخ احتياطي لعدة قواعد بيانات
mysqldump -u root -p --databases db1 db2 db3 > backup_multiple.sql

# نسخ احتياطي لجميع قواعد البيانات
mysqldump -u root -p --all-databases > backup_all.sql

# نسخ احتياطي مضغوط
mysqldump -u root -p company_db | gzip > backup_company_db.sql.gz
استرجاع النسخة الاحتياطية
استرجاع البيانات
# استرجاع من نسخة احتياطية
mysql -u root -p company_db < backup_company_db.sql

# استرجاع من ملف مضغوط
gunzip < backup_company_db.sql.gz | mysql -u root -p company_db
جدولة النسخ الاحتياطي التلقائي
نسخ احتياطي يومي تلقائي (Cron)
# إضافة إلى crontab
# نسخ احتياطي يومي في الساعة 2 صباحاً
0 2 * * * mysqldump -u root -pPASSWORD company_db | gzip > /backups/company_db_$(date +\%Y\%m\%d).sql.gz

# حذف النسخ الاحتياطية الأقدم من 30 يوم
0 3 * * * find /backups -name "*.sql.gz" -mtime +30 -delete

7. مراقبة وتدقيق النشاطات

مراقبة النشاطات المشبوهة وحفظ سجلات التدقيق مهم لاكتشاف الهجمات والتحقيق فيها.

تفعيل سجل الاستعلامات
تفعيل General Query Log
-- تفعيل سجل جميع الاستعلامات
SET GLOBAL general_log = 'ON';
SET GLOBAL general_log_file = '/var/log/mysql/general.log';

-- تفعيل سجل الاستعلامات البطيئة
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 2; -- الاستعلامات أبطأ من ثانيتين
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
إنشاء جدول تدقيق مخصص
جدول تدقيق للنشاطات الحساسة
CREATE TABLE audit_log (
    log_id INT PRIMARY KEY AUTO_INCREMENT,
    user_name VARCHAR(100),
    action VARCHAR(50),
    table_name VARCHAR(100),
    record_id INT,
    ip_address VARCHAR(45),
    action_time DATETIME DEFAULT CURRENT_TIMESTAMP,
    details TEXT
);

-- استخدام Trigger لحفظ سجل تلقائي
DELIMITER //

CREATE TRIGGER audit_employee_changes
AFTER UPDATE ON employees
FOR EACH ROW
BEGIN
    INSERT INTO audit_log (user_name, action, table_name, record_id, details)
    VALUES (
        USER(),
        'UPDATE',
        'employees',
        NEW.employee_id,
        CONCAT('Changed from: ', OLD.salary, ' to: ', NEW.salary)
    );
END //

DELIMITER ;

8. أفضل الممارسات الأمنية الشاملة

على مستوى قاعدة البيانات
  • استخدم دائماً Prepared Statements لمنع SQL Injection
  • طبق مبدأ الحد الأدنى من الصلاحيات
  • لا تستخدم حساب root في التطبيقات
  • استخدم كلمات مرور قوية ومعقدة
  • غير كلمات المرور بشكل دوري
  • فعّل SSL/TLS للاتصالات عبر الشبكة
  • احذف المستخدمين والحسابات غير المستخدمة
  • قم بنسخ احتياطي منتظم ومُختبر
على مستوى الخادم
  • حدّث MySQL/MariaDB بانتظام لإصلاح الثغرات
  • غير المنفذ الافتراضي (3306) إذا أمكن
  • استخدم جدار ناري (Firewall) لتقييد الوصول
  • عطّل الوصول عن بعد إذا لم يكن ضرورياً
  • احفظ ملفات السجلات وراقبها
  • استخدم أدوات مراقبة للكشف عن الأنشطة المشبوهة
على مستوى التطبيق
  • تحقق من صحة جميع المدخلات (Input Validation)
  • استخدم HTTPS دائماً
  • احفظ بيانات الاتصال في متغيرات البيئة
  • لا تعرض رسائل الأخطاء التفصيلية للمستخدمين
  • استخدم معدل محدود (Rate Limiting) لمنع الهجمات
  • فعّل المصادقة الثنائية (2FA) للحسابات الحساسة

9. قائمة فحص الأمان (Security Checklist)

قائمة التحقق الأساسية
  • هل تستخدم Prepared Statements في جميع الاستعلامات؟
  • هل كلمات المرور مُشفرة بشكل صحيح؟
  • هل كل مستخدم لديه فقط الصلاحيات الضرورية؟
  • هل تم تعطيل حساب root للاستخدام عن بعد؟
  • هل يتم النسخ الاحتياطي بشكل منتظم؟
  • هل تم اختبار استرجاع النسخ الاحتياطية؟
  • هل SSL/TLS مُفعّل للاتصالات؟
  • هل يتم مراقبة السجلات بانتظام؟
  • هل MySQL محدّث لآخر إصدار آمن؟
  • هل بيانات الاتصال محمية ومخفية؟
ملخص الدرس

في هذا الدرس الشامل، تعلمنا كل شيء عن أمان قواعد البيانات SQL:

  • الحماية من SQL Injection باستخدام Prepared Statements
  • إدارة المستخدمين والصلاحيات: CREATE USER, GRANT, REVOKE
  • استخدام الأدوار (Roles) لتسهيل إدارة الصلاحيات
  • تشفير البيانات الحساسة
  • تأمين الاتصال بقاعدة البيانات
  • النسخ الاحتياطي والاسترجاع
  • مراقبة وتدقيق النشاطات
  • أفضل الممارسات الأمنية الشاملة

الأمان ليس خياراً، بل ضرورة. تطبيق هذه الممارسات الأمنية سيحمي بياناتك ومستخدميك من الهجمات والاختراقات. تذكر: الأمان هو عملية مستمرة، وليس إجراءً لمرة واحدة.

الخطوة التالية: تحسين الاستعلامات (Query Optimization)

أكمل رحلتك التعليمية وانتقل إلى الدرس التالي لتعلم تحسين الاستعلامات (Query Optimization) وتطوير مهاراتك في قواعد البيانات.

الانتقال إلى الدرس التالي
المحرر الذكي

اكتب الكود وشاهد النتيجة فوراً

جرب الآن مجاناً
قناة ديف عربي

تابع أحدث الدروس والتحديثات مباشرة على واتساب

انضم الآن