Operasyonel Rehber · TIP Entegrasyon

Tehdit İstihbarat Platformlarına SiberAnaliz Verisinin Entegrasyonu

MISP, OpenCTI, ThreatBus ve STIX/TAXII 2.1 uyumlu kurumsal tehdit istihbarat platformlarına SiberAnaliz beslemesini feed olarak bağlamanın; Python konnektör yazımının; cron tabanlı polling akışının ve veri normalizasyonunun uçtan uca operasyonel rehberi.

1. Threat Intel Platform (TIP) nedir?

Tehdit İstihbarat Platformu (TIP); çoklu kaynaktan gelen göstergelerin toplandığı, normalleştirildiği, ilişkilendirildiği ve aşağı akış araçlara (SIEM, EDR, firewall) dağıtıldığı bir orta katman sistemdir. Yaygın açık kaynak örnekleri MISP ve OpenCTI'dir; ticari örnekler Anomali ThreatStream, Recorded Future, ThreatConnect olarak sıralanabilir.

SiberAnaliz beslemesi tek başına bir TIP değildir; "T.C. Siber Güvenlik Başkanlığı doğrulanmış verisi" başlığı altında, ulusal kaynaktan beslenen bir feed'dir. Kurumsal SOC'lerde bu feed, mevcut TIP'in besleme havuzuna bir kaynak olarak eklenir; orada diğer feed'lerle ilişkilendirilir, yorumlanır ve eyleme dönüştürülür.

2. Entegrasyon modeli: pull vs push

İki temel mimari kalıp vardır. Pull modelinde TIP belirli aralıklarla SiberAnaliz uç noktasına HTTP isteği gönderir; düşük bağ, ama TIP'in besleme planına bağlıdır. Push modelinde harici bir script SiberAnaliz'den veriyi çekip TIP'in REST API'sine yazar; daha esnek, normalizasyon kontrolü pipeline yazarına aittir.

  • P Pull — MISP "feed", OpenCTI "external-import connector", TAXII 2.1 koleksiyon polling. Operasyonel olarak en sade yol; TIP'in yerleşik scheduler'ı kullanılır.
  • PU Push — cron + Python script; veri TIP'e REST API ile yazılır. Daha fazla esneklik (özel alan ekleme, enrichment) sağlar; ama hata yönetimi pipeline yazarına aittir.

Karma yaklaşım da olağandır: ham feed pull modunda alınır, periyodik bir push script enrichment ekleyerek refined bir event olarak yeniden yazar. Hangi yolu seçtiğinizden bağımsız olarak: kaynak gösterme zorunludur. Tüm import objeleri source: SiberAnaliz / USOM etiketi ile geçmelidir.

3. MISP feed import

MISP tarafında "feed" objesi bir URL'den düzenli olarak CSV, JSON veya MISP-event JSON çeker. SiberAnaliz CSV uç noktası MISP'in Simple CSV feed tipine uygundur.

# MISP REST API ile feed oluşturma
curl -fsSL -X POST \
  -H "Authorization: $MISP_AUTHKEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  "$MISP_URL/feeds/add" \
  -d '{
    "Feed": {
      "name": "SiberAnaliz IP",
      "provider": "siberanaliz.com",
      "url": "https://siberanaliz.com/export.csv?type=ip",
      "source_format": "csv",
      "input_source": "network",
      "enabled": true,
      "caching_enabled": true,
      "delta_merge": true,
      "settings": "{\"csv\":{\"value\":2,\"delimiter\":\",\"}}"
    }
  }'

Yukarıdaki settings alanında value: 2, CSV'de 2. kolonun IoC değeri olduğunu söyler (SiberAnaliz CSV başlığında id, value, type, criticality_level, ... sırası varsayılmıştır; gerçek üretimde kolon sırası uç noktanın çıktısına göre teyit edilir). delta_merge: true ile yalnızca yeni satırlar event olarak eklenir.

# Feed'i hemen çek ve cache'le
curl -fsSL -X POST \
  -H "Authorization: $MISP_AUTHKEY" \
  -H "Accept: application/json" \
  "$MISP_URL/feeds/fetchFromFeed/$FEED_ID"

# Önbelleğe alma (cache lookup için)
curl -fsSL -X POST \
  -H "Authorization: $MISP_AUTHKEY" \
  "$MISP_URL/feeds/cacheFeeds/$FEED_ID"

4. MISP event olarak bulk import

Feed mekanizması yerine doğrudan bir MISP Event üretmek istenen durumlar da vardır: göstergelere özel galaksi etiketleri eklemek, MITRE ATT&CK tekniği bağlamak, ya da tek bir tarih için olayı kapsüllemek. Python tarafında pymisp kütüphanesi standart araçtır.

#!/usr/bin/env python3
# /usr/local/bin/sib2misp.py
import csv, io, sys
import requests
from pymisp import PyMISP, MISPEvent, MISPAttribute

MISP_URL   = "https://misp.kurum.local"
MISP_KEY   = "REDACTED"
MISP_VERIFY= True
SIB_FEED   = "https://siberanaliz.com/export.csv?type=ip"

def fetch_csv(url):
    r = requests.get(url, timeout=30)
    r.raise_for_status()
    return r.text

def build_event(rows):
    e = MISPEvent()
    e.info = "SiberAnaliz IP göstergeleri — günlük"
    e.distribution = 1   # community
    e.threat_level_id = 2
    e.analysis = 2
    e.add_tag("source:siberanaliz")
    e.add_tag("tlp:white")
    for row in rows:
        ip = row.get("value", "").strip().strip('"')
        if not ip or "." not in ip:
            continue
        a = MISPAttribute()
        a.type = "ip-dst"
        a.value = ip
        a.category = "Network activity"
        a.to_ids = True
        a.comment = f"crit={row.get('criticality_level','')}, src=USOM"
        e.add_attribute(**a.to_dict())
    return e

def main():
    raw = fetch_csv(SIB_FEED)
    reader = csv.DictReader(io.StringIO(raw))
    event = build_event(reader)
    misp = PyMISP(MISP_URL, MISP_KEY, MISP_VERIFY)
    resp = misp.add_event(event)
    print(resp.get("Event", {}).get("uuid", "FAIL"))

if __name__ == "__main__":
    sys.exit(main())

5. OpenCTI external-import connector

OpenCTI tarafında entegrasyon mimarisi connector denilen Docker konteyner tabanlı küçük servislerden oluşur. Üç connector tipi vardır: external-import (kaynaktan çekip OpenCTI'ye yazar), internal-enrichment ve stream. SiberAnaliz için doğru tip external-import'tur.

# docker-compose.yml — connector tanımı
services:
  connector-siberanaliz:
    image: opencti/connector-external-import:6.4.0
    environment:
      OPENCTI_URL: http://opencti:8080
      OPENCTI_TOKEN: $OPENCTI_TOKEN
      CONNECTOR_ID: 7c3a... # uuidgen
      CONNECTOR_TYPE: EXTERNAL_IMPORT
      CONNECTOR_NAME: "SiberAnaliz"
      CONNECTOR_SCOPE: siberanaliz
      CONNECTOR_CONFIDENCE_LEVEL: 75
      CONNECTOR_UPDATE_EXISTING_DATA: "true"
      CONNECTOR_RUN_AND_TERMINATE: "false"
      CONNECTOR_LOG_LEVEL: info
      SIB_API_URL: "https://siberanaliz.com/export.json"
      SIB_INTERVAL: 3600
    restart: always
# main.py — connector minimal iskelet
import os, time, requests
from pycti import OpenCTIConnectorHelper, get_config_variable
import stix2

class SiberAnalizConnector:
    def __init__(self):
        self.helper = OpenCTIConnectorHelper({})
        self.url = os.environ["SIB_API_URL"]
        self.interval = int(os.environ.get("SIB_INTERVAL", 3600))

    def run(self):
        while True:
            try:
                self.helper.log_info("SiberAnaliz pull başlatıldı")
                data = requests.get(self.url, timeout=60).json()
                bundle_objects = []
                for it in data.get("items", []):
                    t = it.get("type")
                    v = it.get("value")
                    if t == "ip":
                        ind = stix2.Indicator(
                            name=f"SiberAnaliz IP {v}",
                            pattern=f"[ipv4-addr:value = '{v}']",
                            pattern_type="stix",
                            valid_from=it.get("seen_at"),
                            labels=["siberanaliz","usom"],
                            confidence=75,
                        )
                        bundle_objects.append(ind)
                bundle = stix2.Bundle(objects=bundle_objects, allow_custom=True)
                self.helper.send_stix2_bundle(bundle.serialize())
            except Exception as e:
                self.helper.log_error(str(e))
            time.sleep(self.interval)

if __name__ == "__main__":
    SiberAnalizConnector().run()

6. STIX 2.1 / TAXII 2.1 ile sunum

STIX (Structured Threat Information Expression) tehdit istihbaratı verisi için JSON tabanlı bir nesne modelidir; TAXII ise STIX nesnelerini taşıyan HTTP protokolüdür. Kurumsal TIP'lerin büyük çoğunluğu STIX 2.1 / TAXII 2.1 ile uyumludur.

SiberAnaliz CSV/JSON çıktısı doğrudan STIX değildir; bir indikatörün STIX'e dönüşmesi indicator nesnesi ve uygun bir desen (pattern) ifadesi ile mümkündür:

{
  "type": "bundle",
  "id": "bundle--7c3a...",
  "objects": [
    {
      "type": "indicator",
      "spec_version": "2.1",
      "id": "indicator--a1b2c3...",
      "created": "2026-05-27T08:00:00Z",
      "modified": "2026-05-27T08:00:00Z",
      "name": "SiberAnaliz IP 203.0.113.10",
      "pattern": "[ipv4-addr:value = '203.0.113.10']",
      "pattern_type": "stix",
      "valid_from": "2026-05-26T23:00:00Z",
      "labels": ["malicious-activity"],
      "external_references": [
        {
          "source_name": "SiberAnaliz",
          "url": "https://siberanaliz.com/tehdit/ip/203-0-113-10"
        }
      ]
    }
  ]
}

Domain için desen [domain-name:value = 'ornek.tld'], URL için [url:value = 'https://...'] şeklindedir. Hash desenleri ise [file:hashes.'SHA-256' = '...'] kalıbındadır. Bu nesneleri bir TAXII 2.1 server'ında (örneğin medallion) yayınlayarak tüm uyumlu TIP'lerin tek bir endpoint üzerinden pull yapmasını sağlayabilirsiniz.

7. ThreatBus / Stratosphere köprüsü

ThreatBus (Tenzir) ve Stratosphere gibi açık kaynak köprüler, çoklu TIP/SIEM/IDS arasında STIX 2.1 mesajlarını ZeroMQ veya Kafka pub-sub kanalları üzerinden taşır. SiberAnaliz beslemesi bir ThreatBus plugin'i olarak yazıldığında; MISP, OpenCTI ve Suricata aynı kaynaktan beslenir.

# threatbus config.yaml — örnek
plugins:
  apps:
    misp:
      api:
        host: https://misp.kurum.local
        ssl: true
        key: REDACTED
      topic: misp
    siberanaliz:
      url: https://siberanaliz.com/export.json
      poll_interval: 3600
      topic: siberanaliz
  backbones:
    zmq:
      host: 127.0.0.1
      pub: 13370
      sub: 13371

8. Cron tabanlı polling pipeline

TIP entegrasyonu kurmaksızın yalnızca SIEM veya firewall'a doğrudan veri sürmek isteyen ekipler için en sade akış cron + curl ya da cron + Python'dur. Aşağıdaki örnek; SiberAnaliz beslemesini çekip yerel bir .json dosyasına yazar, sonra yerel pipeline'a (Logstash, Vector, Fluent Bit) tail ile besletir.

# /etc/cron.d/siberanaliz-pull
# Saat başını 7 dakika geç tetikle (kaynak rate-limit'e nazik davranmak için)
7 * * * * sibops /usr/local/bin/siberanaliz-pull.sh \
              >> /var/log/siberanaliz-pull.log 2>&1
# /usr/local/bin/siberanaliz-pull.sh
#!/usr/bin/env bash
set -euo pipefail

SRC="https://siberanaliz.com/export.json"
DST="/var/lib/threat-intel/siberanaliz.ndjson"
TMP="$(mktemp)"

curl -fsSL --retry 3 --max-time 60 \
     -H "Accept: application/json" \
     -A "siberanaliz-puller/1.0 (sibops@kurum.tr)" \
     -o "$TMP" "$SRC"

# JSON dizisini NDJSON satırlarına çevir (Vector/Logstash dostu)
jq -c '.items[]' "$TMP" >> "$DST"

# Eski veriyi temizle (30 günden eski satır)
find "$(dirname "$DST")" -name "siberanaliz.ndjson" -mtime +30 -delete

9. Python istemci örneği

Kendi pipeline'ınızı yazıyorsanız, aşağıdaki kütüphane sayfalı /api/addresses uç noktasını rate-limit'e nazik davranarak tüketir. Üretimde retry/backoff, timeout ve HTTP cache başlıkları (If-Modified-Since) ekleyin.

#!/usr/bin/env python3
# /usr/local/lib/python3/sibclient.py
import time
import requests
from typing import Iterator, Dict, Any

API = "https://siberanaliz.com/api/addresses"

class SibClient:
    def __init__(self, per_page: int = 100, ua: str = "sibclient/1.0"):
        self.per_page = per_page
        self.s = requests.Session()
        self.s.headers.update({"User-Agent": ua, "Accept": "application/json"})

    def iter_all(self, type_: str = "domain") -> Iterator[Dict[str, Any]]:
        page = 1
        while True:
            r = self.s.get(
                API,
                params={"type": type_, "page": page, "per_page": self.per_page},
                timeout=30,
            )
            r.raise_for_status()
            data = r.json()
            items = data.get("items") or []
            if not items:
                break
            yield from items
            if len(items) < self.per_page:
                break
            page += 1
            # rate-limit'e nazik gecikme
            time.sleep(0.5)


if __name__ == "__main__":
    # SiberAnaliz API'sinde IoC değeri "url" alanında döner; bu alan
    # tip ne olursa olsun (domain/url/ip/ip6) gösterge değerini taşır.
    # OpenCTI/MISP entegrasyonunda kendi şemanıza map'lerken bu noktaya dikkat:
    #   value = it["url"]   # NOT it["value"]
    for it in SibClient().iter_all("domain"):
        value = it["url"]
        criticality = it.get("criticality_level")
        category = it.get("desc")          # ör. "PH", "MD", "BP"
        connection = it.get("connectiontype")
        print(value, criticality, category, connection)

Alan adı notu: SiberAnaliz JSON şemasında IoC değeri tip ne olursa olsun url alanında döner (örn. type=ip için url="185.212.47.73"). CSV'de ise 2. kolon (header: URL) aynı amaca hizmet eder. OpenCTI/MISP/STIX konnektöründe kendi şemanıza map'lerken bu adlandırma farkı kaynak hatalarının en sık nedenidir.

Veri kalitesi ve deduplication

Bir TIP, doğası gereği birden çok kaynaktan beslenir: ticari beslemeler, CERT paylaşımları, OSINT toplayıcıları, dahili gözlemler ve SiberAnaliz gibi ulusal kaynaklı feed'ler. Aynı IP veya domain birden çok kaynakta görünebileceğinden, TIP'in iç deduplication mantığı ile her göstergenin tek bir kanonik objeye bağlanması gerekir. MISP tarafında bu uuid eşleştirmesi ve correlation mekanizması ile, OpenCTI tarafında standard ID üzerinden çözülür.

Operasyonel kural: import sırasında kaynak çoğullaması korunur. Yani SiberAnaliz ve başka bir feed aynı IP'yi yayınlıyorsa, gösterge tek bir obje olarak kalır ama external_references listesinde her iki kaynak da yer alır. Bu, analistin "neden bu IP zararlı?" sorusuna birden fazla doğrulayıcı görerek cevap verebilmesini sağlar.

Gösterge yaşam döngüsü ve eskime

Tehdit göstergesi statik değildir; saldırgan altyapısı sürekli değişir. Bir IP veya domain bugün C2 olabilir, üç ay sonra meşru bir hosting müşterisine yeniden tahsis edilebilir. Bu nedenle TIP içinde her göstergenin valid_from ve valid_until alanları kritiktir. SiberAnaliz beslemesinde resmi kaynak göstergeyi listeden düşürdüğünde, TIP tarafında ilgili indicator revoked bayrağı ile işaretlenmeli ya da aşağı akış sistemlerin engelleme listesinden çıkarılmalıdır.

Pratikte iki yaklaşım vardır. Birincisi hard revoke: kaynak listeden kaybolan gösterge TIP'te de derhal devre dışı bırakılır. İkincisi soft revoke: gösterge devre dışı kalır ama TIP içinde geçmiş referans olarak korunur (forensic ve trend analizi için). SiberAnaliz tarafı için ikincisi önerilir; bir IP'nin tarihçesini bilmek, gelecekteki incident'larda pivot point sağlar.

Konnektör tarafında yaşam döngüsü yönetimi şöyle kurulur: her pull iterasyonunda mevcut SiberAnaliz listesi ile TIP'teki "SiberAnaliz kaynaklı" gösterge kümesi karşılaştırılır. Listede olmayıp TIP'te olanlar (silinmiş göstergeler) revoke edilir; her ikisinde olanlar modified tarihi güncellenerek tutulur; sadece listede olanlar yeni indicator olarak yazılır.

Kontrol Listesi

  • 1 Entegrasyon modeli (pull / push / karma) seçildi ve dokümante edildi.
  • 2 SiberAnaliz uç noktasına HTTPS çıkış erişimi olan bir entegrasyon sunucusu hazırlandı.
  • 3 Tüm import edilen IoC nesnelerine source: SiberAnaliz/USOM etiketi eklendi.
  • 4 TIP içinde feed'in confidence/severity haritalaması bir kez yapıldı.
  • 5 Polling aralığı (önerilen: 60 dk) yapılandırıldı; daha sık çekim sunucu için tüketici dostu değil.
  • 6 Pipeline log'u izleniyor ve hata bildirimi (e-mail, Slack, PagerDuty) aktif.
  • 7 TLP/sharing seviyesi (TLP:WHITE ya da kurumsal politika) doğru ayarlandı.
  • 8 Aşağı akış sistemler (SIEM/EDR/firewall) TIP'ten beslemeyi geri doğrulayan bir test ile teyit edildi.

SiberAnaliz Verisi ile Hızlı Başlangıç

SiberAnaliz; resmi T.C. Siber Güvenlik Başkanlığı feed'i için yetkili bir API yayımlamaz, ancak portalın sunum katmanına ait üç teknik dışa aktarım uç noktası sunar. Pre-built indirme: günde bir kez üretilen gzip CSV/JSON dosyaları /indir üzerinden — en hızlı yol, sunucuda ek yük yaratmaz, SHA-256 doğrulamalı. Filtreli streaming: /export.csv ve /export.json; tek tip filtresinde hazır dosyaya 302 yönlendirir, kritiklik/kategori/tarih gibi özel filtrelerde canlı. Sayfalı erişim: /api/addresses; rate-limit dostu iteration için ideal.