分类: 网络与安全
2007-04-08 20:17:23
所谓入侵,是指任何试图危及计算机资源的完整性、机密性或可用性的行为。而入侵检测系统(Intrusion Detection System)就是对网络或操作系统上的可疑行为做出策略反应,及时切断资料入侵源、记录、并通过各种途径通知网络管理员,最大幅度地保障系统安全,是防火墙的合理补充,帮助系统对付网络攻击,扩展系统管理员的安全管理能力(包括安全审计、监视、进攻识别和响应),提高信息安全基础结构的完整性,被认为是防火墙之后的第二道安全闸门,它在不影响网络性能的情况下能对网络进行监测,从而提供对内部攻击、外部攻击和误操作的实时保护, 最大幅度地保障系统安全。它在网络安全技术中起到了不可替代的作用,是安全防御体系的一个重要组成部分。
入侵检测系统按照其数据来源来看,可以分为三类:基于主机的入侵检测系统、基于网络的入侵检测系和采用上述两种数据来源的分布式的入侵检测系统。
按照其采用的方法来看,可以分为基于行为的入侵检测系统、基于模型推理的入侵检测系统、采用两者混合检测的入侵检测系统。
LIDS是Linux内核补丁和系统管理员工具(lidsadm),它加强了Linux内核。 它在内核中实现了一种安全模式——参考模式以及内核中的Mandatory Access Control(命令进入控制)模式。
下面阐述一下GNU/Linux系统存在的4个方面的问题。
(1) 文件系统未受到保护
系统中的很多重要的文件,例如 /bin/login,一旦黑客入侵后,他可以上传修改过的login文件来代替/bin/login ,然后他就可以不需要任何登陆名和密码就登陆系统。这常被称为Trojan house。
(2) 进程未受到保护
系统上运行的进程是为某些系统功能所服务的,例如HTTP是一个web服务器来满足远程客户端对于web的需求。作为web服务器系统,保护其进程不被非法终止是很重要的。但是当入侵者获得了ROOT权限后,我们却无能为力。
(3) 系统管理未受保护
很多系统管理,例如模块的装载/卸载,路由的设置,防火墙的规则,能很容易就被修改,如果用户的ID是0。所以当入侵者获得ROOT权限后,就变得很不安全。
(4) 超级用户(root)作为ROOT可能滥用权限
LIDS提供了保护、侦察、响应的功能,从而使LINUX系统内核中的安全模式得以实现。
(1) 保护
保护硬盘上任何类型的重要文件和目录,任何人包括ROOT都无法改变。能保护重要进程不被终止 ,能防止非法程序的RAW IO 操作。保护硬盘,包括MBR保护,等等能保护系统中的敏感文件,防止未被授权者(包括ROOT)和未被授权的程序进入。
(2) 侦察
当有人扫描你的主机, LIDS能侦察到并报告系统管理员。 LIDS也可以检测到系统上任何违法规则的进程。
(3) 响应
当有人违反规则, LIDS会将非法的运作细节记录到受LIDS保护的系统log文件中。 LIDS还可以将log信息传到你的信箱中。LIDS也可以马上关闭与用户的对话。
现在存在很多通过tcp/ip协议漏洞进行恶意扫描或攻击的网络手段,本人通过研究这些常用的网络攻击的源代码,创建了一个小型的lids,但其功能类似于防火墙没有自学习功能和ip追踪功能。只能进行分析和警报。
首先考虑数据包的捕获和分析工作,tcp、udp、icmp、igmp几种协议最为广泛。然后再考虑针对于攻击的模式匹配,如几种常见的恶意扫描,ping of death攻击,dos land攻击等还有日志记录工作。
小型lids的算法设计:
1. 读入用户请求,通过嗅探模块打开sockets连接、指定封装协议、捕获协议监听接收数据包。
2. 对读入的数据包进行处理。分析数据包:判断数据包真伪,防止ping of death攻击,如果存在此攻击则打开日志文件进行日志记录并跳入第4步。否则继续对数据包进行分类分析,如tcp包、udp包、icmp包、igmp包以及未知协议包。记录各类型的包的数目,并输出各包头信息,对于未知协议包输出其协议号。
3. 具体分析tcp包。记录其连接的次数。进行攻击模式匹配,如防止恶意扫描,防止dos land攻击,防止winnuke攻击,防止longrul攻击,防止probe cgi攻击。如果存在攻击则打开日志文件进行日志记录并跳入第4步。
4. 循环执行上述第2步,直到收到终止信号。最后输出此次监听信息总结。
首先自定义头文件对所需要引用到的系统文件进行声明,如/netinet/in.h说明ip封装上层协议对应的编号等等、/netinet/ip.h、/netinet/tcp.h、/netinet/udp.h、/netinet/ip_icmp.h文件系统自定义了ip等数据包的数据结构,程序中可以直接使用。下面的表2.1和表2.2分析了ip包头和tcp包头结构。
表2.2 tcp头结构
/sys/ioctl定义了linux系统中的常用端口、设备、网络接口等数据结构以及网卡工作模式标识等。/sys/socket.h、/sys/sockios.h、netinet/in.h定义了网络编程所需要的数据结构和网络函数等。/sys/type.h定义了指定套接字的类型。
htonl()用来将参数指定的32位hostlong 转换成网络字符顺序。返回值 :返回对应的网络字符顺序。
htons()将16位主机字符顺序转换成网络字符顺序。返回对应的网络字符顺序。返回对应的网络字符顺序。
inet_addr()用来将参数cp所指的网络地址字符串转换成网络所使用的二进制数字。网络地址字符串是以数字和点组成的字符串。成功则返回对应的网络二进制的数字,失败返回-1。
inet_aton()用来将参数cp所指的网络地址字符串转换成网络使用的二进制的数字,然后存于参数inp所指的in_addr结构中。成功则返回非0值,失败则返回0。
inet_ntoa()用来将参数in所指的网络二进制的数字转换成网络地址,然后将指向此网络地址字符串的指针返回。成功则返回字符串指针,失败则返回NULL。
(1) 打开sockets连接、指定封装协议、指定捕获协议。
/*打开一个接收ip协议封装的数据包的socket,返回int型socket描述符*/ /*PF_PACKET为提供捕获机制的协议簇* /*SOCK_DGRAM指定将数据包的数据链路层头部去掉*/ /*htons(ETH_P_IP)代表是ip协议封装的包*/ Packetfd = socket (PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
(2) 指定设备驱动程序对网卡的I/O通道进行管理,设置网卡混杂模式。
/*设置网卡模式为混杂模式,使其能够接受一切通过主机的数据,不管数据是否是发送到本机*/ strcpy (ifr.ifr_name, "eth0"); /*赋网络设备名,实际物理网卡*/ if (ioctl(packetfd, SIOCGIFFLAGS, &ifr) < 0) err_quit ("ioctl can not get flags\n"); /*设置网卡模式为混杂模式*/ ifr.ifr_flags |= IFF_PROMISC; if (ioctl(packetfd, SIOCSIFFLAGS, &ifr)<0) err_quit ("can not set PROMISC mode\n");
(3) 系统网络信息如图2.1所示。
图2.1 系统网络信息
(4) 利用死循环反复读包,读包函数recv解析。读包信息如图2.2所示。
sbuffptr = malloc(sizeof(struct sbuff));
/*读包程序,返回数据包长度,并将包信息存到buff数组中,否则返回-1*/
n = recv(packetfd, buff, sizeof(buff),0);
if(n<0) /*出错,或者接受队列已清空,没有数据包可读*/
err_quit("read wrong\n");
图2.2 反复读包