Erfassen von benutzerdefinierten IOC-Logs von Mandiant Threat Intelligence

Unterstützt in:

In diesem Dokument wird beschrieben, wie Sie benutzerdefinierte IOC-Daten von Mandiant Threat Intelligence mit Google Cloud Storage V2 in Google Security Operations aufnehmen.

Mandiant Threat Intelligence bietet kontextreiche Kompromittierungsindikatoren (indicators of compromise, IOCs), darunter IP-Adressen, Domains, URLs, Datei-Hashes und E-Mail-Adressen. Die Plattform liefert Threat Intelligence auf Grundlage von Incident-Response-Untersuchungen an vorderster Front, sodass Sicherheitsteams Bedrohungen, die auf ihr Unternehmen abzielen, erkennen und priorisieren können.

Hinweis

Prüfen Sie, ob die folgenden Voraussetzungen erfüllt sind:

  • Eine Google SecOps-Instanz
  • Ein GCP-Projekt mit aktivierter Cloud Storage API
  • Berechtigungen zum Erstellen und Verwalten von GCS-Buckets
  • Berechtigungen zum Verwalten von IAM-Richtlinien für GCS-Buckets
  • Berechtigungen zum Erstellen von Cloud Run-Diensten, Pub/Sub-Themen und Cloud Scheduler-Jobs
  • Aktives Mandiant Advantage Threat Intelligence-Abo
  • Privilegierter Zugriff auf das Mandiant Advantage-Portal

Google Cloud Storage-Bucket erstellen

  1. Gehen Sie zur Google Cloud Console.
  2. Wählen Sie Ihr Projekt aus oder erstellen Sie ein neues.
  3. Rufen Sie im Navigationsmenü Cloud Storage > Buckets auf.
  4. Klicken Sie auf Bucket erstellen.
  5. Geben Sie die folgenden Konfigurationsdetails an:

    Einstellung Wert
    Bucket benennen Geben Sie einen global eindeutigen Namen ein, z. B. mandiant-ioc-logs.
    Standorttyp Wählen Sie die Option aus, die am besten zu Ihren Anforderungen passt (Region, Dual-Region, Multi-Region).
    Standort Wählen Sie den Standort aus, z. B. us-central1.
    Speicherklasse Standard (empfohlen für Logs, auf die häufig zugegriffen wird)
    Zugriffskontrolle Einheitlich (empfohlen)
    Schutzmaßnahmen Optional: Objektversionsverwaltung oder Aufbewahrungsrichtlinie aktivieren
  6. Klicken Sie auf Erstellen.

Mandiant Advantage-Anmeldedaten erfassen

Mandiant-Website-URL abrufen

  1. Melden Sie sich in Ihrer Mandiant Advantage-Instanz an.
  2. Notieren Sie sich die URL Ihrer Website aus der Adressleiste des Browsers.
    • Die URL lautet: https://advantage.mandiant.com

API-Anmeldedaten erstellen

  1. Melden Sie sich in Mandiant Advantage an.
  2. Gehen Sie zu Einstellungen.
  3. Scrollen Sie zu API-Zugriff und ‑Schlüssel oder wählen Sie die Option im Navigationsmenü aus.
  4. Klicken Sie auf Schlüssel-ID und Secret abrufen.
  5. Kopieren und speichern Sie die API-Anmeldedaten sicher:
    • Schlüssel-ID: Kopieren Sie diesen Wert (auch als API-Schlüssel-ID oder öffentlicher Schlüssel bezeichnet).
    • Schlüssel-Secret: Kopieren Sie diesen Wert (auch als API-Secret oder privater Schlüssel bezeichnet).

Berechtigungen prüfen

So prüfen Sie, ob das Konto die erforderlichen Berechtigungen hat:

  1. Melden Sie sich in Mandiant Advantage an.
  2. Gehen Sie zu Einstellungen.
  3. Prüfen Sie Ihre Nutzerberechtigungen unter Nutzerinformationen.
  4. Prüfen Sie, ob Sie Zugriff auf das Modul Threat Intelligence haben.
  5. Wenn Sie keine Threat Intelligence-Daten sehen, wenden Sie sich an Ihren Mandiant-Administrator, um die entsprechenden Berechtigungen zu erhalten.

API-Zugriff testen

  • Testen Sie Ihre Anmeldedaten, bevor Sie mit der Integration fortfahren:

    # Replace with your actual credentials
    API_KEY_ID="your-key-id"
    API_SECRET="your-key-secret"
    API_BASE="https://api.intelligence.mandiant.com"
    
    # Get OAuth token
    TOKEN=$(curl -s -X POST "${API_BASE}/token" \
        -H "Content-Type: application/x-www-form-urlencoded" \
        -d "grant_type=client_credentials" \
        -u "${API_KEY_ID}:${API_SECRET}" | jq -r '.access_token')
    
    # Test API access
    curl -v -H "Authorization: Bearer ${TOKEN}" \
        "${API_BASE}/v4/indicator?limit=1"
    

Wenn der Test erfolgreich ist, sollten Sie eine JSON-Antwort mit Indikatordaten erhalten. Wenn Sie eine Fehlermeldung erhalten:

  • HTTP 401: Prüfen Sie, ob die API-Schlüssel-ID und das Secret korrekt sind.
  • HTTP 403: Prüfen, ob das Konto Threat Intelligence-Berechtigungen hat
  • HTTP 404: Prüfen Sie, ob die API-Basis-URL korrekt ist.

Dienstkonto für Cloud Run-Funktion erstellen

Die Cloud Run-Funktion benötigt ein Dienstkonto mit Berechtigungen zum Schreiben in den GCS-Bucket und zum Aufrufen durch Pub/Sub.

Dienstkonto erstellen

  1. Wechseln Sie in der GCP Console zu IAM & Verwaltung > Dienstkonten.
  2. Klicken Sie auf Dienstkonto erstellen.
  3. Geben Sie die folgenden Konfigurationsdetails an:
    • Name des Dienstkontos: Geben Sie mandiant-ioc-collector-sa ein (z. B. mandiant-ioc-collector-sa).
    • Beschreibung des Dienstkontos: Geben Sie Service account for Cloud Run function to collect Mandiant IOC logs ein.
  4. Klicken Sie auf Erstellen und fortfahren.
  5. Fügen Sie im Abschnitt Diesem Dienstkonto Zugriff auf das Projekt erteilen die folgenden Rollen hinzu:
    1. Klicken Sie auf Rolle auswählen.
    2. Suchen Sie nach Storage-Objekt-Administrator und wählen Sie die Rolle aus.
    3. Klicken Sie auf + Weitere Rolle hinzufügen.
    4. Suchen Sie nach Cloud Run Invoker und wählen Sie die Rolle aus.
    5. Klicken Sie auf + Weitere Rolle hinzufügen.
    6. Suchen Sie nach Cloud Functions Invoker und wählen Sie die Rolle aus.
  6. Klicken Sie auf Weiter.
  7. Klicken Sie auf Fertig.

Diese Rollen sind für Folgendes erforderlich: - Storage-Objektadministrator: Logs in GCS-Bucket schreiben und Statusdateien verwalten - Cloud Run Invoker: Pub/Sub darf die Funktion aufrufen - Cloud Functions Invoker: Funktionsaufruf zulassen

IAM-Berechtigungen für GCS-Bucket erteilen

Gewähren Sie dem Dienstkonto Schreibberechtigungen für den GCS-Bucket:

  1. Rufen Sie Cloud Storage > Buckets auf.
  2. Klicken Sie auf den Namen Ihres Buckets, z. B. mandiant-ioc-logs.
  3. Wechseln Sie zum Tab Berechtigungen.
  4. Klicken Sie auf Zugriff erlauben.
  5. Geben Sie die folgenden Konfigurationsdetails an:
    • Hauptkonten hinzufügen: Geben Sie die E-Mail-Adresse des Dienstkontos ein (z. B. mandiant-ioc-collector-sa@PROJECT_ID.iam.gserviceaccount.com).
    • Rollen zuweisen: Wählen Sie Storage-Objekt-Administrator aus.
  6. Klicken Sie auf Speichern.

Pub/Sub-Thema erstellen

Erstellen Sie ein Pub/Sub-Thema, in dem Cloud Scheduler veröffentlicht und das von der Cloud Run-Funktion abonniert wird.

  1. Rufen Sie in der GCP Console Pub/Sub > Themen auf.
  2. Klicken Sie auf Thema erstellen.
  3. Geben Sie die folgenden Konfigurationsdetails an:
    • Themen-ID: Geben Sie mandiant-ioc-trigger ein (z. B. mandiant-ioc-trigger).
    • Andere Einstellungen als Standardeinstellungen beibehalten
  4. Klicken Sie auf Erstellen.

Cloud Run-Funktion zum Erfassen von Logs erstellen

Die Cloud Run-Funktion wird durch Pub/Sub-Nachrichten von Cloud Scheduler ausgelöst, um IOC-Daten von der Mandiant Threat Intelligence API abzurufen und in GCS zu schreiben.

  1. Rufen Sie in der GCP Console Cloud Run auf.
  2. Klicken Sie auf Dienst erstellen.
  3. Wählen Sie Funktion aus, um eine Funktion mit einem Inline-Editor zu erstellen.
  4. Geben Sie im Abschnitt Konfigurieren die folgenden Konfigurationsdetails an:

    Einstellung Wert
    Dienstname mandiant-ioc-collector (z. B. mandiant-ioc-collector)
    Region Wählen Sie die Region aus, die Ihrem GCS-Bucket entspricht (z. B. us-central1).
    Laufzeit Wählen Sie Python 3.12 oder höher aus.
  5. Im Abschnitt Trigger (optional):

    1. Klicken Sie auf + Trigger hinzufügen.
    2. Wählen Sie Cloud Pub/Sub aus.
    3. Wählen Sie unter Cloud Pub/Sub-Thema auswählen das Pub/Sub-Thema aus, z. B. mandiant-ioc-trigger.
    4. Klicken Sie auf Speichern.
  6. Im Abschnitt Authentifizierung:

    1. Wählen Sie Authentifizierung erforderlich aus.
    2. Identitäts- und Zugriffsverwaltung
  1. Scrollen Sie nach unten und maximieren Sie Container, Netzwerk, Sicherheit.
  2. Rufen Sie den Tab Sicherheit auf:
    • Dienstkonto: Wählen Sie das Dienstkonto aus, z. B. mandiant-ioc-collector-sa.
  3. Rufen Sie den Tab Container auf:

    1. Klicken Sie auf Variablen und Secrets.
    2. Klicken Sie für jede Umgebungsvariable auf + Variable hinzufügen:
    Variablenname Beispielwert Beschreibung
    GCS_BUCKET mandiant-ioc-logs Name des GCS-Buckets
    GCS_PREFIX mandiant-ioc Präfix für Protokolldateien
    STATE_KEY mandiant-ioc/state.json Statusdateipfad
    API_BASE https://api.intelligence.mandiant.com API-Basis-URL
    API_KEY_ID your-key-id Mandiant API Key ID (Mandiant-API-Schlüssel-ID)
    API_SECRET your-key-secret Mandiant API-Secret
    MAX_RECORDS 1000 Maximale Anzahl von Datensätzen pro Ausführung
    PAGE_SIZE 100 Einträge pro Seite
    LOOKBACK_HOURS 24 Erster Rückschauzeitraum
  4. Scrollen Sie im Bereich Variablen und Secrets nach unten zu Anfragen:

    • Zeitüberschreitung bei Anfrage: Geben Sie 600 Sekunden (10 Minuten) ein.
  5. Rufen Sie den Tab Einstellungen auf:

    • Im Abschnitt Ressourcen:
      • Arbeitsspeicher: Wählen Sie 512 MiB oder höher aus.
      • CPU: Wählen Sie 1 aus.
  6. Im Abschnitt Versionsskalierung:

    • Mindestanzahl von Instanzen: Geben Sie 0 ein.
    • Maximale Anzahl von Instanzen: Geben Sie 100 ein (oder passen Sie den Wert an die erwartete Last an).
  7. Klicken Sie auf Erstellen.

  8. Warten Sie ein bis zwei Minuten, bis der Dienst erstellt wurde.

  9. Nachdem der Dienst erstellt wurde, wird automatisch der Inline-Code-Editor geöffnet.

Funktionscode hinzufügen

  1. Geben Sie main in das Feld Einstiegspunkt ein.
  2. Erstellen Sie im Inline-Codeeditor zwei Dateien:

    • main.py:

      import functions_framework
      from google.cloud import storage
      import json
      import os
      import urllib3
      from datetime import datetime, timezone, timedelta
      import time
      import base64
      
      # Initialize HTTP client with timeouts
      http = urllib3.PoolManager(
          timeout=urllib3.Timeout(connect=5.0, read=30.0),
          retries=False,
      )
      
      # Initialize Storage client
      storage_client = storage.Client()
      
      # Environment variables
      GCS_BUCKET = os.environ.get('GCS_BUCKET')
      GCS_PREFIX = os.environ.get('GCS_PREFIX', 'mandiant-ioc')
      STATE_KEY = os.environ.get('STATE_KEY', 'mandiant-ioc/state.json')
      API_BASE = os.environ.get('API_BASE', 'https://api.intelligence.mandiant.com')
      API_KEY_ID = os.environ.get('API_KEY_ID')
      API_SECRET = os.environ.get('API_SECRET')
      MAX_RECORDS = int(os.environ.get('MAX_RECORDS', '1000'))
      PAGE_SIZE = int(os.environ.get('PAGE_SIZE', '100'))
      LOOKBACK_HOURS = int(os.environ.get('LOOKBACK_HOURS', '24'))
      
      def to_unix_seconds(dt: datetime) -> int:
          """Convert datetime to Unix epoch seconds."""
          if dt.tzinfo is None:
              dt = dt.replace(tzinfo=timezone.utc)
          dt = dt.astimezone(timezone.utc)
          return int(dt.timestamp())
      
      def parse_datetime(value: str) -> datetime:
          """Parse ISO datetime string to datetime object."""
          if value.endswith("Z"):
              value = value[:-1] + "+00:00"
          return datetime.fromisoformat(value)
      
      @functions_framework.cloud_event
      def main(cloud_event):
          """
          Cloud Run function triggered by Pub/Sub to fetch Mandiant IOC data and write to GCS.
      
          Args:
              cloud_event: CloudEvent object containing Pub/Sub message
          """
      
          if not all([GCS_BUCKET, API_BASE, API_KEY_ID, API_SECRET]):
              print('Error: Missing required environment variables')
              return
      
          try:
              # Get GCS bucket
              bucket = storage_client.bucket(GCS_BUCKET)
      
              # Load state
              state = load_state(bucket, STATE_KEY)
      
              # Determine time window
              now = datetime.now(timezone.utc)
              last_time = None
      
              if isinstance(state, dict) and state.get("last_event_time"):
                  try:
                      last_time = parse_datetime(state["last_event_time"])
                      # Overlap by 2 minutes to catch any delayed events
                      last_time = last_time - timedelta(minutes=2)
                  except Exception as e:
                      print(f"Warning: Could not parse last_event_time: {e}")
      
              if last_time is None:
                  last_time = now - timedelta(hours=LOOKBACK_HOURS)
      
              print(f"Fetching IOCs from {last_time.isoformat()} to {now.isoformat()}")
      
              # Convert to Unix timestamps
              start_epoch = to_unix_seconds(last_time)
              end_epoch = to_unix_seconds(now)
      
              # Fetch IOCs
              records, newest_event_time = fetch_iocs(
                  api_base=API_BASE,
                  api_key_id=API_KEY_ID,
                  api_secret=API_SECRET,
                  start_epoch=start_epoch,
                  end_epoch=end_epoch,
                  page_size=PAGE_SIZE,
                  max_records=MAX_RECORDS,
              )
      
              if not records:
                  print("No new IOC records found.")
                  save_state(bucket, STATE_KEY, now.isoformat())
                  return
      
              # Write to GCS as NDJSON
              timestamp = now.strftime('%Y%m%d_%H%M%S')
              object_key = f"{GCS_PREFIX}/iocs_{timestamp}.ndjson"
              blob = bucket.blob(object_key)
      
              ndjson = '\n'.join([json.dumps(record, ensure_ascii=False) for record in records]) + '\n'
              blob.upload_from_string(ndjson, content_type='application/x-ndjson')
      
              print(f"Wrote {len(records)} records to gs://{GCS_BUCKET}/{object_key}")
      
              # Update state with newest event time
              if newest_event_time:
                  save_state(bucket, STATE_KEY, newest_event_time)
              else:
                  save_state(bucket, STATE_KEY, now.isoformat())
      
              print(f"Successfully processed {len(records)} records")
      
          except Exception as e:
              print(f'Error processing IOCs: {str(e)}')
              raise
      
      def load_state(bucket, key):
          """Load state from GCS."""
          try:
              blob = bucket.blob(key)
              if blob.exists():
                  state_data = blob.download_as_text()
                  return json.loads(state_data)
          except Exception as e:
              print(f"Warning: Could not load state: {e}")
      
          return {}
      
      def save_state(bucket, key, last_event_time_iso: str):
          """Save the last event timestamp to GCS state file."""
          try:
              state = {'last_event_time': last_event_time_iso}
              blob = bucket.blob(key)
              blob.upload_from_string(
                  json.dumps(state, indent=2),
                  content_type='application/json'
              )
              print(f"Saved state: last_event_time={last_event_time_iso}")
          except Exception as e:
              print(f"Warning: Could not save state: {e}")
      
      def get_oauth_token(api_base: str, api_key_id: str, api_secret: str) -> str:
          """Get OAuth 2.0 access token from Mandiant API."""
          token_url = f"{api_base}/token"
      
          # Create Basic Auth header
          auth_string = f"{api_key_id}:{api_secret}"
          auth_bytes = auth_string.encode('utf-8')
          auth_b64 = base64.b64encode(auth_bytes).decode('utf-8')
      
          headers = {
              'Authorization': f'Basic {auth_b64}',
              'Content-Type': 'application/x-www-form-urlencoded',
              'Accept': 'application/json'
          }
      
          body = 'grant_type=client_credentials'
      
          try:
              response = http.request('POST', token_url, body=body, headers=headers)
      
              if response.status != 200:
                  print(f"Token request failed: {response.status}")
                  print(f"Response: {response.data.decode('utf-8')}")
                  raise Exception(f"Failed to get OAuth token: HTTP {response.status}")
      
              token_data = json.loads(response.data.decode('utf-8'))
              return token_data['access_token']
      
          except Exception as e:
              print(f"Error getting OAuth token: {e}")
              raise
      
      def fetch_iocs(api_base: str, api_key_id: str, api_secret: str, start_epoch: int, end_epoch: int, page_size: int, max_records: int):
          """
          Fetch IOCs from Mandiant Threat Intelligence API with pagination and rate limiting.
      
          Args:
              api_base: API base URL
              api_key_id: Mandiant API Key ID
              api_secret: Mandiant API Secret
              start_epoch: Start time in Unix epoch seconds
              end_epoch: End time in Unix epoch seconds
              page_size: Number of records per page
              max_records: Maximum total records to fetch
      
          Returns:
              Tuple of (records list, newest_event_time ISO string)
          """
          # Get OAuth token
          access_token = get_oauth_token(api_base, api_key_id, api_secret)
      
          endpoint = f"{api_base}/v4/indicator"
      
          headers = {
              'Authorization': f'Bearer {access_token}',
              'Accept': 'application/json',
              'Content-Type': 'application/json',
              'User-Agent': 'GoogleSecOps-MandiantCollector/1.0'
          }
      
          records = []
          newest_time = None
          page_num = 0
          backoff = 1.0
          next_url = None
      
          while True:
              page_num += 1
      
              if len(records) >= max_records:
                  print(f"Reached max_records limit ({max_records})")
                  break
      
              # Build request URL
              if next_url:
                  # Use next URL from pagination
                  url = next_url
              else:
                  # First request with time filtering
                  params = []
                  params.append(f"start_epoch={start_epoch}")
                  params.append(f"end_epoch={end_epoch}")
                  params.append(f"limit={min(page_size, max_records - len(records))}")
                  url = f"{endpoint}?{'&'.join(params)}"
      
              try:
                  response = http.request('GET', url, headers=headers)
      
                  # Handle rate limiting with exponential backoff
                  if response.status == 429:
                      retry_after = int(response.headers.get('Retry-After', str(int(backoff))))
                      print(f"Rate limited (429). Retrying after {retry_after}s...")
                      time.sleep(retry_after)
                      backoff = min(backoff * 2, 30.0)
                      continue
      
                  backoff = 1.0
      
                  if response.status != 200:
                      print(f"HTTP Error: {response.status}")
                      response_text = response.data.decode('utf-8')
                      print(f"Response body: {response_text}")
                      return [], None
      
                  data = json.loads(response.data.decode('utf-8'))
      
                  # Extract results
                  page_results = data.get('indicators', [])
      
                  if not page_results:
                      print(f"No more results (empty page)")
                      break
      
                  print(f"Page {page_num}: Retrieved {len(page_results)} IOCs")
                  records.extend(page_results)
      
                  # Track newest event time
                  for ioc in page_results:
                      try:
                          # Extract last_updated timestamp
                          event_time = ioc.get('last_updated')
                          if event_time:
                              if newest_time is None or parse_datetime(event_time) > parse_datetime(newest_time):
                                  newest_time = event_time
                      except Exception as e:
                          print(f"Warning: Could not parse event time: {e}")
      
                  # Check for next page
                  next_url = data.get('next')
                  if not next_url:
                      print("No more pages (no next URL)")
                      break
      
              except Exception as e:
                  print(f"Error fetching IOCs: {e}")
                  return [], None
      
          print(f"Retrieved {len(records)} total records from {page_num} pages")
          return records, newest_time
      
    • requirements.txt:

      functions-framework==3.*
      google-cloud-storage==2.*
      urllib3>=2.0.0
      
  3. Klicken Sie auf Bereitstellen, um die Funktion zu speichern und bereitzustellen.

  4. Warten Sie, bis die Bereitstellung abgeschlossen ist (2–3 Minuten).

Cloud Scheduler-Job erstellen

Cloud Scheduler veröffentlicht in regelmäßigen Abständen Nachrichten im Pub/Sub-Thema und löst so die Cloud Run-Funktion aus.

  1. Rufen Sie in der GCP Console Cloud Scheduler auf.
  2. Klicken Sie auf Job erstellen.
  3. Geben Sie die folgenden Konfigurationsdetails an:

    Einstellung Wert
    Name mandiant-ioc-collector-hourly (z. B. mandiant-ioc-collector-hourly)
    Region Dieselbe Region wie für die Cloud Run-Funktion auswählen
    Frequenz 0 * * * * (jede Stunde, zur vollen Stunde)
    Zeitzone Zeitzone auswählen (UTC empfohlen)
    Zieltyp Pub/Sub
    Thema Wählen Sie das Pub/Sub-Thema aus (z. B. mandiant-ioc-trigger).
    Inhalt der Nachricht {} (leeres JSON-Objekt)
  4. Klicken Sie auf Erstellen.

Optionen für die Häufigkeit des Zeitplans

  • Wählen Sie die Häufigkeit basierend auf dem IOC-Aktualisierungsvolumen und den Latenzanforderungen aus:

    Häufigkeit Cron-Ausdruck Anwendungsfall
    Alle 5 Minuten */5 * * * * Hohes Volumen, niedrige Latenz
    Alle 15 Minuten */15 * * * * Mittleres Suchvolumen
    Stündlich 0 * * * * Standard (empfohlen)
    Alle 6 Stunden 0 */6 * * * Geringes Volumen, Batchverarbeitung
    Täglich 0 0 * * * Erhebung von Verlaufsdaten

Integration testen

  1. Suchen Sie in der Cloud Scheduler-Konsole nach Ihrem Job (z. B. mandiant-ioc-collector-hourly).
  2. Klicken Sie auf Force run (Ausführung erzwingen), um den Job manuell auszulösen.
  3. Warten Sie einige Sekunden.
  4. Rufen Sie Cloud Run > Dienste auf.
  5. Klicken Sie auf den Namen Ihrer Funktion, z. B. mandiant-ioc-collector.
  6. Klicken Sie auf den Tab Logs.
  7. Prüfen Sie, ob die Funktion erfolgreich ausgeführt wurde. Darauf sollten Sie achten:

    Fetching IOCs from YYYY-MM-DDTHH:MM:SS+00:00 to YYYY-MM-DDTHH:MM:SS+00:00
    Page 1: Retrieved X IOCs
    Wrote X records to gs://bucket-name/mandiant-ioc/iocs_YYYYMMDD_HHMMSS.ndjson
    Successfully processed X records
    
  8. Rufen Sie Cloud Storage > Buckets auf.

  9. Klicken Sie auf den Namen Ihres Buckets, z. B. mandiant-ioc-logs.

  10. Rufen Sie den Präfixordner auf (z. B. mandiant-ioc/).

  11. Prüfen Sie, ob eine neue .ndjson-Datei mit dem aktuellen Zeitstempel erstellt wurde.

Wenn Sie Fehler in den Logs sehen:

  • HTTP 401: API-Schlüssel-ID und Secret in Umgebungsvariablen prüfen
  • HTTP 403: Prüfen, ob das Konto Threat Intelligence-Berechtigungen hat
  • HTTP 429: Ratenbegrenzung – Funktion wird automatisch mit Backoff wiederholt
  • Fehlende Umgebungsvariablen: Prüfen Sie, ob alle erforderlichen Variablen festgelegt sind.
  • Tokenanfrage fehlgeschlagen: Überprüfen Sie, ob die API-Anmeldedaten korrekt und nicht abgelaufen sind.

Google SecOps-Dienstkonto abrufen

Google SecOps verwendet ein eindeutiges Dienstkonto, um Daten aus Ihrem GCS-Bucket zu lesen. Sie müssen diesem Dienstkonto Zugriff auf Ihren Bucket gewähren.

E-Mail-Adresse des Dienstkontos abrufen

  1. Rufen Sie die SIEM-Einstellungen > Feeds auf.
  2. Klicken Sie auf Neuen Feed hinzufügen.
  3. Klicken Sie auf Einzelnen Feed konfigurieren.
  4. Geben Sie im Feld Feedname einen Namen für den Feed ein, z. B. Mandiant Custom IOC.
  5. Wählen Sie Google Cloud Storage V2 als Quelltyp aus.
  6. Wählen Sie Benutzerdefinierte IOCs von Mandiant als Logtyp aus.
  7. Klicken Sie auf Dienstkonto abrufen. Es wird eine eindeutige E-Mail-Adresse für das Dienstkonto angezeigt, z. B.:

    chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.com
    
  8. Kopieren Sie diese E-Mail-Adresse für den nächsten Schritt.

  9. Klicken Sie auf Weiter.

  10. Geben Sie Werte für die folgenden Eingabeparameter an:

    • Storage-Bucket-URL: Geben Sie den GCS-Bucket-URI mit dem Präfixpfad ein:

      gs://mandiant-ioc-logs/mandiant-ioc/
      
      • Ersetzen Sie:
        • mandiant-ioc-logs: Der Name Ihres GCS-Buckets.
        • mandiant-ioc: Präfix-/Ordnerpfad, in dem IOC-Logs gespeichert werden.
    • Option zum Löschen der Quelle: Wählen Sie die gewünschte Löschoption aus:

      • Nie: Es werden nach Übertragungen nie Dateien gelöscht (empfohlen für Tests).
      • Übertragene Dateien löschen: Dateien werden nach der erfolgreichen Übertragung gelöscht.
      • Übertragene Dateien und leere Verzeichnisse löschen: Dateien und leere Verzeichnisse werden nach der erfolgreichen Übertragung gelöscht.

    • Höchstalter für Dateien: Dateien einschließen, die in den letzten Tagen geändert wurden (Standard ist 180 Tage)

    • Asset-Namespace: Der Asset-Namespace

    • Labels für Datenaufnahme: Das Label, das auf die Ereignisse aus diesem Feed angewendet werden soll

  11. Klicken Sie auf Weiter.

  12. Prüfen Sie die neue Feedkonfiguration auf dem Bildschirm Abschließen und klicken Sie dann auf Senden.

Dem Google SecOps-Dienstkonto IAM-Berechtigungen gewähren

Das Google SecOps-Dienstkonto benötigt die Rolle Storage-Objekt-Betrachter für Ihren GCS-Bucket.

  1. Rufen Sie Cloud Storage > Buckets auf.
  2. Klicken Sie auf den Namen Ihres Buckets, z. B. mandiant-ioc-logs.
  3. Wechseln Sie zum Tab Berechtigungen.
  4. Klicken Sie auf Zugriff erlauben.
  5. Geben Sie die folgenden Konfigurationsdetails an:
    • Hauptkonten hinzufügen: Fügen Sie die E‑Mail-Adresse des Google SecOps-Dienstkontos ein.
    • Rollen zuweisen: Wählen Sie Storage-Objekt-Betrachter aus.
  6. Klicken Sie auf Speichern.

UDM-Zuordnungstabelle

Logfeld UDM-Zuordnung Logik
associated_hashes.value entity.file.md5 Wert aus „associated_hashes.value“, wenn „hash.type“ == „md5“, andernfalls aus „value“, wenn „type“ == „md5“
Wert entity.file.md5
associated_hashes.value entity.file.sha1 Wert aus associated_hashes.value, wenn hash.type == „sha1“, andernfalls aus value, wenn type == „sha1“
Wert entity.file.sha1
associated_hashes.value entity.file.sha256 Wert aus associated_hashes.value, wenn hash.type == „sha256“, andernfalls aus value, wenn type == „sha256“
Wert entity.file.sha256
Wert entity.hostname Wert wird direkt kopiert, wenn type == „fqdn“
Wert entity.ip Wert wird direkt kopiert, wenn type == „ipv4“
threat_rating.threat_score entity.labels Zusammengeführte Label-Objekte mit dem Schlüssel „threat_score“ und dem Wert aus threat_rating.threat_score, dem Schlüssel „mscore“ und dem Wert aus mscore, dem Schlüssel „is_exclusive“ und dem Wert aus is_exclusive, dem Schlüssel „is_publishable“ und dem Wert aus ispublishable sowie für jedes MISP-Feld dem Schlüssel „misp“ und dem Wert aus misp.
mscore entity.labels
is_exclusive entity.labels
is_publishable entity.labels
misp.akamai entity.labels
misp.alexa entity.labels
misp.alexa_1M entity.labels
misp.amazon-aws entity.labels
misp.apple entity.labels
misp.automated-malware-analysis entity.labels
misp.bank-website entity.labels
misp.captive-portals entity.labels
misp.censys-scanning entity.labels
misp.cisco_1M entity.labels
misp.cisco_top1000 entity.labels
misp.cisco_top10k entity.labels
misp.cisco_top20k entity.labels
misp.cisco_top5k entity.labels
misp.cloudflare entity.labels
misp.common-contact-emails entity.labels
misp.common-ioc-false-positive entity.labels
misp.covid entity.labels
misp.covid-19-cyber-threat-coalition-whitelist entity.labels
misp.covid-19-krassi-whitelist entity.labels
misp.crl-hostname entity.labels
misp.crl-ip entity.labels
misp.dax30 entity.labels
misp.digitalside entity.labels
misp.disposable-email entity.labels
misp.dynamic-dns entity.labels
misp.eicar.com entity.labels
misp.empty-hashes entity.labels
misp.fastly entity.labels
misp.findip-host entity.labels
misp.google entity.labels
misp.google-chrome-crux-1million entity.labels
misp.google-gcp entity.labels
misp.google-gmail-sending-ips entity.labels
misp.googlebot entity.labels
misp.ipv6-linklocal entity.labels
misp.majestic_million entity.labels
misp.majestic_million_1M entity.labels
misp.microsoft entity.labels
misp.microsoft-attack-simulator entity.labels
misp.microsoft-azure entity.labels
misp.microsoft-azure-appid entity.labels
misp.microsoft-azure-china entity.labels
misp.microsoft-azure-germany entity.labels
misp.microsoft-azure-us-gov entity.labels
misp.microsoft-office365 entity.labels
misp.microsoft-office365-cn entity.labels
misp.microsoft-office365-ip entity.labels
misp.microsoft-win10-connection-endpoints entity.labels
misp.moz-top500 entity.labels
misp.mozilla-CA entity.labels
misp.mozilla-IntermediateCA entity.labels
misp.multicast entity.labels
misp.nioc-filehash entity.labels
misp.openai-gptbot entity.labels
misp.ovh-cluster entity.labels
misp.parking-domain entity.labels
misp.parking-domain-ns entity.labels
misp.phone_numbers entity.labels
misp.public-dns-hostname entity.labels
misp.public-dns-v4 entity.labels
misp.public-dns-v6 entity.labels
misp.public-ipfs-gateways entity.labels
misp.rfc1918 entity.labels
misp.rfc3849 entity.labels
misp.rfc5735 entity.labels
misp.rfc6598 entity.labels
misp.rfc6761 entity.labels
misp.second-level-tlds entity.labels
misp.security-provider-blogpost entity.labels
misp.sinkholes entity.labels
misp.smtp-receiving-ips entity.labels
misp.smtp-sending-ips entity.labels
misp.stackpath entity.labels
misp.tenable-cloud-ipv4 entity.labels
misp.tenable-cloud-ipv6 entity.labels
misp.ti-falsepositives entity.labels
misp.tlds entity.labels
misp.tranco entity.labels
misp.tranco10k entity.labels
misp.umbrella-blockpage-hostname entity.labels
misp.umbrella-blockpage-v4 entity.labels
misp.umbrella-blockpage-v6 entity.labels
misp.university_domains entity.labels
misp.url-shortener entity.labels
misp.vpn-ipv4 entity.labels
misp.vpn-ipv6 entity.labels
misp.whats-my-ip entity.labels
misp.wikimedia entity.labels
misp.zscaler entity.labels
Wert entity.url Wert wird direkt kopiert, wenn type == „url“
last_seen event.ioc.active_timerange.end Datum, das aus „last_seen“ im ISO8601-Format geparst wurde
first_seen event.ioc.active_timerange.start Datum, das aus „first_seen“ im ISO8601-Format geparst wurde
sources.0.category event.ioc.categorization Zusammengeführt aus dem Array „sources.0.category“ mit Komma als Trennzeichen
threat_rating.threat_score event.ioc.confidence_score Wert direkt kopiert
Wert event.ioc.domain_and_ports.domain Wert wird direkt kopiert, wenn type == „fqdn“
event.ioc.feed_name event.ioc.feed_name Auf „Mandiant“ festgelegt
Wert event.ioc.ip_and_ports.ip_address In „ipaddress“ konvertiert, wenn type == „ipv4“
Typ metadata.entity_type Auf FILE setzen, wenn associated_hashes.type in md5 sha1 sha256, andernfalls DOMAIN_NAME, wenn type == "fqdn", IP_ADDRESS, wenn type == "ipv4", URL, wenn type == "url", FILE, wenn type in md5 sha1 sha256, UNKNOWN_ENTITYTYPE andernfalls
associated_hashes.type metadata.entity_type
custom_ioc_expire_date metadata.interval.end_time Das Datum, das aus „custom_ioc_expire_date“ mit ISO8601 geparst wurde, wenn „type“ in „fqdn ipv4 url“ ist.
first_seen metadata.interval.start_time Datum, das aus „first_seen“ im ISO8601- oder UNIX-Format geparst wurde
id metadata.product_entity_id Wert direkt kopiert
threat_det metadata.threat Zusammengeführt aus „threat_det“
attributed_associations threat_det.associations Zusammengeführte threat_association-Objekte aus attributed_associations und associations, wobei die Felder aus association.id, name, type, region_code.country_or_region, associated_actors, alias, role, first_reference_time, last_reference_time, industries_affected festgelegt werden
Verknüpfungen threat_det.associations
die alle Sinne ansprechen threat_det.campaigns Zusammengeführter campaign.name aus dem Kampagnenarray
Kategorie threat_det.category_details Zusammengeführt aus Kategorie-Array
threat_rating.confidence_level threat_det.confidence Auf LOW_CONFIDENCE setzen, wenn die Übereinstimmung gering ist, auf MEDIUM_CONFIDENCE, wenn sie mittel ist, auf HIGH_CONFIDENCE, wenn sie hoch ist, andernfalls auf UNKNOWN_CONFIDENCE.
threat_rating.confidence_score threat_det.confidence_details Wert aus „threat_rating.confidence_score“, in String konvertiert, oder aus „mscore“, wenn „threat_rating.confidence_score“ leer ist
mscore threat_det.confidence_details
first_seen threat_det.first_discovered_time Das Datum aus „first_seen“, falls nicht leer, andernfalls aus „firstSeen“ im ISO8601- oder UNIX-Format.
firstSeen threat_det.first_discovered_time
first_seen threat_det.last_updated_time Datum, das aus „first_seen“ im ISO8601- oder UNIX-Format geparst wurde
threat_rating.threat_score threat_det.risk_score Wird aus „threat_rating.threat_score“ in Gleitkommazahl konvertiert, falls nicht leer, andernfalls aus „mscore“.
mscore threat_det.risk_score
threat_rating.severity_level threat_det.severity Auf LOW setzen, wenn niedrig, auf MEDIUM, wenn mittel, auf HIGH, wenn hoch, andernfalls UNKNOWN_SEVERITY
threat_det.threat_feed_name threat_det.threat_feed_name Auf „Mandiant“ festgelegt
Wert threat_det.url_back_to_product Auf „https://advantage.mandiant.com/search?query=%{value}“ setzen, wenn der Typ „fqdn ipv4 url md5“ ist.
verdict_simple.timestamp threat_det.verdict_info Zusammengeführt aus „verdict_info_simple“ nach Festlegen von „verdict_time“ aus dem Zeitstempel, „verdict_response“ aus dem Ergebnis, wenn es schädlich ist, und „verdict_type“ aus „verdict_source“
verdict_simple.verdict threat_det.verdict_info
verdict_simple.verdict_source threat_det.verdict_info
metadata.product_name metadata.product_name Auf „MANDIANT_CUSTOM_IOC“ festgelegt
metadata.vendor_name metadata.vendor_name Auf „MANDIANT_CUSTOM_IOC“ festgelegt
threat.threat_feed_name Mandiant Aus dem Änderungsprotokoll zugeordnet
threat_rating.threat_score entity.entity.labels Aus dem Änderungsprotokoll zugeordnet
threat_rating.severity_level threat.severity Aus dem Änderungsprotokoll zugeordnet
threat_rating.confidence_level threat.confidence Aus dem Änderungsprotokoll zugeordnet
verdict_simple.timestamp verdict_info.verdict_time Aus dem Änderungsprotokoll zugeordnet
category threat.category_details Aus dem Änderungsprotokoll zugeordnet
threat_rating.confidence_score threat.confidence_details Aus dem Änderungsprotokoll zugeordnet
threat_rating.threat_score threat.risk_score Aus dem Änderungsprotokoll zugeordnet

Änderungsprotokoll

Änderungsprotokoll für diesen Parser ansehen

Benötigen Sie weitere Hilfe? Antworten von Community-Mitgliedern und Google SecOps-Experten erhalten