使用Windows NT 的安全性

在上一节,我们已经阐述了推荐使用Windows NT做Web服务器的一些理由,其最重要的一点是,能够使用Windows NT的安全性API。然而,懂得为什么要存在Windows NT的安全性API只是一个起步,现在,我们将要关注的是,在现实中你是如何实施这些安全特性的。在这一章中,我们实际上讲述了五种不同类型或等级的安全特性,下面将对每种类型进行定义:
    注 使用Windows NT作为Internet服务器的一个主要原因是,你能使用它的安全性API。
    内置安全性 作为一个操作系统,Windows NT有一定级别的安全性。在Windows NT中,每个对象都对应着一定的安全性,我们将关注这些安全性的实施方法。使用对象级别的安全性意味着:如果没有正确的授权,几乎没人能有机会访问操作系统的任何部分或任何数据,当然,也不是一点机会也没有——我们总是假设你的安全性不是最完美的。
    私有通讯技术(PCT) PCT是微软和IETF一起创建的一种特殊的Internet安全性技术。在近期版本中,PCT将允许客户和服务器建立私有的通讯,以保证通讯不会被人窃听到,这种安全性的实现依赖于数字签名和加密方法。
    Windows NT通过HTTP进行身份认证 许多人都错误地认为,使用这些安全性来工作将是非常繁琐和复杂的,但有时候,看似烦杂的东西却可以通过一个简单的方案做到尽善尽美。我们从Internet的角度来看,在Windows NT中进行身份认证有两种形式,一种形式是简单地询问用户的用户名和口令,并和服务器内的访问列表进行对照,这种形式又可通过两种方法实现,一种是在对Windows NT进行标准登录时进行的询问和回答;另一种则基于当前会话的设置,它也要求客户提供必要的用户名和口令,或者说,让用户使用客户提供的信息登录到机器上。另一种形式相对简单些,它依赖于一种叫安全套接层(SSL)的技术,SSL又是依靠加密和数字认证来工作的。如果你过于担心安全性问题,你甚至可以将这两种形式结合起来使用——它们彼此间并没有什么相互的制约关系。
    数字签名 它是指发送人对他发送的文档或可执行文件进行签名,通过检测签名你可以判断其真伪。数字签名用一系列的私有或公开密钥来实现这个安全等级。
    加密API 有些类型的安全性依靠多个保护层来工作,也就是说,如果一个黑客闯过了你的第一个安全保护层,则另一个保护层将阻止他进一步的访问。这就是加密API(也叫CryptoAPI)所有要做的,它是一个附加的保护层,附加在所有已经存在的保护层上,它能保护你免受黑客更深层次的攻击。
    在本章的下几节中,我们将阅读到几种新的技术,你将发现它既嵌入在Windows NT中,也嵌入在新型的浏览器中。作为Internet服务器中的一种,Windows NT支持如微软的Internet信息服务或对等网信息服务(在WindowsNT4.0和Windows95/98的OSR2版本中免费提供)。我们将有趣地发现:和新版本的Netscape转接器一样,微软的IE3.x/4.x中也提供了内置SSL的支持;你也将发现,PCT至少也支持IE。我们也将关注数字认证码(即数字签名)技术,现在的许多 软件厂家已经采用了它,它允许 编程人员对其作品进行数字化签名,当你下载这些经过数字化签名的程序时,程序代码在签名后的任何损坏都将显示出来。它带来的好处是,你不会轻易下载到一个病毒感染过的程序。
    Web链接 通过访问http://www.microsoft.com/iis/guide/pws.asp?A=2&B=5,你可以为你的Windows 95下载某个版本的个人Web服务器(PWS,Person WebServer)(Windows 98的安装包中自带了PWS),这个版本的PWS也与Windows 95的OSR2版本以及微软的Windows NT可选包随同销售(Windows 95/98也有其可选包)。虽然PWS不会去满足制造Web站点的需求,但它能够让开发者很好地检测Internet 应用程序。要知道,因为Windows 95/98没有提供与Windows NT一样的安全性,所以,如果使用Windows95/98的PWS版本,你将检测不到应用程序的任何安全特性。(幸运的是,在与Windows NT 4.0 Workstation一同销售的PWS中,将允许你完全检测这些安全特性)。
    加密也是保护你的数据的另一个可行方法,让我们参看一下下述微软已经开发的加密函数CryptoAPI,这部分的技术至少是在Internet Explorer内的一种主要形式。然而,不管你现在能够使用它做什么工作,CryptoAPI确实在程序内工作着,另外,对CryptoAPI的开发环境进行扩展,只在美国和加拿大是有效的。
     内置的安全特性
    在安全性方面,Windows NT几乎是当前市场上最超前的操作系统。如果你对微软的这种地位还有什么怀疑的话,那么请去看看Windows NT获得的各种证书吧。你可以通过使用它的安全性能来获取很多便利,例如,你可以在一个OCX中使用这些高级功能,或通过Internet获得一些特殊功能的访问。在做这些事时,你必须受到一些限制,以免破坏你的网络安全。使用一些来自Internet的特性是不切实际的,因为它们并不重要。
    幸运的是,ActiveX控件却不必对Internet进行限制,没有什么条令规定,你不能在你的应用程序中创建一个有特殊用途的控件。在 数据库或其它应用程序中的ActiveX控件,能被网络管理员(或其他有相同权利的人)正常地使用,这使应用程序的工作变得更加简单和可靠。事实上,如果你需要的话,ActiveX控件也可以设计为多种个性化用途,你甚至可以给它增加检测控件当前位置的能力,或增加一个指定的位置作为特性页面配置的一部分,一些人可以选择其用于Internet的特性子集,而另外一些人则可以选择其用于局域网(LAN)的特性子集,还有一些特性集则是用于本地的。
    也许你们中许多人会问:需要什么类型的管理员来管理安全性,且不需使用网络操作系统(NOS)附加的工具呢?Windows NT确实提供了大量的管理工具,而且这些工具都非常容易使用,所以一些 编程者认为,再附加一些工具是不值得的。这个问题不好回答,但是,当大部分人在考虑Window NT下的安全性时,几乎总是这么想:如果管理应用程序的人不是网络管理员,而是练习使用网络操作系统的某个人,这又该如何处理呢?我们说这个人可能是一个工作组管理员或其他独立的个体,他没有必要看到整个网络图,而只需要足够的信息来维护他所负责的应用程序,你将发现这种情况是经常发生的,尤其是一个拥有许多小工作组的大公司,更是属于此类情况。尽管网络管理员不懂得正确管理应用程序,但也不愿让工作组管理员自由地访问整个网络。
    注 ActiveX在局域网环境的一个最好的应用是,它提供一定的子网安全管理能力。
    不管你是在为Internet、还是为局域网(LAN)或是为广域网(WAN)创建控件,你都将发现,懂得网络底层的安全构造是非常重要的。Windows 95/98没有提供像Windows NT一样多的安全特性,所以,在Windows 95/98 中,你有时会发现自己没有增加上应用程序的安全性。然而,尽管Windows 95/98没有为应用程序提供某个安全特性,但有时它们和Windows NT使用同样的安装程序,所以应用程序安全模块将同时为这两种操作系统工作(在其它情形下,你可以干脆为Windows NT使用单独的安全模块,以增强其安全性能,请看下面的具体注释)。
    注释 与Windows 95/98相比,Windows NT确实提供了更多的安全API函数,因为它的安全性更加强壮。现实中,因为Windows 95/98缺少对Windows NT安全函数的支持,所以在使用它时,你会经常遇到一些障碍。例如,在Windows 95/98下,你不能调用GetUserObjectSecurity函数;而在下一节中,我们将会看到的操作访问令牌的函数,也大多不能在Windows 95/98中使用。弄清一个函数是否被支持的最好方法就是直接检测它,如果你在调用它时收到一个“ERROR_CALL_NOT_IMPLEMENTED(value 120)”的信息,则你便知道它只能在Windows NT中使用了。
    在Windows NT 和Windows 95/98中,“对象”(Object)这一名词的使用更加宽松。我们说,在事物的背后确实潜伏着许多对象,但你可能发现,“对象”这个名词的定义已经不能完全符合 C++的习俗了。在下几节中,我们把对象大体看成是:在运行一个指定的安全任务时所需的代码和数据的总和。或者说,每个安全对象自身包含了一个为充当某个角色而设计的单元。(在WindowsNT和Windows 95/98的许多地方,微软主要选用 C++中“对象”的定义,因为作为MFC的一部分,它提供了所需的机能。然而,在阅读本章或微软的其它文档时,你不应该把对象看成是一个严格的 C++对象,而应该多加点COM的意识)。
    知道了所有东西都是对象后,我们将更容易理解安全性——这至少是一个起点,当然,对象本身也就是一个起点。对象是被用户所访问的,所以在Windows中,安全性是指将对象所受的保护与用户的访问权进行比较。如果用户拥有足够的访问权(访问权等于或超过对象所受的保护),则用户能够使用这个对象。在Windows 的文档中将对象所受保护的级别称作安全描述符(securitydescriptor),这是一种结构,它能告诉安全系统:用户需要什么样的权力才能访问这个对象;而用户则有一个访问令牌( Access Token),它是另一种结构,它能告诉安全系统:在一个给定的位置,用户有什么样的访问权。用户将访问令牌交给Windows NT系统,并以此获得对对象的访问。(如果把访问对象看作是一辆公共汽车,把Windows NT看作是驾驶员,则“车票”是访问令牌的一个很好的比喻,乘客只有出示车票才能搭车)。图14.1描述了这两种结构。

          图14.1 访问令牌定义了用户的权利,而安全描述符则定义一个进程的保护级别
    以上,你只是稍微了解了一点Windows 95/98或Windows NT的安全性,简单地知道了它有安全对象和用户访问令牌,这与帮助你理解和使用Windows安全API函数还相差很远。在下面几节中,我们将细致地学习访问令牌是如何工作的;我们也将关注一下安全描述符。如果你只是对Internet感兴趣的话,在你使用ActiveX实施安全性时,可以完全不必懂得这些知识。然而,学会它,将会帮助你设计出更加符合心意的ActiveX控件。
     理解访问令牌
    在Windows中,你将发现有两种方法可以查看用户的权限,而且两者都是通过这样或那样的形式与对象关联的。用户的访问令牌有一个安全标识符(SID),它在整个网络中识别用户棗它就像是一个帐户号。安全识别符表示了用户归属的组和拥有的优先权。每个组也有一个安全识别符,所以,用户的安全识别符也包含了他所属各个组的SID,并将引用这些SID。在Windows NT下,要想改变用户访问令牌的内容,你应该正规地使用用户管理器。
    注 Windows NT支持两种类型的安全标识符(SID):用户SID和组SID
    那么访问令牌的优先权是指什么呢?首先是用户拥有特权数——不是用户所归属的组的数目,而是指访问令牌内指定的特权入口数,这部分还包括特权入口的阵列。每个特权入口还包括一个局部唯一的标识符(LUID)和一个属性掩码(Atrribute mask)。LUID实质上是一个指向对象的指针,而属性掩码能表述用户对对象的权力。组的安全识别符也与此雷同,它们包括一个特权计数和特权入口的阵列。
    技巧 现在,你可以去看看Visual C++ 软件提供的Windows API帮助,找一找与安全标识符或访问令牌相关的API函数。例如,与SID相关的函数包括CopySID和AllocateAndInitializeSID;你会发现OpenProcessToken和GetTokenInformation函数也是非常重要的,它能在任何语言下保证应用程序安全正常工作。
     观察访问权限传递
    你还该知道的一件事是:有些类型的对象,如果它的权限没有被其它SID终止,则可能会继承到它的最低节点。例如,如果你让一个用户对硬盘的“/Temp”目录有读写的权限,则用户对该目录的子目录“/Temp/Stuff”也有相同的权限,除非你分配给这个子目录别的权限。对于容器对象也是如此,如果分配一个用户对容器对象的权限,如一个Word文档,则它允许用户查看这个容器下的所有内容,很多情况下甚至还有别的文件。由此看来,因为你可能会不经意地分配给用户过多的权限,所以使用安全审察来跟踪用户对服务器中各类对象的确切权限,是非常重要的。
     使用访问令牌
    因为访问令牌函数是你实施安全性前必须了解的第一个难点,下边,就让我们简要地谈论一下Windows 提供的访问令牌函数。对用户的帐户做任何工作,哪怕是找出谁在访问指定的工作站,都必须了解访问令牌。正如前面所讲的,访问令牌是安全等式用户方的中心部分。在对一个用户的帐户进行访问时,你几乎总要用到的一个函数是OpenProcessToken,请注意这个函数的名字,它能够处理的对象可以是任何类型的进程、线程或用户等等,该函数的作用是获取附加在这个进程上的令牌句柄。例如,如果你查询一个用户的帐户,你必须有TOKEN_QUERY优先权,(你的访问令牌中必须包括系统委托的一些必要的权限,这就是为什么管理员能访问某个令牌,而其它用户却不能访问的原因)。而对用户的帐户要做任何改动时,你必须拥有TOKEN_ADJUST_PRIVILEGES优先权。还有许多其它的访问权限,我们在这里不再一一表述了。
    一旦你拥有了一个访问令牌的句柄,你需要决定将对它做些什么。如果你想改变用户做某事的优先权,则你将需要这个优先权的局部唯一标识符(LUID),所有这些优先权在WINNT.H文件中都是以“SE_”开头的。例如,SE_SYSTEM_PROFILE_NAME 优先权允许你收集这个系统的配置信息。有些SE的值与用户无关(例如,SE_LOCK_MEMORY_NAME特权允许进程锁定内存中的物理页面)。通过调用LookupPrivilegeValue函数,你可以获取对应局部系统上的优先权的LUID。一般而言,你将使用AdjustTokenPrivileges函数来实现你所需要的修改。
    注 在WINNT.H文件中,查看一下Windows NT定义的优先权列表,这些优先权是你能修改的。
    查询用户帐户(或访问令牌的其它信息)是直接了当的。你可以调用GetTokenInformation函数来获取你需要的信息,这个函数需要一个令牌类参数,它把你所需信息的类型告诉Windows系统。例如,如果你想知道一个指定用户的信息,你应该使用TokenUser类参数,你也将需要提供相应的结构,以让Windows保存你请求的信息,这一点与基于令牌类的请求不一样。
     了解安全描述符
    现在让我们来关注一下安全描述符。在图14.1中,每个安全描述符包括五个主要的部分。第一部分是一个标志列表,这些标志指明了描述符的版本号、格式和访问控制列表(ACL)的状态。
    接下来的两部分包含了多个安全标识符(SID),所有者标识符表述了对象的拥有者,这不必是一个单独的用户;Windows也允许你在这里使用组的SID。有一点是受限制的,即组的SID必须出现在想要改变入口的人的访问令牌中。组标识符允许一组人拥有某个对象。这两种标识符中,只有所有者标识符在Windows下是重要的。组的标识符作为一个部分用于Macintosh和POSIX的安全环境。
    最后两部分包含了各种访问控制列表(ACL)。安全访问控制列表(SACL)控制了Windows的审计功能,用户或组每次访问一个对象时,这个审计功能便启动了,Windows在审计记录中产生一个登记项;全权访问控制列表(DACL)控制了谁能真正使用某个对象。你可以将一个组或用户分配给一个指定的对象。
    注释 实际上,有两种型号的安全描述符:绝对安全描述符和自身安全关联描述符。绝对安全描述符在它的结构中包含了每个ACL的真正拷贝,这种类型的安全描述符用于需要指定句柄的对象;而自身关联安全描述符只包括了指向SACL和DACL的指针,这种描述符在改变组的权限时,节省了内存并减少了所需时间,当某个特定组内,所有对象需要同一级别的安全性时,你应该使用它来处理,例如,通过这种方式,你能将单个进程内的所有线程赋予安全性。在你要保存安全描述符或将它传送给别的进程前,Windows 要求你把一个自身安全关联描述符转换成绝对安全描述符。通过API函数获取的描述符都是自身关联类型的,你必须在保存它之前将其转换。通过对MakeAbsoluteSD和MakeSelfRelativeSD两个API函数的调用,你可以在这两种类型的描述符之间转换。
    一个ACL由两种类型的表项组成:第一个表项是个结构头,它列出了ACL包含的访问控制表项(ACES)个数,Windows使用这个数字检测是否到达了ACE列表的末端(这里没有任何其它记录或手段能够检测每个ACE的准确大小);第二个表项是个ACE数组。
    警告 不要手工直接修改ACL或SID的内容,因为在以后的Windows版本中,微软可能改变它们的结构。Windows API为改变这些结构的内容提供了丰富的功能。如果要对某种结构进行任何的改变,请通过调用API函数来实现,以免不必要的冲突。
    那么什么是访问控制项呢(ACE)?ACE定义了单个用户或用户组在一个对象上的权限。每个ACE由三部分组成:首先是一个结构头,它定义了这个ACE的类型、大小和一些标志;接着是一个访问标志,它定义了一个用户或组对这个对象的权限;最后是用户或组的安全访问标识符(SID)的项。
    一共有四类ACE头(其中有三类已用于当前的Windows版本中)。其中,access-allowed类出现在DACL中,它认可用户的权限,你可以使用它增加用户对一个对象的权限。例如,虽然你想通过禁止用户修改系统时间,以使网络上所有机器的时间同步,但白天还是可以修改时间,而用户需要有这个权限,你可以通过使用一个access-allowed类的ACE来给予用户改变时间的权限;另一类是access-denied类,它废除用户对某一对象的权限,在一个指定的系统事件中,你能够使用它来拒绝对某一对象的访问,例如,当你对某一远程终端进行某些更新时,你可以取消其他人对它的访问权限;还有一类是system-audit类ACE,它与SACL一起作用,它定义了指定的用户对哪些事件进行审查。当前还未使用的是系统警报ACE,它允许SACL或DACL设置一个指定事件发生时的警报。
    注 在当前的Windows NT版本中,使用的三类访问控制项(ACE)是access-allowed、access-denied和system audit。
    技巧 现在,你可以翻阅一下Windows API的帮助文件,看看Windows提供了什么类型的访问权限。为了获得这些信息,你应该更关注各种类结构,尤其是ACL和ACE的结构。看看ACE标志,它决定了在一个容器下的对象是如何作用的。例如,查一下CONTAINER_INHERIT_ACE常数,它允许子目录继承父目录的安全特性。
     使用安全描述符
    到现在,你只是了解了什么是安全描述符,以及它包含的各类结构是如何相互作用的,你还应该知道怎样开始一个实际的访问进程,并使用安全描述符来写一个程序。你必须首先了解的是:安全描述符不同于访问令牌,它没有普及开,所以你不能使用一个标准的函数集来访问它们。实际上,一共有五类安全描述符,每类安全描述符都使用不同的函数集来访问对象。(你必须拥有SE_SECURITY_NAME特权,才能使用这些函数)。
    到现在,你只是了解了什么是安全描述符,以及它包含的各类结构是如何相互作用的,你还应该知道怎样开始一个实际的访问进程,并使用安全描述符来写一个程序。你必须首先了解的是:安全描述符不同于访问令牌,它没有普及开,所以你不能使用一个标准的函数集来访问它们。实际上,一共有五类安全描述符,每类安全描述符都使用不同的函数集来访问对象。(你必须拥有SE_SECURITY_NAME特权,才能使用这些函数)。文件、目录、管道和邮件槽。通过使用GetFileSecurity和SetFileSecurity函数,可以访问这种类型的对象:
    注释 只有Windows NT下的NTFS文件系统提供了安全特性。Windows 95/98下的VFAT文件系统只提供了很少的安全特性。你不能从HPFS或FAT文件系统中分配或获取安全描述符。FAT文件系统没有提供任何扩展属性的空间,而这些空间是增加安全性所必须的;HPFS文件系统虽然提供了扩展属性,但它们没有任何安全特性。在上述的这些文件系统中,NTFS是最安全的。然而,不要错误地认为会有完全安全的文件系统。在Internet上,有一些应用程序能够读取NTFS分区的内容,即便用户没有正确地登录到Window NT中。
    要访问进程、线程、访问令牌和同步对象,你必须使用GetKernelObjectSecurity和SetKernelObjectSecurity函数。所有的这些对象都是内核对象,为了更好地保护这些对象,它们也都有自己的安全描述符。
    要访问Windows 站点、桌面、窗口和菜单,你可以使用GetUserObjectSecurity和SetUserObjectSecurity函数。一个Windows 站点包括键盘、鼠标和屏幕,即你用来访问系统的所有 硬件。桌面包括窗口和菜单。这四个对象按此次序依次从前一个对象继承权限,也就是说,桌面将继承站点的权限。
    要访问系统注册键,你必须使用RegGetKeySecurity和RegSetKeySecurity函数。注意,Windows提供的所有注册类的函数都是以Reg开头的。 可执行服务对象,QueryServiceObjectSecurity和SetServiceObjectSecurity函数用于可执行的服务对象。奇怪的是,在Windows 的API帮助文件中,这两个函数都没有出现在其它安全函数的引用中。你在寻找这些函数之前必须已知道有这么两个函数。可执行服务是Windows提供的后台任务,如UPS的监视功能。通过双击控制面板中的服务程序,你将找到你的系统所支持的服务。
    一旦你获得对某个对象的访问权限,你将发现,通过使用一般的API函数集,你便能够处理很多任务。例如,GetSecurityDescriptorDACL能够从任何类的描述符中获取一份DACL的拷贝。换句话说,这些对象的描述符跟随一个同样的格式棗即便大部分成分的描述符长度不同。导制这些长度不同的原因之一是,它们各自包含了不同数量的访问控制项(ACE),另外,安全标识符(SID)的长度也不同。
    要查询或修改一个安全描述符的下一步工作是分离这些成分。例如,通过使用GETACE API函数,你能够查看在一个DACL或SACL中单独的ACE;通过使用与SID相关的函数,你也可以使用所有者标识符或组标识符(我们已经在本章的访问令牌部分阐述了这些函数)。可以满意地说,只要按指定的步骤做,你便能够使用一般的函数集来操作安全描述符。大致上说,对安全描述符的任何访问,一般都要经过下述三个步骤:
    1. 获取描述符
    2. 删除指定的成分
    3. 修改指定成分的内容
    要修改安全描述符,你应该按相反方向执行这些步骤。换而言之,你先使用类似AddACE函数来增加一个新的ACE至一个ACL;然后,使用SetSecurityDescriptorSACL来改变一个描述符中的SACL;最后,使用类似SetFileSecurity的函数(假设你想要修改一个文件对象)来保存安全描述符。
     Windows中的ACEing安全性
    当你开始考虑Windows在DACL中计算ACE的方法时,你也许会发现一些潜在的存在问题的地方:虽然Windows的系统应用程序会自动关注这些问题,但你必须在自己应用程序中编制好了,才能运算出同样的结果。(SACL也有同样的问题,但它只是影响审查,从系统安全的角度看,它不是那么要求苛刻的)。
    Windows 是按照ACES在ACL中出现的次序来计算访问控制结果的。首先,它可能不是一个很好算法,而且,在某些情况下它还会产生一些问题。例如,如果你想废除所有用户对某一区域的权限,但是在他或她的访问控制列表中包含了一个能够访问这一区域的组(即他或她是这一组的成员),这种情况的结果会如何呢?如果你将access-allowed 访问项放在列表的第一位,则这个用户将能够访问这一区域棗一旦Windows发现第一个满足用户所需权限的ACE时(或者一个禁止所需的权限的ACE时),它将停止继续搜寻。许可的权限是累加的,如果一个ACE允许对一个文件进行读的权限,而另一个允许写的权限,则当用户询问读和写的权限时,Windows 将综合这两个ACE并允许用户进行读写。下面的注中表示你应该将所有access-denied访问控制项放置列表前端,以防止安全上的潜在漏洞。
    注 ACE在ACL中排列的先后次序是非常重要的,因为Windows 按次序对它们求值,并一旦发现第一个ACE允许或拒绝对某一对象的访问时,便停止继续搜索。
    你也必须注意组的安全标识符(SID)的排列次序,因为用户从他(或她)所属的组获取的权限是相累加的。这意味着,如果一个用户属于两个组,其中一个组对某个文件有访问的权限而另一个没有,假如允许访问的组在列表中排列在前,那么用户可以访问这个文件,否则不能。
    显而易见,为了将组排列成最好的次序,你将花费很多的时间。当用户拥有的组的权限和独立的权限数增加时,则可能出现无意识的安全漏洞。所以,仔细地创建一个组并严格限制用户单独的权限是非常重要的。
     其它安全考虑
    当你关注在Windows 95/98或Windows NT下的安全性时,还有两方面需要考虑:数据保护和服务器保护。前者对付客户的这种能力:当客户通过服务器(这里不是指文件服务器,而是某些类型的DDE或其它应用服务。)访问数据时,访问了那些没有获准访问的数据。我们用这种方式思考一下:如果客户对某一指定类型的数据没有访问权限,但是通过调用他有权访问的DDE服务器访问了这些数据,这将会有什么后果呢?服务器又应该如何保护它们的数据,而不是被迫成为造成安全破坏的同谋呢?
    Windows 提供了一些API函数允许服务器模仿一个客户。大体上是:为了检测出客户是否对一个数据或进程有过多的权限,这些函数允许一个服务器假扮成客户所受的安全限制。例如,Windows的一个Word用户可能需要访问Excel的一个数据文件,而这个用户可以通过DDE来获得这个文件的访问,在这种情况下,服务器需要检测一下这个用户是否有权访问这个文件,然后才传送所需的数据。当用户使用这种技术时,服务器甚至能找出客户的优先权。服务器唯一关心的是对它所管理的数据、资源和环境的保护。
    这个API函数集支持三种不同类型的通信:DDE、命名管道和RPCS。对每种通信类型,你必须使用不同的API函数。例如,要模仿一个DDE客户,你应该使用DDEImpersonateClient函数。Windows目前在模仿这方面所提供的支持还有一些限制。例如,它现在还不支持TCP/IP连接,所以在这种情况下,你必须依靠别的手段来检测一个用户是否有合适的访问权限。
    另一个安全考虑是如何保护服务器自身。在一个Windows Word用户调用Excel服务时,用什么方法来防止这个用户对Excel服务器本身进行破坏呢?请确信,对文件和其它有名字的结构,服务器自动会附加上一个安全描述符到这些对象上,并进行严格的保护(一个DDE服务器,如Excel,在这种情况下不需要任何安全描述符,因为文件已在文件服务器的控制之下)。然而,大多数DDE或应用服务器的私有对象没有命名,它们需要另外的保护。Windows也提供了一些API函数来帮助服务器保护自身。例如,CreatePrivateObjectSecurity函数允许服务器附加安全描述符到它的任何私有对象上——如线程或其它进程。这些安全描述符能够防止除服务器外任何人访问其私有对象。
     私有通信技术(PCT)
    微软和IETF正携手开发一个名叫PCT的新的底层协议,和安全套接层(SSL)一样,PCT是用来防止黑客窃听服务器和客户间的通信的,它通过加密、身份认证和数字签名技术来实现通信的安全性。由于可以使用SSL,所以客户身份认证可以根据需要进行选择。
    Web链接 如果想了解有关PCT当前的进展情况,请访问http://www.lne.com/ ericm/pct.html,这个文档中包括了PCT的第二个版本的当前草案,另外,通过访问http://www.w3.org/security/,你也可以参考一下W3C的Web站点上有关当前Internet安全技术的详细情况,其中包括PCT和SSL。
    PCT假设你有一个可靠的传输协议,它能取代类似TCP的协议。有些人把TCP/IP看成是一种唯一的协议,但这是错误的,TCP只是这些协议中的传输部分,而IP才是数据传输部分。IP不支持任何形式的数据加密,所以,当你使用TCP/IP时,你的数据对任何想看它的人都是开放的。使用如TCP/PCT或TCP/SSL协议将使你的通信安全化。PCT的第一个版本修正了在SSL中出现的一些问题,现陈述如下:
    简化了的消息和记录结构。如果你没有使用客户身份验证,那么会话的重新连接在每个地址上需要一个唯一的消息;即便使用客户身份验证,重新连接在每个地址上也只需要两个消息。
    扩展的加密算法。PCT提供了比SSL更丰富的算法,这意味着它能支持更广阔的协议特性,而且这些协议特性的交涉是相互独立的。例如,公共特性包括加密类型、服务验证类型、散列函数类型和密钥字交换类型。 改进的消息验证密钥。在PCT中,消息验证密钥和加密密钥是相互独立的,这意味着,即便加密密钥是短的或不存在的,只要消息能使用一个很长的密钥,也能保证传输的安全,导制这一特性的主要原因是:因为美国政府把管理安全传输的密钥限定为最长为40位。
    修补了安全漏洞。PCT在会话中的客户身份验证是基于加密算法的。这防止了某些人通过捕获客户的验证密钥,并切断原客户的会话,而使用窃取的密钥来建立重新连接。客户只有知道了密文和密钥,才能获得服务器的访问。
    附加的提前检验区域。客户和服务器在最初的握手对话过程中,其通信是透明的,这个附加的区域使得客户和服务器可以检测在这种通信中可能出现的任何损害。
    注释 虽然SSL在版本3中也提供了提前检验区域,但黑客也能够通过将协议版本号修改成2来绕过它,因为版本2中没有提供这一功能,而版本3完全兼容版本2,所以客户和服务器都不会注意到这个变化。
    微软当前正在开发PCT的第二个版本,这个版本与第一个版本完全兼容,但提供第一个版本所不具有的几个重要特性。以下是这些特征的简单概述。
    新的数据报记录类型 单独的记录作为“数据报”独立地发送,从本质上看,这意味着协议不会保证数据发送的次序或到达目的地址的次序,这要求客户将接收到的数据进行排序,然后检验它们是否全部到达。这种方法的最大好处是提高了传输速度。
    可重新识别的记录类型 记录的头包含了一些信息,它告诉接收者将接收什么类型的记录。
    连续记录 PCT版本1中允许数据跨越多个记录,即便是记录头没有指明连续的任何形式,版本2的记录头中增加了连续区,它也允许协议信息跨越多个记录。
    数据记录的中间处理 数据记录是封装的,它允许发送者对数据做一些中间处理,比如压缩。
    数据报记录的独立解密 由于发送的数据报记录可能会通过一个不可靠的传输通道,所以这部分特性对安全通信是非常重要的。每个记录分别加密,使得接收者可以立即对数据报解密,而不管接收数据报是否打乱了次序。
    新的密钥管理记录类型 这个记录类型允许发送者在会话中临时改变加密或消息验证密钥。重要的是,这允许了PCT来传送预先加密的数据。 新的关闭连接密钥管理消息 这是一个特定的消息,它告诉其它参与者关闭连接。因为这个消息是加密的,所以黑客很难发送一条伪装的消息来关闭这些连接。
    增强型消息验证 消息验证现在也包括了记录头。
    改进的握手协议 客户和服务器端的验证都包括了更加丰富的选项,其中有密钥交换、签名公共密钥和证书。
    新的私有验证特性 这个特性允许客户和服务器使用预先一致共享的私有密钥进行验证,而不是使用公共密钥。
    既然我们对PCT有了一些基本的了解,那就让我们看看PCT是如何工作的。PCT使用可变长度的记录作为通信的方法,每个记录包括一个记录头,它定义了记录内的信息类型。一共有两类信息:应用信息和协议信息。应用信息总是包含数据,它们可以用标准的PCT格式或数据报格式;协议信息包含了密钥管理、错误或握手信息。PCT使用两种附加的层,记录总是使用一个连接传送。客户和服务器间一般只有一个连接,但没有任何理由不能有更多的连接,每个连接只是会话的一部分。再强调一次,虽然你一般只能看到客户和服务器间的一个会话,但你确实可以用多个会话。(多会话可能需要客户和服务器间建立多个物理连接)。
    PCT协议的连接由一个握手信号开始,这就是握手管理消息类型开始工作的地方。客户和服务器交换多个信息,首先是连接会话密钥的握手,或者说是客户和服务器决定一个用于相互对话的保密字。此时,客户和服务器也彼此进行验证。如果彼此认为对方不可信时,便不会进行这种握手;一旦客户和服务器都认为对方可信时,它们便约定好了一个用于信息加密的主密钥。
     HTTP上的Windows NT认证
    Windows NT的认证一般不是 编程者要考虑的问题,更重要的是网络设置时要考虑的问题。但作为程序员,你确实应该了解一下认证问题,特别是如果你计划使用Internet或Intranet工作时更是如此。Windows NT现在支持两种基本类型的认证。(虽然没有任何东西阻止一些人使用其它方法。)
    技巧 如果你想使用Windows NT的质问/回答(challenge/response)特性,你必须使用Internet Explorer 2.0或更高版本的浏览器,其它浏览器当前还不支持这种实施安全特性的方法。
    第一种认证的方法是Windows NT的质问/回答。这种认证方法依赖于服务器和客户密钥的通信,而没有用户输入的任何形式。在客户初始登录到系统时,服务器要求客户输入用户名和保密字,客户提供一个特殊加密的用户名和保密字,他还必须提供一个域名,因为客户必须在服务器的域内或在一个服务器所信任的域内。由于Windows NT的质问/回答在客户和服务器间自动使用加密通信,所以它比服务器提供的基本认证更加安全。
    注 Windows NT提供的两种形式的认证是基本认证和质问/回答,使用质问/回答认证是最安全的。
    Web链接 有时,你顺手便可阅读到有关Windows NT针对Internet安全性方面的信息。其中一个信息源是Rick的Windows NT信息中心即http://rick.wzl.rwth-aachen.de/cgi-bin/isindex3.cmd, 这个Web站点涉及的一些内容,是你在微软的用户手册中所看不到的。例如,你将学会怎样使用Windows NT的各类第三方产品。在微软的方案中没有预先考虑到时,有些知识很值得学习。
    那么客户是如何知道需要发送用户名和保密字到服务器的呢?服务器要求这些信息作为头的一部分,实际上,服务器发送了一个错误信息(401 AccessDenied即访问拒绝),它告诉用户需要一个安全访问。浏览器中实际上没有包括从服务器来的所有信息,懂得这一点是很重要的,因为你在浏览器中看到的只是服务器想要你看到的信息,它已经过浏览器筛去了头信息。例如,服务器一般必须告诉浏览器它正接收什么类型的信息,这样如果需要的话,浏览器便能够激活一个帮助。知道有这些头信息,对你了解在客户和服务器间的动态数据传输是非常重要的。
    警告 如果你在你的站点上选择基本认证方式来实施安全性,你必须使用SSL来确保用户名和保密字传输的安全性。否则这些信息很容易被人破解,并利用它获得你的站点的访问。
    第二种方法依赖于诸如SSL的数字签名技术。实质上,Windows NT将需要一个从客户机来的数字认证,客户也需要Windows NT的数字认证。这些数字认证可以从第三方厂家(如VeriSign)获得,它能够保证双方的一致性。我们将会在本章的另一节中看到数字签名技术的确切过程。你现在应该知道的是,数字签名是一种安全手段,它能够标识试图访问你机器的另一方。
    当使用SSL时,实质上是Windows NT服务器需要客户的标识。Windows NT所获取的是由第三方厂家(如VeriSign)发布的认证和随同的一个公共的密钥。SSL在进行认证时,一共有以下六个步骤:
    1. 客户发送给Windows NT一个没有加密的随机消息并伴随一个它的VeriSign发布的认证(它包含了客户的公共密钥),VeriSign发布的认证是使用VeriSign的公共密钥加密的。因为每人都有VeriSign的公共密钥,所以Windows NT能够将整个认证解开并准确地检查它;同样,没有人能够伪造一个他们自己的公共密钥——他们必须从VeriSign那里获得。
    2. 一旦Windows NT确认它从客户那里接收到了一个有效的证书和公共的密钥,它将告诉客户发送一个它最开始发送的消息的加密版本。
    3. 客户计算机计算原始随机消息的摘要,然后使用公共密钥对它进行加密。
    4. Windows NT使用客户的公共密钥对这个摘要进行解密。
    5. Windows NT 将解开的摘要和客户原始发送的随机消息进行对比。
    6. 如果两个摘要匹配,这个客户便认证成功。
    在这里,你可能会关心与管理员有关的问题,虽然Windows NT自身提供了这两种内建的方法来控制服务器的访问,但它并不阻止你创建ISAPI过滤器来扩编或替代这种标准的安全机制。我们在第13章看到了一些非常基本的过滤器,但你也可以干脆使用其它的方法。你所应该做的就是监视那些由服务器产生的安全事件,这些事件中最关键的是客户的认证请求。在监视客户认证请求过程中,允许你增加任何必要的措施来确认谁在访问你的站点。
    注 ISAPI过滤器允许你改变Web服务器认证用户的方法。
     使用数字签名
    要精通数字签名的技术是比较困难的,虽然可以做到,但很少有人愿意去尝试。你首先必须懂得的是,数字签名也可以看成是授予证书。你可以把它想象成驾驶执照,因为它们之间有类似的功能。数字签名能标识一些Internet对象、以及创建它的人和创建的时间,也能潜在地提供很多其它信息,如果这个对象正好是客户或服务器,数字签名将显示对象的当前拥有者。和驾驶执照一样,数字签名也有过期的时候棗它迫使提供商不断地实现它们的承诺,这些过期的数据也使得黑客在篡谋窃取证书上浪费许多无用的时间(因为每个证书都是一个分立的条款,所以黑客只学会如何窃取其中之一是没什么用的)。使用数字签名将帮助人们保持诚实,因为它迫使每个人通过一个中心核查点。在Internet上,使用数字签名做期货交易还避免了一大堆的问题:它不依赖于某个人来维护机器的安全性,现在你可直接对那些获得访问的人进行投资(这也意味着要对用户做某些级别的训练,让他们真正学会如何去使用这个特性)。
    注 虽然代码符号处理(将在这一节的下载Internet部件部分进行讲述)现在还不是数字签名,但最终也将合并到数字签名中来。
    实施数字签名是非常直接而简单的,尤其是对客户端。在大多数情况下,商家提供了标准的证书,它能被所有浏览器或服务器所识别,但在授予证书的实际过程中,它们使用的方式却有不同。例如,在图14.2中的Web页中便显示了其中的一个潜在的问题,如果你想要获得一个客户的证书,你将选择哪个等级呢?(因为Class 1 Digital ID 证书 的价格便宜,所以许多人将会首选它)。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值