附图说明
图1是本发明截获系统调用并获取Call Stack数据的Ptrace机制;
图2是本发明单个系统调用对应的调用栈图的示例图;
图3是本发明调用栈图生成算法流程图;
图4是本发明训练1个小时的Samba进程的调用栈图节点统计
图5是本发明训练2个小时的Samba进程的调用栈图节点统计
图6是本发明训练8个小时的Samba进程的调用栈图节点统计
图7是本发明训练16个小时的Samba进程的调用栈图节点统计
图8是本发明训练8个小时的Samba进程的调用栈图节点统计
图9是本发明训练24个小时的Samba进程的调用栈图节点统计
图10是本发明训练2个小时的Wu-ftp进程的调用栈图节点统计
图1是本发明训练4个小时的Wu-ftp进程的调用栈图节点统计
图12是本发明训练6个小时的Wu-ftp进程的调用栈图节点统计
图13是本发明训练1个小时的Apache(Httpd)进程的调用栈图节点统计
图14是本发明训练2个小时的Apache(Httpd)进程的调用栈图节点统计
图15是本发明训练4个小时的Apache(Httpd)进程的调用栈图节点统计
图16是本发明训练2个小时的Imapd进程的调用栈图节点统计
图17是本发明基于n层调用栈图的通用调用链匹配算法
图18是本发明带匹配度的深度优先搜索流程图
图19是本发明对两次Apache-SSL攻击进行检测的结果
图20是本发明对1次Wu-ftp缓冲区溢出攻击的检测结果
图21是本发明对11次Samba缓冲区溢出漏洞暴力攻击尝试的检测
图22是本发明对1次Imap缓冲区溢出漏洞攻击的检测结果
具体实施方式
下面结合附图对本发明作进一步详细说明。
参见图1,本发明是通过Ptrace机制获取进程系统调用对应的调用栈数据。当父进程Parent通过fork()产生一个子进程Child,然后父进程Parent进入等待;子进程Child通过PTRACE ME主动请求被其父进程Parent跟踪,通过系统EXECVE函数运行被跟踪的进程,如果成功执行,则会在执行第一个系统调用前停下来,并发送一个SIGCHILD信号给等待的父进程Parent,父进程Parent停止等待后发出PTRACE_SYSCALL请求重新启动停止的系统调用,父进程Parent重新进入等待;子进程Child继续执行,在系统调用的入口处被信号SIGTRAP停止并发出SIGCHILD信号中止父进程Parent的等待状态,父进程Parent退出等待状态,在这个时候,可以获取到系统调用入口处的各种信息,并可以进行相应的处理;然后父进程Parent发出PTRACE_SYSCALL请求重新启动停止的系统调用,自己第三次进入等待子进程Child发出停止信号的状态,子进程Child将被停止的系统调用运行结束,在系统调用退出前被信号SIGTRAP停止并通知父进程Parent,父进程Parent在这个时候可以获取系统调用运行后的返回值和其他信息,然后再发出重新启动信号让子进程Child继续运行下一个系统调用,开始新的一轮对系统调用数据的控制和观察,直到子进程Child结束。从这个过程中可以看出,对子进程Child的每个系统调用,可以进行两次有效的观察。一次是在系统调用的入口处,一次是在系统调用结束退出之前的时候。在这两次观察中,第一次可以获得系统调用的调用号、传入参数、返回地址以及调用函数的栈帧指针EBP;第二次可以获得系统调用执行后的返回值,系统调用中分配的栈帧信息等。本发明是在第二次观察时进行调用栈信息获取的。
通过获取的系统调用的调用栈信息,可以建立如图2所示的单个系统调用的调用栈图,如图2所示的一个n层Call Stack图,其中每层上面有k个可能的调用地址,每个调用地址nk(k∈{1..t})(t为第n层可能出现的不同的调用地址的个数)为唯一存在,也即是每层的节点保持着唯一性。Call Stack图是本发明中最重要的数据结构,它清楚地表明每个系统调用执行过程中对操作系统中的基本库函数的调用过程。对这些调用地址的建模可以帮助研究人员对远程或本地缓冲区溢出等非常严重的入侵事件从系统调用对应的调用栈中进行观察和建立相应的防卫机制。当节点(n-1)j出现后下一个调用地址为节点nk则就构成了节点(n-1)i到节点nk之间的连接边,其实这个边是有方向性的,它是由节点(n-1)j指向节点nk的一条有向边,因此构成的Call Stack图本质上也是一个有向图。如图2所示,可以看到当进入一个系统调用时,从第1层的节点11对应的调用地址开始进行调用操作,当第1层的调用完成后再转向第2层的节点21对应的调用地址,由此不断地进行调用操作,但每一层上仅有1个节点对应的地址被调用,从第n-1层某个节点到第n层的某个节点之间存在一条边E(n-1),n,当系统调用退出时,就得到了一条调用地址链L(E12,E23,...,E(n-1,n)),因此每两层之间存在的边就前后相连构成了调用地址链L(E12,E23,...,E(n-1,n)),也就是系统调用运行时在Call Stack图中对应的一条调用路径。从理论上将,当Call Stack图训练到完备情况下时正常状况下的调用链肯定能从图上找到对应的执行路径,也即是L(E12,E23,..,E(n-1,n))∈G(V,E,S)。为了更好地描述Call Stack图中可能出现的节点数量,本文提出了分歧因子的定义,如下:分歧因子(Branching factor):在一个假想的状态空间中,每个状态都可以扩展得到b个状态,则认为这些状态的分歧因子就是b。
在一个n层分歧因子为b的Call Stack图中,如果从第一层的唯一一个节点开始到第二层产生了b个节点,每个节点在第三层又产生b个节点,以此类推在第n层可以产生bn个节点。则整个Call Stack图上最多可以产生1+b+b2+b3…+bn个节点。但在实际情况下,Call Stack图上的节点个数会远远小于这个数。
参见图3,本发明采用CSGBA(Call Stack Graph Building Algorithm)算法来构建调用栈图。调用栈图是由不同的调用链构建成的。将获得的调用链的数据在建立的调用栈上进行分层匹配。由于建立的调用栈图是有向图,由第i层的节点指向第i+l层的节点,因此在每个节点的数据结构中保存了与之相连的下一层节点的关联信息,其中包括关联节点和对应的关联边。调用栈构建算法的基本原理:是循环地将调用链的第i个节点Ch[i]在调用栈图Graph上对应的第i层进行匹配。当第i层上存在这样的节点Ch[i]时,通过获取此节点的关联边从而发现是否与第i+l层的节点Ch[i+1]有关联,从而确定是否已有一条建立在节点Ch[i]和节点Ch[i+1]之间的边。如果不存在关联,则建立与Ch[i+1]节点之间的边,从而建立它们之间的关联。而当第i层上不存在这样的节点Ch[i]时,在第i层上创建新的节点Ch[i],并将Ch[i+1]作为下一层的关联节点,并以此建立了第i层节点Ch[i]和第i+l层节点Ch[i+1]之间的关联边。通过这样的i次递归,可以将不同的多个调用链利用调用栈图Graph描述出来,其中每个节点可能拥有多个关联边和下层关联节点,它们的数量和节点的分歧因子是一致的。对图3所示流程图的描述:Call Stack图构建算法的输入为获取的调用链Ch[]和图变量Graph,初始化层变量i和节点(边)的存在标志,将第i层与调用链的长度进行比较,当层数i小于调用链的长度时,读取第i层的节点,当第i层的节点不为空时,对其包含的节点地址和Ch[i]进行匹配,如果节点包含的地址≠Ch[i],则返回上一步读下一个节点,如果节点包含的地址=Ch[i],则查看节点的关联边是否为空,如果为空则添加边,如果不为空,则和下一个调用链节点Ch[i+1]进行匹配,如果不相等则继续读取下一个关联边,如果相等即关联节点地址=Ch[i+1]则读取第i层的下一个节点,如果关联边为空,则添加关联边。如果读取第i层的节点为空,则添加节点,添加边,同时层数i递增1。
为了训练指定进程的调用栈图,需要对指定的进程进行训练。训练的目的是通过对指定进程进行各种不同方式的使用从而建立每一种系统调用的调用栈图。在这种实时的训练方式下,进程中涉及到的各种系统调用将以不同的方式或参数运行,这样就会产生更多不同的系统调用链,由此可以构成更加完备的调用栈图。从理论上分析,在越长的时间内训练,使用更完备的操作,就可以因此获得更多的不同的调用链,直到得到整个进程中的所有系统调用出现时产生的不同的调用链,从而构成完备的调用栈图。但在实际情况下,由于程序涉及到的功能有可能非常多,非常复杂,而理论上完备的调用栈图只能无限趋近,但不一定能真正获得,因而这使得不可能获得真正完备的调用栈图,只能近似获得。本发明的实验在RedHat 7.2(内核2.4.7-10)环境下进行的,其中对Samba、Wu-ftp、Apache以及Imap等Linux操作系统中的一些关键服务对应的进程进行了训练。其中,训练结果图中的横坐标表示的是出现的系统调用总的数量,而纵坐标指所有系统调用对应的总的系统调用链的个数,也即是所有系统调用在调用栈图中的节点的总和。
训练结果图如图4到图16所示,由图中可以看出,对Samba进程的训练时间最长,达到24个小时,同时训练得到的节点数也最多,而对Httpd进程训练得到的节点数最少。这也说明Samba进程的功能和结构非常复杂,而Httpd和Imapd进程的功能和结构相对简洁。从图中也可以看出,对以上四种进程的训练都进入了稳定状态,即在相对长的一段时间内每个进程对应的Call Stack图中没有出现新的节点,我们就认为获得到了相对稳定的Call Stack图。
在检测过程中,本发明对被检测进程进行跟踪,对每个出现的系统调用的调用链进行检测,通过带最大匹配度的深度优先搜索发现这条链在调用栈图中的匹配程度。通过提出带滑动窗口的异常度的计算方法,将匹配度与异常度映射起来;以便用更加明显的方式来进一步区分这个进程是正常的还是异常。
如图17和18所示,如果被检测的调用链长度为L,将其在指定的系统调用的调用栈图中进行搜索和匹配。从图17流程图的描述可以看出,基于n层调用栈图的通用调用链匹配算法的初始部分为被匹配的调用链Ch[],接着初始化最大匹配度数组MD[]和访问标志数组Visited[],读取第i层的节点,如果节点v不为空则通过Visited[v→id]来判断其是否被访问过,同时是否等于调用链节点Ch[i],如果这个节点没有被访问过,同时它包含的地址等于Ch[i],则调用DFS-MMD算法,进行深度优先搜索和匹配,同时将这个节点的访问标志Visited[v→id]改为Visited[v→id]=1(表示已经访问过);如果这个节点已经被访问过或它的地址不等于Ch[i]则继续读取第i层的下一个节点,直到节点为空,这时层数i加1,如果层数i大于总的层数n则通过Maxium(MD[])计算获得到的最大匹配度。
如图18所示的带匹配度的深度优先搜索算法(DFS-MMD)流程图,初始部分为被检测调用链Ch[j],将当前节点V0的访问标志置位,并求节点V0的邻节点,当不存在邻节点时,计算最大匹配度MD[j]=j/L;返回Max(MD[m]),当节点V0的邻节点w存在时,下一步判断w是否被访问过,如果是则求下一个邻节点,如果w没有被访问过,则判断w包含的地址是否等于Ch[j],如果不相等,则计算最大匹配度MD[j]=j/L并返回Max(MD[m]);如果相等,则把当前节点w做为当前节点V0,调用链节点j递增1,如果j小于调用链的总长度,则从当前节点又开始下一轮DFS-MMD算法;如果j大于调用链的总长度,则计算最大匹配度MD[j]为j/L并返回Max(MD[m]);
带匹配度的深度优先搜索有非常低的内存需求,同时其时间复杂性为O(bn),虽然它的时间复杂性和宽度优先搜索相同,但它的实际速度仍然比宽度优先搜索快,因为它往往可以在仅仅搜索一小块状态空间以后获得结果。而宽度优先必须要搜索完n层调用栈图的所有路径。但带匹配度的深度优先搜索在最坏的情况下的时间复杂性仍然为O(bn)。对于一个n层以及分歧因子为b的调用栈图来说,带匹配度的深度优先搜索在内存中仅需要保存b×n个节点,而相同情况下宽度优先搜索要保存bn个节点。从实际的实验数据发现,通常调用栈的层数都在20以下,也有个别系统调用的调用栈图的层数较大,但也都在40以下;另外,所形成的调用栈图中的分歧因子的大小也都在40以下。由于实际中的分歧因子和层数都不是很大,因此在实际的使用上也获得了较好的性能。
为了把最大匹配度与异常度联系起来,本发明提出了带滑动窗口的异常度度量方法。基本思想是把在滑动窗口内的每个系统调用产生的调用链在调用栈图中的最大匹配值进行累加再减窗口长度,用所得到的值来描述窗口内所有系统调用对应的调用链是否是异常还是正常,从而建立了最大匹配度和异常度之间的映射关系。因此针对异常度的具体度量方法如下:
(0≤MD[i]≤1 0≤Ad[w]≤WL)
其中Ad[w]为第w个滑动窗口处的异常度值。Max(MD)[i]为滑动窗口中第i个系统调用的调用链在对应的调用栈图中的最大匹配度。WL为窗口长度,在实验中选择窗口长度为6。因此有0≤Ad[w]≤6。当Ad[w]越小则越正常,当Ad[w]越大则越异常。带滑动窗口的异常度的度量方法可以把最大匹配度和异常度进行映射起来,避免了没有使用滑动窗口时,单靠一个系统调用的调用链对应的最大匹配度作为异常判断时造成的报警不明显等问题。这种方法使得正常情况下的系统调用窗口的异常度和异常情况下的异常度之间的区别更加明显。当Ad[w]越小则越正常,当Ad[w]越大则越异常。通过设置特定的阈值,当Ad[w]超过特定的阈值则系统发出报警,当Ad[w]低于阈值则系统不发出报警,以此系统通过报警通知系统管理员采取必要的安全防卫措施。在实际测试中,系统把WL/2做为报警阈值。
图19到图22表示了在这种技术下对Linux服务器上的各种服务的入侵检测结果。为了验证本发明的模型和方法,在RedHat7.2(内核2.4.7-10)上进行了系统地试验。实验中检测的攻击种类包括Apache-SSL攻击、Wu-ftp缓冲区溢出攻击、Samba缓冲区溢出暴力攻击以及Imap缓冲区溢出攻击。这几种服务在Linux平台非常具有代表性,这些攻击在Linux平台的严重程度都非常高。实验中图的横坐标是出现的系统调用滑动窗口的序号,纵坐标是异常度。当本发明的检测系统在跟踪被检测进程时,我们对出现的每个系统调用的调用栈数据都进行检测,通过在对应进程的调用栈图中搜索得到当前调用链的最大匹配度。通过获得的最大匹配度,采用滑动窗口长度为6的系统调用序列中每个调用对应的调用链的最大匹配度进行累加,然后通过带滑动窗口的异常度的度量方法获得当前窗口对应的异常度的大小。通过这个异常度可以用来确定系统是否有入侵发生。对有的漏洞进行了实际多次攻击,而对有的漏洞进行攻击时采用了模拟黑客入侵行为的方式。通过带滑动窗口的异常度度量方法可以计算出每个滑动窗口相对应的异常度。实验结果中纵坐标表示的是异常度,它表示在当前窗口内出现的系统调用产生的调用链在调用栈图中不匹配的总程度。
如图19所示,本发明在实验中进行了两次针对Apache服务中存在的SSL漏洞的攻击,所进行的两次攻击都是成功的入侵,而且在发起两次攻击之间的时间相隔不到2分钟。两次攻击都获得了系统apache用户的使用权限。图19表示的是采用带最大匹配度的深度优先搜索对Apache-SSL两次成功攻击进行入侵检测的结果。从图19中可以看出,从开始跟踪Httpd进程,异常度一直为0,保持着正常的运行状态,说明Httpd进程没有受到任何攻击或出现异常的行为。当发起第一次攻击时,在大约第285个滑动窗口处,异常度就达到了4,当攻击过程结束后,异常度又返回到0,在图19上表现为第一个突起的异常值;当发起第二次入侵时,在大约303个滑动窗口处异常度的值达到了6,随后伴有较大的一次异常波动,波动幅度达到了5。因此,从对Httpd进程的入侵检测结果来看,检测结果明显地反映了两次入侵对Httpd进程的系统调用的调用链数据产生的异常。
如图20所示的检测结果所示,从图中可以看出,在初始阶段的Wu-ftp的滑动窗口异常值一直为最小值0。而当入侵攻击发起的时候,发现从大约第169个系统调用滑动窗口处出现了异常度为2的反复波动,直到大约第265个滑动窗口处,异常值达到了最大值6,并伴有幅度为6的最大幅度波动,直到在大约第361个滑动窗口处才降低到最小值0。在成功入侵受害机系统后,本发明模拟黑客在目标机器上运行了以下的一些命令序列:
#dir#ls#cat/etc/passwd#cat/etc/shadow#exit |
从第一个命令dir开始,当执行一个命令时,异常值从最小值急剧上升到最大值6,然后再迅速下跌到最小值0,这样不断的反复,直到exit命令退出。也可以根据此现象来判断某些入侵后的行为情况和入侵时间长短等信息,但某些入侵后产生的shell由于不是被跟踪进程的子进程,因此不能观察到其具体的入侵行为,如图19描述的对Apache-SSL服务的入侵检测。当最后一个命令exit执行后,入侵产生的shell退出,Wu-ftp进程恢复正常。通过对Wu-ftpd进程的检测,获得了非常好的实验结果,一方面通过实验成功地发现了整个入侵过程分为入侵发起过程和入侵成功后的黑客行为过程。从图20可以看到,从大约第169个系统调用滑动窗口到大约第265个系统调用滑动窗口处是入侵的初始阶段,这个阶段的异常值波动不是特别大,幅度大约在2左右。这个阶段黑客还没有成功的入侵到受害机,当这个阶段结束后,黑客在成功的入侵后往往会发出一系列命令来达到其目的。因此,从图20可以看到,从第265到第361个系统调用滑动窗口处的异常值波动就非常大,幅度达到了最大值6。这种对黑客入侵后的行为进行进一步跟踪的性能使得这个系统的功能更加强大,这也对观察入侵后黑客的行为在系统调用的调用栈级的异常提供了可观察的直接依据。
如图21所示的检测结果,在实验中对Samba缓冲区溢出漏洞进行了11次连续的返回地址暴力猜测,以求达到入侵系统的目的。但所有11次攻击都属于失败的攻击,将这些失败的攻击确定为有11次攻击尝试或攻击企图。图21中表示的是对Samba进程中存在的缓冲区溢出漏洞进行入侵攻击的检测结果。从图中可以看出,和Httpd、Wu-ftp进程一样,对于正常行为时的异常度总是始终保持在最小值0。本发明对Samba进程进行了11次暴力尝试溢出的返回地址,当尝试的返回地址为正确的Shellcode地址时,入侵将取得成功,否则失败,再进行下一次尝试。但实验中进行的对11次暴力尝试返回地址(从地址0xbffffed4到地址0xbffff8f8)进行的猜测都没有成功,仅仅是11次入侵尝试。从图21看到,从大约第133个滑动窗口开始异常值就陡然上升到最大值6,然后进入了由最大值6到最小值0的反复波动,系统表现出了和正常状态非常不一致的情况。这11次暴力攻击尝试持续了约2分钟,当暴力攻击结束后,系统调用的滑动窗口中的异常值又减小到最小值0。在不到2分钟的攻击过程中,整个检测结果图中的异常度波动非常大,而且频率也非常高,这主要是由于暴力攻击的次数较多,攻击时间较短所造成的。
如图22所示的检测结果,实验中本发明对Imap缓冲区溢出漏洞进行了1次成功的入侵,图22表示的是对Imap进程中存在的缓冲区溢出漏洞进行入侵攻击的检测结果。从图中可以看出,在发起入侵攻击前从初始滑动窗口到第257个滑动窗口之间,异常值始终保持着最小值0,表明初始阶段Imap进程对应的系统调用的调用链在调用栈图上能完全准确地匹配,也即是Imap处于正常的运行中。而当发起针对Imap缓冲区溢出漏洞的入侵攻击时,异常值急剧上升至5,并在异常值5和4之间反复波动,这个过程大约持续了约有60个系统调用滑动窗口,然后又恢复到正常状态0。当入侵成功以后,在实验中模拟了黑客的一些行为,运行了如下的一些系统命令:
#ls#cat/etc/passwd#cat/etc/shadow#dir#dir#pstree-p#netstat-anp |
由于Imap缓冲区溢出攻击生成的入侵shell是作为Imapd的子进程存在的,因此本发明的系统能够对其进行跟踪。从图22可以看出,在大约第298个滑动窗口到第397个滑动窗口之间对应的异常值从最大值到最小值的反复几次波动表示系统中的入侵者发出了一系列的异常行为,并且和入侵者发出的命令相对应。通过对比图22中针对Wu-ftp缓冲区溢出攻击的检测结果,可以看出对Imap的检测结果和前面对Wu-ftp进程的检测结果有相似的一方面,都是将检测结果分为两部分,一部分是针对入侵过程的检测,一部分是对入侵后的入侵者的行为的检测。前一部分的异常值总是低于后一部分的异常值,并且入侵过程对应的异常值波动比较频繁,而入侵后的行为部分的异常值波动较大,但却并没有出现频繁波动,而是随着黑客入侵后发出的行为一个一个产生的。对Imapd进程的入侵检测获得了非常好的检测结果,不仅获得了入侵初始阶段的异常值,而且还获得了成功入侵后黑客行为在系统调用的调用栈中对应的异常值,从而可以进一步观察黑客入侵后的行为。
通过对内核级系统调用对应的调用栈信息建立指定进程的调用栈图,并结合提出的带最大匹配度的深度优先搜索和带滑动窗口的异常度,实现了对指定进程系统调用的调用链的异常检测机制。本发明对Httpd、Samba、Wu-ftpd以及Imapd四个重要的系统服务的调用栈图进行了训练,获得了具有不同数量节点的稳定的调用栈图。通过带最大匹配度的深度优先搜索,可以把被检测进程的系统调用的调用链在其对应的调用栈图上进行搜索匹配,以获得到最大匹配度。通过获得的最大匹配度,本发明采用滑动窗口将一定长度的系统调用序列中每个调用对应的调用链的最大匹配度进行累加,然后通过带滑动窗口的异常度的计算方法获得当前窗口对应的异常度的大小。这种方法确定了滑动窗口内系统调用序列的调用链相对于调用栈图的异常度,通过这个异常度可以用来确定系统是否有异常入侵发生。实验中本发明分别对Apache(Httpd)、Wu-ftpd、Imapd以及Samba等系统重要服务进行了攻击检测。成功地发现了2次Apache-SSL缓冲区溢出入侵、1次Wu-ftpd缓冲区溢出入侵、11次Samba暴力攻击以及1次Imapd缓冲区溢出攻击。实验结果表明本章提出的方法较好地通过系统调用的调用栈信息检测了黑客的入侵。对Imapd和Wu-ftpd进程的测试实验中,不仅获得了入侵初始阶段的异常值,而且还得到了成功入侵后黑客行为在系统调用的调用栈中对应的异常值。为以后深入研究黑客入侵后的行为在系统底层的表现打下了良好的基础。
本发明进程的系统调用的调用栈图建模安全可靠,通过对进程的不同功能的操作与使用,从而可以建立准确的进程的调用栈图的模型;异常行为检测准确,检测范围覆盖最严重的各种安全威胁;利用带最大调用链匹配度的深度优先搜索进行链匹配,其时间复杂性和空间复杂性都较低;带滑动窗口的异常度度量技术可以把最大匹配度和异常度进行映射起来,避免了报警不明显等问题。这种方法使得正常情况下的异常度和异常情况下的异常度之间的区别更加明显;对发现有异常行为的进程可以及时采取防卫措施,避免了黑客的进一步入侵。