DBSC در عمل: چیزهایی که اسپک بهت نمیگه
خلاصهٔ کاملتر
اسکات هلم تو Report URI قابلیت DBSC (مخفف Device Bound Session Credentials) رو راه انداخته، پیادهسازی سمت سرورش رو هم اپنسورس کرده و حالا فهرست چیزهایی رو نوشته که مستندات استاندارد برایشون آمادهت نمیکنه. ایدهٔ DBSC سادهست: کوکی نشست یه bearer token معمولیه و هر بدافزاری که از حافظهٔ مرورگر بخونتش عملاً میشه همون کاربر؛ پس مرورگر یه کلید خصوصی غیرقابلاستخراج تو سختافزار (TPM یا سکیور انکلیو) میسازه و نشست رو بهش گره میزنه.
اولین درس اینه که اسپک برعکس چیزیه که به نظر میاد: ثبتنام تکمرحلهایه (مرورگر یه JWT امضاشده POST میکنه و سرور با کوکی بایندشده جواب 200 میده)، ولی رفرش دومرحلهایه. مرورگر اول بدون چلنج درخواست میده، سرور با 403 و هدر Secure-Session-Challenge جواب میده، بعد مرورگر اون رو امضا میکنه و دور دوم 200 میگیره. نویسنده تأکید میکنه اون 403 مسیر سالم و روزمرهست، نه خطا.
بدترین باگشون بیصدا بود: وضعیت DBSC رو گذاشته بودن تو سشن PHP. بعد از لاگین، ناوبری کاربر و POST ثبتنام مرورگر همزمان روی یه سشن اجرا میشن و چون کل سشن بهصورت یه بلاب بازنویسی میشه، آخرین نویسنده برندهست و بایندینگ تازهساخته پاک میشه. گیت اجرا هم چون بایندینگی نمیبینه، بیسروصدا به احراز هویت کوکی معمولی برمیگرده — یعنی دقیقاً همون حفرهای که DBSC قرار بود ببنده. راهحل اینه که DBSC ذخیرهسازی مستقل خودش رو داشته باشه.
یه باگ دیگه فقط تو پروداکشن خودش رو نشون میده: مقدار کوکی سر هر رفرش میچرخه، ولی این چرخش از دید مرورگر آنی نیست. درخواستهایی که وسط رفتوبرگشت رفرش ارسال میشن کوکی قدیمی رو حمل میکنن و گیت اونها رو «کوکی دزدیدهشده» حساب میکرد و کاربر رو مینداخت بیرون. نرخ خرابی متناسب با تأخیر شبکهست، برای همین روی لوکالهاست تقریباً هیچوقت دیده نمیشه. راهحلشون پذیرش فقط یه نسل قبلتر کوکیه، اونم دقیقاً تا لحظهای که خود مرورگر هم دیگه اون مقدار رو نمیفرستاد.
بزرگترین تله اما ریدایرکت روی اندپوینت رفرشه: اگه گیت احراز هویت به درخواست رفرش جواب 302 به صفحهٔ لاگین بده، کروم ناوبری معلقشده رو هیچوقت آزاد نمیکنه و تب تا ابد خالی میمونه؛ با 401 اما نشست DBSC بسته میشه و کار جلو میره. درس آخر هم اینه که عدم تطابق چلنج حمله نیست — امضا قبل از چلنج بررسی میشه، پس هر درخواستی که به اون شاخه میرسه از قبل مالکیت کلید دستگاه رو ثابت کرده و جوابش باید یه 403 با چلنج تازه باشه، نه بستن نشست.
نکات کلیدی:
- ثبتنام DBSC تکمرحلهایه ولی رفرش دومرحلهایه و 403 تو مسیرش طبیعیه
- وضعیت DBSC نباید تو بلاب سشن ذخیره شه، وگرنه رقابت نوشتن بایندینگ رو پاک میکنه
- مقدار کوکی و چلنج باید سر هر رفرش بچرخه، وگرنه کروم نشست رو میبنده
- اندپوینت رفرش هیچوقت نباید ریدایرکت بده؛ جواب درست 401 ـه
- تو لاگینهای SSO درخواست ثبتنام cross-site حساب میشه و کوکی Lax باهاش نمیره، پس بهتره پیشنهاد ثبتنام به درخواست بعدی موکول شه
- بایندینگ خراب باید fail-closed باشه، نه اینکه بیصدا به کوکی معمولی برگرده




