مهندسی معکوس در اپلیکیشن‌های اندرویدی و راههای مقابله با آن

  • نویسنده: علی مهرآبادی
  • تاریخ انتشار: شنبه ، ۲۲ آذر ماه ۹۹
  • تعداد بازدید: 1513
  • تعداد نظرها: 0
  • دسته بندی: امنیت برنامه های موبایل

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

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

متاسفانه بسیاری از توسعه دهندگان اپلیکیشنهای موبایلی و صاحبان کسب و کار در این بخش، از اینکه چگونه ممکن است یک اپلیکیشن بعد از توسعه و منتشر شدن مورد سوء استفاده قرار گرفته و کد و اطلاعات آن بازیابی شود، هیچ ذهنیتی ندارند. این موضوع حتی در خصوص اپلیکیشن هایی نظیر اپ های حوزه بانکی و پرداخت که از منظر امنیت اطلاعات از حساسیت بالاتری برخوردار هستند هم دیده می شود. اگر شما نیز جزء آن دسته از توسعه دهندگانی هستید که فکر می کنند تمهیدات امنیتی ای نظیر هاردکد کردن (Hard Coding) اطلاعات حساس در فایل build.gradle، برنامه را از مهندسی معکوس محافظت می کند، باید بدانید که این تفکر صحیح نیست! بنابراین بهترین راهکار برای در امان ماندن از آسیب پذیری های سمت کاربر، آن است که شما یا یک تیم متخصص و معتبر تلاش کنید تا به انواع روشهای ممکن، متن برنامه را با استفاده از مهندسی معکوس استخراج کرده و آسیب پذیری های احتمالی را شناسایی و رفع کنید.

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

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

تحلیل ایستا و پویا

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

  • برگرداندن (Decompiling) کد منبع برنامه
  • یافتن پکیجهای مختلف استفاده شده درون برنامه
  • یافتن دایرکتوری های ذخیره اطلاعات در متن برنامه
  • تشخیص گردش کار و اطلاعات در برنامه و کشف منطق عملکردی آن

و پس از آن با مهندسی معکوس پویای برنامه (با روشهای زیر) رفتار اپلیکیشن در زمان اجرا مشخص شده و نهایتاً امکان تغییر در آن بررسی می شود:

  • پایش جریان داده ها
  • پایش لاگها
  • تحلیل ارتباطات شبکه
  • تغییر در رفتار برنامه

از بین موارد فوق، گام اول از تحلیل ایستا و گام آخر از تحلیل پویا، در این مقاله مورد بررسی قرار می گیرد.

مهندسی معکوس اپلیکیشنها در حالت استاتیک

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

مراحل کلی این کار در شکل زیر نشان داده شده است:

گام اول

ابتدا باید فایل نصبی اپلیکیشن آماده باشد. برای این کار دو روش می تواند مورد استفاده قرار گیرد:

  • دانلود فایل نصبی از مارکتهای مختلف یا درگاههای رسمی شرکت توسعه دهنده یا صاحب آن
  • استخراج APK از برنامه نصب شده. به این منظور با استفاده از ابزارهای استخراجگر (Extractor)، بخشهای مختلف فایل نصبی – از جمله فایل APK – قابل استخراج خواهد بود.

گام دوم

 با تغییر پسوند .apk در نام فایل به .zip و خارج کردن آن از شکل فشرده، به مجموعه ای از فایلها از جمله فایلی با نام classes.dex خواهیم رسید که در بر گیرنده متن کد برنامه است. حالا می توان با تبدیل این فایل به فایل jar (با استفاده از ابزارهایی مانند dex2jar)، آن را در محیطهای دیکامپایلر مشاهده نمود.

توجه داشته باشید که فایل dex یک فایل اجرایی است که بر روی پلتفرم اندروید اجرا می شود و شامل کد کامپایل شده است.

گام سوم

حالا به سادگی می توان در محیطی مانند JD JUI متن این فایل jar را مشاهده کرد. به این ترتیب با انجام چند مرحله ساده توسط مهاجم، تمامی دارائیهای اطلاعاتی شما در دست وی قرار خواهد داشت.

 

اگر امکان برگرداندن کد منبع یک اپلیکیشن وجود داشته باشد، به این معنی است که تمام داده ها، جزئیات ارتباطی اپلیکیشن بر روی شبکه، دارائیها و توابع استفاده شده و غیره در معرض دید و سوء استفاده مستقیم از سوی مهاجمان قرار دارد. این موضوع به ویژه برای اپلیکیشنهای صنعت بانکی و پرداخت که با تراکنشها و پایگاههای داده مالی ارتباط دارند، اهمیت فوق العاده ای دارد. بنابراین اولین آسیب پذیری – که به تعبیری مادر سایر آسیب پذیری ها در این حوزه شمرده می شود – عدم مبهم سازی (Obfuscation) کد منبع می باشد. لذا مهمترین گام در امن سازی اپلیکیشنهای موبایلی، پیاده سازی مکانیزمهای مبهم سازی بر روی کد منبع است.

مهندسی معکوس اپلیکیشنها در حالت دینامیک

مهاجمان ممکن است از ابزارهای تزریق کد برای تخریب کد و تغییر آن استفاده کنند. Frida یکی از این ابزارهای متداول است که مهاجمان جهت تزریق کدهای مخرب به برنامه از آن استفاده می کنند. همچنین با استفاده از این ابزار می توان داده های حساس مانند کلیدهای API درون برنامه را شناسایی نمود.

همان طور که می دانید، استفاده از حساب کاربری و کلمه عبور در بسیاری از اپلیکیشنهای اندرویدی متداول است. اما ممکن است با دسترسی به کد منبع برنامه، امکان و احتمال دور زدن (By Pass) کلمه عبور، افزایش یابد. بعنوان نمونه تصویر زیر که نتیجه دی کامپایل کردن یک اپلیکیشن اندرویدی است، نشان می  هد که از یک کلاس با عنوان PasswordValidator جهت تأیید کلمه عبور استفاده شده است. این کلاس برای نتیجه بررسی کلمه عبور سه حالت را پیش بینی کرده است: صحیح (SUCCEED)، نادرست (FAIL) و بازیابی (RESTORE).

با جستجو در متن برنامه برای یافتن سایر کلاسهایی که با PasswordValidator مرتبط هستند، به تابعی تحت عنوان onPasswordValidated خواهیم رسید. با تزریق یک کد جاوا، می توان جریان داده بین این کلاس و تابع را تغییر داده و منطق برنامه را به دلخواه تغییر داد؛ بگونه ای که امکان دور زدن کلمه عبور فراهم گردد.

یکی از روشهای معمول مورد استفاده جهت مکانیزمهای احراز هویت، محدود کردن فرمت پذیرش داده های ورودی است که سبب سخت و پیچیده شدن فرآیند دور زدن این مکانیزم می شود. در مثال حاضر فرمت قابل پذیرش داده ها،   Enum است که برای دور زدن این مکانیزم، لازم است توابع مناسب به کار گرفته شود. برای تبدیل String به Enum در جاوا، از متد valueOf() و .value استفاده می شود. به این ترتیب به شکل زیر می توان این آسیب پذیری را اکسپلویت کرد.

 

این بخش سبب می شود که در زمان فراخوانی تابع onPasswordValidated، بجای مقدار RESTORE، مقدار SUCCEES برگردانده شود.

به این ترتیب بدون دانستن کلمه عبور صاحب حساب (قربانی)، می توان با استفاده از قابلیت بازیابی کلمه عبور و تغییر پاسخ تابع onPasswordValidated، این مرحله را دور زد.

یکی دیگر از آسیب پذیری های متداول در اپلیکیشنهای موبایلی، امکان نصب آنها بر روی فریم ورک ها و محیطهای شبیه ساز و یا تجهیزات روت (root) شده است. این موضوع برای مهاجم امکان استفاده از ابزارهای دیگر جهت شناخت کاملتر فعالیتها و رفتار اپلیکیشن را فراهم می آورد؛ ابزارهایی که بر روی یک گوشی تلفن همراه معمولی، قابل استفاده نیست.

برای مطالعه بیشتر، در مقاله دیگری به باورهای غلط از سوی برنامه نویسان اپلیکیشن‌های موبایل در خصوص امن بودن پلتفرم های موبایلی پرداخته ایم. در مقاله مذکور اقدام به دستکاری کد (Tampering) و Repackaging یک اپلیکیشن در هر دو پلتفرم اندروید و iOS شده است.

چگونه می توان یک اپلیکیشن را از خطر مهندسی معکوس حفظ کرد؟

امن سازی اپلیکیشنهای موبایلی یک ضرورت اجتناب ناپذیر است که با توجه به ماهیت رو به تزاید استفاده از اپلیکیشنها و آسیب پذیری آنها، باید در دستور کار قرار گیرد.

مهندسی معکوس اولین گام هر مهاجم برای نفوذ به اپلیکیشن و تخریب آن است. نکته اینجاست که چگونه اپلیکیشن را در برابر مهندس معکوس محافظت نماییم؟ به این منظور روش های زیر پیشنهاد می شود:

  • از روشها و ابزارهای حرفه ای مبهم سازی استفاده کنید. به این منظور استفاده از DexGuard بعنوان محصول سطح اول جهانی پیشنهاد می شود.

  • از روشها و ابزارهای حرفه ای جهت تشخیص محیط اجرای برنامه و ممانعت از اجرای آن در محیطهای روت شده، استفاده کرده و در صورت تشخیص تغییر برنامه در زمان اجرا (Tampering)، عکس العمل مناسب را پیش بینی کنید.
  • از روشهای بررسی جامعیت اپلیکیشن در زمان اجرا (Integrity Checking) و جلوگیری از ایجاد تغییر در منطق اجرای برنامه استفاده شود.
  • اجازه اجرای برنامه در حالت debugable را ندهید تا امکان تغییر در متن کد فراهم نشود.
  • قسمتهای مهم کد را با استفاده از زبان برنامه نویسی دیگری (مانند C, C++ که برگرداندن آنها سخت تر است) نوشته و بعنوان یک کتابخانه فراخوانی کنید.

باید توجه داشت که ابزارهای مختلفی برای امن سازی اپلیکیشنهای موبایلی مورد استفاده قرار می گیرند که ممکن است برنامه را در برابر طیفی از آسیب پذیری ها امن کنند. از جمله این ابزارها، می توان به محصولات شرکت Guardsquare بعنوان یکی از معتبرترین شرکتهای فعال در این حوزه اشاره کرد که محصولات ProGuard, DexGuard, iXGuard را ارائه کرده است. ابزار Proguard که برای عموم برنامه نویسان برنامه های موبایلی شناخته شده است، محصول رایگان این شرکت است که در نسخه تجاری آن (DexGuard) قابلیتها و مکانیزمهای امن سازی بسیار زیادی به آن اضافه شده است. برای درک تفاوت این دو ابزار (که هر دو برای پلتفرم اندروید ارائه شده اند) و نحوه ارتقای ProGurad به DexGurad می توانید به وبلاگ آشنا ایمن مراجعه کنید.

در صورت علاقمندی به کسب اطلاعات بیشتر در مورد سایر آسیب پذیری های شناخته شده اپلیکیشنهای موبایلی، می توانید این مقاله را مطالعه و برای آشنایی بیشتر با چگونگی امن سازی آنها، شما را به مطالعه مقالات تخصصی وبلاگ آشنا ایمن دعوت می کنیم.