الأمان والأداء

رؤوس الأمان

20 دقيقة الدرس 8 من 35

رؤوس الأمان

رؤوس أمان HTTP توفر حماية دفاعية متعددة الطبقات ضد ثغرات الويب الشائعة. الرؤوس المكونة بشكل صحيح تمنع هجمات XSS والنقر الخادع واستنشاق MIME وهجمات أخرى على مستوى المتصفح.

سياسة أمان المحتوى (CSP)

CSP هو أقوى رأس أمان، يمنع هجمات XSS من خلال التحكم في الموارد التي يمكن تحميلها:

// رأس CSP الأساسي
Content-Security-Policy: default-src 'self'

// تكوين CSP التفصيلي
<?php
header(
"Content-Security-Policy: " .
"default-src 'self'; " . // الافتراضي: نفس الأصل
"script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net; " . // النصوص البرمجية
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; " . // الأنماط
"img-src 'self' data: https:; " . // الصور
"font-src 'self' https://fonts.gstatic.com; " . // الخطوط
"connect-src 'self' https://api.example.com; " . // AJAX/WebSocket
"frame-src 'none'; " . // إطارات iframe
"object-src 'none'; " . // Flash/المكونات الإضافية
"base-uri 'self'; " . // علامة <base>
"form-action 'self'; " . // إرسالات النماذج
"frame-ancestors 'none'; " . // حماية التضمين
"upgrade-insecure-requests" // HTTP → HTTPS
);
?>

// تكوين Apache
Header set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'"

// تكوين Nginx
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'" always;
ملاحظة: توجيهات CSP:
default-src: الاحتياطي لجميع توجيهات الجلب
script-src: مصادر JavaScript
style-src: مصادر CSS
img-src: مصادر الصور
font-src: مصادر الخطوط
connect-src: AJAX، WebSocket، EventSource
frame-src: مصادر Iframe
object-src: Flash، تطبيقات Java الصغيرة

كلمات مصدر CSP الرئيسية

تستخدم CSP كلمات رئيسية خاصة لتعريف المصادر المسموح بها:

// كلمات مصدر CSP الرئيسية
'none' // حظر جميع المصادر
'self' // نفس الأصل (البروتوكول + النطاق + المنفذ)
'unsafe-inline' // السماح بالنصوص/الأنماط المضمنة (غير موصى به)
'unsafe-eval' // السماح بـ eval() وما شابه (غير موصى به)
data: // السماح بعناوين URL لـ data: (صور base64)
https: // السماح بأي عنوان URL لـ HTTPS
*.example.com // السماح بالنطاقات الفرعية

// CSP القائم على Nonce (موصى به للنصوص المضمنة)
<?php
$nonce = base64_encode(random_bytes(16));
header("Content-Security-Policy: script-src 'self' 'nonce-$nonce'");
?>

<!-- استخدم nonce في علامات script -->
<script nonce="<?php echo $nonce; ?>">
// JavaScript مضمن مسموح به مع هذا nonce
console.log('Secure inline script');
</script>

// CSP القائم على Hash (للنصوص المضمنة الثابتة)
<?php
$script = "console.log('hello');";
$hash = base64_encode(hash('sha256', $script, true));
header("Content-Security-Policy: script-src 'self' 'sha256-$hash'");
?>
أفضل ممارسة: تجنب 'unsafe-inline' و 'unsafe-eval'. استخدم nonces للمحتوى الديناميكي أو hashes للمحتوى الثابت. هذا يوفر أقصى حماية من XSS.

تقارير CSP

يمكن لـ CSP الإبلاغ عن الانتهاكات للمساعدة في تحديد المشكلات قبل فرض سياسات صارمة:

// وضع التقرير فقط (اختبار بدون حظر)
Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report

// وضع الفرض مع التقارير
Content-Security-Policy: default-src 'self'; report-uri /csp-report

// معالج تقرير PHP
<?php
// نقطة نهاية /csp-report
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$report = json_decode(file_get_contents('php://input'), true);

error_log(sprintf(
"CSP Violation: %s blocked %s on %s",
$report['csp-report']['violated-directive'] ?? 'unknown',
$report['csp-report']['blocked-uri'] ?? 'unknown',
$report['csp-report']['document-uri'] ?? 'unknown'
));

// تخزين في قاعدة البيانات للتحليل
logCspViolation($report);

http_response_code(204);
}
?>

// واجهة برمجة تطبيقات Report-To (بديل حديث لـ report-uri)
Content-Security-Policy: default-src 'self'; report-to csp-endpoint
Report-To: {"group":"csp-endpoint","max_age":10886400,"endpoints":[{"url":"/csp-report"}]}

X-Frame-Options

يمنع هجمات النقر الخادع من خلال التحكم في ما إذا كان يمكن تضمين موقعك في إطارات iframe:

// ثلاث قيم محتملة
X-Frame-Options: DENY // لا تسمح أبدًا بالتأطير
X-Frame-Options: SAMEORIGIN // السماح بالتأطير بنفس الأصل فقط
X-Frame-Options: ALLOW-FROM https://example.com // مهمل

// تنفيذ PHP
<?php
header('X-Frame-Options: DENY');
// أو
header('X-Frame-Options: SAMEORIGIN');
?>

// تكوين Apache
Header always set X-Frame-Options "SAMEORIGIN"

// تكوين Nginx
add_header X-Frame-Options "SAMEORIGIN" always;

// بديل CSP الحديث (أكثر مرونة)
Content-Security-Policy: frame-ancestors 'self'
Content-Security-Policy: frame-ancestors 'none'
Content-Security-Policy: frame-ancestors 'self' https://trusted.com
تحذير: ALLOW-FROM مهمل وغير مدعوم من قبل معظم المتصفحات. استخدم توجيه CSP frame-ancestors بدلاً من ذلك للتحكم في iframe متعدد النطاقات.

X-Content-Type-Options

يمنع استنشاق نوع MIME، مما يجبر المتصفحات على احترام Content-Type المعلن:

// تنسيق الرأس
X-Content-Type-Options: nosniff

// تنفيذ PHP
<?php
header('X-Content-Type-Options: nosniff');
?>

// تكوين Apache
Header always set X-Content-Type-Options "nosniff"

// تكوين Nginx
add_header X-Content-Type-Options "nosniff" always;

// لماذا هذا مهم:
// بدون nosniff: قد ينفذ المتصفح text/plain كـ JavaScript
<script src="user-uploaded-file.txt"></script> // يمكن أن ينفذ!

// مع nosniff: يحترم المتصفح Content-Type
// ملف text/plain لن ينفذ كـ JavaScript
ملاحظة: تحدث هجمات استنشاق MIME عندما تتجاهل المتصفحات رأس Content-Type وتخمن نوع الملف بناءً على المحتوى. هذا يمكن أن يسمح بتنفيذ ملفات ضارة متنكرة كأنواع آمنة.

سياسة المُحيل (Referrer-Policy)

تتحكم في مقدار معلومات المُحيل المرسلة مع الطلبات:

// قيم Referrer-Policy
no-referrer // لا ترسل أبدًا المُحيل
no-referrer-when-downgrade // افتراضي: أرسل ما لم يكن HTTPS → HTTP
origin // أرسل الأصل فقط (https://example.com)
origin-when-cross-origin // عنوان URL الكامل لنفس الأصل، الأصل للأصول المتقاطعة
same-origin // أرسل المُحيل إلى نفس الأصل فقط
strict-origin // أرسل الأصل ما لم يكن HTTPS → HTTP
strict-origin-when-cross-origin // موصى به: عنوان URL الكامل نفس الأصل، الأصل الأصول المتقاطعة
unsafe-url // أرسل دائمًا عنوان URL الكامل (غير موصى به)

// تنفيذ PHP
<?php
header('Referrer-Policy: strict-origin-when-cross-origin');
?>

// تكوين Apache
Header always set Referrer-Policy "strict-origin-when-cross-origin"

// تكوين Nginx
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

// علامة HTML Meta
<meta name="referrer" content="strict-origin-when-cross-origin">
أفضل ممارسة: استخدم strict-origin-when-cross-origin كسياسة متوازنة. إنها تحمي خصوصية المستخدم مع توفير بيانات تحليلية مفيدة للتنقل بنفس الأصل.

سياسة الأذونات (Permissions-Policy سابقًا Feature-Policy)

تتحكم في ميزات المتصفح وواجهات برمجة التطبيقات التي يمكن استخدامها:

// بناء جملة Permissions-Policy الحديث
Permissions-Policy: geolocation=(), camera=(), microphone=()

// تكوين تفصيلي
<?php
header(
"Permissions-Policy: " .
"geolocation=(), " . // حظر تحديد الموقع الجغرافي
"camera=(), " . // حظر الكاميرا
"microphone=(), " . // حظر الميكروفون
"payment=(self), " . // السماح بواجهات برمجة تطبيقات الدفع لنفس الأصل
"usb=(), " . // حظر الوصول إلى USB
"accelerometer=(), " . // حظر مقياس التسارع
"gyroscope=(), " . // حظر الجيروسكوب
"magnetometer=(), " . // حظر المغناطيسي
"fullscreen=(self)" // السماح بملء الشاشة لنفس الأصل
);
?>

// السماح بأصول محددة
Permissions-Policy: camera=(self "https://trusted-video.com")

// Feature-Policy القديم (مهمل ولكن لا يزال مدعومًا)
Feature-Policy: geolocation 'none'; camera 'none'; microphone 'none'

// تكوين Apache
Header always set Permissions-Policy "geolocation=(), camera=(), microphone=()"

// تكوين Nginx
add_header Permissions-Policy "geolocation=(), camera=(), microphone=()" always;

X-XSS-Protection (قديم)

التحكم في مرشح XSS القديم. يجب أن تعتمد المواقع الحديثة على CSP بدلاً من ذلك:

// قيم الرأس
X-XSS-Protection: 0 // تعطيل مرشح XSS
X-XSS-Protection: 1 // تمكين مرشح XSS
X-XSS-Protection: 1; mode=block // تمكين وحظر الصفحة

// تنفيذ PHP
<?php
// موصى به: تعطيل (يتعارض مع CSP)
header('X-XSS-Protection: 0');
?>

// تكوين Apache
Header always set X-XSS-Protection "0"

// لماذا التعطيل؟
// - المتصفحات الحديثة أهملت هذه الميزة
// - يمكن أن يُدخل ثغرات
// - CSP يوفر حماية أفضل
// - يخلق شعورًا زائفًا بالأمان
تحذير: رأس X-XSS-Protection مهمل. يمكن أن يُدخل فعليًا ثغرات XSS في بعض الحالات. قم بتعطيله واستخدم Content-Security-Policy بدلاً من ذلك.

تكوين رؤوس الأمان الكامل

إعداد رؤوس أمان جاهز للإنتاج:

// PHP - رؤوس الأمان الكاملة
<?php
// فرض HTTPS
header('Strict-Transport-Security: max-age=31536000; includeSubDomains; preload');

// سياسة أمان المحتوى
$nonce = base64_encode(random_bytes(16));
header(
"Content-Security-Policy: " .
"default-src 'self'; " .
"script-src 'self' 'nonce-$nonce' https://cdn.jsdelivr.net; " .
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; " .
"img-src 'self' data: https:; " .
"font-src 'self' https://fonts.gstatic.com; " .
"connect-src 'self'; " .
"frame-src 'none'; " .
"object-src 'none'; " .
"base-uri 'self'; " .
"form-action 'self'; " .
"frame-ancestors 'none'; " .
"upgrade-insecure-requests; " .
"block-all-mixed-content"
);

// حماية النقر الخادع
header('X-Frame-Options: DENY');

// منع استنشاق MIME
header('X-Content-Type-Options: nosniff');

// سياسة المُحيل
header('Referrer-Policy: strict-origin-when-cross-origin');

// سياسة الأذونات
header('Permissions-Policy: geolocation=(), camera=(), microphone=()');

// تعطيل مرشح XSS (مهمل)
header('X-XSS-Protection: 0');
?>

// Apache - تكوين كامل
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
Header always set Content-Security-Policy "default-src 'self'; script-src 'self'"
Header always set X-Frame-Options "DENY"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "geolocation=(), camera=(), microphone=()"
Header always set X-XSS-Protection "0"
</IfModule>

// Nginx - تكوين كامل
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self'" always;
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), camera=(), microphone=()" always;
add_header X-XSS-Protection "0" always;

Helmet.js لـ Node.js/Express

يقوم Helmet.js تلقائيًا بتعيين رؤوس الأمان لتطبيقات Node.js:

// تثبيت Helmet
npm install helmet

// التنفيذ الأساسي
const express = require('express');
const helmet = require('helmet');

const app = express();

// استخدام جميع الرؤوس الافتراضية
app.use(helmet());

// تكوين مخصص
app.use(
helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'unsafe-inline'", "cdn.jsdelivr.net"],
styleSrc: ["'self'", "'unsafe-inline'", "fonts.googleapis.com"],
imgSrc: ["'self'", "data:", "https:"],
fontSrc: ["'self'", "fonts.gstatic.com"],
connectSrc: ["'self'"],
frameSrc: ["'none'"],
objectSrc: ["'none'"],
},
},
hsts: {
maxAge: 31536000,
includeSubDomains: true,
preload: true,
},
frameguard: {
action: 'deny',
},
referrerPolicy: {
policy: 'strict-origin-when-cross-origin',
},
})
);

// رؤوس فردية
app.use(helmet.contentSecurityPolicy({ /* options */ }));
app.use(helmet.hsts({ /* options */ }));
app.use(helmet.frameguard({ action: 'deny' }));
app.use(helmet.noSniff());
app.use(helmet.referrerPolicy({ policy: 'strict-origin-when-cross-origin' }));

اختبار وتدقيق رؤوس الأمان

أدوات وتقنيات للتحقق من تكوين رؤوس الأمان بشكل صحيح:

// اختبار سطر الأوامر
# فحص الرؤوس باستخدام curl
curl -I https://example.com

# فحص رأس محدد
curl -I https://example.com | grep "Content-Security-Policy"

// أدوات تطوير المتصفح
// 1. افتح DevTools (F12)
// 2. علامة تبويب الشبكة (Network)
// 3. أعد تحميل الصفحة
// 4. انقر على الطلب
// 5. عرض قسم "الرؤوس" (Headers)

// ماسحات رؤوس الأمان عبر الإنترنت
// 1. https://securityheaders.com/
// - درجات من A+ إلى F
// - توصيات تفصيلية

// 2. https://observatory.mozilla.org/
// - فحص أمان شامل
// - مدقق CSP

// 3. https://csp-evaluator.withgoogle.com/
// - محلل سياسة CSP
// - يحدد نقاط الضعف

// نص PHP لاختبار الرؤوس
<?php
function checkSecurityHeaders($url) {
$headers = get_headers($url, 1);

$requiredHeaders = [
'Strict-Transport-Security',
'Content-Security-Policy',
'X-Frame-Options',
'X-Content-Type-Options',
'Referrer-Policy'
];

foreach ($requiredHeaders as $header) {
if (isset($headers[$header])) {
echo "✓ $header: {$headers[$header]}\n";
} else {
echo "✗ $header: مفقود\n";
}
}
}

checkSecurityHeaders('https://example.com');
?>
تمرين: قم بتطبيق نظام رؤوس أمان كامل:
1. أنشئ نص PHP يعين جميع رؤوس الأمان الموصى بها
2. قم بتطبيق CSP القائم على nonce للنصوص المضمنة
3. قم بتكوين HSTS مع max-age لمدة سنة واحدة و preload
4. قم بإعداد نقطة نهاية تقارير CSP لتسجيل الانتهاكات
5. قم بتكوين Referrer-Policy و Permissions-Policy
6. اختبر الرؤوس في securityheaders.com (هدف درجة A+)
7. أضف رؤوس الأمان إلى تكوين Apache أو Nginx
8. تحقق من الرؤوس باستخدام أدوات تطوير المتصفح
9. اختبر CSP من خلال محاولة تحميل موارد محظورة
10. راقب تقارير انتهاكات CSP لمدة أسبوع واحد لتحديد المشكلات