بالا بردن امنیت درگاه پرداخت اینترنتی

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

Double-Spending یا به اصطلاح دو بار خرج کردن!

Double-Spending یکی از ساده ترین و پیش پا افتاده ترین راه (البته از نظر من) برای دور زدن روال پرداخت هست. توی این روش شخصی که قصد دور زدن سیستم پرداخت رو داره یک بار پرداخت رو انجام میده و بار بعدی سعی میکنه از اطلاعات پرداخت موفق قبلی استفاده کنه و پرداخت های ناموفق بعدیش رو موفق کنه! دقیقا چه اتفاقی میافته؟

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

از جمله این اطلاعات شناسه یکتای مربوط به هر PSP (شرکت ارائه دهنده پرداخت) هستش. البته این اطلاعات رو میتونه بدون ثبت ایمیل هم به دست بیاره!

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

بعد اینکار دکمه انصراف پرداخت رو فشار میده و چون JavaScript غیرفعال هستش تو همون صفحه میمونه ، بعد با استفاده از امکانات خود مرورگر به اسم Inspect Element سورس HTML صفحه رو دسکاری میکنه و اطلاعات پرداخت قبلی رو که توی ایمیلش داره (به جز شناسه پرداخت) جایگذاری میکنه و یه دکمه هم میذاره اونجا…

حالا تنها کاری که باید بکنه اینه که JavaScript مرورگر رو فعال میکنه و روی اون دکمه کلیک میکنه. خوب تو این حالت با اطلاعات پرداخت قبلی برمیگرده به سایت پذیرنده…

اینجا اگه سایت پذیرنده جلوی Double-Spending رو نگرفته باشه : بووووووووووم!!! ?

نکته!

یه نکته دیگه در این مورد اینه که ما فرض رو بر این گرفتیم که برنامه نویس شرط برابر بودن مبلغ تراکنش ثبت شده با مبلغی که PSP هنگام Verify برمیگردونه رو در نظر گرفته! اگه نه دیگه شرایط خیلی بحرانی میشه. چون هکر میتونه با یه پرداخت موفق 1000 ریالی ، پرداخت بعدی با مبلغ دلخواه خودش رو هم موفق کنه! 

خوب چجوری جلوی اینو بگیریم؟

خیلی ساده! موقعی که مشتری از صفحه پرداخت برمیگرده اطلاعات پرداخت رو در صورت موفق بودن ذخیره میکنیم توی دیتابیس… توجه کنیم که فیلد مربوط به شناسه یکتای PSP حتما باید unique باشه تا 2 بار این رکورد وارد دیتابیس نشه. به همین سادگی…

خوب شاید این سوال براتون پیش بیاد چرا موقع Verify تراکنش شرکت ارائه دهنده سرویس پرداخت چک نمیکنه که این تراکنش قبلا وریفای شده یا نه؟ البته برای خودمم اوایل سوال بود.

دلیلش اینه که موقع Verify تراکنش ممکنه اشکال شبکه ای رخ بده و درخواست شما به PSP برسه و تراکنش وریفای بشه ، اما پاسخش به دستتون نرسه. در این صورت شما دوباره وریفای رو انجام میدین. اینجا PSP همون پاسخ قبلی رو براتون میفرسته تا شما بتونید خدماتتون رو به مشتری ارائه بدید.

Same-Time-Request یا درخواست همزمان

خوب اول بگم که همچین اصطلاحی مرسوم نیست و من شخصا این اسم رو روش گذاشتم ???

فرض کنید هکر یه پرداخت موفق انجام میده ولی به سایت پذیرنده برنمیگرده (مثلا JavaScript مرورگرشو غیر فعال میکنه) بعد میاد با استفاده از یه ابزاری همین اطلاعات رو 2 بار و به صورت همزمان به آدرس بازگشتی شما ارسال میکنه.

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

خوب چه اتفاقی میافته؟ توی قسمتی از کدهاتون که شما چک میکنید موقع فراخوانی آدرس بازگشتیتون حتما تراکنش مورد نظر وریفای نشده باشه تا وریفایش کنید ، اگه 2 بار و به صورت همزمان اجرا بشه در هر دو حالت اون شرط True میشه!

حالا اگه یه سیستمی دارید که کاربراتون Balance دارن و بعد هر تراکنش شارژ میشه ممکنه Balance کاربر 2 بار شارژ بشه و در نهایت منجر به ضرر و زیان سیستم بشه!

راه حل

راه حال این مورد هم بسیار ساده هستش. فقط باید قبل از اینکه شرط “تراکنش قبلا وریفای نشده” رو چک کنید ، رکورد تراکنش رو توی جدول دیتابیس Lock کنید تا فقط یکی از Request ها بتونه ازش استفاده کنه.

بعد از اینکه بروزرسانی شد و اون رکورد جدول Unlock شد ، Request بعدی که میاد اطلاعات رکورد رو بخونه و کار وریفای رو انجام بده ، با نتیجه “پرداخت قبلا وریفای شده” مواجه میشه و مشکل رفع میشه ?

برای Lock کردن رکورد جدول چنتا لینک میذارم این زیر شاید به دردتون بخوره :

درباره نویسنده: سعید وزیری

سلام. من سعید وزیری هستم برنامه نویس شبکه پرداخت پِی

۵ دیدگاه

  1. ممنون بابت این مطلب. فقط در مورد دوم چه لزومی به اصطلاح lock کردن هست؟
    اگر فقط ۱ ثانیه وقفه در پذیرش ریکواست بدیم تا ریکوست دوم عمل پردازش روی اولی تموم شده.

  2. ممنونم بابت پست خوبتون

    یه سوالی که یه کم از موضوع پست شما دوره،
    من فک میکردم بانک با یک شماره خرید فقط یک بار اجازه پرداخت موفق میده، اما بعداً دیدم بانک محدودیتی روی پرداخت با یک شماره خرید از یک پذیرنده نداره…!
    این درسته؟ ینی بانک اگر با یه شمار خرید از یک پذیرنده هزار بار هم سمتش بریم مشکلی نداره و خطا نمیده؟

نظرات بسته شده است.