CVE-2019-14287 : פגיעות בקוד של sudo מאפשר הרצת פקודות כמשתמש על

בתאריך ה-14.10.2019 התפרסמה פגיעות בקוד של אחת הפקודות הנפוצות הקיימות במערכות ההפעלה המבוססות unix. החולשה שקיבלה את שם הקוד : CVE-2019-14287, הינה חולשה בקוד של פקודת ה sudo , המשמשת להענקת גישות למשתמש.

החולשה בקוד נמצאה ונותחה ע"י Joe Vennix מ Apple

מהי פקודת ה sudo ?

פקודת ה sudo הינה פקודה במערכות הפעלה המבוססות unix המאפשרת הרצת פקודות בעזרת הרשאות של משתמש אחר, בדרך כלל כמשתמש על – root

בעת שימוש יום יומי במערכת , נהוג לעבוד כמשתמש "נמוך" (משתמש ללא הרשאות מיוחדות) , ולהחליף משתמש רק כשיש צורך להריץ פקודות המחייבות הרשאות גבוהות . בעבר הדבר בוצע ע"י הפקודה su שהיא קיצור ל switch user ומאפשרת להחליף משתמש. עם הזמן , הגיעו למסקנה כי החלפת משתמש היא לא מנהג טוב, משתמשים פשוט היו מבצעים החלפת משתמש למשתמש גבוה (root) ופשוט ממשיכים לעבוד כמשתמש זה,בלי לחזור חזרה למשתמש הנמוך.

פקודת sudo באה להתגבר על תופעה זו , ע"י כך שהיא משמשת להרצה של פקודות ספציפיות , ולא מבצעת החלפת משתמש מלאה.

פגיעות או חולשות בקוד של פקודה זו , הינה דבר חמור שיכול לגרום לתופעה של privilege escalation – תופעה הגורמת למשתמש פשוט להריץ פקודות כמשתמש גבוה בלי שניתנה לו ההרשאה המתאימה .

אז מה בעצם החולשה ?

בואו נראה דוגמא . ברשותי מערכת ubuntu  , עם קרנל גירסה 4.15.0-64 : 

uname_result

יצרתי משתמש חדש בשם testuser ללא הרשאות מיוחדות . כמובן שבשביל ליצור משתמש חדש, יש צורך בהרשאות גבוהות ולכן הרצתי את הפקודה sudo על מנת להריץ את הפקודה adduser כמשתמש root :

adduser

שימו לב , שהשלב הראשון אחרי הרצת הפקודה , אני צריך להכניס את הסיסמה של היוזר שלי . פקודת ה sudo מחייבת מהמשתמש להכניס את הסיסמה שלו לצורך הזדהות.

כעת , בוא נשתמש בפקודה su על מנת להחליף את המשתמש ולהתחיל לעבוד כמשתמש החדש שיצרנו:

switch user

כעת , ננסה שוב ליצור משתמש חדש , הפעם בעזרת היוזר החדש שיצרנו :

user not in sudoers

שימו לב , שהפעם קיבלנו הודעת שגיאה . ההודעה אומרת שהיוזר שלנו (testuser) לא קיים בקובץ ה sudoers . מה ?!?!

מה זה קובץ ה sudoers ?

קובץ זה נמצא בתוך התיקייה etc והוא מכיל את כל הקונפיגורציה של פקודת ה sudo . שם אפשר להגדיר איזה משתמש יכול לקבל גישה לאיזו פקודה ואפילו כאיזה משתמש (חשוב מאוד , פקודת ה sudo יכולה לתת הרשאות של כל משתמש , לא רק משתמש root)

ניתן לראות את קובץ ה sudoers ע"י הפקודה cat /etc/sudoers  – שימו לב , כי דרושה הפקודה sudo על מנת להעלות את ההרשאות מאחר וקובץ זה ניתן לפתיחה רק ע"י משתמש גבוהה:

sudoers file

ניקח לדוגמא את הפקודה whoami . פקודה זו נועדה (כשמה) להראות מי היוזר. הנה דוגמא להרצה:

whoami first test

בפעם הראשונה אני מריץ את הפקודה כמשתמש guym , והפקודה מחזירה לי את שם המשתמש שהריץ אותה – guym

בפעם השניה אני מריץ את הפקודה בעזרת הפקודה sudo , ולאחר אימות , אנחנו רואים שהפקודה whoami , החזירה לי את שם המשתמש root . זה בגלל שהפקודה sudo העלתה את ההרשאות שלנו ל root לפני שהריצה את הפקודה whoami .

אותו דבר, ניתן לעשות בעזרת sudo ולשנות את המשתמש שלנו למשתמש אחר . לדוגמא:

sudo to another user

בדוגמא הזאת , השתמשנו ב sudo על מנת לתת למשתמש שלנו guym את ההרשאות של היוזר testuser , ולכן הפקודה whoami  הציגה לנו את שם המשתמש שהריץ אותה , שהוא testuser

אז איפה הבעיה ?

כזכור , כשניסינו להריץ את sudo בעזרת המשתמש שיצרנו testuser קיבלנו את הודאת השגיאה כי היוזר testuser לא נמצא בקובץ ה sudoers .

בואו נוסיף אותו :

add user to soduers

הוספנו את המשתמש testuser , ונתנו לו את ההרשאות להריץ את הפקודה whoami ככל יוזר.

בוא נבצע בדיקה חוזרת :

another sudo example

בשורה הראשונה , אנחנו משתמשים ב su על מנת להחליף את המשתמש למשתמש testuser

בשורה השניה , אנחנו רואים שכשאנחנו מריצים sudo whoami כמשתמש testuser , אנחנו בעצם מקבלים את root (כי הפקודה whoami רצה עם ההרשאות של root)

בשורה השלישית אנחנו רואים כי המשתמש testuser יכול להריץ את הפקודה whoami גם כמשתמש אחר – לדוגמא guym

אבל אם root לא בא לי ?

יש אפשרות בקובץ ה sudoers להגביל את מתן ההרשאות למשתמשים מסוימים . לדוגמא, נשנה את השורה שהוספנו ונגביל את האפשרות למשתמש testuser לשנות את ההרשאות למשתמש root :

soduers file with cve

ביצענו את השינוי בקובץ ה sudoers והוספנו את האפשרות root!– שאומרת שאת הפקודה whoami המשתמש testuser לא יוכל להריץ כמשתמש root

בואו נבדוק:

sodu root not allow example

בשורה הראשונה , אנחנו משנים את המשתמש שלנו למשתמש testuser

בשורה השניה , אנחנו מריצים whoami בצורה רגילה , ובאמת התשובה היא testuser

בשורה השלישית , אנחנו מריצים את whoami כמשתמש guym , ובאמת התוצאה היא guym

בשורה הרביעית , אנחנו מנסים להריץ את whoami כמשתמש על – root – ומקבלים הודאת שגיאה.

בשורה החמישית , עושים עוד ניסיון להריץ את הפקודה כ root , ושוב , הודאת שגיאה.

הכל עובד כמו שצריך , אז מה בעצם הבעיה ?

על מנת לראות את החולשה בפעולה , ננסה שוב להפעיל את הפקודה whoami , אבל כמשתמש …

רגע לפני שממשיכים , שימו לב שלפקודה sudo ניתן להוסיף את הפרמטר -u ואת המשתמש שרוצים לקבל את ההרשאות שלו . ניתן להוסיף את שם המשתמש , או את ה uid שלו .

מה זה uid ? זה מספר המייצג את המשתמש . ניתן לקבל אותו ע"י שימוש בפקודה id , או לראות אותו בתוך קובץ ה passwd :

passwd and id

כמו שאתם רואים , ה id של המשתמש guym הוא 1000 , ואילו ה id של המשתמש root הוא 0

אתם רואים שאם אני מעביר את ה id 1001 לפקודה sudo , אני בעצם מקבל את ההרשאות של המשתמש testuser (כי זה ה uid שלו)

מה יקרה , אם אני אעביר לפקודה sudo את ה uid מינוס 1 ? ה uid צריך להיות מספר חיובי , איך הפקודה sudo תתייחס לכזה נתון ?

בואו נבדוק :

cve exploit

זהו , הצלחנו לנצל את החולשה בפקודה sudo על מנת להריץ את הפקודה whoami עם ההרשאות של root, למרות שבקובץ ה sudoers מוגדר במפורש לא לתת למשתמש testuser להריץ את הפקודה whoami כ root (אפשר לראות שבפעם הראשונה בפקודה באמת נכשלת)

ניתן גם להשתמש במספר 4294967295 על מנת לקבל את אותה תוצאה .

אז למה בעצם זה קורה ?

בשביל להבין למה זה קורה בדיוק , צריך להבין איך רצה הפונקציה sudo.

אם נסתכל על ההגדרה של קובץ ה sudoers , נראה שמסתתרת לנו s קטנה כחלק מהרשאות הקובץ:

sudo chmod settings

ה s הזאת בעצם נקראת – SetUID bit – ואומרת שהתוכנה הזאת רצה עם ID המשתמש שלה (כמו שאנחנו רואים הצילום מסך הקובץ sudo שייך למשתמש root) ולא עם ה ID של המשתמש שהריץ אותה . לכן , כל משתמש שיריץ sudo , יריץ אותו כ root.

בשלב השני , תסתכל הפונקציה sudo בקובץ ה soduers , ותבדוק האם ניתן או לא ניתן להריץ את הפקודה שניתנה. במקרה שלנו , המשתמש testuser מנסה להריץ את הפקודה whoami כיוזר -1 . האם מותר ?

כן , לפי קובץ ה soduers מותר למשתמש testuser להריץ את whoami ככל משתמש אחר למעט root . המשתמש -1 הוא לא root (ה id של המשתמש root  זה 0 ) , ולכן מותר (בעיה מספר 1 )

בשלב שלישי , הפונקציה sudo קוראת לפונקציות setresuid ו setreuid על מנת לשנות את ה id של המשתמש , ל id שנבחר (במקרה שלנו ה id הוא 1-) . כאן יש בעיה שהפונקציות הלו , בהינתן ה id 1- , לא מבצעות כלום , ולא משנות את ה id . (בעיה נוספת ? )

בשלב הרביעי , sudo יריץ את הפקודה שניתנה לו (במקרה שלנו whoami) , ובגלל שבשלב 3 לא שונה ה id , התוכנה whoami תרוץ עם ה id של sudo , שכמו שאמרנו בשלב 1 , sudo תמיד רץ כ root

וזהו , המשתמש testuser הצליח להריץ את whoami כמשתמש root , למרות שקובץ ה soduers בפירוש לא מרשה את זה.

האם הגיע הזמן להיכנס לפאניקה ?

ובכן , כנראה שלא.

מדובר על חולשה שמנצלת קינפוג מאוד ספציפי שמרשה למשתמש מסוים להריץ פקודה מסוימת ככל משתמש אחר למעט root . האם זה משהו שמקונפג בדרך כלל , נראה לי שלא ומדובר פה על מקרים מאוד ספציפים.

מה עושים עכשיו ?

עכשיו הזמן לשדרג . תבדקו מה גירסת ה sudo שלכם , ובמידה והיא קטנה מ 1.8.28  , אז צריך לשדרג:

sudo version

 

למידע נוסף :

מידע נוסף באנגלית

קישור לקוד של sudo שמכיל את התיקון

השארת תגובה