مقالات معمّقة حول التكنولوجيا التي تشكّل المستقبل.

ماسحات الأمان بالذكاء الاصطناعي تكشف ديون تقنية مدفونة

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

قفص طيور في نفق منجم فحم، وشقوق متوهجة تمتد عبر جدران الصخر خلفه
PHP2Shell كان بمثابة الإنذار المبكر: أعطال تجاهلناها سنوات تبيّن أنها شقوق بنيوية.

وصل بلاغ عن خلل إلى متتبع مشروع PHP في عام 2024. كان يصف حالة نفاد الذاكرة (out-of-memory)، وهو النوع الذي يُسقط العملية ويُزعج، لكنه في التسلسل الهرمي غير الرسمي للأخطاء يُعامل بلا اكتراث. ظل البلاغ معلقاً. ثم، خلال تدقيق أمني مستقل لـPHP برعاية OpenAI، أمضى باحث في شركة الأمن Calif، يعمل بأدوات فحص تعتمد على الذكاء الاصطناعي وخبرته العميقة، نحو أسبوعين في تحويل ذلك العطل المزعج إلى تنفيذ كود عن بُعد (RCE). أي خادم يشغّل نسخة PHP معرّضة للخطر كان يمكن إجباره على تنفيذ كود المهاجم أو تسريب بيانات حساسة. ومن المواقع التي شملها نطاق الخطر: ناسا وويكيبيديا والبيت الأبيض، لأن ووردبريس ودروبال يعملان على PHP، وPHP يعمل على جزء مذهل من الويب.

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

الخطأ الأول: تصنيف أعطال الانهيار على أنها «مزعجة لكنها غير ضارة»

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

إليك السبب الميكانيكي لأهمية هذا التمييز. فالخلل في الذاكرة الذي يُفسد الكومة (heap) ببيانات غير منضبطة يقتل العملية عادةً فقط: يلاحظ المُخصِّص (allocator) تناقضاً فيُجهض التنفيذ، أو تُشير العملية إلى قيمة مهملة فتنهار. لكن الخلل نفسه، إذا غُذّي بمدخلات بحجم وشكل مدروسين، يصبح primitive للكتابة:

void handle_request(const char *input, size_t len) {
char *buf = malloc(64);
memcpy(buf, input, len);   /* len never validated */
/* len = 65:            heap metadata trashed -> likely abort, filed as 'crash' */
/* len = attacker-tuned: adjacent object's function pointer overwritten */
process(buf);             /* calls through the corrupted pointer -> their code runs */
free(buf);
}

الفاصل بين النتيجتين ليس في الخلل، بل في المدخلات. معرفة أي البتات يجب الكتابة فوقها، وبأي ترتيب، لتوجيه التنفيذ إلى عنوان مختار عمل شاق لكنه آلي، و«شاق لكن آلي» هو بالضبط ما تجيد نماذج اللغة المساعدة فيه. إصلاح هذا الخطأ مفاهيمي قبل أن يكون تقنياً: توقف عن اعتبار «إنه ينهار فقط» مؤشراً على الخطورة في الشيفرة غير الآمنة للذاكرة. الانهيار في C أو C++ (أو في النواة C لمفسّر مثل PHP) هو استغلال لم يُطوَّر بعد. سؤال الفرز الجديد ليس «هل ينهار؟» بل «هل التلف متأثر بالمهاجم؟». إذا كانت المدخلات غير الموثوقة تتحكم في حجم الكتابة الخاطئة أو إزاحتها أو محتواها، فافترض قابلية الاستغلال ورتّب الأولويات وفقاً لذلك، حتى لو لم يُثبت أحد استغلالاً عملياً. خاصةً في هذه الحالة، لأن الاستغلالات المثبتة تستغرق الآن أسابيع لا سنوات.

الخطأ الثاني: معاملة مخرجات الماسح كأنها قائمة متراكمة (backlog)

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

الفرز الفعّال في هذا النظام يطرح أسئلة عن مسار الاستغلال، لا أسئلة عن درجة الخطورة:

  • هل يمكن الوصول إلى الشيفرة المعرّضة للخلل من مدخلات غير موثوقة؟ فيض كومة (heap overflow) في دالة تعالج ملف إعدادات محلياً فقط شيء مختلف تماماً عن الفيض نفسه في معالجة الطلبات.
  • هل هي متاحة للإنترنت اليوم؟ ليس «هل ينبغي أن تكون»، بل هل هي كذلك فعلاً. راجع إعدادات موازن الأحمال وDNS، لا مخطط البنية.
  • هل المدخلات تتحكم في التلف؟ الحجم أو الإزاحة أو محتوى الوصول الخاطئ. هذا هو الخط الفاصل بين العطل والاستغلال الذي ذكرناه في القسم السابق.
  • ماذا يمنح الاستغلال المهاجم؟ العطل داخل عامل معزول يُعاد تشغيله يختلف عن العطل داخل العملية التي تحمل بيانات اعتماد قاعدة البيانات.
  • هل يوجد استغلال منتشر في الواقع أو شرح علني؟ هذا يدفع أي بند إلى مقدمة الطابور بغض النظر عن الدرجة.

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

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

الخطأ الثالث: افتراض أن الترقيع يمكن أن يسير بسرعة اكتشاف الثغرات

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

الفرق التي تتجاهل هذا عدم التماثل تراهن رهاناً من اثنين سيئين: إما أن تسارع إلى الترقيع لمجاراة ضغط الإفصاح فتشحن انحدارات، فترقيع PHP لمس تفاصيل داخلية للمفسّر تستخدمها نحو ثلاثة أرباع المواقع التي تعلن مكدسها، فنطاق الضرر لأي إصلاح سيئ هنا حضاري؛ وإما أن تيأس فلا تفعل شيئاً وتنتظر إصلاحاً مثالياً. الممارسون الذين تعاملوا مع هذه النافذة جيداً فعلوا شيئاً أقل بطولية وأكثر فعالية: فصلوا بين «خفّف الآن» و«أصلح بشكل صحيح». التخفيفات رخيصة وسريعة وقابلة للتراجع: قيّد نقطة النهاية المتأثرة عند البروكسي العكسي، وانشر قاعدة WAF تحجب شكل المدخلات الخاص بالاستغلال، وأخرج مسار الشيفرة المعرّض خلف علم (feature flag)، وقلّص من يستطيع الوصول إلى الخدمة بينما ينضج الترقيع الحقيقي. كتبت سابقاً عن أن قرار الترقيع مقابل التخفيف مقايضة حقيقية وليس إخفاقاً أخلاقياً، وهذه الحادثة هي ذلك الدرس بحجم كوكبي.

النتيجة التي لا يريد أحد سماعها: زمن متوسط الوصول إلى التخفيف (mean-time-to-mitigate) صار هو المقياس المهم، لأن الفترة بين «اكتشفه الباحثون الأخلاقيون» و«اكتشفه من هو أسوأ» تتقلص. في حالة PHP بقيت النافذة مفتوحة فقط لأن الباحثين كانوا مسؤولين والمؤسسة تحركت بسرعة. مكتبة Brotli في الفترة نفسها روت قصة أقل إشراقاً: خلل مشابه بقي في الشيفرة ثماني سنوات، وأُصلح في git لكنه لم يُصدر لثمانية أشهر، وأعاد اكتشافه أربعة باحثين على الأقل بشكل مستقل. عندما يصبح الاكتشاف رخيصاً ومتوازياً، تتوقف فكرة «سيجده أحدهم في النهاية» عن كونها فكرة مريحة وتصبح ضماناً في الجدولة.

الخطأ الرابع: الثقة بالإصلاح لأن نموذجاً لغوياً كتبه

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

لكنني رأيت فريقين يتبنيان سير عمل «ترقيع أمني مولّد بالذكاء الاصطناعي»، وكلاهما وقع في الخطأ نفسه: عاملا ترقيع النموذج كـحل بدلاً من مرشح. في إحدى الحالات أغلق الترقيع فيض الكومة المبلَّغ عنه بإضافة فحص للطول، ونقل الفيض إلى مسار تخصيص ثانٍ يبعد ست أسطر لم يضعه النموذج في حسبانه. مرّ الإصلاح من المراجعة لأنه بدا صحيحاً بوضوح، وهذا بالضبط نمط الفشل: ترقيعات النماذج اللغوية طليقة بطريقة لا تتسم بها الترقيعات البشرية، والطلاقة تُخفّف التدقيق. الفرق التي استفادت من الترقيعات المولّدة أضافت ثلاث بوابات، بهذا الترتيب:

  1. مجموعة اختبارات انحدار تتضمن مدخل الاستغلال. إثبات المفهوم الذي فعّل الاكتشاف يصبح اختباراً دائماً. إذا أعطاك الماسح مدخلاً يُسبب انهياراً، فهذه أول حالة اختبار جديدة لك بلا تكلفة.
  2. صيد المتغيرات (variant hunt). قبل الدمج، يجيب أحدهم (أو شيء ما): أين يظهر هذا النمط نفسه في مكان آخر؟ إصلاح نسخة واحدة من نمط منهجي هو الطريقة التي تنتج بها تكملات CVE.
  3. تحقق مستقل من المتغير الثابت، لا من الفرق (diff). اذكر ما يجب أن يكون صحيحاً الآن، مثل «لا يوجد مسار من معالجة الطلبات يصل إلى memcpy بطول غير مُتحقَّق منه»، وتحقق من ذلك بالاختبارات أو التحليل الساكن أو أدوات التحقق الرسمية. مراجعة الفرق وحده تعيد قراءة واجب النموذج المنزلي فحسب.

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

ختم ميكانيكي وعدسة مكبرة نحاسية بجانب مخططات ملفوفة، تُبرز التباين بين الإنشاء والتحقق
دع النماذج تولّد؛ ودع شيئاً صغيراً وغبياً وموثوقاً يجري الفحص النهائي.

الخطأ الخامس: افتراض أن شخصاً آخر قد دقّق الشيفرة

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

نجح إفصاح PHP2Shell بسبب ترتيب غير معتاد: رعت OpenAI تدقيقاً خارجياً، وأنجزته شركة ذات موارد وفيرة، وساعدت Wiz في تأكيد النتائج وتوسيعها. هذا عمل خيري وليس نظاماً، ولا يتسع لآلاف المشاريع الحرجة وغير الممولة في شجرة اعتمادياتك. إذا كان إنتاج مؤسستك يعتمد على مفسّر أو إطار عمل أو مكتبة مفتوحة المصدر، وهو كذلك فعلاً، فالإصلاحات التي تهم هي الإصلاحات المملة: موّل المؤسسات الداعمة، ورعِّ عمليات التدقيق، وساهم بساعات هندسية، وعندما تشغّل ماسحاتك وتجد شيئاً في اعتمادية، أبلغ عنه في المنبع بدلاً من ترقيع نسختك والمضي قدماً. البديل هو العالم الذي يتوقعه ماثيو غرين من جامعة جونز هوبكنز: لا يتغير شيء بنيوياً حتى يقع حادث كبير بما يكفي ليُزعج الناس العاديين فيُجبر على التغيير. نصيحته في الأثناء غير لامعة وصحيحة: عندما تظهر نافذة التحديث، ثبّته الآن، لا الأسبوع القادم. تعلّمنا الدرس نفسه بالطريقة الصعبة في دورة الإفصاح الكبيرة الأخيرة عن PHP، حين تفوّق سحب القابس على الإصلاحات الذكية للفرق التي لم تستطع الترقيع بسرعة كافية.

وصلت الأعين. لكنها لا تبالي بالجهة التي تقف فيها.

دليل الاثنين الصباحي للثغرات التي يكشفها الذكاء الاصطناعي

كل ما سبق يتلخص في قائمة قصيرة لأشياء كنت سأفعلها فعلاً هذا الربع لو كنت أدير مؤسسة هندسية لديها شيفرة قديمة في الإنتاج، وإن كنت تقرأ هذا فلديك شيفرة قديمة في الإنتاج:

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

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