web安全

1,135 阅读6分钟

揭秘web安全的本质

安全是什么?什么样的情况下会产生安全问题?我们要如何看待安全问题?只有搞明白了这些基本问题,才能明白一切防御技术的出发点,才能明白为何我们要这样做,要那样做。

我们不妨从现实世界入手。火车站,机场里,在乘客们开始正式旅程之前,都有必要的程序:安全检查。这种检查就是过滤有害的,危险的东西。通过这种检查,可以梳理未知的人或物,使其变得可信任。web安全也是如此,安全问题的本质是信任问题。

一切的安全的方案的基础,都是建立在信任关系上的。我们必须相信一些东西,必须有一些最基本的假设,安全方案才能得以建立;如果我们否定一切,安全方案就会如无源之水,无根之木,也无法完成。

安全三要素

在设计方案之前,要正确全面地看待安全问题。

要全面地认识安全问题,我们有很多种办法,但首先要理解安全问题的组成属性。前人通过无数次实践,最后将安全的属性总结为安全三要素,简称CIA

安全三要素是安全的基本组成元素,分别是机密性(Confidentiality), 完整性(Integrity), 可用性(Avaliability)

机密性要求保护数据内容不能泄露,加密是实现机密性要求的常见手段。

完整性要求保护的内容是完整的,没有被篡改的。常见的保证一致性的技术手段是数字签名

可用性要求保护资源是"随需而得的",假设一个停车场里有100个车位,在正常情况下,可以停100辆车。但是在某一天,有个坏人搬了100块大石头,把每个车位都占用了,停车场无法再提供正常的服务。在安全领域中这中攻击叫做拒绝服务攻击,简称Dos(Denial of service)。拒绝服务攻击破坏的是安全的可用性。

Secure By Default原则

在设计安全方案时,最基本也是最重要的原则就是“secure By Default”。在做任何安全设计时,都要牢牢记住这个原则。一个方案设计得是否足够安全,与有没有应用这个原则有很大的关系。实际上, “secure By Default”原则,也可以归纳为白名单,黑名单思想。如果更多地使用白名单,那么系统就会变得更安全。

黑名单,白名单

比如,在制定防火墙的网络访问控制策略时,如果网站只提供web服务,那么正确的做法是只允许网站服务器的80和443端口对外提供服务,屏蔽除此之外的其他端口。这是一种“白名单”做法;如果使用“黑名单”,则可能出现问题。假设黑名单的策略是:不允许SSh端口对Internet开发,那么就要审记SSH的默认端口:22端口是否开发了Internet。但在实际工作过程中,经常会发现有的工程师为了偷懒或图方便,私自改变了SSH的监听端口,比如把SSH的端口从22改到了2222,从而绕过了安全策略。

又比如,在网站的生产环境服务器上,应该限制随意安装软件,而需要制定统一的软件版本规范。这个规范的制定,也可以选择白名单的思想来实现。按照白名单的思想,应该根据业务需求,列出一个允许使用的软件版本清单,在此清单外的软件则禁止使用。如果允许工程师在服务器上随意安装软件的话,则可能会因为安全部门不知道,不熟悉这些软件而导致一些漏洞,从而扩大攻击面。

在web安全中,对白名单思想的运用也比比皆是。比如应用处理用户提交的富文本时,考虑到XSS的问题,需要做安全检查。常见的XSS Filter一般是先对用户输入的HTML原文作HTML Parse, 解析成标签对象后,再针对标签匹配XSS的规则。这个规则列表就是一个黑白名单。如果选择黑名单思想,则这套规则里可能是禁用诸如<script>, <iframe>等标签。但是黑名单可能会有遗漏,比如未来浏览器如果支持新的html标签,那么此标签可能就不在黑名单之中了。如果选择白名单的思想,就能避免种问题,在规则中,只允许用户输入诸如<a>,<img>等需要用到的标签。

最小权限原则

Secure By Default 的另一层含义就是“最小权限原则”。最小权限原则也是安全设计的基本原则之一。最小权限原则要求系统只授予主体必要的权限,而不要过度授权,这样能有效地减少系统,网络,应用数据库出错的机会。

数据与代码分离原则 另一个重要的安全原则是数据与代码分离原则。这一原则广泛适用于各种由于“注入”而引发的安全问题的场景。

实际上,缓冲区溢出,也可以认为是程序违背了这一原则的后果——程序在栈或者堆中,将用户数据当做代码执行,混淆了代码与数据的边界,从而导致安全问题的发生。

在web安全中,由“注入”引起的问题比比皆是,如XSS, SQL Injection,CRLF Injection, Xpath Injection等。此类问题均可以根据“数据与代码分离原则”设计出真正安全的解决方案,因为这个原则抓住了漏洞形成的本质原因。

以XSS为例,它产生的原因是HTML Injection 或 JavaScript Injection,如果一个页面的代码如下

<html>
  <head>test</head>
  <body>
    $var
  </body>
</html>

其中 $var 是用户能够控制的变量,那么对于这段代码来说:

<html>
  <head>test</head>
  <body>
  </body>
</html>

就是程序的代码执行段。

var**
就是程序的用户数据片段。如果把用户数据片段 **var 当成代码片段来解释、执行,就会引发安全问题。 比如,当$var的值是

<script  src=http://evil ></script>

时,用户数据就被注入到代码片段中。解析这段脚本并执行的过程,是由浏览器来完成的——浏览器将用户数据里的