L’interface est localisée ; les présentations et documents des Skills sont traduits automatiquement par IA dans votre langue. Le code, les commandes, chemins et termes techniques restent en version originale, et le document de l’auteur fait foi.
Explorer les Skills
Données et recherche · SKILL.md

performing-ip-reputation-analysis-with-shodan

performing-ip-reputation-analysis-with-shodan

使用 Shodan API 分析 IP 地址声誉,识别开放端口、运行服务、已知漏洞和托管上下文,用于威胁情报富化和事件分类。

Independent GitHub snapshot · Automated classification · Original documentation governs

Documentation de la Skill

GitHub

name: performing-ip-reputation-analysis-with-shodan description: 使用 Shodan API 分析 IP 地址声誉,识别开放端口、运行服务、已知漏洞和托管上下文,用于威胁情报富化和事件分类。 domain: cybersecurity subdomain: threat-intelligence tags: [shodan, ip-reputation, enrichment, threat-intelligence, reconnaissance, vulnerability, api, internet-scanning] version: "1.0" author: mahipal license: Apache-2.0

使用 Shodan 执行 IP 声誉分析

概述

Shodan 是全球首个互联网设备搜索引擎,持续扫描 IPv4 和 IPv6 地址空间,记录开放端口、运行服务、SSL 证书和已知漏洞。本技能涵盖使用 Shodan API 和 InternetDB 免费 API 富化来自安全告警的 IP 地址、根据暴露服务和漏洞评估威胁级别、识别托管基础设施模式,以及将 IP 声誉数据集成到 SOC 分类和威胁情报工作流中。

前置条件

  • Python 3.9+,安装 shodan 库(pip install shodan)
  • Shodan API 密钥(免费版:查询受限;付费版支持更高限额和流式传输)
  • 了解 TCP/UDP 端口、常见服务和 CVE 标识符
  • 熟悉 ASN、CIDR 表示法和 IP 地理定位概念
  • 具备解读扫描结果的网络安全知识

核心概念

Shodan 数据模型

Shodan 中的每条 IP 记录包含:开放端口和协议、Banner 数据(服务响应)、SSL/TLS 证书详情、已知 CVE 漏洞、主机名和反向 DNS、ASN 和 ISP 信息、地理位置、操作系统指纹,以及显示变化历史的历史扫描数据。

InternetDB API

Shodan 的免费 InternetDB API(internetdb.shodan.io)无需身份验证即可快速查询 IP,返回开放端口、主机名、标签、CPE 和已知漏洞。适用于全量 Shodan API 可能触及速率限制的高容量富化场景。

声誉评分

通过以下维度综合评估 IP 声誉:开放端口数量和类型(异常端口表明可能遭到攻陷)、易受攻击服务(含已知 CVE 的未修补软件)、托管类型(住宅、云端、VPN/代理、防弹托管)、历史活动(过去与恶意软件、扫描、垃圾邮件的关联),以及地理背景(以特定威胁活动著称的国家/地区)。

操作步骤

步骤 1:使用 Shodan API 进行基础 IP 富化

import shodan
import json
from datetime import datetime

class ShodanEnricher:
    def __init__(self, api_key):
        self.api = shodan.Shodan(api_key)
        self.info = self.api.info()
        print(f"[+] Shodan API 已初始化。剩余扫描积分:{self.info.get('scan_credits', 0)}")

    def enrich_ip(self, ip_address):
        """通过 Shodan 对 IP 地址进行完整富化。"""
        try:
            host = self.api.host(ip_address)
            enrichment = {
                "ip": ip_address,
                "organization": host.get("org", ""),
                "asn": host.get("asn", ""),
                "isp": host.get("isp", ""),
                "country": host.get("country_name", ""),
                "country_code": host.get("country_code", ""),
                "city": host.get("city", ""),
                "latitude": host.get("latitude"),
                "longitude": host.get("longitude"),
                "os": host.get("os", ""),
                "ports": host.get("ports", []),
                "hostnames": host.get("hostnames", []),
                "domains": host.get("domains", []),
                "vulns": host.get("vulns", []),
                "tags": host.get("tags", []),
                "last_update": host.get("last_update", ""),
                "services": [],
            }

            for service in host.get("data", []):
                svc = {
                    "port": service.get("port", 0),
                    "transport": service.get("transport", "tcp"),
                    "product": service.get("product", ""),
                    "version": service.get("version", ""),
                    "module": service.get("_shodan", {}).get("module", ""),
                    "banner": service.get("data", "")[:200],
                }
                if "ssl" in service:
                    svc["ssl_subject"] = service["ssl"].get("cert", {}).get("subject", {})
                    svc["ssl_issuer"] = service["ssl"].get("cert", {}).get("issuer", {})
                    svc["ssl_expires"] = service["ssl"].get("cert", {}).get("expires", "")
                enrichment["services"].append(svc)

            # 计算声誉评分
            enrichment["reputation"] = self._calculate_reputation(enrichment)
            print(f"[+] {ip_address}:{len(enrichment['ports'])} 个端口,"
                  f"{len(enrichment['vulns'])} 个漏洞,"
                  f"声誉等级:{enrichment['reputation']['level']}")
            return enrichment

        except shodan.APIError as e:
            print(f"[-] {ip_address} 的 Shodan 查询出错:{e}")
            return None

    def _calculate_reputation(self, data):
        """根据 Shodan 数据计算 IP 声誉评分。"""
        score = 0
        factors = []

        # 漏洞评估
        vuln_count = len(data.get("vulns", []))
        if vuln_count > 10:
            score += 40
            factors.append(f"{vuln_count} 个已知漏洞")
        elif vuln_count > 5:
            score += 25
            factors.append(f"{vuln_count} 个已知漏洞")
        elif vuln_count > 0:
            score += 10
            factors.append(f"{vuln_count} 个已知漏洞")

        # 可疑端口分析
        suspicious_ports = {4444, 5555, 6666, 8888, 9090, 1234, 31337,
                           6667, 6697, 8080, 8443, 3128, 1080}
        open_ports = set(data.get("ports", []))
        sus_found = open_ports.intersection(suspicious_ports)
        if sus_found:
            score += 15
            factors.append(f"可疑端口:{sus_found}")

        # 基于标签的评估
        malicious_tags = {"self-signed", "cloud", "vpn", "proxy", "tor"}
        tags = set(data.get("tags", []))
        mal_tags = tags.intersection(malicious_tags)
        if mal_tags:
            score += 10
            factors.append(f"标签:{mal_tags}")

        # 开放端口过多
        port_count = len(data.get("ports", []))
        if port_count > 20:
            score += 15
            factors.append(f"开放端口过多({port_count} 个)")

        level = (
            "critical" if score >= 50
            else "high" if score >= 35
            else "medium" if score >= 15
            else "low"
        )

        return {"score": score, "level": level, "factors": factors}

    def enrich_ip_free(self, ip_address):
        """使用免费 InternetDB API 快速富化 IP。"""
        import requests
        resp = requests.get(f"https://internetdb.shodan.io/{ip_address}", timeout=10)
        if resp.status_code == 200:
            data = resp.json()
            print(f"[+] InternetDB:{ip_address} -> "
                  f"{len(data.get('ports', []))} 个端口,"
                  f"{len(data.get('vulns', []))} 个漏洞")
            return data
        return None

enricher = ShodanEnricher("YOUR_SHODAN_API_KEY")
result = enricher.enrich_ip("8.8.8.8")
print(json.dumps(result, indent=2, default=str))

步骤 2:批量 IP 声誉检查

import time

def batch_ip_reputation(enricher, ip_list, output_file="ip_reputation.json"):
    """检查 IP 地址列表的声誉。"""
    results = []
    for i, ip in enumerate(ip_list):
        result = enricher.enrich_ip(ip)
        if result:
            results.append(result)
        if (i + 1) % 10 == 0:
            print(f"  [{i+1}/{len(ip_list)}] 已处理")
            time.sleep(1)  # 速率限制

    # 按声誉评分降序排列(最高风险在前)
    results.sort(key=lambda x: x.get("reputation", {}).get("score", 0), reverse=True)

    with open(output_file, "w") as f:
        json.dump(results, f, indent=2, default=str)

    # 汇总
    levels = {"critical": 0, "high": 0, "medium": 0, "low": 0}
    for r in results:
        level = r.get("reputation", {}).get("level", "low")
        levels[level] += 1

    print(f"\n=== 批量声誉汇总 ===")
    print(f"IP 总数:{len(results)}")
    for level, count in levels.items():
        print(f"  {level.upper()}:{count}")

    return results

suspicious_ips = ["203.0.113.1", "198.51.100.5", "192.0.2.100"]
results = batch_ip_reputation(enricher, suspicious_ips)

步骤 3:基础设施关联

def correlate_infrastructure(enricher, ip_address):
    """根据共享属性发现相关基础设施。"""
    host_data = enricher.enrich_ip(ip_address)
    if not host_data:
        return {}

    correlations = {
        "same_org": [],
        "same_asn": [],
        "shared_ssl": [],
    }

    # 搜索同一组织
    org = host_data.get("organization", "")
    if org:
        try:
            results = enricher.api.search(f'org:"{org}"', limit=20)
            for match in results.get("matches", []):
                correlations["same_org"].append({
                    "ip": match.get("ip_str", ""),
                    "port": match.get("port", 0),
                    "product": match.get("product", ""),
                })
        except shodan.APIError:
            pass

    # 搜索相同 SSL 证书
    for service in host_data.get("services", []):
        ssl_subject = service.get("ssl_subject", {})
        if ssl_subject:
            cn = ssl_subject.get("CN", "")
            if cn:
                try:
                    results = enricher.api.search(f'ssl.cert.subject.CN:"{cn}"', limit=20)
                    for match in results.get("matches", []):
                        correlations["shared_ssl"].append({
                            "ip": match.get("ip_str", ""),
                            "cn": cn,
                        })
                except shodan.APIError:
                    pass

    print(f"[+] {ip_address} 的基础设施关联:")
    print(f"  同一组织:{len(correlations['same_org'])} 台主机")
    print(f"  共享 SSL:{len(correlations['shared_ssl'])} 台主机")
    return correlations

验收标准

  • Shodan API 经正确身份验证后查询成功
  • IP 富化返回端口、服务、漏洞和地理定位信息
  • 声誉评分按威胁级别对 IP 进行分类
  • 批量富化正确处理速率限制
  • 基础设施关联识别相关主机
  • InternetDB 免费 API 用于高容量查询

参考资料

Skills enregistrées