پس از این که با OAuth و انواع روش های دریافت مجوز آن در فصل های قبل آشنا شدیم، حالا نوبت به این رسیده است تا کمی از نکات امنیتی حین پیاده سازی OAuth را با هم بررسی کنیم. در این فصل به بررسی چندین آسیب پذیری امنیتی مهم و معروف در پیاده سازی OAuth خواهیم پرداخت و اولین آسیب پذیری که در این مقاله معرفی میکنیم Session Hijacking میباشد.
در واقع Session Hijacking به حالتی گفته میشود که در آن هکر Session کاربر را به طریقی به دست میآورد و با استفاده از آن، توانایی انجام تمام کارهایی که کاربر مجوز انجامشان را دارد به دست میآورد. همانطور که در قسمتهای قبلی آموختیم برای به دست آوردن یک Access Token، Client باید از مرحله ای میانی عبور کرده و یک Authorization Code را به دست آورد. در این مرحله Authorization Server یک Authorization Code را تولید کرده و در پارامتر موجود در URL به صورت یک درخواست redirect (HTTP 302) به کلاینت تحویل میدهد. نمونهای از این درخواست در مثال زیر قابلمشاهده است.
GET /callback?code=SyWhvRM2&state=Lwt50DDQKUB8U7jtfLQCVGDL9cnmwHH1 HTTP/1.1
Host: localhost:9000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:39.0) Gecko/20100101 Firefox/39.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Referer:
http://localhost:9001/authorize?response_type=code&scope=foo&client_id=oauthclient-1&redirect_uri=http%3A%2F%2Flocalhost%3A9000%2Fcallback&state=Lwt50DDQ KUB8U7jtfLQCVGDL9cnmwHH1
Connection: keep-alive
مقدار Authorization Code در واقع یک credential یکبار مصرف است که نشان دهنده تصمیم Resource Owner درباره مجوزهای کاربر است. نکته موجود در این قسمت باقی ماندن Authorization Code در تاریخچه ی مرورگر کاربر است که نمونهای از آن در تصویر زیر قابلمشاهده است.
فرض کنید سناریویی داشته باشیم که در آن سایت A یک وب سرور دارد که از تعدادی Rest API به عنوان کلاینت OAuth استفاده میکند. یک Resource Owner در یک کتابخانه یا جایی دیگر، با استفاده از یک کامپیوتر اشتراکی به سایت A دسترسی پیدا میکند. سایت A از روند به دست آوردن Authorization Code استفاده میکند تا Token خود را به دست آورد. با توجه به این موضوع کاربر نیاز دارد تا در Authorization Server وارد شود (Login) و در نتیجه،Authorization Code در تاریخچه مرورگر همانند شکل بالا باقی خواهد ماند. پس از اتمام کار،Resource Owner احتمالاً از حساب کاربری خود و Authorization Server خارج میشود (Log Out) اما احتمالاً تاریخچه مرورگر خود را پاک نخواهد کرد.
حال فرض کنید که یک هکر بعد از کاربر در پشت این کامپیوتر بنشیند. اینجا هکر از مشخصات خودش برای ورود به سایت A استفاده میکند اما در مرحله میانی در محتوای درخواست redirect، به جای Authorization Code خودش از Authorization Code موجود در تاریخچه، استفاده خواهد کرد. در نتیجه هکر با استفاده از مشخصات کاربری خود به دسترسی هایی برابر با Resource Owner خواهد رسید. نمونهای از این فرآیند را در تصویر زیر می بینید.
راه حل این مشکل استفاده نکردن بیش از یکبار از هر Authorization Code است. اگر یک Authorization Code بیش از یک بار استفاده شود Authorization Server باید درخواست کلاینت را رد کرده و اعتبار همه ی توکن های قبلی که با استفاده از این Authorization Code دریافت شدهاند را ساقط کند. پیاده سازی صحیح این مورد برعهده کسی است که در حال پیاده سازی Authorization Server است. نمونهای از پیاده سازی این شیوه را در مثال زیر میتوانید مشاهده کنید.
if (req.body.grant_type == ‘authorization_code’) {
var code = codes[req.body.code];
if (code) {
delete codes[req.body.code];
راه حل دیگر برای رفع این آسیب پذیری، ایجاد وابستگی (Bind کردن) بین Authorization Code ها و client_id، به خصوص در کاربران احراز هویت شده است. قطعه کدی ساده برای پیاده سازی این راه حل را میتوانید در مثال زیر مشاهده کنید.
if (code.authorizationEndpointRequest.client_id == clientId) {...
بدون این بررسی ها، یک کلاینت میتواند با استفاده از Authorization Code یک کاربر دیگر، Access Token ای به دست آورد که دسترسی هایی غیرمجاز به او میدهد.