تخطَّ إلى المحتوى

حماية CSRF

2.5.x ✅ 4.0.x ✅

تخدع هجمات التزوير عبر الموقع (CSRF) المستخدمين لتنفيذ إجراءات غير مرغوبة على موقع يكونون مصرحين فيه. يوفر XOOPS حماية CSRF مدمجة من خلال فئة XoopsSecurity.

  • أفضل ممارسات الأمان - دليل الأمان الشامل
  • تطهير المدخلات - MyTextSanitizer والتحقق
  • منع حقن SQL - ممارسات أمان قاعدة البيانات

يحدث هجوم CSRF عندما:

  1. يكون المستخدم مصرحاً على موقع XOOPS الخاص بك
  2. يزور المستخدم موقع ويب ضار
  3. يقدم الموقع الضار طلباً لموقع XOOPS الخاص بك باستخدام جلسة المستخدم
  4. يعالج موقعك الطلب كما لو كان من المستخدم الشرعي

يوفر XOOPS فئة XoopsSecurity للحماية من هجمات CSRF. تدير هذه الفئة رموز الأمان التي يجب تضمينها في النماذج والتحقق منها عند معالجة الطلبات.

تنشئ فئة الأمان رموز فريدة يتم تخزينها في جلسة المستخدم ويجب تضمينها في النماذج:

$security = new XoopsSecurity();
// الحصول على حقل إدخال رمز HTML
$tokenHTML = $security->getTokenHTML();
// احصل على قيمة الرمز فقط
$tokenValue = $security->createToken();

عند معالجة إرسالات النموذج، تحقق من أن الرمز صحيح:

$security = new XoopsSecurity();
if (!$security->check()) {
redirect_header('index.php', 3, _MD_TOKENEXPIRED);
exit();
}

عند استخدام فئات نموذج XOOPS، تكون حماية الرمز واضحة:

// إنشاء نموذج
$form = new XoopsThemeForm('Add Item', 'form_name', 'submit.php');
// إضافة عناصر النموذج
$form->addElement(new XoopsFormText('Title', 'title', 50, 255, ''));
$form->addElement(new XoopsFormTextArea('Content', 'content', ''));
// أضف حقل الرمز المخفي - تضمين هذا دائماً
$form->addElement(new XoopsFormHiddenToken());
// أضف زر الإرسال
$form->addElement(new XoopsFormButton('', 'submit', _SUBMIT, 'submit'));

للنماذج المخصصة HTML التي لا تستخدم XoopsForm:

// في نموذج النموذج أو ملف PHP الخاص بك
$security = new XoopsSecurity();
?>
<form method="post" action="submit.php">
<input type="text" name="title" />
<textarea name="content"></textarea>
<!-- تضمين الرمز -->
<?php echo $security->getTokenHTML(); ?>
<button type="submit">Submit</button>
</form>

عند إنشاء نماذج في قوالب Smarty:

// في ملف PHP الخاص بك
$security = new XoopsSecurity();
$GLOBALS['xoopsTpl']->assign('token', $security->getTokenHTML());
{* في النموذج الخاص بك *}
<form method="post" action="submit.php">
<input type="text" name="title" />
<textarea name="content"></textarea>
{* تضمين الرمز *}
<{$token}>
<button type="submit">Submit</button>
</form>

معالجة إرسالات النموذج

Section titled “معالجة إرسالات النموذج”

التحقق الأساسي من الرمز

Section titled “التحقق الأساسي من الرمز”
// في ملف معالجة النموذج الخاص بك
$security = new XoopsSecurity();
// التحقق من الرمز
if (!$security->check()) {
redirect_header('index.php', 3, _MD_TOKENEXPIRED);
exit();
}
// الرمز صحيح، معالجة النموذج
$title = $_POST['title'];
// ... متابعة المعالجة

مع معالجة الأخطاء المخصصة

Section titled “مع معالجة الأخطاء المخصصة”
$security = new XoopsSecurity();
if (!$security->check()) {
// احصل على معلومات الخطأ المفصلة
$errors = $security->getErrors();
// تسجيل الخطأ
error_log('CSRF token validation failed: ' . implode(', ', $errors));
// إعادة التوجيه برسالة خطأ
redirect_header('form.php', 3, 'Security token expired. Please try again.');
exit();
}

عند العمل مع طلبات AJAX، قم بتضمين الرمز في طلبك:

// JavaScript - احصل على الرمز من الحقل المخفي
var token = document.querySelector('input[name="XOOPS_TOKEN_REQUEST"]').value;
// تضمين في طلب AJAX
fetch('ajax_handler.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'action=save&XOOPS_TOKEN_REQUEST=' + encodeURIComponent(token)
});
// معالج AJAX PHP
$security = new XoopsSecurity();
if (!$security->check()) {
echo json_encode(['error' => 'Invalid security token']);
exit();
}
// معالجة طلب AJAX

لحماية إضافية، خاصة لطلبات AJAX، يمكنك أيضاً التحقق من عنوان HTTP referer:

$security = new XoopsSecurity();
// التحقق من عنوان referer
if (!$security->checkReferer()) {
echo json_encode(['error' => 'Invalid request']);
exit();
}
// تحقق أيضاً من الرمز
if (!$security->check()) {
echo json_encode(['error' => 'Invalid token']);
exit();
}
$security = new XoopsSecurity();
// إجراء كلا الاختبارات
if (!$security->checkReferer() || !$security->check()) {
redirect_header('index.php', 3, 'Security validation failed');
exit();
}

للرموز حياة محدودة لمنع هجمات إعادة التشغيل. يمكنك تكوين هذا في إعدادات XOOPS أو معالجة الرموز المنتهية الصلاحية برشاقة:

$security = new XoopsSecurity();
if (!$security->check()) {
// قد يكون الرمز قد انتهى صلاحيته
// إعادة إنشاء نموذج برمز جديد
redirect_header('form.php', 3, 'Your session has expired. Please submit the form again.');
exit();
}

نماذج متعددة على نفس الصفحة

Section titled “نماذج متعددة على نفس الصفحة”

عندما تحتوي على نماذج متعددة على نفس الصفحة، يجب أن يكون لكل واحد رمز خاص به:

// النموذج 1
$form1 = new XoopsThemeForm('Form 1', 'form1', 'submit1.php');
$form1->addElement(new XoopsFormHiddenToken('token1'));
// النموذج 2
$form2 = new XoopsThemeForm('Form 2', 'form2', 'submit2.php');
$form2->addElement(new XoopsFormHiddenToken('token2'));

استخدم دائماً الرموز لعمليات تغيير الحالة

Section titled “استخدم دائماً الرموز لعمليات تغيير الحالة”

قم بتضمين الرموز في أي نموذج يقوم بـ:

  • إنشاء بيانات
  • تحديث البيانات
  • حذف البيانات
  • تغيير إعدادات المستخدم
  • إجراء أي إجراء إداري

لا تعتمد فقط على فحص Referer

Section titled “لا تعتمد فقط على فحص Referer”

يمكن لعنوان HTTP referer أن:

  • تم حذفه بواسطة أدوات الخصوصية
  • غائب في بعض المتصفحات
  • تم تزويره في بعض الحالات

استخدم التحقق من الرمز دائماً كدفاعك الأساسي.

أعد إنشاء الرموز بشكل صحيح

Section titled “أعد إنشاء الرموز بشكل صحيح”

ضع في الاعتبار إعادة إنشاء الرموز:

  • بعد إرسال النموذج بنجاح
  • بعد تسجيل الدخول / تسجيل الخروج
  • على فترات منتظمة للجلسات الطويلة

معالجة انتهاء صلاحية الرمز برشاقة

Section titled “معالجة انتهاء صلاحية الرمز برشاقة”
$security = new XoopsSecurity();
if (!$security->check()) {
// تخزين بيانات النموذج مؤقتاً
$_SESSION['form_backup'] = $_POST;
// إعادة التوجيه إلى النموذج برسالة
redirect_header('form.php?restore=1', 3, 'Please resubmit the form.');
exit();
}

المشاكل الشائعة والحلول

Section titled “المشاكل الشائعة والحلول”

المشكلة: فحص الأمان يفشل مع “الرمز غير موجود”

الحل: تأكد من تضمين حقل الرمز في النموذج الخاص بك:

$form->addElement(new XoopsFormHiddenToken());

خطأ الرمز المنتهي الصلاحية

Section titled “خطأ الرمز المنتهي الصلاحية”

المشكلة: يرى المستخدمون “الرمز انتهى صلاحيته” بعد إكمال النموذج لفترة طويلة

الحل: ضع في الاعتبار استخدام JavaScript لتحديث الرمز بشكل دوري:

// تحديث الرمز كل 10 دقائق
setInterval(function() {
fetch('refresh_token.php')
.then(response => response.json())
.then(data => {
document.querySelector('input[name="XOOPS_TOKEN_REQUEST"]').value = data.token;
});
}, 600000);

المشكلة: طلبات AJAX تفشل في التحقق من الرمز

الحل: تأكد من نقل الرمز مع كل طلب AJAX والتحقق منه من جانب الخادم:

// معالج AJAX
header('Content-Type: application/json');
$security = new XoopsSecurity();
if (!$security->check(true, false)) { // لا تمسح الرمز لـ AJAX
http_response_code(403);
echo json_encode(['error' => 'Invalid token']);
exit();
}

#أمان #csrf #xoops #نماذج #رموز #XoopsSecurity