[أمان] 7 دقائق للقراءة

[أمان] أفضل ممارسات أمان Base64

اعتبارات أمان مهمة عند العمل مع ترميز Base64 في تطبيقات الويب.

يناير 2025 | security

// BASE64 ليس تشفيراً

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

أي شخص يمكنه فك ترميز بيانات Base64 فوراً. لا تعتمد أبداً على Base64 للأمان أو حماية البيانات.

// ❌ خطأ: استخدام Base64 كـ 'أمان'
const password = 'secret123';
const encoded = btoa(password); // cGFzc3dvcmQ=
// أي شخص يمكنه فك ترميز هذا فوراً!

// ✅ صحيح: تجميع كلمة المرور المناسب
import bcrypt from 'bcrypt';
const password = 'secret123';
const hashedPassword = await bcrypt.hash(password, 12);
// هذا آمن فعلاً

// التحقق من المدخل

تحقق دائماً من مدخل Base64 لمنع هجمات الحقن وأخطاء التطبيق:

التحقق المناسب يمنع المدخل الضار من التسبب في مشاكل أمنية أو تعطل التطبيق.

// التحقق من تنسيق Base64
function isValidBase64(str) {
    // التحقق من التنسيق: أحرف Base64 صالحة فقط
    const base64Regex = /^[A-Za-z0-9+/]*={0,2}$/;
    if (!base64Regex.test(str)) {
        return false;
    }
    
    // التحقق من الطول (يجب أن يكون مضاعف 4)
    if (str.length % 4 !== 0) {
        return false;
    }
    
    // اختبار فك الترميز
    try {
        atob(str);
        return true;
    } catch (e) {
        return false;
    }
}

// فك ترميز آمن مع التحقق
function safeBase64Decode(input, maxLength = 10000) {
    if (typeof input !== 'string') {
        throw new Error('المدخل يجب أن يكون نصاً');
    }
    
    if (input.length > maxLength) {
        throw new Error('المدخل طويل جداً');
    }
    
    if (!isValidBase64(input)) {
        throw new Error('Base64 غير صالح');
    }
    
    return atob(input);
}

// منع XSS

بيانات Base64 يمكن أن تحتوي على سكريبت ضار عند فك الترميز. أنظف دائماً المخرجات عند عرض المحتوى المفكوك:

لا تثق أبداً في مدخل Base64 من المستخدمين. أنظف دائماً قبل العرض في HTML.

// ❌ خطر: حقن HTML مباشر
function displayDecodedData(base64) {
    const decoded = atob(base64);
    document.innerHTML = decoded; // ثغرة XSS!
}

// ✅ آمن: تنظيف المخرجات
function safeDisplayDecodedData(base64) {
    const decoded = atob(base64);
    
    // إنشاء عقدة نص (لا تنفيذ HTML)
    const textNode = document.createTextNode(decoded);
    container.appendChild(textNode);
    
    // أو هروب كيانات HTML
    const escaped = decoded
        .replace(/&/g, '&')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#x27;');
    
    container.innerHTML = escaped;
}

// حدود الحجم

ترميز Base64 يزيد حجم البيانات بـ ~33%. نفذ حدود حجم لمنع هجمات DoS:

مدخل Base64 غير المحدود يمكن أن يستهلك ذاكرة وقوة معالجة مفرطة.

  • > ضع حدود طول مدخل قصوى
  • > راقب استخدام الذاكرة أثناء المعالجة
  • > نفذ مهلات زمنية للعمليات الطويلة
  • > استخدم التدفق لمجموعات البيانات الكبيرة
  • > فكر في الضغط قبل الترميز
  • > حدد معدل عمليات Base64

// معالجة الرمز الآمنة

عند استخدام Base64 للرموز أو المعرفات الحساسة، اتبع أفضل ممارسات الأمان:

معالجة الرمز المناسبة تمنع الوصول غير المصرح به والهجمات القائمة على الرمز.

// إنشاء رمز آمن
function createSecureToken() {
    // استخدم قيم عشوائية آمنة تشفيرياً
    const array = new Uint8Array(32);
    crypto.getRandomValues(array);
    
    // تحويل إلى Base64 وجعله آمن للـ URL
    const base64 = btoa(String.fromCharCode(...array))
        .replace(/\+/g, '-')
        .replace(/\//g, '_')
        .replace(/=/g, '');
    
    return base64;
}

// التحقق الآمن من الرمز
function validateToken(token, expectedLength = 43) {
    if (typeof token !== 'string') {
        return false;
    }
    
    // التحقق من الطول
    if (token.length !== expectedLength) {
        return false;
    }
    
    // التحقق من تنسيق Base64 آمن للـ URL
    const urlSafeBase64Regex = /^[A-Za-z0-9_-]+$/;
    return urlSafeBase64Regex.test(token);
}

// أمان DATA URI

Base64 data URIs يمكن أن تحتوي على محتوى ضار. تحقق من وأنظف data URIs دائماً:

data URIs الضارة يمكن أن تنفذ سكريبت، تحمل موارد خارجية، أو تحتوي على محتوى غير مناسب.

// التحقق من data URI
function validateDataURI(dataUri, allowedTypes = ['image/png', 'image/jpeg']) {
    const dataUriRegex = /^data:([a-zA-Z0-9][a-zA-Z0-9\/+]*);base64,(.+)$/;
    const match = dataUri.match(dataUriRegex);
    
    if (!match) {
        throw new Error('تنسيق data URI غير صالح');
    }
    
    const [, mimeType, base64Data] = match;
    
    // التحقق من نوع MIME
    if (!allowedTypes.includes(mimeType)) {
        throw new Error(`نوع MIME غير مدعوم: ${mimeType}`);
    }
    
    // التحقق من بيانات Base64
    if (!isValidBase64(base64Data)) {
        throw new Error('Base64 غير صالح في data URI');
    }
    
    // التحقق من الحجم
    const sizeEstimate = (base64Data.length * 3) / 4;
    if (sizeEstimate > 1024 * 1024) { // حد 1 ميجابايت
        throw new Error('data URI كبير جداً');
    }
    
    return { mimeType, base64Data };
}

// قائمة التحقق للتنفيذ الآمن

  • > لا تستخدم Base64 أبداً كتشفير أو إجراء أمني
  • > تحقق دائماً من تنسيق وطول مدخل Base64
  • > أنظف المخرجات المفكوكة قبل العرض
  • > نفذ حدود حجم ومهل زمنية
  • > استخدم Base64 آمن للـ URL لتطبيقات الويب
  • > تحقق من أنواع MIME لـ data URIs
  • > استخدم قيم عشوائية آمنة تشفيرياً للرموز
  • > نفذ معالجة أخطاء مناسبة
  • > راقب لهجمات DoS محتملة
  • > مراجعات أمنية منتظمة لكود معالجة Base64