איסוף יומנים של Qualys Virtual Scanner
מנתח הנתונים הזה ממיר יומנים גולמיים של Qualys Virtual Scanner בפורמט JSON לפורמט מובנה שתואם ל-UDM של Google Security Operations. הוא מחלץ שדות רלוונטיים כמו פרטי נכסים, פרטי סריקה ונקודות חולשה שזוהו, וממפה אותם לשדות UDM תואמים כדי לייצג ולנתח אותם באופן עקבי.
לפני שמתחילים
ודאו שאתם עומדים בדרישות המוקדמות הבאות:
- מכונה של Google Security Operations.
- גישה מיוחדת אל Google Cloud.
- גישה מיוחדת ל-Qualys.
הפעלת ממשקי ה-API הנדרשים:
- נכנסים למסוף Google Cloud .
- עוברים אל APIs & Services (ממשקי API ושירותים) > Library (ספרייה).
- מחפשים את ממשקי ה-API הבאים ומפעילים אותם:
- Cloud Functions API
- Cloud Scheduler API
- Cloud Pub/Sub (נדרש כדי ש-Cloud Scheduler יפעיל פונקציות)
יצירת קטגוריית אחסון ב- Google Cloud
- נכנסים למסוף Google Cloud .
נכנסים לדף Cloud Storage Buckets.
לוחצים על יצירה.
מגדירים את הקטגוריה:
- Name: מזינים שם ייחודי שעומד בדרישות לשמות של קטגוריות (לדוגמה, qualys-vscanner-bucket).
- Choose where to store your data: בוחרים מיקום.
- Choose a storage class for your data: בוחרים סוג אחסון (storage class) שמוגדר כברירת מחדל לקטגוריה, או בוחרים ב-Autoclass לניהול אוטומטי של סוג האחסון.
- Choose how to control access to objects: בוחרים לא לאכוף מניעת גישה ציבורית, ובוחרים מודל בקרת גישה לאובייקטים של הקטגוריה.
- סוג האחסון (storage class): בוחרים בהתאם לצרכים (לדוגמה, Standard).
לוחצים על יצירה.
יצירת חשבון שירות ב-Google Cloud
- נכנסים לדף IAM & Admin > Service Accounts.
- יוצרים חשבון שירות חדש.
- נותנים לו שם תיאורי (לדוגמה, qualys-user).
- מקצים לחשבון השירות את התפקיד אדמין של אובייקטים באחסון בקטגוריה של Cloud Storage שיצרתם בשלב הקודם.
- מקצים לחשבון השירות את התפקיד Cloud Functions Invoker.
- יוצרים מפתח SSH לחשבון השירות.
- מורידים קובץ מפתח בפורמט JSON לחשבון השירות. חשוב לשמור על הקובץ הזה מאובטח.
אופציונלי: יצירת משתמש API ייעודי ב-Qualys
- נכנסים למסוף Qualys.
- מעבר לדף משתמשים
- לוחצים על חדש > משתמש.
- מזינים את המידע הכללי שנדרש לגבי המשתמש.
- לוחצים על הכרטיסייה תפקיד משתמש.
- מוודאים שהתיבה API Access מסומנת בתפקיד.
- לוחצים על Save.
זיהוי כתובת ה-URL הספציפית של Qualys API
אפשרות 1
מזהים את כתובות ה-URL כמו שמופיע בזיהוי הפלטפורמה.
אפשרות 2
- נכנסים למסוף Qualys.
- עוברים אל עזרה > מידע כללי.
- גוללים כדי לראות את המידע הזה בקטע "מרכז תפעול אבטחה (SOC)".
- מעתיקים את כתובת ה-URL של Qualys API.
הגדרת הפונקציה של Cloud Functions
- נכנסים לדף Cloud Functions במסוף Google Cloud .
- לוחצים על Create Function.
מגדירים את הפונקציה:
- Name: נותנים שם לפונקציה (לדוגמה, fetch-qualys-vscanner).
- Region: בוחרים אזור שקרוב לקטגוריה.
- טריגר: בוחרים טריגר HTTP לפי הצורך, או Cloud Pub/Sub להפעלה מתוזמנת.
- אימות: אבטחה באמצעות אימות.
- כותבים את הקוד באמצעות עורך ישיר:
```python from google.cloud import storage import requests import base64 import json # Google Cloud Storage Configuration BUCKET_NAME = "<bucket-name>" FILE_NAME = "qualys_virtual_scanners.json" # Qualys API Credentials QUALYS_USERNAME = "qualys-username" QUALYS_PASSWORD = "<qualys-password>" QUALYS_BASE_URL = "https://<qualys_base_url>" # for example, https://qualysapi.qualys.com def fetch_virtual_scanners(): """Fetch Virtual Scanner details from Qualys.""" auth = base64.b64encode(f"{QUALYS_USERNAME}:{QUALYS_PASSWORD}".encode()).decode() headers = { "Authorization": f"Basic {auth}", "Content-Type": "application/xml" } url = f"{QUALYS_BASE_URL}/api/2.0/fo/scanner/" payload = { "action": "list", "scanner_type": "virtual" } response = requests.post(url, headers=headers, data=payload) response.raise_for_status() return response.text # Qualys API returns XML data def upload_to_gcs(data): """Upload data to Google Cloud Storage.""" client = storage.Client() bucket = client.get_bucket(BUCKET_NAME) blob = bucket.blob(FILE_NAME) blob.upload_from_string(data, content_type="application/xml") def main(request): """Cloud Function entry point.""" try: scanners = fetch_virtual_scanners() upload_to_gcs(scanners) return "Qualys Virtual Scanners data uploaded to Cloud Storage successfully!" except Exception as e: return f"An error occurred: {e}", 500 ```אחרי שמסיימים את ההגדרה, לוחצים על Deploy.
הגדרת Cloud Scheduler
- נכנסים לדף Cloud Scheduler במסוף Google Cloud .
- לוחצים על Create Job.
מגדירים את המשימה:
- Name: נותנים שם למשימה (לדוגמה, trigger-fetch-qualys-vscanner).
- תדירות: משתמשים בתחביר cron כדי לציין את לוח הזמנים (לדוגמה, 0 0 * * * כדי להגדיר תדירות יומית בחצות).
- אזור זמן: הגדירו את אזור הזמן המועדף עליכם.
- Trigger Type (סוג הטריגר): בוחרים באפשרות HTTP.
- Trigger URL: מזינים את כתובת ה-URL של הפונקציה של Cloud Functions (מופיעה בפרטי הפונקציה אחרי הפריסה).
- Method (שיטה): בוחרים באפשרות POST.
יוצרים את המשימה.
הגדרת פידים
כדי להגדיר פיד:
- עוברים אל הגדרות > ניהול נתונים > פידים. אם אתם משתמשים בפלטפורמה של SIEM בלבד, עוברים אל הגדרות > פידים.
- לוחצים על הוספת פיד חדש.
- בדף הבא, לוחצים על הגדרת פיד יחיד.
- בשדה Feed name, מזינים שם לפיד, לדוגמה Qualys Virtual Scanner Logs.
- בוחרים באפשרות Google Cloud Storage V2 בתור סוג המקור.
- בוחרים באפשרות Qualys Virtual Scanner בתור Log type.
- לוחצים על הבא.
מציינים ערכים לפרמטרים הבאים של הקלט:
- Storage Bucket URI: ה-URI של קטגוריית האחסון במקור ב- Google Cloud .
- אפשרות מחיקת המקור: בוחרים את אפשרות המחיקה הרצויה.
לוחצים על הבא.
בודקים את הגדרות הפיד החדש במסך סיום ולוחצים על שליחה.
טבלת מיפוי UDM
| שדה ביומן | מיפוי UDM | Logic (פונקציה לוגית) |
|---|---|---|
| ASSET_ID | entity.entity.asset.asset_id | מיפוי ישיר מהשדה ASSET_ID. |
| CLOUD_PROVIDER_TAGS.CLOUD_TAG.NAME | entity.relations.entity.resource.attribute.labels.key | מיפוי ישיר מהשדה CLOUD_PROVIDER_TAGS.CLOUD_TAG.NAME. |
| CLOUD_PROVIDER_TAGS.CLOUD_TAG.VALUE | entity.relations.entity.resource.attribute.labels.value | מיפוי ישיר מהשדה CLOUD_PROVIDER_TAGS.CLOUD_TAG.VALUE. |
| CLOUD_RESOURCE_ID | entity.relations.entity.resource.id | מיפוי ישיר מהשדה CLOUD_RESOURCE_ID. |
| DETECTION_LIST.DETECTION.FIRST_FOUND_DATETIME | entity.metadata.threat.first_discovered_time | מיפוי ישיר מהשדה DETECTION_LIST.DETECTION.FIRST_FOUND_DATETIME, שהומר לחותמת זמן. |
| DETECTION_LIST.DETECTION.FIRST_REOPENED_DATETIME | entity.metadata.threat.detection_fields.value | מיפוי ישיר מהשדה DETECTION_LIST.DETECTION.FIRST_REOPENED_DATETIME. המפתח מקודד כ-"FIRST_REOPENED_DATETIME". |
| DETECTION_LIST.DETECTION.IS_DISABLED | entity.metadata.threat.detection_fields.value | מיפוי ישיר מהשדה DETECTION_LIST.DETECTION.IS_DISABLED. המפתח מקודד כ-"IS_DISABLED". |
| DETECTION_LIST.DETECTION.LAST_FIXED_DATETIME | entity.metadata.threat.detection_fields.value | מיפוי ישיר מהשדה DETECTION_LIST.DETECTION.LAST_FIXED_DATETIME. המפתח מקודד כ-"LAST_FIXED_DATETIME". |
| DETECTION_LIST.DETECTION.LAST_FOUND_DATETIME | entity.metadata.threat.detection_fields.value | מיפוי ישיר מהשדה DETECTION_LIST.DETECTION.LAST_FOUND_DATETIME. המפתח מקודד כ-"LAST_FOUND_DATETIME". |
| DETECTION_LIST.DETECTION.LAST_PROCESSED_DATETIME | entity.metadata.threat.detection_fields.value | מיפוי ישיר מהשדה DETECTION_LIST.DETECTION.LAST_PROCESSED_DATETIME. המפתח מקודד כ-"LAST_PROCESSED_DATETIME". |
| DETECTION_LIST.DETECTION.LAST_REOPENED_DATETIME | entity.metadata.threat.detection_fields.value | מיפוי ישיר מהשדה DETECTION_LIST.DETECTION.LAST_REOPENED_DATETIME. המפתח מקודד כ-"LAST_REOPENED_DATETIME". |
| DETECTION_LIST.DETECTION.LAST_TEST_DATETIME | entity.metadata.threat.detection_fields.value | מיפוי ישיר מהשדה DETECTION_LIST.DETECTION.LAST_TEST_DATETIME. המפתח מקודד כ-"LAST_TEST_DATETIME". |
| DETECTION_LIST.DETECTION.LAST_UPDATE_DATETIME | entity.metadata.threat.detection_fields.value | מיפוי ישיר מהשדה DETECTION_LIST.DETECTION.LAST_UPDATE_DATETIME. המפתח מקודד כ-"LAST_UPDATE_DATETIME". |
| DETECTION_LIST.DETECTION.PORT | entity.metadata.threat.detection_fields.value | מיפוי ישיר מהשדה DETECTION_LIST.DETECTION.PORT. המפתח מקודד כ-"PORT". |
| DETECTION_LIST.DETECTION.PROTOCOL | entity.metadata.threat.detection_fields.value | מיפוי ישיר מהשדה DETECTION_LIST.DETECTION.PROTOCOL. המפתח מקודד כ-"PROTOCOL". |
| DETECTION_LIST.DETECTION.QID | entity.metadata.threat.detection_fields.value | מיפוי ישיר מהשדה DETECTION_LIST.DETECTION.QID. המפתח מקודד כ-"QID". |
| DETECTION_LIST.DETECTION.RESULTS | entity.metadata.threat.summary | מיפוי ישיר מהשדה DETECTION_LIST.DETECTION.RESULTS. |
| DETECTION_LIST.DETECTION.SEVERITY | entity.metadata.threat.severity_details | מיפוי ישיר מהשדה DETECTION_LIST.DETECTION.SEVERITY. |
| DETECTION_LIST.DETECTION.SSL | entity.metadata.threat.detection_fields.value | מיפוי ישיר מהשדה DETECTION_LIST.DETECTION.SSL. המפתח מקודד כ-"SSL". |
| DETECTION_LIST.DETECTION.STATUS | entity.metadata.threat.detection_fields.value | מיפוי ישיר מהשדה DETECTION_LIST.DETECTION.STATUS. המפתח מקודד כ-"STATUS". |
| DETECTION_LIST.DETECTION.TIMES_FOUND | entity.metadata.threat.detection_fields.value | מיפוי ישיר מהשדה DETECTION_LIST.DETECTION.TIMES_FOUND. המפתח מקודד כ-"TIMES_FOUND". |
| DETECTION_LIST.DETECTION.TIMES_REOPENED | entity.metadata.threat.detection_fields.value | מיפוי ישיר מהשדה DETECTION_LIST.DETECTION.TIMES_REOPENED. המפתח מקודד כ-"TIMES_REOPENED". |
| DETECTION_LIST.DETECTION.TYPE | entity.metadata.threat.severity | מופה מהשדה DETECTION_LIST.DETECTION.TYPE. אם הערך הוא "info" (לא תלוי-רישיות), הוא ממופה ל-"INFORMATIONAL". אחרת, הוא מתווסף כשדה זיהוי עם המפתח TYPE. |
| DETECTION_LIST.DETECTION.UNIQUE_VULN_ID | entity.metadata.threat.detection_fields.value | מיפוי ישיר מהשדה DETECTION_LIST.DETECTION.UNIQUE_VULN_ID. המפתח מקודד כ-"UNIQUE_VULN_ID". |
| DNS | entity.entity.asset.hostname | ממופה מהשדה DNS אם השדה DNS_DATA.HOSTNAME ריק. |
| DNS_DATA.HOSTNAME | entity.entity.asset.hostname | מיפוי ישיר מהשדה DNS_DATA.HOSTNAME. |
| EC2_INSTANCE_ID | entity.relations.entity.resource.product_object_id | מיפוי ישיר מהשדה EC2_INSTANCE_ID. |
| מזהה | entity.entity.asset.product_object_id | מיפוי ישיר מהשדה ID. |
| מזהה | entity.metadata.product_entity_id | מיפוי ישיר מהשדה ID. |
| קניין רוחני (IP) | entity.entity.ip | מיפוי ישיר מהשדה IP. |
| LAST_SCAN_DATETIME | entity.metadata.interval.start_time | מיפוי ישיר מהשדה LAST_SCAN_DATETIME, שהומר לחותמת זמן. |
| METADATA.AZURE.ATTRIBUTE.NAME | entity.relations.entity.resource.attribute.labels.key | מיפוי ישיר מהשדה METADATA.AZURE.ATTRIBUTE.NAME. |
| METADATA.AZURE.ATTRIBUTE.VALUE | entity.relations.entity.resource.attribute.labels.value | מיפוי ישיר מהשדה METADATA.AZURE.ATTRIBUTE.VALUE. |
| מערכת הפעלה | entity.entity.asset.platform_software.platform | מופה מהשדה OS. אם הערך מכיל את המילה "windows" (לא תלוי-רישיות), הוא ממופה ל-"WINDOWS". אם הוא מכיל את המילה "Linux" (לא תלוי-רישיות), הוא ממופה ל-"LINUX". |
| TAGS.TAG.NAME | entity.relations.entity.resource.attribute.labels.key | מיפוי ישיר מהשדה TAGS.TAG.NAME. |
| TAGS.TAG.TAG_ID | entity.relations.entity.resource.attribute.labels.value | מופה מהשדה TAGS.TAG.TAG_ID. הערך מתחיל ב-"TAG_ID: ". |
| entity.metadata.collected_timestamp | חותמת הזמן של הרשומה ביומן. | |
| entity.metadata.entity_type | נקבע על סמך הנוכחות של השדה IP. אם IP קיים, הוא מוגדר כ-"IP_ADDRESS". אחרת, הוא מוגדר כ-"ASSET". |
|
| entity.metadata.interval.end_time | הערך של חותמת הזמן מקודד באופן קשיח לערך גדול מאוד (253402300799 שניות). | |
| entity.metadata.product_name | מקודד באופן קשיח ל-"QUALYS_VIRTUAL_SCANNER". | |
| entity.metadata.vendor_name | מקודד באופן קשיח ל-"QUALYS_VIRTUAL_SCANNER". | |
| entity.relations.entity.resource.resource_type | אם הערך של CLOUD_SERVICE הוא "VM", הוא מוגדר כ-"VIRTUAL_MACHINE". |
|
| entity.relations.entity_type | מקודד באופן קשיח ל-"RESOURCE". | |
| entity.relations.relationship | מקודד באופן קשיח ל-"MEMBER". |
יומן שינויים
הצגת יומן השינויים של המנתח הזה
הבעיה עדיין לא נפתרה? קבלת תשובות מחברי הקהילה וממומחי Google SecOps.