מהי מתקפת DNS Rebinding
מה אם הייתי מספר לכם שכל אתר שאתם גולשים אליו יכול להריץ קוד אצלכם על המחשב ואף לגשת דרך המחשב שלכם לכל המכשירים ברשת הפנימית? מתקפה בשם DNS Rebinding מנצלת אוסף של מקרי קצה מוזרים כדי להפוך את הסיוט הזה למציאות. מסתבר שזה יותר פשוט ממה שאתם מדמיינים ובצד החיובי גם ההתגוננות לא מסובכת.
1. הנחת העבודה המוטעית שלנו
נניח שאתם גולשים בבית ברשת ה WiFi המאובטחת שלכם. האם תשימו סיסמא גם על ממשק הניהול של ה Router? וגם על דיסק האיחסון החיצוני? או הרמקול החכם? אז גישה אחת אומרת שאם יש סיסמא על הרשת אין טעם לשים סיסמא לכל התקן בנפרד. סיסמת הרשת מספיקה. ממילא אנחנו ניתן רק לחברים להיכנס לרשת.
והגישה הזאת היא בדיוק הדלק של משאית ה DNS Rebinding. אבל אנחנו רצים קדימה. בואו ניקח את אחד המחשבים ברשת הביתית שלכם ונפעיל עליו דפדפן ונגלוש לאתר לא סימפטי. אתם יודעים, מהאתרים שאתם מגיעים אליהם כשאתם לוחצים על קליק-בייט בפייסבוק.
באופן רגיל אתרים שאנחנו מבקרים בהם יכולים להריץ קוד JavaScript שתחום לאותו אתר בלבד. קוד ה JavaScript הזה יכול לגרום לדברים לקפוץ על המסך, אבל כשתסגרו את הטאב הכל יעלם.
הדרך של דפדפנים לחסום פעילות באתר אחד שעשויה להשפיע על אתר אחר נקראת Same Origin Policy. קוד JavaScript שרץ על אתר מסוים מוגבל לבצע פעולות רק באותו הדומיין של האתר ממנו הקוד נטען. כך כשאתם גולשים כאן בטוקוד קוד ה JavaScript של טוקוד ירוץ אצלכם בדפדפן, אבל יוכל לבצע פעולות רק בתוך אתר ToCode עצמו.
2. איך עוקפים Same Origin Policy
וכאן אנחנו מגיעים למתקפה- היינו רוצים להריץ אצל הגולשים שלנו קוד JavaScript שלמשל יפנה לנתב הביתי ברשת הפנימית שלהם וישנה את הסיסמא; או שיפעיל את המצלמה החכמה, ינגן שיר ברמקול החכם או יזמין אוכל מהמקרר החכם. כל ההתקנים האלה פעילים ברשת הפנימית וכולם חושפים ממשק ניהול שאפשר לגשת אליו מתוך דפדפן.
אם נניח שה Router שלנו יושב ברשת הפנימית בכתובת 192.168.0.1 ושאפשר לשנות את סיסמת הניהול שלו באמצעות בקשת POST לנתיב password הייתי שמח להריץ את קוד ה JavaScript הבא על מחשבי הגולשים:
$.post('http://192.168.0.1/password', { newPassword: 'ninja' });
הבעיה שיצרן ה Router שמע על מתקפות CSRF ויודע להתגונן מהן, ולכן לא מספיק לשלוח את הסיסמא החדשה אלא יש צורך לשלוח בטופס גם את ה CSRF Token שמיוצר ספציפית עבור ה Session הנוכחי. לכן הקוד האמיתי שנרצה להריץ יראה בערך כך:
const form = await $.get('http://192.168.0.1/password');
const token = $(form).find('input[name="authenticity_token"]).value;
$.post('http://192.168.0.1/password', { newPassword: 'ninja', authenticityToken: token });
אבל קוד כזה לא יכול לעבוד בגלל Same Origin Policy- הדפדפן מזהה שהגישה ל 192.168.0.1
יוצאת מתחום האתר שאתם עכשיו גולשים בו ולכן יחסום את קריאת התשובה מאתר זה. זאת בדיוק הסיבה שאנחנו משתמשים ב CSRF Tokens.
מתקפת DNS Rebinding אומרת שאני יכול לשנות את שרת ה DNS שלי כך שבמקום לענות את אותה כתובת IP לכל בקשה של לקוח אני אשלח ללקוח תשובה אחרת בכל פניה, ולכל תשובה שאני שולח יהיה TTL קצר ממש.
בצורה כזאת לקוח מגיע לדף הראשי באתר evilsite.com
ושם הוא מקבל קובץ HTML עם קוד JavaScript שנראה כך:
const form = await $.get('http://evilsite.com/password');
const token = $(form).find('input[name="authenticity_token"]).value;
$.post('http://evilsite.com/password', { newPassword: 'ninja', authenticityToken: token });
בגלל שה TTL של תשובת ה DNS היה ממש קצר, כשהדפדפן צריך להריץ את קוד ה JavaScript הזה הוא יצטרך לתשאל את שרת ה DNS פעם שניה מה כתובת ה IP של evilsite.com. הפעם אותו שרת DNS ישלח את הכתובת 192.168.0.1
. הדפדפן ימשיך ויפנה לנתב ברשת הפנימית וכך האתר evilsite.com
גרם לכם לפרוץ לעצמכם את הראוטר.
3. איך מתגוננים?
ההגנה ממתקפת DNS Rebinding היא מאוד פשוטה והיא מתבססת על ההתנהגות של דפדפנים בבקשות Ajax. מסתבר שכל דפדפן שולח HTTP Header בשם Host ושם הוא כותב את שם הדומיין אליו הוא מנסה לגשת. אם ה Router שלכם מקבל בקשת HTTP עם ערך Host שהוא לא מכיר עליו לזרוק את הבקשה. וכך גם כל רכיב אחר ברשת הפנימית שלכם.
אם יש לכם Firewall על המחשב אפשר להגדיר שיחסום כל תשובת DNS שכתובת ה IP שלה היא מהרשת הפנימית.
ואם אתם מפעילים שרת DNS בעצמכם תוכלו לפלטר כל תשובת DNS שתקבלו משרת אחר שכוללת התיחסות לכתובת ברשת פנימית.
4. מתקפות DNS Rebinding בעולם האמיתי
בחודש מרץ 2018 התגלתה חולשה במנגנון ה Remote Debugging של Node.JS שהיה פגיע למתקפות DNS Rebinding. גולש שהפעיל את נוד במצב דיבג ובאותו זמן לחץ על קישור מפוקפק בפייסבוק היה עלול לגרום לאתר זדוני לתקוף את אותו Node Instance כדי להפעיל קוד זדוני אצלו על המחשב. פרטים מלאים בקישור כאן:
https://nodejs.org/en/blog/vulnerability/march-2018-security-releases/
חודשיים קודם לכן בינואר דווח על בעיית אבטחה דומה בתוכנה בשם Transmission שהיא Bitorrent Client פופולרי למק. התוכנה מורכבת מ Service שרץ על המחשב שלכם ואפשר לשלוט בו דרך ממשק ווב. פרטים ודוגמאות קוד לפריצה ולתיקון בקישור:
https://github.com/transmission/transmission/pull/468
ובנימה אישית מתקפות מהסוג הזה מזכירות את החשיבות של פיתוח קוד מאובטח בתור תהליך ושיטת עבודה. קשה מאוד לראות מה הולך לבוא ועל איזה רעיונות מוזרים אנשים עוד יחשבו, אבל גם אם המתקפה הזאת לא היתה קיימת עדיין זה היה רעיון טוב להגן בסיסמא על כל אחד מההתקנים ברשת הפנימית. הנחת העבודה של פיתוח מאובטח היא שגם אם מכשיר אחד נופל הוא לא צריך להפיל איתו את כל השאר כמו דומינו. וכשאתם בונים בתוך הרשת ואפילו בתוך המחשב חומות פנימיות בין ההתקנים והרכיבים השונים אתם חסינים למתקפה זו ולרבות נוספות.