Zeek安装指南及实验

安装

今天我们又要来接触一种新的IDS
首先,准备好虚拟机(我使用的是Ubuntu20.04)
进入zeek官网(zeek-lts from security:zeek project)查看安装过程
选择适配的操作系统,点击 " 添加软件源并手动安装 "
在这里插入图片描述
对于 xUbuntu 20.04,请运行以下命令:
Keep in mind that the owner of the key may distribute updates, packages and repositories that your system will trust (more information).

echo 'deb http://download.opensuse.org/repositories/security:/zeek/xUbuntu_20.04/ /' | sudo tee /etc/apt/sources.list.d/security:zeek.list
curl -fsSL https://download.opensuse.org/repositories/security:zeek/xUbuntu_20.04/Release.key | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/security_zeek.gpg > /dev/null
sudo apt update
sudo apt install zeek-lts

在terminal依次输入以上命令即可

如果在安装过程中遇到无法解决的问题,我们还可以用线上编译平台解决燃眉之急


实验

Detection Requirement

  • check http sessions and if a source IP is related to three different user-agents or more
  • output “xxx.xxx.xxx.xxx is a proxy” where xxx.xxx.xxx.xxx is the source IP

You Need

  • a global variable to store the relationship of sourceIP to user-agent
  • write a event which can return you the http header user_agent information
  • you may need to study the datatype of Table, Set, String,
  • to_lower(str) return a lowercase version string of the original one
  • you may use print to output the alert

确定数据结构

首先我们需要确定存储IP和agent对应关系的数据结构
最简单最直接的想法:二维数组,第一维是IP,第二维存储Agent
在根据提示简单查看了Set,Table等数据类型后
我决定使用Set这种数据结构
但是当我开始申请变量的时候,遇到了一点麻烦
set[addr]表示:集合中存储的变量是addr类型,[]里面定义的是集合里面元素的类型
然而我们需要的是set有一个索引,索引是addr类型,set里面存储的是agent(string)
于是我又考虑使用Table类型
table [ type^+ ] of type的定义格式
启发了我结合Table和Set两种类型

global addrToAgent : table[addr] of set[string] = table();

处理http头部信息

Zeek Event - HTTP

这里我们选择http_header事件
(实际上我觉得其他事件也是可以的,看下去你就会发现,我们只用到了connection这个参数)
可以看到提供的参数有

ParametersMeaning
CThe connection.
Is_origTrue if the header was sent by the originator of the TCP connection.
Original_nameThe name of the header (unaltered).
NameThe name of the header (converted to all uppercase).
ValueThe value of the header.

在我寻找了一万年之后,终于发现了解决方法:
connection实际上是一个record(有一点类似c里面的结构体)
有以下两个操作符
在这里插入图片描述

至于connection里面有什么,我们可以去Zeek Script Index: base/init-bare.zeek: Types: connection看一看
然后我们找到了一个叫做http的成员
在这里,我们终于找到了和agent相关的信息
在这里插入图片描述
我们需要判断connection的http成员中是否存在agent内容
如果存在,则需要提取该agent记录(为了避免大小写的影响,我们需要用to_lower统一格式)
至于如何提取source IP
我们可以找到connection的id成员的orig_h内容

if (c$http?$user_agent) {
	local src_ip=c$id$orig_h;
	local user_agent=to_lower(c$http$user_agent);
}

接下来我们要把agent加入到集合中
注意需要分情况处理,因为table在第一次与set建立对应关系的时候,需要特别的初试化

if (src_ip in addrToAgent){
	add (addrToAgent[src_ip])[user_agent];  //set insert
}else{
	addrToAgent[src_ip]=set(user_agent);  //table insert
}

输出答案

有了之前的经验,这一部分就很简单了
遍历所有ip地址(可以使用index in table的方法)
如果对应的集合大小大于等于3,则输出针对该ip的警报
在这里插入图片描述
需要强调一下addr的类型转换
Zeek Types - addr
在这里插入图片描述
我们可以使用第二种方法(类似c语言比较好理解)把ip地址转换为字符串输出

event zeek_done() {
	for (addr_ip in addrToAgent) {
	    if (|addrToAgent[addr_ip]| >= 3) {
	        print fmt("%s is a proxy", addr_ip);
	    }
	}
}

完整代码

global addrToAgent : table[addr] of set[string] = table();

event http_header (c: connection, is_orig: bool, name: string, value: string){
	if(c$http?$user_agent){
		local src_ip=c$id$orig_h;
		local user_agent=to_lower(c$http$user_agent);
		if(src_ip in addrToAgent){
			add (addrToAgent[src_ip])[user_agent];
		}else{
			addrToAgent[src_ip]=set(user_agent);
		}
	}
}

event zeek_done() {
	for (addr_ip in addrToAgent) {
	    if (|addrToAgent[addr_ip]| >= 3) {
	        print fmt("%s is a proxy", addr_ip);
	    }
	}
}

参考资料

Zeek语法(原网站)
Zeek语法(翻译)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值