Linux וכלי פיתוח
יסודות Bash לעבודת אבטחה
pipes, הפניות, משתנים, לולאות, קודי יציאה ו-set -euo pipefail, ואז שימוש בהם כדי לספור התחברויות כושלות ולחשב hash לתיקייה.
איך מפתחות מארח ומשתמש של SSH עובדים, למה Ed25519 עם passphrase הוא ברירת המחדל, ואיך מגדירים ומקשיחים התחברות במפתח על VM של מעבדה בבעלותך.
SSH (Secure Shell) הוא הפרוטוקול שבו רוב האנשים מתחברים לשרתי Linux, למכונות וירטואליות של מעבדה ולמארחי Git. הוא פותח shell בערוץ מוצפן, ואותו ערוץ יכול להעתיק קבצים או להעביר פורטים. יש לו שלושה תפקידים. הוא מצפין את התעבורה כך שאיש בנתיב הרשת לא יכול לקרוא אותה. הוא מוכיח לשרת מי מתחבר. הוא מוכיח ללקוח מי השרת.
מפתחות עושים את התפקיד השני בלי לשלוח סיסמה ברשת. אפשר לנחש סיסמה או לגנוב אותה בפישינג. זוג מפתחות עובד אחרת. השרת שומר רק את החצי הציבורי. כדי להתחבר, הלקוח שלך חותם על אתגר עם החצי הפרטי, והשרת בודק את החתימה. המפתח הפרטי אף פעם לא יוצא מהמחשב שלך.
יש מקרים ש-SSH לא מגן בהם, והם חשובים כמו הפרוטוקול עצמו. אם המחשב שלך נפרץ, נוזקה שרצה תחת המשתמש שלך יכולה לקרוא את קובץ המפתח הפרטי או לבקש מה-agent שלך לחתום על דברים. אם המפתח הפרטי נגנב וה-passphrase שלו חלש, תוקף יכול לנסות לנחש אותו offline. אם מקבלים את זהות השרת בלי לבדוק אותה, ייתכן שהצד השני הוא בכלל לא השרת.
SSH משתמש בשני סוגי מפתחות שונים, ואנשים מבלבלים ביניהם לעיתים קרובות.
מפתחות מארח מזהים את השרת. לכל שרת SSH יש אחד או יותר, בדרך כלל בנתיב /etc/ssh/ssh_host_*_key. החלק הפרטי נשאר על השרת. החלק הציבורי מוצג לכל לקוח שמתחבר. בפעם הראשונה שהלקוח רואה אותו, הוא שומר אותו בקובץ known_hosts. בחיבורים הבאים, מפתח מארח ששונה מפעיל אזהרה.
מפתחות משתמש מזהים אותך. את הזוג יוצרים על המחשב שלך. המפתח הפרטי נשאר אצלך. המפתח הציבורי עובר לשרת, לקובץ ~/.ssh/authorized_keys של החשבון שרוצים להשתמש בו.
להבדל יש השלכות מעשיות. העתקת המפתח הפרטי שלך לשרת נותנת לשרת הזה, ולכל מי שיכול לקרוא אותו, את החומר שדרוש כדי לפעול בשמך בכל מקום שסומך על המפתח. אם מתעלמים מאזהרת מפתח מארח, הסיסמה או הפקודות שלך עלולות להגיע למתחזה.
OpenSSH תומך בכמה סוגי מפתחות. RSA עדיין עובד, אבל מפתחות RSA חדשים צריכים להיות לפחות 3072 ביט, ושורות המפתח הציבורי ארוכות. מפתחות Ed25519 קצרים, מהירים לאימות ומתוקננים ל-SSH ב-RFC 8709. OpenSSH 9.5 ואילך הופך את Ed25519 לברירת המחדל של ssh-keygen. Ed25519 הוא ברירת המחדל הנכונה למפתח מעבדה, אלא אם מערכת שצריך להגיע אליה מקבלת רק סוג ישן יותר.
passphrase מצפין את קובץ המפתח הפרטי בדיסק. בלעדיו, כל מי שמעתיק את הקובץ יכול להשתמש במפתח. איתו, צריך גם את הקובץ וגם את ה-passphrase. זה מגן מפני התקלות הנפוצות ביותר: גיבוי שנשלח למקום הלא נכון, מפתח שנשאר בתיקייה משותפת, קובץ שסונכרן בטעות לכונן ענן. passphrase לא עוזר אחרי שהמפתח נטען ל-agent ונוזקה רצה בשמך. כדאי לבחור passphrase ארוך, לשמור אותו במנהל סיסמאות ולהחזיק גיבוי של קובץ המפתח במקום בטוח.
RFC 4253 מתאר את שכבת התעבורה. במבט על, חיבור עובר את השלבים האלה:
known_hosts. אם המארח חדש, הלקוח מציג את טביעת האצבע ומבקש אישור.authorized_keys, הוא שולח אתגר. הלקוח שלך חותם על האתגר עם המפתח הפרטי, והשרת בודק את החתימה.כדאי לשים לב מאיפה מגיע האמון. שלב 3 עוסק בשרת. שלב 4 עוסק בך. אם מדלגים על בדיקת טביעת האצבע בשלב 3, שאר לחיצת היד עובדת לטובת מי שענה.
טביעת אצבע היא hash קצר של מפתח ציבורי. OpenSSH מציג כברירת מחדל טביעות אצבע של SHA256. שני אנשים יכולים להשוות טביעת אצבע כדי לוודא שהם מחזיקים באותו מפתח ציבורי, בלי להקריא את המפתח כולו.
הפקודות בהמשך הורצו על מחשב Windows 11 עם OpenSSH 9.9p2 (ssh -V), ב-Git Bash. המפתח היה עותק לניסיון שנוצר לצורך הבדיקה הזאת, עם passphrase ריק, כדי שאפשר יהיה להציג כאן את הפלט. למפתח האמיתי שלך תהיה טביעת אצבע אחרת.
ssh-keygen -t ed25519 -C 'lab-key' -f ./lab_ed25519 -N ''
ssh-keygen -lf ./lab_ed25519.pubהפלט שהתקבל:
256 SHA256:2BAyZTrHADdiG1FNwfCwb/fC5vSVZPwfGnZjRaaExc4 lab-key (ED25519)ssh-keygen -lvf מדפיס את אותה טביעת אצבע עם תמונת random-art. קל יותר להבחין בשינוי בתמונה, אבל משווים את טקסט טביעת האצבע.
צריך מכונה וירטואלית או מופע ענן בבעלותך ובשליטתך, עם שרת OpenSSH פעיל וחשבון שיכול להשתמש בפקודה sudo. VM מקומי ב-VirtualBox או ב-Hyper-V מתאים. כך גם מופע ענן קטן שמשלמים עליו ואפשר למחוק אותו. לא מריצים את השלבים האלה מול מחשב ששייך למישהו אחר.
ssh-keygen -t ed25519 -C 'lab-key' -f ~/.ssh/lab_ed25519כשמתבקשים, מזינים passphrase ארוך. הפקודה יוצרת שני קבצים: lab_ed25519 (פרטי) וגם lab_ed25519.pub (ציבורי). רק הקובץ עם הסיומת .pub מיועד לצאת מהמחשב שלך.
ssh-keygen -lf ~/.ssh/lab_ed25519.pubכדאי לרשום את טביעת האצבע, או לפחות את התווים הראשונים. בהמשך משווים אליה שוב.
chmod 600 ~/.ssh/lab_ed25519ב-Linux וב-macOS, ssh מסרב למפתח פרטי שמשתמשים אחרים יכולים לקרוא. ב-Windows, OpenSSH בודק ACLs של קבצים ולא את ביטי ההרשאות של Unix. במחשב ה-Windows הזה chmod 600 רץ בלי שגיאה, אבל ls -l עדיין הציג -rw-r--r-- אחרי זה. אי אפשר להניח שם שביטי ההרשאות השתנו. אם ssh מתלונן על הרשאות ב-Windows, בודקים את הקובץ עם icacls ומסירים גישה מחשבונות אחרים.
ssh-copy-id -i ~/.ssh/lab_ed25519.pub youruser@your-lab-vmזו הפעם היחידה שמקלידים את סיסמת החשבון בכוונה. הפקודה מוסיפה את המפתח הציבורי אל ~/.ssh/authorized_keys על ה-VM.
החיבור הראשון ל-VM מציג גם טביעת אצבע של מפתח המארח. משווים אותה לטביעה האמיתית. על ה-VM מריצים:
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pubאם שתי טביעות האצבע תואמות, מקלידים yes. אם לא, עוצרים. מבררים למה לפני שממשיכים. חוסר התאמה יכול להעיד על כך שה-VM הותקן מחדש, או שמישהו יושב בינך לבין ה-VM.
השלב הזה לא הורץ כאן, כי לא היה VM זמין במחשב הזה. מסיבה זו הפקודות בשלבים 4 עד 6 מוצגות בלי פלט. אפשר לבדוק כל אחת מהן על ה-VM שלך.
ssh -i ~/.ssh/lab_ed25519 youruser@your-lab-vmהלקוח מבקש את ה-passphrase של המפתח ולא את סיסמת החשבון. אם מתקבל shell, המפתח עובד. משאירים את הסשן הזה פתוח לשלב הבא.
על ה-VM:
sudo sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sshd -t && sudo systemctl restart sshהשורה עם sed מחליפה את שורת PasswordAuthentication, בין אם היא בהערה ובין אם לא. sshd -t בודק את תחביר הקונפיגורציה ועוצר את השרשרת אם הוא נכשל. systemctl restart ssh מחיל את השינוי. ב-Fedora ובמערכות אחרות ממשפחת RHEL השירות נקרא sshd, ולכן משתמשים בשם הזה.
שלושה דברים משתבשים כאן לעיתים קרובות:
/etc/ssh/sshd_config כולל קבצים מהתיקייה /etc/ssh/sshd_config.d/, והערך הראשון שנקרא עבור מילת מפתח הוא הקובע. בודקים את הערך ש-sshd משתמש בו בפועל:sudo sshd -T | grep -i '^passwordauthentication'אחרי השינוי הפלט אמור להיות passwordauthentication no. אם עדיין מופיע yes, מאתרים את הקובץ שקובע את זה ומתקנים שם.
sed עורך רק שורה קיימת. אם אין שורת PasswordAuthentication, חלה ברירת המחדל, ודף ה-man של sshd_config(5) אומר שברירת המחדל היא yes. מוסיפים את השורה ידנית:echo 'PasswordAuthentication no' | sudo tee -a /etc/ssh/sshd_configאחר כך בודקים מהמחשב שלך שהתחברות בסיסמה נדחית:
ssh -o PubkeyAuthentication=no -o PreferredAuthentications=password youruser@your-lab-vmהחיבור אמור להיכשל בהודעת permission denied. את הבדיקה הזאת מריצים בעצמך על ה-VM שבבעלותך. היא לא הורצה במחשב הזה.
הקלדת ה-passphrase בכל חיבור מתישה. ssh-agent מחזיק את המפתח המפוענח בזיכרון למשך הסשן, כך שמקלידים את ה-passphrase פעם אחת.
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/lab_ed25519
ssh-add -lssh-add -l מציג את טביעות האצבע שה-agent מחזיק. במחשב ה-Windows הזה ssh-add -l רץ בלי agent פעיל והדפיס Could not open a connection to your authentication agent. עם קוד יציאה 2. ב-Windows משתמשים לזה בשירות OpenSSH Authentication Agent. מפעילים את השירות מקונסולת Services או מ-PowerShell עם הרשאות מנהל. זה שינוי במערכת שלך, ולכן עושים אותו בעצמך ורק אם רוצים שה-agent ירוץ.
agent הוא נוח, והוא גם מטרה. כל מי שיכול לדבר עם ה-socket של ה-agent בזמן שהסשן שלך פעיל יכול לבקש ממנו לחתום על דברים. לכן נמנעים מ-agent forwarding (ssh -A) למארחים שאין בהם אמון מלא. משתמש root במארח המרוחק יכול להשתמש ב-agent המועבר שלך. כדי להגיע למארח פרטי דרך bastion, משתמשים ב-jump host:
ssh -J youruser@bastion youruser@private-vmהלקוח שומר מפתחות מארח בקובץ ~/.ssh/known_hosts, שורה אחת לכל מארח וסוג מפתח. אפשר לעשות hash לשורות עם HashKnownHosts yes, וזה מסתיר שמות מארחים ממי שקורא את הקובץ.
חיפוש מארח:
ssh-keygen -F your-lab-vmהסרת רשומה אחרי בנייה מחדש של VM וקבלת מפתח מארח חדש:
ssh-keygen -R your-lab-vmעושים את זה רק כשברור למה המפתח השתנה. מפתח מארח ששונה הוא אזהרה ולא מטרד. הסרת הרשומה הישנה בלי בדיקת טביעת האצבע החדשה מלמדת להתעלם מהאזהרה הבאה, וייתכן שהיא תהיה אמיתית.
.pub יוצא לשרתים, למארחי Git או לאנשים אחרים.authorized_keys..pub בתוך הקובץ authorized_keys.~/.ssh צריך להיות 700 והקובץ authorized_keys צריך להיות 600. הרשאות רופפות יותר יכולות לגרום ל-sshd להתעלם מהמפתח. כשהתחברות במפתח נכשלת, בודקים את הלוגים של sshd.lab_ed25519 למעבדה ומפתח אחר ל-GitHub.yes.ssh-copy-id פעמיים לא מזיקה, אבל הוספה ידנית של מפתח כמה פעמים מקשה על ביקורת הקובץ. מסירים מפתחות שכבר לא בשימוש.כשהמעבדה עובדת, כמה צעדים הופכים את השימוש היומיומי לבטוח ומסודר יותר.
~/.ssh/config. נותנים לכל מארח כינוי, מגדירים IdentityFile ומוסיפים IdentitiesOnly yes, כדי שהלקוח יציע רק את המפתח שנבחר. כך הלקוח לא מנסה כל מפתח שב-agent מול שרת.ssh-keygen -t ed25519-sk. החלק הפרטי לא ניתן אז להעתקה מהמכשיר. לפני שמסתמכים על זה, בודקים את גרסת ה-OpenSSH ואת התמיכה של המפתח שלך.ssh-keygen ושל sshd_config מתארים כל אפשרות שנתקלים בה. RFC 4253 מסביר את שכבת התעבורה, ו-RFC 8709 מכסה את Ed25519 ב-SSH.אם הרשאות קבצים ובעלות עדיין חדשים לך, כדאי לקרוא קודם את המאמר על קבצים והרשאות ב-Linux. המאמר הבא עוסק ברשתות Docker מבודדות למעבדות, שאפשר להשתמש בהן כדי להרחיק תעבורת מעבדה מהרשת היומיומית שלך.
ssh-keygen(1): https://man.openbsd.org/ssh-keygensshd_config(5): https://man.openbsd.org/sshd_configLinux וכלי פיתוח
pipes, הפניות, משתנים, לולאות, קודי יציאה ו-set -euo pipefail, ואז שימוש בהם כדי לספור התחברויות כושלות ולחשב hash לתיקייה.
Linux וכלי פיתוח
בעלים וקבוצות ב-Linux, ביטי rwx, chmod, umask ו-setuid, עם מעבדה שבודקת גישה כמשתמש שני ומוצאת הרשאות קבצים מסוכנות.
Linux וכלי פיתוח
GitHub למתחילים: מה Git ו-GitHub עושים, המונחים הבסיסיים, תרגול Git מקומי ואיך בודקים פרויקט לפני שמריצים אותו.