Skip to content

caidongyun/iocs

Repository files navigation

IOC 协作工具

威胁情报(IOC — Indicators of Compromise)协作项目,用于收集、整理、检索恶意指标。


一、需求

1.1 背景

  • 团队通过多方渠道采集威胁情报 IOC(域名、IP、文件 Hash)
  • 原始数据以 CSV 格式提供,需要统一解析、去重、清洗后入库
  • 入库后供本地检测使用(检测主机/网络流量中是否存在已知恶意指标)

1.2 核心功能

功能 说明
CSV 解析 将原始 CSV 转换为统一 JSON 格式
去重合并 新旧 IOC 对比,去除重复条目
备注清洗 移除备注中的内部告警词和来源标识
完整性校验 SHA256 索引文件,验证 IOC 库未被篡改
本地检测 给定域名/IP/Hash/文件,查询是否在黑名单中
白名单过滤 排除权威可信站点(.qq.com),避免误报
Git 协作 同步到 GitHub/Gitee,多人协作

1.3 数据规模

当前总计:2920 条

批次 日期范围 数量
iocs.json 2026-03-25 ~ 2026-04-29 2316
iocs-20260605.json 2026-04-30 ~ 2026-06-05 604
合计 2920

二、规范

2.1 上传规则

文件 说明 上传
index.json 主索引(SHA256,指向所有批次)
data/processed/iocs.json IOC 数据库(初始批次)
data/processed/iocs-YYYYMMDD.json IOC 数据库(新批次)
src/*.py 工具脚本
src/sensitive_words.txt 敏感词清单
RELEASES.md 版本记录
AUTOMATION.md 运维指南
CHANGELOG-*.json 变更报告
whitelist.txt 白名单 ❌ 本地
*.csv CSV 原始文件 ❌ 不上传
SPEC.md 本地规范 ❌ 不上传
.env Token 配置 ❌ 不上传

2.2 数据规范

IOC JSON 条目格式:

{
  "ioc": "evil.com",
  "type": "域名",
  "action": "拉黑",
  "threat_type": "钓鱼仿冒",
  "发现日期": "2026/03/25",
  "备注": "钓鱼仿冒知名企业",
  "source_file": "IOC情报协作_IOC_IOC-3.25-2.csv",
  "added_date": "2026-03-25"
}

字段规则:

字段 必填 说明
ioc IOC 值(域名/IP/Hash)
type 类型:域名 / IP / Hash
action 处置动作,如"拉黑"
threat_type 威胁类型,如"钓鱼仿冒"
发现日期 原始发现日期
备注 备注信息,将被清洗
source_file 来源 CSV 文件名
added_date 入库日期(自动)
platform 平台加黑,不采集

2.3 备注清洗规范

以下关键词在入库时将被自动移除:

  • 内部告警产品标识
  • 来源标识
  • 外部产品标识

2.4 白名单规范

  • 来源:用户编辑 whitelist.txt,不上传 Git
  • 格式:每行一个域名或后缀
  • 匹配
    • 精确匹配:qq.com → 匹配 qq.com
    • 后缀匹配:.qq.com → 匹配 api.qq.commp.weixin.qq.com
  • 作用时机:加载时过滤 + 检测时二次验证

2.5 Git 提交规范

前缀 说明 示例
feat: 新功能、工具 feat: add whitelist support
clean: 数据清理 clean: remove lidar alerts from remarks
regen: 重新生成 IOC 库 regen: from new CSV
fix: 修复问题 fix: dedup logic error
docs: 文档更新 docs: rewrite README

三、架构

3.1 技术栈

  • 语言:Python 3
  • 版本管理:Git(GitHub + Gitee 双平台)
  • 数据格式:JSON
  • 校验方式:SHA256

3.2 目录结构

D:\IOC-src\
├── index.json                  # 主索引(SHA256,指向所有批次)
├── data/
│   └── processed/
│       ├── iocs.json           # 初始批次(2026-03-25 ~ 2026-04-29,2316 条)
│       └── iocs-20260605.json  # 新批次(2026-04-30 ~ 2026-06-05,604 条)
├── src/
│   ├── ioc_parser.py           # CSV → JSON 解析器
│   ├── ioc_sync.py             # Git 同步脚本
│   ├── ioc_checker.py          # 本地 IOC 检测器
│   ├── ioc_clean.py            # 备注清洗工具(从 sensitive_words.txt 加载)
│   ├── ioc_validate.py         # 数据质量校验
│   ├── ioc_publish.py          # 发布报告生成(批次兼容)
│   ├── ioc_filter_date.py      # 日期过滤
│   ├── ioc_preflight.py        # 发布前自动检查
│   └── sensitive_words.txt     # 敏感词清单
├── RELEASES.md                 # 版本发布记录
├── AUTOMATION.md               # 运维操作指南
├── CLAUDE.md                   # AI 助手操作指南
├── run_pipeline.sh             # 一键处理管道
├── sync.sh                     # 快捷同步脚本
├── whitelist.txt               # 域名白名单(本地,不上传)
├── .gitignore                  # 忽略规则
├── README.md                   # 本文件
├── SPEC.md                     # 本地规范(不上传)
└── .env                        # Token 配置(不上传)

3.3 数据流

CSV 文件(原始)
    ↓
ioc_filter_date.py → 按日期过滤老数据(可选)
    ↓
解析去重      → 写入独立批次文件 iocs-YYYYMMDD.json
    ↓
ioc_clean.py    →  清洗备注(自动移除内部告警词)
    ↓
ioc_validate.py →  数据质量校验(格式、去重、白名单)
    ↓
ioc_preflight.py →  发布前自动检查(SHA256/敏感词/git 状态)
    ↓
ioc_publish.py  →  生成 CHANGELOG + 更新 RELEASES.md + 更新 index.json
    ↓
git add → commit → tag → push → GitHub / Gitee

3.4 批次文件设计

随着 IOC 数据增长,采用分批次独立文件 + 统一索引的架构:

data/processed/
├── iocs.json                    ← 初始批次(2026-03-25 ~ 2026-04-29,2316 条)
├── iocs-20260605.json           ← 新批次(2026-04-30 ~ 2026-06-05,604 条)
└── iocs-YYYYMMDD.json           ← 后续批次按此命名

原则:

  • 已有批次文件不会被修改iocs.json 始终不变)
  • 每个新批次写入独立 JSON 文件,文件名以日期标识
  • 下游可只拉取增量批次,无需全量重新下载
  • index.json 通过 files[] 数组统一索引所有批次

四、对外监控接口

外部消费者(下游系统、合作方、自动化监控)通过以下方式追踪 IOC 变化:

4.1 监控 index.json

index.json 是唯一入口,包含所有批次文件的索引和校验:

当前实际内容:

{
  "total_count": 2920,
  "last_updated": "2026-06-05T07:15:20Z",
  "files": [
    {
      "filename": "data/processed/iocs.json",
      "sha256": "5d85eeee8d4eda4be58bfa54791a35a1b3552a14a60fb3848458421c0923f5fc",
      "batch_date": "2026-04-29",
      "record_count": 2316
    },
    {
      "filename": "data/processed/iocs-20260605.json",
      "sha256": "60dfbcdf31e2050b8510629c26737a5c63bdb0260e5eb8c96bfdf09dc735c0d9",
      "batch_date": "2026-06-05",
      "record_count": 604
    }
  ]
}
字段 含义 监控方式
total_count IOC 总数(所有批次合计) 数值变化 = 数量增减
last_updated 最后更新时间 时间变化 = 有新发布
files[] 所有批次文件列表 数组变长 = 新批次
files[].sha256 对应文件的指纹 值变化 = 文件变更
files[].batch_date 批次日期 识别新批次时间范围
files[].record_count 该批次的 IOC 数量 了解各批次规模

增量下载示例:

# 1. 获取 index.json 发现新批次
curl -s https://.../index.json | jq '.files[-1]'

# 2. 只下载新批次
curl -O https://.../data/processed/iocs-20260605.json

# 3. 校验完整性
sha256sum iocs-20260605.json | jq -r '.files[-1].sha256'  # 对比

4.2 监控 RELEASES.md

每次发布在文件末尾追加版本记录,消费者通过 Git diff 获取变更:

git diff HEAD~1 -- RELEASES.md

4.3 监控 CHANGELOG-*.json

每次发布生成机器可读的变更报告 CHANGELOG-<version>.json,包含:

{
  "version": "v1.2.0-20260401",
  "summary": { "total_before": 1855, "total_after": 2100, "added": 250, "removed": 5 },
  "by_type": { "域名": 1200, "IP": 358, "Hash": 704 },
  "diff": { "added": 250, "removed": 5, "added_by_type": {...}, "removed_by_type": {...} },
  "sha256": "..."
}

4.4 Git 标签

每次发布打语义化版本标签,消费者可订阅 tag 推送:

# 列出所有版本
git tag -l 'v*'

# 查看某个版本的索引
git show v1.3.0-20260605:index.json | jq '.files'

# 查看某个版本的全部批次
git show v1.3.0-20260605:data/processed/iocs.json | wc -l
git show v1.3.0-20260605:data/processed/iocs-20260605.json | wc -l

4.5 兼容性保证

承诺 说明
已有批次文件只写不改 data/processed/iocs.json 等已发布的批次文件不会再修改
字段不删 已发布的 JSON 字段不会被移除,只会新增
类型不增删 域名/IP/Hash/URL 类型枚举稳定
索引结构不变 index.json 顶层字段和 files[] 结构稳定

五、运维操作

5.1 一键处理新 CSV

# 新 CSV 不含老数据,直接处理
bash run_pipeline.sh "IOC情报协作_IOC_IOC-4.01.csv" "v1.2.0-20260401" "新增 4 月 IOC"

# 新 CSV 包含老数据,按日期过滤(从 2026-03-25 开始提取)
bash run_pipeline.sh "新文件.csv" --from "2026/03/25" -v "v1.2.0-20260401" -m "新增 4 月 IOC"

自动完成:日期过滤 → 解析 → 合并去重 → 清洗 → 校验 → 发布报告 → 提交推送。

5.2 单步操作(调试用)

# 日期过滤(从指定日期开始提取)
python src/ioc_filter_date.py "新文件.csv" "2026/03/25"

# 解析合并去重(写入独立批次文件)
# ... 解析逻辑将新 IOC 写入 data/processed/iocs-YYYYMMDD.json ...

# 清洗备注
python src/ioc_clean.py data/processed/iocs-YYYYMMDD.json

# 校验数据质量
python src/ioc_validate.py data/processed/iocs-YYYYMMDD.json

# 发布前检查(自动校验 index.json 一致性、敏感词、git 状态)
python src/ioc_preflight.py --batch-file iocs-YYYYMMDD.json

# 生成发布报告
python src/ioc_publish.py --version v1.3.0-20260605 --message "新增 IOC" --batch-file iocs-YYYYMMDD.json

5.3 IOC 检测

# 检测域名
python src/ioc_checker.py --domain evil.com

# 检测 IP
python src/ioc_checker.py --ip 1.2.3.4

# 检测文件 hash
python src/ioc_checker.py --hash abc123...

# 检测文件本身
python src/ioc_checker.py --file suspicious.exe

5.4 发布前检查

# 自动运行全部检查
python src/ioc_preflight.py --batch-file iocs-YYYYMMDD.json

# 检查项:
#   ✅ index.json SHA256 一致性
#   ✅ 批次文件格式一致性
#   ✅ 敏感词扫描(IOC 备注 + 公开文件)
#   ✅ git staged 状态(是否含不该提交的文件)
#   ✅ JSON 格式合法性

六、版本历史

详见 RELEASES.md

日期 版本 变更说明
2026-06-05 v1.3.0 新增 604 条 IOC(4.30-6.5);批次架构改造;新增发布前检查脚本
2026-04-29 v1.2.0 新增 461 条 IOC(3.26-4.29);新增发布规范、监控接口
2026-03-26 v1.1.0 新增白名单机制、重写 README
2026-03-25 v1.0.0 初始版本,含 CSV 解析、检测、清洗、同步

版本变更详情

v1.3.0-20260605 — 2026-06-05
  • 新增: 604 条 IOC(4.30-6.5 批次),去重后净增
  • 移除: 0 条
  • 批次文件: iocs-20260605.json
  • .hl.cn 聚合: 187 个子域名 → 1 条根域名拉黑
  • SHA256: 60dfbcdf31e2050b8510629c26737a5c63bdb0260e5eb8c96bfdf09dc735c0d9
v1.2.0-20260429 — 2026-04-29
  • 新增: 461 条 IOC(3.26-4.29 批次)
  • 移除: 0 条
  • SHA256: c7bc505cdc6f92b0ebcb066efa6584f42eafc967d606c9643775af89e47d8887

七、安全运营人员使用指南

7.1 首次接入

# 1. 获取索引文件,了解有哪些批次
curl -s https://raw.githubusercontent.com/caidongyun/iocs/master/index.json | jq '.'

# 2. 下载指定批次(首次建议全量下载所有批次)
curl -O https://raw.githubusercontent.com/caidongyun/iocs/master/data/processed/iocs.json
curl -O https://raw.githubusercontent.com/caidongyun/iocs/master/data/processed/iocs-20260605.json

# 3. 校验文件完整性(对比 index.json 中的 sha256)
sha256sum data/processed/iocs.json
sha256sum data/processed/iocs-20260605.json
# 输出应与 index.json 中对应条目的 sha256 一致

7.2 增量更新

# 定期检查 index.json 是否有新批次
OLD_COUNT=$(cat index.json | jq '.total_count')
curl -s https://raw.githubusercontent.com/caidongyun/iocs/master/index.json > index_new.json
NEW_COUNT=$(cat index_new.json | jq '.total_count')

if [ "$NEW_COUNT" -gt "$OLD_COUNT" ]; then
    echo "有新 IOC,数量从 $OLD_COUNT 增加到 $NEW_COUNT"
    # 获取新批次文件列表
    jq -r '.files[].filename' index_new.json
    # 下载最新批次
    curl -O https://raw.githubusercontent.com/caidongyun/iocs/master/data/processed/iocs-20260605.json
fi

7.3 本地检测集成

IOC JSON 格式标准字段:

字段 类型 说明
ioc string IOC 值(域名/IP/Hash/URL)
type string 类型:域名 / IP / Hash / URL / 路径 / 邮箱
action string 处置动作(如"拉黑")
threat_type string 威胁类型分类
发现日期 string 原始发现日期
备注 string 备注信息(已清洗内部标识)
source_file string 来源 CSV 文件名
added_date string 入库日期

检测示例(Python):

import json, hashlib

# 加载所有批次
iocs = []
for f in ['iocs.json', 'iocs-20260605.json']:
    with open(f'data/processed/{f}', encoding='utf-8') as fh:
        iocs.extend(json.load(fh))

# 构建快速查找索引
domain_set = {x['ioc'] for x in iocs if x['type'] == '域名'}
ip_set = {x['ioc'] for x in iocs if x['type'] == 'IP'}
hash_set = {x['ioc'] for x in iocs if x['type'] == 'Hash'}

# 检测
def check_domain(domain):
    if domain in domain_set:
        return 'MATCH'
    # 子域名匹配:检查父域名
    parts = domain.split('.')
    for i in range(1, len(parts)):
        parent = '.'.join(parts[i:])
        if parent in domain_set:
            return f'MATCH (parent: {parent})'
    return 'OK'

7.4 误报上报

如发现有误报(正常业务域名/IP 被拉黑),请:

  1. 提交 GitHub Issue,标注 [误报]
  2. 提供误报 IOC 值、命中批次、影响说明
  3. 团队核实后会在下一版本中移除

7.5 API/自动化集成

通过 index.json 实现完全自动化的 IOC 同步:

import requests, json, hashlib

INDEX_URL = 'https://raw.githubusercontent.com/caidongyun/iocs/master/index.json'
BASE_URL = 'https://raw.githubusercontent.com/caidongyun/iocs/master/'

def sync_iocs(local_index):
    """增量同步 IOC"""
    remote = requests.get(INDEX_URL).json()

    # 找出本地没有的新批次
    local_files = {e['filename'] for e in local_index.get('files', [])}
    new_files = [e for e in remote['files'] if e['filename'] not in local_files]

    for entry in new_files:
        url = BASE_URL + entry['filename']
        content = requests.get(url).content
        actual_sha = hashlib.sha256(content).hexdigest()

        if actual_sha != entry['sha256']:
            print(f'警告: {entry["filename"]} SHA256 不匹配,跳过')
            continue

        with open(entry['filename'], 'wb') as f:
            f.write(content)
        print(f'已下载: {entry["filename"]} ({entry["record_count"]} 条)')

    return remote

致谢

感谢以下成员对本项目的贡献:

  • 夏志鹏
  • 孙子鹏
  • 吴浩
  • 牛星岩

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors