سیستم عامل اندروید دارای feature های امنیتی از پیش تعیین شده بسیاری است ، مانند application sandboxing(این ویژگی امنیتی از تخریب سیستمی که برنامه ها روی آن اجرا می شوند جلو گیری می کند) ، محافظت در برابر حملات سرریز(overflow) بافر و عدد صحیح و فضاهای جداگانه حافظه برای دستورالعمل ها و داده های برنامه. در نتیجه ، برنامه های ساده اندروید که هیچگونه سیستم فایل یا عملیات شبکه ای را انجام نمی دهند ، اغلب می توانند به طور پیش فرض امن تلقی شوند.
اگر در حال توسعه یک برنامه پیچیده تر هستید ، با این حال وظیفه شما این است که آن را ایمن کرده و از حریم خصوصی کاربران خود محافظت کنید. در این مقاله ، برای ایجاد یک برنامه امن اندروید که می تواند داده ها یا مجوزها نشت نکند و به طور کلی در برابر برنامه های مخرب که ممکن است بر روی برنامه نصب شوند ، کمتر آسیب باشند را شما می توانید دنبال کنید.
1- از حافظه داخلی برای داده های مهم و حساس استفاده کنید
هر برنامه اندرویدی دارای یک پوشه ذخیره سازی داخلی (internal storage directory) است که مسیر آن بر اساس نام پکیج برنامه است. فایل های داخل این دایرکتوری بسیار امن هستند زیرا از شیوه ایجاد فایل MODE_PRIVATE به طور پیش فرض استفاده می کنند. این بدان معناست که هیچ برنامه دیگری در دستگاه نمی تواند به فایل ها دسترسی داشته باشد. بنابراین ، بهترین مکان برای ذخیره تمام داده های حساس برنامه شما، پوشه ذخیره سازی داخلی است.
زمانی که مسیر آن را بدانید, ارجاع به فایلهای داخل آن به همان سادگی ارجاع به فایلهای مربوط به هر دایرکتوری دیگر است. برای مثال, در اینجا ارجاع یک فایل به نام myfile.dat در دایرکتوری internal storage برنامه شما انجام می گیرد :
File myFile = new File(getFilesDir(), “myfile.dat”);
2- رمزگذاری داده ها در External Storage
ظرفیت حافظه داخلی دستگاه های اندرویدی اغلب محدود است. بنابراین ، گاهی اوقات ، ممکن است چاره ای جز ذخیره داده های حساس در external storage ، مانند removable SD card نداشته باشید.
از آنجا که کاربران و سایر برنامه های موجود در دستگاه می توانند به داده های external storage دسترسی مستقیم داشته باشند ، مهم است که آنها را در قالب رمزگذاری شده ذخیره کنید. یکی از محبوب ترین الگوریتم های رمزنگاری که امروزه توسعه دهندگان از آن استفاده می کنند AES است ، مخفف عبارت Advanced Encryption Standard ، با key size 256 بیت.
نوشتن کد برای رمزگذاری و رمزگشایی داده های برنامه با استفاده از پکیج javax.crypto ، که در SDK Android موجود است ، می تواند گیج کننده باشد. بنابراین ، اکثر توسعه دهندگان ترجیح می دهند از کتابخانه های third party مانند کتابخانهConceal فیس بوک استفاده کنند ، که معمولاً کار با آنها بسیار آسان تر است.
3- از Intent ها برای IPC استفاده کنید
برنامه نویسان باتجربه که به تازگی در توسعه برنامه های اندرویدی فعالیت می کنند ، اغلب سعی می کنند از سوکت ها ، pipe های نامگذاری شده یا فایل های به اشتراک گذاشته شده برای برقراری ارتباط همزمان با سایر برنامه های نصب شده در دستگاه اندروید استفاده کنند. این روش ها نه تنها سخت و نامناسب هستند ، بلکه مستعد تهدید نیز هستند. روش آسان تر و مطمئن تر در سیستم عامل اندروید ، استفاده از intent است.
برای ارسال داده به یک کامپوننت مشخص یک برنامه ، باید یک نمونه جدید از کلاس Intent ایجاد کنید و از متد setComponent()آن برای تعیین نام پکیج برنامه و نام کامپوننت استفاده کنید. سپس می توانید داده ها را با استفاده از متد() putExtra اضافه کنید.
به عنوان مثال ، در اینجا چگونگی ارسال رشته Hello World به یک Activity با نام MyActivity ، که متعلق به برنامه ای است که نام پکیج آن my.other.app است ، ارسال می شود:
// Create an intent
Intent intent = new Intent();
// Specify the component name
intent.setComponent(
new ComponentName(“my.other.app”,”my.other.app.MyActivity”)
);
// Add data
intent.putExtra(“DATA”, “Hello World!”);
// Send the intent to the activity
startActivity(intent);
برای ارسال داده به چندین برنامه به طور همزمان ، می توانید intent را با استفاده از روشsendBroadcast() به عنوان broadcast ارسال کنید. با این حال ، به طور پیش فرض ، broadcast را می توان با هر برنامه ای که دارای تنظیمات مناسب BroadcastReceiver است ، خواند.
بنابراین ، اگر می خواهید اطلاعات حساس را به عنوان broadcast ارسال کنید ، باید از permission سفارشی استفاده کنید که سطح حفاظت آن روی امضا تنظیم شده است. با انجام این کار ، سیستم عامل اندروید مطمئن می شود که فقط برنامه هایی که با کلید امضای (signing key)شما امضا شده اند می توانند broadcast را دریافت کنند.
این مثال نحوه ارسال رشته Hello World را به عنوان یک broadcast امن نشان می دهد:
// Create an intent
Intent intent = new Intent();
// Add data
intent.putExtra(“DATA”, “Hello World”);
// Specify an action name for
// the receiver’s intent-filter
intent.setAction(“my.app.receive”);
// Send as a broadcast using a custom permission
sendBroadcast(intent, “my.custom.permission”);
توجه داشته باشید که کد فوق تنها در صورتی کار می کند که مجوز سفارشی تعریف شود و در فایل های مانیفست (manifest) هر دو برنامه فرستنده و گیرنده مورد استفاده قرار گیرد.
<permission android:name=”my.custom.permission”
android:protectionLevel=”signature”/>
<uses-permission android:name=”my.custom.permission”/>
4- استفاده از https
تمام ارتباطات بین برنامه و سرورهای شما باید از طریق اتصال HTTPS باشد ، ترجیحاً از کلاس HttpsURLConnection استفاده کنید. اگر فکر می کنید استفاده از HTTP برای داده های محرمانه خوب است ، دوباره فکر کنید.
بسیاری از کاربران اندروید هر روز به چندین Wi-Fi hotspots باز در مناطق عمومی متصل می شوند. برخی از hotspot ها می توانند مخرب باشند. یک hotspot مخرب می تواند به راحتی محتویات ترافیک HTTP را تغییر دهد تا برنامه شما به گونه ای غیر منتظره رفتار کند ، یا بدتر از آن ، تبلیغات یا سوء استفاده هایی را به آن تزریق کند.
با استفاده از HTTPS ، تا زمانی که سرور با گواهی صادر شده توسط یک مرجع معتبر certificate ، مانند DigiCert یا GlobalSign پیکربندی شده باشد ، می توانید مطمئن باشید که ترافیک شبکه شما در برابر استراق سمع و حملات بین فردی ایمن خواهد بود.
اگر برنامه شما دارای کد شبکه (networking code) زیادی است و می ترسید که ناخواسته برخی داده ها را به عنوان cleartext ارسال کنید ، باید از nogotofail (یک ابزار اوپن سورس ساخته شده توسط Google) استفاده کنید تا چنین اشتباهاتی را پیدا کنید.
5- استفاده از FCM به جای SMS
زمانی که GCM (Firebase Cloud Messaging) وجود نداشت ، بسیاری از توسعه دهندگان از SMS برای انتقال داده ها از سرورهای خود به برنامه های خود استفاده می کردند. امروزه این عمل تا حد زیادی از بین رفته است.
اگر شما هنوز از SMS به سمت FCM ، switch نکرده اید ، باید بدانید که پروتکل پیامک نه رمزگذاری شده و نه در برابر حملات جعلی ایمن است. علاوه بر این ، پیامک را توسط هر برنامه ای در دستگاه کاربر که مجوز READ_SMS دارد ، می توان خواند.
FCM بسیار امن تر است و روش ترجیحی برای انتقال پیام به یک برنامه است زیرا همه ارتباطات FCM رمزگذاری شده است. آنها با استفاده از token های ثبت شده به طور منظم در سمت کلاینت و یک کلید API منحصر به فرد در سمت سرور احراز هویت می شوند.
6- از درخواست اطلاعات شخصی خودداری کنید
این روزها به حریم خصوصی کاربران اهمیت زیادی داده می شود. در واقع ، قوانینی مانند دستورالعمل حفاظت از داده های اتحادیه اروپا و قانون حفاظت از اطلاعات شخصی و اسناد الکترونیکی کانادا وجود دارد که حفاظت از حریم خصوصی یک کاربر را الزامی می کند. بنابراین ، مگر اینکه دلیل خوبی داشته باشید و زیرساخت بسیار مطمئنی برای جمع آوری ، ذخیره و انتقال اطلاعات شخصی کاربران دارید ، باید از درخواست مستقیم آن در برنامه های خود اجتناب کنید.
یک روش بهتر برای احراز هویت کاربر و جستجوی اطلاعات profile کاربر در اندروید ، استفاده از Google Identity Platform است. Google Identity Platform به کاربران امکان می دهد با استفاده از حساب Google خود به سرعت وارد برنامه شما شوند. پس از ورود موفق به سیستم از طریق پلت فرم ، هر زمان که لازم باشد ، برنامه شما می تواند به راحتی جزئیات مختلف در مورد کاربر ، مانند نام کاربر ، آدرس ایمیل ، تصویر profile ، مخاطبین و موارد دیگر را جستجو کند. از طرف دیگر ، می توانید از خدمات رایگان مانند Firebase استفاده کنید که می تواند احراز هویت کاربر را برای شما مدیریت کند.
اگر خودتان اعتبارنامه(credential ) کاربر را کنترل کنید ، توصیه می شود که آنها را در قالب هش های امن (secure hashes)ذخیره و منتقل کنید. ساده ترین راه برای ایجاد انواع مختلف hash با اندروید SDK ، استفاده از کلاس MessageDigest است.
این مثال نحوه ایجاد hash رشته Hello World با استفاده از تابع hash ، SHA-256 را نشان می دهد:
// Initialize MessageDigest to use SHA-256
MessageDigest md = MessageDigest.getInstance(“SHA-256”);
// Convert the string to a hash
byte[] sha256Hash = md.digest(“Hello World”.getBytes());
7– اعتبارسنجی ورود کاربر
در اندروید ، معمولاً ورود نامعتبر کاربر منجر به مشکلات امنیتی مانند سرریز(overrun) بافر نمی شود. با این حال ، اگر به کاربران اجازه می دهید با پایگاه داده SQLite یا content provider که به طور داخلی از پایگاه داده SQLite استفاده می کند ، تعامل داشته باشند ، یا باید ورود کاربر را به طور کامل اصلاح کنید یا از پرس و جوهای پارامتری استفاده کنید. عدم انجام این کار ، داده های شما را در برابر حملات تزریق SQL آسیب پذیر می کند.
8– استفاده از ProGuardقبل از انتشار
اگر مهاجمان (attackers) بتوانند سورس کد را در دست بگیرند ، اقدامات امنیتی ایجاد شده در یک برنامه اندروید می تواند به شدت به خطر بیفتد. قبل از انتشار برنامه خود ، توصیه می شود از ابزاری به نام ProGuard ، که در Android SDK موجود است ، استفاده کنید تا سورس کد را مبهم (obfuscate) و کوچک (minify) کنید.
اگر buildType جهت release، تنظیم(set) شده باشد، Android Studio به طور خودکار ProGuard را در فرایند ساخت قرار می دهد. پیکربندی پیش فرض ProGuard موجود در فایل SDK اندروید proguard-android.txt برای اکثر برنامه ها کافی است. اگر می خواهید قوانین سفارشی را به پیکربندی(configuration) اضافه کنید ، می توانید این کار را در داخل فایلی با نام proguard-rules.pro انجام دهید ، که بخشی از هر پروژه Android Studio است.
نتیجه
امیدوارم اکنون درک بهتری از نحوه ایمن سازی برنامه های اندروید داشته باشید. اکثر شیوه هایی که در این مقاله ذکر کردم فقط در صورتی قابل استفاده هستند که از Android SDK برای توسعه برنامه های خود استفاده می کنید. اگر به جای آن از Android NDK استفاده می کنید ، باید بسیار مراقب باشید زیرا هنگام برنامه نویسی به زبان C ، از شما انتظار می رود که جزئیات سطح پایین(low-level) ، مانند اشاره گرها و تخصیص حافظه(memory allocation) را خودتان مدیریت کنید.