בדיקת מכונה וירטואלית לאיתור סימנים לשיבוש בזיכרון הליבה

בדף הזה מוסבר איך לבצע משימות כדי לאמת את התוצאה של rootkit במצב ליבה מתוך זיהוי איומים במכונות וירטואליות. ממצאים של ערכת Rootkit במצב ליבה מצביעים על כך שתוכנה זדונית עלולה לשנות את זיכרון הליבה של מכונה וירטואלית.

כשמקבלים ממערכת זיהוי האיומים במכונה וירטואלית (VM) ממצא של rootkit במצב ליבה, מומלץ להריץ את פקודות ה-Linux האלה במופע Compute Engine המושפע כדי לבדוק את המערכת לאיתור נקודות נתונים שעשויות להצביע על אנומליות, כמו קריאות מערכת שנחטפו או מודולי ליבה מוסתרים.

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

אלא אם צוין אחרת, כל משימת בדיקה בדף הזה רלוונטית לכל הממצאים של rootkit במצב ליבה.

במסמך הזה אנחנו יוצאים מנקודת הנחה ש:

  • אתם מבצעים את המשימות במסמך הזה אחרי שקיבלתם ממערכת זיהוי האיומים במכונה וירטואלית (VM) ממצא לגבי rootkit במצב ליבה. רשימה של קטגוריות הממצאים הרלוונטיות מופיעה במאמר ממצאים בנושא איומים של רוטקיט במצב ליבה.

  • יש לכם הבנה בכלי שורת פקודה של Linux ובליבת Linux.

מידע על זיהוי איומים במכונות וירטואליות

זיהוי איומים במכונות וירטואליות הוא שירות מובנה של Security Command Center. השירות הזה סורק מכונות וירטואליות כדי לזהות אפליקציות זדוניות פוטנציאליות, כמו תוכנות לכריית מטבעות קריפטוגרפיים, ערכות כלים לרוט במצב ליבה ותוכנות זדוניות שפועלות בסביבות ענן שנפרצו.

התכונה 'זיהוי איומים במכונות וירטואליות' היא חלק מחבילת התכונות לזיהוי איומים ב-Security Command Center, והיא נועדה להשלים את היכולות הקיימות של Event Threat Detection ושל זיהוי איומים בקונטיינר.

מידע על זיהוי איומים במכונות וירטואליות זמין במאמר סקירה כללית על זיהוי איומים במכונות וירטואליות. במאמר בדיקת הממצאים במסוףGoogle Cloud מוסבר איך לראות את הפרטים של ממצא ב-VM Threat Detection.

לפני שמתחילים

כדי לקבל את ההרשאות שדרושות בשביל לראות את כל המשאבים והממצאים ב-Security Command Center ולנהל את מופע Compute Engine המושפע, אתם צריכים לבקש מהאדמין לתת לכם את התפקידים הבאים ב-IAM:

להסבר על מתן תפקידים, ראו איך מנהלים את הגישה ברמת הפרויקט, התיקייה והארגון.

יכול להיות שאפשר לקבל את ההרשאות הנדרשות גם באמצעות תפקידים בהתאמה אישית או תפקידים מוגדרים מראש.

מזהים את מכונת ה-VM המושפעת

  1. הצגת פרטי הממצא
  2. בקטע Affected resource (המשאב שהושפע), בשדה Resource full name (השם המלא של המשאב), לוחצים על הקישור. תצוגת הפרטים של מופע Compute Engine המושפע נפתחת בכרטיסייה חדשה.
  3. מתחברים למופע. מידע נוסף זמין במאמר התחברות למכונות וירטואליות של Linux במסמכי העזרה של Compute Engine.

חיפוש מודולים לא צפויים של ליבת המערכת

נוכחות של מודולים לא צפויים במכונה וירטואלית יכולה להצביע על כך שזיכרון הליבה של המכונה הווירטואלית עלול להיות חשוף לסיכון.

כדי למצוא מודולים לא צפויים של ליבת המערכת:

  1. רשימה של כל מודולי הליבה שנטענו במכונה הווירטואלית:

    lsmod
    cat /proc/modules
    
  2. מציגים את רשימת הערכים של sysfs עבור המודולים שנטענו והמודולים שלא נטענו:

    ls -l /sys/module/
    
  3. משווים את התוצאות של הרשימות האלה עם רשימות ממכונות VM אחרות בפרויקט. חפשו מודולים שמופיעים ב-VM המושפעת אבל לא ב-VM-ים האחרים.

חיפוש מודולים מחוץ לעץ ב-syslog

סימנים לכך שמודול מחוץ לעץ נטען במכונה וירטואלית יכולים להעיד על כך שמודולי ליבה לא טיפוסיים נטענו. אפשר לחפש ב-kernel log buffer וב-syslog הודעות כדי לקבוע אם נטען מודול out-of-tree. ברשומות ביומן, מודול מחוץ לעץ מסומן כטעינה פגומה.

במאגר הנתונים הזמני של היומן השמור בליבה ובהודעות syslog, מחפשים רשומות ביומן שדומות לרשומות הבאות:

MODULE_NAME: loading out-of-tree module taints kernel.
  • מחפשים במאגר הנתונים הזמני של היומן השמור בליבה רשומות ביומן שמציינות את הנוכחות של מודולים מחוץ לעץ:

    sudo dmesg | grep out-of-tree
    
  • חיפוש בכל ההודעות syslog של רשומות ביומן שמציינות נוכחות של מודולים מחוץ לעץ:

    grep "out-of-tree" /var/log/syslog*
    

בדיקה של תיקון באגים בזמן אמת

תיקון בזמן אמת במכונה וירטואלית עלול להפריע לזיהוי איומים במכונה וירטואלית ולהפעיל תוצאות חיוביות כוזבות.

כדי לבדוק אם יש תיקון בזמן אמת, פועלים לפי השלבים הבאים:

  1. בודקים את syslog כדי לראות אם מודול תיקון הבאגים הותקן ואם הרישום ביומן מתבצע. בדרך כלל, תיקון בזמן אמת משנה את קוד הליבה על ידי התקנת ftrace נקודות ליבה.

    sudo grep livepatch /var/log/syslog*
    
  2. מחפשים מודולים חדשים של ליבת המערכת שהותקנו לתיקון ליבה פעילה (בדרך כלל עם הקידומת livepatch):

    sudo lsmod | grep livepatch
    
  3. חיפוש קובצי עדכונים:

    sudo ls -l /sys/kernel/livepatch
    

מידע על תיקון ליבה בזמן ריצה זמין במאמר Livepatch במסמכי התיעוד של ליבת Linux.

בדיקה אם זוהתה פעילות זדונית פוטנציאלית אחרת במכונה הווירטואלית

  1. ב-Security Command Center, מעיינים בפרטים של הממצא של VM Threat Detection שאתם בודקים.
  2. בקטע Affected resource, בשדה Resource full name, לוחצים על החץ לתפריט הנפתח ואז על Show all findings with this resource full name. השאילתה של הממצאים מתעדכנת כך שיוצגו רק ממצאים שקשורים למכונה הווירטואלית הזו.
  3. בודקים אם יש ממצאים שמצביעים על פעילויות פוטנציאליות של כריית מטבע וירטואלי, תוכנות זדוניות, הענקות IAM חריגות ואיומי אבטחה אחרים.

בדיקה אם תוכנת האנטי-וירוס גורמת לממצא חיובי כוזב

תוכנת אנטי-וירוס יכולה להפריע לזיהוי איומים במכונה וירטואלית, ולגרום לזיהוי חיובי שגוי.

בדיקת כל התהליכים שפועלים במערכת

נוכחות של תהליכים לא צפויים יכולה להצביע על כך שממצא הזיהוי של איומים במכונה הווירטואלית תקף, ושהמכונה הווירטואלית נפרצה.

  1. מציגים רשימה של כל התהליכים שפועלים במכונת ה-VM:

    ps -eAf
    
  2. מחפשים תהליכי ניפוי באגים – כמו gdb,‏ strace ו-pstack – שבדרך כלל לא מופעלים במכונה הווירטואלית הזו. תהליכי ניפוי באגים יכולים לרגל אחרי תהליכים אחרים.

  3. מחפשים תהליכים חשודים אחרים במכונה הווירטואלית.

בדיקת ליבת המערכת שהופעלה

בודקים את הליבה שהופעלה כדי לזהות את ליבת Linux:

cat /proc/version

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

משימה נוספת ל-Unexpected system call handler

מבצעים את המשימה הזו אם מתקבלת Defense Evasion: Unexpected system call handler ממצא.

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

משימה נוספת ל-Unexpected interrupt handler

מבצעים את המשימה הזו אם מתקבלת Defense Evasion: Unexpected interrupt handler ממצא.

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

כדי להציג את רשימת המטפלים בהפסקות בזמן אמת, מריצים את הפקודה הבאה:

cat /proc/interrupts

הפלט אמור להיראות כך:

           CPU0       CPU1
  0:         44          0   IO-APIC   0-edge      timer
  1:          9          0   IO-APIC   1-edge      i8042
  4:      17493          0   IO-APIC   4-edge      ttyS0
  8:          0          0   IO-APIC   8-edge      rtc0
  9:          0          0   IO-APIC   9-fasteoi   acpi
 12:          0        152   IO-APIC  12-edge      i8042
 24:         16          0   PCI-MSI 81920-edge      virtio2-config
 25:          0      40194   PCI-MSI 81921-edge      virtio2-inflate
 26:      58528          0   PCI-MSI 81922-edge      virtio2-deflate
 27:          0     966356   PCI-MSI 81923-edge      virtio2-stats
 28:          0          0   PCI-MSI 49152-edge      virtio0-config
 29:          0          0   PCI-MSI 49153-edge      virtio0-control
 30:          0          0   PCI-MSI 49154-edge      virtio0-event
 31:          0     555807   PCI-MSI 49155-edge      virtio0-request
 32:          0          0   PCI-MSI 98304-edge      virtio3-config
 33:        184          0   PCI-MSI 98305-edge      virtio3-input
 34:          0          0   PCI-MSI 65536-edge      virtio1-config
 35:     556203          0   PCI-MSI 65537-edge      virtio1-input.0
 36:     552746          1   PCI-MSI 65538-edge      virtio1-output.0
 37:          1     426036   PCI-MSI 65539-edge      virtio1-input.1
 38:          0     408475   PCI-MSI 65540-edge      virtio1-output.1

משימה נוספת ל-Unexpected processes in runqueue

אם קיבלתם ממצא Defense Evasion: Unexpected processes in runqueue, מבצעים את השלבים הבאים. הקטע הזה יעזור לכם לאסוף נקודות נתונים נוספות כדי לבדוק את הממצאים. יכול להיות שנקודות הנתונים האלה לא יצביעו ישירות על בעיה שקשורה לתוכנות זדוניות.

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

  1. הצגת פרטים על משך הזמן שכל תהליך פעיל מבלה בכל מעבד. כך תוכלו לראות אם יחידת עיבוד מרכזית (CPU) מסוימת עמוסה מאוד. אפשר לקשר את התוצאות להפסקות שמוצמדות למעבד מ-/proc/interrupts.

    cat /proc/schedstat
    

    מידע נוסף על הפקודה הזו זמין במאמר Scheduler Statistics במסמכי התיעוד של ליבת Linux.

  2. מפרטים את כל המשימות הנוכחיות שניתן להפעיל ואת הפרטים לגבי מעברים בין הקשרים לכל מעבד.

    cat /proc/sched_debug
    

    הפלט אמור להיראות כך:

    Sched Debug Version: v0.11, 5.4.0-1081-gke #87-Ubuntu
    ktime                                   : 976187427.733850
    sched_clk                               : 976101974.761097
    cpu_clk                                 : 976101973.335113
    jiffies                                 : 4538939132
    sched_clock_stable()                    : 1
    
    sysctl_sched
      .sysctl_sched_latency                    : 12.000000
      .sysctl_sched_min_granularity            : 1.500000
      .sysctl_sched_wakeup_granularity         : 2.000000
      .sysctl_sched_child_runs_first           : 0
      .sysctl_sched_features                   : 2059067
      .sysctl_sched_tunable_scaling            : 1 (logarithmic)
    
    cpu#0, 2199.998 MHz
      .nr_running                    : 0
      .nr_switches                   : 16250401
      .nr_load_updates               : 0
      .nr_uninterruptible            : 12692
      .next_balance                  : 4538.939133
      .curr->pid                     : 0
      .clock                         : 976101971.732857
      .clock_task                    : 976101971.732857
      .avg_idle                      : 880408
      .max_idle_balance_cost         : 500000
    
    runnable tasks:
     S           task   PID         tree-key  switches  prio     wait-time             sum-exec        sum-sleep
    -----------------------------------------------------------------------------------------------------------
     S        systemd     1     51740.602172    326778   120         0.000000    165741.786097         0.000000 0 0 /init.scope
     S       kthreadd     2   1482297.917240      1361   120         0.000000       112.028205         0.000000 0 0 /
     I      rcu_sched    11   1482642.606136   1090339   120         0.000000     17958.156471         0.000000 0 0 /
     S        cpuhp/1    15       537.058588         8   120         0.000000         2.275927         0.000000 0 0 /
     S  idle_inject/1    16        -2.994953         3    49         0.000000         0.012780         0.000000 0 0 /
     S    migration/1    17         0.000000    245774     0         0.000000      5566.508869         0.000000 0 0 /
     S    ksoftirqd/1    18   1482595.656315     47766   120         0.000000      1235.099147         0.000000 0 0 /
     I   kworker/1:0H    20       536.961474         5   100         0.000000         0.043908         0.000000 0 0 /
     S      kdevtmpfs    21     11301.343465       177   120         0.000000         3.195291         0.000000 0 0 /
     I          netns    22         6.983329         2   100         0.000000         0.021870         0.000000 0 0 /
     Srcu_tasks_kthre    23        10.993528         2   120         0.000000         0.010200         0.000000 0 0 /
     S        kauditd    24   1482525.828948       319   120         0.000000        14.489652         0.000000 0 0 /
    
  3. מחפשים את הדברים הבאים:

    • שמות של תהליכים שפועלים.
    • מספר החלפות ההקשר לכל CPU. בודקים אם התהליך גורם למעט מדי או ליותר מדי מעברים במעבד.
    • זמן CPU (מעבד) שהושקע (הזמן שבו המעבד לא היה במצב סרק).

דוגמה לבדיקה עם ערכת השורש Diamorphine

בקטע הזה מוצגת בדיקה של מכונה וירטואלית שבה מותקן רוטקיט Diamorphine. ‫Diamorphine הוא מודול ליבה (LKM) פופולרי שאפשר לטעון. הרוטקיט הזה מפעיל את הקטגוריות הבאות של ממצאים:

  • Defense Evasion: Unexpected system call handler
  • Defense Evasion: Unexpected kernel modules
  • Defense Evasion: Unexpected kernel read-only data modification

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

השלבים שבוצעו לבדיקה והתסמינים שנצפו במכונה הווירטואלית הם:

  1. חיפוש syslog של כל מודולי הליבה מחוץ לעץ שנטענו.

    1. חיפוש במאגר היומן של ליבת המערכת:

      sudo dmesg | grep out-of-tree
      

      פלט:

      diamorphine: loading out-of-tree module taints kernel.
      
    2. חיפוש בהודעות syslog:

      grep "out-of-tree" /var/log/syslog*
      

      פלט:

      /var/log/syslog: diamorphine: loading out-of-tree module taints kernel.
      
  2. מחפשים syslog כשלים באימות של מודולים (לא זמין בכל הפצות Linux).

    1. חיפוש במאגר היומן של ליבת המערכת:

      sudo dmesg | grep "module verification failed"
      

      פלט:

      diamorphine: module verification failed: signature and/or required key missing - tainting kernel
      
    2. חיפוש בהודעות syslog:

      sudo grep "module verification failed" /var/log/syslog*
      

      פלט:

      /var/log/syslog: diamorphine: module verification failed: signature and/or required key missing - tainting kernel
      
  3. מוודאים שהמודול מוסתר מהפקודות /proc/modules ו-lsmod.

    sudo grep diamorphine /proc/modules
    sudo lsmod | grep diamorphine
    

    לא הוצגו תוצאות.

  4. מוודאים שיש רשומה למודול ב-sysfs.

    sudo cat /sys/module/diamorphine/coresize
    

    פלט:

    16384
    
  5. קבלת טבלת קריאות המערכת לארכיטקטורה:

    sudo ausyscall --dump
    

    פלט:

    Using x86_64 syscall table:
    0       read
    1       write
    2       open
    3       close
    

    ביצוע ביקורת לאיתור אנומליות בקריאות למערכת – כמו kill ו-getdents – שבדרך כלל נעשה בהן שימוש לרמאות על ידי ערכות Rootkit.

  6. כדי לבדוק אם בוצעו שינויים לא מורשים בטיפול בשיחות המערכת, מבצעים ביקורת על שיחות המערכת ובודקים אם יש התנהגויות חריגות. ההתנהגויות האלה משתנות בהתאם לקריאה למערכת.

    קריאת המערכת שנפרצת בדרך כלל היא קריאת kill. אפשר לבדוק אם בוצע עקיפה של קריאת המערכת kill. בדוגמה הבאה, בוצע ביקורת על קריאת המערכת kill.

    1. מתקינים את auditd ומתבוננים בהתנהגות של המכונה הווירטואלית בלי ערכת השורש Diamorphine:

      $ sudo apt-get update && sudo apt-get install auditd
      $ # Add audit rules for specific system calls
      $ sudo echo "-a exit,always -F arch=b64 -S kill -k audit_kill" >> /etc/audit/rules.d/audit.rules
      $  sudo /etc/init.d/auditd restart
      Restarting auditd (via systemctl): auditd.service.
      
      $ # Behavior observed without rootkit
      $ sleep 600 &
      [1] 1119
      $ sudo kill -9 1119
      $ sudo ausearch -k audit_kill | grep -A 3 "pid=1119"
      type=OBJ_PID msg=audit(1677517839.523:198): opid=1119 oauid=1001 ouid=0 oses=1 obj=unconfined ocomm="sleep"
      type=SYSCALL msg=audit(1677517839.523:198): arch=c000003e syscall=62 success=yes exit=0 a0=45f a1=9 a2=0 a3=7f61c64b2ac0 items=0 ppid=1034 pid=1035 auid=1001 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0
      tty=pts0 ses=1 comm="bash" exe="/usr/bin/bash" subj=unconfined key="audit_kill"
      $ sleep 600 &
      [1] 1087
      $ sudo kill -31 1087
      $ sudo ausearch -k audit_kill | grep -A 3 "pid=1087"
      type=OBJ_PID msg=audit(1677517760.844:168): opid=1087 oauid=1001 ouid=0 oses=1 obj=unconfined ocomm="sleep"
      type=SYSCALL msg=audit(1677517760.844:168): arch=c000003e syscall=62 success=yes exit=0 a0=43f a1=1f a2=0 a3=7f61c64b2ac0 items=0 ppid=1034 pid=1035 auid=1001 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0        ses=1 comm="bash" exe="/usr/bin/bash" subj=unconfined key="audit_kill"
      

      בשלב הזה בבדיקה, ערכת השורש Diamorphine הותקנה. בשלבים הבאים מוצג אופן הפעולה של המכונה הווירטואלית אחרי ההתקנה של ערכת ה-rootkit.

    2. מוודאים שרשומה ביומן הביקורת של האות לא מופיעה יותר אחרי התקנת ערכת השורש Diamorphine:

      $ sudo ausearch -k audit_kill | grep -A 3 "pid=1158"
      $ sleep 600 &
      [2] 1167
      
    3. בודקים את הפרטים של האות ברשומה ביומן הביקורת. בדוגמה הזו, למרות שהאות הספציפי הזה לא נחטף לחלוטין על ידי ערכת ה-rootkit, מידע על תהליך ההפעלה זמין.

      $ sudo kill -9 1167
      $ sudo ausearch -k audit_kill | grep -A 3 "pid=1167"
      type=OBJ_PID msg=audit(1677518008.586:237): opid=1167 oauid=1001 ouid=0 oses=1 obj=unconfined ocomm="sleep"
      type=SYSCALL msg=audit(1677518008.586:237): arch=c000003e syscall=62 success=yes exit=0 a0=48f a1=9 a2=0 a3=7f61c64b2ac0 items=0 ppid=1034 pid=1035 auid=1001 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0
      tty=pts0 ses=1 comm="bash" exe="/usr/bin/bash" subj=unconfined key="audit_kill"
      

ניפוי באגים בסקריפט לאיסוף נתונים

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

$ cat kprot.sh
#!/bin/bash

echo "Boot command line"
cat /proc/cmdline
echo "=================================================="
echo "Loaded modules"
cat /proc/modules
echo "=================================================="
echo "Current tracer"
cat /sys/kernel/debug/tracing/current_tracer
echo "=================================================="
echo "Tracing event enable"
cat /sys/kernel/debug/tracing/events/enable
echo "=================================================="
echo "Tracing sub events enable"
for en in `find /sys/kernel/debug/tracing/events/*/enable`; do printf "\b$en\n"; cat $en; done
echo "=================================================="
echo "IP table rules"
iptables -L
echo "=================================================="
echo "Ftrace list"
cat /sys/kernel/debug/tracing/enabled_functions
echo "=================================================="
echo "Kprobes enabled"
cat /sys/kernel/debug/kprobes/enabled
echo "=================================================="
echo "Kprobes list"
cat /sys/kernel/debug/kprobes/list
echo "=================================================="
echo "Kprobes blocklist"
cat /sys/kernel/debug/kprobes/blacklist
echo "=================================================="
echo "BPF trace"
sudo apt update && sudo apt-get update && sudo apt-get install bpftrace
bpftrace -l
echo "=================================================="
echo "BPF prog list"
sudo apt update && sudo apt install linux-tools-`uname -r`
bpftool prog
echo "=================================================="

המאמרים הבאים