نصائح الأمان

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

تساعدك ميزات الأمان الأساسية التالية في إنشاء تطبيقات آمنة:

  • وضع الحماية لتطبيقات Android، الذي يعزل بيانات تطبيقك وتنفيذ الرمز عن التطبيقات الأخرى.
  • إطار تطبيق يتضمّن عمليات تنفيذ فعّالة لوظائف الأمان الشائعة، مثل التشفير والأذونات والاتصال الآمن بين العمليات (IPC).
  • تقنيات مثل التوزيع العشوائي لتخطيط مساحة العنوان (ASLR) وno-execute (NX) وProPolice وsafe_iop وOpenBSD dlmalloc وcalloc وLinux mmap_min_addr للتخفيف من المخاطر المرتبطة بأخطاء إدارة الذاكرة الشائعة.
  • نظام ملفات مشفّر يمكن تفعيله لحماية البيانات على الأجهزة المفقودة أو المسروقة.
  • أذونات يمنحها المستخدم لتقييد الوصول إلى ميزات النظام وبيانات المستخدمين.
  • أذونات يحددها التطبيق للتحكّم في بيانات التطبيق لكل تطبيق على حدة.

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

مخزن البيانات

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

  • وحدة التخزين الداخلية
  • وحدة تخزين خارجية
  • موفّرو المحتوى
توضّح الأقسام التالية مشاكل الأمان المرتبطة بكل أسلوب.

وحدة التخزين الداخلية

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

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

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

وحدة تخزين خارجية

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

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

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

موفّرو المحتوى

يقدّم موفّرو المحتوى آلية تخزين منظّمة يمكن أن تقتصر على تطبيقك الخاص أو يتم تصديرها للسماح بوصول التطبيقات الأخرى إلى تلك التطبيقات. إذا كنت لا تنوي منح تطبيقات أخرى إذن الوصول إلى ContentProvider، يمكنك وضع علامة android:exported=false عليه في بيان التطبيق. ويمكنك بدلاً من ذلك ضبط السمة android:exported على true للسماح للتطبيقات الأخرى بالوصول إلى البيانات المخزَّنة.

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

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

يستطيع موفّرو المحتوى أيضًا توفير إمكانية وصول أكثر دقة من خلال الإعلان عن السمة android:grantUriPermissions واستخدام العلامتَين FLAG_GRANT_READ_URI_PERMISSION وFLAG_GRANT_WRITE_URI_PERMISSION في عنصر Intent الذي يفعّل المكوِّن. يمكن تحديد نطاق هذه الأذونات بشكل أكبر من خلال العنصر <grant-uri-permission>.

عند الوصول إلى موفّر محتوى، استخدِم طُرق طلب بحث تتضمّن معلَمات، مثل query() وupdate() وdelete() لتجنُّب تضمين أي مَعلمات SQL (لغة الاستعلام البنيوية) من مصادر غير موثوق بها. يُرجى العلم أنّ استخدام الطُرق التي تتضمّن معلَمات غير كافٍ إذا تم إنشاء الوسيطة selection من خلال ربط بيانات المستخدمين قبل إرسالها إلى الطريقة.

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

الأذونات

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

طلبات الأذونات

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

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

بالإضافة إلى طلب الأذونات، يمكن لتطبيقك استخدام العنصر <permission> لحماية IPC الحساسة للأمان والمعرّضة للتطبيقات الأخرى، مثل ContentProvider. نقترح بشكل عام استخدام عناصر التحكّم في الوصول حيثما أمكن بخلاف الأذونات التي يؤكّدها المستخدم، لأنّ الأذونات قد تكون مربكة للمستخدمين. على سبيل المثال، يمكنك استخدام مستوى حماية التوقيع في أذونات التواصل مع IPC بين التطبيقات التي يوفرها مطوِّر واحد.

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

تعريفات الأذونات

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

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

إذا كان إنشاء إذن جديد لا يزال مطلوبًا، يُرجى تحديده في بيان التطبيق باستخدام العنصر <permission>. يمكن للتطبيقات التي تستخدم الإذن الجديد الإشارة إليه من خلال إضافة عنصر <uses-permission> في ملفات البيان الخاصة بها. يمكنك أيضًا إضافة الأذونات بشكل ديناميكي باستخدام طريقة addPermission().

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

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

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

اتصال بالشبكات

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

شبكات عناوين IP

لا يختلف الاتصال بالشبكات على Android بشكل كبير عن بيئات Linux الأخرى. الاعتبار الرئيسي هو التأكد من استخدام البروتوكولات المناسبة للبيانات الحساسة، مثل HttpsURLConnection لزيارات الويب الآمنة. يمكنك استخدام بروتوكول HTTPS عبر HTTP في أي مكان يكون فيه بروتوكول HTTPS متوافقًا على الخادم، نظرًا لأن الأجهزة الجوّالة تتصل بشكل متكرر على شبكات غير آمنة، مثل نقاط اتصال Wi-Fi العامة.

يمكن تنفيذ الاتصال المشفَّر على مستوى المقبس بسهولة باستخدام الفئة SSLSocket. نظرًا لتكرار اتصال أجهزة Android بالشبكات اللاسلكية غير الآمنة باستخدام Wi-Fi، يُنصح بشدة باستخدام الشبكات الآمنة لجميع التطبيقات التي تتصل عبر الشبكة.

تستخدم بعض التطبيقات منافذ شبكة localhost للتعامل مع IPC الحساسة. لا تستخدم هذا الأسلوب، لأنه يمكن للتطبيقات الأخرى على الجهاز الوصول إلى هذه الواجهات. بدلاً من ذلك، يمكنك استخدام آلية IPC لنظام التشغيل Android حيثما تكون المصادقة ممكنة، كما هو الحال مع Service. ربط عنوان IP غير المحدد INADDR_ANY أسوأ من استخدام الاسترجاع، لأنه يسمح للتطبيق بتلقّي طلبات من أي عنوان IP.

تأكَّد من أنّك لا تثق في البيانات التي يتم تنزيلها من HTTP أو بروتوكولات أخرى غير آمنة. ويشمل ذلك التحقق من صحة الإدخال في WebView وأي استجابات للنوايا الصادرة ضد HTTP.

الشبكات الهاتفية

تم تصميم بروتوكول خدمة الرسائل القصيرة (SMS) بشكل أساسي للتواصل من مستخدم إلى آخر وليس مناسبًا جدًا للتطبيقات التي تريد نقل البيانات. بسبب قيود الرسائل القصيرة SMS، ننصح باستخدام المراسلة عبر السحابة الإلكترونية من Firebase (FCM) وشبكات IP لإرسال رسائل البيانات من خادم ويب إلى تطبيقك على جهاز المستخدم.

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

التحقّق من صحة البيانات المدخَلة

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

فإذا كنت تستخدم رمزًا برمجيًا أصليًا، قد تتسبب أي بيانات تتم قراءتها من الملفات أو يتم استلامها عبر الشبكة أو يتم استلامها من IPC في حدوث مشكلة أمنية. تتمثّل المشاكل الأكثر شيوعًا في تجاوز المخزن المؤقت والاستخدام بعد حرية التعبير والأخطاء لكل مرة. يوفّر Android عددًا من التقنيات، مثل تقنية ASLR ومنع تنفيذ البيانات (DEP)، التي تقلل من إمكانية استغلال هذه الأخطاء، ولكنها لا تحل المشكلة الأساسية. يمكنك منع الثغرات الأمنية من خلال التعامل مع المؤشرات وإدارة الموارد الاحتياطية بعناية.

إنّ اللغات الديناميكية المستندة إلى السلسلة، مثل JavaScript وSQL، عرضة أيضًا لمشاكل التحقّق من صحة الإدخال بسبب أحرف الإلغاء وإدخال النصوص البرمجية.

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

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

بيانات المستخدمين

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

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

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

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

وإذا كان المعرّف الفريد عالميًا (GUID) مطلوبًا، عليك إنشاء رقم فريد كبير وتخزينه. لا تستخدم معرّفات الهواتف، مثل رقم الهاتف أو IMEI، التي قد تكون مرتبطة بالمعلومات الشخصية. تتم مناقشة هذا الموضوع بمزيد من التفصيل في الصفحة المتعلّقة بأفضل الممارسات المتعلّقة بالمعرّفات الفريدة.

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

WebView

بما أنّ WebView يستخدم محتوى ويب قد يتضمّن HTML وJavaScript، قد يؤدي الاستخدام غير الصحيح إلى مشاكل شائعة في أمان الويب، مثل النصوص البرمجية على مواقع إلكترونية متعددة (إدخال JavaScript). يتضمّن نظام التشغيل Android عددًا من الآليات لتقليل نطاق هذه المشاكل المحتملة من خلال حصر إمكانية استخدام WebView على الحدّ الأدنى من الوظائف التي يتطلبها تطبيقك.

إذا كان تطبيقك لا يستخدم JavaScript مباشرةً في WebView، لا تستدعي setJavaScriptEnabled(). تستخدم بعض الرموز النموذجية هذه الطريقة؛ إذا كنت تعيد استخدام نموذج رمز برمجي يستخدمه في تطبيق إنتاج، فأزل استدعاء الطريقة هذا إذا لم يكن مطلوبًا. بشكل تلقائي، لا ينفّذ WebView JavaScript، لذا لا يمكن تنفيذ البرمجة النصية على مستوى المواقع الإلكترونية.

استخدِم addJavaScriptInterface() بعناية خاصة، لأنه يسمح لـ JavaScript باستدعاء العمليات المحجوزة عادةً لتطبيقات Android. وفي حال استخدامه، لا تعرِّض addJavaScriptInterface() سوى لصفحات الويب التي تكون جميع الإدخالات منها جديرة بالثقة. في حال السماح بالإدخال غير الموثوق به، قد تتمكن لغة JavaScript غير الموثوق بها من استدعاء أساليب Android داخل تطبيقك. وبشكلٍ عام، ننصحك بعرض addJavaScriptInterface() فقط للغة JavaScript المضمَّنة في حزمة APK لتطبيقك.

إذا كان تطبيقك يصل إلى بيانات حسّاسة باستخدام WebView، يمكنك استخدام طريقة clearCache() لحذف أي ملفات مخزَّنة محليًا. ويمكنك أيضًا استخدام العناوين من جهة الخادم، مثل no-store، للإشارة إلى أنه يجب ألا يخزّن التطبيق محتوى معيّنًا في ذاكرة التخزين المؤقت.

تستخدم الأجهزة التي تعمل بأنظمة تشغيل أقدم من Android 4.4 (مستوى واجهة برمجة التطبيقات 19) إصدار webkit الذي يتضمّن عددًا من مشاكل الأمان. وكحل بديل، إذا كان تطبيقك يعمل على هذه الأجهزة، يجب التأكّد من أنّ عناصر WebView تعرض المحتوى الموثوق به فقط. للتأكّد من عدم تعرُّض تطبيقك للثغرات الأمنية المحتملة في طبقة المقابس الآمنة، يمكنك استخدام عنصر الأمان Provider القابل للتحديث كما هو موضَّح في تحديث موفِّر الأمان للحماية من استغلال طبقة المقابس الآمنة. إذا كان على تطبيقك عرض المحتوى من الويب المفتوح، ننصحك بتوفير عارض خاص بك حتى يظل محدّثًا بأحدث رموز تصحيح الأمان.

طلبات بيانات الاعتماد

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

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

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

بعد استخدام AccountManager لاسترداد Account، استخدِم CREATOR قبل تمرير أي بيانات اعتماد حتى لا يتم تمرير بيانات الاعتماد إلى التطبيق الخطأ بدون قصد.

إذا كانت التطبيقات التي تنشئها لا تستخدم بيانات الاعتماد إلا، يمكنك إثبات ملكية التطبيق الذي يصل إلى AccountManager باستخدام checkSignatures(). بدلاً من ذلك، إذا كان هناك تطبيق واحد فقط يستخدم بيانات الاعتماد، يمكنك استخدام KeyStore للتخزين.

التشفير

بالإضافة إلى توفير عزل البيانات، ودعم تشفير نظام الملفات بالكامل، وتوفير قنوات اتصال آمنة، يوفر Android مجموعة واسعة من الخوارزميات لحماية البيانات باستخدام التشفير.

تعرّف على موفري أمان بنية تشفير Java (JCA) التي يستخدمها برنامجك. حاول استخدام أعلى مستوى من تنفيذ إطار العمل الموجود مسبقًا الذي يمكن أن يدعم حالة الاستخدام لديك. يمكنك استخدام مقدّمي الخدمات الذين تحدّدهم Google بالترتيب الذي تحدّده Google، إن أمكن.

لقراءة الملفات المحلية وكتابتها بشكل أكثر أمانًا، يمكنك استخدام مكتبة الأمان.

إذا كنت تريد استرداد ملف بشكل آمن من أحد المواقع المعروفة على الشبكة، فقد يكون استخدام معرّف موارد منتظم (URI) البسيط الذي يستخدم HTTPS مناسبًا ولا يتطلب أي معرفة بالتشفير. إذا كنت بحاجة إلى نفق آمن، يمكنك استخدام HttpsURLConnection أو SSLSocket بدلاً من كتابة البروتوكول الخاص بك. إذا كنت تستخدم SSLSocket، يُرجى الانتباه إلى أنّه لا يجري التحقّق من اسم المضيف. يُرجى الاطّلاع على التحذيرات بشأن استخدام SSLSocket بشكل مباشر.

وإذا وجدت أنك بحاجة إلى تنفيذ بروتوكولك الخاص، لا تنفِّذ خوارزميات التشفير الخاصة بك. استخدام خوارزميات التشفير الحالية، مثل عمليات تنفيذ AES وRSA المتوفرة في الفئة Cipher. بالإضافة إلى ذلك، اتبع أفضل الممارسات التالية:

  • استخدام 256-bit AES للأغراض التجارية. (استخدام 128 بت AES في حال عدم توفّرها)
  • استخدم إما أحجام المفاتيح العامة 224 أو 256 بت لتشفير المنحنى البيضاوي (EC).
  • تعرّف على حالات استخدام أوضاع الحظر في CBC أو نسبة النقر إلى الظهور أو GCM.
  • تجنَّب إعادة استخدام IV/ضد في وضع نسبة النقر إلى الظهور. تأكد من أنها عشوائية بشكل عشوائي.
  • عند استخدام التشفير، يجب تنفيذ التكامل باستخدام وضع CBC أو نسبة النقر إلى الظهور من خلال إحدى الوظائف التالية:
    • اختبار HMAC-SHA1
    • معيار HMAC-SHA-256
    • اختبار HMAC-SHA-512
    • وضع GCM

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

إذا كنت بحاجة إلى تخزين مفتاح للاستخدام المتكرّر، يمكنك استخدام آلية، مثل KeyStore، توفّر مساحة تخزين طويلة الأجل واسترجاع مفاتيح التشفير.

التواصل بين العمليات

تحاول بعض التطبيقات تنفيذ IPC باستخدام أساليب Linux التقليدية مثل مقابس الشبكة والملفات المشتركة. ومع ذلك، نقترح بدلاً من ذلك استخدام وظائف نظام Android مع تصنيف IPC مثل Intent أو Binder أو Messenger مع Service وBroadcastReceiver. تتيح لك آليات IPC لنظام التشغيل Android التحقق من هوية التطبيق المتصل بـ IPC وضبط سياسة أمان لكل آلية من آليات IPC.

تتم مشاركة العديد من عناصر الأمان عبر آليات IPC. إذا لم تكن آلية IPC مخصّصة للاستخدام من خلال تطبيقات أخرى، اضبط السمة android:exported على false في عنصر البيان الخاص بالمكوِّن، على سبيل المثال للعنصر <service>. هذا مفيد للتطبيقات التي تتكون من عمليات متعددة داخل نفس المُعرّف الفريد أو إذا قررت متأخرًا في التطوير أنك لا تريد بالفعل إظهار الوظائف كـ IPC، ولكنك لا تريد إعادة كتابة التعليمات البرمجية.

إذا كان بإمكان التطبيقات الأخرى الوصول إلى IPC، يمكنك تطبيق سياسة أمان باستخدام العنصر <permission>. إذا كان IPC بين تطبيقات تملكها ووقّعت باستخدام المفتاح نفسه، استخدِم إذنًا على مستوى signature في android:protectionLevel.

مكان ووقت الاستماع إلى الموسيقى

بالنسبة إلى الأنشطة وأجهزة استقبال البث، تُعد الأغراض الآلية المفضلة للاتصال IPC غير المتزامن على Android. وفقًا لمتطلبات التطبيق، يمكنك استخدام sendBroadcast() أو sendOrderedBroadcast() أو هدف صريح لمكوّن معيّن في التطبيق. يُفضَّل استخدام الأغراض الفاضحة لأغراض تتعلّق بالأمان.

تنبيه: إذا كنت تستخدم غرضًا لربط التطبيق Service، يجب استخدام هدف صريح للحفاظ على أمان تطبيقك. يشكل استخدام نية ضمنية لبدء الخدمة خطرًا أمنيًا، لأنك لن تكون متأكدًا من الخدمة التي ستستجيب للنية، ولا يمكن للمستخدم معرفة الخدمة التي يتم تشغيلها. بدايةً من Android 5.0 (المستوى 21 من واجهة برمجة التطبيقات)، يطرح النظام استثناءً إذا استدعيت bindService() بهدف ضمني.

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

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

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

الخدمات

غالبًا ما يتم استخدام Service لتوفير وظائف للتطبيقات الأخرى لاستخدامها. يجب أن يكون لكل فئة خدمة إعلان <service> مقابل في ملف البيان.

وفقًا للإعدادات التلقائية، لا يتم تصدير الخدمات ولا يمكن استدعاءها من خلال أي تطبيق آخر. ومع ذلك، إذا أضفت أي فلاتر أهداف إلى بيان الخدمة، سيتم تصديرها تلقائيًا. ومن الأفضل أن تعلن عن السمة android:exported بشكل صريح للتأكّد من أنّها تعمل بالطريقة التي تريدها. يمكن أيضًا حماية الخدمات باستخدام السمة android:permission. لإجراء ذلك، يجب أن تشير التطبيقات الأخرى إلى عنصر <uses-permission> مقابل في ملف البيان الخاص بها ليكون بإمكانها تشغيل الخدمة أو إيقافها أو الربط بها.

ملاحظة: إذا كان تطبيقك يستهدف الإصدار Android 5.0 (المستوى 21 لواجهة برمجة التطبيقات) أو إصدارًا أحدث، استخدِم JobScheduler لتنفيذ الخدمات التي تعمل في الخلفية.

يمكن للخدمة حماية استدعاءات IPC الفردية التي يتم إجراؤها فيها من خلال الأذونات. يتم ذلك من خلال استدعاء checkCallingPermission() قبل تنفيذ الاستدعاء. نوصي باستخدام أذونات تصريحية في البيان، نظرًا لأن تلك الأذونات أقل عرضة للإهمال.

تنبيه: لا تخلط بين أذونات العميل والخادم، واحرص على أن يكون لدى التطبيق المطلوب الأذونات المناسبة وتأكَّد من أنّك تمنح الأذونات نفسها لتطبيق الاتصال.

واجهتا Binder وMessenger

إنّ استخدام Binder أو Messenger هو الآلية المفضّلة لنمط IPC لنمط استدعاء إجراء عن بُعد (IPC) على Android. توفر واجهات محددة جيدًا تمكن المصادقة المتبادلة لنقاط النهاية، إذا لزم الأمر.

ننصحك بتصميم واجهات تطبيقك بطريقة لا تتطلب عمليات تحقّق من الأذونات الخاصة بالواجهة. لا يتم الإعلان عن كائنات Binder وMessenger ضمن بيان التطبيق، وبالتالي لا يمكنك تطبيق أذونات تعريفية عليها مباشرةً. وتكتسب هذه الأذونات بشكل عام الأذونات المعلَن عنها في بيان التطبيق الخاص بـ Service أو Activity التي يتم تنفيذها. إذا كنت تنشئ واجهة تتطلب المصادقة و/أو عناصر التحكم في الوصول، يجب إضافة عناصر التحكم هذه بشكل صريح كرمز في الواجهة Binder أو Messenger.

في حال توفير واجهة تتطلب عناصر تحكُّم بالوصول، استخدِم checkCallingPermission() للتحقّق مما إذا كان المتصل لديه الإذن المطلوب. وهذا مهم على وجه الخصوص قبل الدخول إلى خدمة نيابةً عن المتصل، حيث يتم تمرير هوية تطبيقك إلى الواجهات الأخرى. في حال استدعاء واجهة يوفّرها Service، قد يتعذّر استدعاء bindService() إذا لم يكن لديك إذن بالوصول إلى الخدمة المحدّدة. إذا كنت بحاجة إلى السماح لعملية خارجية بالتفاعل مع تطبيقك ولكن ليس لديها الأذونات اللازمة لإجراء ذلك، يمكنك استخدام طريقة clearCallingIdentity(). تؤدي هذه الطريقة إلى إجراء الاتصال بواجهة تطبيقك كما لو كان تطبيقك يُجري الاتصال نفسه، بدلاً من المتصل الخارجي. يمكنك استعادة أذونات المتصل لاحقًا باستخدام طريقة restoreCallingIdentity().

ولمزيدٍ من المعلومات عن تنفيذ IPC باستخدام إحدى الخدمات، اطّلِع على الخدمات المرتبطة.

أجهزة استقبال البث

يعالج BroadcastReceiver الطلبات غير المتزامنة التي تبدأ من Intent.

يتم تصدير أجهزة الاستقبال تلقائيًا ويمكن استدعاؤها من أي تطبيق آخر. إذا كان BroadcastReceiver مخصّصًا للاستخدام من خلال تطبيقات أخرى، قد تحتاج إلى تطبيق أذونات الأمان على أجهزة الاستقبال التي تستخدم العنصر <receiver> ضمن بيان التطبيق. يمنع ذلك التطبيقات التي لا تملك الأذونات المناسبة من إرسال الغرض إلى BroadcastReceiver.

الأمان باستخدام رمز تم تحميله ديناميكيًا

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

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

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

الأمان في جهاز افتراضي

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

إذا كنت مهتمًا بمعرفة المزيد من المعلومات عن أمان الأجهزة الافتراضية، يمكنك الاطّلاع على بعض المؤلفات الحالية حول هذا الموضوع. اثنان من أكثر الموارد شيوعًا هما:

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

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

الأمان في الرموز البرمجية الأصلية

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

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

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