الذكاء الاصطناعي بناه. أنا كسرته. والذكاء الاصطناعي ساعدني في كسره.

قصة فضول، حملة لعبة، ثقة عمياء بالعميل، وما يحدث حين يُطلق تطوير مدعوم بالذكاء الاصطناعي دون منظور أمني — تحليل أُجري هو الآخر بمساعدة الذكاء الاصطناعي.

Author: Mohamed Yaakoubi

Published: 2026-03-24

Category: AI & Cybersecurity

Tags: اختبار الاختراق, أمن الويب, التطوير بالذكاء الاصطناعي, إفصاح مسؤول, Vibe Coding, SecureByDesign, أمن الألعاب, ثقة جانب العميل

Reading time: 15 minutes

تحليل أمني · 24/03/2026

الذكاء الاصطناعي بناه. أنا كسرته.
والذكاء الاصطناعي ساعدني في كسره.

قصة فضول، حملة لعبة، ثقة عمياء بالعميل، وما يحدث حين يُطلق تطوير مدعوم بالذكاء الاصطناعي دون منظور أمني — تحليل أُجري هو الآخر بمساعدة الذكاء الاصطناعي.

اختبار الاختراقأمن الويبالتطوير بالذكاء الاصطناعيإفصاح مسؤولVibe Coding
مرّر للقراءة
01 —

نقطة البداية

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

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

هذه فرضية تُنشئ إحساساً زائفاً بالأمان. المتصفح المدمج لا يُغيّر ما يرسله الخادم. ملفات JavaScript ذاتها، ردود الـ API ذاتها، حزمة الكود ذاتها — كل ذلك متاح بالتساوي لأي شخص يفتح الرابط في متصفح سطح مكتب. الغلاف الجوال طبقة تجربة مستخدم، وليس حدّاً أمنياً.

من باب الفضول التحليلي، فعلت ذلك بالضبط — فتحت الرابط في متصفح سطح مكتب وضغطت F12.

أول ما رأيته لم يكن التطبيق. كانت الكونسول.

02 —

الإشارة الأولى: الكونسول

قبل أي تحليل لكود المصدر، قبل أي اختبار للـ API — لحظة فتح أدوات المطوّر، كانت كونسول المتصفح تطبع تدفقاً مستمراً من السجلات الداخلية للتطبيق.

ليس سطرين من سجلات التنقيح. كل صفحة. كل إجراء. كل استدعاء للخدمة.

code
[GAME SERVICE] بدأت الجلسة: {sessionId}
[GAME SERVICE] إرسال النتيجة: {sessionId, roundNumber, score}
[TEAM SERVICE] تم إنشاء الفريق: {teamId}
[TEAM SERVICE] تم إرسال الدعوة بنجاح
[AUTH PROVIDER] خطأ 401، محاولة تجديد التوكن
[AUTH PROVIDER] تم تجديد التوكن، إعادة المحاولة
[AUTH PROVIDER] تسجيل الخروج بالإعدادات المحلية: {locale}
[LOGIN PAGE] استدعاء API الـ OTP...
[LOGIN PAGE] نجح الـ OTP API

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

كانت هذه الإشارة الأولى. ليست خفيّة على الإطلاق.

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

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

الرابط كان عاماً. أي متصفح سطح مكتب يمكنه فتحه. وكانت الكونسول خريطة طريق إلى كل ما تلا.

03 —

البنية المعمارية

قبل الدخول في النتائج، من المفيد فهم ما نتعامل معه.

كان التطبيق تطبيق Next.js بالعرض من جانب العميل (CSR) مدعوماً بـ REST API. ثلاثة أوضاع للعب، نظام فرق، لوحة ترتيب، ومصادقة هاتفية بـ OTP.

العميل (تطبيق CSR في المتصفح)

├── واجهة اللعبة ──────── النتيجة تُولَّد هنا ⚠️
├── حساب النقاط ─────── عشوائية جانب العميل ⚠️
├── التوقيع HMAC ─────── المفتاح السري يعود من الخادم ⚠️
└── سجلات الكونسول (إنتاج) ── داخليات الجلسة مكشوفة ⚠️

API (الخادم الخلفي REST)

├── POST /session/create ──── يُعيد مفتاح التوقيع ⚠️
├── POST /session/:id/submit-round ── يقبل قيم العميل ⚠️
└── POST /session/:id/submit-result ── يقبل الفائز من العميل ⚠️

الـ stack في حد ذاتها حديثة ومعقولة. الثغرات لم تكن في اختيارات التقنية — كانت في نموذج الثقة. بالتحديد، مقدار ثقة الخادم بالعميل في الإبلاغ الصادق عن نتائج اللعبة.

04 —

النتائج

حرجة النتيجة الأولى — نتائج اللعبة يتحكم بها العميل + تزوير HMAC

كانت اللعبة تولّد قيم النتائج بالكامل في المتصفح باستخدام دالة عشوائية من جانب العميل. كانت هذه القيم — المدخلات والنقاط المحسوبة — تُرسل بعد ذلك إلى الخادم مع توقيع HMAC لإثبات النزاهة.

كان نظام HMAC آلية أمنية مشروعة من حيث المفهوم. العيب القاتل: أن مفتاح التوقيع كان يعود من الخادم في استجابة إنشاء الجلسة.

javascript
// نمط: صيغة التوقيع مكشوفة في حزمة كود العميل
function signOutcome(sessionId, roundNumber, input1, input2, score, timestamp, signingKey) {
  const message = \\${sessionId}:\${roundNumber}:\${input1}:\${input2}:\${score}:\${timestamp}\;
  return HMAC_SHA256(message, signingKey);
}

بمجرد حصول اللاعب على مفتاح التوقيع، يمكنه تزوير توقيع صالح لأي قيم نتائج وأي نقاط يختارها. لم يكن بإمكان الخادم التمييز بين تسليم مشروع وآخر مزوّر — كلاهما يستخدم المفتاح الصحيح لإنتاج توقيع صحيح.

مسار الاستغلال:

javascript
// الخطوة 1 — إنشاء جلسة، التقاط مفتاح التوقيع من الاستجابة
const { sessionId, signingKey } = await createSession();
 
// الخطوة 2 — لكل جولة، تزوير قيم النتائج القصوى وتوقيعها
for (let round = 1; round <= TOTAL_ROUNDS; round++) {
  const timestamp = Date.now();
  const signature = signOutcome(sessionId, round, MAX_INPUT, MAX_INPUT, MAX_SCORE, timestamp, signingKey);
 
  // الخطوة 3 — تسليم النتيجة المزوّرة — الخادم يقبلها لأن التوقيع صالح
  await submitRound({ round, input1: MAX_INPUT, input2: MAX_INPUT, score: MAX_SCORE, timestamp, signature });
}
// النتيجة: أعلى نقاط ممكنة مسجّلة. الخادم قبل دون أي تساؤل.

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

تم تسليم أعلى نقاط ممكنة عبر جميع الجولات، وقبولها، وانعكاسها على لوحة الترتيب.

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

الإصلاح: توليد جميع قيم النتائج من جانب الخادم. عدم قبول مدخلات اللعبة أو النقاط من العميل. عدم إعادة مفتاح التوقيع في أي استجابة API. إذا كان الخادم يولّد النتيجة، فلا يوجد شيء يُزوَّر.

حرجة النتيجة الثانية — لا حماية للنزاهة على تسليم الجولة

وضع لعب ثانٍ — اللاعب ضد الحاسوب — لم يكن يمتلك أي آلية للنزاهة إطلاقاً. كان endpoint التسليم يقبل النتائج الكاملة للجولة مباشرة من العميل، بما في ذلك من فاز في كل جولة، وما كانت عليه قيمة كل مدخل، والنقاط النهائية.

javascript
// نمط: العميل يسلّم نتيجة لعبته بنفسه
await submitGameResult({
  score: TOTAL_ROUNDS,
  rounds: [
    { round: 1, playerInput: MAX_VALUE, opponentInput: MIN_VALUE, winner: 'player' },
    { round: 2, playerInput: MAX_VALUE, opponentInput: MIN_VALUE, winner: 'player' },
    { round: 3, playerInput: MAX_VALUE, opponentInput: MIN_VALUE, winner: 'player' }
  ]
});
// الاستجابة: { success: true }

كان الخادم قد حدّد نتيجة اللعبة مسبقاً داخلياً — علامة نتيجة كانت موجودة في منطق الجلسة — لكنه لم يُطبّقها أبداً عند التسليم. النتيجة التي يوفّرها العميل كانت تتجاوز كل شيء. استدعاء API واحد. الفائز: اللاعب. في كل مرة.

الإصلاح: تحديد نتائج اللعبة من جانب الخادم. عدم قبول قيم النتائج، أو مدخلات الخصم، أو تحديد الفائز من العميل.

عالية النتيجة الثالثة — سجلات كونسول مفصّلة في الإنتاج

كما وُصف في المقدمة — لم تكن سجلات الكونسول عرضية. كانت منتشرة في كل مكان. كل خدمة رئيسية، كل إجراء للمستخدم، كل حدث مصادقة كان يُسجَّل في كونسول المتصفح في بيئة الإنتاج.

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

النتيجة هي خلاصة debug داخلية حية تُسلَّم لكل مستخدم يعرف كيف يضغط F12.

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

عالية النتيجة الرابعة — الجلسات المُهجَرة تستهلك الحد اليومي

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

كان تقدمه يظهر score: 0, status: NOT_PLAYED — لكن لم يكن بالإمكان إنشاء جلسة جديدة. رموز خطأ الحد اليومي (dailyPlayLimitReached للوضع الفردي، dailyLimitReached لوضع الفريق) كانت تحجب أي محاولات إضافية بغض النظر عن كون الجلسة قد لُعبت فعلاً أم لا.

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

الإصلاح: استهلاك الحد اليومي فقط عند اكتمال الجلسة بنجاح (sessionCompleted: true)، وليس عند إنشاء الجلسة.

عالية النتيجة الخامسة — منطق اللعبة الكامل مكشوف في حزمة كود العميل

إلى جانب سجلات الكونسول ومنطق النتائج، احتوت حزمة كود العميل على أكثر بكثير مما تحتاجه طبقة العرض:

  • صيغة التوقيع الكاملة مع نمط بناء الرسالة الكامل
  • خوارزمية النقاط الكاملة بما فيها شروط المكافآت
  • جميع هياكل مسارات الـ API عبر جميع أوضاع اللعب
  • قيم دورة حياة الجلسة لكل وضع
  • سجل كامل لرموز الأخطاء الداخلية عبر جميع النطاقات — المصادقة، منطق اللعبة، عمليات الفريق، الأمان، والتحقق من الصحة
  • مفتاح التوقيع السري مخزّن في حالة المكوّن، قابل للقراءة عبر أدوات المطوّر في المتصفح
يستطيع محلل متحفّز إعادة بناء سطح هجوم الـ API الخلفي الكامل، ومنطق العمل، وسلوك معالجة الأخطاء، ونموذج الأمان في غضون 30 دقيقة من قراءة الحزمة. سجلات الكونسول كانت تُسرّع ذلك أكثر — ملصقات الخدمات وأسماء الإجراءات كانت تشير مباشرة إلى أقسام الكود ذات الصلة.

الإصلاح: يجب أن يتلقى العميل فقط ما يحتاجه لعرض الحالة الراهنة. صيغ النقاط، وتطبيقات HMAC، وتصنيفات الأخطاء الداخلية تنتمي إلى الخادم.

ملخص النتائج

النتيجةالخطورةالحالة
نتائج اللعبة يتحكم بها العميل + تزوير HMACحرجةاستُغل وتأكّد
لا نزاهة على تسليم الجولةحرجةاستُغل وتأكّد
سجلات كونسول مفصّلة في الإنتاجعاليةمؤكّد
الجلسات المُهجَرة تستهلك الحد اليوميعاليةمؤكّد
منطق اللعبة الكامل مكشوف في حزمة كود العميلعاليةمؤكّد
05 —

السبب الجذري

كل نتيجة حرجة تشترك في السبب الجذري ذاته: الخادم وثق بالعميل.

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

البنية المعمارية الصحيحة:

العميل
الخادم
العميل
إنشاء جلسة
الخادم
الخادم
{ sessionId }
لا سرّ. لا مفتاح توقيع.
العميل
العميل
"توليد النتيجة"
مجرد إشارة تشغيل.
الخادم
الخادم
{ input1, input2, score }
الخادم يولّد. الخادم يحسب النقاط.
العميل
العميل
"تسليم الجولة"
لا قيم. الخادم يعرف بالفعل.
الخادم
الخادم
{ roundResult }
العميل

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

06 —

القصة الحقيقية: الذكاء الاصطناعي بناه. والذكاء الاصطناعي اكتشفه.

أدوات البرمجة بالذكاء الاصطناعي تُحسّن لشيء واحد: جعل الكود يعمل.
هي ليست مهندسي أمن.

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

لكن أدوات البرمجة بالذكاء الاصطناعي تمتلك نقطة عمياء جوهرية: تُحسّن للصحة الوظيفية، وليس للأمان.

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

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

حين تطلب منه إضافة سجلات للتنقيح، سيُضيف تعليمات في كل خدمة، كل مكوّن، كل إجراء. لن يُضيف فحوصات بيئة. لن يُذكّرك بحذفها قبل النشر. يُحسّن للمهمة الآنية — والمهمة الآنية كانت تسهيل التطوير، لا الاستعداد للإنتاج.

النتيجة كود:

  • يجتاز كل اختبار وظيفي

  • يعمل بشكل صحيح في التطوير

  • يبدو محترفاً ومنظّماً جيداً

  • يحتوي على افتراضات أمنية لم تُتحقق منها قط
هذا ليس فشل ذكاء أو جهد. هو فشل سياق. لم يُعطَ الأداة نموذج تهديد. أُعطيت متطلبات وظيفية. وقد وفّت بها كاملةً.

والآن، هنا الجزء الذي يستحق التأمل.

هذا التحليل بأكمله أُجري أيضاً بمساعدة الذكاء الاصطناعي.

المنهجية، استكشاف كود المصدر، سكريبتات الاستغلال، اختبار الـ API، النتائج المنظّمة — كل ذلك طُوِّر بالتعاون مع أداة ذكاء اصطناعي. نفس صنف الأداة الذي أدخل هذه الثغرات استُخدم لاكتشافها.

هذه ليست مناقضة. بل توضّح شيئاً دقيقاً:

أدوات الذكاء الاصطناعي مضاعفات قوة. تُضخّم نوايا ومعرفة الشخص الذي يشغّلها. مطوّر يستخدم الذكاء الاصطناعي للشحن السريع دون وعي أمني يشحن بسرعة وبشكل غير آمن. محلل أمني يستخدم الذكاء الاصطناعي للاستكشاف المنهجي مع معرفة أمنية يحلّل بشكل أسرع وأعمق.

المشكلة ليست الأداة. المشكلة هي سير العمل. التطوير المدعوم بالذكاء الاصطناعي دون خطوة مراجعة أمنية سيُنتج باستمرار تطبيقات تعمل بشكل مثالي وتفشل في عمليات التدقيق.

الأداة محايدة. الوعي ليس كذلك.

07 —

ما يجب إضافته إلى سير عملك

لا شيء من هذا يتطلب فريق أمن مخصصاً. يتطلب وعياً وقائمة مراجعة.

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

خاتمة

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

الهدف هو جعل هذا النمط مرئياً — لأنه سيتكرر. مع أن التطوير المدعوم بالذكاء الاصطناعي يصبح القاعدة، ستتسع الهوّة بين "يعمل بشكل صحيح" و"يعمل بشكل آمن" ما لم يسعَ المطوّرون بنشاط لردمها.

الأمان ليس ميزة تُضيفها بعد الانتهاء. إنه قرار معماري تتخذه قبل كتابة أول سطر كود.

الذكاء الاصطناعي يمكنه مساعدتك في البناء. تأكد أنك أنت من يُفكّر في الأمان.

أُجريت جميع الاختبارات الموصوفة في هذا المقال بشكل تحليلي وبحسن نية على حسابات أتحكم فيها. لم يُتاح الوصول إلى أي بيانات مستخدم أو استخراجها أو الاحتفاظ بها. لم يُلحق أي ضرر بأي نظام.

— كُتب بمساعدة الذكاء الاصطناعي، وراجعه الحكم البشري.

#اختبار الاختراق#أمن الويب#التطوير بالذكاء الاصطناعي#إفصاح مسؤول#Vibe Coding#SecureByDesign#أمن الألعاب#ثقة جانب العميل