הערה: ההסבר טכני (מאוד), אבל עשוי להיות קריא ו/או מעניין גם לאנשים ללא ידע טכני.
המטרה:
מטרתה היחידה של תחרות APCHI (תחרות ההאקינג של אוגוסט פינגווין) היתה לעשות קצת כיף. למתחרים עצמם, שקיבלו אפשרות לבחון את כישורי ההאקינג שלהם, למארגנים, שנהנו להכין את המכשולים וזכו לראו את ההבעות הנבוכות של המתחרים כשגילו את המלכודות שהכנו להם, ושל הצופים, שנהנו מההצגה. אני יכול להגיד שבשתי המטרות הראשונות עמדנו יפה (לפחות לפי הפידבק הראשוני מהמארגנים והמשתתפים), ולגבי המטרה השלישית, הצופים צריכים להעיד.
יוזם ונותן הרעיון שמאחורי APCHI היה לא אחר מאשר גלעד בן יוסף (
קודפידנס), שהציע תחרות "שתתחיל במקום שתחרויות האקינג בדרך כלל מסתיימות". בתחרויות האקינג המטרה היא לרוב להשיג גישה למחשב. כאן אנו מתחילים מגישה מלאה למחשב, וצריכים להמשיך הלאה: "אוקי, קיבלת root. מה אתה עושה עכשיו?"
ההצטרפות לקבוצות היתה ברישום מוקדם, כאשר הגבלנו את ההשתתפות ל- 5 אנשים בקבוצה. בפועל נרשמו מראש 8 אנשים שחולקו אקראית ל- 2 קבוצות, שלושה מהם לא הגיעו לכנס (או הגיעו לכנס אחרי התחלת התחרות), ו- 2 חדשים נרשמו בתחילת היום. כך היתה לנו קבוצה של 4 מתחרים מול קבוצה של 3 מתחרים. אני חושב שמספר המתחרים היה סביר - פחות מ- 3 בקבוצה זה מעט, ומעל 5 זה הרבה. אני אשמח לשמוע את דעת המתחרים לגבי מספר המשתתפים בקבוצה.
הקבוצות נבחרו באקראי, אבל להפתעתי (ושמחתי!) היה איזון מושלם בין הקבוצות. המעבר משלב לשלב נעשה כמעט באותו הזמן, גם אם הפתרונות שנמצאו לא תמיד היו זהים. דבר נוסף שבלט היה הכשרון הרב שהיה בשתי הקבוצות - ללא ספק מדובר היה בתותחי לינוקס אמיתיים...
סינמה סיטי הואילו לתת לנו גישה למסכי הפלזמה שפזורים בלובי. זה איפשר לנו להראות את מסך העבודה של כל אחת מהקבוצות על מסך ענק, כמו גם את סטטוס התחרות על מסך נפרד. כל מי שחשקה נפשו לראות מסך command line עם כל מיני פקודות משונות קיבל את סיפוקו.
התחלת התחרות:
המשתתפים קיבלו חולצות של
securiteam עם הדפסי פינגווינים בכחול ואדום כדי להבדיל בין הקבוצות (אגב, את ההדפסים תכנן והפיק אלי עם עזרה מטל בביצוע). הם נועדו בעיקר למנוע מעבר של שחקן מקבוצה לקבוצה וריגול תעשייתי. החולצות גם עזרו להבדיל בין הצופים למתחרים.
התחרות היתה מורכבת מספר משימות. המשימה הראשונה שניתנה לקבוצות עם התחלת התחרות היתה לשנות את הקובץ etc/stage2.tmp/ ולהחליף את המלה "locked" ב- "unlocked" (למה stage2 למשימה הראשונה? זה יתברר עוד מעט). לקבוצות ניתנה סיסמת ה- root למחשב (הסיסמה היתה apchi) וגישה מלאה - המגבלה היחידה שהיטלנו על הקבוצות היתה לא להרוג תהליך בשם scoreboard. סיפור הכיסוי היה שתהליך זה מאפשר לנו לנטר את התחרות; פרט לזה הכל מותר.
הקבוצות עשו לוגין, ומיהרו לבדוק את תוכן הקובץ. להפתעתם, למרות שעשו לוגין כ- root, לא יכלו לגשת לקבצים וספריות שונים בדיסק. הסיבה לכך היתה ששינינו את קובץ המשתמשים (etc/passwd/) והחלפנו בין המשתמשים nobody ו- root. כך, משתמש העל (uid 0) נקרא עכשיו "nobody", והמשתמש nobody נקרא עכשיו "root". כך שססמת ה- root היתה כמעט חסרת משמעות. מצד שני, המטרה לא היתה להקשות אלא בעיקר לבלבל; למשתמש nobody (משתמש העל אצלנו) לא היתה ססמה, וכל שנדרש היה su nobody כדי להפוך למשתמש על במערכת. לשתי הקבוצות לקח פחות מדקה להבין מה קורה ולהפוך למשתמש על - קצת יותר מהר ממה שחשבנו, אבל זה השיג את המטרה - הקבוצות נהיו חשדניות הרבה יותר והבינו שהדברים הם לא תמיד כפי שהם נראים...
אגב, ברגע שהקבוצות פתרו את בעית ה-root הן גם הבינו למה הקובץ נקרא stage2 - להפוך למשתמש-על היתה בעצם המשימה הראשונה.
שלב 2:
הקובץ etc/stage2.tmp/ הוא בעל הרשאות המאפשרות למשתמש שהוא בעל הקובץ לערוך אותו (הרשאת write). למרות זאת, נסיון לערוך אותו מראה שהוא read-only. מה קורה פה?
השתמשנו כאן באופציה עתיקה, אבל לא כל-כך מפורסמת, של מערכת הקבצים ext2. קיימת אפשרות לסמן קבצים ב- attributes שונים (man chattr יראה לכם את כל האופציות), בין השאר תכונת ה- immutable גורמת לכך שהקובץ בלתי ניתן לשינוי, ללא קשר להרשאות שלו, וגם לא ע"י משתמש העל. למה זה טוב? בעיקר נגד טעויות אנוש (למנוע שינוי של קבצים קריטים במערכת). attribute דומה הוא האפשרות להגדיר קובץ כ- append-only, כדי למנוע מקבצי לוגים להמחק בטעות. במקרה שלנו immutable גרם לכך שהדרך היחידה לשנות את הקובץ היא להוריד את תכונת ה- immutable. כלומר, chattr -i stage2.tmp מאפשר לשנות אותו, ואז ניתן לערוך אותו עם כל עורך טקסט כגון vi. השלב הזה לא נועד להיות קשה מדי, אבל הנחנו שבגלל לחץ התחרות ובגלל שאין אפשרות לראות את ה- attribute הזה בצורה סטנדרטית (הוא לא מופיע ב- ls, למשל) יקח זמן עד שמישהו "יעלה" על הטריק שלנו. טעינו בגדול.
אין לי מושג איך, אבל שתי הקבוצות עלו על העובדה שהבעיה קשורה ל- chattr. הפקודה man chattr עלתה על המסכים אחרי בערך 3 דקות, והמשימה השניה הושלמה ע"י 2 הקבוצות בו-זמנית אחרי 5 דקות מתחילת התחרות.
בשלב זה קצת נלחצנו - אמנם לא זלזלנו ביכולת הקבוצות, אבל גם לא חשבנו שכל כך מהר יעברו את 2 השלבים כל כך מהר - אני הנחתי שהפתרון של שלב 1+2 ידרוש בין חצי שעה לשעה. לשמחתנו, היה לנו בשלב השלישי נשק עוצמתי הרבה יותר :-)
שלב 3:
אחרי פתרון השלב השני חילקנו שוב פתקים עם משימות. הפעם המשימה היתה לשנות את הקובץ usr/local/august/stage3.tmp/. קצת רקע: המחיצה usr/local/august/ היתה mount ב- loopback של מערכת קבצים מסוג minix. כלומר, היה קובץ על הדיסק שהיווה מערכת הפעלה בעצמו, ולו עשינו mount. בתוך מערכת הקבצים הזאת היה הקובץ שאותו היה צריך לשנות - גם כאן מהמלה Locked ל- Unlocked.
היו לנו כמה טריקים בשרוול. הטריק האולטימטיבי היה מגה-פאץ' של
מולי בן יהודה. הפאץ' ניצל את ה- security framework של לינוקס כדי להוסיף יכולת שאיננה קיימת בקרנלים הרגילים. היכולת המיוחדת היא למנוע שינויים בקבצים הנושאים את השם stage3.tmp. היכולת הזאת נמצאה בקונפיגורציה הסטנדרטית של הקרנל (אחרי הטלאתו עם הפאץ' של מולי, כמובן), תחת ההגדרה CONFIG_SECURITY_AUGUST. סימון של "Y" באופציה הזאת (אגב, ניתן גם להגדירו כמודול קרנל) הופכת את הקרנל מתמים לגמרי, לכזה שלא מאפשר בשום פנים ואופן לשנות קבצים בשם stage3.tmp.
ומה הסיפור עם ה- minix?
זכרו שהמחסום הוא בקרנל. הדבר הראשון שציפינו מהמתחרים לעשות היה לעלות מ- CD עם קרנל שלהם (למשל, בעזרת הדיסק שחולק בכנס). במקרה כזה, קרנל רגיל היה מאפשר את עריכת הקובץ ומסיים את השלב הזה בזמן שלוקח לעשות פעמיים boot.
כדי למנוע החלפת קרנלים מולי ביצע שינוי נוסף בקרנל. למערכת הקבצים minix יש מספר הגדרות (define-ים) שכוללים את ה- magic number של מערכת הקבצים (מי שלא מבין על מה אני מדבר - מספר הקסם הזה הוא פשוט מזהה של מערכת הקבצים minix). בקרנל של מולי מספרי הקסם האלו שונו, וגם במערכת הקבצים minix שאנחנו יצרנו שונו מספרי הקסם בהתאמה. בעצם יצרנו מערכת קבצים חדשה, שרק הקרנל של מולי יודע לזהותה כ- minix. נסיון להחליף קרנל או לעשות אתחול מ- CD אחר לא היה נותן כלום למתחרים פרט לבזבוז זמן נוראי - קרנל אחר היה פשוט מסרב לעשות mount.
כמו כן, לא היתה לנו שום כוונה להקל על המשתמשים. היה ידוע לכולם שמולי קשור לתחרות, וידוע שתחת ההגדרה מולי בן יהודה במילון מופיעה תמונה של הקרנל. כיוון שהשארנו את קוד המקור של הקרנל על הדיסק, הנחנו שאחד הדברים הראשונים שיעשו הקבוצות יהיה grep למחרוזת stage3. לכן מולי החביא את השם, וכתב את האותיות במספרי hex כדי שלא יהיו חשופים ב- plaintext.
חשבנו שכיסינו את עצמנו מכל הכיוונים - הפתרון היחידי שיכולנו לחשוב עליו היה לבצע את השינוי בקרנל; כאן נתנו מספר אפשרויות - אפשר לכנס לפונקציות שמולי הגדיר ולבטל אותם; אפשר גם להוריד את ההגדרת של CONFIG_SECURITY_AUGUST ולקמפל מחדש את הקרנל. שני הפתרונות האלו דורשים זמן (זמן קימפול קרנל, כ- 10 עד 15 דקות). רצינו לצ'פר את הקבוצה שתקפיד להתעמק בשינוי של מולי ותנסה ממש להבין אותו - הקבוצה שעשתה זאת ראתה שיש מעין "דלת אחורית" לטלאי - לפני ביצוע החסימה, הטלאי בודק את התאריך. אם התאריך הוא לפני אוגוסט, הטלאי לא מבצע כלל את הבדיקה. הפתרון המהיר ביותר, אם כן, לא דורש כלל קימפול של הקרנל - רק שינוי התאריך!
אמרתי שחשבנו שכיסינו את עצמנו מכל הכיוונים - על דבר אחד לא חשבנו. קיימת אפשרות להחליף בכלל את מערכת הקבצים שלנו באחת אחרת, כלומר לעשות mount של ספריה אחרת מעל הספריה שלנו, וכך לדאוג שהקובץ ב- usr/local/august/stage3.tmp/ פשוט יוחלף בקובץ אחר.
החלטנו לא לקבל את הפתרון משתי סיבות. ראשית, המטרה היתה לשנות קובץ ספציפי - ולא להחליף אותו בקובץ אחר. שנית, אם היינו מקבלים את הפתרון הזה, הקבוצות היו יכולות לפתור את שלב 2 ו- 3 ע"י הבאת מערכת קבצים אלטרנטיבית וביצוע mount למערכת קבצים החדשה, וברור שלא זו היתה הכוונה. כאן חרגנו מכלל ה- "הכל חוקי כדי להגיע למטרה", ורשמנו לפנינו להגדיר להבא טוב יותר מה אסור לעשות.
באגים:
הטלאי של מולי נכתב בשעות המאוחרות של הלילה שלפני התחרות - לא היה הרבה זמן לבצע QA מעמיק. היו 2 באגים בולטים; הראשון, נסיון לשנות את הקובץ היה מאפס אותו (במקום למנוע את הכתיבה) - זה לא פגע בתחרות (עדיין היה בלתי אפשרי להכניס את המילה "unlocked") ואולי אפילו עזר. היה כיף לראות את המבטים המשתאים של הקבוצות כאשר נסיון לערוך את הקובץ החזיר תשובה חיובית (כאילו הקובץ שונה), אבל מבט לתוכן הקובץ הראה שהוא אופס...
הבאג השני היה משמעותי יותר לתחרות - היו מקרי קצה מסוימים שאיפשרו לשנות את הקובץ. לא ברור עדיין מה המקרים האלה, אבל אנחנו יודעים שיש לפחות מקרה אחד כזה - הקבוצה הכחולה מצאו אותו והצליחה לשנות את הקובץ אחרי מאמצים מרובים (אגב, גם הם לא ידעו איך הם עשו את זה :-) ).
שני הבאגים שימחו אותי מאוד - קיוויתי מאוד שנראה את הקבוצות פותרות את המשימות לאו דווקא בצורה שאנחנו תכננו, גם אם זה קרה במקרה (הרבה פרצות אבטחה מתגלות בצורה מקרית לחלוטין וללא כל תכנון מראש).
בסוף השלב השלישי שתי הקבוצות במצב צמוד מאוד, כאשר לכל אחת מהקבוצות לקח קרוב לשעה כדי לפתור את השלב הזה. הקבוצה האדומה סיימה את השלב מספר דקות לפני הכחולה, אבל לעומת זאת הקבוצה הכחולה מצאה את טכניקת ה- mount בערך רבע שעה לאחר תחילת המשימה - על זה אומרים בכדורגל שהחלטת השיפוט אולי חרצה את גורל המשחק :-)
שלב 4:
גם המשימה הרביעית חולקה בפתקים. הפעם המשימה היתה למצוא את הקובץ של שלב הרביעי, ולפענח את תוכנו. מציאת הקובץ לא היתה קשה, אבל גם לא טריביאלית - בניגוד לקבצים הקודמים לא אמרנו איפה הוא נמצא, רק רמזנו ששמו דומה לשמות הקודמים רק ב- elite speak )ראו: http://www.classicart.biz/733t/733tspeak.htm ). המתחרים מיד הבינו שמדובר בקובץ s74g3.tmp. העובדה שהוא היה קבור עמוק בספריה נידחת גם לא הקשה - locate ו- find נועדו בדיוק כדי למצוא קבצים שאת שמם יודעים אבל את מיקומם לא. הקושי העיקרי היה שהקובץ עצמו היה מוצפן באמצעות PGP. איפה מוצאים את המפתח?
כשתכננו את השלב הזה רצינו להיות מציאותיים ככל האפשר. הצפנה של קובץ מערכת קריטי בדר"כ מחייבת אפשרות אוטומטית של פתיחתו - כלומר המפתח צריך להיות במקום נגיש ולא יכול להיות סיסמה המוקלדת באופן ידני. שמירת המפתח בתוך קובץ במערכת הקבצים היא כמובן האפשרות הטריביאלית, אבל שם גם יחפש המתקיף. איפה עוד אפשר לשים את המפתח? כמובן, אפשר על מערכת קבצים אחרת (דיסקט, התקן USB), אבל את זה יראה מיד מתקיף שיש לו גישה פיסית למחשב (כמו קבוצות ההאקרים שלנו). החלטנו לפיכך להטמין את המפתח בין שירותי המערכת. כך, המפתח לא נמצא על הדיסק, אלא "ברשת", רק שלא בדיוק ברשת - על הרשת של המחשב המקומי. בקיצור, המפתח היה על שירות chargen. שירות שבדר"כ מחזיר ערך אינסופי של תווים, החזיר אצלנו את המפתח תודות לשינוי מיוחד של התהליך inet שעשה נועם. הנחת היסוד שלנו היתה שהמתחרים שלנו יבדקו מהר מאוד איזה תהליכים רצים ואיזה שירותים פתוחים. חשבנו גם שקיום של שירותים מיותרים כמו chargen יהיה חשוד - למה שבשרת שהוקשח במיוחד נגד פורצים יהיו שירותים מיותרים כאלה? ביצוע telnet localhost chargen היה מראה מיד את המפתח.
אך כמו שהופתענו לטובה בשלבים הקודמים, כך הופתענו ל"רעה" בשלב הזה - המתחרים שברו את הראש בנסיונות למצוא את המפתח, כולל סריקה מלאה של הדיסק לחיפוש המפתח. זאת למרות שתיאור המשימה כלל רמז (שיתכן שהיה קצת מטעה) שאמר שהמפתח אינו נמצא על מערכת הקבצים.
אחרי כמעט שעה שבה המתחרים שברו את הראש והזיעו בנסיונות סרק למצוא את המפתח (ולא התקרבו אפילו לפתרון) החלטנו לתת רמז, או בעצם pre-רמז.
רמזים:
כשתכננו את התחרות לא ידענו איזה מהשלבים יהיה קל ואיזה קשה. גם לא רצינו שהקבוצות יבזבזו שעות בלנסות לעבור לשלב הבא, ולכן החלטנו שבמידה וקבוצה מסוימת לא עוברת שלב אחרי שעה, היא תקבל רמז עבה מאוד שיאפשר לה לפתור את השלב במהירות יחסית. לשמחתנו, הרמזים נשארו כמעט מיותרים. קצת התבעסנו, כי גם הצורה שהתכוונו לחלק את הרמזים היתה מעניינת: בשיתוף פעולה עם combooks "שתלנו" בדוכן הספרים 2 ספרי תיכנות על windows, כך שמציאת הרמזים חייבה ידע מסוים בתכנות windows. הספרים נשארו מיותמים, והרמז היחיד שנאלצנו לחלק היה רמז-מקדים, כלומר לא ממש רמז, אלא רק כיוון כללי. הודענו לקבוצות שהפתרון "קשור ל- networking", וחיכינו לראות מי מהם יריץ nmap או netstat על עצמו...
לשמחתנו שתי הקבוצות מצאו את המפתח (אם כי לקח להם קרוב לרבע שעה מקבלת הרמז), השתמשו במפתח כדי לפתוח את הקובץ המוצפן וקיבלו את ההנחיות לשלב המכריע.
באופן מדהים לגמרי שתי הקבוצות סיימו את השלב הזה כמעט בו זמנית, ועברו לשלב האחרון.
השלב האחרון:
כשקבוצה אחת מנצחת, הקבוצה השניה חייבת להפסיד. כדי לוודא שהנצחון הוא ב- knock out, השלב האחרון הודיע לקבוצות על המשימה שלהם: לחדור למחשב הקבוצה השניה ולמחוק אותו לגמרי באמצעות / rm -rf.
לא פירטנו מהי הדרך לחדור למחשב הקבוצה השניה, רק כתבנו שיש backdoor על כל אחד מהמחשבים, ושהסיסמה היא ApchiPassword. מה שהמשתתפים לא ידעו, זה שהתהליך אותו נאסר עליהם להרוג (scoreboard) היה בעצם sshd משופר, שמאזין על פורט גבוה (כדי שסריקת nmap רגילה לא תמצא אותו אלא רק סריקה מלאה) ולא בודק את הססמה מול קובץ הססמאות, אלא רק בודק אם היא שווה ל- ApchiPassword (החשיבות של שני הפרטים האלה תתברר בהמשך).
כיוון שלא התאפשר לנו (עקב אילוצי המקום) לחבר את 2 המחשבים באופן ישיר אחד לשני, חיברנו לפטופ לכל אחד מהמחשבים וביקשנו מכל קבוצה לשלוח נציג שישב על הלפטופ וינסה לחדור לשניה.
הקבוצה האדומה מיהרה לשלוח נציג, ואילו הקבוצה הכחולה התעכבה כדי לנסות ולהקשיח את המחשב כנגד ההתקפה הצפויה. זה היה הימור על כל הקופה - אם אכן היו מצליחים להקשיח את המחשב היו מונעים מהאדומים לחדור אליהם למחשב ולנצח. אם הם נכשלו במלאכת ההקשחה, הם בזבזו זמן יקר שיאפשר לקבוצה האדומה לנצח.
בפועל, תהליך ה- scoreboard לא בדק כלל את קובץ הססמאות, ולכן רוב פעולות ההקשחה (שינוי ססמת ה- root, הורדת שירותים מיותרים, וכו') לא עזרו. הקבוצה הכחולה גם ניסתה להוריד את כרטיס הרשת כדי למנוע כל גישה למחשב, אך זה נאסר ע"י השופטים, בטענה שצריך גישה ל- scoreboard מהרשת (רשמנו לעצמנו לציין את זה במפורש בחוקים להבא).
חשבנו שהשלב האחרון יהיה המהיר מכולם - הרי כל הרמזים שם. יש תהליך בשם scoreboard שללא ספק "חשוד". הצצה חטופה ב- netstat (או שימוש ב- nmap) היתה מראה שהוא מאזין על פורט מסוים, וביצוע telnet לפורט היה מראה שמדובר בשרת SSH. את הססמה נתנו להם מראש, אז מה הבעיה? כנראה שהחדרנו לקבוצות פארנויה ברמות גבוהות - הקבוצות הניחו ש"שום דבר הוא לא כפי שהוא נראה", ולקח להם זמן רב עד שגילו את הפורט הנכון ונכנסו איתו למחשב. לבסוף מחשב אחד נמחק והקבוצה האדומה ניצחה - אבל עוד דקה או שתיים והתוצאה היתה מתהפכת - תחרות כלבבי!
הנפשות המעורבות:
קבוצה כחולה: ליאור קפלן (
תיאור שלו של התחרות), יובל כוכבי, שחר שמש (
תיאור שלו של התחרות), ניר לביא
קבוצה אדומה: עמוס שפירא, צפריר כהן, עדי סתיו
הכינו את התחרות: עמי חיון, נועם רטהאוס, אלי קארה וטל זלצר (
ביונד סקיוריטי) ומולי בן יהודה (יבמ)
עזר ותמך: גלעד בן יוסף
לינק לטלאי של מולי