年轻人的第一个IDS
前情提要
流量重要性
流量能带来什么?流量就是当今社会变现的关键所在! 啊,不是说这个流量啊
在网络安全领域,不关你是做什么方向的安全,免不了需要一直跟网络打交道,跟流量检测的安全产品打交道,你看到的是一个一个的告警,告警之下到底都具体发生了啥?IDS/IPS/NDR到底在干啥?让我们一起来看看!
IDS工作原理
捕获并分析网络数据包,寻找与预定义规则或异常行为模式相匹配的特征。这些规则通常基于已知的攻击签名或异常行为特征。当匹配发生时,IDS会触发警报,通知系统管理员潜在的恶意活动。简而言之,IDS不断地比较网络流量与攻击指纹或异常模式,从而实时地检测和警告网络威胁。
经典网络流量分析工具
Suricata 和 Zeek(之前称为Bro)都是强大的网络流量分析工具,但它们的设计理念、功能和使用场景有所不同。下面是对两者的简要比较,以及它们在不同应用场景中的适用性:
设计和主要功能:
- Suricata:
- 主要设计为一个入侵检测系统 (IDS) 和入侵防御系统 (IPS)。
- 主要依赖签名匹配来检测和/或阻止潜在的恶意流量。
- 支持多线程,能够处理大量并发的网络流量。
- Zeek (Bro):
- 主要设计为一个网络安全监控工具。
- 提供详细的日志和流量分析,而不是基于签名的警报。
- 允许用户编写自己的脚本来自定义分析和响应。
应用场景:
- Suricata:
- 当你需要一个传统的IDS/IPS来检测和/或阻止恶意流量时。
- 当你的主要关注点是恶意软件、攻击尝试等威胁,并且希望在它们进入网络之前阻止它们。
- Zeek (Bro):
- 当你需要详细了解网络上正在发生的事情,例如:哪些设备正在通信、哪些端口正在使用等。
- 当你希望自定义网络流量分析和响应时,例如:特定事件的警报、数据的特定抽取等。
流量分析:
- 如果你想做安全研究并且想要学习流量分析,选Zeek。其原因如下:
- 日志详细且有好:Zeek 提供了丰富、结构化的日志,这些日志涵盖了网络上的各种活动,包括HTTP请求、DNS查询、SSL/TLS连接等。
- 网络流量分析为主:Zeek主要重点是提供详细的网络流量分析,以帮助检测网络活动和了解网络中的通信模式。
- 高度可定制:Zeek具有灵活的脚本编写能力,允许您自定义特定于环境的网络监控和检测规则。这使得它非常适合进行自定义网络流量分析。
ZEEK初体验
与传统的 IDS 不同,Zeek 主要关注网络的元数据,为安全研究提供丰富的上下文信息。
快速入门
# 安装zeek
git clone --recursive https://github.com/zeek/zeek
cd zeek
./configure && make && sudo make install
vim hello.zeek
# File "hello.zeek"
event zeek_init()
{
print "Hello World!";
}
执行脚本
zeek hello.zeek
核心概念
-
网络事件
Zeek 的一个核心概念是”事件”。Zeek 官方文档定义事件为“一些可能或可能不会在网络上发生的事情,如一个新连接的开始或结束”。
例如:当 HTTP 请求在网络上被捕获时,Zeek 会触发一个 http_request
事件,而当我们捕获这个事件之后,我们可以进一步进行一些操作:
event http_request(c: connection, method: string, uri: string, version: string) {
# 当检测到 HTTP 请求时,输出相关信息
print fmt("来自 %s 的 HTTP 请求: %s %s", c$id$orig_h, method, uri);
}
http_request里面的参数又是什么含义呢?
- connection
- 这是一个关于此次网络连接的复合记录。它包含了源地址、目的地址、源端口、目标端口等信息。例如,
c$id$orig_h
表示请求的源 IP 地址。- method: string
- HTTP 请求的方法。常见的方法有
GET
,POST
,PUT
,DELETE
等。- uri: string
- 请求的 URI(统一资源标识符)。简单地说,这通常是请求的网页路径和参数,例如 “/index.html” 或 “/search?q=zeek”。
- version: string
- HTTP 协议的版本。常见的版本有 “HTTP/1.0” 和 “HTTP/1.1”。
-
告警定义
除了捕获事件,Zeek 也可以定义警告。通过Notice 框架实现的,它允许我们指定何时以及如何通知潜在的威胁。
例如: 假设我们想要在检测到特定的恶意 URL 时生成告警:
module DemoIDS;
export {
# 定义新的告警类型
redef enum Notice::Type += { Malicious_URL_Visit };
}
# 检查是否有访问恶意 URL 的请求
event http_request(c: connection, method: string, uri: string, version: string) {
if ( uri == "/malicious.php" ) {
NOTICE([$note=Malicious_URL_Visit, $msg=fmt("来自 %s 的恶意URL访问", c$id$orig_h)]);
}
}
实现你自己的第一个IDS - MiniIDS
根据前面的内容我们知道了最基础的事件与告警,我们可以开始写一个miniids了!
编写脚本
vim DetailedIDS.zeek
zeek默认输出ACSCII编码,不支持直接输出UTF-8编码的字符,所以我们不能打印中文
@load base/protocols/http
@load base/protocols/dns
module DetailedIDS;
# 检测恶意的 HTTP 请求
event http_request(c: connection, method: string, original_URI: string, unescaped_URI: string, version: string) {
# 发出警告,如果 original_URI 与已知的恶意 URI 匹配
if (original_URI == "/malicious.php") {
print fmt("[warning] Malicious request from %s was detected!", c$id$orig_h);
}
}
# 检测到恶意 DNS 查询
event dns_request(c: connection, msg: dns_msg, query: string, qtype: count, qclass: count) {
# 对与已知的恶意域名匹配的 "A记录" 查询发出警告
if (qtype == 1 && query == "baidu.com") {
print fmt("[warning] Malicious DNS query detected from %s!", c$id$orig_h);
}
}
测试
-
启动脚本
zeek -i eth0 DetailedIDS.zeek
-
生成测试流量
# 启动一个http服务器 php -S 0.0.0.0:8888 # 我们的zeek脚本针对 URI 的 /malicious.php 请求会生成告警,所以我们访问该路径 # 注意不要在php http服务同主机发起请求,zeek默认忽略本地的流量 curl http://vps_ip:8888/malicious.php # 构造恶意域名dns解析,假设我们定义的恶意域名是:baidu.com,使用dig解析baidu.com dig baidu.com
-
检查告警
MiniIDS Pro版本
前面已经小试牛刀,如果我们结合开源情报库,定时拉取开源情报库的ip和域名,更新到我们的规则,那我们是不是就可以实现一个初具规模的ids, 并且还能实时更新规则
定义恶意IP和域名列表:
创建一个名为malicious.zeek
的配置文件,并使用以下格式列出恶意的IP和域名:
module Malicious;
export {
const malicious_ips: set[addr] = {
192.168.1.14,
192.168.1.121
} &redef;
const malicious_domains: set[string] = {
"jd.com",
"baidu.com"
} &redef;
}
在Zeek脚本中读取和使用这些列表:
DetailedIDSPro.zeek
# 加载必要的包
@load base/protocols/dns
@load policy/frameworks/notice
# 加载恶意列表文件
@load ./malicious.zeek
# 定义新的Notice类型
redef enum Notice::Type += {
Malicious_IP_Notice,
Malicious_Domain_Notice
};
# 检查恶意IP
event connection_established(c: connection) {
if (c$id$resp_h in Malicious::malicious_ips) {
NOTICE([
$note=Malicious_IP_Notice,
$msg=fmt("Connection to malicious IP: %s", c$id$resp_h),
$conn=c,
$identifier=fmt("mal_ip-%s", c$id$resp_h)
]);
}
}
# 检查恶意域名 - 使用dns_request来捕获DNS请求
event dns_request(c: connection, msg: dns_msg, query: string, qtype: count, qclass: count) {
if (query in Malicious::malicious_domains) {
NOTICE([
$note=Malicious_Domain_Notice,
$msg=fmt("Query to malicious domain: %s", query),
$conn=c,
$identifier=fmt("mal_domain-%s", query)
]);
}
}
运行Zeek脚本:
zeek -i eth0 DetailedIDSPro.zeek
检查告警
按照上述步骤完成之后,每当有与恶意IP或域名的交互,Zeek都会在notice.log
中生成一个警告
走到这里你在回头看我们前面写的IDS工作原理,是不是你已经大概实现了一个你的MiniIDS
IDS工作原理:
捕获并分析网络数据包,寻找与预定义规则或异常行为模式相匹配的特征。这些规则通常基于已知的攻击签名或异常行为特征。当匹配发生时,IDS会触发警报,通知系统管理员潜在的恶意活动。简而言之,IDS不断地比较网络流量与攻击指纹或异常模式,从而实时地检测和警告网络威胁。
总结扩展
在Zeek中,您可以定义各种类型的恶意规则,不仅限于IP地址和域名。Zeek的灵活性和扩展性允许我们可以根据各种网络活动模式和特性定义规则。
规则类型 | 描述 |
---|---|
IP地址规则 | { "Malicious_IPs": set[addr] } - 检测与指定的恶意IP地址相关的网络流量。 |
域名规则 | { "Malicious_Domains": set[string] } - 检测与指定的恶意域名相关的DNS查询。 |
端口规则 | { "Allowed_Ports": set[count], "Blocked_Ports": set[count] } - 允许或拒绝特定端口上的流量。 |
协议规则 | { "Protocol_Rules": table[string] of bool } - 检测与指定协议类型相关的网络流量。 |
文件规则 | { "File_Transfer_Rules": table[string] of bool } - 检测文件传输活动,如文件上传和下载。 |
SSL/TLS规则 | { "SSL_TLS_Rules": table[string] of bool } - 检测SSL/TLS协议的异常行为。 |
漏洞规则 | { "Vulnerability_Rules": table[string] of bool } - 检测与已知漏洞相关的网络流量。 |
用户行为规则 | { "User_Behavior_Rules": table[string] of bool } - 检测异常用户行为,如多次失败的登录尝试。 |
DNS规则 | { "DNS_Rules": table[string] of bool } - 检测与DNS查询中的异常行为相关的网络流量。 |
HTTP规则 | { "HTTP_Rules": table[string] of bool } - 检测HTTP流量中的恶意Web请求、SQL注入等。 |
内部威胁规则 | { "Internal_Threat_Rules": table[string] of bool } - 监测内部网络活动,如内部主机间的异常通信。 |
自定义规则 | { "Custom_Rules": table[string] of bool } - 创建自定义规则以检测特定网络行为或事件。 |
当定义这些规则时,我们需要确保规则不过于宽泛,以避免大量的误报,可以经过一段时间的测试之后再正式上线。使用Zeek脚本语言,我们可以轻松地组合多个条件和检测模式,以定义复杂的恶意活动规则。