אקראיות צפויה, כשמחשב מנסה להיות אקראי ונכשל¶
אבטחת מידע נשענת המון על "אקראיות" - טוקן סשן אקראי, מספר חד פעמי (nonce) באתגר, מפתח הצפנה אקראי. הבעיה היא שמחשבים, מעצם הגדרתם, הם מכונות דטרמיניסטיות - נותנים להן אותו קלט, הן תמיד יחזירו אותה תוצאה. אז איך בכלל אפשר לייצר "אקראיות" אמיתית ממכונה שכל כולה חוקים קבועים? זו בדיוק הבעיה שמובילה לחולשות אקראיות צפויה.
מה זה בעצם PRNG¶
רוב המחוללים ש"נראים" אקראיים הם בפועל מחוללי מספרים פסאודו אקראיים - PRNG (Pseudo-Random Number Generator). אלגוריתם כזה מתחיל מערך התחלתי שנקרא seed, ומייצר ממנו סדרה ארוכה של מספרים שנראים אקראיים סטטיסטית, אבל בפועל הם לגמרי דטרמיניסטיים. אם שני מחוללים מתחילים מאותו seed בדיוק, הם ייצרו בדיוק את אותה סדרת מספרים, בכל פעם.
זה בעצם עיקרון תכנוני נהדר לרוב השימושים - למשל בהדמיות או במשחקים, שבהם רוצים תוצאות שחוזרות על עצמן לצורכי בדיקה. אבל בהקשר אבטחה, זו בדיוק הבעיה - אם תוקף יכול לנחש או לחשב את ה-seed, הוא יכול לחזות בדיוק כל ערך שהמחולל ייצר.
מאיפה seed חלש מגיע¶
הטעות הכי נפוצה היא שימוש בזמן הנוכחי (timestamp) כ-seed. זה נשמע הגיוני - הזמן "תמיד שונה", אז זה נראה כמו מקור טוב לאקראיות. אבל בפועל, לתוקף לרוב יש מושג טוב מאוד מתי בערך התוכנית רצה - למשל, אם התוקף יודע בקירוב מתי בקשה מסוימת נשלחה לשרת, הוא צריך לנסות רק חלון זמן קטן יחסית של timestamps אפשריים, ולא את כל טווח הזמן האפשרי מתחילת ההיסטוריה. במקרים מסוימים, אם דיוק ה-timestamp הוא בשניות בלבד, יש רק כמות מוגבלת מאוד של seeds אפשריים לנסות בכלל.
בעיה נוספת ונפוצה היא שימוש חוזר באותו seed בין הרצות שונות, למשל seed קבוע שנכתב ישירות בקוד לצורכי בדיקה, ונשאר שם בטעות גם בגרסת הפרודקשן.
מה תוקף יכול לעשות עם זה בפועל¶
ברגע שתוקף מזהה או משחזר את ה-seed, הוא יכול לחשב מראש בדיוק כל ערך שהמחולל אמור לייצר. בהקשר CTF, זה מתבטא לרוב באתגר שבו צריך "לנחש" סדרת מספרים כדי לקבל דגל - וברגע שמזהים איזה PRNG משמש ומה ה-seed שלו, פשוט מריצים את אותו אלגוריתם באופן עצמאי ומקבלים בדיוק את אותה סדרה.
בהקשר אבטחה אמיתי, ההשלכות חמורות בהרבה - טוקן איפוס סיסמה שנוצר עם PRNG חלש יכול להיות צפוי לתוקף, מה שמאפשר השתלטות על חשבונות בלי לפרוץ שום דבר "טכני" - רק לחשב את מה שהמערכת חשבה שהוא בלתי צפוי.
איך פותרים את הבעיה נכון¶
הפתרון הוא להשתמש במחולל מספרים אקראיים קריפטוגרפי (CSPRNG), שנועד במיוחד לשימושי אבטחה - מחוללים כאלה שואבים אנטרופיה אמיתית ממקורות פיזיים במערכת ההפעלה (רעשי חומרה, תזמוני קלט), ולא ניתנים לחיזוי גם אם תוקף יודע בדיוק מתי הם רצו. בפייתון, למשל, ההבדל הוא בין מודול random הרגיל, שאסור להשתמש בו לצרכים ביטחוניים, לבין מודול secrets, שנבנה בדיוק בשביל זה.
איך זה מתחבר לעולם ה-CTF¶
אתגרי "אקראיות צפויה" מלמדים שיעור שחוזר על עצמו כל הזמן בעולם האבטחה - אקראיות היא רק חזקה כמו המקור שממנו היא נובעת. חוקר טוב תמיד שואל "מאיפה ה-seed הזה הגיע, ומה עוד אני יודע עליו".
בקורס מחקר חולשות אנחנו עוברים על זיהוי וניצול PRNG חלש כחלק מהיסודות של חשיבה קריפטוגרפית, כי זו חולשה שחוזרת שוב ושוב גם מחוץ לעולם ה-CTF.
זיהיתם שאתגר משתמש ב-PRNG חלש אבל לא בטוחים איך לשחזר את ה-seed המדויק? בדיסקורד שלנו יש אנשים שאוהבים בדיוק את סוג הבלשות הזה.
לסיכום¶
אקראיות צפויה מוכיחה שלא כל דבר שנראה אקראי הוא באמת בלתי צפוי. מחשבים דטרמיניסטיים במהותם, וכל אקראיות שהם מייצרים תלויה במקור שממנו היא נובעת. חוקר חולשות טוב יודע לשאול את השאלה הפשוטה הזאת בכל פעם שהוא נתקל ב"ערך אקראי" חשוב.