告警流程简介
在接收到agent传来的日志后,manager会根据/var/ossec/ruleset/decoders
里面的各种规则对日志进行处理,提取到了指定字段的值之后再根据/var/ossec/ruleset/rules
里面的各种规则进行匹配,告警日志输出到/var/ossec/logs/alerts/alerts.json
,logstash
再将其解析后传输到elasticsearch
上面。
另外不懂怎么编写自己的规则时,可以先看看官方的规则是怎么写的。
官方示例解释
有这样一条日志Dec 25 20:45:02 MyHost example[12345]: User 'admin' logged from '192.168.1.100'
。
为了解码这条日志,需要编写自定义解码器,修改/var/ossec/etc/decoders/local_decoder.xml
,name是解码规则的名称,program_name是匹配日志以example
开头,regex
表示用正则提取,order
表示正则提取出来值依次是user,srcip。
<decoder name="example">
<program_name>^example</program_name>
</decoder>
<decoder name="example">
<parent>example</parent>
<regex>User '(\w+)' logged from '(\d+.\d+.\d+.\d+)'</regex>
<order>user, srcip</order>
</decoder>
现在修改/var/ossec/etc/rules/local_rules.xml
,level
就是告警的等级。
<rule id="100010" level="0">
<program_name>example</program_name>
<description>User logged</description>
</rule>
然后运行/var/ossec/bin/ossec-logtest
来测试写的规则是否能正常运作。另外这个命令还有好几个参数,可以看到更详细的过程。
**Phase 1: Completed pre-decoding.
full event: 'Dec 25 20:45:02 MyHost example[12345]: User 'admin' logged from '192.168.1.100''
hostname: 'MyHost'
program_name: 'example'
log: 'User 'admin' logged from '192.168.1.100''
**Phase 2: Completed decoding.
decoder: 'example'
dstuser: 'admin'
srcip: '192.168.1.100'
**Phase 3: Completed filtering (rules).
Rule id: '100010'
Level: '0'
Description: 'User logged'
实操解析Windows系统登陆日志
打开客户端的ossec.conf
,可以看到是默认就有采集windows系统登陆日志,并过滤了不必要的事件ID。
<localfile>
<location>Security</location>
<log_format>eventchannel</log_format>
<query>Event/System[EventID != 5145 and EventID != 5156 and EventID != 5447 and
EventID != 4656 and EventID != 4658 and EventID != 4663 and EventID != 4660 and
EventID != 4670 and EventID != 4690 and EventID != 4703 and EventID != 4907]</query>
</localfile>
在服务端用bin/ossec-logtest
测试以下中英文windows登陆日志。
可以看到中文日志只有解析出这些字段2018 Aug 18 17:59:31 WinEvtLog: Security: AUDIT_SUCCESS(4624): Microsoft-Windows-Security-Auditing: (no user): no domain: WIN-E3EJOGG67EK: 已成功登录帐户。 主题: 安全 ID: S-1-5-18 帐户名: WIN-E3EJOGG67EK$ 帐户域: WORKGROUP 登录 ID: 0x3e7 登录类型: 2 新登录: 安全 ID: S-1-5-21-3320951223-3242959419-3755421162-500 帐户名: Administrator 帐户域: WIN-E3EJOGG67EK 登录 ID: 0x56b0384 登录 GUID: {00000000-0000-0000-0000-000000000000} 进程信息: 进程 ID: 0xc68 进程名: C:\Windows\System32\winlogon.exe 网络信息: 工作站名: WIN-E3EJOGG67EK 源网络地址: 1.1.1.1 源端口: 0 详细身份验证信息: 登录进程: User32 身份验证数据包: Negotiate 传递服务: - 数据包名(仅限 NTLM): - 密钥长度: 0 在创建登录会话后在被访问的计算机上生成此事件。 “主题”字段指明本地系统上请求登录的帐户。这通常是一个服务(例如 Server 服务)或本地进程(例如 Winlogon.exe 或 Services.exe)。 “登录类型”字段指明发生的登录种类。最常见的类型是 2 (交互式)和 3 (网络)。 “新登录”字段会指明新登录是为哪个帐户创建的,即登录的帐户。 “网络”字段指明远程登录请求来自哪里。“工作站名”并非总是可用,而且在某些情况下可能会留为空白。 “身份验证信息”字段提供关于此特定登录请求的详细信息。 -“登录 GUID”是可以用于将此事件与一个 KDC 事件关联起来的唯一标识符。 -“传递服务”指明哪些直接服务参与了此登录请求。 - “数据包名”指明在 NTLM 协议之间使用了哪些子协议。 -“密钥长度”指明生成的会话密钥的长度。如果没有请求会话密钥则此字段为 0。
英文日志就会很完整
2017 Apr 18 17:30:52 WinEvtLog: Security: AUDIT_FAILURE(4625): Microsoft-Windows-Security-Auditing: (no user): no domain: WIN-1: An account failed to log on. Subject: Security ID: S-1-5-10 Account Name: WIN-1$ Account Domain: WORKGROUP Logon ID: 0x3E7 Logon Type: 10 Account For Which Logon Failed: Security ID: S-1-0-0 Account Name: Santiago Account Domain: test2 Failure Information: Failure Reason: Unknown user name or bad password. Status: 0xC000006D Sub Status: 0xC0000064 Process Information: Caller Process ID: 0xb50 Caller Process Name: C:\Windows\System32\winlogon.exe Network Information: Workstation Name: WIN-1 Source Network Address: 17.217.25.247 Source Port: 0 Detailed Authentication Information: Logon Process: User32 Authentication Package: Negotiate Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon request fails. It.
可以看到ossec并不是完整支持正则表达式所有语法。毕竟正则越复杂,消耗的资源就越多,尤其是这种需要快速处理大量日志的场景对性能的要求就极为苛刻。(正则表达式拒绝服务攻击既ReDos)
总之,我用/bin/ossec-regex
反复测试后:
可以用\S
来匹配中文,但是无法匹配混搭中英的字符串,比如\S\S: \S\S:
,可以匹配的是dd: dd:
或者中文: dd:
,却不匹配中文: 中文:
和dd: 中文:
负责处理Windows日志的decoder就是/var/ossec/ruleset/decoders/0380-windows_decoders.xml
为了让自己修改后的规则库不会因为后期的软件包更新而被覆盖,如下操作
先手动复制一份原有的规则cp -a ruleset/decoders/0380-windows_decoders.xml etc/decoders/
/var/ossec/
├─ etc/
│ ├─ decoders/
| | └─ local_decoder.xml
│ └─ rules/
| └─ local_rules.xml
└─ ruleset/
├─ decoders/
└─ rules/
然后修改etc/ossec.conf
,在</ruleset>
节点新增一行,将原有的解码器从ossec
的载入列表中排除,看上去如下
<!-- User-defined ruleset -->
<decoder_dir>etc/decoders</decoder_dir>
<rule_dir>etc/rules</rule_dir>
<decoder_exclude>ruleset/decoders/0380-windows_decoders.xml</decoder_exclude>
</ruleset>
如果以后官方更新了0380-windows_decoders.xml
,就需要手动合并新旧两个版本了。
打开0380-windows_decoders.xml
出现了两次security_id
的取值,是按照先后顺序取到的。
因为无法匹配中英混合字符串,于是改为单次匹配提取,即将其原本一次性提取4个特征改为分为4次提取特征。
提取规则会跟下面有所重复,但是<order></order>
是不一样的,而且是按字符串先后顺序只提取一次。
比如第一次匹配到的安全ID
是S-1-5-18
,会作为subject.security_id
的值。
第二次匹配到的安全ID
是S-1-5-21-3320951223-3242959419-3755421162-500
,会作为security_id
的值。
补充:srcip
则是:\t*\s*(\S+.\S+.\S+.\S+)
来提取,日志源中ip的格式标准且可信的情况下使用。
修改后的解码规则
<decoder name="windows_fields">
<type>windows</type>
<parent>windows</parent>
<regex offset="after_regex">Security ID:\t*\s*(\S\S+)|\S\S ID:\t*\s*(\S\S+)</regex>
<order>subject.security_id</order>
</decoder>
<decoder name="windows_fields">
<type>windows</type>
<parent>windows</parent>
<regex offset="after_regex">Account Name:\t*\s*(\S\S+)|\S\S\S: (\s*\S+)</regex>
<order>subject.account_name</order>
</decoder>
<decoder name="windows_fields">
<type>windows</type>
<parent>windows</parent>
<regex offset="after_regex">Account Domain:\t*\s*(\S\S+)\t*\s*|\S\S\S: (\s*\S+)</regex>
<order>subject.account_domain</order>
</decoder>
<decoder name="windows_fields">
<type>windows</type>
<parent>windows</parent>
<regex offset="after_regex">Logon ID:\t*\s*(\S\S+)|\S\S ID:\t*\s*(\S\S+)</regex>
<order>subject.logon_id</order>
</decoder>
<decoder name="windows_fields">
<type>windows</type>
<parent>windows</parent>
<regex offset="after_regex">Security ID:\t*\s*(\S\S+)|\S\S ID:\t*\s*(\S\S+)</regex>
<order>security_id</order>
</decoder>
<decoder name="windows_fields">
<type>windows</type>
<parent>windows</parent>
<regex offset="after_regex">Account Name:\t*\s*(\S\S+)|\S\S\S:\t*\s*(\S\S+)</regex>
<order>account_name</order>
</decoder>
<decoder name="windows_fields">
<type>windows</type>
<parent>windows</parent>
<regex offset="after_regex">Account Domain:\t*\s*(\S\S+)\t*\s*|\S\S\S:\t*\s*(\S\S+)\t*\s*</regex>
<order>account_domain</order>
</decoder>
<decoder name="windows_fields">
<type>windows</type>
<parent>windows</parent>
<regex>Logon Type:\t*\s*(\S+)|\S\S\S\S: (\d+)</regex> #注意这里有三个空格
<order>logon_type</order>
</decoder>
每次修改规则之后,需要重新运行bin/ossec-logtest
,才能验证规则是否有效。验证通过后,
重启manager以便让新规则生效,另外kibana会提示你刷新索引以便更新字段。
编写Windows远程桌面异常IP登陆告警规则
报警规则语法
里面的条件选项有很多,不用单单靠<regex>
和<match>
来进行匹配。
是属于
windows
规则组的,搜一下18107就发现报警规则位于/var/ossec/ruleset/rules/0220-msauth_rules.xml
修改/var/ossec/etc/rules/local_rules.xml
,添加如下规则。
从上到下依次匹配,全部为true方可触发告警。
这个规则的意思就是:首先要匹配到父级规则18107(Windows系统登陆事件ID满足4624等),然后srcip不是127.0.0.1,也不是堡垒机ip,那么触发告警。
<rule id="100002" level="8">
<if_sid>18107</if_sid>
<srcip>!127.0.0.1</srcip>
<srcip>!堡垒机IP</srcip>
<description>login from Unknow Host</description>
<group>authentication_success</group>
</rule>
改完之后记得用ossec-logtest
自行测试。
编写Linux ssh异常IP登陆告警规则
默认即可成功解析,只要写好告警规则即可
Dec 3 15:34:33 localhost sshd[4148]: Accepted password for root from 127.0.0.1 port 29963 ssh2
修改
/var/ossec/etc/rules/local_rules.xml
<rule id="100000" level="10">
<if_sid>5715</if_sid>
<srcip>!127.0.0.1</srcip>
<srcip>!堡垒机IP</srcip>
<description>sshd: logon from unkown host</description>
<group>authentication_success</group>
</rule>
验证下规则无误
网友评论