关键词:信息安全,网络漏洞,套接字,分布式拒绝服务,简单邮件传输协议
一 扫描器软件概述
计算机网络的迅猛发展引发了人们对网络安全的重视,信息安全的目标在于保护信息保密性、完整性以及对合法用户提供应有服务。网络漏洞是系统软、硬件存在安全方面的脆弱性,安全漏洞的存在导致非法用户入侵系统或未经授权获得访问权限,造成信息篡改和泄露、拒绝服务或系统崩溃等问题。系统管理员可根据安全策略,使用网络工具实现系统安全审计。
1.1 扫描器的功能
扫描器是检测远程或本地系统安全脆弱性的软件;通过与目标主机TCP/IP端口建立连接和并请求某些服务(如TELNET、FTP等),记录目标主机的应答,搜集目标主机相关信息(如匿名用户是否可以登录等),从而发现目标主机某些内在的安全弱点。扫描器的重要性在于把极为烦琐的安全检测,通过程序来自动完成,这不仅减轻管理者的工作,而且缩短了检测时间,使问题发现更快。当然,也可以认为扫描器是一种网络安全性评估软件。一般而言,扫描器可以快速、深入地对网络或目标主机进行评估。
1.2 扫描器的分类
从信息流的角度理解信息安全,可划分为数据存放的安全性与网络传输的安全性(涉及操作系统安全性及应用程序的安全性),网络中任何一个环节出现不安全因素都会破坏整个信息流的安全性,因此把扫描器分为三类:数据库安全扫描器,操作系统安全扫描器和网络安全扫描器(针对于网络服务、应用程序、网络设备、网络协议等)。对扫描对象的脆弱性进行深入了解,能较好地用运用程序来自动检测发现其是否存在已有的漏洞;能给扫描时发现的问题提供一个良好的解决方案;能在系统实现时,提高效率并提供了相应的补救信息。
二 网络扫描器设计方案
网络扫描器是一个涉及知识面广、动态性强的软件,应具有易于配置、易于扩展、快速扫描、智能报告和深度分析等功能。网络扫描是对系统脆弱性的分析评估,能够检查、分析网络范围内的设备、网络服务、操作系统、数据库系统等系统的安全性,从而为提高网络安全的等级提供决策的支持。
2.1 基本功能模块
经过大量的分析与调研,进而设计出由以下几个模块组成的网络扫描器:用户界面,友好的用户界面使扫描配置更加简单有效,结果显示清楚条理,扫描插件维护功能方便;扫描引擎,检测目标系统,调度扫描插件模块,执行安全测试;扫描插件,主要完成对目标系统的检查;脆弱性报告,能够依据不同的需求,提供不同形式的报表;数据库,包括系统安全漏洞、告警信息和补救方法。
2.2 扫描内容的分类
根据安全漏洞的测试原理,扫描内容可分为:general普通、Microsoft win9x/NT平台、firewalls防火墙、useless services无用服务、ftp文件传输协议、backdoors后门程序、cgi abuses(cgi滥用)、remote file access远端文件获取、gain root remotely远端获得根权限、rpc远端过程调用、nis网络信息服务、finger abuses(finger 滥用)、smtp problems简单邮件传输协议的错误、virus病毒、DDoS分布式拒绝服务、Router Setting路由器配置等20多种类型,800多个安全漏洞。简介如下:
(1)ftp文件传输协议类
ftp服务广泛应用于Internet中,同时具有显著的安全脆弱性。如匿名ftp本身不是安全漏洞,但其提供了访问远程系统能力,入侵者可借此获取系统口令文件并探测系统漏洞,因而通常禁用匿名ftp服务,开放时必须正确配置并进行严格管理;此外,建立上传目录往往为了便于在Internet上交换文件,而网络攻击者则在可写区域中肆意删除、修改信息或上传恶意代码(如特洛伊木马、计算机病毒等)。
(2) DDoS分布式拒绝服务类
分布式拒绝服务攻击也是最为常见的网络攻击方法,进攻形式多种多样。从利用网络协议到针对操作系统平台的漏洞,都可以发出拒绝服务攻击,可以说其攻击手段防不胜防。通过发送连续的字符可以检测Microsoft SQL Server等数据库服务器是否有DDoS漏洞。
(3) firewall防火墙类
设置网络防火墙的目的是在通信网与外界网之间提供一道屏障,以保护网络中的信息流免受来自外部网络的各种威胁。防火墙可以是路由器、PC机、主机系统或一批主系统,是硬件和软件的组合体。由于网络防火墙自身存在的设计问题和使用配置错误,扫描器可以检测不同类别或版本的网络防火墙存在的安全漏洞。
三 实现中的关键问题
网络扫描器采用B/S模式进行软件开发,B/S模式是指软件的主体部分都在服务器端,用户只需使用浏览器发出扫描服务的请求,由服务器执行对扫描目标的扫描操作,并将最终扫描结果以脆弱性报告形式发送到客户端。这种模式的优点在于用户只需通过浏览器,就可以对目标进行扫描,操作简单易学。
3.1 Windows Sockets编程
Socket存在于通信区域中是网络通信基本构件,是可以被命名和寻址的通信端点,网络编程中各套接字都有相关进程与其类型对应。下面仅就网络扫描器开发过程中用到的Windows Socket的一些共性操作加以说明。
(1) 设置服务器地址和连接端口
struct sockaddr_in sad; // 获得主机地址的结构
struct hostent *ptrh; // 指向主机入口的指针
ptrh=NULL;
sad.sin_port=htons(21); // 如设定连接端口为21
sad.sin_addr.s_addr=inet_addr(host->ip); //扫描目标主机IP地址
sad.sin_family=AF_INET; // 地址类型规范
(2) 创建Windows Socket套接字
套接字类型可根据通信特征进行分类。Windows Sockets 1.1支持两种套接字:流套接字SOCK_STREAM和数据报套接字SOCK_DGRAM。具体实现如下:
SOCKET sd; // 定义sd为Socket
sd=socket(PF_INET,SOCK_STREAM,0); //创建TCP Socket套接字
if (sd<0) {return FALSE;} // sd<0表示本地创建Socket失败,返回值为假
socket(int af, int type, int protocol)指定地址族、数据类型和协议描述符及相关资源。
(3)套接字建立连接与数据的收发
connect(SOCKET s, const struct sockaddr FAR * name, int namelen)参数s是套接字描述符,name是套接字地址结构指针,namelen说明套接字地址长度。
在TCP协议中数据发送与接收函数为send和recv,UDP协议中为sendto和recvfrom,使用时调用程序要提供超时控制。
send ( SOCKET s, const char FAR * buf, int len, int flags );
recv ( SOCKET s, char FAR * buf, int len, int flags );
sendto(SOCKET s,const char FAR * buf,int len,int flags,const struct sockaddr FAR * to, int tolen ); //UDP协议中数据发送函数
recvfrom ( SOCKET s, char FAR * buf,int len, int flags, struct sockaddr FAR * from, int FAR * fromlen ); //UDP协议中数据接受函数
3.2 数据结构
检测系统存在的安全漏洞是不断被发现与升级的,这要求网络扫描器的开发应具有很强扩展性,通过准实时的增加扫描功能或扩展扫描插件可较好解决这一问题,插件的开发利用Microsoft Visual C++ 6.0编译链接后生成DLL文件。为便于统一管理,将文件的扩展名修改为NFS,由NFS的调用模块调用执行,编写的插件源代码包括如下两个数据结构:
struct RECORD
{ char classname[50]; //插件所属的类型名
char ID[10]; //标名插件的类及成员关系
char membername[50]; //插件的成员名称
char filename[50]; //插件对应的文件名(不含路径)
char risk[10]; //标名风险的等级
char description[300]; //该插件对应的文字描述
char advice[300]; //该插件提供的一些建议
bool mark; //标识该插件是否被某一模板选中
}record; //建立信息说明数据库,内容包括插件所属的类型名、插件的类及成员关系、插件对应的文件名、风险的等级、提供的建议等。优点是主调模块可自动加载插件文字说明部分,存储到数据库中,便于主程序快速调用,易于开发人员的管理和配置。
struct HOST
{ char ip[15]; //目标主机的IP地址
int mark; //标示buff的类别
char buff[200]; //动态返回信息
int timeout; //超时控制变量
}host; //指定了插件运行的参数,包括目标主机IP地址、动态返回信息及标示类别与超时控制变量,主机IP和超时控制参数由主调模块传递。优点是使插件富有灵活性和扩展性。两个标准函数:extern"C" __declspec( dllexport )BOOL InitFunc(struct RECORD *record)
和extern "C" __declspec( dllexport ) BOOL ApplFunc(struct HOST *host) 前者便于插件管理和使用,后者根据不同参数实现相关功能。
3.3 编程示例
在设计方案中依照扫描内容将插件分为20多类,这里对具有普遍性和代表性的例子加以分析说明(篇幅所限仅列出插件中主要函数部分代码)。
(1)检测Microsoft SQL Server 是否有DDoS漏洞
extern "C" __declspec( dllexport ) BOOL InitFunc(struct RECORD *record)
{ strcpy(record->advice,"过滤发向端口1433的数据包。"); //建议
strcpy(record->classname,"DDoS"); //类型
strcpy(record->description,"SQL server接收连续0信号TCP包时被非法关闭");
strcpy(record->filename,"mssqlserver_dos.nfs");
strcpy(record->ID,"6XX"); //编号
strcpy(record->membername,"mssqlserver_dos");
strcpy(record->risk,"严重"); //等级
record->mark=true;
return true;}
extern "C" __declspec( dllexport ) BOOL ApplFunc(struct HOST *host)
{ struct sockaddr_in sad; //structure to hold server's address
struct hostent *ptrh; //pointer to host entry
SOCKET sd; char buf[6]; memset(buf,0,6);
memset((char *)&sad,0,sizeof(sad)); //clear sockaddr structure
ptrh=NULL;
sad.sin_port=htons(1433); // SQL通信端口号1433
sad.sin_addr.s_addr=inet_addr(host->ip);
sad.sin_family=AF_INET;
sd=socket(PF_INET,SOCK_STREAM,0); // TCP连接
if (sd<0) {return FALSE;}
if (connect(sd,(struct sockaddr *)&sad,sizeof(sad))<0)
{closesocket(sd); return FALSE;}
buf[0]=0x00; buf[1]=0x00; buf[2]=0x00;
buf[3]=0x00; buf[4]=0x00; buf[5]=0x00;
send(sd,buf,sizeof(buf),0);
closesocket(sd); Sleep(2000); //等待
sd=socket(PF_INET,SOCK_STREAM,0); //再次建立连接
if (sd<0) {return FALSE;}
if (connect(sd,(struct sockaddr *)&sad,sizeof(sad))<0)
{closesocket(sd); return true; }//连接失败,则发生拒绝服务
closesocket(sd); return FALSE;}
简要说明:Microsoft SQL Server通信端口为1433,程序首先与SQL Server建立TCP连接并判断连接是否成功;然后向服务器发送连续字节的0并关闭连接,等待数秒后,再次试图与服务器建立连接,如果失败则表明服务器已发生拒绝服务故障。
(2)smtp problems简单邮件传输协议漏洞扫描
extern "C" __declspec( dllexport ) BOOL InitFunc(struct RECORD *record)
{ strcpy(record->advice,"升级NT Mail3系统。"); //建议
strcpy(record->classname,"SMTP problems"); //类型
strcpy(record->description," smtp存在非授权邮件收发,可能成为攻击跳板");
strcpy(record->filename,"nt_spam.nfs");
strcpy(record->ID,"7XX");
strcpy(record->membername,"nt_spam");
strcpy(record->risk,"中");
record->mark=true;
return true;}
extern "C" __declspec( dllexport ) BOOL ApplFunc(struct HOST *host)
{ struct sockaddr_in sad; //structure to hold server's address
struct hostent *ptrh; //pointer to host entry
SOCKET sd; char buf[1024]; memset(buf,0,1024);
memset((char *)&sad,0,sizeof(sad)); //clear sockaddr structure
ptrh=NULL; sad.sin_port=htons(25); // 端口号25
sad.sin_addr.s_addr=inet_addr(host->ip);
sad.sin_family=AF_INET;
sd=socket(PF_INET,SOCK_STREAM,0);
if (sd<0) {return FALSE;}
if (connect(sd,(struct sockaddr *)&sad,sizeof(sad))<0)
{closesocket(sd); return FALSE;}
strcpy(buf,"HELO\n"); //第一步
send(sd,buf,sizeof(buf),0); //发送数据
fd_set rd; //超时控制
FD_ZERO(&rd); FD_SET(sd,&rd);
struct timeval tv={host->timeout,0};
select(sd,&rd,NULL,NULL,&tv);
int n=recv(sd,buf,1024,0); //接收数据
if (n<0) {closesocket(sd);return FALSE;} // 判断接收是否成功
strcpy(buf,"MAIL FROM:<>\n"); //第二步
send(sd,buf,sizeof(buf),0); //发送数据
FD_ZERO(&rd); //超时控制
FD_SET(sd,&rd); select(sd,&rd,NULL,NULL,&tv);
n=recv(sd,buf,1024,0); // 接收数据
if (n<0) {closesocket(sd);return FALSE;} // 判断接收是否成功
strcpy(buf,"RCPT TO: nobody@990.net\n"); //第三步
send(sd,buf,sizeof(buf),0); // 发送数据
FD_ZERO(&rd); // 超时控制
FD_SET(sd,&rd); select(sd,&rd,NULL,NULL,&tv);
n=recv(sd,buf,4,0); //接收4字节的字符串
if (n<0) {closesocket(sd);return FALSE;} // 判断接收是否成功
closesocket(sd); //在字符串中寻找执行成功代码“250”
if ((buf[0]=='2')&&(buf[1]=='5')&&(buf[2]=='0')) return true;
if ((buf[1]=='2')&&(buf[2]=='5')&&(buf[3]=='0')) return true;
return FALSE;}
简要说明: SMTP保证高效可靠地传输邮件服务器上安装不同的服务软件后,可能会因程序错误和配置不当引起一些安全漏洞。可能导致服务器停止SMTP服务,也可能使存储在服务器上的用户邮件信息泄露、丢失或被篡改。程序分三个步骤执行:首先与目标主机NT Mail3系统25端口建立TCP连接,发送“HELO\n”并在超时时间内判断有无接收;然后发送“MAIL FROM:<>\n”并在超时时间内判断有无接收;最后发送“RCPT TO: nobody@990.net\n”,如接收到代码“250”则存在安全漏洞。
(3)gain root remotely(远端获得根权限类):这类插件测试的目标主机一般都有操作系统平台上的漏洞或服务程序配置不当。远程攻击者通过向主机发送特定的非法数据,如过长的命令行,可导致主机发生缓冲区溢出、处理器资源耗尽等故障,根据操作系统和服务软件的不同,有的故障还可能会提高远程用户的权限。
extern "C" __declspec( dllexport ) BOOL InitFunc(struct RECORD *record)
{strcpy(record->advice,"升级至最新版本或者过滤来自TCP 617端口的数据流");
strcpy(record->classname,"gain root remotely");
strcpy(record->filename,"Arkeia.nfs");
strcpy(record->ID,"4");
strcpy(record->membername,"Arkeia");
strcpy(record->risk,"高");
record->mark=true;return true;} //也可取自数据库,对漏洞划分等级提出建议
extern "C" __declspec( dllexport ) BOOL ApplFunc(struct HOST *host)
{ struct sockaddr_in sad; //structure to hold server's address//
struct hostent *ptrh; //pointer to host entry//
SOCKET sd; char buf[10000];
memset(buf, ’a’, 10000); // buf中存储了10000字节的“a”
memset((char *)&sad,0,sizeof(sad));//clear sockaddr structure//
ptrh=NULL; sad.sin_port=htons(617); // 连接端口设为617
sad.sin_addr.s_addr=inet_addr(host->ip);
sad.sin_family=AF_INET;
sd=socket(PF_INET,SOCK_STREAM,0); //本地创建套接字
if (sd<0) {return FALSE;} //建立套接字连接
if (connect(sd,(struct sockaddr *)&sad,sizeof(sad))<0)
{closesocket(sd);return FALSE;}
send(sd,buf,sizeof(buf),0); //发送buf中的数据
closesocket(sd); sd=socket(PF_INET,SOCK_STREAM,0);
if (sd<0){closesocket(sd);return FALSE;} //再次建立连接
if (connect(sd,(struct sockaddr *)&sad,sizeof(sad))<0)
{closesocket(sd);return FALSE;} closesocket(sd);
return true;}
调试说明:插件调试时由于没有找到相应的服务程序,服务器只打开了默认通信端口617来模拟服务程序;在与主机建立连接后,向其发送10000个字节数据企图使服务器缓冲区溢出。关闭这个连接再试图建立新连接,如失败则认为达到了预先的攻击目的。
四 结束语
随着Internet的高速发展,国家社会信息化建设脚步的加快,包括政府机关、军队、企业与商业在内的各行各业进入了一个前所未有的网络建设时代。但由于黑客活动日益猖獗,网络入侵事件越来越多,网络系统的安全已经成为网络建设面临的一个重大问题:如何能够有效地防止网络系统被攻击,是网络建设需要首先解决的问题,同时了解网络安全状况又是防止网络被攻击必须解决的问题;只有发现并填补了网络系统存在的各种安全漏洞,才能更有效地保护我们自己的网络,真正将网络带来的优势发挥出来。
参 考 文 献
Andrew S.Tanenbaum.计算机网络.北京:清华大学出版社,1998
anonymous.网络最高安全技术指南.北京:机械工业出版社,1998
David A.Solomon. Windows NT技术内幕.北京:清华大学出版社,1999
Douglas E.Comer. TCP/IP网络互连技术.北京:清华大学出版社,1998
David J.Kruglinski. Visual C++ 技术内幕.北京:清华大学出版社,1999
Chris hare, Karanjit Siyan. Internet防火墙与网络安全.北京:机械工业出版社,1998
Andrew S.Tanenbaum, Albert S.Woodhull.Operating Systems Design and Implementation.北京:电子工业出版社,1999
延伸阅读
文章来源于领测软件测试网 https://www.ltesting.net/