SAPI与网络服务器安全研究
Research of the Web Server Security Based on ISAPI Filter田东风,秦江波
(中国地质大学(北京) 信息工程学院 北京 100083)
摘要:本文探讨了一种基于IIS服务器的ISAPI过滤器技术,通过过滤器进行服务器数据转发,从而隐藏了后台服务器,使之更加安全.
关键词:ISAPI过滤器 B/S结构模式 Web服务器
1. B/S模式的三层体系结构
目前基于WWW服务的应用越来越多,这些应用系统的结构也由C/S模式发展为B/S模式.我们首先简要分析一下B/S模式的三层体系结构.
B/S 模式就是采用浏览器/服务器结构的网络计算模式,用户使用浏览器向服务器发起请求,服务器接到请求后处理用户的请求然后将处理结果返回给浏览器.在浏览器与服务器的传输过程中采用了HTTP协议.而三层体系结构,就是数据显示层,数据逻辑处理层,数据存储层.数据显示层采用一定的方式将用户需要的数据内容以某种形式表达给用户,让用户理解数据的内容和意思.数据逻辑处理层对显示层交互的数据进行逻辑处理与控制.数据存储层负责存储用户的数据信息,以便与用户交互.
在Windows环境下,该三层体系结构将B/S模式系统的不同组件分成三"层":
客户端层 — Web 浏览器在其上显示 Web 页面的本地计算机.Web 页面可以显示并处理来自远程数据源的数据,或者(在不基于 Web 的应用程序中)是单独编译的前端应用程序.
中间层 — 封装组织业务规则的组件的 Microsoft Windows NT Server 主机.中间层组件可以是在 Internet Information Server(IIS) 上执行的 Active Server Pages 脚本,或者是(在不基于 Web 的应用程序中)编译的可执行文件.
数据源层 — 宿主数据库管理系统 (DBMS) 计算机.如 Microsoft SQL Server 数据库.(注意:在C/S两层的应用系统中,中间层与数据源层是组合在一起的.)
需要指出的是,这些层没有必要对应于网络上的物理地点.例如,所有三层可能只存在于两台计算机上,一台计算机可能是 Microsoft Windows 95 计算机,该计算机将 Microsoft Internet Explorer 4.0 作为它的浏览器来运行,第二台计算机可能是运行 Internet Information Server 和 Microsoft SQL Server 的 Windows NT Server 计算机.
总之,B/S模式是把所有的开发与计算工作转移到了服务器端,客户端是支持解析HTML的浏览器.这样,不但系统升级维护容易,且应用系统在网络上分配进程和数据时有更大的灵活性,使系统获得更好的性能.但基于B/S的开发模式也存在安全上的隐患,这就要求我们采用有效的方法和措施消除安全隐患.
2.B/S模式存在的安全问题
B/S模式虽然以其简单灵活实用的特性迅速普及,但其本身也存在一些缺陷漏洞.我们通过对B/S模式进行系统分析发现,三层体系结构下的B/S模式,在其中两层存在安全隐患问题,这两层分别是中间层和数据源层.
在Windows NT环境下,中间层是由IIS提供的.IIS可以提供基于WWW的服务,同时可以执行的 Active Server Pages 脚本满足用户动态内容的交互.由于这一层是处于服务器端的,就很可能造成安全漏洞问题.目前IIS出现过以下典型的安全漏洞.
存在一种被称为"非法HTR请求"的缺陷.此缺陷在特定情况下会导致任意代码都可以在服务器端运行.IIS支持多种需要服务器端处理的文件类型,譬如:ASP,ASA, IDC,HTR,当一个WEB用户从客户端请求此类文件时,相应的DLL文件将自动对其进行处理.然而在ISM.DLL这个负责处理HTR文件的文件中被发现存在严重的安全漏洞.
通过构造特殊字符,可以查看ASP源代码.iis2, iis3, iis4 的一个广为人知的漏洞就是 ::$DATA,通过它使用 ie 的 view source 或 netscape 直接访问该 asp 文件就能轻而易举地看到 asp 代码.
数据源层一般由MS SQL Server数据库或Oracle数据库来负责数据的存储工作.在这一层也同样存在很多的漏洞.比较常见的是SQL Server的1433端口远程连接安全漏洞.黑客一旦知道了数据库用户的口令或者系统用户的口令,就可以通过远程连接来存取远程的数据库数据.
鉴于这两层上的安全问题都属于系统上的漏洞问题,一般的方法都是打补丁,但这不是一个明智的好办法.除了打安全补丁,进行安全配置之外,我们还应该制定有效的安全策略和安全措施并加以实施.由于最重要的资源应该处于数据源层,所以我们应该重点保护好数据源层的数据,下面我们提出了基于ISAPI过滤器实现数据库服务器安全的策略和措施,经实际检验可以有效的保护好数据源层的数据.
3.ISAPI过滤器安全技术提出与实现
本文提出的策略是:使用两台服务器来实现隐藏后台服务器(数据层上的服务器);通过公开网站服务器来访问数据层上的服务器,在数据层上的服务器上限制只能让网站服务器来访问. 而在网站服务器上使用ISAPI过滤器实现透明数据转发,将用户在公开的网站服务器上的请求转发到数据层上的服务器上而不是进行简单的重定向,这样可以保证难以跟踪到数据层上的服务器.对用户来说,用户访问的是公开的网站服务器,而实际上公开的网站服务器是一个虚拟的网站,实际上根本不存在任何页面内容. 而后台服务器才是真正的网站服务者.这后台服务器上面配置中间层和数据源层,并限制访问IP,起到了与外界隔离的作用,在一定程度上保护了数据库服务器, 增强了安全性,同时也进行了负载均衡.
ISAPI(Internet Server Application Programming Interface)作为一种可用来替代CGI的方法,是由微软和Process软件公司联合提出的Web服务器上的API标准.ISAPI程序以DLL 形式被Web服务器加载到自己的进程空间中,因此和服务器共用同一个地址空间,且在没有客户请求时可以将其从内存中卸载;ISAPI主要分为ISA和 ISAPI Filter两部分.ISA方法相对而言要传统一些,利用一些特殊的链接,指向服务器的作业,供程序开发人员设计一些扩展功能;而ISAPI过滤器则倾向于构造服务器直接调用的模块,提供一种无缝链接部件用于监测直接来自于服务器的HTTP请求.通过ISAPI过滤器,进行自己定制的处理,来增强IIS的功能.ISAPI过滤器可以定制以下的处理:接收HTTP协议头预处理,发送HTTP协议头预处理,发送生数据预处理,获得生数据预处理,HTTP会话结束信息.
IIS过滤器的实现过程是:首先捕获客户端用户请求的数据,解析出用户请求的URL,请求方法等所有的消息头和消息体,之后将通过 WinInet将请求二次转发到后台服务器,后台服务器接受来自网站服务器转发的请求,处理后将结果返回给网站服务器.网站服务器得到后台服务器处理的结果将结果以重定向的形式原样返回给客户端.
ISAPI的使用需要通过编码的方式进行,下面给出关键性代码,并加以解释.代码采用VC++ 6.0编写,用RedirFilter.dll文件来实现IIS过滤器.在RedirFilter过滤器中我们共用到IIS三个通知事件: OnReadRawData,OnPrepareHeader和OnLog.通过OnReadRawData事件将请求参数截获,将截获的请求参数打包原样转发给后台服务器,然后把后台服务器返回的数据写入临时文件,通知OnPrepareHeader事件重定向到临时文件.为了测试起见,我们只考虑在一个目录下的POST方法的请求转发.如需要全部的目录和更多的请求方法只要稍微改动即可.
类实现:
class CRedirFilter : public CHttpFilter
{
public:
virtual BOOL GetFilterVersion(PHTTP_FILTER_VERSION pVer);
virtual DWORD OnPreprocHeaders(CHttpFilterContext* pCtxt, PHTTP_FILTER_PREPROC_HEADERS pHeaderInfo);
virtual DWORD OnReadRawData(CHttpFilterContext* pCtxt, PHTTP_FILTER_RAW_DATA pRawData);
private:
CString ReSendPost(CString strAddress,CString FormData); //转发POST表单数据
CString pstrPostData; //用户请求数据
protected:
CString GetPostData(LPTSTR lpStrData); //得到用户请求数据
};
在原始的请求数据过滤OnReadRawData:
DWORD CRedirFilter::OnReadRawData(CHttpFilterContext* pCtxt,
PHTTP_FILTER_RAW_DATA pRawData)
{
LPTSTR pstrIn;
pstrIn=(LPTSTR)pRawData->pvInData;
pCtxt->m_pFC->pFilterContext = NULL;
//如果是POSt方法并且虚拟目录是User进行过滤操作
if (pstrIn[0]=='P'&&pstrIn[1]=='O'&&pstrIn[2]=='S'&&pstrIn[3]=='T'&&
pstrIn[5]=='/'&&(pstrIn[6]=='U'||pstrIn[6]=='u')&&(pstrIn[7]=='S'||pstrIn[7]=='s')&&
(pstrIn[8]=='E'||pstrIn[8]=='e')&&(pstrIn[9]=='R'||pstrIn[9]=='r')&&pstrIn[10]=='/')
{//是POST方法
pstrPostData=GetPostData(pstrIn); //找到POST提交的数据
}
else
{
pCtxt->m_pFC->pFilterContext=(VOID *)1; //不是Post方法
}
return SF_STATUS_REQ_NEXT_NOTIFICATION;
}
得到表单POST数据GetPostData:
CString CRedirFilter::GetPostData(LPTSTR lpStrData) //分析并得到Post数据
{
int ndx=0;
CString strPostData;
strPostData=(CString)lpStrData;
ndx=strPostData.ReverseFind('\n');
strPostData=strPostData.Mid(ndx+1);
return strPostData;
}
进行重定向和转发处理.
转发处理函数ReSendPost:
CString CRedirFilter::ReSendPost(CString strAddress,CString FormData)
{
//重定向的文件名
CString RedirFile="error.asp";
//请求的地址
CString m_strAddress="http://192.168.0.168/back"+strAddress;
CInternetSession session(_T("RedirFilter"));
CHttpConnection* pServer = NULL;
CHttpFile* pFile = NULL;
try
{
CString strServer;
CString strObject;
INTERNET_PORT nPort;
DWORD dwServiceType;
CString strHeaders =_T("Content-Type: application/x-www-form-urlencoded");
CString strFormData=FormData;
AfxParseURL(m_strAddress,dwServiceType,strServer,strObject,nPort);
pServer = session.GetHttpConnection(strServer,nPort);
//增加头来支持POST表单
pFile = pServer->OpenRequest(0,strObject,NULL,1,NULL,NULL,
INTERNET_FLAG_EXISTING_CONNECT | INTERNET_FLAG_NO_AUTO_REDIRECT );
pFile->AddRequestHeaders(_T("USER-AGENT:RedirFilter"));
pFile->SendRequest(strHeaders,(LPVOID)(LPCTSTR)strFormData, strFormData.GetLength());
DWORD dwRet;
pFile->QueryInfoStatusCode(dwRet);
CString strNewLocation;
pFile->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF, strNewLocation);
// 是否需要重新定向
if (dwRet == HTTP_STATUS_MOVED ||
dwRet == HTTP_STATUS_REDIRECT ||
dwRet == HTTP_STATUS_REDIRECT_METHOD)
{
CString strNewLocation;
pFile->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF, strNewLocation);
int nPlace = strNewLocation.Find(_T("Location: "));
strNewLocation = strNewLocation.Mid(nPlace + 10);
nPlace = strNewLocation.Find('\n');
if (nPlace > 0)
strNewLocation = strNewLocation.Left(nPlace);
//关闭重定向站点
pFile->Close();
delete pFile;
pServer->Close();
delete pServer;
// 检查原来的位置
if (!AfxParseURL(strNewLocation, dwServiceType, strServer, strObject, nPort))
{
MessageBox(_T("重定向的URL无法被解析"),_T("错误"));
}
if (dwServiceType != INTERNET_SERVICE_HTTP)
{
MessageBox(_T("重定向的URL不是一个HTTP资源"),_T("错误"));
}
// 重试新位置
pServer = session.GetHttpConnection(strServer, nPort);
//增加头来支持POST表单
pFile = pServer->OpenRequest(0,strObject,NULL,1,NULL,NULL,
INTERNET_FLAG_EXISTING_CONNECT | INTERNET_FLAG_NO_AUTO_REDIRECT );
pFile->AddRequestHeaders(_T("USER-AGENT:RedirFilter"));
pFile->SendRequest(strHeaders,(LPVOID)(LPCTSTR)strFormData, strFormData.GetLength());
pFile->QueryInfoStatusCode(dwRet);
if (dwRet != HTTP_STATUS_OK)
{
MessageBox(_T("HTTP状态错误"),_T("错误"));
}
}
CString line;
CFile file;
//生成物理路径------
CString RedirFilePath="E:\\JMwork\\www\\stat\\Redir\\";
srand( (unsigned)time( NULL ) );
RedirFile.Format("%d.asp",rand());
RedirFilePath=RedirFilePath+RedirFile;
file.Open(RedirFilePath,CFile::modeCreate|CFile::modeWrite);
while(pFile->ReadString(line))
{
file.Write(line+"\r\n",strlen(line+"\r\n"));
}
pFile->Close();
pServer->Close();
file.Close();
}
catch (CInternetException* pEx) //异常处理
{
pEx->Delete();
}
if (pFile != NULL)
delete pFile;
if (pServer != NULL)
delete pServer;
session.Close();
return RedirFile;
}
进行重定向OnPreprocHeaders:
DWORD CRedirFilter::OnPreprocHeaders(CHttpFilterContext* pCtxt,
PHTTP_FILTER_PREPROC_HEADERS pHeaderInfo)
{
//这里只处理POST方法
char buffer[1024]; //得到头URL
DWORD bufferSize=sizeof(buffer);
if (pCtxt->m_pFC->pFilterContext==NULL)
{
pHeaderInfo->GetHeader(pCtxt->m_pFC,"url",buffer,&bufferSize);
char resultBuffer[1024]="/Redir/";
//生成重定向文件名
CString RedirFileName;
//向目的机器发送POST请求数据
RedirFileName=ReSendPost((CString)buffer,pstrPostData);
strcat(resultBuffer,RedirFileName);
pHeaderInfo->SetHeader(pCtxt->m_pFC,"url",resultBuffer); //重定向到从远程的来的响应数据
WritePrivateProfileString("Section3", "RedirFile",RedirFileName,"E:\\JMwork\\www\\stat\\test.txt");
}
return SF_STATUS_REQ_NEXT_NOTIFICATION;
}
实现计算机网络安全是一个需要不断加深认识的过程.无论网络安全技术发展的什么程度,数据总是最宝贵的资源与财富.针对目前广泛应用的B/S开发模式的三层体系结构技术,本文提出的方法使三层中最重要的数据层的安全性得到了更安全的保障,这对于目前所有基于B/S模式开发的系统安全性有一定的实际意义.
参考文献:
[1].叶忠杰主编,计算机网络安全技术,北京:科学出版社, 2003;
[2].田东风,Windows CE 应用程序设计.北京:机械工业出版社,2003.10
作者简介:田东风,男(1958-),汉族,中国地质大学(北京) 信息工程学院教授;秦江波,男(1978-),汉族,中国地质大学(北京) 信息工程学院研究生.电话:010-82323183,13693314162,E-mail: tdf3503@vip.sina.com, dftian@cugb.edu.cnBrief Introduction of the Author: Tian Dongfeng(1958-),male,a professor of China University of Geosciences(Beijing).Qin Jiangbo(1978-),male,the graduate student of China University of Geosciences(Beijing).Tel:010-82323183,13693314162,E-mail: tdf3503@vip.sina.com, dftian@cugb.edu.cn
通讯地址:北京海淀区成府路20号院眷39楼5门551,田东风,邮编:100083本项目得到中国地质大学(北京)校内科研基金的资助
