我的译言链接:

[url]http://www.yeeyan.com/articles/view/blackanger/17939[/url]

5. 企业内联专用网和管理安全

企业内联网和管理界面是最流行的***目标, 因为它们有特殊的访问权限. 虽然它会有一些额外的安全措施,可是现实里并非如此。

2007年,在线招聘站点Monster.com遭受了一起定制***(Tailor-made Trojans)***,这是第一只专门从企业内联网偷窃信息的定制***。定制***是非常罕见的,迄今为止,发生率比较低, 但是它也确实是可能发生的,这也是一个客户端主机 安全何等重要的例子. 然而,企业内联网和管理应用程序面对的最大威胁还是XSS和CSRF.

XSS  如果你的应用重现了恶意用户从外网的输入,那么你的应用会受到XSS的危害。用户名,评论,垃圾邮件等是容易被XSS***的常见的例子。
在管理界面或是内网只要一个地方没有被消毒(sanitized)就会导致整个应用遭受危害。可能的漏洞包括窃取有特权管理员的cookie,iframe注入(Monster.com就是被这样***的)窃取管理员密码或者是通过浏览器的 安全漏洞安装一款恶意软件来接管管理员的计算机。
参看Injection章节,有XSS的对策,以及推荐了一款在内网和管理员界面使用的SafeErb的插件。
 
CSRF 跨站点 Reference 伪造 (CSRF) 是一个强大的***方法,它允许***者能做内网用户和管理员能做的一切事情。正如你已经看到上面几部分里CSRF如何工作的,这里也有一些例子,说明***者能在内网和管理界面做些什么。
一个现实世界的例子是一个通过CSRF重新配置路由的例子。这个***者发送了一封包含CSRF的恶意的电子邮件给墨西哥的用户。电子邮件声称有一个电子贺卡等着他们,但是它也包含了一个可以造成一个HTTP- GET请求去重新设置用户路由的图像标记(p_w_picpath tag)(这在墨西哥比较流行)。这个请求改变了DNS设置以便到墨西哥银行的请求可以映射到***者的站点。每个访问银行网站的人通过这个路由都能看到***者的伪造站点,并且他的证书被盗。
 
另一个例子是通过 GSRF改变Google Adsense的email地址和密码。如果受害者是登陆到Google Adsense,一个Google竞投广告的管理界面,***者可能会改变他的 安全证书。
另一种流行的***是你的web应用上的垃圾, 在你的blog或者论坛传播恶意XSS. 当然,***者必须知道URL结构,但是大多数的 Rails URLS是相对简单,或者,如果它是一个开源应用的管理界面,是很容易被他们找出的。***者甚至可以做1000个仅包括恶意img tags的幸运的猜测去尝试每一个可能的组合。
 
对于在管理界面和内网应用的CSRF对策,请参考CSRF章节里的对策。
 

5.1. 额外的预防措施

一般的管理界面是这样工作的: 它的位置是[url]www.example.com/admin[/url], 可只有在用户模式被设置了admin tag的才能访问。重现用户的输入,然后删除,增加,修改想要的任何数据。这里有一些想法:
  • 考虑最坏的情况是非常重要的 : 如果某人真的掌握了我的cookie或是用户证书。你能控制角色为管理界面去限制***者的可能性。或者除了哪些用于公共部分的应用,为管理界面提供一个专门的登陆证书如何,或者对于每次重要的action提供一个密码 ?
  • 是否这个管理员真的必须能从世界各地访问这个接口? 考虑一下根据ip地址段来限制登陆。检测request.remote_ip 了解用户的IP地址. 这并不是防弹的,而只是制造一个障碍。但请记住,有可能有人在使用代理。
  • 把管理界面放到一个专门的子域,例如admin.application.com,使其用户管理成为一个单独的应用程序。这使得***者不可能从通常的[url]www.application.com[/url]窃取cookie。这是因为在你的浏览器里存在同一个原生标准: 在[url]www.application.com[/url]的注入脚本(XSS)不能读取admin.application.com的cookie,反之亦然。

6. Mass assignment

是指对Model.new(params[:model]) 允许***者设置任意数据库列的值没有任何防范措施。

这个mass-assignment可能变成一个问题, 因为它允许***者通过操作hash传到一个model的new()方法里来设置model的任意属性 :
def signup
params[:user] #=> {:name => “ow3ned”, :admin => true}
@user = User.new(params[:user])
end
Mass-assignment为你省去了大量的工作, 因为你不必要去设置每个单独的值。只需要给new()方法传一个hash,或者是指定attributes=(attributes)hash值,就可以在hash里设置一个model的属性。问题是,在controller里经常使用可用的hash参数会被***者操纵。 他可能会这样改变URL:
[url]http://www.example.com/user/signup?user[/url][name]=ow3ned&user[admin]=1
这样会在controller里设置如下的参数 :
params[:user] #=> {:name => “ow3ned”, :admin => true}

如果你通过
mass-assignment这种方式创建一个新用户,那么这个用户很有可能会变成一个管理员。

6.1. 对策

为了避免这个问题, Rails在ActiveRecord类里提供了两个类方法去控制访问你的那些model的属性。attr_protected方法可以设置一个不被mass-assignment方式访问的属性清单(黑名单):
attr_protected :admin
attr_accessible是一个更好的方式,因为它遵循了白名单原则。 这和attr_protected是完全相反的,因为它列出的是可被访问的属性清单。 所有其他的属性会被保护。这样你就不会忘记去保护在开发过程中增加的新的属性。这里有个例子:
attr_accessible :name
如果你想要保护一个属性,你就必须独立的去指定它 :
params[:user] #=> {:name => "ow3ned", :admin => true}
@user = User.new(params[:user])
@user.admin #=> false # not mass-assigned
@user.admin = true
@user.admin #=> true