رایتاپ ها
زمان مطالعه :7 دقیقه
شارژ کیف پول به صورت نامحدود تو یکی از سامانه های معروف ایرانی
درود ، عرفان توکلی هستم. تو این رایت آپ میخوایم به بررسی یه آسیب پذیری پرداخت داخل یه سامانه معروف ایرانی بپردازیم ولی چون اجازه پابلیش ندارم از سامانه اسمی نمیبرم ):
خب قبل شروع بهتره که یه flow کلی از فرایند شارژ کیف پول رو باهم مرور کنیم.
بریم سراغ آسیب پذیری. برای شارژ کردن کیف پولمون باید از اندپوینت پایین که داخل عکس هست استفاده کنیم که دوتا پارامتر از ما میگیره :
amount که میشه همون مقداری که میخوایم کیف پولمون شارژ بشه.
gatewayId که مشخص میکنه از چه بانکی برای پرداخت میخوایم استفاده کنیم.
در جواب بهمون یه JSON برمیگردونه که ما با paymentCode کار داریم. ( همچنین با هربار صدا زدن این اندپوینت یک orderId برای ما داخل دیتابیس ثبت میشه. توجه کنید که orderId به صورت incremental هست و هربار +1 بهش اضافه میشه. )
حالا برای ادامه فرایند شارژ حساب کاربریمون نیاز به یک توکن داریم که با صدا زدن اندپوینت زیر و ارسال paymentCode میتونیم یک توکن از سمت بانک دریافت کنیم.
بعد از انجام عملیات پرداخت یک درخواست callback به سمت تارگت ما ارسال میشه تا با استفاده از اطلاعات اون درخواست و چک کردن مقادیر مورد نظر مشخص بشه که آیا پرداخت ما صحیح بوده یا نه.
ی سری پارامتر تو این درخواست وجود داره که مهم تریناش :
token : همون توکنی که با استفاده از paymentCode به دست میاریم.
orderId : شماره سفارش ما که با هربار صدا زدن اندپوینت شارژ کیف پول +1 به مقدارش اضافه میشه.
status : وضعیت پرداخت ( 0 یا 1 ).
amount : مقداری که پرداخت کردیم تا حسابمون شارژ بشه.
تو این قسمت من سناریوهای مختلف double spending و race condition و خلاصه هرچی که به ذهنم میرسید رو تست کردم و جواب نگرفتم ، چون سمت بک اند اطلاعات به خوبی داشت ولیدیت میشد.
سناریو طلایی ؟
اومدم با خودم گفتم خب اوکی پس من میام یه درخواست دیگه برای شارژ کیف پولم با مبلغ خیلی بالاتر ارسال میکنم و یک orderId جدید برام داخل دیتابیس ثبت میشه و بعدش میام orderId جدید رو داخل درخواست جایگزین میکنم و با توکنی که پرداخت شده سعی میکنم سفارش جدیدمو تایید کنم.
توضیحات بیشتر :
به طور مثال من 1000 تومن کیف پولمو شارژ میکنم و یک orderId با مقدار 4004 برای من ثبت میشه ، همچنین یدونه paymentCode به من اختصاص داده میشه (مثلا S34YoCxZ) که با استفاده از اون میتونم یک توکن (yyyyzzzz) از سمت بانک دریافت کنم و عملیات پرداخت رو انجام بدم.
و در آخر در درخواست callback این token و orderId و پارامتر های دیگه سمت سرور ارسال میشن و ولیدیت میشن.
حالا ما میایم و جلوی ارسال درخواست callback به سمت سرور رو میگیریم.
1POST /api/v1/BankPayment/ParsianCallBack?gatewayId=36
2...
3Token=yyyyzzzz&OrderId=4004&RNN=746582135467&Status=0&TerminalNo=986543214&HashCardNumber=e6f9c347672daae5a2557ae118f44a1e&Amount=10%2C000&SwAmount=&STraceNo=9236457&DiscountedProduct=
پس ما یدونه توکن داریم که پرداخت شده و ولید هست (yyyyzzzz) و حالا میایم و دوباره درخواست شارژ کیف پول رو ارسال میکنیم ، ایندفعه با مبلغ 10 میلیون و orderId این درخواست رو برمیداریم (مثلا 4005) و با orderId درخواست callback قبلیمون جایگزین میکنیم و درخواست رو ارسال میکنیم.
1POST /api/v1/BankPayment/ParsianCallBack?gatewayId=36
2...
3Token=yyyyzzzz&OrderId=4005&RNN=746582135467&Status=0&TerminalNo=986543214&HashCardNumber=e6f9c347672daae5a2557ae118f44a1e&Amount=10%2C000&SwAmount=&STraceNo=9236457&DiscountedProduct=
انتظار داشتم این روش جواب بده ولی خب رفتم تو دیوار D:
با دید برنامه نویسی به این درخواست نگاه کردم و با خودم گفتم خب اگر همه این پارامتر ها سمت سرور ولیدیت میشه ، چی میشه اگر بیام و این پارامتر هارو حذف کنم ؟
با هزارتومن هزارتومن شارژ کردم کیف پولم اومدم و چک کردم ببینم چه پارامتر هایی نبودنشون تاثیری نداره.
خلاصه آخرش فهمیدم که میتونم همه پارامتر هارو پاک کنم به جز :
Token
Status
OrderId
RRN
با خودم گفتم ولش کن دیگ حال ندارم دوباره سناریو قبلی رو تست کنم ، احتمالا Token با OrderId سمت بک اند و بانک چک میشن و این سناریو جواب نمیده ولی یه مایندستی که دارم اینه ک هرچی تو ذهنت اومد تست کن شاید مسخره ترین ایده جواب بده و خب دوباره که این سناریو رو پیاده کردم دیدم عع... حسابم 10 میلیون شارژ شد (((:
خودم دقیق نمیدونم چه اتفاقی اون پشت افتاد ولی احتمالا سمت بک اند مقدار یکی از پارامتر ها جلوی عملی شدن سناریو منو میگرفت و با حذف کردنش سناریو من انجام شد.
امیدوارم از خوندنش لذت برده باشین و یه چیز جدید یاد گرفته باشین.
عرفان توکلی
مشاهده مقاله های بیشتر