نگاره‌هایی پیرامون امنیت، شبکه و رمزنگاری

11 مه 2020

در ادامه پست بررسی ضعف‌های امنیتی در DNS، توی این پست میخواهیم به ساختار حملات DNS Cache Poisoning نگاه کنیم. این‌که چطور مهاجمین می‌تونن از ساختار آسیب‌پذیر ‌DNS استفاده کنن و ترافیک یک شبکه رو به میل خودشون هدایت کنن.

حملات Cache Poisoning به علت فراوانی DNS Server های آسیب‌پذیر و راحتی اجرای حمله، بسیار رایج هست. این حمله میتونه اهداف مختلفی مثل از دسترس خارج کردن سرویس و یا دزدی اطلاعات داشته باشه.


بررسی یک درخواست ساده DNS

یک درخواست DNS وقتی شروع میشه که یه شخصی میخواد با یک سرویس روی یک نام‌دامنه ارتباط برقرار کنه. همون طور که در پست سازوکار پروتکل DNS خوندیم، وقتی یک سرور DNS میخواد اطلاعات مربوط به www.google.com رو بگیره، سه سطح وجود داره:

  • (.) – Root
  • (.com) – TLD
  • (.google) – Authoritative

برای مثال client یک بسته درخواستی برای www.example.com به سرور DNS می‌فرسته. با فرض براینکه اون سرور Recursive این مقدار رو توی Cache نداره، شروع میکنه به پرسش و پاسخ برای ترجمه این نام دامنه. در ابتدا به یک سرور Root درخواست میده که کجا میتونم www.example.com رو پیدا کنم؟ سرور Root هم یه ارجاع میده به سرور .com ، بعد سرور Recursive باز همین درخواست رو به سرور .com میفرسته. سرور .com هم یک بسته حاوی اطلاعات سرور Authoritative مسئول example.com رو برای سرور Recursive میفرسته. تو این مرحله سرور Recursive باز همین درخواست رو به سرور معتبر (Authoritative) میفرسته و در اغلب موارد در اینجا اطلاعات مربوط به www.example.com رو میگیره و تو Cache خودش ذخیره میکنه و برای client ارسال میکنه.

این تمام مراحل پرس و پاسخ DNS بود کاملا ساده و بدون هیچ سازوکار امنیتی. به محض این که DNS پاسخ رو دریافت کنه اون رو برای کاربر می‌فرسته و به کار خودش ادامه میده. این نوع سازوکار بسیار آسیب پذیر به حملات مرد میانی (Man-in-the-middle) هست چون هیچ چیز تضمین کننده این نیست که پاسخ صحیح و معتبر هست.


حملات Cache Poisoning

منظور از Cache Poisoning یعنی آلوده کردن پایگاه‌داده موقت DNS در سرور Recursive. اگه مهاجم به هر نحوی بتونه مقدار نادرستی برای نام‌دامنه‌ای رو به Cache تزریق کنه، میتونه تمام کاربرانی که از اون سرور Recursive استفاده می‌کنن و میخوان با اون نام‌دامنه ارتباط بر قرار کنن رو به سمت دیگه‌ای بفرسته (البته تا پایان مقدار TTL).

فرض کنید که سرور Recursive، درخواستی رو به سرور Authoritative بفرسته و قبل از سرور Authoritative، مهاجم به این درخواست پاسخ بده (که از لحاظ عملی کاملا شدنی هست). در این مرحله Cache آلوده میشه (Cache Poisoning) و باعث میشه تمام کاربران برای یک مدت (TTL) یک پاسخ نا معتبر بگیرن که هیچ سازوکاری وجود نداره که اون رو تشخیص بدن.

Cache Poisoning به سادگی این نیست که تعدادی بسته پاسخ به سرور بفرستیم چون سرور فقط بسته‌هایی رو قبول میکنه که منتظر اون ها بوده.

سرور DNS در لحظه مشغول به بررسی چندین درخواست هست، پس از کجا متوجه میشه این پاسخ برای کدوم درخواست هستش؟

  • پاسخ به همون پورتی (Port) فرستاده بشه که درخواست از همون فرستاده شده.
  • قسمت Question در بسته DNS پاسخ، با مقدار اون در بسته درخواست برابر باشه.
  • اگه یادتون باشه در پست سازوکار پروتکل DNS اشاره کردیم که در هدر (Header) بسته یک مقدار 16 بیتی به نام ID وجود داره. این ID در هدر کمک میکنه که سرور تشخیص بده کدوم پاسخ برای کدوم درخواست بوده.
  • همچنین سرور بررسی میکنه که مقادیری که در پاسخ هستن با مقادیر درخواست مطابقت داشته باشه. مثلا درخواست google.com نمیتونه پاسخی برای bank.com برگردونه.

اگه تمام این شرایط برقرار بود این پاسخ قبول میشه و در Cache ذخیره میشه و همچنین بسته‌های بعدی دیگه مورد بررسی قرار نمی‌گیره (یعنی اولین بسته واجد شرایط قبول میشه).

پس اولین چالش برای اینکه این اتفاق عملی بشه این هست که مهاجم باید قبل از پاسخ سرور اصلی پاسخ خودش رو بفرسته.

دومین چالش شماره Port مبدا و مقدار ID در هدر بسته هست. همون‌طوری که اشاره کردم سرور بررسی میکنه که آیا این دو مقدار با مقادیری که در بسته درخواست بودن یکسان هست یا نه. Port مبدا یک مقدار ثابت هست و مهاجم میتونه اون رو به سادگی بدست بیاره (جلو تر توضیح میدم)، پس میمونه حدس زدن مقدار ID.

* حدس زدن مقدار ID

در گذشته سرورها مقدار ID رو به سادگی در هر درخواست به مقدار یک اضافه میکردن؛ یعنی ID ترتیب داشت پس اگه مهاجم بتونه یک بسته اخیر از DNS رو ببینه میتونه بعدی رو به راحتی حدس بزنه. ولی مشکل این‌جاست که نمیشه از سرور درخواست کنیم که ID رو برامون بفرسته. البته مشکلی هم نیست روش دیگه‌ای برای این کار وجود داره:

  1. مهاجم برای سرور Recursive یک بسته درخواستی میفرسته. بسته‌ای که در اون درخواست ترجمه نام دامنه‌ای رو کرده که برای خودش هست (مثلا test.badguy.com)
  2. سرور Recursive به روال عادی خودش شروع میکنه به پرسش و پاسخ تا به سرور Authoritative دامنه badguy.com برسه. و بعد یک بسته درخواستی برای test.badguy.com میفرسته و … .
  3. در همین مرحله ایده عملی شد ادامه مرحله قبل اهمیتی نداره، مهاجم میره سراغ سرور Authoritative دامنه خودش و بسته‌هایی رو که رد و بدل شده رو برای test.badguy.com جستجو میکنه و مقدار ID و Port مبدا بسته رو می‌بینه.

البته تمام این مراحل توسط نرم افزار انجام میشه چون این حمله نیازمند سرعت بالایی هست.

* شروع حمله

بعد از به دست اووردن Port مبدا (که ثابت هست) و آخرین مقدار ID، مهاجم بدون درنگ شروع میکنه به پیاده سازی حمله.

  1. در مرحله اول مهاجم درخواستی رو برای ترجمه نام‌دامنه‌ای که هدف قرار داده (در این مثال www.bankofsteve.com) رو برای سرور Recursive می‌فرسته (در ابتدا مهاجم اطمینان حاصل میکنه که نام‌دامنه مورد نظر در Cache سرور وجود نداره. این کار به‌سادگی با بررسی مقدار TTL اون دامنه انجام میشه).
  2. در این مرحله سرور شروع میکنه به انجام روتین‌ها برای بدست آوردن پاسخ؛ یعنی با سرور Root و TLD ارتباط برقرار میکنه تا آدرس سرور Authoritative مربوط به bankofsteve.com رو دریافت کنه. در همین زمان مهاجم شروع میکنه به فرستادن سیلی از پاسخ‌های مرتبط با اون درخواست به سرور Recursive. مهاجم مقدار آخر ID رو داره و یک باز‌‌ه‌ای از مقادیر ممکن تشکلی میده مثلا از LastID+3 تا LastID+15 (مقدار ID، دو بار در ارتباط با سرورهای Root و TLD افزایش پیدا کرده پس حداقل مقدار ID+3 هست).
  3. همون‌طوری که در تصویر زیر می‌بینید، مهاجم تونسته سریع‌تر پاسخ خودش رو با تمام پارامترهای درست بفرسته. و در این‌جا نفر اول برنده‌ست.

توجه داشته باشید که تمام پاسخ‌هایی که با ID اشتباه فرستاده شدن Drop میشن و درنظر گرفته نمیشن، پس اهمیتی ندارن. و باز هم تاکید میکنم بعد از اول پاسخ، پرونده درخواست بسته میشه و پاسخ معتبر که از سرور میاد نادیده گرفته میشه.

* جلوگیری از حمله

پیشگیری در این برهه از تاریخ خیلی ساده صورت گرفت. مهندسین سیاست افزایش ID منظم رو به ID اتفاقی (Random) تغییر دادن. حالا مهاجم لازمه قبل از از اینکه سرور معتبر پاسخ معتبر رو به سرور Recursive بفرسته یک مقدار 16 بیتی رو حدس بزنه؛ یعنی 65535 مقدار مختلف.

هر چند مهاجم لازم نیست 65535 تا بسته با ID مختلف ارسال کنه، در پارادوکس روز تولد اثبات میشه که مهاجم میتونه با استفاده از حمله روز تولد، با ارسال 700 بسته مقدار درست رو با احتمال نزدیک به 100% بفرسته و در نتیجه Cache Poisoning اتفاق بیوفته.

این نکته رو هم باید در نظر داشت که اگه مهاجم نتونه زودتر از سرور معتبر پاسخ رو ارسال کنه مجبوره تا پایان TTL منتظر بمونه و دوباره تلاش کنه که این چالش، این حمله رو سخت‌تر کرده (ولی نه نا ممکن).


آسیب پذیری CVE-2008-1447

در قسمت قبلی دیدیم که چطور یک مهاجم میتونه DNS Poisoning رو انجام بده و دیدیم که چطور با استفاده از مقدار ID اتفاقی جلوی حمله تا حدی گرفته شد.

در کنفرانس تابستانه Black Hat 2008، یک محقق امنیتی به نام Dan Kaminsky یک آسیب‌پذیری جدی در پروتکل ‌DNS رو ارائه کرد که حملات DNS Poisoning رو به طرز چشم‌گیری موثرتر از حملات مرسوم کرد. این آسیب‌پذیری یکی از بزرگترین‌ها در تاریخ اینترنت بوده و شوک بزرگی رو به جامعه امنیتی وارد کرد.

سازوکار آسیب پذیری مثل همون چیزی هست که بالاتر باهم بررسی کردیم ولی از لحاظ اجرایی کمی تفاوت داره.

در این مثال قراره ببینیم که چطوری میشه با استفاده از این آسیب‌پذیری نه تنها یک دامنه بلکه سرور Authoritative اون دامنه رو به دست گرفت. این به این معنی هست که هرچیزی که مربوط به اون دامنه میشه مثل mail server ها هم در دست مهاجم قرار می‌گیره.

* آماده شدن برای شروع حمله

در ابتدا مهاجم یک سرور Authoritative برای دامنه‌ای که مورد هدف قرار داده، می‌سازه. چیزی نمیتونه جلوی کسی رو بگیره که یک سرور Authoritative برای هر دامنه‌ای که خواست بسازه.

در واقع سروری که می‌سازید جواب‌ها رو داره ولی هیچ وقت سرور بالاتر (Parent) به اون اشاره نمی‌کنه و در نتیجه نمیتونه کاری انجام بده. مهاجم فقط این سرور رو آماده می‌کنه تا وقتی حمله انجام شد بتونه از اون استفاده کنه.

* شروع حمله

در اینجا هم مثال رو برای دامنه bankofsteve.com در نظر می‌گیریم:

  1. مهاجم یک درخواست برای زیردامنه‌ای ارسال می‌کنه که اطمینان داره وجود نداره. مثلا www12345678.bankofsteve.com.
  2. در این مرحله مهاجم شروع می‌کنه به فرستادن بسته‌های مختلف با مقدار ID متغیر (با استفاده از حمله روز تولد). ولی این‌بار به جای برگردونن پاسخ با یک رکود A به سرور Recursive میگه: “من این آدرس رو ندارم ولی میتونی از این آدرس بپرسی”. برای این‌کار مهاجم در فیلد Additional بسته، یک آدرس Nameserver که به IP سرور از پیش ساخته شده خودش اشاره میکنه قرار میده.

اگه در مرحله دوم مهاجم بتونه پاسخ همراه ID درست رو قبل از سرور Authoritative ارسال کنه میتونه Cache رو این‌بار با ‌آدرس جعلی سرور Authoritative خودش پر کنه و این به معنی تصاحب کل Zone هست!!! این حلمه واقعا ویران کننده‌ست.

چیزی که در این‌جا مقداری شک درش هست سرعت لازم برای فرستادن حدود 700 بسته برای عملی شدن حمله روز تولد هست. که این در واقعیت کمی سخته. روندی که در بالا باهم دیدیم فقط یک رشته از این حمله بود. این حمله برای عملیاتی شدن نیاز داره که حداقل 50 رشته از عملیات بالا رو بصورت هم‌زمان انجام بده. هر کدوم از این رشته‌های موازی، با یک زیردامنه‌ای که وجود نداره کار خودشون رو انجام میدن. این چند رشته بودن حمله باعث میشه احتمال عملی شدن حمله به مراتب بالاتر بره. در گزارش‌ها زمان مورد نیاز برای انجام این حمله 10 ثانیه ثبت شده!!

* فرا تر

اگه یک‌بار دیگه به سازوکار این حمله نگاه کنیم به این نتیجه می‌رسیم که خب این حمله چرا باید روی Authoritative ها انجام بشه؟ چرا ما تمام Zone مربوط به یک TLD رو تصاحب نکنیم؟. باید بگم این امر کاملا عملی هست هرچند مهاجم باید توان مدیریت ترافیک یک TLD رو داشته باشه!

* پیشگیری

در این وهله از تاریخ مهندسین باز با یک روش سریع و تغریبا موقت جلو این حمله رو گرفتن.

ایده این بود که مقدار 65535 به عنوان ID، بسیار برای حدس زدن ساده‌ست. از طرفی نمیشه این مقدار رو بیشتر کرد چون ساختار بسته DNS خراب میشه پس کاری که کردن این بود سیاسیت پروتکل مبنی بر استفاده از یک Port یکسان در پرسش‌و‌پاسخ رو عوض کردن و عدد Port رو بصورت اتفاقی (Random) در نظر گرفتن. که این باعث شده مجموع حالت ها به 134 میلیون افزایش پیدا کنه.

منبع: http://unixwiz.net/techtips/iguide-kaminsky-dns-vuln.html


حملات DNS Cache Poisoning باعث شد مهندسین به فکر راه‌های تضمینی باشن. این‌شد که پروتکل DNSSec شکل گرفت. در آینده این پروتکل رو بررسی می‌کنیم.

علی اصغر جوزی
7 پست نوشته شده
من نه کارشناس امنیت هستم و نه محقق، من حتی یک برنامه‌نویس واقعی هم نیستم. هیچ کدوم از این عنوان‌ها برای من نیست. من فقط علاقه‌مندم به هرچیزی که پشتش یک سازوکار جالب باشه مهم نیس چی باشه من دوست دارم دربارش بخونم.
مطالبی که می نویسم صرفا خلاصه مطالعه RFC ها و کتاب‌های معروفه که همتون می‌شناسید. و هیچ کدوم از این ها کشفیات خودم نبوده و نیست. خوشحال میشم نقد کنید و اگه موردی از نظرتون درست نبود بهم بگید.

راه ارتباطی با من معمولا aggr3ssor@protonmail.com هست و در توییتر با 0xc0d میتونید منو پیدا کنید.
دسته‌ها: امنیت شبکه
  • به اشتراک بگذارید:
  1. Avatar محسن گفت:

    عالی بود

  2. Avatar محمد گفت:

    سپاسگزارم. خیلی روان و مفید بود

  3. Avatar علی گفت:

    بسیار عالی
    ولی یک سناریو واقعی
    فرض می گیریم یه نفوذگر DNS ما رو تحت کنترل گرفته یا ترافیک ما رو به سمت DNS خودش هدایت کرده
    ۱.چطور می تونه مثلا به جای http://www.facebook.com ما رو به دامنه ای که خودش رو سرور خودش هوست کرده هدایت کنه چون عملا دامین http://www.facebook.com رجیستر شده پس آدرس وبسایت قلابی نمی تونه http://www.facebook.com باشه در نتیجه ترافیک یوزر یا به صفحه اصلی فیسبوک هدایت نمیشه یا به یه دامینی مثل http://www.facebbook.com هدایتش می کنه که یوزر کمی آگاه متوجه تفاوتش میشه
    ۲.آیا اگر نفوذگر تنظیمات DNS رو برای http://www.facebook.com همین آدرس و نه مشابه http://www.faceebook.com تنظیم کنه و IP مطلوب خودش رو بده در مرورگر قربانی http://www.facebook.com باز میشه؟

    • علی اصغر جوزی علی اصغر جوزی گفت:

      وقتی شما دامنه‌ای رو ثبت میکنید شما صاحب دامنه هستید و میتونید تعیین کنید که دامنه‌تون به کجا اشاره کنه. آدرس IP دامنه میتونه تغییر کنه در تنظیمات DNS سرور شما. وب‌سایتی ممکن هست هر روز IP خودش رو تغییر بده منظور از ثبت شدن دامنه این هست که این دامنه صاحب حقیقی یا حقوقی داره و به این معنی نیست که روی یک IP صرفا ثابت، ثبت شده.
      در حملات DNS Cache Poisoning مهاجم سعی میکنه به‌جای شما پاسخ‌گوی یک پرسش مرتبط با نام دامنه شما باشه! این حمله اگر انجام بشه در endpoint های که از DNS سرور آلوده استفاده میکنن، آدرس facebook به IP مورد نظر شما هدایت میشه.
      پیشنهاد میکنم سری مطالب مربوط به DNS رو مطالعه کنید.
      سناریویی که شما فرمودید جز این حملات محسوب نمیشه.