Wazuh-rule与飞书通知

rule编写

任务目标

  1. 查看modsec拦截是是否匹配到相关rule,如果有其id是多少,没有则自定义一条
  2. 或扩展上面为 同一IP 60秒内被拦截20次自动封禁
  3. 添加集成,限定相关组,或rule id 实现封禁名单通知 飞书
  4. 后续自动化封禁IP

找到modsecurity拦截的规则

id 30411

level 7

可使用搜索:

复制代码
rule.level: 7


新增规则同一IP60秒内ban10次

通过查找官网定义的例子进行编写

参考: https://documentation.wazuh.com/current/user-manual/ruleset/rules/custom.html

复制代码
cd /var/ossec/ruleset/rules
grep -rn "same" ./   # 相同IP的语法
grep -rn frequency ./ # 频率


if_matched_sid  如果使用频率的话必须要matched
same_field 相同字段

完成

注意rule id 不可重复 100001已存在故改为110001

复制代码
<group name="modsec,">
  <rule id="110001" level="12" frequency="5" timeframe="60">
     <if_matched_sid>30411</if_matched_sid>
     <same_field>client</same_field>
    <description>同ip 60秒 5次 拦截</description>
  </rule>
</group>


飞书通知

参考:

https://wazuh.com/blog/how-to-integrate-external-software-using-integrator/

https://blog.csdn.net/wanganmuzi/article/details/148555367

前言

经过上面的规则编写,同ip 60秒 5次 拦截的进行一个规则告警id 110001

开启integration日志

后续脚本执行的问题都在这里排查

vi /var/ossec/etc/internal_options.conf

复制代码
integrator.debug=2 # 开启integrator

systemctl restart wazuh-manager

此时可以在/var/ossec/logs/ossec.log 中查看integrator相关执行日志

如没安装requests库

新增integrator

注意

  1. 要在ossec_config中

  2. 这里限定使用最少的。额外可选的如level、group规则触发 参考链接 https://documentation.wazuh.com/current/user-manual/reference/ossec-conf/integration.html#integration-options

  3. custom-feishu中custom- 必不可少,后面的可以自己修改
    vi /var/ossec/etc/ossec.conf

    custom-feishu 110001 json 填你的飞书webhook链接

新增可执行脚本

alert的json日志

/var/ossec/logs/alerts/alerts.json

找到你要触发的规则 ,比如我的规则是110001

复制代码
{"timestamp":"2026-01-05T00:10:32.178+0800","rule":{"level":12,"description":"同ip 60秒 5次 拦截","id":"110001","frequency":5,"firedtimes":1,"mail":true,"groups":["modsec"]},"agent":{"id":"001","name":"c8-1","ip":"10.20.0.147"},"manager":{"name":"c8-50g"},"id":"1767543032.74677","previous_output":"[Mon Jan 05 00:12:57.298633 2026] [:error] [pid 1533445:tid 139845762520832] [client 10.20.0.81:56484] [client 10.20.0.81] ModSecurity: Access denied with code 403 (phase 2). Operator GE matched 5 at TX:anomaly_score. [file \"/etc/httpd/modsecurity.d/activated_rules/REQUEST-949-BLOCKING-EVALUATION.conf\"] [line \"153\"] [id \"949110\"] [msg \"Inbound Anomaly Score Exceeded (Total Score: 8)\"] [severity \"CRITICAL\"] [ver \"OWASP_CRS/3.3.4\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-generic\"] [hostname \"10.20.0.147\"] [uri \"/catalog-portal/ui/oauth/verify\"] [unique_id \"aVqRiSz2c2hIU6C2KKXCHQAAAEc\"]\n[Mon Jan 05 00:12:57.264398 2026] [:error] [pid 1533445:tid 139845745735424] [client 10.20.0.81:56494] [client 10.20.0.81] ModSecurity: Access denied with code 403 (phase 2). Operator GE matched 5 at TX:anomaly_score. [file \"/etc/httpd/modsecurity.d/activated_rules/REQUEST-949-BLOCKING-EVALUATION.conf\"] [line \"153\"] [id \"949110\"] [msg \"Inbound Anomaly Score Exceeded (Total Score: 13)\"] [severity \"CRITICAL\"] [ver \"OWASP_CRS/3.3.4\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-generic\"] [hostname \"10.20.0.147\"] [uri \"/${(#a=@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec(\\\\\"id\\\\\").getInputStream(),\\\\\"utf-8\\\\\")).(@com.opensymphony.webwork.ServletActionContext@getResponse().setHeader(\\\\\"X-Cmd-Response\\\\\",#a))}/\"] [unique_id \"aVqRiSz2c2hIU6C2KKXCHAAAAEk\"]\n[Mon Jan 05 00:12:57.110959 2026] [:error] [pid 1533666:tid 139845678593792] [client 10.20.0.81:56454] [client 10.20.0.81] ModSecurity: Access denied with code 403 (phase 2). Operator GE matched 5 at TX:anomaly_score. [file \"/etc/httpd/modsecurity.d/activated_rules/REQUEST-949-BLOCKING-EVALUATION.conf\"] [line \"153\"] [id \"949110\"] [msg \"Inbound Anomaly Score Exceeded (Total Score: 18)\"] [severity \"CRITICAL\"] [ver \"OWASP_CRS/3.3.4\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-generic\"] [hostname \"10.20.0.147\"] [uri \"/plus/weixin.php\"] [unique_id \"aVqRiapBCZNoRJDlGtzGFQAAANE\"]\n[Mon Jan 05 00:12:57.087256 2026] [:error] [pid 1533666:tid 139845712164608] [client 10.20.0.81:56468] [client 10.20.0.81] ModSecurity: Access denied with code 403 (phase 2). Operator GE matched 5 at TX:anomaly_score. [file \"/etc/httpd/modsecurity.d/activated_rules/REQUEST-949-BLOCKING-EVALUATION.conf\"] [line \"153\"] [id \"949110\"] [msg \"Inbound Anomaly Score Exceeded (Total Score: 18)\"] [severity \"CRITICAL\"] [ver \"OWASP_CRS/3.3.4\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-generic\"] [hostname \"10.20.0.147\"] [uri \"/actuator/gateway/routes/iwtcoaro\"] [unique_id \"aVqRiapBCZNoRJDlGtzGFgAAAM0\"]","full_log":"[Mon Jan 05 00:12:57.634304 2026] [:error] [pid 1533666:tid 139845653415680] [client 10.20.0.81:56454] [client 10.20.0.81] ModSecurity: Access denied with code 403 (phase 2). Operator GE matched 5 at TX:anomaly_score. [file \"/etc/httpd/modsecurity.d/activated_rules/REQUEST-949-BLOCKING-EVALUATION.conf\"] [line \"153\"] [id \"949110\"] [msg \"Inbound Anomaly Score Exceeded (Total Score: 8)\"] [severity \"CRITICAL\"] [ver \"OWASP_CRS/3.3.4\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-generic\"] [hostname \"10.20.0.147\"] [uri \"/index.php\"] [unique_id \"aVqRiapBCZNoRJDlGtzGFwAAANQ\"]","decoder":{"parent":"apache-errorlog","name":"apache-errorlog"},"data":{"id":"949110","client":"10.20.0.81","file":"REQUEST-949-BLOCKING-EVALUATION","msg":"Inbound Anomaly Score Exceeded (Total Score: 8)"},"location":"/var/log/httpd/error_log"}
脚本编写方法

参考 https://wazuh.com/blog/how-to-integrate-external-software-using-integrator/ 中的

复制代码
alert_file = open(sys.argv[1]) # 对应上面json日志
api_key = sys.argv[2].split(':')[1] # ossec.conf定义的,我上面没有定义,具体可以参考官方的链接
hook_url = sys.argv[3] # ossec.conf定义的,具体可以参考官方的链接,也可以直接写死在python文件里面

AI提示词

复制代码
(贴上json日志)
帮我写一个python脚本,alert_file = open(sys.argv[1])  alert_file为上方的json日志 hook_url = sys.argv[3]  hook_url为飞书的机器人
要求提取data.client msg  time agentname  ruleid    full_log,字段
使用requests库进行发送
custom-feishu

注意

  1. 脚本文件权限一定为: 750 root:wazuh

  2. #!/usr/bin/env python3 # -*- coding: utf-8 -*- 这个一定不能少

  3. 检查是否有python 与requests库
    vi /var/ossec/integrations/custom-feishu

    #!/usr/bin/env python3

    -- coding: utf-8 --

    import json
    import sys
    import requests
    import re
    from datetime import datetime

    使用方式:

    python script.py alert.json your_api_key:xxx https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxx

    if len(sys.argv) < 4:
    print("用法: python script.py <alert_json_file> <api_key:xxx> <feishu_hook_url>")
    sys.exit(1)

    alert_file = sys.argv[1]
    hook_url = sys.argv[3] # 飞书 Webhook 地址

    读取 JSON 文件

    try:
    with open(alert_file, 'r', encoding='utf-8') as f:
    alert = json.load(f)
    except Exception as e:
    print(f"读取文件失败: {e}")
    sys.exit(1)

    提取核心字段

    data_client = alert.get('data', {}).get('client', 'N/A')
    msg = alert.get('data', {}).get('msg', 'N/A')
    rule_id = alert.get('rule', {}).get('id', 'N/A')
    agent_name = alert.get('agent', {}).get('name', 'N/A')
    full_log = alert.get('full_log', '')

    提取时间(优先从 full_log 里解析 apache 日志时间,更精确)

    time_str = '未知时间'
    if full_log:
    # 匹配类似 [Mon Jan 05 20:48:51.424887 2026]
    match = re.search(r'([A-Za-z]{3} [A-Za-z]{3} \d{2} \d{2}:\d{2}:\d{2}\.\d+ \d{4})', full_log)
    if match:
    time_str = match.group(1)
    else:
    # 回退使用 timestamp
    ts = alert.get('timestamp')
    if ts:
    try:
    dt = datetime.fromisoformat(ts.replace('Z', '+00:00'))
    time_str = dt.strftime('%Y-%m-%d %H:%M:%S %z')
    except:
    time_str = ts
    else:
    ts = alert.get('timestamp')
    if ts:
    try:
    dt = datetime.fromisoformat(ts.replace('Z', '+00:00'))
    time_str = dt.strftime('%Y-%m-%d %H:%M:%S %z')
    except:
    time_str = ts

    构造飞书富文本卡片(红色高危样式)

    payload = {
    "msg_type": "interactive",
    "card": {
    "config": {
    "wide_screen_mode": True,
    "enable_forward": True
    },
    "header": {
    "template": "red",
    "title": {
    "tag": "plain_text",
    "content": "ModSecurity 拦截 - 高危 SQL 注入尝试"
    }
    },
    "elements": [
    {
    "tag": "div",
    "text": {
    "tag": "lark_md",
    "content": f"规则ID:{rule_id} (同IP 60秒内 ≥5次触发)"
    }
    },
    {
    "tag": "hr"
    },
    {
    "tag": "div",
    "fields": [
    {
    "is_short": True,
    "text": {
    "tag": "lark_md",
    "content": f"时间\n{time_str}"
    }
    },
    {
    "is_short": True,
    "text": {
    "tag": "lark_md",
    "content": f"攻击IP\n{data_client}"
    }
    }
    ]
    },
    {
    "tag": "div",
    "fields": [
    {
    "is_short": True,
    "text": {
    "tag": "lark_md",
    "content": f"Agent\n{agent_name}"
    }
    },
    {
    "is_short": True,
    "text": {
    "tag": "lark_md",
    "content": "异常分数\n8 (≥5 拦截)"
    }
    }
    ]
    },
    {
    "tag": "div",
    "text": {
    "tag": "lark_md",
    "content": f"告警详情\n{msg}"
    }
    },
    {
    "tag": "note",
    "elements": [
    {
    "tag": "plain_text",
    "content": f"日志片段:{full_log[:180]}{'...' if len(full_log) > 180 else ''}"
    }
    ]
    }
    ]
    }
    }

    发送到飞书

    try:
    headers = {'Content-Type': 'application/json'}
    resp = requests.post(hook_url, json=payload, headers=headers, timeout=10)
    if resp.status_code == 200:
    result = resp.json()
    if result.get('code') == 0:
    print("飞书消息发送成功")
    else:
    print(f"飞书返回错误: {result}")
    else:
    print(f"HTTP {resp.status_code}: {resp.text}")
    except Exception as e:
    print(f"发送失败: {e}")
    [root@c8-50g integrations]#

AI生成的标题,下次再改

相关推荐
瑞克-桑切斯2 小时前
8、ELK 认识与部署
elk
guoran_shini2 天前
Agent系统服务化封装和IM接入
飞书
mudtools4 天前
在飞书 SDK 上用 Microsoft Agent Framework 搭一个能干活的工作搭子
人工智能·ai·.net·飞书·agent
极致了5 天前
飞书插件、RPA、API三条路的真实分界线
飞书·rpa
玩泥巴的6 天前
在飞书 SDK 上用 Microsoft Agent Framework 搭一个能干活的工作搭子
ai·.net·飞书·agent
玩泥巴的7 天前
一份声明,多份产物:飞书 SDK 的 AI 工具面是怎么生成的
ai·.net·飞书·agent
g10565591398 天前
ELK企业日志分析系统
elk
OpenPortal认证计费系统9 天前
基于 飞书认证 通过 华为、H3C 结合 OpenPortal认证计费系统 实现 网络准入 飞书授权 实名认证
华为·飞书·h3c·portal认证·openportal
前进的李工10 天前
飞书企业知识库设计+后端高频八股
数据库·redis·后端·mysql·性能优化·飞书·rag