Aller au contenu principal

Guide d’intégration

Lookups de menaces pour Splunk issus des listes isMalicious

Une entrée scriptée récupère chaque liste avec votre clé API, refuse l’échantillon de 10 % et reconstruit un lookup CSV toutes les 12 heures. Enterprise Security lit une copie interne ; l’envoi par HEC pousse les IOC à la demande.

Aucune carte bancaire requise · Clé API gratuite

Chemin des données
  1. isMalicious

    api.ismalicious.com

    blocklist-ips-critical.txt

    Régénérée toutes les 12 h

  2. Lookups Splunk et ES

    Étape 3

    Ajouter le script de récupération

  3. Rapprocher vos événements des listes

    Étape 5
Sur cette page08

Ce que vous obtenez

Un lookup comme une threat list ES lit un indicateur par ligne : les listes simples conviennent. Commencez par les IP de niveau critical et les listes par catégorie ; n’ajoutez les domaines de niveau critical qu’après avoir dimensionné le lookup.

ListeEntréesRégénéréeOffres
blocklist-ips-critical.txtPar défaut. IP signalées par 6 sources de menaces ou plus, ou par 3 ou plus avec une catégorie critique.environ 89 000toutes les 12 hBasic, Pro et Enterprise
blocklist-ips-c2.txtIP de commande et contrôle (C2) signalées par des trackers de C2, quel que soit leur niveau.environ 44 000toutes les 12 hBasic, Pro et Enterprise
blocklist-domains-c2.txtDomaines de commande et contrôle (C2) signalés par des trackers de C2, quel que soit leur niveau.environ 22 000toutes les 12 hBasic, Pro et Enterprise
blocklist-domains-ransomware.txtDomaines de la catégorie ransomware, quel que soit leur niveau.environ 3 600toutes les 12 hBasic, Pro et Enterprise
blocklist-domains-critical.txtSeulement après dimensionnement : une ligne de lookup ou un enregistrement ES par entrée.environ 2 millionstoutes les 12 hBasic, Pro et Enterprise
/app/integrations/splunkIOC et événements SOC poussés vers votre HTTP Event Collector, en sourcetypes ismalicious:ioc et ismalicious:soc. Ce n’est pas un flux : voir Limites.jusqu’à 1 000 par synchronisationà la synchronisationPro et Enterprise

Nombres arrondis d’après la génération du  ; chaque liste est régénérée toutes les 12 heures. Les chiffres du jour sont publics et ne demandent aucune clé.

Ce que reçoit chaque offre

  • FreeCompte Free, ou aucune clé : les premiers 10 % de chaque liste, signalés par X-Blocklist-Version: lite.
  • Basic, Pro et EnterpriseBasic, Pro et Enterprise : toutes les listes, complètes.
  • Pro et EnterpriseCollections TAXII 2.1, pour les plateformes qui lisent les indicateurs STIX : Pro et Enterprise.
  • Pro et EnterpriseDestinations SIEM du tableau de bord (Splunk, Elastic, Sentinel) : Pro et Enterprise.

Comparer les offres

Ce que renvoie un téléchargementHTTP

GET https://api.ismalicious.com/blocklist/download/blocklist-ips-critical.txt

Liste complète ou échantillon de 10 %

ChampBasic, Pro et EnterpriseFree
X-Blocklist-Version:fulllite
X-Blocklist-Percentage:10010
Total entries:<COUNT><COUNT> (Lite Version - 10% of <TOTAL>)

Premières lignes du fichier

# IsMalicious.com Blocklist - IPs (Critical)
# Format: Plain
# Generated: <BUILD_TIME>
# Total entries: <COUNT>
# Update frequency: every 12 hours
# Category: All
# Threat level: Critical
# Website: https://ismalicious.com
# © <YEAR> IsMalicious (compilation). Licensed to the downloading account under https://ismalicious.com/terms; redistribution of the compilation prohibited. Third-party entries remain under their providers' licences — see https://ismalicious.com/sources.
#

Les valeurs entre chevrons sont fixées à chaque génération.

Prérequis

  • Splunk Enterprise 9.x ou 10.x pour les lookups. Sur Splunk Cloud Platform, les fichiers .conf ne se modifient pas directement : voir les limites.
  • Un shell sur le search head, avec curl et awk.
  • Une clé API et son secret isMalicious, dans Compte › Accès API.
  • Un accès HTTPS sortant (TCP 443) en IPv4 depuis le search head Splunk vers api.ismalicious.com, qui n’a pas d’adresse IPv6.

Mise en place

  1. Copier la clé API et le secret

    Ouvrez Compte › Accès API et copiez la Clé API et le Secret API. La liste complète demande une offre Basic, Pro ou Enterprise ; une clé Free reçoit l’échantillon de 10 %, que le script refuse.
  2. Créer l’app et son fichier d’identifiants

    Sur le search head, créez $SPLUNK_HOME/etc/apps/ismalicious_lists/ avec bin/, local/ et lookups/. Écrivez la clé et le secret dans local/ismalicious.netrc, propriété de l’utilisateur Splunk, en mode 600 : curl les lit dans le fichier, pas sur la ligne de commande.
    local/ismalicious.netrcnetrc
    machine api.ismalicious.com login <API_KEY> password <API_SECRET>
  3. Ajouter le script de récupération

    Enregistrez-le sous bin/fetch_ismalicious.sh, en mode 755. Il télécharge la liste, refuse une erreur, un contenu qui n’est pas une liste, l’échantillon de 10 % et un fichier dont le nombre d’entrées diffère de son en-tête, écrit un lookup CSV à deux colonnes sans les lignes d’en-tête #, et affiche une ligne d’état : status=ok avec le nombre de lignes, ou status=refused, la raison allant dans splunkd.log. Une liste refusée garde le lookup précédent.
    bin/fetch_ismalicious.shsh
    #!/bin/sh
    # Rebuilds lookups/$NAME.csv from $LIST and prints one status line, which the
    # scripted input indexes. Copy it per list: for a domain list, set FIELD=domain.
    set -eu
    APP_DIR=$(cd "$(dirname "$0")/.." && pwd)
    NETRC="$APP_DIR/local/ismalicious.netrc"
    LIST=blocklist-ips-critical.txt
    NAME=ismalicious_ips
    FIELD=ip
    RAW=$(mktemp)
    TMP=$(mktemp "$APP_DIR/lookups/.$NAME.csv.XXXXXX")
    trap 'rm -f "$RAW" "$TMP"' EXIT
    
    # fetch_list LIST OUT: download one list to OUT and check it.
    # On any failure OUT is removed and the function returns 1.
    fetch_list() {
      if ! code=$(curl --silent --show-error --fail --netrc-file "$NETRC" \
          --proto '=https' --max-time 300 --retry 2 \
          --output "$2" --write-out '%{http_code}' "https://api.ismalicious.com/blocklist/download/$1"); then
        rm -f "$2"; echo "$1: download failed" >&2; return 1
      fi
      if [ "$code" != 200 ]; then
        rm -f "$2"; echo "$1: HTTP $code" >&2; return 1
      fi
      if ! head -n 1 "$2" | grep -q '^[#!] IsMalicious.com Blocklist'; then
        rm -f "$2"; echo "$1: not an isMalicious list" >&2; return 1
      fi
      if grep -q 'Lite Version' "$2"; then
        rm -f "$2"; echo "$1: lite list received, check the API key and the plan" >&2
        return 1
      fi
      # Every entry ends with a newline, and one header counts them: refuse a
      # cut, doubled or empty file.
      if [ -n "$(tail -c 1 "$2")" ]; then
        rm -f "$2"; echo "$1: cut short, no final newline" >&2; return 1
      fi
      if [ "$(grep -c '^[#!] Total entries:' "$2")" != 1 ]; then
        rm -f "$2"; echo "$1: not one Total entries line" >&2; return 1
      fi
      total=$(sed -n 's/^[#!] Total entries: \([0-9,]*\)$/\1/p' "$2" | tr -d ,)
      got=$(grep -c '^[^#!]' "$2" || true)
      if [ -z "$total" ] || [ "$total" = 0 ] || [ "$got" != "$total" ]; then
        rm -f "$2"; echo "$1: $got entries, the header says ${total:-none}" >&2
        return 1
      fi
    }
    
    # On any failure the previous lookup stays; the reason goes to splunkd.log.
    if ! fetch_list "$LIST" "$RAW"; then
      echo "ismalicious_fetch status=refused list=$LIST"
      exit 1
    fi
    
    awk -v field="$FIELD" -v list="${LIST%.txt}" 'BEGIN { print field ",ismalicious_list" }
      !/^[#!]/ && NF { print $1 "," list }' "$RAW" > "$TMP"
    chmod 644 "$TMP"
    mv -f "$TMP" "$APP_DIR/lookups/$NAME.csv"
    echo "ismalicious_fetch status=ok list=$LIST rows=$(($(wc -l < "$APP_DIR/lookups/$NAME.csv") - 1))"
  4. Le planifier et déclarer le lookup

    Ajoutez les deux stanzas sous local/, puis redémarrez Splunk. L’entrée scriptée s’exécute deux fois par jour ; un intervalle cron ne s’exécute pas au démarrage : lancez donc le script une première fois à la main.
    local/inputs.confconf
    [script://./bin/fetch_ismalicious.sh]
    # The lists are rebuilt every 12 hours. A cron interval does not run at start-up.
    interval = 17 3,15 * * *
    index = <INDEX>
    sourcetype = ismalicious:fetch
    disabled = 0
    local/transforms.confconf
    [ismalicious_ips]
    filename = ismalicious_ips.csv
    
    # A domain lookup built the same way (FIELD=domain):
    [ismalicious_domains]
    filename = ismalicious_domains.csv
    case_sensitive_match = false
  5. Faites le lookup sur le champ d’adresse de vos événements de pare-feu ou de proxy. Les lookups comparent des valeurs exactes : normalisez d’abord le champ.
    RechercheSPL
    index=<FIREWALL_INDEX> sourcetype=<FIREWALL_SOURCETYPE>
    | lookup ismalicious_ips ip AS dest_ip OUTPUT ismalicious_list
    | where isnotnull(ismalicious_list)
  6. Dans Enterprise Security, ajouter une source Line Oriented (facultatif)

    • Servez à ES, en HTTPS, une copie récupérée sur un hôte que vous contrôlez avec le script ci-dessous, qui applique les mêmes vérifications, et donnez à ES cette URL, sans identifiant.
    • Dans ES 8, interface en anglais : Configure › Threat intelligence › Data sources › + Data source › Line Oriented.
    • Name ismalicious_ips_critical, Type threatlist_ip, l’URL de votre copie, Interval 43200, Delimiting regular expression ,, Skip header lines 0, et gardez l’Ignoring regular expression par défaut, qui saute les lignes #.
    • Ajoutez une source par liste avec les Fields ci-dessous, puis activez les recherches de threat matching utiles.
    Copie pour Enterprise Securitysh
    #!/bin/sh
    # Every 12 hours from cron, on a host ES reaches over HTTPS.
    # /etc/ismalicious/netrc (mode 600) holds the three netrc lines.
    set -eu
    NETRC=/etc/ismalicious/netrc
    DIR=/var/www/blocklists
    FILE=blocklist-ips-critical.txt
    
    # fetch_list LIST OUT: download one list to OUT and check it.
    # On any failure OUT is removed and the function returns 1.
    fetch_list() {
      if ! code=$(curl --silent --show-error --fail --netrc-file "$NETRC" \
          --proto '=https' --max-time 300 --retry 2 \
          --output "$2" --write-out '%{http_code}' "https://api.ismalicious.com/blocklist/download/$1"); then
        rm -f "$2"; echo "$1: download failed" >&2; return 1
      fi
      if [ "$code" != 200 ]; then
        rm -f "$2"; echo "$1: HTTP $code" >&2; return 1
      fi
      if ! head -n 1 "$2" | grep -q '^[#!] IsMalicious.com Blocklist'; then
        rm -f "$2"; echo "$1: not an isMalicious list" >&2; return 1
      fi
      if grep -q 'Lite Version' "$2"; then
        rm -f "$2"; echo "$1: lite list received, check the API key and the plan" >&2
        return 1
      fi
      # Every entry ends with a newline, and one header counts them: refuse a
      # cut, doubled or empty file.
      if [ -n "$(tail -c 1 "$2")" ]; then
        rm -f "$2"; echo "$1: cut short, no final newline" >&2; return 1
      fi
      if [ "$(grep -c '^[#!] Total entries:' "$2")" != 1 ]; then
        rm -f "$2"; echo "$1: not one Total entries line" >&2; return 1
      fi
      total=$(sed -n 's/^[#!] Total entries: \([0-9,]*\)$/\1/p' "$2" | tr -d ,)
      got=$(grep -c '^[^#!]' "$2" || true)
      if [ -z "$total" ] || [ "$total" = 0 ] || [ "$got" != "$total" ]; then
        rm -f "$2"; echo "$1: $got entries, the header says ${total:-none}" >&2
        return 1
      fi
    }
    
    mkdir -p "$DIR"
    tmp=$(mktemp "$DIR/.$FILE.XXXXXX")
    trap 'rm -f "$tmp"' EXIT
    fetch_list "$FILE" "$tmp"
    chmod 644 "$tmp"
    mv -f "$tmp" "$DIR/$FILE"
    
    # ES source URL: https://<INTERNAL_HOST>/blocklists/blocklist-ips-critical.txt
    Fields ES, par listeSplunk ES

    # Line Oriented sources, one per list: the file, then its Fields.

    blocklist-ips-critical.txt
    ip:$1,description:isMalicious_ips_critical
    blocklist-ips-c2.txt
    ip:$1,description:isMalicious_ips_c2
    blocklist-domains-c2.txt
    domain:$1,description:isMalicious_domains_c2
    blocklist-domains-ransomware.txt
    domain:$1,description:isMalicious_domains_ransomware

    # URL and hash lists route to http_intel and file_intel. /blocklist/stats does

    # not count them: read a file's Total entries line before you add it.

    blocklist-urls-critical.txt
    url:$1,description:isMalicious_urls_critical
    blocklist-hashes-malware.txt
    file_hash:$1,description:isMalicious_hashes_malware
    # Line Oriented sources, one per list: the file, then its Fields.
    blocklist-ips-critical.txt        ip:$1,description:isMalicious_ips_critical
    blocklist-ips-c2.txt              ip:$1,description:isMalicious_ips_c2
    blocklist-domains-c2.txt          domain:$1,description:isMalicious_domains_c2
    blocklist-domains-ransomware.txt  domain:$1,description:isMalicious_domains_ransomware
    
    # URL and hash lists route to http_intel and file_intel. /blocklist/stats does
    # not count them: read a file's Total entries line before you add it.
    blocklist-urls-critical.txt       url:$1,description:isMalicious_urls_critical
    blocklist-hashes-malware.txt      file_hash:$1,description:isMalicious_hashes_malware
  7. Pousser les IOC par HEC (facultatif, offre Pro ou Enterprise)

    • Dans Splunk, Settings › Add Data › Monitor › HTTP Event Collector : nom ismalicious, sélectionnez l’index autorisé, Review, Submit, et copiez le jeton ; dans Global Settings, passez All Tokens sur Enabled.
    • HEC doit présenter un certificat d’une autorité publique : le certificat HEC par défaut de Splunk est autosigné et refusé, réglez donc serverCert dans la stanza [http] d’inputs.conf, ou placez HEC derrière un répartiteur de charge qui en a un.
    • Dans /app/integrations/splunk, saisissez l’URL HEC (https://, port 8088, chemin /services/collector), le Jeton HEC et l’Index.
    • Cliquez sur Tester, puis sur Synchroniser maintenant : chaque synchronisation envoie jusqu’à 1 000 IOC (100 par défaut) à partir de l’endroit où la précédente s’est arrêtée, et les événements SOC partent dans les cinq minutes.

Vérifier le résultat

  • | inputlookup ismalicious_ips | stats count correspond au count de la liste dans /blocklist/stats, à une régénération près.
  • Les événements ismalicious:fetch donnent l’état et le nombre de lignes de chaque exécution. status=lite signifie que la clé n’a pas obtenu la liste complète : le lookup précédent a été conservé.
  • Dans ES, Analytics › Audit › Threat intelligence audit indique la source comme téléchargée, et le nombre d’entrées ip_intel de son threat_key correspond à la liste.
  • Après une synchronisation, sourcetype="ismalicious:ioc" contient les IOC, et la page de l’intégration liste chaque livraison.
RecherchesSPL
| inputlookup ismalicious_ips | stats count

index=<INDEX> sourcetype=ismalicious:fetch
| table _time status list rows

| inputlookup ip_intel | search threat_key=ismalicious_ips_critical | stats count

index=<INDEX> sourcetype="ismalicious:ioc" | stats count by event.entityType

Dépannage

La récupération échoue avec une erreur 401

La clé ou le secret du fichier netrc est faux ou incomplet : le script journalise status=refused, splunkd.log affiche « download failed », et le lookup précédent reste en place. Le corps de la réponse indique « Blocklist not found or empty » ; fiez-vous au code HTTP. Recopiez les deux valeurs depuis Compte › Accès API.

« lite list received » dans splunkd.log

L’offre est Free ou interrompue : un abonnement impayé, en retard de paiement, annulé, incomplet ou suspendu compte comme Free. Le script journalise status=refused et garde le lookup précédent jusqu’à ce que la clé obtienne la liste complète.

« entries, the header says », « cut short, no final newline » ou « not one Total entries line » dans splunkd.log

Le fichier était vide, tronqué ou n’était pas une des listes, comme quand un proxy ou un portail captif répond. Le script garde le lookup précédent ; l’exécution suivante réessaie.

Délai dépassé ou erreur 502

Un téléchargement qui prend plus de 30 secondes de notre côté finit en délai dépassé ou en 502 : prenez une liste par niveau ou par catégorie du tableau.

503 Service Unavailable

La liste est en cours de première génération, et la réponse porte Retry-After: 600. Le script échoue, garde le lookup précédent, et l’exécution suivante récupère la liste.

Lignes d’en-tête dans le lookup ou dans ES

Un lookup ne peut pas contenir l’en-tête # : c’est pourquoi le script retire ces lignes. ES les saute avec son Ignoring regular expression par défaut : rétablissez-la si vous l’avez modifiée.

Une valeur listée ne correspond pas

Les lookups comparent des valeurs exactes, en respectant la casse par défaut. Normalisez le champ de l’événement, et réglez case_sensitive_match = false sur un lookup de domaines.

Erreurs de certificat

curl vérifie le magasin de certificats du système. Mettez-le à jour, vérifiez l’horloge et exemptez api.ismalicious.com de l’inspection TLS.

La destination HEC est refusée ou les livraisons échouent

L’URL HEC doit être une adresse HTTPS publique avec un certificat d’une autorité publique : les adresses privées et de bouclage sont refusées à l’enregistrement, et le certificat autosigné par défaut de Splunk fait échouer chaque livraison. Chaque livraison doit recevoir une réponse en moins de 5 secondes, et le jeton doit autoriser l’index saisi.

Limites

  • La source TAXII 2 d’ES lit les objets STIX observed-data, pas les patterns d’indicateurs, et les collections isMalicious contiennent des indicateurs à patterns : ES n’en chargerait rien. Utilisez les listes.
  • L’envoi par HEC n’est pas un flux : il part quand vous cliquez sur Synchroniser maintenant, envoie au plus 1 000 IOC par synchronisation, et rien ne le planifie.
  • L’option d’identifiant d’ES pour les sources URL n’est pas couverte ici : donnez à ES une copie interne.
  • Aucun fichier CSV, JSON, CIDR ou générique n’est servi. Le script construit le lookup CSV dont Splunk a besoin, et les types de correspondance CIDR et WILDCARD de Splunk n’ont rien à comparer dans les listes.
  • Sur Splunk Cloud Platform, les fichiers .conf ne se modifient pas directement : empaquetez bin/, local/ et lookups/ en app privée et installez-la après validation AppInspect (Victoria Experience ; non testé pour ce guide), importez le lookup à la main dans Settings › Lookups, ou utilisez l’envoi par HEC.
  • Les clusters de search heads ne sont pas couverts : déployez l’app depuis le deployer plutôt que d’écrire des lookups sur un seul membre.
  • Les listes d’URL et de hashs existent sous les mêmes noms, mais /blocklist/stats ne les compte pas : lisez la ligne Total entries d’un fichier avant de vous en servir.
  • L’échantillon de 10 % est le premier dixième d’un fichier non trié, pas le dixième le plus risqué.

Questions fréquentes

Splunk Enterprise Security peut-il utiliser le flux TAXII d’isMalicious ?

Non. La source TAXII 2 d’ES lit les objets STIX observed-data et n’analyse pas les patterns d’indicateurs, or ce sont eux que contiennent les collections isMalicious. Chargez plutôt les listes en sources Line Oriented.

Est-ce que cela fonctionne sur Splunk Cloud Platform ?

Pas tel quel : Splunk Cloud Platform ne permet pas de modifier directement les fichiers .conf. Une app privée contenant le script, ses entrées et le lookup peut y tourner après validation AppInspect (Victoria Experience ; non testé pour ce guide) ; sinon, importez le lookup à la main, ou utilisez l’envoi par HEC depuis le tableau de bord, avec une offre Pro ou Enterprise, qui envoie jusqu’à 1 000 IOC par synchronisation.

À quelle fréquence le lookup est-il rafraîchi ?

Deux fois par jour, selon l’intervalle cron d’inputs.conf. Les listes sont régénérées toutes les 12 heures : une exécution plus fréquente retélécharge le même fichier. Un intervalle cron ne s’exécute pas au démarrage.

Que se passe-t-il avec une clé API gratuite ?

Le téléchargement est l’échantillon de 10 %, et le script le refuse : il journalise status=refused et garde le lookup précédent. La liste complète demande une offre Basic, Pro ou Enterprise.

Pourquoi un domaine listé ne correspond-il pas à mes événements ?

Les lookups comparent des valeurs exactes et respectent la casse par défaut. Réglez case_sensitive_match = false sur le lookup de domaines, et normalisez le champ de l’événement avant le lookup.

Commencer

Prêt à commencer ?

Aucune carte bancaire requise · Clé API gratuite