چک لیست امنیتی

اندروید دارای ویژگی‌های امنیتی داخلی است که به طور قابل توجهی فراوانی و تأثیر مشکلات امنیتی برنامه‌ها را کاهش می‌دهد. این سیستم به گونه‌ای طراحی شده است که شما معمولاً می‌توانید برنامه‌های خود را با مجوزهای پیش‌فرض سیستم و فایل بسازید و از تصمیم‌گیری‌های دشوار در مورد امنیت اجتناب کنید.

ویژگی‌های امنیتی اصلی زیر به شما در ساخت برنامه‌های امن کمک می‌کنند:

  • سندباکس اپلیکیشن اندروید، که داده‌های اپلیکیشن و اجرای کد شما را از سایر اپلیکیشن‌ها جدا می‌کند.
  • یک چارچوب کاربردی با پیاده‌سازی‌های قوی از قابلیت‌های امنیتی رایج مانند رمزنگاری، مجوزها و ارتباط بین پردازشی امن (IPC).
  • فناوری‌هایی مانند تصادفی‌سازی طرح‌بندی فضای آدرس (ASLR) ، بدون اجرا (NX) ، ProPolice، safe_iop ، OpenBSD dlmalloc و calloc و لینوکس mmap_min_addr برای کاهش خطرات مرتبط با خطاهای رایج مدیریت حافظه.
  • مجوزهای اعطا شده توسط کاربر برای محدود کردن دسترسی به ویژگی‌های سیستم و داده‌های کاربر.
  • مجوزهای تعریف‌شده توسط برنامه برای کنترل داده‌های برنامه بر اساس هر برنامه.

آشنایی با بهترین شیوه‌های امنیتی اندروید که در این صفحه آمده است، بسیار مهم است. پیروی از این شیوه‌ها به عنوان عادات کلی کدنویسی به شما کمک می‌کند تا از بروز ناخواسته مشکلات امنیتی که بر کاربران شما تأثیر منفی می‌گذارد، جلوگیری کنید.

احراز هویت

احراز هویت پیش‌نیاز بسیاری از عملیات امنیتی کلیدی است. برای کنترل دسترسی به دارایی‌های محافظت‌شده مانند داده‌های کاربر، عملکرد برنامه و سایر منابع، باید احراز هویت را به برنامه اندروید خود اضافه کنید.

شما می‌توانید با ادغام برنامه خود با Credential Manager ، تجربه احراز هویت کاربر خود را بهبود بخشید. Credential Manager یک کتابخانه Android Jetpack است که پشتیبانی API را برای اکثر روش‌های اصلی احراز هویت، از جمله کلیدهای عبور، رمزهای عبور و راه‌حل‌های ورود به سیستم فدرال مانند ورود با Google ، یکپارچه می‌کند.

برای افزایش بیشتر امنیت برنامه خود، اضافه کردن روش‌های احراز هویت بیومتریک مانند اسکن اثر انگشت یا تشخیص چهره را در نظر بگیرید. گزینه‌های خوب برای اضافه کردن احراز هویت بیومتریک ممکن است شامل برنامه‌های مالی، مراقبت‌های بهداشتی یا مدیریت هویت باشد.

چارچوب تکمیل خودکار اندروید می‌تواند فرآیند ثبت نام و ورود را آسان کند و میزان خطا و اصطکاک کاربر را کاهش دهد. تکمیل خودکار با مدیران رمز عبور ادغام می‌شود و به کاربران امکان می‌دهد رمزهای عبور پیچیده و تصادفی را انتخاب کنند که می‌توانند به راحتی و ایمن ذخیره و بازیابی شوند.

یکپارچگی برنامه

API یکپارچگی بازی به شما کمک می‌کند تا بررسی کنید که آیا تعاملات و درخواست‌های سرور از فایل باینری اصلی برنامه شما که روی یک دستگاه اندروید اصلی اجرا می‌شود، می‌آیند یا خیر. با تشخیص تعاملات بالقوه خطرناک و جعلی، مانند تعاملات ناشی از نسخه‌های دستکاری‌شده برنامه و محیط‌های غیرقابل اعتماد، سرور بک‌اند برنامه شما می‌تواند با اقدامات مناسب برای جلوگیری از حملات و کاهش سوءاستفاده پاسخ دهد.

ذخیره‌سازی داده‌ها

رایج‌ترین نگرانی امنیتی برای یک برنامه در اندروید این است که آیا داده‌هایی که در دستگاه ذخیره می‌کنید برای سایر برنامه‌ها قابل دسترسی است یا خیر. سه راه اساسی برای ذخیره داده‌ها در دستگاه وجود دارد:

  • حافظه داخلی
  • حافظه خارجی
  • ارائه دهندگان محتوا

بخش‌های زیر مسائل امنیتی مرتبط با هر رویکرد را شرح می‌دهند.

حافظه داخلی

به طور پیش‌فرض، فایل‌هایی که در حافظه داخلی ایجاد می‌کنید فقط برای برنامه شما قابل دسترسی هستند. اندروید این محافظت را پیاده‌سازی کرده است و برای اکثر برنامه‌ها کافی است.

از حالت‌های منسوخ‌شده‌ی MODE_WORLD_WRITEABLE و MODE_WORLD_READABLE برای فایل‌های IPC اجتناب کنید. آن‌ها امکان محدود کردن دسترسی به داده‌ها را برای برنامه‌های خاص فراهم نمی‌کنند و هیچ کنترلی بر فرمت داده‌ها ارائه نمی‌دهند. اگر می‌خواهید داده‌های خود را با سایر فرآیندهای برنامه به اشتراک بگذارید، به جای آن از یک ارائه‌دهنده محتوا استفاده کنید که مجوزهای خواندن و نوشتن را به برنامه‌های دیگر ارائه می‌دهد و می‌تواند مجوزهای پویا را به صورت موردی اعطا کند.

حافظه خارجی

فایل‌های ایجاد شده در حافظه خارجی ، مانند کارت‌های SD، به صورت سراسری قابل خواندن و نوشتن هستند. از آنجا که حافظه خارجی می‌تواند توسط کاربر حذف شود و همچنین توسط هر برنامه‌ای تغییر یابد، فقط اطلاعات غیر حساس را با استفاده از حافظه خارجی ذخیره کنید.

هنگام مدیریت داده‌ها از حافظه خارجی، اعتبارسنجی ورودی را مانند هر منبع غیرقابل اعتماد دیگری انجام دهید . فایل‌های اجرایی یا فایل‌های کلاس را قبل از بارگذاری پویا در حافظه خارجی ذخیره نکنید. اگر برنامه شما فایل‌های اجرایی را از حافظه خارجی بازیابی می‌کند، قبل از بارگذاری پویا، مطمئن شوید که فایل‌ها امضا شده و از نظر رمزنگاری تأیید شده‌اند.

ارائه دهندگان محتوا

ارائه دهندگان محتوا یک مکانیزم ذخیره‌سازی ساختاریافته ارائه می‌دهند که می‌تواند به برنامه شما محدود شود یا برای دسترسی سایر برنامه‌ها صادر شود. اگر قصد ندارید به برنامه‌های دیگر دسترسی به ContentProvider خود را ارائه دهید، آن را در مانیفست برنامه به صورت android:exported=false علامت‌گذاری کنید. در غیر این صورت، ویژگی android:exported روی true تنظیم کنید تا سایر برنامه‌ها به داده‌های ذخیره شده دسترسی داشته باشند.

هنگام ایجاد یک ContentProvider که برای استفاده توسط برنامه‌های دیگر صادر می‌شود، می‌توانید یک مجوز واحد برای خواندن و نوشتن تعیین کنید، یا می‌توانید مجوزهای مجزایی برای خواندن و نوشتن تعیین کنید. مجوزهای خود را به مواردی که برای انجام وظیفه مورد نظر لازم است محدود کنید. به خاطر داشته باشید که معمولاً اضافه کردن مجوزها بعداً برای نمایش قابلیت‌های جدید آسان‌تر از حذف آنها و تحت تأثیر قرار دادن کاربران موجود است.

اگر از یک ارائه‌دهنده محتوا برای اشتراک‌گذاری داده‌ها فقط بین برنامه‌های خودتان استفاده می‌کنید، توصیه می‌کنیم از ویژگی android:protectionLevel که روی signature protection تنظیم شده است، استفاده کنید. مجوزهای امضا نیازی به تأیید کاربر ندارند، بنابراین وقتی برنامه‌هایی که به داده‌ها دسترسی دارند با کلید یکسان امضا شده باشند، تجربه کاربری بهتر و دسترسی کنترل‌شده‌تری به داده‌های ارائه‌دهنده محتوا ارائه می‌دهند.

ارائه دهندگان محتوا همچنین می‌توانند با تعریف ویژگی android:grantUriPermissions و استفاده از پرچم‌های FLAG_GRANT_READ_URI_PERMISSION و FLAG_GRANT_WRITE_URI_PERMISSION در شیء Intent که کامپوننت را فعال می‌کند، دسترسی جزئی‌تری ارائه دهند. دامنه این مجوزها را می‌توان با عنصر <grant-uri-permission> محدودتر کرد.

هنگام دسترسی به یک ارائه‌دهنده محتوا، از متدهای پرس‌وجوی پارامتری مانند query ، update و delete() استفاده کنید تا از تزریق SQL احتمالی از منابع غیرقابل اعتماد جلوگیری شود. توجه داشته باشید که اگر آرگومان selection با الحاق داده‌های کاربر قبل از ارسال آن به متد ساخته شده باشد، استفاده از متدهای پارامتری کافی نیست.

در مورد مجوز نوشتن، احساس امنیت کاذب نداشته باشید. مجوز نوشتن به دستورات SQL اجازه می‌دهد تا برخی از داده‌ها را با استفاده از عبارات WHERE خلاقانه و تجزیه نتایج، تأیید کنند. به عنوان مثال، یک مهاجم ممکن است با تغییر یک ردیف، وجود یک شماره تلفن خاص را در گزارش تماس بررسی کند، تنها در صورتی که آن شماره تلفن از قبل وجود داشته باشد. اگر داده‌های ارائه دهنده محتوا ساختار قابل پیش‌بینی داشته باشند، مجوز نوشتن می‌تواند معادل فراهم کردن هر دو مجوز خواندن و نوشتن باشد.

مجوزها

از آنجا که سندباکس‌های اندروید، برنامه‌ها را از یکدیگر جدا می‌کنند، برنامه‌ها باید صریحاً منابع و داده‌ها را به اشتراک بگذارند. آن‌ها این کار را با اعلام مجوزهایی که برای قابلیت‌های اضافی که توسط سندباکس اصلی ارائه نمی‌شوند، از جمله دسترسی به ویژگی‌های دستگاه مانند دوربین، نیاز دارند، انجام می‌دهند.

درخواست‌های مجوز

تعداد مجوزهایی که برنامه شما درخواست می‌کند را به حداقل برسانید. محدود کردن دسترسی به مجوزهای حساس، خطر سوءاستفاده سهوی از آن مجوزها را کاهش می‌دهد، پذیرش کاربر را بهبود می‌بخشد و برنامه شما را در برابر مهاجمان کمتر آسیب‌پذیر می‌کند. به طور کلی، اگر مجوزی برای عملکرد برنامه شما لازم نیست، آن را درخواست نکنید. به راهنمای ارزیابی اینکه آیا برنامه شما نیاز به اعلام مجوز دارد یا خیر، مراجعه کنید.

در صورت امکان، برنامه خود را به گونه‌ای طراحی کنید که نیازی به هیچ مجوزی نداشته باشد. برای مثال، به جای درخواست دسترسی به اطلاعات دستگاه برای ایجاد یک شناسه منحصر به فرد، یک UUID برای برنامه خود ایجاد کنید. (در بخش مربوط به داده‌های کاربر بیشتر بدانید). یا به جای استفاده از حافظه خارجی (که نیاز به مجوز دارد)، داده‌ها را در حافظه داخلی ذخیره کنید.

علاوه بر درخواست مجوزها، برنامه شما می‌تواند از عنصر <permission> برای محافظت از IPC که از نظر امنیتی حساس است و در معرض برنامه‌های دیگر، مانند ContentProvider قرار دارد، استفاده کند. به طور کلی، توصیه می‌کنیم در صورت امکان از کنترل‌های دسترسی غیر از مجوزهای تأیید شده توسط کاربر استفاده کنید، زیرا مجوزها می‌توانند برای کاربران گیج‌کننده باشند. به عنوان مثال، استفاده از سطح حفاظت امضا در مجوزها برای ارتباط IPC بین برنامه‌های ارائه شده توسط یک توسعه‌دهنده واحد را در نظر بگیرید.

داده‌های محافظت‌شده با مجوز را فاش نکنید. این اتفاق زمانی می‌افتد که برنامه شما داده‌هایی را از طریق IPC افشا می‌کند که فقط به این دلیل در دسترس هستند که برنامه شما مجوز دسترسی به آن داده‌ها را دارد. ممکن است کلاینت‌های رابط IPC برنامه شما همان مجوز دسترسی به داده‌ها را نداشته باشند. جزئیات بیشتر در مورد فراوانی و اثرات بالقوه این مشکل در مقاله تحقیقاتی «تفویض مجدد مجوز: حملات و دفاع‌ها » که در USENIX منتشر شده است، آمده است.

تعاریف مجوز

کوچکترین مجموعه از مجوزها را که الزامات امنیتی شما را برآورده می‌کند، تعریف کنید. ایجاد یک مجوز جدید برای اکثر برنامه‌ها نسبتاً غیرمعمول است، زیرا مجوزهای تعریف‌شده توسط سیستم، موقعیت‌های زیادی را پوشش می‌دهند. در صورت لزوم، بررسی‌های دسترسی را با استفاده از مجوزهای موجود انجام دهید.

اگر به مجوز جدیدی نیاز دارید، در نظر بگیرید که آیا می‌توانید وظیفه خود را با سطح حفاظت امضا انجام دهید یا خیر. مجوزهای امضا برای کاربر شفاف هستند و فقط به برنامه‌هایی که توسط همان توسعه‌دهنده‌ای که برنامه بررسی مجوز را انجام می‌دهد، امضا شده‌اند، اجازه دسترسی می‌دهند.

اگر هنوز ایجاد یک مجوز جدید لازم است، آن را با استفاده از عنصر <permission> در مانیفست برنامه اعلام کنید. برنامه‌هایی که از مجوز جدید استفاده می‌کنند می‌توانند با اضافه کردن عنصر <uses-permission> در فایل‌های مانیفست خود به آن ارجاع دهند. همچنین می‌توانید با استفاده از متد addPermission() مجوزها را به صورت پویا اضافه کنید.

اگر مجوزی با سطح حفاظت خطرناک ایجاد کنید، باید چندین پیچیدگی را در نظر بگیرید:

  • این مجوز باید شامل رشته‌ای باشد که به طور خلاصه تصمیم امنیتی مورد نیاز کاربر را برای او بیان کند.
  • رشته مجوز باید برای زبان‌های مختلف بومی‌سازی شود.
  • کاربران ممکن است به دلیل گیج‌کننده بودن یا ریسکی بودن مجوز، از نصب یک برنامه صرف نظر کنند.
  • ممکن است برنامه‌ها زمانی درخواست مجوز کنند که سازنده‌ی مجوز نصب نشده باشد.

هر یک از این موارد، چالش غیرفنی قابل توجهی را برای شما به عنوان توسعه‌دهنده ایجاد می‌کند و در عین حال کاربران شما را گیج می‌کند، به همین دلیل است که ما استفاده از سطح مجوز خطرناک را توصیه نمی‌کنیم.

شبکه‌سازی

تراکنش‌های شبکه ذاتاً از نظر امنیتی پرخطر هستند، زیرا شامل انتقال داده‌هایی می‌شوند که بالقوه برای کاربر خصوصی هستند. مردم به طور فزاینده‌ای از نگرانی‌های مربوط به حریم خصوصی یک دستگاه تلفن همراه آگاه هستند، به خصوص هنگامی که دستگاه تراکنش‌های شبکه را انجام می‌دهد، بنابراین بسیار مهم است که برنامه شما تمام بهترین شیوه‌ها را برای ایمن نگه داشتن داده‌های کاربر در همه زمان‌ها اجرا کند.

شبکه IP

شبکه‌سازی در اندروید تفاوت چندانی با سایر محیط‌های لینوکس ندارد. نکته کلیدی این است که مطمئن شوید از پروتکل‌های مناسب برای داده‌های حساس استفاده می‌شود، مانند HttpsURLConnection برای ترافیک وب امن. در هر جایی که HTTPS روی سرور پشتیبانی می‌شود، از HTTPS به جای HTTP استفاده کنید، زیرا دستگاه‌های تلفن همراه اغلب به شبکه‌هایی متصل می‌شوند که امن نیستند، مانند هات‌اسپات‌های Wi-Fi عمومی.

ارتباط رمزگذاری‌شده و احراز هویت‌شده در سطح سوکت را می‌توان به راحتی با استفاده از کلاس SSLSocket پیاده‌سازی کرد. با توجه به فراوانی اتصال دستگاه‌های اندروید به شبکه‌های بی‌سیم ناامن با استفاده از Wi-Fi، استفاده از شبکه امن برای همه برنامه‌هایی که از طریق شبکه ارتباط برقرار می‌کنند، اکیداً توصیه می‌شود.

برخی از برنامه‌ها از پورت‌های شبکه محلی برای مدیریت IPC حساس استفاده می‌کنند. از این رویکرد استفاده نکنید، زیرا این رابط‌ها توسط سایر برنامه‌های روی دستگاه قابل دسترسی هستند. در عوض، از یک مکانیزم IPC اندروید که احراز هویت در آن امکان‌پذیر است، مانند یک Service ، استفاده کنید. اتصال به آدرس IP غیر اختصاصی INADDR_ANY بدتر از استفاده از loopback است، زیرا به برنامه شما اجازه می‌دهد درخواست‌ها را از هر آدرس IP دریافت کند.

مطمئن شوید که به داده‌های دانلود شده از HTTP یا سایر پروتکل‌های ناامن اعتماد ندارید. این شامل اعتبارسنجی ورودی در WebView و هرگونه پاسخ به intent های صادر شده در برابر HTTP نیز می‌شود.

شبکه تلفن

پروتکل سرویس پیام کوتاه (SMS) در درجه اول برای ارتباط کاربر با کاربر طراحی شده است و برای برنامه‌هایی که می‌خواهند داده منتقل کنند، مناسب نیست. با توجه به محدودیت‌های SMS، توصیه می‌کنیم از Firebase Cloud Messaging (FCM) و شبکه IP برای ارسال پیام‌های داده از یک وب سرور به برنامه خود در دستگاه کاربر استفاده کنید.

توجه داشته باشید که پیامک نه در شبکه و نه در دستگاه، رمزگذاری شده و نه به شدت احراز هویت شده است. به طور خاص، هر گیرنده پیامک باید انتظار داشته باشد که یک کاربر مخرب ممکن است پیامک را به برنامه شما ارسال کرده باشد. برای انجام دستورات حساس به داده‌های پیامکی احراز هویت نشده اعتماد نکنید. همچنین، توجه داشته باشید که پیامک می‌تواند در معرض جعل و/یا رهگیری در شبکه قرار گیرد. در خود دستگاه مبتنی بر اندروید، پیام‌های پیامکی به صورت Broadcast intents ارسال می‌شوند، بنابراین می‌توانند توسط برنامه‌های دیگری که مجوز READ_SMS دارند، خوانده یا ضبط شوند.

اعتبارسنجی ورودی

اعتبارسنجی ناکافی ورودی یکی از رایج‌ترین مشکلات امنیتی است که برنامه‌ها را تحت تأثیر قرار می‌دهد، صرف نظر از اینکه روی چه پلتفرمی اجرا می‌شوند. اندروید اقدامات متقابلی در سطح پلتفرم دارد که احتمال مواجهه برنامه‌ها با مشکلات اعتبارسنجی ورودی را کاهش می‌دهد و توصیه می‌کنیم در صورت امکان از این ویژگی‌ها استفاده کنید. همچنین، توصیه می‌کنیم از زبان‌های type-safe برای کاهش احتمال مشکلات اعتبارسنجی ورودی استفاده کنید.

اگر از کد بومی استفاده می‌کنید، هر داده‌ای که از فایل‌ها خوانده می‌شود، از طریق شبکه دریافت می‌شود یا از یک IPC دریافت می‌شود، پتانسیل ایجاد یک مشکل امنیتی را دارد. رایج‌ترین مشکلات، سرریز بافر ، استفاده پس از آزادسازی و خطاهای off-by-one هستند. اندروید تعدادی فناوری مانند ASLR و پیشگیری از اجرای داده‌ها (DEP) را ارائه می‌دهد که قابلیت سوءاستفاده از این خطاها را کاهش می‌دهد، اما مشکل اساسی را حل نمی‌کنند. می‌توانید با مدیریت دقیق اشاره‌گرها و مدیریت بافرها از این آسیب‌پذیری‌ها جلوگیری کنید.

زبان‌های پویا و مبتنی بر رشته مانند جاوا اسکریپت و SQL نیز به دلیل کاراکترهای escape و تزریق اسکریپت ، در معرض مشکلات اعتبارسنجی ورودی قرار دارند.

اگر از داده‌هایی در کوئری‌هایی استفاده می‌کنید که به یک پایگاه داده SQL یا یک ارائه‌دهنده محتوا ارسال می‌شوند، تزریق SQL می‌تواند یک مشکل باشد. بهترین راه دفاع، استفاده از کوئری‌های پارامتری است، همانطور که در بخش مربوط به ارائه‌دهندگان محتوا بحث شده است. محدود کردن مجوزها به فقط خواندنی یا فقط نوشتنی نیز می‌تواند احتمال آسیب‌های مربوط به تزریق SQL را کاهش دهد.

اگر نمی‌توانید از ویژگی‌های امنیتی مورد بحث در این بخش استفاده کنید، حتماً از قالب‌های داده‌ای با ساختار مناسب استفاده کنید و تأیید کنید که داده‌ها با قالب مورد انتظار مطابقت دارند. اگرچه مسدود کردن کاراکترهای خاص یا انجام جایگزینی کاراکتر می‌تواند یک استراتژی مؤثر باشد، اما این تکنیک‌ها در عمل مستعد خطا هستند و توصیه می‌کنیم در صورت امکان از آنها اجتناب کنید.

داده‌های کاربر

بهترین رویکرد برای امنیت داده‌های کاربر، به حداقل رساندن استفاده از APIهایی است که به اطلاعات حساس یا شخصی دسترسی دارند. اگر به داده‌های کاربر دسترسی دارید، در صورت امکان از ذخیره یا انتقال آن خودداری کنید. در نظر بگیرید که آیا منطق برنامه شما می‌تواند با استفاده از یک هش یا شکل برگشت‌ناپذیر داده‌ها پیاده‌سازی شود یا خیر. به عنوان مثال، برنامه شما ممکن است از هش یک آدرس ایمیل به عنوان کلید اصلی برای جلوگیری از انتقال یا ذخیره آدرس ایمیل استفاده کند. این امر احتمال افشای ناخواسته داده‌ها را کاهش می‌دهد و همچنین احتمال تلاش مهاجمان برای سوءاستفاده از برنامه شما را نیز کاهش می‌دهد.

هر زمان که دسترسی به داده‌های خصوصی مورد نیاز است، کاربر خود را احراز هویت کنید و از روش‌های مدرن احراز هویت مانند کلیدهای عبور و مدیریت اعتبارنامه استفاده کنید. اگر برنامه شما نیاز به دسترسی به اطلاعات شخصی دارد، به خاطر داشته باشید که برخی از حوزه‌های قضایی ممکن است از شما بخواهند که یک سیاست حفظ حریم خصوصی ارائه دهید که نحوه استفاده و ذخیره‌سازی آن داده‌ها را توضیح دهد. برای ساده‌سازی انطباق، از بهترین شیوه‌های امنیتی به حداقل رساندن دسترسی به داده‌های کاربر پیروی کنید.

همچنین، در نظر بگیرید که آیا برنامه شما می‌تواند سهواً اطلاعات شخصی را در اختیار اشخاص ثالث، مانند مؤلفه‌های شخص ثالث برای تبلیغات یا سرویس‌های شخص ثالث مورد استفاده برنامه شما، قرار دهد یا خیر. اگر نمی‌دانید چرا یک مؤلفه یا سرویس به اطلاعات شخصی نیاز دارد، آن را ارائه ندهید. به طور کلی، کاهش دسترسی برنامه شما به اطلاعات شخصی، احتمال بروز مشکلات در این زمینه را کاهش می‌دهد.

اگر برنامه شما نیاز به دسترسی به داده‌های حساس دارد، ارزیابی کنید که آیا نیاز به انتقال آن به سرور دارید یا می‌توانید عملیات را روی کلاینت اجرا کنید. برای جلوگیری از انتقال داده‌های کاربر، اجرای هر کدی را که از داده‌های حساس استفاده می‌کند روی کلاینت در نظر بگیرید. همچنین، مطمئن شوید که سهواً داده‌های کاربر را از طریق IPC بیش از حد مجاز، فایل‌های قابل نوشتن جهانی یا سوکت‌های شبکه در معرض سایر برنامه‌های روی دستگاه قرار نمی‌دهید. IPC بیش از حد مجاز، مورد خاصی از نشت داده‌های محافظت‌شده با مجوز است که در بخش درخواست‌های مجوز مورد بحث قرار گرفته است.

اگر به یک شناسه جهانی منحصر به فرد (GUID) نیاز دارید، یک شماره بزرگ و منحصر به فرد ایجاد کنید و آن را ذخیره کنید. از شناسه‌های تلفن مانند شماره تلفن یا IMEI استفاده نکنید، زیرا ممکن است با اطلاعات شخصی مرتبط باشند. این موضوع با جزئیات بیشتر در صفحه بهترین شیوه‌ها برای شناسه‌های منحصر به فرد مورد بحث قرار گرفته است.

هنگام نوشتن در گزارش‌های روی دستگاه مراقب باشید. در اندروید، گزارش‌ها یک منبع مشترک هستند و با مجوز READ_LOGS در دسترس برنامه‌ای قرار می‌گیرند. اگرچه داده‌های گزارش تلفن موقت هستند و با راه‌اندازی مجدد پاک می‌شوند، ثبت نامناسب اطلاعات کاربر می‌تواند ناخواسته داده‌های کاربر را به برنامه‌های دیگر نشت دهد. علاوه بر عدم ثبت اطلاعات شخصی، استفاده از گزارش را در برنامه‌های عملیاتی محدود کنید. برای پیاده‌سازی آسان این امر، از پرچم‌های اشکال‌زدایی و کلاس‌های Log سفارشی با سطوح ثبت گزارش که به راحتی قابل تنظیم هستند، استفاده کنید.

وب ویو

از آنجا که WebView از محتوای وب استفاده می‌کند که می‌تواند شامل HTML و جاوا اسکریپت باشد، استفاده نادرست از آن می‌تواند مشکلات امنیتی رایج وب مانند اسکریپت‌نویسی بین سایتی (تزریق جاوا اسکریپت) را ایجاد کند. اندروید شامل تعدادی مکانیسم برای کاهش دامنه این مشکلات بالقوه با محدود کردن قابلیت WebView به حداقل عملکرد مورد نیاز برنامه شما است.

اگر برنامه شما مستقیماً از جاوا اسکریپت در یک WebView استفاده نمی‌کند، تابع setJavaScriptEnabled را فراخوانی نکنید . برخی از کدهای نمونه از این متد استفاده می‌کنند؛ اگر کد نمونه‌ای را که از آن در یک برنامه کاربردی استفاده می‌کند، مجدداً استفاده می‌کنید، در صورت عدم نیاز، فراخوانی آن متد را حذف کنید. به طور پیش‌فرض، WebView جاوا اسکریپت را اجرا نمی‌کند، بنابراین اسکریپت‌نویسی بین سایتی امکان‌پذیر نیست.

از addJavaScriptInterface() با دقت خاصی استفاده کنید، زیرا به جاوا اسکریپت اجازه می‌دهد عملیاتی را فراخوانی کند که معمولاً برای برنامه‌های اندروید رزرو شده‌اند. اگر از آن استفاده می‌کنید، addJavaScriptInterface() را فقط در صفحات وبی که تمام ورودی‌های آنها قابل اعتماد است، نمایش دهید. اگر ورودی‌های غیرقابل اعتماد مجاز باشد، جاوا اسکریپت غیرقابل اعتماد ممکن است بتواند متدهای اندروید را در برنامه شما فراخوانی کند. به طور کلی، توصیه می‌کنیم addJavaScriptInterface() فقط در جاوا اسکریپتی که در APK برنامه شما موجود است، نمایش دهید.

اگر برنامه شما از طریق WebView به داده‌های حساس دسترسی پیدا می‌کند، استفاده از متد clearCache() را برای حذف هرگونه فایل ذخیره شده به صورت محلی در نظر بگیرید. همچنین می‌توانید از هدرهای سمت سرور، مانند no-store ، برای نشان دادن اینکه یک برنامه نباید محتوای خاصی را ذخیره کند، استفاده کنید.

دستگاه‌هایی که پلتفرم‌های قدیمی‌تر از اندروید ۴.۴ (API سطح ۱۹) را اجرا می‌کنند، از نسخه‌ای از webkit استفاده می‌کنند که دارای تعدادی مشکل امنیتی است. به عنوان یک راه حل، اگر برنامه شما روی این دستگاه‌ها اجرا می‌شود، باید تأیید کند که اشیاء WebView فقط محتوای قابل اعتماد را نمایش می‌دهند. برای اطمینان از اینکه برنامه شما در معرض آسیب‌پذیری‌های احتمالی SSL قرار نمی‌گیرد، از شیء Provider امنیت قابل به‌روزرسانی، همانطور که در «به‌روزرسانی ارائه‌دهنده امنیت خود برای محافظت در برابر سوءاستفاده‌های SSL » توضیح داده شده است، استفاده کنید. اگر برنامه شما باید محتوا را از وب باز رندر کند، ارائه‌دهنده رندر خود را در نظر بگیرید تا بتوانید آن را با آخرین وصله‌های امنیتی به‌روز نگه دارید.

درخواست‌های اعتبارنامه

درخواست‌های اعتبارنامه مسیری برای حمله هستند. در اینجا چند نکته برای کمک به شما در ایمن‌تر کردن درخواست‌های اعتبارنامه در برنامه‌های اندروید شما ارائه شده است.

به حداقل رساندن افشای اطلاعات اعتباری

  • از درخواست‌های غیرضروری برای اطلاعات احراز هویت خودداری کنید . برای اینکه حملات فیشینگ آشکارتر و احتمال موفقیت آنها کمتر شود، تعداد دفعات درخواست اطلاعات احراز هویت کاربر را به حداقل برسانید. در عوض، از یک توکن مجوز استفاده کنید و آن را به‌روز کنید. فقط حداقل اطلاعات لازم برای احراز هویت و مجوز را درخواست کنید.
  • اعتبارنامه‌ها را به صورت ایمن ذخیره کنید . از Credential Manager برای فعال کردن احراز هویت بدون رمز عبور با استفاده از کلیدهای عبور یا برای پیاده‌سازی ورود یکپارچه با استفاده از طرح‌هایی مانند ورود با گوگل استفاده کنید. اگر مجبور به استفاده از احراز هویت سنتی با رمز عبور هستید، شناسه‌های کاربری و رمزهای عبور را در دستگاه ذخیره نکنید. در عوض، احراز هویت اولیه را با استفاده از نام کاربری و رمز عبور ارائه شده توسط کاربر انجام دهید و سپس از یک توکن مجوز کوتاه مدت مخصوص سرویس استفاده کنید.
  • دامنه مجوزها را محدود کنید . برای کاری که فقط به دامنه محدودتری نیاز دارد، مجوزهای گسترده درخواست نکنید.
  • محدود کردن توکن‌های دسترسی . از عملیات توکن‌های کوتاه‌مدت و فراخوانی‌های API استفاده کنید.
  • نرخ احراز هویت را محدود کنید . درخواست‌های احراز هویت یا مجوز سریع و متوالی می‌تواند نشانه‌ای از حمله‌ی جستجوی فراگیر باشد. این نرخ‌ها را به یک فرکانس معقول محدود کنید، در حالی که همچنان امکان یک تجربه‌ی کاربردی و کاربرپسند از برنامه را فراهم می‌کنید.

استفاده از احراز هویت امن

  • کلیدهای عبور را پیاده‌سازی کنید . کلیدهای عبور را به عنوان یک ارتقاء امن‌تر و کاربرپسندتر به رمزهای عبور فعال کنید.
  • افزودن بیومتریک . امکان استفاده از احراز هویت بیومتریک مانند اثر انگشت یا تشخیص چهره را برای امنیت بیشتر فراهم کنید.
  • از ارائه‌دهندگان هویت فدرال استفاده کنید . Credential Manager از ارائه‌دهندگان احراز هویت فدرال مانند ورود با گوگل پشتیبانی می‌کند.
  • ارتباطات را رمزگذاری کنید. از HTTPS و فناوری‌های مشابه برای اطمینان از محافظت از داده‌هایی که برنامه شما از طریق شبکه ارسال می‌کند، استفاده کنید.

مدیریت حساب کاربری امن را تمرین کنید

  • با استفاده از AccountManager به سرویس‌هایی که برای چندین برنامه قابل دسترسی هستند متصل شوید. از کلاس AccountManager برای فراخوانی یک سرویس مبتنی بر ابر استفاده کنید و رمزهای عبور را روی دستگاه ذخیره نکنید.
  • پس از استفاده از AccountManager برای بازیابی یک Account ، قبل از ارسال هرگونه اعتبارنامه CREATOR استفاده کنید تا سهواً اعتبارنامه‌ها را به برنامه اشتباهی ارسال نکنید.
  • اگر اعتبارنامه‌ها فقط توسط برنامه‌هایی که شما ایجاد می‌کنید استفاده می‌شوند، می‌توانید برنامه‌ای را که به AccountManager دسترسی دارد با استفاده checkSignatures تأیید کنید. از طرف دیگر، اگر فقط یک برنامه از اعتبارنامه استفاده می‌کند، می‌توانید از یک KeyStore برای ذخیره‌سازی استفاده کنید.

هوشیار باشید

  • کد خود را به‌روز نگه دارید . حتماً کد منبع خود، از جمله کتابخانه‌ها و وابستگی‌های شخص ثالث را به‌روز کنید تا در برابر جدیدترین آسیب‌پذیری‌ها محافظت شوید.
  • فعالیت‌های مشکوک را زیر نظر داشته باشید . به دنبال سوءاستفاده‌های احتمالی، مانند الگوهای سوءاستفاده از مجوزها، باشید.
  • کد خود را بررسی کنید . بررسی‌های امنیتی منظمی را روی کدبیس خود انجام دهید تا مشکلات احتمالی درخواست اعتبارنامه را پیدا کنید.

مدیریت کلید API

کلیدهای API جزء حیاتی بسیاری از برنامه‌های اندروید هستند که آنها را قادر به دسترسی به سرویس‌های خارجی و انجام عملکردهای ضروری مانند اتصال به سرویس‌های نقشه‌برداری، احراز هویت و سرویس‌های آب و هوا می‌کند. با این حال، افشای این کلیدهای حساس می‌تواند عواقب شدیدی از جمله نقض داده‌ها، دسترسی غیرمجاز و ضررهای مالی داشته باشد. برای جلوگیری از چنین سناریوهایی، توسعه‌دهندگان باید استراتژی‌های امنی را برای مدیریت کلیدهای API در طول فرآیند توسعه پیاده‌سازی کنند.

برای محافظت از سرویس‌ها در برابر سوءاستفاده، کلیدهای API باید با دقت محافظت شوند. برای برقراری ارتباط بین برنامه و سرویسی که از کلید API استفاده می‌کند، باید دسترسی به API را ایمن کنید. هنگامی که برنامه شما کامپایل می‌شود و کد منبع برنامه شما شامل کلیدهای API است، این امکان برای یک مهاجم وجود دارد که برنامه را تجزیه کند و این منابع را پیدا کند.

این بخش برای دو گروه از توسعه‌دهندگان اندروید در نظر گرفته شده است: آن‌هایی که با تیم‌های زیرساختی در خط تولید تحویل مداوم خود کار می‌کنند و آن‌هایی که برنامه‌های مستقل را در فروشگاه Play مستقر می‌کنند. این بخش بهترین شیوه‌ها را برای نحوه مدیریت کلیدهای API شرح می‌دهد، به طوری که برنامه شما بتواند به طور ایمن با سرویس‌ها ارتباط برقرار کند.

تولید و ذخیره سازی

توسعه‌دهندگان باید با استفاده از یک رویکرد دفاع در عمق، ذخیره‌سازی کلید API را به عنوان یک جزء حیاتی از حفاظت از داده‌ها و حریم خصوصی کاربر در نظر بگیرند.

فضای ذخیره‌سازی کلید قوی

برای امنیت بهینه در مدیریت کلید، از Android Keystore استفاده کنید و کلیدهای ذخیره شده را با استفاده از ابزاری قوی مانند Tink Java رمزگذاری کنید.

محرومیت از کنترل منبع

هرگز کلیدهای API را در مخزن کد منبع خود قرار ندهید. اضافه کردن کلیدهای API به کد منبع، خطر افشای کلیدها به مخازن عمومی، نمونه‌های کد مشترک و فایل‌های به اشتراک گذاشته شده تصادفی را به همراه دارد. در عوض، از افزونه‌های Gradle مانند secrets-gradle-plugin برای کار با کلیدهای API در پروژه خود استفاده کنید.

کلیدهای مخصوص محیط

در صورت امکان، از کلیدهای API جداگانه برای محیط‌های توسعه، آزمایش و تولید استفاده کنید. از کلیدهای مختص هر محیط برای جداسازی هر محیط استفاده کنید، که این امر خطر افشای داده‌های تولید را کاهش می‌دهد و به شما امکان می‌دهد کلیدهای در معرض خطر را بدون تأثیر بر محیط تولید خود غیرفعال کنید.

کنترل استفاده و دسترسی

شیوه‌های ایمن‌سازی کلید API برای محافظت از API و کاربران شما ضروری است. در اینجا نحوه آماده‌سازی کلیدهای شما برای امنیت بهینه آورده شده است:

  • برای هر برنامه کلیدهای منحصر به فرد ایجاد کنید : برای هر برنامه از کلیدهای API جداگانه استفاده کنید تا به شناسایی و جداسازی دسترسی‌های مشکوک کمک کند.
  • محدودیت‌های IP را اعمال کنید : در صورت امکان، استفاده از کلید API را به آدرس‌ها یا محدوده‌های IP خاص محدود کنید.
  • محدود کردن استفاده از کلید برنامه تلفن همراه : با استفاده از بسته‌بندی برنامه‌های تلفن همراه خاص با کلید یا با استفاده از گواهی‌های برنامه، استفاده از کلید API را به آنها محدود کنید.
  • ثبت و نظارت بر فعالیت‌های مشکوک : سازوکارهای ثبت و نظارت بر استفاده از API را برای شناسایی فعالیت‌های مشکوک و جلوگیری از سوءاستفاده‌های احتمالی پیاده‌سازی کنید.

نکته : سرویس شما باید ویژگی‌هایی برای محدود کردن کلیدها به یک بسته یا پلتفرم خاص ارائه دهد. برای مثال، API نقشه‌های گوگل دسترسی به کلید را بر اساس نام بسته و کلید امضا محدود می‌کند.

OAuth 2.0 چارچوبی برای مجوز دسترسی به منابع فراهم می‌کند. این چارچوب استانداردهایی را برای نحوه تعامل کلاینت‌ها و سرورها تعریف می‌کند و امکان مجوزدهی امن را فراهم می‌کند. شما می‌توانید از OAuth 2.0 برای محدود کردن استفاده از کلید API به کلاینت‌های خاص استفاده کنید و دامنه دسترسی را طوری تعریف کنید که هر کلید API فقط حداقل سطح دسترسی مورد نیاز برای هدف مورد نظر خود را داشته باشد.

چرخش و انقضای کلید

برای کاهش خطر دسترسی غیرمجاز از طریق آسیب‌پذیری‌های کشف نشده API، مهم است که کلیدهای API را مرتباً بچرخانید. استاندارد ISO 27001 یک چارچوب انطباق برای تعداد دفعات چرخش کلید تعریف می‌کند. در بیشتر موارد، یک دوره چرخش کلید بین ۹۰ روز تا ۶ ماه باید کافی باشد. پیاده‌سازی یک سیستم مدیریت کلید قوی می‌تواند به شما در ساده‌سازی این فرآیندها کمک کند و کارایی نیازهای چرخش و انقضای کلید شما را بهبود بخشد.

بهترین شیوه‌های عمومی

  • استفاده از SSL/HTTPS : همیشه از ارتباط HTTPS برای رمزگذاری درخواست‌های API خود استفاده کنید.
  • پین کردن گواهی : برای یک لایه امنیتی بیشتر، می‌توانید پیاده‌سازی پین کردن گواهی را برای بررسی اینکه کدام گواهی‌ها معتبر هستند، در نظر بگیرید.
  • اعتبارسنجی و پاکسازی ورودی کاربر : ورودی کاربر را اعتبارسنجی و پاکسازی کنید تا از حملات تزریق که می‌توانند کلیدهای API را افشا کنند، جلوگیری شود.
  • پیروی از بهترین شیوه‌های امنیتی : بهترین شیوه‌های امنیتی عمومی را در فرآیند توسعه خود، از جمله تکنیک‌های کدنویسی امن، بررسی کد و اسکن آسیب‌پذیری، پیاده‌سازی کنید.
  • مطلع بمانید : در مورد آخرین تهدیدات امنیتی و بهترین شیوه‌ها برای مدیریت کلید API به‌روز باشید.
  • به‌روزرسانی SDKها : مطمئن شوید که SDKها و کتابخانه‌های شما به آخرین نسخه به‌روزرسانی شده‌اند.

رمزنگاری

اندروید علاوه بر فراهم کردن ایزوله‌سازی داده‌ها، پشتیبانی از رمزگذاری کامل سیستم فایل و ارائه کانال‌های ارتباطی امن، مجموعه‌ای گسترده از الگوریتم‌ها را برای محافظت از داده‌ها با استفاده از رمزنگاری ارائه می‌دهد.

بدانید که نرم‌افزار شما از کدام ارائه‌دهندگان امنیتی معماری رمزنگاری جاوا (JCA) استفاده می‌کند. سعی کنید از بالاترین سطح پیاده‌سازی چارچوب از پیش موجود که می‌تواند از مورد استفاده شما پشتیبانی کند، استفاده کنید. در صورت لزوم، از ارائه‌دهندگان ارائه شده توسط گوگل به ترتیب مشخص شده توسط گوگل استفاده کنید.

اگر نیاز به بازیابی ایمن فایلی از یک مکان شبکه شناخته‌شده دارید، یک HTTPS URI ساده ممکن است کافی باشد و نیازی به دانش رمزنگاری ندارد. اگر به یک تونل امن نیاز دارید، به جای نوشتن پروتکل خودتان، استفاده HttpsURLConnection یا SSLSocket را در نظر بگیرید. اگر از SSLSocket استفاده می‌کنید، توجه داشته باشید که تأیید نام میزبان را انجام نمی‌دهد. به هشدارهای مربوط به استفاده مستقیم SSLSocket مراجعه کنید.

اگر متوجه شدید که باید پروتکل خودتان را پیاده‌سازی کنید، الگوریتم‌های رمزنگاری خودتان را پیاده‌سازی نکنید. از الگوریتم‌های رمزنگاری موجود، مانند پیاده‌سازی‌های AES و RSA که در کلاس Cipher ارائه شده‌اند، استفاده کنید. علاوه بر این، این بهترین شیوه‌ها را دنبال کنید:

  • برای اهداف تجاری از AES 256 بیتی استفاده کنید. (در صورت عدم دسترسی، از AES 128 بیتی استفاده کنید.)
  • برای رمزنگاری منحنی بیضوی (EC) از کلیدهای عمومی با اندازه ۲۲۴ یا ۲۵۶ بیتی استفاده کنید.
  • بدانید چه زمانی از حالت‌های بلوکی CBC، CTR یا GCM استفاده کنید.
  • از استفاده مجدد IV/شمارنده در حالت CTR خودداری کنید. مطمئن شوید که آنها از نظر رمزنگاری تصادفی هستند.
  • هنگام استفاده از رمزگذاری، یکپارچگی را با استفاده از حالت CBC یا CTR با یکی از توابع زیر پیاده‌سازی کنید:
    • HMAC-SHA1
    • HMAC-SHA-256
    • HMAC-SH-512
    • حالت GCM

از یک مولد اعداد تصادفی امن، SecureRandom ، برای مقداردهی اولیه‌ی هرگونه کلید رمزنگاری تولید شده توسط KeyGenerator استفاده کنید. استفاده از کلیدی که با یک مولد اعداد تصادفی امن تولید نشده باشد، قدرت الگوریتم را به طور قابل توجهی تضعیف می‌کند و ممکن است امکان حملات آفلاین را فراهم کند.

اگر نیاز دارید که یک کلید را برای استفاده مکرر ذخیره کنید، از مکانیزمی مانند KeyStore استفاده کنید که امکان ذخیره و بازیابی طولانی مدت کلیدهای رمزنگاری را فراهم می‌کند.

ارتباط بین فرآیندی

برخی از برنامه‌ها سعی می‌کنند IPC را با استفاده از تکنیک‌های سنتی لینوکس مانند سوکت‌های شبکه و فایل‌های اشتراکی پیاده‌سازی کنند. با این حال، ما به جای آن توصیه می‌کنیم که از قابلیت‌های سیستم اندروید برای IPC مانند Intent ، Binder یا Messenger with a Service و BroadcastReceiver استفاده کنید. مکانیسم‌های IPC اندروید به شما امکان می‌دهند هویت برنامه‌ای که به IPC شما متصل است را تأیید کنید و برای هر مکانیسم IPC سیاست امنیتی تنظیم کنید.

بسیاری از عناصر امنیتی در مکانیسم‌های IPC مشترک هستند. اگر مکانیسم IPC شما برای استفاده توسط سایر برنامه‌ها در نظر گرفته نشده است، ویژگی android:exported در عنصر manifest کامپوننت، مانند عنصر <service> ، روی false تنظیم کنید. این برای برنامه‌هایی که از چندین فرآیند در یک UID مشابه تشکیل شده‌اند یا اگر در اواخر توسعه تصمیم بگیرید که واقعاً نمی‌خواهید عملکرد را به عنوان IPC افشا کنید، اما نمی‌خواهید کد را دوباره بنویسید، مفید است.

اگر IPC شما برای برنامه‌های دیگر قابل دسترسی است، می‌توانید با استفاده از عنصر <permission> یک سیاست امنیتی اعمال کنید. اگر IPC بین برنامه‌هایی است که متعلق به خودتان هستند و با کلید یکسان امضا شده‌اند، از یک مجوز signature-level در android:protectionLevel استفاده کنید.

اهداف

برای فعالیت‌ها و دریافت‌کننده‌های پخش، اینتنت‌ها مکانیزم ترجیحی برای IPC ناهمزمان در اندروید هستند. بسته به نیازهای برنامه شما، ممکن است sendBroadcast ، sendOrderedBroadcast یا یک اینتنت صریح برای یک جزء خاص برنامه استفاده کنید. برای اهداف امنیتی، اینتنت‌های صریح ترجیح داده می‌شوند.

Note that ordered broadcasts can be consumed by a recipient, so they might not be delivered to all applications. If you are sending an intent that must be delivered to a specific receiver, you must use an explicit intent that declares the receiver by name.

Senders of an intent can verify that the recipient has permission by specifying a non-null permission with the method call. Only applications with that permission receive the intent. If data within a broadcast intent might be sensitive, consider applying a permission to make sure that malicious applications can't register to receive those messages without appropriate permissions. In those circumstances, you might also consider invoking the receiver directly, rather than raising a broadcast.

خدمات

A Service is often used to supply functionality for other applications to use. Each service class must have a corresponding <service> declaration in its manifest file.

By default, services aren't exported and can't be invoked by any other application. However, if you add any intent filters to the service declaration, it is exported by default. It's best if you explicitly declare the android:exported attribute to be sure it behaves the way you intend it to. Services can also be protected using the android:permission attribute. By doing so, other applications need to declare a corresponding <uses-permission> element in their own manifest to be able to start, stop, or bind to the service.

A service can protect individual IPC calls that are made into it with permissions. This is done by calling checkCallingPermission() before executing the implementation of the call. We recommend using the declarative permissions in the manifest, since those are less prone to oversight.

Binder and Messenger interfaces

Using Binder or Messenger is the preferred mechanism for RPC style IPC on Android. They provide well-defined interfaces that enable mutual authentication of the endpoints, if required.

We recommend that you design your app interfaces in a way that doesn't require interface-specific permission checks. Binder and Messenger objects aren't declared within the application manifest, and therefore you can't apply declarative permissions directly to them. They generally inherit permissions declared in the application manifest for the Service or Activity within which they are implemented. If you are creating an interface that requires authentication and/or access controls, you must explicitly add those controls as code in the Binder or Messenger interface.

If you are providing an interface that does require access controls, use checkCallingPermission() to verify whether the caller has a required permission. This is especially important before accessing a service on behalf of the caller, as the identity of your application is passed to other interfaces. If you are invoking an interface provided by a Service , the bindService() invocation can fail if you don't have permission to access the given service. If you need to allow an external process to interact with your app but it doesn't have the necessary permissions to do so, you can use the clearCallingIdentity() method. This method performs the call to your app's interface as though your app were making the call itself, rather than the external caller. You can restore the caller permissions later with the restoreCallingIdentity() method.

For more information about performing IPC with a service, see Bound Services .

Broadcast receivers

A BroadcastReceiver handles asynchronous requests initiated by an Intent .

By default, receivers are exported and can be invoked by any other application. If your BroadcastReceiver is intended for use by other applications, you might want to apply security permissions to receivers using the <receiver> element within the application manifest. This prevents applications without appropriate permissions from sending an intent to the BroadcastReceiver .

Security with dynamically loaded code

We strongly discourage loading code from outside of your application APK. Doing so significantly increases the likelihood of application compromise due to code injection or code tampering. It also adds complexity around version management and application testing—and it can make it impossible to verify the behavior of an application, so it might be prohibited in some environments.

If your application does dynamically load code, the most important thing to keep in mind is that the dynamically loaded code runs with the same security permissions as the application APK. The user makes a decision to install your application based on your identity, and the user expects that you provide any code run within the application, including code that is dynamically loaded.

Many applications attempt to load code from insecure locations, such as downloaded from the network over unencrypted protocols or from world-writable locations such as external storage. These locations could let someone on the network modify the content in transit or another application on a user's device to modify the content on the device. On the other hand, modules included directly within your APK can't be modified by other applications. This is true whether the code is a native library or a class being loaded using DexClassLoader .

Security in a virtual machine

Dalvik is Android's runtime virtual machine (VM). Dalvik was built specifically for Android, but many of the concerns regarding secure code in other virtual machines also apply to Android. In general, you don't need to concern yourself with security issues relating to the virtual machine. Your application runs in a secure sandbox environment, so other processes on the system can't access your code or private data.

If you're interested in learning more about virtual machine security, familiarize yourself with some existing literature on the subject. Two of the more popular resources are:

This document focuses on areas that are Android specific or different from other VM environments. For developers experienced with VM programming in other environments, there are two broad issues that might be different about writing apps for Android:

  • Some virtual machines, such as the JVM or .NET runtime, act as a security boundary, isolating code from the underlying operating system capabilities. On Android, the Dalvik VM is not a security boundary—the application sandbox is implemented at the OS level, so Dalvik can interoperate with native code in the same application without any security constraints.
  • Given the limited storage on mobile devices, it's common for developers to want to build modular applications and use dynamic class loading. When doing this, consider both the source where you retrieve your application logic and where you store it locally. Don't use dynamic class loading from sources that aren't verified, such as unsecured network sources or external storage, because that code might be modified to include malicious behavior.

Security in native code

In general, we recommend using the Android SDK for application development, rather than using native code with the Android NDK . Applications built with native code are more complex, less portable, and more likely to include common memory-corruption errors such as buffer overflows.

Android is built using the Linux kernel, and being familiar with Linux development security best practices is especially useful if you are using native code. Linux security practices are beyond the scope of this document, but one of the most popular resources is Secure Programming HOWTO - Creating Secure Software .

An important difference between Android and most Linux environments is the application sandbox. On Android, all applications run in the application sandbox, including those written with native code. A good way to think about it for developers familiar with Linux is to know that every application is given a unique User Identifier (UID) with very limited permissions. This is discussed in more detail in the Android Security Overview , and you should be familiar with application permissions even if you are using native code.