不管什么时候,如果你检查微软网站中的为视窗系统(或其他大多数微软产品)作的最新的安全更新,你将会发现大多数重要的补丁都是为系统防止缓冲溢出而设计的。在像做这样的设计时主要考虑是,一个攻击者可以使用一个恶意的代码片断作为执行他/她自己的代码的基础。
这里有很多种缓冲溢出攻击的类型,但是他们都是基于恶意代码编写或者利用那些原来开发的代码编程语言上的漏洞。那些用C写的程序是最容易受到缓冲溢出攻击的,因为C程序产生运行时间错误,并且在大多数被使用的C资料库没有被缺省设计为在执行时作错误检查(这一点正在改变)。
如果你能够保证你的输入是正确的,那么没有运行错误检查是好的做法。但是,黑客们已经发现当一个没有检查溢出C程序相应用户输入时,在程序执行失败时,可能会进入一个包括执行代码异常长的队列。这就是为什么我告诉你大多数的视窗操作系统和一些视窗服务器系统产品是用C写成的。
不要找我的错误,Windows不是唯一的容易被C程序的缓存溢出攻击影响的操作系统,同样Linux也一样容易被影响。
两种最主要的缓存溢出攻击类型是堆栈攻击和堆攻击。堆栈攻击是最常用的,因为它们是最容易被执行的。一个基于堆栈的缓冲运行工作是因为程序使用内存对象作为一个堆栈来存储用户输入。通常,在程序请求用户输入之前,堆栈会被清空。在这一点,程序写出一个返回内存地址到堆栈,然后用户的输入被放置到堆栈的顶端。当堆栈被处理时,用户的输入获得发送到指定的返回地址。
可是一个堆栈不具有无限制的大小。程序员编码一定要为堆栈预制指定的大小数量。如果用户的输入比喻预制指定的数量长,堆栈就会溢出。对于堆栈本身来说,溢出并不是什么大问题,但是当遇到恶意输入时,就会变成一个巨大的安全漏洞。
假设举一个例子,一个程序希望用户输入他/她的名字。相比输入名字,黑客更愿意输入一个超过堆栈大小的可执行指令。这个指令通常都很简短。比如说,在Linux环境中指令通常是要求系统打开一个即时指令窗口(就像大家都知道的循环Linux 的root内核)。
然而,一个可执行指令的缓冲溢出不是指指令要被执行。过程的另一方面是,攻击者必须指定一个返回地址指向恶意的指令。因此,程序损坏的一部分原因是因为堆栈溢出。程序试图去修复将要用到的返回地址,但是返回地址的指向已经被黑客改成了指到黑客制定的指令。意思就是黑客一定要知道恶意指令将要存放的位置。为了知道准确的地址,恶意指令常常被在NOP指示下的两部分填补。如果黑客指定的地址被填充,恶意指令将会被执行。
最后一个部分是可执行程序的许可权限。众所周知,大多数流行的操作系统都有一些机制来控制用户的登录访问级别。可执行程序的典型要求是比普通的登陆的许可权限级别更高,因此运行在内核模式或者许可权限继承自服务账户。当一个堆栈溢出攻击运行指令在一个新的返回地址时,程序认为它一直在运行。这就意味着被打开的命令提示窗口正在运行相同的一批许可命令,作为危及安全的应用。通常讲,这个的意思就是攻击者将会获得对操作系统的所有控制。
保护自己的技巧
那么,怎样能够保护你免受这一类的攻击呢?最容易和最紧急的技巧是保证你的操作系统,Exchange服务器和其他运行在服务器上的程序及时更新。这样将修复潜在的缓存溢出使用。
另一个技巧是你谨慎地使用运行在其上的特殊应用软件。我曾看到过许多人使用域管理员账户作为服务账户。这样问题就会出现:如果服务被不正常的使用,这样黑客就会访问到你的整个域。最好运行服务作为本地系统。然而如果一个服务必须需要用一个用户帐号作为服务账号,用一个本地用户账号就比用一个域账号好。另一方面,如果服务被危及安全,那么攻击者将被限制到控制那一个服务器而不是整个的域的机器。
你可用的最后一个技巧是用一个应用代理,在应用代理之后的方法是站在用户和应用之间并且过滤用户的输入,在字符串层和协议层来确定用户的输入是有效的。不幸的是你不可能去计算机里面为Exchange服务器存储并且购买一个应用代理。但是当正确配置的时候,在前端处理/后端处理配置中运行Exchange 能够达到作为一个应用代理的同样的目的。
另外一个应用代理的例子是一个工具,叫做URLscan,虽然你不能完全理解,但是你可以从Microsoft的Web站点下载这个工具。这个工具可以监控进入你的IIS服务器(IIS是Exchange需要的)中去的请求,来确保请求不会过长并且请求中不包含恶意代码。