频道栏目
首页 > 安全 > 工具软件 > 正文

网络漏洞扫描器的设计与实现,第二部分

2013-12-04 09:04:46           
收藏   我要投稿
上一文:http://www.2cto.com/Article/201312/261793.html

简介: 漏洞扫描器是一种自动检测远程或本地主机安全性弱点的程序。通过使用漏洞扫描器,系统管理员能够发现所维护的Web服务器的各种TCP端口的分配、提供的服务、Web服务软件版本和这些服务及软件呈现在Internet上的安全漏洞。从而在计算机网络系统安全保卫战中做到“有的放矢”,及时修补漏洞,构筑坚固的安全长城。

 
本文的第一部分分析了当前网络巨大的安全隐患,概述漏洞扫描器原理并针对目前TCP/IP网络和各种网络主机的安全现状,设计了一个网络漏洞扫描器。本部分将具体阐述了这个网络漏洞扫描器的实现。
网络漏洞扫描器的实现
扫描模块的实现
整个网络漏洞扫描器的核心部分是扫描模块,它是由很多子模块组成的,其结构如图2所示。
基本信息探测子模块的实现
在设计时加入该模块的目的是在调用扫描主模块之前探测主机是否在线,以避免不必要的空扫描。该模块的实现原理和常用的ping命令相似,方法是向目标主机发送ICMP回显报文请求,根据返回值来分析判断主机是否在线。所有安装了TCP/IP协议的在线网络主机,都会对这样的ICMP回显报文请求给与答复。虽然现在有些主机装了个人防火墙,可以屏蔽掉这样的ICMP回显报文请求,但是我们这个扫描系统的对象是提供网络服务的网络主机,而这样的主机是不应该屏蔽掉ICMP回显报文请求的,因为这样会让一些用户误认为该主机不在线,从而丧失了作为网络服务器的意义。为了降低网络拥塞导致丢包的可能性,在实现中重复四次向目标主机发送ICMP回显请求包。
该模块不只探测主机是否在线,而且能根据ICMP回显应答报文的TTL(TTL是位于IP首部中的生存时间字段)值来粗略分辨出目标主机操作系统,为下一步的扫描提供依据,特别是在扫描模块的调用和漏洞库的选择上。
该模块在实现中和其他模块不同的一个最大特点是:其他扫描模块是针对应用层的,用一般的套接字即能完成网络连接;而该模块是针对于网络层的,使用一种叫原始套接字的技术来实现。原始套接字(raw socket)提供了一些使用TCP和UDP套接字不能实现的功能:可以访问ICMP和IGMP等协议的数据包,可以读写内核不处理的IP数据包,可以创建自定义的IP数据首部。使用原始套接字可以编写基于IP协议的高层网络协议。
端口扫描子模块的实现
当基本信息探测子模块得知目标主机在线时,端口扫描子模块即被调用。该模块将根据传来的参数相应的扫描TCP的1~1024或者1~65535端口。扫描方式是利用TCP的完全连接方式,即利用TCP connect 扫描技术来设计扫描模块,这是最基本的TCP扫描。通常通过调用套接口函数connect()连接到目标计算机上,完成一次完整的三次握手过程。如果端口处于侦听状态,那么connect()就能成功返回。否则,这个端口不可用,即没有提供服务。这个技术的一个最大的优点是不需要任何权限。系统中的任何用户都有权利使用这个调用。另外的一个优点就是比其他扫描方式(如SYN扫描和FIN扫描等等)更稳定可靠。但这种方法的一个缺陷是:扫描方式不隐蔽。通常作为一个扫描器软件的应用,TCP的connect会重复且大量地被集中使用,在被扫描的一端则会很容易发现这种扫描行为,目标计算机的log文件会显示一连串的连接和连接是否出错的服务消息,并且能很快地使它关闭;而且大多数防火墙也能屏蔽这种扫描,随着防火墙技术的快速发展,其他的一些曾经被认为是很隐蔽的扫描方式也可能被防火墙发现并屏蔽掉。所以相对而言,TCP connect扫描方式的这个缺陷已经被淡化了。而且,我们开发的扫描系统是从系统管理员的角度出发,因此上述的问题都是不存在的,除非他/她非法扫描他人网站主机。

 
图2 扫描模块的结构
网络扫描是个集中的、重复的行为,显而易见,它也是个比较耗资源的行为--不光是耗费扫描主机的资源,也耗费被扫描主机的资源;不光占用主机的资源,同时也占用网络相当多的资源。总体上看是个特别耗时的过程。在该网络扫描器的设计和实现的过程中,我们从两方面进行了优化:利用非阻塞连接技术和多进程技术。其结果是,首先,这两种技术的运用明显地加快了扫描的速度;而且,用多进程来实现高效率的利用了资源,从而达到了节省资源的功效。
网络漏洞扫描是建立在端口扫描的基础之上的。从黑客攻击行为的分析和收集的漏洞来看,绝大多数都是针对某一个网络服务,也就是针对某一个特定的端口的。所以漏洞扫描也是以同样的思路来进行的。而如今大多数国内国外的扫描器把端口扫描和具体的漏洞扫描分开来,相互之间几乎没有什么联系:端口扫描的目的就是为了向用户报出当前所开的端口和网络服务,以及看是否有些特定的后门存在;漏洞扫描则完全是另外一个独立的流程,不管目标主机的相应端口及服务是否打开,都要做一系列的扫描。这样看起来好像扫得很全面很彻底,但很明显的一点是,如果在对目标主机毫无了解的情况下,比如说是一台最普通的、几乎没有提供任何网络服务的机器,此时对它也进行彻底的漏洞扫描可以说是意义甚微的,甚至可以说在某些时候会对系统及网络有些反面的影响。
而我们在设计实现该漏洞扫描系统时则从另一个角度出发,保证在达到同等目的的前提下,尽量少占用网络、主机以及时间资源,提高资源的利用率和扫描系统的效率。基本思想是:避免不必要的模块调用,根据不同的实际情况来调用相应的扫描子模块。
在实现中,所有子模块的运行都是和端口扫描的主流程同时进行的。在此,我们利用了多进程技术来实现并发。进程是具有一定功能的程序,是关于一个数据集合的一次运行活动,它是程序运行的基本单位。在传统的UNIX模型中,当一个进程需要由另一个实体执行某些操作时,该进程派生(fork)一个子进程,让子进程去进行处理。此时子进程与父进程是完全独立的两个运行实体,以这样的方式可以实现并行。现在在UNIX/Linux系统中也可以用线程来实现程序的并行执行。和线程比起来,fork子进程存在以下两个问题:
  1. fork的代价是昂贵的:内存映像要从父进程拷贝到子进程,所有描述字要在子进程中复制等等。目前的实现使用一种称为写时拷贝(copy-on-write)的技术,可避免父进程数据空间向子进程的拷贝,除非子进程需要自己的拷贝。尽管有这种优化技术,fork仍然是很昂贵的。
  2. fork子进程执行后,需要用进程间通信(IPC)在父子进程之间传递信息。fork之前的信息容易传递,因为子进程从一开始就有父进程数据空间以及所有描述字的拷贝。从子进程返回信息给父进程则需要做更多的工作。
在我们的扫描系统的设计中,所需要的并发执行模块数并不是很多,对于现有的硬件设备来讲,创建十来个子进程的代价根本算不上什么,这样fork子进程的第一种缺陷的影响几乎就不存在了; 关于它的第二种问题其实对我们的实现也没有影响,因为这些扫描子模块之间以及子模块和主模块之间的交流除了共享文件之外,避免了其它的通信。而且从实现上来说,线程使用比较复杂,采用fork子进程会使开发和调试相对简单易行些。
入侵扫描的实现
从图2中可以看出,由于扫描方式的不同,可以将端口扫描子模块分为两大类:网络扫描和入侵扫描。与网络扫描不同,入侵扫描没有对应的漏洞库,本节简单介绍三类入侵扫描子模块的实现方式。
FTP弱势密码探测子模块主要是对一些可能存在的用户名作弱势密码的探测。其实现方法主要就是模拟客户端的用户协议解释器的功能,和服务器端建立连接并发送一系列命令和处理相应的应答,以此模拟登录,从而判断是否存在有弱势密码的账号。
FTP命令和应答在客户和服务器的控制连接上是以NVT ASCII码形式传送的。这些命令都是3或4个字节的大写ASCII字符,其中一些带选项参数。从客户向服务器发送的FTP命令超过30种,如ABOR(放弃先前的FTP命令和数据传输)、QUIT(从服务器上注销)、SYST(服务器返回系统类型)等。应答都是ASCII码形式的3位数字,并跟有报文选项。其原因是软件系统需要根据数字代码来决定如何应答,而选项是面向人工处理的。在我们的子模块中是根据应答中的数字代码来判断的,如125(数据连接已经打开,传输开始)、331(用户名就绪,要求输入口令)、501(语法错误--无效参数)等。
OPENRelay邮件转发漏洞是针对SMTP网络协议的。用TCP进行的邮件交换是由报文传送代理MTA(Message Transfer Agent)完成的。最普通的Unix系统中的MTA是Sendmail。客户端MTA通过访问服务器端的25号端口来和服务器端的MTA通信。两个MTA之间也用NVT ASCII进行通信。客户向服务器发出命令,服务器用数字应答码和可选的可读字符串进行响应。这与FTP非常类似。关于服务器端的应答也与FTP非常类似,在此就不赘述了。
OPENRelay邮件转发漏洞探测子模块也是通过发送一系列的命令和分析处理一系列的应答,以此模拟客户端MTA的功能来通过服务器连续发送一定数量的邮件,从而判断服务器是否没有屏蔽掉OPENRelay的功能。
Unicode遍历目录漏洞探测子模块是针对80端口的WWW网络服务的。WWW服务遵循的是HTTP协议,所以HTTP协议的一些特点决定了该子模块的实现。Unicode遍历目录漏洞的扫描是对IIS服务器软件的编码机制存在的漏洞进行具体的探测。不同的测试漏洞的特殊编码加上命令后,被封装在HTTP协议的请求中,向目标主机的80端口发送,并靠分析返回的状态码分析这种编码是否绕过了IIS的路径检查,可以执行相应的命令了。在Unicode遍历目录漏洞探测子模块的实现中,所采用的请求方法是GET方法。
扫描模块的流程
扫描模块在工作时,首先进行初始化,在初始化阶段,主要是读取所需的参数。比如从基本信息探测子模块得到操作系统类型,由此来决定在扫描中需要使用的漏洞库;还有一些用户自己配置的参数。除了读取参数外,还要建立一些文件以供以后使用。
初始化后,建立非阻塞socket并连接,然后根据得到的相关端口及对应的服务,来调用相应的漏洞扫描子模块(包括CGI漏洞扫描子模块、POP漏洞扫描子模块、FTP漏洞扫描子模块、SSH漏洞扫描子模块、HTTP漏洞扫描子模块、SMTP漏洞扫描子模块和IMAP漏洞扫描子模块以及三种类型的入侵扫描子模块),当所有的端口都已经扫描完以后,调用后门扫描子模块和其他漏洞扫描子模块。由于这两个扫描子模块并不是针对某一个端口或网络服务的,所以没有像其他的漏洞扫描子模块一样在端口扫描过程中被调用。但有一点是和其他子模块是一致的,即这两个子模块的调用形式也是通过创建子进程来完成的。
3.5 漏洞库的建立
一个网络漏洞扫描系统的灵魂就是它所使用的系统漏洞库,漏洞库信息的完整性和有效性决定了扫描系统的功能,漏洞库的编制方式决定了匹配原则,以及漏洞库的修订、更新的性能,同时影响扫描系统的运行时间。
设计原则
通过比较分析和实验分析,在漏洞库的设计中,我们遵循了以下几条原则:
  1. 从漏洞库的简易性、有效性出发,选择以文本方式记录漏洞。这样易于用户自己对漏洞库进行添加配置。因此在我们提供漏洞库升级的基础上,又多出了一条途径更新漏洞库,以保持漏洞库的实时更新,也使得漏洞库可以根据不同的实际环境而具有相应的特色。
  2. 对每个存在安全隐患的网络服务建立对应的漏洞库文件。一般情况下一个网络服务对应两个漏洞库,一个是针对UNIX的漏洞库,另一个则是针对Windows NT/2000的漏洞库。
  3. 对漏洞危险性进行分级。这有助于系统管理员了解漏洞的危险性,从而决定所要采取的措施。
  4. 提供漏洞危害性描述和建议的解决方案。有些扫描器,虽然扫描漏洞的功能强大,但不提供详细描述和解决方案(如著名的扫描器ISS Internet Scanner)。这往往导致系统管理员对检测出的漏洞没有足够的重视,或不了解它的危害也不知如何修补漏洞而暂置一旁。因此,漏洞扫描器要真正发挥它的预警及预防的作用,真正成为系统管理员的有效助手,就应当提供对漏洞的具体描述和有效的解决方案。
漏洞分级原则
在对黑客攻击行为分析的基础上,又借助了一些资深的系统管理员的经验,我们对漏洞进行了比较粗略的分级。将漏洞按其对目标主机的危险程度分为三级,即A级、B级和C级。A级漏洞是允许恶意入侵者访问并可能会破坏整个目标系统的漏洞,如允许远程用户未经授权访问的漏洞。A级漏洞是威胁最大的一种漏洞,大多数A级漏洞是由于较差的系统管理或配置有误造成的。同时,几乎可以在不同的地方,在任意类型的远程访问软件中都可以找到这样的漏洞。如,FTP、gopher、Telnet、Sendmail、finger等一些网络程序常存在一些严重的A级漏洞。B级漏洞是允许本地用户提高访问权限,并可能允许其获得系统控制的漏洞。例如允许本地用户非法访问的漏洞。网络上大多数B级漏洞是由应用程序中的一些缺陷或代码错误引起的。Sendmail和Telnet都是典型的例子。此外,因编程缺陷或程序设计语言的问题造成的缓冲区溢出问题也是一类典型的B级安全漏洞。C级漏洞是任何允许用户中断、降低或阻碍系统操作的漏洞,如拒绝服务漏洞。最典型的一种拒绝服务攻击是SYNFLOOD,即入侵者将大量的连接请求发往目标服务器,目标主机不得不处理这些"半开"的SYN,然而并不能得到ACK回答,很快服务器将用完所有的内存而挂起,任何用户都不能再从服务器上获得服务。综上所述,对网络主机危害最严重的是A级漏洞,其次是B级漏洞,而C级漏洞是对系统正常工作进行干扰。
漏洞库的实现
通过大量的多方收集,主要是对 www.cert.org、 www.aucert.com、 www.securefocus.com及中国绿色联盟等反黑权威网站漏洞信息进行分类整理,我们对存在漏洞的主要的网络服务逐一建立了三级漏洞描述文件,作为各个漏洞扫描子模块的访问库体。
在每个漏洞库文件中,每条漏洞信息占一行,行首用"!"标示漏洞级别,叹号的个数代表漏洞危险级别。A级危害以"!!!"标示,B级以"!!"标示,C级以"!"标示。接下来是漏洞的特征字符串,当特征字符串不止一个时,用一个不容易引起混淆的(~)字符加以隔离。
漏洞形成的原因形形色色、不一而足,在我们设计开发的漏洞库中,主要包含以下类型的漏洞:CGI脚本漏洞、POP3漏洞、FTP漏洞、SSH漏洞、HTTP漏洞、SMTP漏洞、IMAP漏洞、后门漏洞、RPC漏洞、DNS漏洞等。下面我们将以CGI脚本漏洞和SMTP漏洞为例来简单说明漏洞库的编制。
(1)CGI脚本漏洞
CGI脚本是实现Web交互功能的重要手段。Shell 脚本、Perl程序和C可执行程序是CGI脚本最常采用的形式。由于程序编写上的疏忽,很多CGI脚本都存在漏洞,根据我们所收集的漏洞信息,CGI漏洞的危害主要有三种:
  1. 缓冲区溢出攻击
    这种攻击实质是不遵守规则、歪曲或违反页面中建立的某个限制或约束。大部分CGI 脚本是作为HTML表单的后台运行的,负责处理由用户输入的信息并提供某种定制的输出。因为在这种情况下,大部分CGI 脚本编写时都等待某种特定格式的数据。然而,黑客可以有许多方法绕过这些预定义的格式而给脚本发送一些看起来是随机的数据。此时,由于CGI 脚本可能在对输入数据的有效性的判定上存在不足,缺少全面的输入验证和净化,导致攻击者能够将特殊的字符和本地系统命令结合起来,作为参数输入,从而使得Web服务器执行该命令。
例如: !/cgi-bin/phf
漏洞描述: Apache httpd服务器程序(1.0.3版本)的PHF脚本由于输入验证中遗失了对换行符("\n",十六进制为0x0a)的检查,从而可用于转义脚本,诱骗Web服务器程序的本地语法运行该转义符后的任何内容。比如,如果受攻击的Web服务器程序的执行用户具有/etc/passwd文件的读权限,那么以下URL将输出该文件的内容: http://www.somedomain.org/cgi-bin/phf?Qalias=x%0a/bin/cat%20/etc/passwd 解决方案:自行修改该脚本,加入对\n的检验,或者暂停使用该脚本。
  1. 数据验证型溢出攻击
    由于CGI程序本身或程序调用的函数缺乏对用户输入数据的合法性检查,未能滤除一些特殊字符,使得入侵者可以通过构造请求来达到入侵的目的。比如,缺乏对"../"的过滤,可能导致入侵者读取系统的任意文件。
例如: !!/shop.cgi
漏洞描述:shop.cgi/shop.pl用于网上购物,支持SSL,包含多种验证模块,配置文件是shop.cfg。正常的请求显示商品信息的URL语法是: http://example.com/cgi-bin/shop.cgi/page=products.htm/SID=SHOPPING_ID_HERE ,于是带有客户信息的products.htm文件被显示出来。$page变量的值是通过open()调用打开的,open()调用本身并没有做任何输入/访问验证,也没有任何边界检查,诸如: http://example.com/cgi-bin/shop.cgi/page=../../../../etc/passw 。这样的URL请求是合法的,于是/etc/passwd就会被打开并显示出来。 解决方案:考虑利用正则表达式增加输入验证,过滤诸如../ 和 .\./ . 之类的字符组合,也可以增加一个变量限制目录遍历深度。结合这两种技术,就可以限制来自潜在攻击者的任意目录遍历行为。
  1. 信息泄漏
    一些CGI程序所提供的功能自身违背安全性要求,如损害了信息的保密性,极易被入侵者利用。
例如: !/webpage.cgi
漏洞描述:当URL请求的文件不存在时,webpage.cgi会向客户端浏览器返回某些敏感信息,比如脚本所在路径、HTTP根目录所在路径、Perl版本、server_admin、server_name、PATH环境变量等。这就可以为进一步的攻击做准备。 解决方案:在浏览器中禁止java applet。目前,大多数网站均使用免费的公共CGI脚本程序去驱动各自的Web服务,如此导致有缺陷的CGI脚本在Internet上泛滥开来。因此,对CGI脚本的安全性应高度重视。
(2)SMTP漏洞
SMTP(Simple Mail Transfer Protocol,简单邮件传输协议)是用来发送邮件的协议,其服务守护程序是Sendmail。Sendmail因为大而复杂,配置又十分麻烦,所以一度曾是Unix上的漏洞最多的程序,著名的蠕虫病毒就是利用Sendmail旧版本上的一个"DEBUG"命令的漏洞而从一个系统传播到另一个系统的。又如:利用ETRN命令可使Sendmail停止响应(即拒绝服务)。当Sendmail接收到ETRN命令时,它将调用fork()。此时子进程将代替父进程发送响应输出,而父进程将不再响应send()/write()错误。因此攻击者可发送大量ETRN命令,然后中断连接,这会使父进程连续地调用fork()和sleep(5),而无法恢复正常的响应。
攻击者利用这个漏洞可以产生大量的"不可用"Sendmail子进程,导致Sendmail长时间挂起(即使攻击者的网络带宽和资源很少)。直接的后果就是耗尽所有的服务器内存(Linux 2.0内核将崩溃,出错信息为'no memory for Sendmail'、'no memory for klogd'或其它)。
Sendmail服务程序不断的升级,同时新的漏洞也不断的出现。一个不经意的错误,往往成了可怕的隐患。Sendmail高级版本中仍存在着种种漏洞,仅举两例说明:
例1: !!Sendmail~8.7
!!Sendmail~8.8.0
!!Sendmail~8.8.1
!!Sendmail~8.8.2
漏洞描述:Sendmail版本8.7-8.8.2存在一个可获得超级用户权限的漏洞。Sendmail服务一般作为守护进程运行,在标准SMTP端口(通常是25号端口)"监听"连接请求。超级用户是唯一允许以这种方式启动Sendmail服务的,因为Sendmail协议中有代码强制执行这种限制。但由于一个编码错误,任何本地用户都可能绕过检查,以守护进程的方式启动Sendmail。通过改变Sendmail的邮件环境,用户可以以超级用户的权限令Sendmail执行任意程序。
解决方案:升级到Sendmail 8.10以上的版本。
例2: !Sendmail~8.9.3
漏洞描述:mail.local是Sendmail里面的一个程序,它被用作本地邮件的传送代理。mail.local使用LMTP(本地邮件传输协议)接受标准输入并发信给用户。当在LMTP模式下时,mail.local处理的消息以".\n"开始。因此,我们可以发送一个2047字节的,后跟".\n"的字符串。那么这个字符串后面的内容就会被mail.local当做LMTP命令来处理。这样sendmail的日志或者过滤机制就失去了作用。另一个问题是,当LMTP命令被执行的时候,mail.local可能会产生结果输出。但是sendmail并不知道,所以不会去读I/O buffer。这些结果输出如果很多,就会导致sendmail和mail.local死锁,I/O Buffer也会被填满。
解决方法:sendmail 8.10以上版本已经解决了deadlock/LMTP 问题


回页首
结束语
我们针对目前TCP/IP网络和各种网络主机的安全现状,设计并实现了一个网络漏洞扫描器,该扫描器基于浏览器/服务器(B/S)结构,可以扫描UNIX、Windows 2000/NT等多种操作系统的安全漏洞。通过试运行,可以看出该扫描器具有如下特点:
  1. 能够多方位、多角度对处于网络环境中的重要网络主机进行安全扫描,可以分别模拟黑客和系统管理员的身份,对处于网络环境中的主机可能面对的安全隐患进行全面的检查。
  2. 扫描覆盖面广:能同时在系统级和应用级上进行隐患扫描。能针对网络主机的主流操作系统包括Unix、Linux和Windows NT/2000进行扫描,能检测出多达1000多种现势漏洞。
  3. 扫描速度快:利用多进程并发和TCP的非阻塞连接等技术加快了扫描的速度。在特定的扫描中根据不同的实际情况运行不同的模块,尽量避免一些没有必要的代码段的运行,进一步提高效率和速度。
  4. 可扩展性强:作为体现整个扫描系统功效的重要组成部分,漏洞库可从多个途径不断扩充、更新。用户可以根据简单的易操作规则把一些最新出现的安全漏洞整理后加入漏洞库。整个操作过程都十分简单友好。
  5. 可移植性强:采用服务器/浏览器结构,浏览器端可放在几乎任何操作系统平台上。目前运行在Linux平台上。
  6. 可配置性好:通过友好的图形化界面,用户可以十分方便的配置本系统的主要参数,以便于灵活的适应各种各样的实际网络应用环境。
  7. 扫描结果详尽:扫描结果包括关于被扫描主机的各方面详尽的信息。其中包括主机的IP地址、操作系统类型及版本号、补丁号、网络主机的三大网络服务的信息描述,以及主机开放的所有网络服务、主机上存在的网络安全漏洞等。另外,系统对扫描出的漏洞根据它的危害程度进行分级分别标示。并提供完整易操作的步骤来帮助用户方便地消除隐患。
  8. 人机界面美观友好:提供了一个全中文化的图形界面,界面赏心悦目,可操作性强,尽量达到简单易用。
 
关于作者
李志强,计算机应用硕士学位,目前主要从事网络安全技术(漏洞扫描技术和入侵检测技术)的研究与开发工作,可以通过E_mail: lizq_99@163.com与他联系。
 
上一篇:网络漏洞扫描器的设计与实现,第一部分
下一篇:Meterpreter扩展工具包的基本应用2
相关文章
图文推荐
文章
推荐
热门新闻

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站