לינוקס מתקדם CLI
לינוקס מתקדם CLI — Pipes, הפניות וחיפוש
שיעור זה לוקח אתכם מ"יודע פקודות בסיסיות" ל"יכול לבנות שרשרות פקודות עוצמתיות". Pipe, Redirection, grep, find ו-xargs הם הליבה של כל עבודת CLI אמיתית — ובמיוחד ב-CTF.
- Pipe (|) — שרשור פקודות: stdout של אחת = stdin של הבאה
- Redirection: >, >>, < — הפניית קלט ופלט לקבצים
- stderr (2>) ו-/dev/null — השתקת שגיאות
- grep — חיפוש וסינון טקסט, -i, -r, -n, -v, -c, Regex
- wc — ספירת שורות, מילים ו-bytes
- find — חיפוש קבצים לפי שם, הרשאות, גודל, זמן
- xargs — המרת פלט pipe לארגומנטים לפקודה אחרת
- sort, uniq, cut, awk — עיבוד טקסט מתקדם
- שרשורי Pipes מורכבים — ניתוח לוגים ב-CTF
Pipe — שרשור פקודות
הכוח האמיתי של Linux CLI: לקחת את פלט פקודה אחת ולהזרים אותו ישירות כקלט לפקודה הבאה. Pipe = | (Vertical Bar).
# דוגמה 1: כמה תהליכים של apache רצים?
ps aux | grep apache | wc -l
# דוגמה 2: 10 הקבצים הכבדים ביותר ב-/var/log
ls -lS /var/log | head -10
# דוגמה 3: מי מחובר למערכת, ללא כפילויות?
who | awk '{print $1}' | sort | uniq
# דוגמה 4: חיפוש flags ב-CTF
grep -r "flag{" /home/ 2>/dev/null | head -20
# דוגמה 5: שמות כל המשתמשים ממוינים
cut -d: -f1 /etc/passwd | sortps aux | grep apache | wc -l?Redirection — הפניית קלט ופלט
כל תוכנית ב-Linux עובדת עם שלושה ערוצים: stdin (0), stdout (1), stderr (2). Redirection שולטת לאן כל ערוץ הולך.
| אופרטור | ערוץ | פעולה | דוגמה |
|---|---|---|---|
| > | stdout (1) | כתוב לקובץ (דרוס!) | ls /etc > list.txt |
| >> | stdout (1) | הוסף לסוף קובץ קיים | date >> log.txt |
| < | stdin (0) | קרא מקובץ | sort < names.txt |
| 2> | stderr (2) | הפנה שגיאות לקובץ | cmd 2> errors.txt |
| 2>&1 | stderr→stdout | שלח שגיאות לאותו מקום כמו stdout | cmd > out.txt 2>&1 |
| 2> /dev/null | stderr (2) | השתק שגיאות (חור שחור) | find / -name "*.key" 2> /dev/null |
# כתוב רשימת קבצים לקובץ
ls /etc > ~/etc_list.txt
# הוסף תאריך לסוף לוג קיים (לא דורס!)
date >> ~/security_log.txt
# חיפוש קבצים — השתק "Permission denied"
find / -name "*password*" 2> /dev/null
# שמור stdout לקובץ, שגיאות לקובץ אחר
./script.sh > output.txt 2> errors.txt
# /dev/null — "החור השחור" של Linux
# כל מה שנכתב אליו נעלם לצמיתות
echo "unwanted" > /dev/null # נעלם
cat /dev/null # מחזיר כלום! > דורס — >> מוסיף. זה ההבדל ›
> (כתיבה): מוחקת כל תוכן קיים בקובץ לפני כתיבה — מסוכן!
>> (הוספה): מוסיף לסוף הקובץ מבלי לפגוע בתוכן הקיים.
echo "A" > out.txt; echo "B" >> out.txt; echo "C" > out.txt?grep — חיפוש וסינון טקסט
grep (Global Regular Expression Print) — סורק קבצים שורה אחר שורה ומחזיר רק שורות שתואמות לתבנית. אחד הכלים הכי שימושיים בכל עבודת CLI.
grep "pattern" file.txt # חיפוש בסיסי
grep -i "pattern" file.txt # Case-insensitive
grep -r "pattern" /etc/ # Recursive — כל ספריה
grep -n "pattern" file.txt # הצג מספרי שורות
grep -v "pattern" file.txt # Invert — שורות שלא מכילות
grep -c "pattern" file.txt # ספור כמה שורות תואמות
grep -l "pattern" *.txt # רק שמות קבצים
grep -A 3 "pattern" file.txt # 3 שורות אחרי ההתאמה
grep -B 2 "pattern" file.txt # 2 שורות לפני ההתאמה
grep -E "pat1|pat2" file.txt # Extended Regex — OR
# דוגמאות CTF:
grep -r "password" /etc/ 2>/dev/null # חפש סיסמאות
grep -r "flag{" /home/ 2>/dev/null # חפש CTF flags
grep "FAILED" /var/log/auth.log # כניסות כושלות
ps aux | grep -v grep | grep "python" # תהליכי python- grep -r "password\|pass\|secret" /etc/ 2>/dev/null
- grep -r "flag{" / 2>/dev/null
- grep "Accepted\|Failed" /var/log/auth.log
- cat /etc/passwd | grep -v nologin — רק משתמשים אמיתיים
grep -v "nologin" /etc/passwd?find ו-wc — חיפוש קבצים וספירה
find מחפש קבצים בכל עץ ספריות לפי כל קריטריון. wc סופר שורות, מילים ו-bytes — שניהם כלי ליבה בסייבר.
find — חיפוש קבצים
# חיפוש לפי שם
find / -name "flag.txt" 2>/dev/null
find /home -name "*.sh" 2>/dev/null
find . -name "*password*"
# חיפוש לפי סוג
find /tmp -type f # קבצים בלבד
find /etc -type d # ספריות בלבד
# חיפוש לפי הרשאות — חיוני לPrivEsc!
find / -perm -4000 -type f 2>/dev/null # SUID binaries
find / -perm -2000 -type f 2>/dev/null # SGID binaries
find / -writable -type f 2>/dev/null # קבצים שכולם יכולים לכתוב
# חיפוש לפי גודל
find /home -size +10M # גדולים מ-10MB
find /tmp -size -1k # קטנים מ-1KB
# חיפוש לפי זמן
find /etc -mtime -7 # שונו ב-7 ימים האחרונים
# ביצוע פעולה על כל תוצאה
find . -name "*.tmp" -exec rm {} \;
find /home -name "*.log" -exec cat {} \;wc — ספירה
wc -l file.txt # ספור שורות (הנפוץ ביותר!)
wc -w file.txt # ספור מילים
wc -c file.txt # ספור bytes
wc file.txt # הכל: שורות מילים bytes
# שימוש נפוץ — ספירת תוצאות:
ps aux | grep apache | wc -l # כמה תהליכי apache?
grep "Failed" auth.log | wc -l # כמה ניסיונות כושלים?
find /tmp -name "*.sh" | wc -l # כמה scripts ב-/tmp?find /etc -mtime -7?xargs — ממיר Pipe לארגומנטים
חלק מהפקודות (rm, cat, chmod) לא מקבלות קלט מ-stdin — הן דורשות ארגומנטים ישירים. xargs לוקח פלט מ-Pipe והופך אותו לארגומנטים.
find . -name "*.tmp" | xargs rm — עובד! xargs ממיר את השורות לארגומנטים של rm.
# בעיה: rm לא יכול לקרוא מ-Pipe ישירות
find . -name "*.tmp" | rm # ✗ לא עובד!
# פתרון: xargs ממיר לארגומנטים
find . -name "*.tmp" | xargs rm # ✓ עובד!
# דוגמאות נוספות
find /tmp -name "*.log" | xargs cat # הדפס כל לוגים
find . -name "*.py" | xargs grep "password" # חפש ב-Python files
find / -perm -4000 2>/dev/null | xargs ls -la # פרטי SUID files
# -I {} — ציין בדיוק איפה לשים הארגומנט
find . -name "*.sh" | xargs -I {} chmod +x {}
# חלופה: find עם -exec (לעיתים עדיף)
find . -name "*.tmp" -exec rm {} \;
find . -name "*.tmp" -delete # הכי יעיל!! שמות קבצים עם רווחים — בעיית xargs ›
אם שמות הקבצים מכילים רווחים, xargs יפרש כל מילה כארגומנט נפרד. הפתרון: find . -name "*.tmp" -print0 | xargs -0 rm — print0 משתמש בNULL כמפריד במקום רווח.
find . -name "*.py" | xargs grep "password"?עיבוד טקסט — sort, uniq, cut, awk
הכלים שמשלימים את תמונת ה-Pipe. ביחד עם grep — אלה בוני השרשרות החזקות ביותר ב-CLI.
# sort — מיון שורות
sort file.txt # סדר אלפביתי
sort -n file.txt # סדר מספרי
sort -r file.txt # הפוך (Z→A)
sort -u file.txt # מיון + הסרת כפילויות
sort -k2 file.txt # מיון לפי עמודה 2
# uniq — הסרת כפילויות עוקבות (חייב sort קודם!)
sort file.txt | uniq # כפילויות מוסרות
sort file.txt | uniq -c # ספור כמה פעמים כל שורה
sort file.txt | uniq -d # רק שורות כפולות
# cut — חתוך עמודות
cut -d: -f1 /etc/passwd # שמות משתמשים בלבד
cut -d: -f1,7 /etc/passwd # שם + shell
cut -c1-10 file.txt # תווים 1 עד 10 בכל שורה
# awk — עיבוד שדות
awk '{print $1}' file.txt # שדה ראשון (מופרד ברווח)
awk -F: '{print $1,$6}' /etc/passwd # שם + home dir
ps aux | awk '{print $2,$11}' | head # PID + command- cut -d: -f1 /etc/passwd | sort — רשימת משתמשים ממוינת
- ps aux | awk '{print $1}' | sort | uniq -c | sort -rn — מי מריץ הכי הרבה תהליכים
- grep "Failed password" /var/log/auth.log | awk '{print $11}' | sort | uniq -c | sort -rn | head — Top IPs לbrute force
cut -d: -f1 /etc/passwd | sort?sort file.txt | uniq -c | sort -rn | head -3 כאשר file.txt מכיל: alice, bob, alice, carol, bob, alice?grep "Failed password" /var/log/auth.log | awk '{print $11}' | sort | uniq -c | sort -rn | head -5?תרגול נוסף — Shell: Pipes, Redirection ו-Injection
שאלות העשרה נוספות לחיזוק החומר של השיעור — באותו פורמט בחירה של הקורס.
cat file | sort | uniq -c | sort -rn | head -5?> ל->>?TARGET=$(cat /dev/stdin). מה הבעיה אם הקלט מגיע ממשתמש?אתגר מעשי — לינוקס — grep, awk וצינורות
שיא השיעור: היפוך, ניתוח וזיהוי — כלי ה-RE וה-Low-Level בפעולה. ההגשה נבדקת אוטומטית.
שאלות תרגול ותשובות (19)
שאלה 1.1 · מה עושה השרשרת: ps aux | grep apache | wc -l?
ps aux | grep apache | wc -l
- א. מוחקת את כל תהליכי apache הרצים במערכת, אף שהשרשרת רק סופרת את השורות ואינה מוחקת דבר כלל כאן
- ב. מציגה את כל תהליכי apache יחד עם מספר השורות שלהם, אף ש-wc מחזירה רק את מספר השורות ולא אותם כאן
- ג. מדפיסה את מספר תהליכי apache הרצים כרגע במערכת, על-ידי ספירת שורות הפלט של הפקודה grep כאן
- ד. מחפשת את המילה apache בתוך קובץ בשם wc, אף ש-wc היא פקודה הסופרת שורות ואינה קובץ שמחפשים בו כאן
✓ תשובה: ג) — ps aux = כל תהליכים. | grep apache = סנן רק שורות עם "apache". | wc -l = ספור שורות (= מספר תהליכים). השרשרת = 3 פעולות, תוצאה אחת.
שאלה 1.2 · מה ההבדל בין | לבין >?
# כתוב רשימת קבצים לקובץ ls /etc > ~/etc_list.txt # הוסף תאריך לסוף לוג קיים (לא דורס!) date >> ~/security_log.txt # חיפוש קבצים — השתק "Permission denied" find / -name "*password*" 2> /dev/null # שמור stdout לקובץ, שגיאות לקובץ אחר ./script.sh > output.txt 2> errors.txt # /dev/null — "החור השחור" של Linux # כל מה שנכתב אליו נעלם לצמיתות echo "unwanted" > /dev/null # נעלם cat /dev/null # מחזיר כלום
- א. הסימן | מעביר את stdout של פקודה אחת אל stdin של הפקודה הבאה, ואילו > שומר את הפלט לתוך קובץ
- ב. אין ביניהם כל הבדל, ושני הסימנים מפנים את הפלט אל אותו היעד בדיוק בכל מקרה שהוא במערכת כאן כן
- ג. הסימן | כותב את הפלט לקובץ ואילו > מעביר אותו אל פקודה אחרת, שהוא בדיוק ההפך מן ההבחנה הנכונה כאן
- ד. הסימן | משמש עבור פקודות ואילו > משמש עבור תהליכים, אף שאין זו כלל ההבחנה הנכונה בין שני הסימנים כאן
✓ תשובה: א) — cmd1 | cmd2 = stdout של cmd1 → stdin של cmd2 (תהליך חי). cmd1 > file = stdout של cmd1 → נשמר לקובץ (נכתב לדיסק).
שאלה 2.1 · איזה אופרטור מוסיף פלט לסוף קובץ קיים מבלי לדרוס את התוכן הישן?
- א. הסימן >: דורס את כל תוכן הקובץ הקיים ומחליף אותו בפלט החדש, ולכן אינו מתאים לצורך המבוקש כאן כן
- ב. הסימן |: מעביר את הפלט אל פקודה אחרת ולא אל קובץ, ולכן אינו שומר כלל את התוכן אל תוך קובץ כאן כן
- ג. הסימן <: מזרים קלט אל תוך פקודה מתוך קובץ, ולא כותב פלט אל קובץ כלל, ולכן אינו מתאים לצורך כאן
- ד. הסימן >>: מוסיף את הפלט אל סוף הקובץ הקיים מבלי לדרוס כלל את התוכן הישן שכבר נמצא בתוכו כאן
✓ תשובה: ד) >> — Append: מוסיף לסוף הקובץ. > = Override: מוחק הכל וכותב מחדש. | = Pipe: לא קובץ. < = קריאה מקובץ.
שאלה 2.2 · אתם מריצים סקריפט סריקה שמייצר המון שגיאות. רוצים שהשגיאות יעלמו אבל הפלט התקין ייוצג על המסך. איזו פקודה?
- א. script.sh > /dev/null: מפנה את הפלט התקין (1) אל האַיִן, ומשאיר דווקא את השגיאות מוצגות על המסך כאן
- ב. script.sh 1> /dev/null: מפנה במפורש את הפלט התקין (1) אל האַיִן, בדיוק כמו הפקודה הקודמת ולא כרצוי
- ג. script.sh | /dev/null: מנסה להעביר את הפלט אל dev/null כאל פקודה, אף שהוא קובץ ולא פקודה שניתן לצנרת
- ד. script.sh 2> /dev/null: מפנה את זרם השגיאות (2) אל האַיִן, ומשאיר את הפלט התקין מוצג על המסך כאן
✓ תשובה: ד) 2> /dev/null — ערוץ 2 = stderr = השגיאות. הניתוב שלו ל-/dev/null משמיד רק שגיאות. ערוץ 1 (stdout) ממשיך למסך. א) ו-ב) = ההפך: משתיק stdout.
שאלה 2.3 — Dry Run · מה מכיל הקובץ out.txt לאחר: echo "A" > out.txt; echo "B" >> out.txt; echo "C" > out.txt?
echo "A" > out.txt; echo "B" >> out.txt; echo "C" > out.txt
- א. C: הסימן > האחרון דורס את כל התוכן הקודם, ולכן נשאר בקובץ רק התו C מן הפקודה האחרונה שרצה כאן
- ב. ABC: הנחה שגויה ששלוש הפקודות מוסיפות זו אחר זו, אף שהסימן > דורס את התוכן ואינו מוסיף אליו כאן כן
- ג. AC: הנחה שגויה שהתו A נשמר והתו C מתווסף, אף שהפקודה האחרונה עם > דורסת גם את התו A שהיה קודם כאן
- ד. BC: הנחה שגויה שהתווים B ו-C נשמרים יחד, אף שהפקודה האחרונה עם > דורסת את כל התוכן הקודם שהיה כאן
✓ תשובה: א) C בלבד — echo "A" > = כותב A. echo "B" >> = מוסיף B (out.txt = A,B). echo "C" > = דורס הכל, כותב C בלבד. out.txt = "C".
שאלה 3.1 · איזה דגל של grep מחפש ללא תלות באותיות גדולות/קטנות?
- א. grep -i: מחפש את הדפוס ללא כל תלות באותיות גדולות או קטנות, כך שהטקסט ABC ו-abc נחשבים זהים כאן
- ב. grep -r: מחפש את הדפוס באופן רקורסיבי בכל הקבצים שבתיקייה, אך אינו מתעלם כלל מגודל האותיות בחיפוש
- ג. grep -v: מציג דווקא את השורות שאינן מכילות את הדפוס, ואינו קשור כלל לגודל האותיות של הטקסט הנחפש כאן
- ד. grep -n: מוסיף את מספר השורה לכל התאמה שנמצאה בקובץ, אך אינו מתעלם כלל מגודל האותיות במהלך החיפוש
✓ תשובה: א) grep -i — -i = case-Insensitive. חיפוש "Password" יתאים גם "password", "PASSWORD", "PaSsWoRd". שימושי ב-CTF כשלא יודעים אם שם הקובץ בגדולות.
שאלה 3.2 · מה עושה: grep -v "nologin" /etc/passwd?
grep -v "nologin" /etc/passwd
- א. מציג רק את השורות שכן מכילות את המילה nologin, שהוא בדיוק ההפך הגמור מפעולת הדגל v של הפקודה כאן
- ב. מציג רק את השורות שאינן מכילות את המילה nologin, כלומר את המשתמשים האמיתיים שיש להם מעטפת כאן
- ג. מוחק מן הקובץ את כל המשתמשים שיש להם nologin, אף ש-grep רק מסנן ומציג שורות ואינו מוחק דבר כלל כאן
- ד. סופר כמה משתמשים במערכת מוגדרים עם nologin, אף שהדגל v מסנן ומציג שורות ואינו סופר את מספרן כלל כאן
✓ תשובה: ב) — -v = Invert: מציג שורות שלא מתאימות לתבנית. nologin = שורות של service accounts. -v מציג רק משתמשים אמיתיים (עם /bin/bash וכדומה).
שאלה 3.3 — CTF · אתם מחפשים flags בכל המערכת. איזו פקודה היעילה ביותר?
# חיפוש לפי שם
find / -name "flag.txt" 2>/dev/null
find /home -name "*.sh" 2>/dev/null
find . -name "*password*"
# חיפוש לפי סוג
find /tmp -type f # קבצים בלבד
find /etc -type d # ספריות בלבד
# חיפוש לפי הרשאות — חיוני לPrivEsc!
find / -perm -4000 -type f 2>/dev/null # SUID binaries
find / -perm -2000 -type f 2>/dev/null # SGID binaries
find / -writable -type f 2>/dev/null # קבצים שכולם יכולים לכתוב
# חיפוש לפי גודל
find /home -size +10M # גדולים מ-10MB
find /tmp -size -1k # קטנים מ-1KB
# חיפוש לפי זמן
find /etc -mtime -7 # שונו ב-7 ימים האחרונים
# ביצוע פעולה על כל תוצאה
find . -name "*.tmp" -exec rm {} \;
find /home -name "*.log" -exec cat {} \;- א. grep -r "flag{" / 2>/dev/null: מחפש את הדפוס בתוך תוכן כל הקבצים במערכת ומתעלם מהודעות השגיאה כאן
- ב. find / -name flag 2>/dev/null: מחפש קבצים ששמם הוא flag בלבד, ולא את הדפוס בתוך תוכן הקבצים שבמערכת
- ג. cat / | grep flag: תחביר שגוי, שכן לא ניתן כלל להריץ את הפקודה cat על שורש מערכת הקבצים כולה בבת אחת
- ד. ls -la / | grep flag: מחפש את המילה flag רק בשמות הקבצים שבשורש בלבד, ולא בתוך תוכן הקבצים עצמם כאן
✓ תשובה: א) — grep -r "flag{" חיפוש רקורסיבי בתוכן כל הקבצים. 2>/dev/null מסתיר שגיאות Permission Denied. ב) מוצא רק קובץ בשם "flag", לא flag בתוך קובץ.
שאלה 4.1 · אתם רוצים לגלות כמה תהליכי apache רצים. הפקודה הנכונה לסיים את השרשרת ps aux | grep apache | ___?
- א. wc -w: סופר את מספר המילים שבפלט ולא את מספר השורות, ולכן אינו נותן את מספר התהליכים המבוקש כאן כן
- ב. count -lines: פקודה שאינה קיימת כלל במערכת, ולכן אינה יכולה לספור את שורות הפלט של הפקודה grep כאן
- ג. grep -c apache: סופר בעצמו את מספר ההתאמות, אך שילובו כאן יספור שורות בתוך שורות ה-grep הקודם ושגוי
- ד. wc -l: סופר את מספר השורות שבפלט, וכל שורה מייצגת תהליך apache אחד שרץ במערכת ברגע זה בדיוק כאן
✓ תשובה: ד) wc -l — wc -l סופר שורות. כל תהליך = שורה אחת בפלט. wc -w סופר מילים = לא נכון. grep -c גם יעבוד אבל פחות שגרתי בשרשרת.
שאלה 4.2 · ב-CTF רוצים למצוא את כל SUID binaries במערכת. איזו פקודה?
- א. ls -la / | grep s: מחפש את האות s בשמות הקבצים שבשורש בלבד, ולא את ביט ה-SUID שבתוך הרשאות הקבצים
- ב. find / -perm -4000 -type f 2>/dev/null: מחפש את הקבצים שביט ה-SUID (הערך 4000) דלוק בהרשאותיהם
- ג. grep -r "SUID" /etc/ 2>/dev/null: מחפש את המחרוזת SUID בתוך תוכן קבצים, ולא קבצים שביט ה-SUID דלוק בהם
- ד. find / -name "*.suid" 2>/dev/null: מחפש קבצים בעלי סיומת suid, אף שאין כלל סיומת שכזו לקבצים עם SUID כאן
✓ תשובה: ב) — -perm -4000 = קבצים עם bit 4000 מוגדר (SUID). -type f = קבצים בלבד. 2>/dev/null = השתק Permission Denied errors. זה השרשרת הקלאסית ל-PrivEsc ב-CTF.
שאלה 4.3 · מה עושה: find /etc -mtime -7?
find /etc -mtime -7
- א. קבצים שנוצרו לפני 7 ימים בדיוק, אף שהדגל mtime מציין טווח של שינוי ולא נקודת זמן מדויקת אחת בלבד כאן
- ב. קבצים שגודלם עולה על 7KB, אף שהדגל mtime קשור כולו לזמן השינוי של הקובץ ולא לגודלו במערכת הקבצים כאן
- ג. שבעת הקבצים האחרונים שנוצרו בתיקייה, אף שהדגל mtime מסנן לפי זמן ואינו מגביל כלל את כמות הקבצים כאן
- ד. קבצים שהשתנו במהלך 7 הימים האחרונים, שכן הדגל mtime עם הערך 7- מציין שינוי שהתרחש בטווח הזה כאן
✓ תשובה: ד) — -mtime -7 = modified time פחות מ-7 ימים = שונו בשבוע האחרון. שימושי ב-CTF לגלות קבצי config שהותקנו לאחרונה. +7 = יותר מ-7 ימים.
שאלה 5.1 · מצאתם 100 קבצי זבל בשם *.tmp. ניסיתם find . -name "*.tmp" | rm אבל נכשל. תיקון נכון?
- א. find . -name "*.tmp" > rm: מפנה את הפלט אל קובץ בשם rm ואינו מריץ כלל את פקודת המחיקה על הקבצים כאן
- ב. find . -name "*.tmp" | xargs rm: הפקודה xargs הופכת את הפלט לרשימת ארגומנטים עבור הפקודה rm כאן
- ג. rm < find . -name "*.tmp": תחביר שגוי, שכן לא ניתן כלל להזרים כך את פלט הפקודה find אל הפקודה rm כאן
- ד. find . -name "*.tmp" -delete | rm: אף שהדגל delete- כן מוחק את הקבצים, ה-| rm שאחריו הוא מיותר ושגוי כאן
✓ תשובה: ב) — xargs לוקח את שורות הפלט מ-find והופך אותן לארגומנטים לrm: בפועל מריץ rm file1.tmp file2.tmp .... חלופה טובה: find . -name "*.tmp" -delete.
שאלה 5.2 · מה עושה: find . -name "*.py" | xargs grep "password"?
find . -name "*.py" | xargs grep "password"
- א. מוצא רק את קובצי ה-Python ששמם הוא password, ואינו מחפש כלל את המילה בתוך תוכן הקבצים עצמם כלל כאן
- ב. מחפש את המילה password בתוך תוכן כל קובצי ה-Python שנמצאים בתיקייה הנוכחית ובתת-התיקיות שבתוכה כאן
- ג. מוחק את כל קובצי ה-Python שמכילים את המילה password, אף ש-grep רק מחפש ומציג ואינו מוחק דבר כלל כאן
- ד. נותן שגיאה בטענה שלא ניתן לשלב את find עם xargs, אף ששילוב זה נפוץ ותקין לחלוטין בשימוש יומיומי כאן כן
✓ תשובה: ב) — find מוצא כל *.py. xargs מעביר אותם לgrep. grep מחפש "password" בתוכם. מקביל ל-grep -r "password" *.py אבל גמיש יותר.
שאלה 6.1 · מה עושה: cut -d: -f1 /etc/passwd | sort?
cut -d: -f1 /etc/passwd | sort
- א. מציג את כל קובץ passwd כשהוא ממוין לפי שורות, אף שהפקודה cut חותכת ומציגה רק את השדה הראשון בלבד כאן
- ב. מדפיס רשימה ממוינת של שמות המשתמשים בלבד, שכן השדה הראשון בקובץ passwd הוא שם המשתמש שנחתך כאן
- ג. חותך את קובץ passwd לשני חלקים נפרדים, אף שהפקודה cut מחלצת שדה מכל שורה ואינה מפצלת את הקובץ עצמו
- ד. מציג את שדות ה-UID וה-GID כשהם ממוינים, אף שהדגל f1 מחלץ את שם המשתמש בלבד ולא את המזהים המספריים כאן
✓ תשובה: ב) — cut -d: -f1 = חתוך לפי מפריד ":" ולקח שדה 1 = שמות משתמשים. | sort = מיין אלפביתית. תוצאה: רשימת כל המשתמשים ממוינת.
שאלה 6.2 — Dry Run מורכב · מה מציגה הפקודה: sort file.txt | uniq -c | sort -rn | head -3 כאשר file.txt מכיל: alice, bob, alice, carol, bob, alice?
sort file.txt | uniq -c | sort -rn | head -3
- א. alice bob carol (ממוין): הנחה שגויה, שכן הדגל c ב-uniq מוסיף גם את מספר המופעים לכל שורה שמוצגת כאן
- ב. 3 alice, 2 bob, 1 carol: הצירוף סופר מופעים, ממיין יורד לפי הספירה, ומציג את שלושת הנפוצים ביותר כאן
- ג. 3 2 1: הנחה שגויה שמוצגות רק הספירות עצמן, אף שכל שורה כוללת גם את השם שנמצא לצד המספר של המופעים כאן
- ד. carol bob alice (הפוך): הנחה שגויה שהמיון הוא לפי שם בסדר הפוך, ולא לפי מספר המופעים של כל שם ברשימה כאן
✓ תשובה: ב) — sort = ממיין. uniq -c = ספור: alice×3, bob×2, carol×1. sort -rn = מיין מרובה לקטן: 3 alice, 2 bob, 1 carol. head -3 = 3 ראשונים = כולם. זו הפקודה הקלאסית לניתוח תדירות ב-CTF.
שאלה 6.3 — אתגר CTF · מה עושה: grep "Failed password" /var/log/auth.log | awk '{print $11}' | sort | uniq -c | sort -rn | head -5?
grep "Failed password" /var/log/auth.log | awk '{print $11}' | sort | uniq -c | sort -rn | head -5- א. מציגה את חמש הפקודות האחרונות שנכשלו במערכת, אף שהשרשרת מנתחת דווקא את ניסיונות ההתחברות הכושלים
- ב. מחפשת חמישה משתמשים שנכשלו בהתחברות, אף שהשדה 11 מחלץ את כתובת ה-IP של המנסה ולא את שם המשתמש כאן
- ג. מציגה את חמש כתובות ה-IP שניסו brute force הכי הרבה, ממוינות לפי מספר הניסיונות הכושלים של כל אחת
- ד. נותנת שגיאה בטענה שהקובץ auth.log אינו קיים, אף שזהו קובץ יומן סטנדרטי הקיים ברוב מערכות הלינוקס כאן
✓ תשובה: ג) — grep מוצא שורות "Failed password". awk שדה 11 = כתובת IP התוקף. sort + uniq -c = ספור כמה פעמים כל IP. sort -rn = מי ניסה הכי הרבה ראשון. head -5 = 5 התוקפים הכי אגרסיביים. זו אנליזת brute force קלאסית!
שאלה 7.1 [קל] · מה עושה cat file | sort | uniq -c | sort -rn | head -5?
cat file | sort | uniq -c | sort -rn | head -5
- א. מוצא את חמש השורות הנפוצות ביותר בקובץ יחד עם ספירת המופעים שלהן — זהו דפוס קלאסי של ניתוח תדירות, שימושי מאוד בקריאת לוגים
- ב. ממיין את הקובץ לפי אלפבית: הנחה שגויה, אף שהמיון הוא רק שלב ביניים לפני uniq -c, ומטרת השרשרת היא ספירת השורות הנפוצות ביותר
- ג. מוחק שורות כפולות בלבד: הנחה שגויה, אף ש-unic -c סופר מופעים במקום למחוק בלבד, וה-sort -rn ו-head מדרגים את החמש הנפוצות ביותר כן
- ד. מציג את חמש השורות הראשונות: הנחה שגויה, אף ש-head -5 פועל אחרי מיון יורד לפי ספירה, ולכן מוחזרות הנפוצות ביותר ולא הראשונות
✓ תשובה נכונה: א — sort → uniq -c (ספירה) → sort -rn (יורד לפי מספר) → head -5. תוצאה: Top 5 שורות שכיחות. חובה למיין לפני uniq.
שאלה 7.2 [בינוני] · מה ההבדל בין > ל->>?
>
- א. שניהם מוסיפים לסוף: הנחה שגויה, אף שהסימן הבודד דורס ומאפס את הקובץ בעוד הכפול מוסיף לסופו, ולכן רק אחד מהם באמת מבצע הוספה כאן כן
- ב. הבודד קורא והכפול כותב: הנחה שגויה, אף ששניהם מפנים פלט לכתיבה, וההבדל הוא בין דריסת הקובץ (בודד) להוספה לסופו (כפול) בלבד כן
- ג. הכפול מוחק את הקובץ: הנחה שגויה, אף שדווקא הסימן הבודד מאפס את הקובץ, בעוד הכפול משמר את התוכן הקיים ומוסיף אליו בסוף כפי שהוגדר כאן
- ד. הסימן הבודד מחליף את תוכן הקובץ ומאפס אותו (truncate), ואילו הסימן הכפול מוסיף את הפלט לסוף הקובץ הקיים מבלי למחוק את מה שכבר בו
✓ תשובה נכונה: ד — > = דריסה (מאפס ואז כותב). >> = הוספה לסוף. טעות נפוצה ומסוכנת: > על קובץ קיים מוחק אותו. ב-Logs תמיד >>.
שאלה 7.3 [קשה] · סקריפט מריץ TARGET=$(cat /dev/stdin). מה הבעיה אם הקלט מגיע ממשתמש?
TARGET=$(cat /dev/stdin)
- א. Command Injection — משתמש יכול להזין למשל google.com ואז נקודה-פסיק ו-rm כדי ש-Bash יריץ גם את הפקודה השנייה, ולכן זו חולשה חמורה
- ב. הסקריפט יאט מאוד: הנחה שגויה, אף שהבעיה אינה בביצועים אלא בכך שקלט לא-מסונן עלול להכיל פקודות זדוניות ש-Bash יריץ בהמשך בפועל בכל מקרה
- ג. הקלט לא ייקרא כלל: הנחה שגויה, אף ש-cat /dev/stdin דווקא קורא את הקלט, והסכנה היא שקלט זדוני מוזרק ומורץ כפקודה על ידי המעטפת בפועל
- ד. הקובץ יימחק אוטומטית: הנחה שגויה, אף שאין כאן מחיקת קובץ מובנית, והחשש האמיתי הוא הזרקת פקודות שרירותיות דרך קלט לא-מסונן כאן
✓ תשובה נכונה: א — קלט לא-מסונן שנכנס להקשר של פקודה = Command Injection. 'site.com; rm -rf ~' → Bash מריץ את שתי הפקודות. פתרון: תמיד לצטט ולוודא קלט.