التقنية المالية والمدفوعات الأدلة التقنية

أمن بيانات البطاقات PCI DSS والترميز Tokenization

نطاق PCI DSS v4.0.1 وما يمنع حفظه من بيانات البطاقة، وكيف يعمل الترميز، مع مختبر لفحص السجلات وخطر التجزئة دون مفتاح.

أمن بيانات البطاقات PCI DSS والترميز Tokenization

لنفرض أن الشركة الناشئة التي تبيع اشتراكات الأندية الرياضية، والتي تتبعنا أموالها في مقالات هذا القسم، وصلتها شكوى من عضو تجدد اشتراكه مرتين. فتح مهندس الدعم سجلات خدمة الدفع ليتتبع الطلب، وبحث برقم الطلب، فظهر له سطر لم يتوقعه: سطر DEBUG كتبته نسخة قديمة من صفحة الدفع، قبل أن ينتقل الفريق إلى حقل الدفع الذي يقدمه المزود، وفيه جسم الطلب كاملاً، ومنه رقم بطاقة العضو وتاريخ انتهائها. السجلات محفوظة منذ أشهر، ومنسوخة إلى نظام جمع السجلات، ويقرؤها نصف الفريق، ومن بينهم متدرب بدأ الأسبوع الماضي. وسأل المهندس في قناة الفريق: «هل هذا يعني أننا داخل نطاق PCI DSS كله؟ وما المطلوب منا الآن؟».

هذا السؤال يصل إلى أغلب شركات المدفوعات الناشئة في وقت ما، وعادة في أسوأ وقت. وفي مقال عملية الدفع بالبطاقة ذكرنا القرار الذي يحدد حجم المشكلة كلها: أين تمر بيانات البطاقة، ووعدنا بمقال مستقل عن المعيار. وهذا هو المقال: ما معيار أمن بيانات صناعة بطاقات الدفع PCI DSS، وما إصداره الحالي v4.0.1، وما البيانات التي يحميها وأيها يمنع حفظه، وكيف يتحدد النطاق، وما الطرق التي يقبلها لحفظ رقم البطاقة، ثم الترميز Tokenization بالتفصيل من إرشادات مجلس PCI SSC، وأنواع التوكن التي تقابلها في المدفوعات، ومختبران: الأول يبحث عن أرقام البطاقات في سجلات مولدة ويبين لماذا يغرق الفحص في التنبيهات الكاذبة، والثاني يبين لماذا يحذر المعيار من حفظ تجزئة الرقم مع جزء منه. وكل الأرقام في المختبرين أرقام بطاقات اختبار عامة، لا بطاقات حقيقية.

وسوف نناقش في هذا المقال ما يلي:

  • ما PCI DSS، ومن يطلبه، وما الذي تغير في الإصدار v4.0.1.
  • بيانات الحساب: بيانات حامل البطاقة وبيانات التحقق الحساسة، وما الذي لا يحفظ أبداً.
  • النطاق: بيئة بيانات البطاقة، والأنظمة المتصلة بها، والتجزئة، وتأكيد النطاق السنوي.
  • صفحة الدفع والاستبيانات الذاتية، ولماذا لا يختفي النطاق مع حقل المزود.
  • أربع طرق لجعل الرقم غير مقروء عند الحفظ، والإخفاء عند العرض.
  • الترميز Tokenization: التوليد والخزنة والمفاتيح والعمليات ونماذج النشر.
  • توكن مزود الدفع وتوكن الشبكة والخزنة الداخلية.
  • مختبر فحص السجلات، ومختبر التجزئة مع الاقتطاع.
  • ما فعله الفريق، والأخطاء الشائعة، وقائمة تحقق.

ما PCI DSS ومن يطلبه؟

معيار أمن بيانات صناعة بطاقات الدفع Payment Card Industry Data Security Standard يصدره مجلس معايير أمن صناعة بطاقات الدفع PCI Security Standards Council، وتقول صفحته الرسمية إنه يقدم خط أساس من المتطلبات التقنية والتشغيلية لحماية بيانات حسابات الدفع، وإنه موجه للجهات التي تحفظ بيانات حاملي البطاقات أو بيانات التحقق الحساسة أو تعالجها أو ترسلها، أو التي قد تؤثر على أمن بيئة هذه البيانات، ومنها التجار والمعالجون والمستحوذون والمصدرون ومقدمو الخدمات. وتضيف الصفحة نقطة يغفل عنها كثيرون: المجلس يكتب المعيار، ولكن إلزام جهة بالالتزام به أو بإثبات التزامها يعود لمن يدير برامج الامتثال، مثل شبكات البطاقات والبنوك المحصلة. ولذلك فالسؤال العملي للشركة الناشئة ليس «هل نحن ملزمون نظرياً؟»، وإنما «ماذا يطلب منا البنك المحصل أو مزود الدفع الذي نتعامل معه، وبأي نموذج نثبت ذلك؟».

والإصدار الحالي v4.0.1، وبحسب إعلان المجلس في 11 يونيو 2024 فهو مراجعة محدودة للإصدار v4.0 الذي نشر في مارس 2022: تصحيحات في التنسيق والأخطاء الطباعية وتوضيح لهدف بعض المتطلبات وإرشاداتها، دون أي متطلب مضاف أو محذوف. ومن أمثلة ما تغير فيه:

  • في المتطلب 3: هدف للنهج المخصص وتوضيح لمن يستخدم التجزئة بمفتاح Keyed Cryptographic Hash لجعل الرقم غير مقروء.
  • في المتطلب 6: العودة إلى صياغة v3.2.1 بأن تثبيت التحديثات خلال 30 يوماً ينطبق على الثغرات الحرجة فقط، وملاحظات توضح تطبيق متطلب إدارة سكربتات صفحة الدفع.
  • في المتطلب 8: التحقق متعدد العوامل لكل دخول غير إداري إلى بيئة البطاقات لا ينطبق على الحسابات التي لا تستخدم إلا عوامل مقاومة للتصيد Phishing-resistant.

ويذكر الإعلان أن الإصدار v4.0 يتقاعد في 31 ديسمبر 2024 ليبقى v4.0.1 الإصدار الوحيد الفعال، وأن المراجعة لم تغير موعد 31 مارس 2025 لسريان المتطلبات الجديدة. وفي حوار نشره المجلس أن الإصدار الرابع أضاف 64 متطلباً جديداً منها 51 مؤجلة إلى ذلك التاريخ، فهي كلها سارية الآن. وفي 3 يونيو 2026 فتح المجلس فترة تعليقات على v4.0.1 تمهيداً للإصدار التالي، فراجع صفحة المعيار قبل أي تقييم لتعرف الإصدار الساري يومها.

ويتكون المعيار من اثني عشر متطلباً رئيسياً، كما تعرضها استمارة التقييم الذاتي D للتجار: ضوابط أمن الشبكة، والإعدادات الآمنة، وحماية بيانات الحساب المحفوظة، وتشفير البيانات أثناء النقل، والحماية من البرمجيات الخبيثة، وتطوير الأنظمة والبرمجيات بأمان، وتقييد الوصول بحسب حاجة العمل، وتعريف المستخدمين والتحقق منهم، وتقييد الوصول المادي، وتسجيل الوصول ومراقبته، واختبار الأمن دورياً، والسياسات والبرامج التنظيمية. وهذا المقال يركز على المتطلب الثالث وعلى النطاق، لأنهما ما يقرر حجم البقية.

من يقيم الالتزام؟

تذكر صفحة المعيار ثلاثة أدوار يعتمدها المجلس، وكل منها يظهر في حياة الشركة في مرحلة مختلفة:

  • المقيم الأمني المؤهل Qualified Security Assessor: شركات أمن مستقلة يؤهلها المجلس ويدربها لتقييم التزام الجهات بالمعيار، وتكتب تقرير الالتزام Report on Compliance عندما يطلب من الجهة تقييم خارجي.
  • المقيم الأمني الداخلي Internal Security Assessor: موظفون في الجهة نفسها يدربهم المجلس ليجروا التقييمات الداخلية ويساعدوا على تطبيق الضوابط بشكل متسق.
  • جهة الفحص المعتمدة Approved Scanning Vendor: جهات يؤهلها المجلس لإجراء فحص الثغرات الخارجي الذي يطلبه المعيار، وهو الفحص الربع سنوي الذي أصبح مطلوباً حتى من تاجر SAQ A.

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

بيانات الحساب: ما الذي يحميه المعيار؟

أول ما فعله الفريق أن فتح مسرد مصطلحات المجلس ليعرف بالضبط ما الذي وجده في السجل. والمسرد يقسم بيانات الحساب Account Data إلى نوعين، كما في الصورة التالية:

لوحتان: بيانات حامل البطاقة Cardholder Data وهي رقم البطاقة PAN كاملاً ومعه الاسم أو الانتهاء أو رمز الخدمة ويجوز حفظها بحماية، وبيانات التحقق الحساسة Sensitive Authentication Data وهي رمز التحقق CVV وبيانات الشريط كاملة ورمز PIN وكتلته ولا تحفظ بعد التفويض، وتحتهما أن المتطلب 3.3.1 يمنع حفظ بيانات التحقق بعد التفويض ولو كانت مشفرة
نوعان من البيانات، والفرق بينهما بين «احمها» و«لا تحفظها»
  • بيانات حامل البطاقة Cardholder Data: بحسب المسرد هي في حدها الأدنى رقم الحساب الأساسي PAN كاملاً، وقد تظهر في صورة الرقم كاملاً مع اسم حامل البطاقة أو تاريخ الانتهاء أو رمز الخدمة. ورقم البطاقة هو مركزها: الاسم وتاريخ الانتهاء وحدهما دون الرقم لا يجعلانها بيانات حامل بطاقة.
  • بيانات التحقق الحساسة Sensitive Authentication Data: معلومات أمنية تستخدم للتحقق من حامل البطاقة أو تفويض العمليات، ومنها رمز التحقق المطبوع على البطاقة، وبيانات الشريط الممغنط أو ما يعادلها في الشريحة كاملة، ورمز PIN وكتلة PIN.

والفرق في الحكم كبير: بيانات حامل البطاقة يجوز حفظها إذا احتاجها العمل وحميت بحسب المتطلب الثالث، أما بيانات التحقق الحساسة فالمتطلب 3.3.1 ينص على ألا تحفظ بعد التفويض ولو كانت مشفرة، وأن تصبح غير قابلة للاسترجاع عند اكتمال عملية التفويض، وتفصل المتطلبات 3.3.1.1 إلى 3.3.1.3 ذلك: لا تحفظ محتويات الشريط كاملة، ولا رمز التحقق، ولا رمز PIN وكتلته. ورمز التحقق كما يعرفه المعيار هو الرقم من ثلاث أو أربع خانات المطبوع على وجه البطاقة أو ظهرها، ويستخدم في عمليات عدم حضور البطاقة. ولهذا فالسطر الذي وجده المهندس، والذي فيه الرقم وتاريخ الانتهاء دون رمز التحقق، هو بيانات حامل بطاقة محفوظة بلا حماية، وهي مشكلة كبيرة، ولكنها كانت ستكون أسوأ لو كتبت النسخة القديمة رمز التحقق أيضاً، لأن ذلك محظور حفظه في أي حال.

النطاق: أين تبدأ بيئة البطاقة وأين تنتهي؟

السؤال الثاني للمهندس كان عن النطاق، والمسرد يعرف بيئة بيانات حامل البطاقة Cardholder Data Environment بأنها الأنظمة والأشخاص والعمليات التي تحفظ بيانات حامل البطاقة أو بيانات التحقق الحساسة أو تعالجها أو ترسلها، ومعها الأنظمة التي لا تفعل ذلك ولكن لها اتصال غير مقيد بها. والصورة التالية تبين الدوائر الثلاث:

ثلاث بطاقات: بيئة بيانات البطاقة CDE تحفظ البيانات أو تعالجها أو ترسلها، ومتصل بها Connected-to باتصال غير مقيد أو يؤثر على أمنها، وخارج النطاق Out of scope معزول بالتجزئة ولا يصل للبيانات، وتحتها أن المتطلب 12.5.2 يطلب تأكيد النطاق كل 12 شهراً وعند أي تغيير كبير
ثلاث دوائر، والتجزئة هي ما يفصل الدائرة الثالثة عن الأوليين
  • داخل البيئة: كل نظام يمر به رقم البطاقة. وفي قصتنا هذا يعني خدمة الدفع القديمة، وملفات سجلاتها، ونظام جمع السجلات الذي نسخت إليه، والنسخ الاحتياطية لهذا النظام، وكل من له حق قراءتها.
  • المتصل بها: الأنظمة التي لا يمر بها الرقم ولكنها تتصل بالبيئة دون قيود، أو يمكن أن تؤثر على أمنها، مثل خادم إدارة الهوية الذي يتحقق منه من يدخل إليها.
  • خارج النطاق: ما عزل عن البيئة بالتجزئة Segmentation، وهي بحسب المسرد عزل مكونات النظام التي تحفظ البيانات أو تعالجها أو ترسلها عن التي لا تفعل، كما شرحنا أدواتها في مقال تقسيم الشبكة. ومسرد المجلس يعرف تحديد النطاق Scoping بأنه تحديد كل مكونات النظام والأشخاص والعمليات التي تدخل في التقييم.

والإصدار الرابع جعل تأكيد النطاق متطلباً قائماً بذاته: ينص المتطلب 12.5.2 على أن يوثق النطاق ويؤكد مرة كل 12 شهراً على الأقل، وعند أي تغيير كبير في البيئة، وأن يشمل التأكيد في حده الأدنى:

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

ولو كان الفريق يطبق هذا المتطلب لظهر سطر DEBUG في أول مراجعة: البند الثالث يطلب صراحة البحث عن البيانات «خارج البيئة المعرفة حالياً»، وهذا بالضبط ما كانت عليه سجلات النسخة القديمة.

صفحة الدفع: النطاق يضيق ولا يختفي

أكبر قرار يقلل النطاق للتاجر الإلكتروني هو ألا يمر رقم البطاقة على سيرفراته أصلاً، كما في الصورة التالية:

أربع محطات من اليمين إلى اليسار: العميل Browser يكتب البطاقة في حقل المزود، ثم مزود الدفع PSP iframe يستلم الرقم ويحفظه في خزنته، ثم التوكن Token قيمة بديلة تعود لصفحتك، ثم سيرفرك Merchant API يطلب الخصم بالتوكن فقط، وتحتها أن النطاق يضيق ولا يختفي لأن صفحتك وسكربتاتها ما زالت مسؤوليتك بحسب 6.4.3 و11.6.1
سيرفرك لا يرى الرقم، ولكن صفحتك ما زالت تعرض الحقل

وفي هذا النموذج يكتب العميل بيانات بطاقته في حقل يستضيفه مزود الدفع داخل إطار iframe في صفحة التاجر، أو في صفحة دفع على موقع المزود، فيستلمها المزود ويعيد للتاجر توكن يستخدمه للخصم. والتاجر الذي يعمل بهذا النموذج قد يكون مؤهلاً لاستمارة تقييم ذاتي Self-Assessment Questionnaire مختصرة هي SAQ A، بدلاً من SAQ D التي تغطي المعيار كله تقريباً. ولكن الإصدار الرابع أضاف إلى هذا النموذج مسؤوليتين:

  • سكربتات صفحة الدفع (6.4.3 و11.6.1): يتطلب 6.4.3 أن تدار كل السكربتات التي تحمل في صفحة الدفع وتنفذ في متصفح العميل: بتأكيد أن كلاً منها مصرح به، وبطريقة تضمن سلامته، وبقائمة بها مع مبرر كل سكربت. ويتطلب 11.6.1 آلية لكشف التغيير والعبث تنبه الفريق إلى أي تعديل غير مصرح به في ترويسات HTTP ومحتوى صفحة الدفع كما يستلمها متصفح العميل. والسبب أن سكربتاً خبيثاً في الصفحة يستطيع أن يقرأ ما يكتبه العميل، أو يضع حقلاً مزيفاً فوق حقل المزود.
  • فحص الثغرات: بحسب الحوار المنشور على مدونة المجلس، أصبح التاجر الذي يكمل SAQ A مطالباً بفحص ثغرات خارجي مرة كل ثلاثة أشهر على الأقل بواسطة جهة فحص معتمدة Approved Scanning Vendor.

وفي إعلان 28 فبراير 2025 وضح المجلس شرط الأهلية الجديد في SAQ A: أن يؤكد التاجر أن موقعه ليس عرضة لهجمات سكربتات قد تؤثر على أنظمة التجارة الإلكترونية لديه. ويمكنه ذلك إما بتقنيات مثل ما في 6.4.3 و11.6.1، ينفذها هو أو طرف ثالث، وإما بتأكيد من مزود الدفع الملتزم بالمعيار أن حله يتضمن تقنيات تحمي صفحة التاجر إذا نفذ بحسب تعليماته. ويوضح الإعلان أن هذا الشرط يخص التاجر الذي يضمن حقل المزود في صفحته، لا التاجر الذي يحول العميل إلى صفحة المزود، ولا من يرسل للعميل رابط دفع على موقع المزود. وينصح الإعلان التاجر بأن يتأكد من البنك المحصل أو من شبكات البطاقات أن SAQ A هي الاستمارة المناسبة لبيئته، وهذا ما نكرره هنا: نوع الاستمارة يحدده وصف بيئتك ومن يطلب منك الامتثال، لا اختيارك.

حفظ رقم البطاقة: أربع طرق مقبولة

إذا احتاج العمل أن يحفظ رقم البطاقة، فالمتطلب 3.5.1 ينص على أن يكون غير مقروء في كل مكان يحفظ فيه، بإحدى الطرق الأربع في الصورة التالية:

أربع بطاقات: تجزئة باتجاه واحد One-way hash للرقم كاملاً وبمفتاح سري بحسب 3.5.1.1، واقتطاع Truncation بحذف جزء من الرقم ولا يجتمع مع التجزئة، وتوكن فهرسي Index token قيمة عشوائية تقابل الرقم في خزنة، وتشفير قوي Strong cryptography مع إدارة المفاتيح، وتحتها أن الإخفاء عند العرض Masking متطلب مستقل هو 3.4.1 والحد الأعلى للظاهر BIN وآخر أربعة أرقام
أربع طرق للحفظ، والعرض له متطلب مستقل
  • التجزئة باتجاه واحد One-way hash: للرقم كاملاً، مبنية على تشفير قوي. والمتطلب 3.5.1.1 الذي أصبح ملزماً منذ 31 مارس 2025 يجعلها تجزئة بمفتاح Keyed Cryptographic Hash للرقم كاملاً، مع عمليات وإجراءات لإدارة المفتاح. ويعرف المسرد هذه التجزئة بأنها دالة تجزئة تتضمن مفتاحاً سرياً مولداً عشوائياً لتقاوم هجمات التخمين.
  • الاقتطاع Truncation: حذف جزء من الرقم عند حفظه. ولا يجوز أن تستخدم التجزئة لتحل محل الجزء المقتطع، وإذا وجدت في البيئة نسخة مجزأة ونسخة مقتطعة من نفس الرقم، أو صيغتا اقتطاع مختلفتان له، فيجب وجود ضوابط إضافية تمنع ربطهما لإعادة بناء الرقم الأصلي.
  • التوكن الفهرسي Index token: بحسب المسرد قيمة عشوائية من جدول قيم عشوائية تقابل رقماً بعينه، وهي ما سنفصله في الترميز.
  • التشفير القوي Strong cryptography: مع عمليات وإجراءات لإدارة المفاتيح، وهي متطلبات تفصلها بقية المتطلب الثالث. وشرحنا الفرق بين التجزئة والتشفير وإدارة المفاتيح في مقال التشفير للمطورين.

وتنص ملاحظة التطبيق في 3.5.1.1 على أن الحماية تنطبق على التخزين الأساسي، كقواعد البيانات والملفات النصية والجداول، وعلى غير الأساسي، كالنسخ الاحتياطية وسجلات التدقيق وسجلات الاستثناءات وتتبع الأخطاء. وهذا السطر وحده يكفي لتعرف أن سجل DEBUG في قصتنا مخالفة مباشرة، لا منطقة رمادية. أما عرض الرقم على الشاشة أو الإيصال فله متطلب مستقل هو 3.4.1: أن يخفى الرقم عند العرض بحيث لا يظهر أكثر من رقم تعريف المصدر BIN وآخر أربعة أرقام، إلا لمن له حاجة عمل موثقة. والمسرد يفرق بين الاثنين بوضوح: الإخفاء Masking لما يعرض أو يطبع، والاقتطاع Truncation لما يحفظ أو يعالج أو يرسل إلكترونياً.

الترميز Tokenization: كيف يعمل؟

أصدر المجلس في أغسطس 2011 ملحق إرشادات الترميز، وهو ما زال المرجع المنشور للمجلس في هذا الموضوع، مع التنبيه إلى أنه كتب في زمن الإصدار 2.0 فأرقام المتطلبات فيه قديمة. ويعرف الملحق الترميز بأنه عملية يستبدل فيها رقم البطاقة بقيمة بديلة تسمى التوكن، وإلغاء الترميز De-tokenization هو العكس: استرداد الرقم مقابل التوكن. وأمن التوكن يعتمد أساساً على استحالة معرفة الرقم الأصلي من التوكن وحده. ويضع الملحق مبدأين يجب أن يبدأ بهما أي نقاش عن الترميز:

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

والصورة التالية تلخص عملية الترميز كما يصفها الملحق:

أربع درجات: التطبيق يرسل الرقم Request مع بيانات التحقق من هويته، ثم نظام الترميز يتحقق Authenticate ويسجل أي فشل للمراقبة، ثم الخزنة تحفظهما Card data vault يولد التوكن أو يعيد الموجود، ثم التوكن يعود للتطبيق Token والرقم لا يخرج إلا لمصرح له
أربع خطوات، والخزنة في قلبها

توليد التوكن

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

ويفرق الملحق بين التوكن لمرة واحدة Single-use الذي يمثل عملية واحدة بعينها، والتوكن متعدد الاستخدام Multi-use الذي يمثل رقماً بعينه ويقابله دائماً بنفس القيمة، فيسمح بتتبع البطاقة عبر عمليات كثيرة. والاشتراكات المتجددة في قصتنا تحتاج النوع الثاني، لأن التجديد الشهري يجب أن يخصم من نفس البطاقة دون أن يدخلها العضو كل مرة. ويعرض الملحق أمثلة لصيغ التوكن: أحرف وأرقام، أو أرقام فقط بطول الرقم، أو صيغة تحتفظ بأول ستة وآخر أربعة من الرقم وتستبدل الوسط.

الخزنة والمفاتيح

خزنة بيانات البطاقات Card Data Vault هي المستودع المركزي للأرقام وتوكناتها، ويصفها الملحق بأنها أكثر أجزاء النظام جذباً للمهاجمين، لأن اختراقها قد يعني اختراق نظام الترميز كله، وقد تستحق ضوابط فوق ما يطلبه المعيار. وأي مكون يستطيع استرجاع الرقم مقابل التوكن يجب أن يحمى بحسب المعيار، والقدرة على الاسترجاع يجب أن تقتصر على أفراد وتطبيقات وأنظمة مصرح لها تحديداً. أما المفاتيح، سواء التي تشفر الأرقام في الخزنة أو التي تولد التوكن، فاختراقها يعني اختراق كل التوكنات الحالية والمستقبلية المولدة بها، ولذلك يجب ألا تكون متاحة لأي تطبيق أو نظام أو مستخدم خارج نظام الترميز الآمن.

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

التمييز بين التوكن والرقم

يطلب الملحق أن يتضمن حل الترميز طريقة للتمييز بين التوكن والرقم الحقيقي، لأن التوكن الذي يشبه الرقم في الشكل والطول قد يخدع المراجع، فيظن أن قاعدة بيانات فيها أرقام حقيقية مليئة بتوكنات، أو العكس، فيخطئ في تحديد النطاق. وبعض التوكنات مصممة لتحاكي صيغة الأرقام، فلا يستطيع الإنسان التمييز بينهما بالنظر، وقد يحتاج أداة أو دالة للتحقق. وهذه نقطة سنراها في المختبر: الفحص الذي يبحث عن أرقام البطاقات في السجلات يحتاج أن يعرف شكل التوكن عندك حتى لا يبلغ عنه، وأن يعرف شكل أرقامك الأخرى حتى لا يغرق في التنبيهات.

نماذج النشر والمسؤوليات

يذكر الملحق ثلاثة نماذج: حل داخلي يديره التاجر في بنيته، وحل خارجي يفوض فيه التاجر الإدارة لمقدم خدمة ترميز Tokenization Service Provider خارج بنيته، وحل هجين يجمع الاثنين. وفي الحل الخارجي أو الهجين قد تنتقل مسؤولية بعض المكونات إلى مقدم الخدمة، ولكن بعض المتطلبات تبقى على التاجر دائماً، مثل نقطة استلام الرقم وأي نقطة لإلغاء الترميز، وسياسات إدارة مقدمي الخدمة. ومن مسؤوليات التاجر التي يعددها الملحق: تقييم المخاطر عند اختيار المقدم، وعقد يقر فيه المقدم بمسؤوليته عن أمن البيانات التي يعالجها، ومراقبة حالة التزامه بالمعيار مرة في السنة على الأقل، ومراجعة سجلات تعامل التاجر مع نظام الترميز بانتظام، وخطط للاستجابة للحوادث والتعافي إذا تعطل نظام الترميز أو اخترق. والتاجر في النهاية صاحب المسؤولية النهائية عن التنفيذ الصحيح لأي حل ترميز يستخدمه.

ثلاثة أنواع من التوكن

كلمة «توكن» في المدفوعات تطلق على ثلاثة أشياء مختلفة، والصورة التالية تفرق بينها:

ثلاث بطاقات: توكن مزود الدفع PSP token يعمل عند المزود الذي أصدره فقط، وتوكن الشبكة EMV payment token يقيده المصدر بتاجر أو جهاز، وخزنتك الداخلية In-house vault أنت تحفظ الأرقام والخزنة في النطاق، وتحتها أن كل توكن يقلل قيمة البيانات ولكن من يملك الخزنة يملك النطاق
نفس الكلمة لثلاثة أنظمة، والسؤال من يملك الخزنة
  • توكن مزود الدفع: ما يعيده المزود عندما يستلم البطاقة من حقله أو صفحته. التاجر يحفظه ويخصم به، ولكنه لا يعمل إلا عند هذا المزود، والرقم الحقيقي في خزنة المزود. وهذا ما تستخدمه الشركة في قصتنا للاشتراكات المتجددة، وما شرحنا أثره على تبديل المزود في مقال بوابات الدفع، فنقل البطاقات المحفوظة إلى مزود آخر عملية تحتاج تعاون المزود القديم.
  • توكن الشبكة EMV Payment Token: تقول صفحة EMVCo إن الترميز بحسب مواصفاتها يزيل أثمن بيانات للمحتال، وهو رقم البطاقة، ويضع مكانه قيمة بديلة فريدة، وإن هذا التوكن مقيد في استخدامه، مثلاً بتاجر أو جهاز أو سيناريو دفع بعينه. وهذا ما تستخدمه محافظ الجوال عندما تضيف بطاقتك إليها، كما ذكرنا في مقال المحافظ الرقمية. وتذكر الصفحة أن مواصفة الإطار التقني v2.3 نشرت في 19 أكتوبر 2021، وأن الإصدار v2.4 نشر في 9 يوليو 2026.
  • الخزنة الداخلية: أن تبني الشركة نظام ترميز خاصاً بها، فتحفظ الأرقام مشفرة في خزنتها، وتوزع التوكنات على بقية أنظمتها. وهذا يخرج بقية الأنظمة من النطاق إذا نفذ جيداً، ولكن الخزنة نفسها ومن يصل إليها داخل النطاق بكامل متطلباته. وله منطق عند من يتعامل مع عدة مزودين ويريد أن يوجه العمليات بينهم ببطاقة محفوظة واحدة، وثمنه أن تصبح الشركة مسؤولة عن أصعب جزء في المعيار.

المختبر الأول: البحث عن أرقام البطاقات في السجلات

أول خطوة بعد اكتشاف السطر كانت معرفة حجم المشكلة: كم سطراً في السجلات فيه رقم بطاقة؟ والبرنامج التالي يحاكي ذلك بسجلات يوم كامل مولدة لخدمة دفع: عشرون ألف سطر، في كل منها رقم طلب من 16 خانة، ونسبة صغيرة منها أسطر DEBUG فيها جسم الطلب برقم بطاقة. والأرقام في هذه الأسطر ثلاثة من بطاقات الاختبار التي ينشرها Stripe كمثال، لا بطاقات حقيقية. والفحص يمر بثلاث مراحل: كل سلسلة أرقام من 13 إلى 19 خانة، ثم فحص رقم التحقق Luhn الذي تحمله أرقام البطاقات في خانتها الأخيرة، ثم مع الخيار --brand بادئة تقريبية لشبكتي Visa وMastercard. والخيار --short-ids يجعل أرقام الطلبات من 12 خانة، والخيار --tokenize يجعل الخدمة ترسل توكن بدلاً من الرقم:

# scan.py: find card numbers (PAN) that leaked into application logs; test card numbers only
import sys, re, random, secrets

TEST_PANS = ["4242424242424242", "5555555555554444", "4000056655665556"]   # public test cards (Stripe docs)

def luhn_ok(digits):
    total = 0
    for i, ch in enumerate(reversed(digits)):
        d = int(ch)
        if i % 2 == 1:
            d *= 2
            if d > 9: d -= 9
        total += d
    return total % 10 == 0

vault = {}                                   # token -> PAN; lives only inside the tokenization service
def tokenize(pan):
    tok = "tok_" + secrets.token_hex(8)      # random index token, not derived from the PAN
    vault[tok] = pan
    return tok

# 1) generate one day of synthetic logs from a checkout service
rnd = random.Random(7)
lines = []
for i in range(20000):
    order = str(rnd.randrange(10**15, 10**16))           # 16-digit order id, looks like a card number
    if "--short-ids" in sys.argv:
        order = order[:12]                              # the second fix: ids that cannot look like a PAN
    kind = rnd.random()
    if kind < 0.002:                                    # the bug: a debug line dumps the request body
        pan = rnd.choice(TEST_PANS)
        if "--tokenize" in sys.argv:
            pan = tokenize(pan)                         # the fix: the body only ever carries a token
        lines.append(f'DEBUG checkout body={{"order":"{order}","card":"{pan}","exp":"12/34"}}')
    else:
        lines.append(f"INFO order={order} status=authorized amount={rnd.randrange(50, 900)}.00")

# 2) scan: 13-19 digit runs, then Luhn, then (with --brand) a rough Visa/Mastercard prefix check
cand = re.compile(r"(?<!\d)\d{13,19}(?!\d)")
runs = luhn_pass = brand = 0
hits = set()
for n, line in enumerate(lines, 1):
    for m in cand.finditer(line):
        s = m.group(); runs += 1
        if not luhn_ok(s): continue
        luhn_pass += 1
        if "--brand" in sys.argv and not s.startswith(("4", "51", "52", "53", "54", "55", "2")): continue
        brand += 1
        if s in TEST_PANS: hits.add(n)

print(f"log lines {len(lines):,}  digit runs {runs:,}  pass Luhn {luhn_pass:,}  reported {brand:,}")
print(f"lines with a real (test) PAN: {len(hits)}  false alarms: {brand - sum(1 for _ in hits)}")
print(f"tokens in vault: {len(vault)}")

وعند تشغيله بالأمر python scan.py على Python 3.13 سوف يكون المخرج كما يلي:

log lines 20,000  digit runs 20,039  pass Luhn 1,962  reported 1,962
lines with a real (test) PAN: 39  false alarms: 1923
tokens in vault: 0

في الكود والمخرج أعلاه لاحظ التالي:

  • الفحص وجد كل الأسطر الـ 39 التي فيها رقم بطاقة اختبار، ولكنه أبلغ معها عن 1,923 سطراً آخر كاذباً، أي أن 98% من التنبيهات لا قيمة لها.
  • السبب أرقام الطلبات: كل رقم طلب من 16 خانة، وفحص Luhn يقبل رقماً من كل عشرة أرقام عشوائية تقريباً، لأن الخانة الأخيرة تطابق مجموع التحقق بالصدفة مرة من عشر. وهذا ما ظهر: 1,962 من أكثر من عشرين ألفاً.
  • الفحص لا يعرف شيئاً عن سياق السطر، فهو يرى سلسلة أرقام لا حقلاً اسمه card أو order، وهذا ما يجعله يعمل على أي سجل، وما يجعله مزعجاً في نفس الوقت.

مشكلة ظهرت: التنبيهات الكاذبة

هذه أول مشكلة واجهناها مع المختبر، وهي نفس مشكلة أدوات اكتشاف البيانات الحقيقية: فريق يتلقى ألفي تنبيه يومياً سيتجاهلها كلها، ومعها الـ 39 الحقيقية. فجربنا أولاً تضييق الفحص بالبادئة بالأمر python scan.py --brand:

log lines 20,000  digit runs 20,039  pass Luhn 1,962  reported 594
lines with a real (test) PAN: 39  false alarms: 555
tokens in vault: 0

البادئة خفضت التنبيهات من 1,962 إلى 594، ولكن 555 منها ما زالت كاذبة، لأن أرقام الطلبات العشوائية تبدأ أحياناً بنفس البادئات. فالتضييق من جهة الفحص له حد، والحل الأفضل كان من جهة البيانات: أن تكون أرقام الطلبات بصيغة لا تشبه أرقام البطاقات أصلاً. وبالأمر python scan.py --brand --short-ids، أي بأرقام طلبات من 12 خانة:

log lines 20,000  digit runs 39  pass Luhn 39  reported 39
lines with a real (test) PAN: 39  false alarms: 0
tokens in vault: 0

الآن لم يجد الفحص إلا 39 سلسلة أرقام، كلها أرقام بطاقات حقيقية في نظر الفحص، وصفر تنبيهات كاذبة. والدرس الذي خرج به الفريق أن تصميم المعرفات جزء من أمن البطاقات: معرف الطلب أو العميل الذي يشبه رقم بطاقة يجعل كل أداة اكتشاف أقل فائدة، وهو ما يقصده ملحق الترميز عندما يطلب التمييز بين التوكن والرقم، ويمتد منطقه إلى كل معرف في النظام. وهذا يشبه ما رأيناه في مقال اكتشاف الأسرار المسربة، حيث تحتاج أدوات الفحص قواعد للاستثناء حتى تبقى تنبيهاتها مسموعة.

ماذا لو أرسلت الخدمة توكن بدلاً من الرقم؟

الآن نشغل نفس اليوم بالخيار --tokenize، فتمر البطاقة عبر دالة الترميز قبل أن تصل إلى أي سطر سجل، والتوكن قيمة عشوائية تبدأ بـ tok_، والرقم يبقى في قاموس vault الذي يمثل الخزنة:

log lines 20,000  digit runs 0  pass Luhn 0  reported 0
lines with a real (test) PAN: 0  false alarms: 0
tokens in vault: 39

لا يوجد أي سلسلة أرقام في السجلات، لا كاذبة ولا حقيقية، و39 توكناً في الخزنة. وسطر DEBUG الخاطئ ما زال يكتب جسم الطلب كاملاً، فالخطأ في السجل لم يصلح، ولكنه لم يعد يحمل رقم بطاقة. وهذا هو المعنى العملي للترميز: لا يمنع الأخطاء، وإنما يجعل البيانات التي تتسرب بسببها بلا قيمة لمن يقرؤها. ولاحظ أن التوكن يبدأ بـ tok_ وفيه أحرف، فلا يمكن أن يخلطه فحص الأرقام برقم بطاقة، وهذا تطبيق مباشر لمبدأ التمييز. ولكن الخزنة نفسها، وهي هنا قاموس في الذاكرة، هي في النظام الحقيقي أكثر الأجزاء حساسية، وتحتاج كل ما وصفه الملحق.

ولاحظ أيضاً أن دالة tokenize في المختبر تولد توكناً جديداً في كل مرة، حتى لو تكررت نفس البطاقة، فهي أقرب إلى التوكن لمرة واحدة. والبطاقات الثلاث تكررت في 39 سطراً، فصار في الخزنة 39 توكناً لثلاثة أرقام فقط. وهذا مناسب للسجلات، لأن أحداً لا يستطيع أن يربط سطرين ببطاقة واحدة من التوكن وحده، ولكنه لا يناسب الاشتراكات المتجددة التي تحتاج أن تعرف أن هذه البطاقة هي نفس بطاقة الشهر الماضي. ولذلك يحتاج نظام الترميز الحقيقي أن يقرر لكل استخدام أي نوع من التوكن يعطيه، كما يقول الملحق.

أعمدة: Luhn فقط 1,962 تنبيهاً، وLuhn وبادئة الشبكة 594، وأرقام طلبات أقصر 39 كلها حقيقية، ومع الترميز 0، وتحتها أنها من 20,000 سطر سجل مولد فيها 39 سطراً تسرب منها رقم بطاقة اختبار
التنبيهات من 1,962 إلى 39 حقيقية، ثم صفر مع الترميز

المختبر الثاني: لماذا لا تجتمع التجزئة مع الاقتطاع؟

وجد الفريق أثناء المراجعة أن جدولاً قديماً في قاعدة البيانات يحفظ لكل بطاقة أول ستة وآخر أربعة أرقام لعرضها للعضو، ومعها تجزئة SHA-256 للرقم كاملاً لاكتشاف البطاقة المكررة. ويبدو هذا آمناً، فلا رقم كامل في الجدول. ولكن ملاحظة المتطلب 3.5.1 تقول إن إعادة بناء الرقم الأصلي جهد بسيط نسبياً لمن يملك النسختين المقتطعة والمجزأة، وسؤال المجلس رقم 1308 (يونيو 2025) يقول إن أبسط حل ألا تحفظ الاثنين، وإن التجزئة بمفتاح بحسب 3.5.1.1 ضابط صالح لمنع الربط. والبرنامج التالي يقيس ذلك على رقم بطاقة اختبار عام:

# hashtrunc.py: why PCI DSS 3.5.1 warns about storing a hash and a truncated PAN side by side; test card only
import sys, hashlib, hmac, secrets, time

pan = "4242424242424242"                         # public test card number
truncated = pan[:6] + "******" + pan[-4:]        # first six and last four, as many systems keep it
plain_hash = hashlib.sha256(pan.encode()).hexdigest()
key = secrets.token_bytes(32)                    # the HMAC key lives in a key store, never next to the data
keyed_hash = hmac.new(key, pan.encode(), hashlib.sha256).hexdigest()

def luhn_ok(digits):
    total = 0
    for i, ch in enumerate(reversed(digits)):
        d = int(ch)
        if i % 2 == 1:
            d *= 2
            if d > 9: d -= 9
        total += d
    return total % 10 == 0

target = keyed_hash if "--keyed" in sys.argv else plain_hash
start = time.perf_counter()
tried = 0
found = None
for middle in range(10**6):                      # only six digits are unknown
    cand = pan[:6] + f"{middle:06}" + pan[-4:]
    if not luhn_ok(cand):
        continue                                  # the check digit removes nine of every ten guesses
    tried += 1
    if hashlib.sha256(cand.encode()).hexdigest() == target:   # the attacker does not have the key
        found = cand
        break
print(f"stored: {truncated}  {'HMAC-SHA256 (keyed)' if '--keyed' in sys.argv else 'SHA-256 (no key)'}")
print(f"guesses after Luhn: {tried:,}  time: {time.perf_counter()-start:.2f}s  recovered: {found or 'no'}")

تشغيله بالأمر python hashtrunc.py يعطي:

stored: 424242******4242  SHA-256 (no key)
guesses after Luhn: 42,425  time: 2.39s  recovered: 4242424242424242

وتشغيله بالأمر python hashtrunc.py --keyed يعطي:

stored: 424242******4242  HMAC-SHA256 (keyed)
guesses after Luhn: 100,000  time: 9.28s  recovered: no

في الكود والمخرجين أعلاه لاحظ التالي:

  • من ست عشرة خانة لم يبق مجهولاً إلا ست، أي مليون احتمال، وفحص Luhn يحذف تسعة من كل عشرة فيبقى مئة ألف، ووجد البرنامج الرقم بعد 42,425 محاولة في 2.39 ثانية على حاسوب عادي، بلغة مفسرة، دون أي تحسين.
  • مع HMAC-SHA256 بمفتاح سري جرب البرنامج كل الاحتمالات المئة ألف دون أن يطابق أي منها، لأن من يملك الجدول لا يملك المفتاح، فلا يستطيع حساب نفس التجزئة. والمفتاح في البرنامج مولد عشوائياً في كل تشغيل، وفي النظام الحقيقي يحفظ في مخزن مفاتيح منفصل عن قاعدة البيانات، وهذا شرط فعاليته كله.
  • التجزئة دون مفتاح ليست حماية لرقم البطاقة بأي معنى عملي، لأن مساحة الأرقام صغيرة ومنظمة، بعكس كلمات المرور الطويلة. ولهذا جعل الإصدار الرابع التجزئة بمفتاح متطلباً ملزماً.
بطاقتان: تجزئة بلا مفتاح SHA-256 في 2.39 ثانية بـ 42,425 محاولة واسترجع الرقم كاملاً، وتجزئة بمفتاح HMAC-SHA256 لا شيء بعد 100,000 محاولة دون المفتاح لا تطابق، وتحتهما أنه رقم بطاقة اختبار عام وستة أرقام مجهولة فقط بين أول ستة وآخر أربعة
التجزئة دون مفتاح مع الاقتطاع لا تحمي شيئاً

وغير الفريق الجدول: أبقى أول ستة وآخر أربعة للعرض، واستبدل التجزئة البسيطة بتجزئة بمفتاح يحفظ في مخزن المفاتيح بعيداً عن قاعدة البيانات، ثم سأل نفسه سؤالاً أبسط: هل نحتاج اكتشاف البطاقة المكررة أصلاً؟ وعندما لم يجد حاجة عمل حقيقية حذف العمود كله، فأفضل رقم محمي هو الرقم الذي لا تحفظ منه شيئاً.

بيئات الاختبار والتطوير

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

ما الذي فعله الفريق؟

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

  • الاحتواء: حصر من قرأ السجلات، وتقييد الوصول إليها فوراً، ثم التواصل مع مزود الدفع والبنك المحصل بحسب خطة الاستجابة للحوادث، لأن قرار ما يلزم بعد ذلك ليس قرار الفريق وحده.
  • الحذف الآمن: حذف الأسطر من كل مكان وصلت إليه: الخادم، ونظام جمع السجلات، والنسخ الاحتياطية بحسب سياسة الاحتفاظ، مع توثيق ما حذف ومتى.
  • إغلاق المصدر: إزالة النسخة القديمة من صفحة الدفع نهائياً، ومنع تسجيل أجسام الطلبات في خدمة الدفع، كما ناقشنا في مقال السجلات التي تساعدك، حيث السجل الجيد يحمل المعرفات لا البيانات.
  • الفحص المستمر: فحص يومي للسجلات بقواعد المختبر، مع تغيير صيغة أرقام الطلبات حتى تبقى التنبيهات قليلة ومسموعة.
  • النطاق: أول مراجعة نطاق بحسب 12.5.2، بمخطط لتدفق بيانات البطاقة في كل مراحل الدفع، وقائمة بكل سكربت في صفحة الدفع ومبرره.

متى تبني خزنة داخلية فعلاً؟

بعد كل ما سبق سأل المؤسس: هل نبني خزنتنا الخاصة حتى لا نعتمد على توكن مزود واحد؟ وكان جواب الفريق بالأسئلة: هل نتعامل فعلاً مع أكثر من مزود ونحتاج توجيه نفس البطاقة المحفوظة بينهم؟ هل عندنا فريق يدير أنظمة داخل النطاق بكامل متطلباته، من الشبكة إلى إدارة المفاتيح والمراقبة، ويتحمل تقييماً خارجياً؟ هل تكلفة ذلك أقل من تكلفة الاعتماد على مزود واحد؟ وكانت الإجابات كلها لا في هذه المرحلة. فالخزنة الداخلية قرار يناسب من صار التوجيه بين المزودين جزءاً من عمله الأساسي، كما ناقشنا في مقال بوابات الدفع، لا من يريد تجنب الاعتماد على مزود من باب الاحتياط. وبين الطرفين خيار ثالث يذكره ملحق الترميز: مقدم خدمة ترميز مستقل عن مزودي الدفع، يحفظ الأرقام ويوزعها على مزودين متعددين، فيبقى عبء الخزنة عليه، وتبقى على الشركة مسؤوليات إدارة مقدم الخدمة ومراقبته.

أخطاء شائعة

الخطألماذا يضرالبديل
«نستخدم مزوداً فنحن خارج PCI»صفحة الدفع وسكربتاتها ما زالت في النطاقتطبيق 6.4.3 و11.6.1 أو تأكيد المزود
تسجيل أجسام الطلبات في خدمة الدفعأرقام البطاقات في السجلات والنسخ الاحتياطيةتسجيل المعرفات فقط وفحص دوري
حفظ رمز التحقق لتسهيل التجديدمحظور بعد التفويض ولو مشفراً (3.3.1)توكن متعدد الاستخدام من المزود
تجزئة الرقم دون مفتاحتسترجع بالتخمين، خاصة مع الاقتطاعتجزئة بمفتاح (3.5.1.1) أو توكن
معرفات تشبه أرقام البطاقاتأدوات الاكتشاف تغرق في التنبيهاتصيغ معرفات مميزة
خزنة داخلية «لأنها أسهل»الخزنة ومن يصل إليها في النطاق بكاملهتوكن المزود إلا لحاجة حقيقية
تحديد النطاق مرة واحدةالبيانات تظهر في أماكن جديدة مع كل تغييرمراجعة سنوية وعند كل تغيير كبير (12.5.2)

قائمة تحقق

  • أعرف من يطلب منا الامتثال (البنك المحصل أو مزود الدفع)، وبأي استمارة نثبته، وأعرف الإصدار الساري من صفحة المجلس.
  • رقم البطاقة لا يمر على سيرفراتنا، أو إن مر فنعرف كل مكان يمر به ويحفظ فيه.
  • لا نحفظ رمز التحقق ولا بيانات الشريط ولا PIN بعد التفويض في أي مكان، ومنها السجلات.
  • كل سكربت في صفحة الدفع مصرح به ومبرر ومحمي من التعديل، وعندنا تنبيه عند أي تغيير.
  • أي رقم محفوظ غير مقروء بإحدى الطرق الأربع، ولا تجزئة دون مفتاح، ولا نسختان قابلتان للربط.
  • العرض لا يظهر أكثر من BIN وآخر أربعة إلا لمن له حاجة موثقة.
  • نفحص السجلات والنسخ الاحتياطية دورياً بحثاً عن أرقام البطاقات، ومعرفاتنا لا تشبهها.
  • مخطط تدفق البيانات محدث، ونراجع النطاق سنوياً وعند كل تغيير كبير.
  • الاختبارات ببطاقات الاختبار التي ينشرها المزود فقط.

الخلاصة

وصلنا لنهاية الموضوع، وأهم ما فيه:

  • PCI DSS v4.0.1 مراجعة محدودة بلا متطلبات مضافة أو محذوفة، والمتطلبات الجديدة للإصدار الرابع سارية منذ 31 مارس 2025، ومن يلزمك بها البنك المحصل أو شبكات البطاقات.
  • بيانات حامل البطاقة تحمى إذا حفظت، وبيانات التحقق الحساسة لا تحفظ بعد التفويض أبداً.
  • النطاق كل ما يحفظ البيانات أو يعالجها أو يرسلها وما يتصل به دون قيود، والتجزئة تخرج الباقي، ويؤكد كل سنة.
  • حقل المزود يضيق النطاق ولا يلغيه: سكربتات الصفحة وفحص الثغرات ما زالت عليك.
  • الترميز يجعل البيانات المتسربة بلا قيمة، ولكن من يملك الخزنة يملك أصعب جزء في المعيار.
  • في المختبر انخفضت التنبيهات من 1,962 إلى 39 حقيقية بتغيير صيغة المعرفات، ثم إلى صفر مع الترميز، واسترجعت التجزئة دون مفتاح الرقم من نسخته المقتطعة في ثانيتين ونصف.

وبقية مقالات قسم التقنية المالية والمدفوعات:

دليلكيف يعمل الدفع بالبطاقة؟ التفويض Authorization والتسويةمن ضغطة «ادفع» إلى آخر اعتراض: التفويض و3D Secure والتحصيل والتسوية والاسترداد والاعتراض، مع مختبر لأحداث مزود الدفع ومطابقتها.دليلبوابات الدفع Payment Gateways في السعودية والبدائل المفتوحةكيف تختار مزود الدفع في المملكة بما تنشره صفحاتهم الرسمية، وأين يقف Stripe والبرمجيات المفتوحة، مع مختبر التحويل بين مزودين.دليلالمحافظ الرقمية Digital Wallets: الأنواع والترخيص والبناءأنواع المحافظ الرقمية وتراخيص النقود الإلكترونية في المملكة وحدودها، وحماية أموال العملاء، مع مختبر للحدود والمطابقة اليومية.دليلالمحفظة الرقمية من الداخل: دفتر القيد المزدوج Ledgerكيف تبني محفظة رقمية لا يضيع فيها ريال ولا يخصم مرتين، بالقيد المزدوج والمعاملات والمطابقة مع مزود الدفع.دليلالتشفير للمطورين: ماذا تستخدم ولماذا لا تخترع خوارزميتكأي هاش تستخدم لكلمات المرور، ومتى تحتاج التشفير المتماثل أو غير المتماثل، وأين تحفظ المفاتيح بأمان في تطبيقك.

سجل التحديثات

  • أكتوبر 2026: كتابة المقال، وتشغيل مختبري فحص السجلات والتجزئة مع الاقتطاع على Python 3.13.3 ببطاقات اختبار وبيانات مولدة، والتحقق من صفحة PCI DSS ومسرد المجلس وإعلاناته وملحق إرشادات الترميز وسؤاله رقم 1308 واستمارة SAQ D وصفحة EMVCo بتاريخ 27 أكتوبر 2026.
نشرة عرب رووت | ArabRoot

معرفة تستحق مكاناً في بريدك.

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

يمكنك إلغاء الاشتراك متى شئت. الخصوصية

تم استلام طلبك. افتح بريدك واضغط رابط التأكيد لإتمام الاشتراك.