آیا رمز پویا امنیت کاربران بانک‌های ایرانی را حفظ خواهد کرد؟

توجه:‌ این مقاله صرفا جهت آموزش و ارتقا امنیت سایبری نوشته شده مسئولیت هرگونه سؤ استفاده با شخص سؤ استفاده کننده می‌باشد.

مقدمه

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

خب، اول از همه اینکه رمز پویا چیه؟ اصولا برای احراز هویت از سه‌تا مؤلفه می‌شه استفاده کرد.

۱- دانایی: چیزی که کاربر می‌دونه (مثل رمز، پین‌کد، pattern، سوال امنیتی)

۲- مالکیت: چیزی که کاربر داره (مثل تلفن همراه، لپ‌تاپ، سخت‌افزار رمزیاب)

۳- اصالت: چیزی که کاربر هست (مثل اثر انگشت، چهره، قرنیه، DNA، امضا و صدا)

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

حالا راه‌حل درست چیه؟

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

رمز یک‌بار مصرف مبتنی بر زمان (TOTP)

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

توکن‌های سخت‌افزاری
توکن‌های سخت‌افزاری

الگوریتم TOTP خیلی سادست اول زمان رو به بازه‌های منطقی‌بلند (مثلا یک دقیقه‌ای) تقسیم می‌کنه اینطوری کدی که تولید می‌شه یک دقیقه اعتبار داره. یعنی اینجوری:

Time = SystemTime/Period

بعد که زمان رو ساختیم حالا می‌تونیم اون رو کد کنیم برای این‌کار از HMAC استفاده می‌کنیم. خود HMAC رو خیلی توضیح نمی‌دم ولی ایده اینه که کلید رو به داده می‌چسپونید و Hash می‌کنین.

OTP = HMAC(Key, Time)

اینطوری یه پسوردی دارین که یک دقیقه اعتبار داره و می‌تونین برای احراز هویت از اون استفاده کنین.

بررسی امنیت اپلیکیشن رمزینه بانک سامان

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

نمونه QR Code بانک سامان
نمونه QR Code بانک سامان

خب اول از همه توی این عکس چه اطلاعاتی هست. اگر این عکس رو اسکن کنیم می‌بینیم که اینا توشه:

https://gist.github.com/0xC0D3D00D/f40ed843599e2b37afd3d2878daf0d0e

خب این JSON تو اولین نگاه دوتا فیلد جذاب داره یکی CIF و اون یکی Token. با یه جستجوی ساده می‌تونید به فهمید که CIF یه جورایی شماره مشتری شما پیش بانکه. Token به نظر میاد که کلید TOTP باشه ولی با یکم بالا پایین کردن و امتحان کردن الگوریتم‌های استاندارد TOTP متوجه شدم که اینطور نیست. ضمنا وقتی که شما کد رو اسکن می‌کنین باید شماره موبایلتون رو بدین تا یه کد دیگه هم براتون توی اپلیکیشن رمزینه بیاد.

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

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

https://gist.github.com/0xC0D3D00D/b30dde2eb2acc77b2bfd91562f1fb791

مشکل اینجاست که توکن توسط سرور به گوشی فرستاده شده و از اونجایی که گوشی من root نیست به طور مستقیم دسترسی به اطلاعات اپلیکیشن ندارم. با یه ذره سرچ فهمیدم که می‌تونم با adb از اپلیکیشن بک‌آپ بگیرم. پس اینکارو کردم:

$ adb backup -f saman.ab -noapk com.tosan.mobile.otpapp.saman

و اون رو استخراج کردم:

$ dd if=saman.ab bs=1 skip=24 | openssl zlib -d | tar -xvf -

اولین ضعف امنیتی اینجاست چون من قاعدتا نباید بتونم بک‌آپ بگیریم از این اپلیکیشن و خیلی ساده می‌شه این رو توی Manifest با android:allowBackup بست.

خب حالا من فایل SharedPreferences اپلیکیشن رو دارم که اینه:

https://gist.github.com/0xC0D3D00D/9e3729a6faa8de08ae57201702e40023

خب از اینا کدوماش بدرد بخوره. یکی CardOtpSecretKey هست که کلید TOTP واسه کارته، اون یکی ModernOtpSecretKey هست که کلید TOTP واسه اینترنت بانکه و آخری PIN_KEY هست که bcrypt شده رمز ورود به اپلیکیشنه. ضعف دوم امنیتی اینجاست که PIN_KEY داخل اپلیکیشن ذخیره می‌شه و این امن نیست.

حالا چرا؟ پیاده‌سازی که الان وجود داره اینطوریه که شما می‌ری اینترنت بانک و رمز یک‌بار مصرف رو می‌زنی و می‌ری داخل پس صرفا با مالکیت رمز دوم می‌تونی وارد حساب بانکی شخص بشی. ولی خبری از مولفه دانایی نیست یعنی من اگر صرفا به گوشی اون شخص دسترسی پیدا کنم می‌تونم از اپلیکیشن بک‌آپ بگیرم و پارامترهای کلید رو دربیارم. حالا شاید بگید که PIN_KEY با bcrypt کد شده ولی PIN_KEY فقط یک کد شش رقمیه و حداکثر با یک میلیون بار امتحان می‌شه bruteforceش کرد. درسته که bcrypt الگوریتم از قصد کندیه ولی با درجه سختی ۱۰ که اینجا ست شده. یک فرد عادی می‌تونه با لپ‌تاپش توی یک روز رمز رو بشکنه و اگر ۸ تا کارت گرافیک GTX TitanX داشته باشید شکستن این رمز فقط سه ثانیه طول می‌کشه :)

پس عملا این امکان پذیره که با دسترسی به گوشی قربانی و نهایت دونستن رمز یا pattern گوشی این اطلاعات رو ازش کشید بیرون.

پ.ن.: مشابه این Attack رو برای iPhone هم باید بشه ساخت حالا یه مقدار سخت‌تر.

پ.ن.۲: مسئله Man-in-the-Middle برای وقتی که توکن داره از سرور میاد هست. خیلی روی این موضوع کار نکردم ولی حسی که کدها بهم داد باید امکان انجام این نوع Attack هم باشه.

جمع بندی

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