در قسمت قبل، در مورد روشهای مختلفی که وبسایتها میتوانند برای شناسایی کاربر بازدیدکننده استفاده کنند، صحبت کردیم. اما شناسایی، خودش فقط یک ادعا را ارائه می دهد. وقتی خودتان را شناسایی می کنید، ادعا می کنید که یک شخص هستید. اما هیچ مدرکی برای آن وجود ندارد. از سوی دیگر، احراز هویت نشان می دهد که شما همان چیزی هستید که ادعا می کنید هستید، مانند نشان دادن شناسه شخصی یا تایپ رمز عبورتان.
بیشتر اوقات، وب سایت ها به این مدرک نیاز دارند تا منابع حساس را به شما ارائه دهند.
HTTP مکانیسمهای احراز هویت خاص خود را دارد که به سرورها اجازه میدهد چالشها را ایجاد کنند و مدرک مورد نیاز خود را دریافت کنند. در این مقاله قرار است که درباره اینکه آنها چه هستند و چگونه کار می کنند آشنا شوید. ما همچنین میخواهیم مزایا و معایب هر یک را پوشش دهیم و بفهمیم که آیا واقعاً به اندازه کافی خوب هستند که به تنهایی از آنها استفاده کنیم.
این چهارمین قسمت از سری HTTP است.
در این مقاله با این موارد بیشتر آشنا خواهید شد:
قبل از اینکه به مکانیسمهای احراز هویت HTTP بپردازیم، اجازه دهید بررسی کنیم که احراز هویت HTTP چیست.
احراز هویت HTTP چطور کار میکند؟
احراز هویت راهی برای شناسایی خود شما در وب سرور است. شما باید مدرکی ارائه دهید که نشان دهد حق دسترسی به منابع درخواستی را دارید. معمولاً این کار با استفاده از ترکیبی از نام کاربری و رمز عبور (کلید و رمز) انجام می شود که سرور اعتبارسنجی می کند و سپس تصمیم می گیرد که آیا می توانید به منبع دسترسی داشته باشید یا خیر.
HTTP دو پروتکل احراز هویت را ارائه می دهد:
- احراز هویت Basic
- احراز هویت Digest
قبل از یادگیری بیشتر در مورد هر یک، اجازه دهید برخی از مفاهیم پایه را مرور کنیم.
چارچوب احراز هویت چالش/پاسخ
این به چه معناست؟
به این معنی است که وقتی شخصی درخواستی را ارسال می کند، سرور به جای پاسخ فوری به آن، یک چالش را ارسال می کند. این کاربر را به چالش می کشد تا با وارد کردن اطلاعات مخفی (نام کاربری و رمز عبور) مدرک هویت ارائه کند.
پس از آن، درخواست با استفاده از credential ها (شامل نام کاربری و رمز عبور) ارائه شده تکرار می شود و در صورت صحیح بودن، کاربر پاسخ مورد انتظار را دریافت می کند. در صورتی که credential اشتباه باشد، سرور می تواند چالش را مجدداً صادر کرده یا فقط پیام خطا را ارسال کند.
header های request/response مرتبط با احراز هویت
سرور با استفاده از WWW-Authenticate response headerچالش را صادر می کند. این header حاوی اطلاعاتی در مورد پروتکل و حوزه امنیتی است. پس از وارد کردن credential توسط کلاینت، درخواست دوباره ارسال می شود. این بار با هدر Authorization که حاوی الگوریتم و ترکیب نام کاربری/رمز عبور است انجام میشود.
اگر credential ها درست باشند، سرور پاسخ و اطلاعات اضافی را در یک Authentication-Info response header اختیاری برمی گرداند.
حوزه های امنیتی
حوزههای امنیتی راهی را برای مرتبط کردن حقوق دسترسی مختلف به گروههای منابع مختلف در سرور فراهم میکنند. اینها فضاهای حفاظتی نامیده می شوند.
چیزی که این به طور مؤثر معنا میدهد این است که بسته به منبعی که میخواهید به آن دسترسی داشته باشید، ممکن است نیاز باشد credential های مختلفی را وارد کنید.
سرور می تواند چندین حوزه داشته باشد. به عنوان مثال، یکی برای اطلاعات آماری وب سایت است که فقط مدیران وب سایت می توانند به آن دسترسی داشته باشند. یکی دیگر برای تصاویر وب سایت است که سایر کاربران می توانند به آنها دسترسی داشته باشند و تصاویر را در آنها آپلود کنند.
1 |
/admin/statistics/financials.txt -> Realm=”Admin Statistics” |
1 |
/images/img1.jpg -> Realm = “Images” |
وقتی سعی می کنید به financs.txt دسترسی پیدا کنید، سرور شما را به چالش می کشد و پاسخ از سرور به این شکل خواهد بود:
1 2 |
HTTP/1.0 401 Unauthorized WWW-Authenticate: Basic realm="Admin Statistics" |
اطلاعات بیشتر در مورد حوزه های امنیتی: https://tools.ietf.org/html/rfc7235#section-2.2
مثالی ساده از احراز هویت HTTP
حالا بیایید با نگاه کردن به سادهترین مثال احراز هویت HTTP، راهکارها را به طور عینی ببینیم (احراز هویت پایه، که در زیر توضیح داده شده است):
1. User Agent -> Server
کاربر درخواست دسترسی به تصویر روی سرور را دارد.
1 2 |
GET /gallery/personal/images/image1.jpg HTTP/1.1 Host: www.somedomain.com |
2. Server -> User Agent
سرور چالش را برای کاربر ارسال می کند.
1 2 |
HTTP/1.1 401 Access Denied WWW-Authenticate: Basic realm="gallery" |
3. User Agent -> Server
کاربر خود را از طریق ورودی فرم معرفی می کند.
1 2 |
GET /gallery/personal/images/image1.jpg HTTP/1.1 Authorization: Basic Zm9vOmJhcg== |
4. Server -> User Agent
سرور credential ها را بررسی می کند و کد وضعیت OK 200 و داده های تصویر را ارسال می کند.
1 2 3 |
HTTP/1.1 200 OK Content-type: image/jpeg ...<image data> |
آنقدرها هم پیچیده نیست، درسته؟
اکنون اجازه دهید وارد جزییات شده و نگاهی به احراز هویت Basic بیندازیم.
احراز هویت Basic
رایج ترین و پشتیبانی شده ترین پروتکل موجود میباشد. از زمان HTTP/1.0 وجود داشته است و هر کلاینت بزرگی آن را پیاده سازی می کند. مثال بالا نحوه احراز هویت با استفاده از احراز هویت Basic را نشان می دهد. پیاده سازی و استفاده از آن نسبتاً ساده است، اما دارای برخی نقص های امنیتی است.
قبل از رفتن به سراغ مسائل امنیتی، بیایید ببینیم احراز هویت Basic چگونه با نام کاربری و رمز عبور سروکار دارد.
احراز هویت Basic، نام کاربری و رمز عبور را در یک رشته قرار میدهد و با استفاده از دو نقطه (:) آنها را از هم جدا می کند. سپس آنها را با استفاده از رمزگذاری Base64 رمزگذاری می کند. علارغم چیزی که به نظر می رسد، قرار دادن ترتیب کاراکترها کنار هم امن نیست و می توانید به راحتی آن را رمزگشایی کنید.
هدف از رمزگذاری Base64 رمزگذاری نیست، بلکه سازگار کردن نام کاربری و رمز عبور HTTP است. دلیل اصلی آن این است که نمی توانید از کاراکترهای بین المللی در هدرهای HTTP استفاده کنید.
1 2 |
GET /gallery/personal/images/image1.jpg HTTP/1.1 Authorization: Basic Zm9vOmJhcg== |
“Zm9vOmJhcg==” از این مثال چیزی جز رشته “foo:bar” با کد رمزگذاری شده Base64 نیست.
بنابراین هر کسی که به درخواست ها گوش می دهد می تواند به راحتی credential ها را رمزگشایی و استفاده کند.
حتی بدتر از آن، رمزگذاری نام کاربری و رمز عبور کمکی نمی کند. یک third party مخرب همچنان می تواند ترتیب مورد نظر کارکترها را برای دستیابی به همان اثر ارسال کند.
همچنین هیچ حفاظتی در برابر پراکسی ها یا هر نوع حمله دیگری که بدنه درخواست را تغییر دهد و header های درخواست را دست نخورده باقی بگذارد وجود ندارد.
بنابراین، همانطور که می بینید، احراز هویت Basic کمتر از مکانیزم احراز هویت کامل است.
با این حال، با وجود آن، می توانید از آن برای جلوگیری از دسترسی تصادفی به منابع محافظت شده استفاده کنید و آن درجه ای از شخصی سازی را ارائه می دهد.
برای ایمن تر و قابل استفاده تر کردن آن، احراز هویت Basic را می توان با استفاده از HTTPS روی SSL که در قسمت 5 این سری صحبت می کنیم، پیاده سازی کرد.
برخی استدلال می کنند که این فقط به اندازه مکانیسم حمل و نقل شما ایمن است.
احراز هویت Digest
احراز هویت Digest جایگزین ایمن تر و قابل اعتمادتر برای احراز هویت ساده اما ناامن Basic است.
بنابراین، چگونه کار می کند؟
احراز هویت Digest از hash رمزنگاری MD5 در ترکیب با nonces استفاده می کند. به این ترتیب اطلاعات رمز عبور را برای جلوگیری از انواع مختلف حملات مخرب مخفی می کند.
این ممکن است کمی پیچیده به نظر برسد، اما زمانی که ببینید در یک مثال ساده چگونه کار می کند، واضح تر می شود.
مثال
1. User Agent -> Server
1 2 |
GET /dir/index.html HTTP/1.0 Host: localhost |
کلاینت یک درخواست احراز هویت نشده ارسال می کند.
2. Server -> User Agent
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
HTTP/1.0 401 Unauthorized WWW-Authenticate: Digest realm="shire@middleearth.com", qop="auth,auth-int", nonce="cmFuZG9tbHlnZW5lcmF0ZWRub25jZQ", opaque="c29tZXJhbmRvbW9wYXF1ZXN0cmluZw" Content-Type: text/html Content-Length: 153 <!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>Error</title> </head> <body> <h1>401 Unauthorized.</h1> </body> </html> |
سرور با استفاده از احراز هویت Digest، کلاینت را برای احراز هویت به چالش می کشد و اطلاعات مورد نیاز را برای کلاینت ارسال می کند.
3. User Agent -> Server
1 2 3 4 5 6 7 8 9 10 11 |
GET /dir/index.html HTTP/1.0 Host: localhost Authorization: Digest username="Gandalf", realm="shire@middleearth.com", nonce="cmFuZG9tbHlnZW5lcmF0ZWRub25jZQ", uri="/dir/index.html", qop=auth, nc=00000001, cnonce="0a4f113b", response="5a1c3bb349cf6986abf985257d968d86", opaque="c29tZXJhbmRvbW9wYXF1ZXN0cmluZw" |
کلاینت response value را محاسبه می کند و آن را همراه با نام کاربری، realm، URI، nonce، opaque، qop، nc و cnonce ارسال می کند. خیلی چیزها را ارسال میکند.
توضیح مفصل
اجازه دهید اینها را تعریف کنیم:
- nonce و opaque – سرور رشته هایی را تعریف کرده است که کلاینت پس از دریافت آنها، آنها را برمی گرداند.
- qop (کیفیت حفاظت) – یک یا چند مقدار از پیش تعریف شده (“auth” | “auth-int” | token). این مقادیر بر محاسبه digest تأثیر می گذارد.
- cnonce – در صورتی که qop تنظیم شده باشد، client nonce باید تولید شود. برای جلوگیری از حملات plaintext انتخاب شده و محافظت از یکپارچگی پیام استفاده می شود.
- nc – اگر qop تنظیم شده باشد، nonce count باید ارسال شود. این دستورالعمل به سرور اجازه میدهد تا با حفظ کپی خود از این count، درخواستهای تکراری را شناسایی کند – اگر همان مقدار nc دو بار ظاهر شود، آنگاه درخواست تکراری است.
ویژگی response به روش زیر محاسبه می شود:
1 2 3 4 5 6 7 8 9 10 11 |
HA1 = MD5("Gandalf:shire@middleearth.com:Lord Of The Rings") = 681028410e804a5b60f69e894701d4b4 HA2 = MD5("GET:/dir/index.html") = 39aff3a2bab6126f332b942af96d3366 Response = MD5( "681028410e804a5b60f69e894701d4b4: cmFuZG9tbHlnZW5lcmF0ZWRub25jZQ: 00000001:0a4f113b:auth: 39aff3a2bab6126f332b942af96d3366" ) = 5a1c3bb349cf6986abf985257d968d86 |
اگر علاقه مند به یادگیری نحوه محاسبه response بسته به qop هستید، می توانید آن را در RFC 2617 بیابید.
4. Server -> User Agent
1 2 3 4 |
HTTP/1.0 200 OK Content-Type: text/html Content-Length: 2345 ... <content data> |
سرور به تنهایی hash را محاسبه می کند و این دو را با هم مقایسه می کند. اگر مطابقت داشته باشند، با داده های درخواستی به کلاینت خدمت می کند.
خلاصه ای کوتاه
همانطور که می بینید احراز هویت Digest برای درک و پیاده سازی پیچیده تر است. همچنین نسبت به احراز هویت Basic ایمن تر است، اما همچنان در برابر حمله Man-in-the-Middle آسیب پذیر است. RFC 2617 توصیه می کند که از احراز هویت Digest به جای احراز هویت Basic استفاده شود زیرا برخی از نقاط ضعف آن را برطرف می کند. همچنین این واقعیت را پنهان نمی کند که احراز هویت Digest هنوز با استانداردهای رمزنگاری مدرن ضعیف است. قدرت آن تا حد زیادی به پیاده سازی بستگی دارد.
بنابراین به طور خلاصه احراز هویت Digest:
- رمزهای عبور متنی ساده را از طریق شبکه ارسال نمی کند
- از حملات تکراری جلوگیری می کند
- از دستکاری پیام محافظت می کند
برخی از نقاط ضعف:
- آسیب پذیری در برابر حمله man-in-the-middle
- بسیاری از گزینههای امنیتی مورد نیاز نیستند و بنابراین اگر تنظیم نشده باشند، احراز هویت Digest با امنیت کمتری صورت میگیرد
- از استفاده از الگوریتم های hash رمز عبور قوی هنگام ذخیره رمز عبور جلوگیری می کند
با توجه به این حقایق، احراز هویت Digest هنوز مورد توجه زیادی قرار نگرفته است. احراز هویت Basic بسیار سادهتر است و با SSL ترکیب میشود و همچنان امنتر از احراز هویت Digest است.
نتیجه گیری
این برای این قسمت از سری HTTP است.
ما مکانیسمهای احراز هویت مختلفی را که HTTP بهطور پیشفرض ارائه میدهد بررسی کردهایم و در مورد مزایا و معایب آنها صحبت کردهایم.
امیدواریم این مفاهیم دیگر فقط حروف روی صفحه نباشند و دفعه بعد که در مورد آنها شنیدید دقیقاً بدانید که چه هستند و چه زمانی باید آنها را اعمال کنید.
همچنین میدانید که خطرات امنیتی وجود دارد که با این مکانیسمهای احراز هویت حل نشده اند. به همین دلیل مفاهیمی مانند HTTPS و SSL/TLS وجود دارند. در قسمت بعدی این مجموعه بیشتر در مورد خطرات امنیتی و نحوه حل آنها صحبت می کنیم.
اگر برخی از مفاهیم این قسمت را نامفهوم دیدید، به قسمت 1، قسمت 2 و قسمت 3 سری HTTP مراجعه کنید.