一、Secure By Default原则

1、黑名单和白名单

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

在 Flash 跨域访问请求里,是通过检查目标资源服务器端的 crossdomain.xml 文件来验证是 否允许客户端的 Flash 跨域发起请求的,它使用的是白名单的思想。比如下面这个策略文件:

<cross-domain-policy>
<allow-access-from domain="*.taobao.com"/>
<allow-access-from domain="*.taobao.net"/>
<allow-access-from domain="*.taobaocdn.com"/>
<allow-access-from domain="*.tbcdn.cn"/>
<allow-access-from domain="*.allyes.com"/>
</cross-domain-policy>

指定了只允许特定域的 Flash 对本域发起请求。可是如果这个信任列表中的域名变得不可 信了,那么问题就会随之而来。比如:

<cross-domain-policy>
<allow-access-from domain="*"/>
</cross-domain-policy>

通配符“*”,代表来自任意域的 Flash 都能访问本域的数据,因此就造成了安全隐患。所 以在选择使用白名单时,需要注意避免出现类似通配符“*”的问题。

2、最小权限原则

比如在 Linux 系统中,一种良好的操作习惯是使用普通账户登录,在执行需要 root 权限的 操作时,再通过 sudo 命令完成。这样能最大化地降低一些误操作导致的风险;同时普通账户 被盗用后,与 root 帐户被盗用所导致的后果是完全不同的。

在通过访谈了解业务时,可以多设置一些反问句,比如:您确 定您的程序一定需要访问 Internet 吗?通过此类问题,来确定业务所需的最小权限。

二、众深防御原则

纵深防御包含两层含义:首先,要在各个不同层面、不同方面实施安全方案,避免出现疏 漏,不同安全方案之间需要相互配合,构成一个整体;其次,要在正确的地方做正确的事情, 即:在解决根本问题的地方实施针对性的安全方案。

纵深防御并不是同一个安全方案要做两遍或多遍,而是要从不同的层面、不同的角度对系 统做出整体的解决方案。

纵深防御的第二层含义,是要在正确的地方做正确的事情。

三、数据与代码分离原则

这一原则广泛适用于各种由于“注入”而 引发安全问题的场景,在 Web 安全中,由“注入”引起的问题比比皆是,如 XSS、SQL Injection、CRLF Injection、 X-Path Injection 等。

根据数据与代码分离原则,在这里应该对用户数据片段 $var 进行安全处理,可以使用过 滤、编码等手段,把可能造成代码混淆的用户数据清理掉,具体到这个案例中,就是针对 <、> 等符号做处理。

四、不可预测性原则

不可预测性的实现往往需要用到加密算法、随机数算法、哈希算法,好好使用这条原则, 在设计安全方案时往往会事半功倍。

五、常见的攻击

1、点击劫持

点击劫持是一种视觉上的欺骗手段。攻击者使用一个透明的、不可见的 iframe,覆盖在一 个网页上,然后诱使用户在该网页上进行操作,此时用户将在不知情的情况下点击透明的 iframe 页面。通过调整 iframe 页面的位置,可以诱使用户恰好点击在 iframe 页面的一些功能性按钮上。

2、图片覆盖攻击

简单的说就是某网站的logo图片被覆盖,点击时链接到了其他网站

3、拖拽劫持与数据窃取

“拖拽劫持”的思路是诱使用户从隐藏的不可见 iframe 中“拖拽”出攻击者希望得到的数 据,然后放到攻击者能控制的另外一个页面中,从而窃取数据。

在这个例子中,xisigr 使用 event.dataTransfer.getData('Text') 来获取“drag”到的数据。当 用户拖拽小球时,实际上是选中了隐藏的 iframe 里的数据;在放下小球时,把数据也放在了隐 藏的 textarea 中,从而完成一次数据窃取的过程。

白帽子讲web安全笔记_数据

六、web框架与CSRF防御

CSRF 攻击的目标,一般都会产生“写数据”操作的 URL,比如“增”、“删”、“改”;而 “读数据”操作并不是 CSRF 攻击的目标,因为在 CSRF 的攻击过程中攻击者无法获取到服务 器端返回的数据,攻击者只是借用户之手触发服务器动作,所以读数据对于 CSRF 来说并无直 接的意义(但是如果同时存在 XSS 漏洞或者其他的跨域漏洞,则可能会引起别的问题,在这

里,仅仅就 CSRF 对抗本身进行讨论)。
因此,在 Web 应用开发中,有必要对“读操作”和“写操作”予以区分,比如要求所有的

“写操作”都使用 HTTP POST。

完整的 CSRF 防御方案,对于 Web 框架来说有以下几处地方需要改动。
(1)在 Session 中绑定 token。如果不能保存到服务器端 Session 中,则可以替代为保存到

Cookie 里。
(2)在 form 表单中自动填入 token 字段,比如 <input type=hidden name="anti_csrf_token"

value="$token" />。

(3)在 Ajax 请求中自动添加 token,这可能需要已有的 Ajax 封装实现的支持。

(4)在服务器端对比 POST 提交参数的 token 与 Session 中绑定的 token 是否一致,以验证 CSRF 攻击。

在 Rails 中,要做到这一切非常简单,只需要在 Application Controller 中增加一行即可: protect_from_forgery :secret => "123456789012345678901234567890..."

它将根据 secret 和服务器端的随机因子自动生成 token,并自动添加到所有 form 和由 Rails 生成的 Ajax 请求中。通过框架实现的这一功能大大简化了程序员的开发工作。

   最后感谢作者吴翰清的分享!