现在信息安全已经成为热门行业,而程序漏洞又在信息安全里面占有很重要的地位,因此我们有必要对如何研究漏洞、找出程序中的臭虫进行研究。
在我写的《漏洞研究方法总结》里面总结了一些经验,建立安全模型,源代码、二进制代码分析等的一些研究方法,但总体上还是人工去找漏洞,这对于研究的人员要求也比较高。现在大量的服务软件出来,而基本上都存在着漏洞,完全靠人员去一个个的分析代码测试显然满足不了需求,所以我们需要设计一个比较自动化能够适合多数服务器的测试工具。原来也编写过测试工具,利用测试工具辅助研究。但原来编写的getiisfile还是具有很强的针对性,基本上只能用于WEB服务等的一些研究,也不够自动化。
那我们如何设计一个比较通用的测试工具呢?不同的服务有不同的协议,而很多漏洞研究也是协议相关性很大,所以我们研究一个服务的漏洞,往往先研究其协议、熟悉其软件等,然后研究其漏洞。这显然是一个漫长的过程,所以我们的测试软件不能走这套路子。如果我们的测试软件里面也需要“掌握”每个服务的协议知识,那显然就不能很好的做到通用,所以我们需要提炼一些服务的共性。仔细想想,现在的大多服务模型就是一个服务端,一个客户端,两者利用通信协议通信,所以服务的共性就是数据包的通信,具体每个数据包里面什么内容怎么解释,那就是看每个服务采用的协议,我们的测试程序不能涉及到具体协议。再想想,像IIS的.htr的溢出包,就是请求”GET /aaa.htr HTTP/1.1 \r\n HOST:host”的”aaa.htr”这个域比较长 ,IIS的ipp的溢出包,就是请求“GET /a.printer HTTP/1.1 \r\n HOST:host”的”host”这个域比较长而又没有超过一个范围。很多服务的漏洞不就是包里面的某个域的数据过长或者数值不对的问题吗?所以我们的漏洞测试工具的主要任务就是构造、自动发送这些某个域数据有问题的包。怎么构造这样的包呢?我们可以采用脚本的方法,脚本指定怎么构造、构造什么样的包。测试不同的服务,只要编写针对这个服务的简单脚本,这样程序就能够通用了。不同服务采用不同的协议,他们接收的包要有一定的协议要求,那怎么解决协议的问题呢。我们可以采用样本包的办法,就是脚本里面提供一个样本包,构造包都在这个样本包的基础上,这样就可以满足包的协议要求,也可以避免测试每个服务我们需要掌握其协议的要求。
其实我们的设计主要两点好的思路,一个就是脚本,这个使得我们的程序编写好后比较通用,而又能够比较灵活。再一个就是样本包的解决办法,这个屏蔽了具体协议,这样我们的测试已经基本上是协议无关的了。比如我们要测试一个新的数据库软件的漏洞,不需要先分析好它的协议、包格式后才能开始了。
好了,现在基本设计方案已经明朗了,剩下的就是需要考虑脚本包含一些什么内容,以能够更有效的进行测试。
我们可以把脚本提供的一些相关参数放一块,组成一个节,这样方便我们的程序读取脚本参数,也方便我们自己编写、阅读脚本。还有就是最好支持注释。
一、测试目标;
1、目标IP;
2、协议;这儿的协议当然是UDP,TCP、ICMP等;
3、端口;有些协议没有端口的概念;
4、可能这些项通过样本包直接提供。
二、样本包;
1、样本包提供的方式;为了更有效的进行测试,我们有必要通过多种途径提供样本包。如脚本里面直接提供样本包,这个需要处理包的输入问题,比如我们的脚本是以回车换行分隔各个脚本变量等,那么样本包显然需要处理回车换行等,还有0的问题,不可显示字符的输入,所以基本上需要一个16进制的输入和直接字符输入的混合输入方法。通过一个样本包数据文件提供样本包。通过抓包提供样本包。这个抓包提供样本包,可以方便我们到具体应用环境测试,因为这个测试工具的测试效果显然主要靠样本包要能够是有问题包的一个基准,所以样本包越丰富,测试得也会越多。再一个可以第一项的测试目标也可以通过样本包提供。
三、测试包组装;
1、发包前固定发送的信息;这个像有些FTP的测试,可能需要认证,而是需要测试认证后的命令处理。可以每次发包前固定发送认证内容,这样就可以通过认证了。
2、样本包的分隔符;用于把样本包的各个域分隔出来,分隔符可以指定多个。比如请求“GET /a.htr?a=var1&b=var2 HTTP/1.1\r\nHOST:host\r\n\r\n”,分割符就可能有空格” ”、”?”、”=”、”&”、”\r”、”\n”、”:”等,当然也要处理16进制的输入问题。
3、测试域范围;包分隔后从第几到第几个域进行测试,或者从样本包的哪个偏移到哪个偏移进行测试。
4、测试的类型;服务软件处理一个包里面常见的错误一个是包字符串的处理错误,一个是一些数值的错误。
对于字符串测试:
5、添加的域前缀、后缀;比如测试CGI的问题,可能需要URL域后面要有固定串”.cgi”。
6、域串测试开始长度、结束长度、步长;
7、填充所用的字符;一般测试可能就用”a”填充,但如果要测试那个域的处理是否有格式串的问题,可能就需要填充”%s”、”%n”等这样的串了。
对于数值测试:
8、数值字段单位(字节、字、双字)、开始、结束、步长;
四、测试包发送;
1、 是否采用阻塞模式;
2、 每次发包是否重新连接;
3、 两个包发送之间等待时间;
4、每个包发送次数;
五、返回信息处理;
1、 是否接收返回信息;
2、 返回信息是否记录;
3、 返回信息特征串的搜索,报警处理;比如IIS返回”The remote procedure call failed”,就是RPC服务出现了错误,一般就是溢出或者有漏洞什么的了,可以进行报警或者LOG里面进行记录。
4、 返回信息的分析处理,判断服务有问题;这点可能一时还比较难。
比如:
getiisfile 80 "GET /" 1 a .ida
返回” 找不到 IDQ 文件 c:\inetpub\wwwroot\a.ida。”
getiisfile 80 "GET /" 10 a .ida
返回”找不到 IDQ 文件 c:\inetpub\wwwroot\aaaaaaaaaa.ida。”
getiisfile 61.132.55.67 80 "GET /" 239 a .ida
返回”c:\inetpub\wwwroot\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaa.i??????r。系统找不到指定的路径。”
显然此程序已经发生了错误,239个”a”的请求已经与1个、10个”a”的请求不一样了,多了后面一个尾巴” ??????r”。其实是strncpy调用没有串结尾的一个问题,这样导致泄露了堆栈的内容。要根据返回信息自动判断这些问题,可能算法就比较难做了,这种问题我们还是采用人工识别可能好做点。
六、LOG;
1、 测试状态的LOG;方便测试停止后的继续测试。
2、 每个测试的状态、返回信息的LOG;
这样我们可以构造发送各种包,显然还不能算完,我们还得知道这些包的效果,服务软件到底出问题没有。现在判断问题主要根据返回信息,这显然不够,这只能收集到很少部分信息,主要信息显然都在服务器上,所以我们还需要有服务端运行的软件配合检测服务软件的状态。这个大致可以从下面一些方面入手:
一、 内存使用监视;这个可以用现有软件或者写软件监视,可以判断一些内存不释放的漏洞。
二、 异常的监视;像一些溢出、数值非法导致的内存非法访问等往往会导致一些异常,这个保护模式的CPU就会产生一个异常中断,在WINDOWS下程序就会返回到NTDLL.DLL的引出函数”KiUserExceptionDispatcher”的入口,所以可以编写软件拦截这个入口或者在SOFT-ICE下设置这个断点,再根据调用这个入口提供的数据结构,得到发生异常时的EIP等寄存器内容,判断是否程序真正有问题。*NIX系统下可以采用可加载内核模块(LKM)拦截系统的异常中断,然后进行综合判断。如果写程序,难点就主要在这个判断是否程序错误、漏洞的算法,不过看来应该还比较乐观,差不多出现异常就是有问题了。*NIX系统由于基本上没有结构异常这个概念,所以一般程序发生错误基本上就会进程死掉等,所以很好判断。内存交换出去了等异常WINDOWS自己识别了不会返回到这个入口,再就是WINDOWS结束一个线程等可能会进入这个入口,但基本上得到的发生异常的EIP是比较固定的,所以很好排除。但WINDOWS编程有结构异常的概念,所以如果不拦截异常,很多程序的错误可能就不会暴露出来。
三、 服务进程状态的监视;像很多服务程序出现问题后,系统可能会杀死服务进程,IIS5等系统会自动重新启动此服务进程,*NIX等系统可能会产生进程DUMP的操作,所以我们都可以根据这些信息判断服务软件是否产生了错误。
阅读(267) | 评论(0) | 转发(0) |