اختبار أمان تطبيقات الجوال

يتحقق اختبار أمان تطبيقات الجوال (Mobile Security Testing) من أن التطبيق يحمي بيانات مستخدميه على الجهاز، وعلى الشبكة، وحيث يلتقي بنظام التشغيل والتطبيقات الأخرى. ويحدد معيار OWASP للتحقق من أمان تطبيقات الجوال (MASVS) ما يجب أن يفعله التطبيق الآمن، ويشرح دليل OWASP لاختبار أمان تطبيقات الجوال (MASTG) كيف تتحقق من ذلك.

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

لماذا يهم

الشركة لا تتحكم في الهاتف. فقد يُفقد أو تُكسر حمايته (rooted) فيُفتح الوصول الكامل إلى نظامه، أو يُستعاد من نسخة احتياطية، ويتصل بشبكات Wi-Fi عامة، ويستطيع أي شخص تفكيك حزمة التطبيق. فكل ما يخزّنه التطبيق أو يرسله أو يقبله من التطبيقات الأخرى مكشوف، ورمز (token) واحد مسرَّب قد يعني الاستيلاء على حساب.

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

مجموعات الضوابط في MASVS

يوزّع MASVS ضوابطه على ثماني مجموعات ضوابط (control groups)، يبدأ اسم كل منها بالبادئة MASVS-، ويشرح MASTG كيف تُختبر على Android وiOS.

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

  • MASVS-STORAGE: البيانات الحساسة على الجهاز محمية ولا تتسرب.
  • MASVS-CRYPTO: خوارزميات قوية، ولا مفاتيح مكتوبة داخل التطبيق.
  • MASVS-AUTH: تسجيل الدخول والجلسات والتفويض يفرضها الخادم الخلفي؛ والتحقق المحلي مثل القياسات الحيوية (biometrics) يُنفَّذ بأمان.
  • MASVS-NETWORK: TLS مع تحقق سليم من الشهادات، وتثبيت الشهادة حيث تستدعيه المخاطر.
  • MASVS-PLATFORM: استعمال آمن للروابط والمكوّنات وWebView والشاشة.
  • MASVS-CODE: التحقق من المدخلات غير الموثوقة؛ ولا مكوّنات ذات ثغرات معروفة.
  • MASVS-RESILIENCE: مقاومة الهندسة العكسية والعبث حيث تستدعي المخاطر ذلك.
  • MASVS-PRIVACY: البيانات التي يحتاجها التطبيق فقط، يراها المستخدم ويتحكم فيها.

التخزين المحلي: ما يبقى على الجهاز

يحفظ التطبيق بياناته في بيئته المعزولة (sandbox): ملفات التفضيلات في shared_prefs وقواعد بيانات SQLite والملفات على Android، وUserDefaults والملفات وقواعد البيانات على iOS. والبيئة المعزولة تمنع التطبيقات الأخرى، لكنها لا تمنع من يملك هاتفاً مكسور الحماية أو نسخة احتياطية أو نسخة قابلة للتصحيح (debuggable)، وهي نسخة تصحيح تسمح لأدوات مثل run-as بالوصول إلى ملفات التطبيق، أما نسخ الإصدار فليست قابلة للتصحيح. وتتسرب البيانات أيضاً إلى السجلات (logs) والحافظة ولقطة مبدّل التطبيقات.

واختبار MASVS-STORAGE بسيط: البيانات الحساسة لا تُخزَّن إلا عند الحاجة، والأسرار محفوظة في iOS Keychain أو مشفّرة بمفتاح محفوظ في Android Keystore (وهما المخزنان المحميان في المنصتين)، والسجلات خالية من أي شيء حساس، وتسجيل الخروج يحذف بيانات الجلسة. والترميز ليس تشفيراً: سلسلة Base64 أو رمز JWT موقَّع في ملف يقرؤه كل من يحصل على الملف. وعلى نسخة ضمان الجودة (QA build) في Android، انظر بنفسك:

# Debuggable QA build, on a test phone or emulator you may use
adb shell run-as com.example.shop ls shared_prefs databases files
adb shell run-as com.example.shop cat shared_prefs/session.xml
#   <string name="refresh_token">eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOi...</string>
#   ^ a finding: a token in plain text

adb logcat -d | grep -i -E "password|token|bearer|otp"

# Release build: run-as must fail, because the build is not debuggable
adb shell run-as com.example.shop ls

جرّبها: مفكّك ترميز Base64 جرّبها: مفكّك ترميز JWT جرّبها: فاحص انتهاء صلاحية JWT

مثال تطبيقي: قراءة حركة HTTPS لتطبيق Android

لديك إذن كتابي باختبار تطبيق التسوّق الخاص بفريقك مقابل api.staging.shop.example. والوكيل الاعتراضي (intercepting proxy) أداة تقف بين التطبيق والخادم وتعرض كل طلب واستجابة؛ ويشرح درس الوكيل الاعتراضي إعداده بالتفصيل. ونطاقه (scope) هو مجموعة المضيفات المأذون لك باختبارها، فلا تضع في النطاق إلا هذا المضيف. وسجلّه (history) يسرد كل طلب التقطه، فتستطيع أن تجد الطلب لاحقاً، أو ترفقه دليلاً، أو تعيد تشغيله (replay)، أي ترسله إلى الخادم مجدداً. ويعمل الوكيل على حاسوبك، ويستمع على عنوان الحاسوب في شبكة Wi-Fi، مثل 192.168.1.20:8080. ولكي يقرأ الوكيل حركة HTTPS، فإنه ينهي اتصال TLS الخاص بالتطبيق بنفسه ويقدّم للتطبيق شهادة باسم المضيف موقّعة من مرجعه المصدّق (CA) الخاص. لذا تضبط على هاتف اختبار مخصّص هذا العنوان وكيلاً لشبكة Wi-Fi، وتضيف شهادة المرجع المصدّق للوكيل إلى الهاتف كشهادة مستخدم.

يفشل التطبيق الآن في الاتصال، ويسجّل الوكيل أخطاء في مصافحة TLS. هذا هو Android يعمل كما صُمّم: منذ Android 7.0 (مستوى API رقم 24)، لا تثق التطبيقات التي تستهدف هذا المستوى أو أعلى افتراضياً إلا بمراجع النظام المصدّقة، لا بالمراجع التي أضافها المستخدم. والطريقة الآمنة للسماح بها، الظاهرة أدناه، هي كتلة debug-overrides في إعدادات أمان الشبكة (Network Security Configuration): لا تُطبَّق إلا على نسخة قابلة للتصحيح، فتثق نسخة ضمان الجودة بمرجع الوكيل وتحتفظ نسخة الإصدار (release build) بالإعداد الافتراضي. وبعد أن تصبح حركة المرور مقروءة، افحص:

  • كل طلب يستخدم HTTPS، بما في ذلك الصور وحزم SDK. والتطبيقات التي تستهدف Android 9 (مستوى API رقم 28) أو أعلى تمنع HTTP الصريح افتراضياً، فنداء http:// الناجح يعني غالباً أن أحداً سمح بالنص الصريح لهذا المضيف: أبلغ عنه.
  • الرموز تنتقل في الترويسة Authorization، لا في عنوان URL أبداً، حيث تسجّلها الخوادم.
  • بعد تسجيل الخروج، إذا أعدت تشغيل طلب بالرمز القديم فالاستجابة 401 Unauthorized.
<!-- res/xml/network_security_config.xml -->
<network-security-config>
  <debug-overrides>          <!-- applies only when the app is debuggable -->
    <trust-anchors>
      <certificates src="user" />
    </trust-anchors>
  </debug-overrides>
</network-security-config>

<!-- AndroidManifest.xml -->
<application android:networkSecurityConfig="@xml/network_security_config" ...>

جرّبها: محلّل ترويسات HTTP جرّبها: مختبِر مصادقة API

تثبيت الشهادة سلوك متوقع

تثبيت الشهادة (Certificate Pinning)، ويسمّيه MASVS تثبيت الهوية (identity pinning)، يعني أن التطبيق لا يقبل لمضيفات واجهته البرمجية إلا شهادة أو مفتاحاً عاماً أو مرجعاً مصدّقاً معروفاً. وهو يحمي المستخدمين من مرجع مصدّق خبيث أو غير مرغوب على الهاتف، ويحجب الوكيل الخاص بك أيضاً: تفشل المصافحة. وعلى نسخة الإصدار هذه نتيجة ناجحة، لذا فتقرير «التطبيق لا يعمل عبر الوكيل» تقرير خاطئ.

والتثبيت قرار مخاطر يوثّقه الفريق. وحين يطبّق التطبيق تثبيت الشهادة، اختبر السلوك لا التجاوز:

  • عبر الوكيل، ترفض النسخة التي تطبّق التثبيت الاتصالَ برسالة خطأ واضحة، بلا انهيار ولا إعادة محاولة عبر HTTP الصريح؛ ومن دون الوكيل تعمل.
  • نسخة الإصدار في Android ترفض شهادة المستخدم أصلاً، فهذا الفشل وحده ليس دليلاً على التثبيت؛ اطلب نسخة اختبار تثق بشهادات المستخدم وتُبقي التثبيت مفعّلاً.
  • حركة المرور للفحوص الوظيفية تأتي من نسخة ضمان الجودة: افتراضياً لا يطبّق Android التثبيت المعرَّف في إعدادات أمان الشبكة على المراجع المضافة في debug-overrides. أما التثبيت المكتوب في شيفرة التطبيق فيحتاج إلى خيار تعطيل خاص بنسخ التصحيح؛ فاتفق عليه مع المطورين. وتجاوز التثبيت في نسخة الإصدار عمل متخصصين.
  • اسأل كيف تُبدَّل المفاتيح المثبَّتة: توصي وثائق Android بإضافة مفتاح احتياطي دائماً، وإلا فتغيير المفتاح على الخادم يقطع اتصال كل نسخة من التطبيق على أجهزة المستخدمين إلى أن يُنشر تحديث للتطبيق.

التفاعل مع المنصة: الروابط والمكوّنات وWebView والشاشة

يغطي MASVS-PLATFORM ما يتبادله التطبيق مع نظام التشغيل والتطبيقات الأخرى. عامِل كل نقطة دخول يصل إليها تطبيق آخر أو صفحة ويب كمدخل غير موثوق؛ والأوامر أدناه تفتح رابطاً عميقاً كما يفعل تطبيق آخر.

  • الروابط العميقة (Deep Links): يستطيع أي تطبيق فتح shop://orders/1043 بأي قيمة. الشاشة المحمية تطلب تسجيل الدخول أولاً، والخادم يرفض مع ذلك طلب شراء مستخدم آخر. وروابط Android App Links وiOS Universal Links يُتحقق من ارتباطها بنطاق التطبيق؛ أما المخطط المخصّص مثل shop:// فلا، ويستطيع تطبيق آخر تسجيل المخطط نفسه واستقبال الرابط، لذا يجب ألا يحمل سراً أبداً، كرمز دخول.
  • المكوّنات المكشوفة (exported): الأنشطة والخدمات ومستقبِلات البث ومزوّدات المحتوى في Android لا تُكشف إلا إذا احتاجتها تطبيقات أخرى، وعندئذ تتحقق مما تتلقاه.
  • WebView لا يحمّل إلا صفحات التطبيق نفسه أو الصفحات المسموح بها، لا عنوان URL مأخوذاً من معامل في رابط.
  • الشاشة: الشاشات الحساسة مخفية في معاينة مبدّل التطبيقات، وحقول كلمات المرور مقنّعة.
# Android test device: open a deep link the way another app would
adb shell am start -W -a android.intent.action.VIEW \
  -d "shop://orders/1043" com.example.shop

# iOS simulator
xcrun simctl openurl booted "shop://orders/1043"
كل فحص لأمان الجوال في هذا الدرس حسب مجموعة MASVS: ما تفحصه، وعلى أي نسخة، والنتيجة المتوقعة؛ وفي الصفوف المظللة يكون رفض الاتصال عبر الوكيل هو النتيجة الناجحة.
الفحص · مجموعة MASVSالنسخة والطريقةالنتيجة المتوقعة
الملفات التي يكتبها التطبيقMASVS-STORAGEنسخة ضمان الجودة: run-as قبل تسجيل الخروج وبعدهلا كلمة مرور ولا رمز بنص صريح؛ وبيانات الجلسة تختفي بعد تسجيل الخروج
السجلاتMASVS-STORAGEنسخة الإصدار: adb logcatلا رموز ولا كلمات مرور ولا بيانات شخصية
محتوى حركة المرورMASVS-NETWORKنسخة ضمان الجودة عبر الوكيل؛ وdebug-overrides تثق بمرجع المستخدمHTTPS فقط؛ والرموز في الترويسات لا في عناوين URL
شهادة المستخدم على نسخة الإصدارMASVS-NETWORKمرجع الوكيل مضاف كشهادة مستخدم، ⁦Android 7+⁩رفض الاتصال برسالة خطأ واضحة، بلا انهيار
تثبيت الشهادة، إن اختاره الفريقMASVS-NETWORKنسخة اختبار تثق بشهادات المستخدم وتُبقي التثبيت مفعّلاًرفض الاتصال عبر الوكيل بالمضيفات التي يُطبَّق عليها التثبيت؛ ويعمل التطبيق من دونه
رابط عميق بمعرّف مستخدم آخرMASVS-PLATFORMadb shell am start أو xcrun simctl openurlتسجيل الدخول أولاً؛ والخادم يرفض طلب المستخدم الآخر
معاينة مبدّل التطبيقاتMASVS-PLATFORMافتح شاشة حساسة ثم مبدّل التطبيقاتالمحتوى مخفي أو مموّه
  • رفض الاتصال هو النتيجة الناجحة

كل فحص: جهاز اختبار مخصّص، ونسخ من فريقك، وإذن كتابي للخادم الخلفي.

أخطاء شائعة

  • الإبلاغ عن «التطبيق لا يعمل عبر الوكيل» بينما تؤدي قاعدة الثقة في ⁦Android 7+⁩ أو تثبيت الشهادة عملها.
  • طلب الثقة بشهادات المستخدم أو تعطيل التثبيت في نسخة الإصدار بدلاً من إعداد خاص بنسخ التصحيح.
  • اعتبار البيئة المعزولة تخزيناً آمناً، أو اعتبار قيمة Base64 أو JWT محمية.
  • فحص السجلات على نسخة ضمان الجودة فقط لا على نسخة الإصدار، أو فحص البيانات المخزّنة قبل تسجيل الخروج دون بعده.
  • فتح الروابط العميقة بالقيم التي يولّدها التطبيق فقط، لا بمعرّف مستخدم آخر.
  • إضافة مرجع الوكيل إلى هاتف شخصي، أو الاختبار دون إذن كتابي.

من منظور ضمان الجودة

فحوص أمان الجوال جزء من كل دورة اختبار، لا من اختبار الاختراق السنوي وحده. اتفق مبكراً على نسختين: نسخة ضمان جودة قابلة للتصحيح تثق بشهادات المستخدم، والنسخة المرشّحة للإصدار (release candidate) تماماً كما ستُنشر. واستعن بمتخصص في التشفير والصمود وكل ما يحتاج إلى جهاز مكسور الحماية أو تجاوز للتثبيت.

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

تمرين عملي

افرز نتائج جلسة اختبار أمان للجوال

المطلوب

لديك إذن كتابي باختبار تطبيق التسوّق الخاص بفريقك مقابل واجهة staging بحسابَي اختبار. وتسرد المادة ست ملاحظات من نسخة ضمان الجودة القابلة للتصحيح ومن النسخة المرشّحة للإصدار.

لكل ملاحظة، اذكر مجموعة MASVS، وقرّر هل هي متوقعة أم عيب أم تحتاج إلى فحص إضافي، وقل ماذا ستفعل بعد ذلك.

المادة
التطبيق: تطبيق تسوّق 4.2 على Android، وواجهة staging هي api.staging.shop.example
حسابا الاختبار: qa.buyer1 وqa.buyer2. والإذن الكتابي يشمل النسختين.

1. نسخة ضمان الجودة: الملف shared_prefs/session.xml يحوي refresh_token بنص صريح.
2. نسخة ضمان الجودة: يطبع logcat "Authorization: Bearer eyJhbGciOi..." مع كل نداء.
3. نسخة الإصدار، ومرجع الوكيل مضاف كشهادة مستخدم: يعرض التطبيق "Can't connect
   securely"، ويُظهر الوكيل أخطاء في مصافحة TLS. ومن دون الوكيل يعمل التطبيق.
4. صور المنتجات تُحمَّل من http://img.shop.example/p/5531.jpg
5. بعد تسجيل الدخول باسم qa.buyer1، يفتح adb الرابط shop://orders/88231
   (طلب شراء يخص qa.buyer2): تُعرض تفاصيل الطلب.
6. معاينة مبدّل التطبيقات لشاشة الدفع بالبطاقة تعرض رقم البطاقة كاملاً.
الخطوات
  1. انسب كل ملاحظة إلى مجموعة MASVS.
  2. افصل سلوك المنصة المتوقع عن العيوب.
  3. لكل عيب، اذكر السلوك الآمن المتوقع والدليل.
  4. اكتب أسئلتك للمطورين.
إظهار الإجابة النموذجية
الإجابة النموذجية

الملاحظة 1 (STORAGE): عيب، رمز طويل العمر بنص صريح. المتوقع: تشفيره بمفتاح من Android Keystore، أو عدم تخزينه. أرفق المسار مع إخفاء القيمة، وتحقق هل يبقى بعد تسجيل الخروج.

الملاحظة 2 (STORAGE، السجلات): تحتاج إلى فحص إضافي. فقد يكون التسجيل المفصّل مقصوداً في نسخة ضمان الجودة؛ كرّر على نسخة الإصدار، حيث يكون ظهور الرمز عيباً.

الملاحظة 3 (NETWORK): متوقعة. نسخة الإصدار ترفض شهادة المستخدم، كما تفعل تطبيقات ⁦Android 7+⁩ افتراضياً، وتفشل بأمان. لكن ذلك ليس دليلاً على التثبيت؛ فإن كان يُفترض أن يطبّق التطبيق تثبيت الشهادة، فاسأل كيف جرى التحقق من ذلك.

الملاحظة 4 (NETWORK): عيب، HTTP صريح مسموح لهذا المضيف، فيمكن قراءة الصور أو تعديلها أثناء النقل. المتوقع: HTTPS فقط، بلا استثناء للنص الصريح. الدليل: الطلب في سجل الوكيل.

الملاحظة 5 (AUTH، عبر نقطة دخول من PLATFORM): عيب، غالباً في الخادم. كرّر الخطوة بنسخة ضمان الجودة وابحث عن طلب الشراء في الوكيل: إعادة 200 OK مع طلب qa.buyer2 كسر للتفويض على مستوى الكائن (BOLA)، أي أن الخادم يعيد سجلاً دون أن يتحقق من أنه يخص المستدعي، فيتأثر كل تطبيق عميل يستخدم الواجهة البرمجية. المتوقع: 403 أو 404، ويعرض التطبيق رسالة خطأ.

الملاحظة 6 (PLATFORM، الشاشة): عيب في شاشة دفع. المتوقع: المعاينة مخفية أو مموّهة. الدليل: لقطة شاشة لمبدّل التطبيقات.

أسئلة للمطورين: أيّ البيانات يجب تخزينها أصلاً؟ هل تسجيل HTTP معطَّل في نسخ الإصدار؟ هل قرر الفريق تطبيق تثبيت الشهادة؟ ولماذا لمضيف الصور استثناء للنص الصريح؟

أسئلة شائعة

هل أحتاج إلى هاتف مكسور الحماية (rooted) لاختبار أمان الجوال؟

ليس لفحوص هذا الدرس. ففي نسخة ضمان الجودة القابلة للتصحيح يقرأ run-as ملفات التطبيق نفسه على هاتف اختبار عادي أو على محاكٍ، وتسمح إعدادات الشبكة الخاصة بالتصحيح للوكيل بقراءة حركة المرور. أما الأجهزة مكسورة الحماية (rooted أو jailbroken) فتُستعمل في التقييمات المتخصصة، مثل فحص ضوابط الصمود، وعلى أجهزة اختبار مخصّصة فقط.

لماذا يُظهر الوكيل حركة متصفح الهاتف لا حركة التطبيق؟

منذ Android 7.0، لا تثق التطبيقات التي تستهدف مستوى API رقم 24 أو أعلى إلا بمراجع النظام المصدّقة، ما لم تختر إعدادات أمان الشبكة فيها الثقة بمراجع المستخدم. اطلب نسخة ضمان جودة فيها كتلة debug-overrides. وإن كان التطبيق يطبّق تثبيت الشهادة، فأي نسخة تُبقي التثبيت مفعّلاً تُظهر العَرَض نفسه على كلتا المنصتين.

كيف أقرأ حركة مرور تطبيق iOS عبر الوكيل؟

أضف مرجع الوكيل إلى جهاز iPhone مخصّص للاختبار كملف تعريف (profile)، ثم فعّل الثقة الكاملة به في الإعدادات ضمن «General > About > Certificate Trust Settings». وتقبل التطبيقات المرجع الموثوق ثقةً كاملة ما لم تطبّق تثبيت الشهادة. فإن رفضت نسخة تطبّق التثبيت الاتصال فهذه هي النتيجة المتوقعة؛ واطلب من المطورين نسخة اختبار يُسمح لك بفحص حركة مرورها.

هل يشترط MASVS تثبيت الشهادة؟

يغطي MASVS تثبيت الهوية في مجموعة الشبكة، لكن وجوب التثبيت في تطبيق بعينه قرار مخاطر؛ وتكتفي تطبيقات كثيرة بالتحقق السليم من شهادات TLS. اعرف ما قرره الفريق، واختبر أن التطبيق يتصرف وفقه، بما في ذلك الفشل الآمن وخطة تبديل المفاتيح.

المراجع

  • OWASP Mobile Application Security Verification Standard (MASVS)OWASP Foundationمتطلبات OWASP الأمنية لتطبيقات الجوال، مجمّعة في مجالات ضبط مثل التخزين والتشفير والمصادقة والشبكة والتفاعل مع المنصة.
  • OWASP Mobile Application Security Testing Guide (MASTG)OWASP Foundationدليل الاختبار المرافق لـ MASVS: تقنيات وحالات اختبار للتحقق من أمان تطبيقات الجوال.
  • About App LinksAndroid Developers (Google)روابط App Links في Android: روابط عميقة إلى موقعك يتحقق منها النظام عبر ملف Digital Asset Links (assetlinks.json)، فتفتح التطبيق مباشرةً.
  • Certified Tester Mobile Application Testing (CT-MAT)ISTQB · 2019منهج ISTQB التخصصي لاختبار تطبيقات الجوال: أنواع التطبيقات وتحديات الأجهزة والمنصات وأنواع الاختبار والأدوات.

تدرّب بأدوات متقن

فكّ ترميز سلاسل Base64 أو Base64url إلى نص، مع إصلاح الحشو تلقائياً.

الترميز

فكّ ترميز ترويسة JWT وحمولته، وفحص المطالبات (claims) والتحقق من انتهاء الصلاحية — بالكامل داخل متصفحك.

الأمان

التحقق مما إذا كان رمز JWT منتهي الصلاحية أو لم يصبح صالحاً بعد، أو المدة المتبقية حتى انتهاء صلاحيته.

الأمان

تحليل ترويسات طلبات واستجابات HTTP الخام إلى جدول منظّم مع الشروحات.

الويب

اختبر مصادقة Bearer وBasic ومفتاح API والترويسات المخصّصة على نقطة نهاية وقارن الاستجابات المصرّح بها بغير المصرّح بها.

اختبار واجهات API

للتعمّق أكثر

تقدّمك في هذا الموضوع

جزء من مسار تعلم ضمان الجودة