面试总结5 - Ruby on Rails 安全指南总结

2019/01/17

面试总结5 - Ruby on Rails 安全指南总结

这一篇博文主要还是要讲cookie和session问题,只不过是针对rails的实现,但对面试的助益应该不大,

因为面试官的目的仍是想得知抛开语言的技术,即上文的数字签名,ssl等,具体在某一语言领域的实现只能说锦上添花而已。

故大致知道如何实现各种安全防御的手段即可。


1 攻击方式&解决方案概览

1 会话劫持

http等黑客窃取用户cookie,避免身份验证。

1 解决

https SSL链接

config.force_ssl = true

2 会话存储

从 Rails 4 开始,默认存储机制是 EncryptedCookieStore。EncryptedCookieStore 会先对会话进行加密,再储存到 cookie 中。这么做可以防止用户访问和篡改 cookie 的内容。因此,会话也成为储存数据的更安全的地方。加密时需要使用 config/secrets.yml 文件中储存的服务器端密钥 secrets.secret_key_base。

也就是数字签名 + 内容加密

2 对 CookieStore 会话的重放攻击

比如cookie中存储信用值,初始100,用户使用一次之后剩余99,但是用户将原来的cookie替换现在的cookie,重新用信用值100去操作。

1 解决

在会话中包含随机数可以防止重放攻击。每个随机数验证一次后就会失效,服务器必须跟踪所有有效的随机数。当有多个应用服务器时,情况会变得更复杂,因为我们不能把随机数储存在数据库中,否则就违背了使用 CookieStore 的初衷(避免访问数据库)。

因此,防止重放攻击的最佳方案,不是把这类敏感数据储存在会话中,而是把它们储存在数据库中。回到上面的例子,我们可以把信用额度储存在数据库中,而把当前用户的 ID 储存在会话中。

3 会话固定攻击

不是上述窃取用户cookie(包含会话id),而是黑客创建了一个会话id,然后使用XSS JavaScript替换用户的会话id,而用户第一次会去鉴权,这样黑客和用户用了一个会话id,而用户不自知。

1 解决

面对会话固定攻击,最有效的对策是在登录成功后重新设置会话 ID,并使原有会话 ID 失效,这样攻击者持有的会话 ID 也就失效了。这也是防止会话劫持的有效对策。在 Rails 中重新设置会话 ID 的方式如下:

reset_session

4 会话过期

黑客获取cookie后,五分钟访问一次,防止过期。

1 解决

session中添加create_at字段,删除过期会话

delete_all "updated_at < '#{time.ago.to_s(:db)}' OR
  created_at < '#{2.days.ago.to_s(:db)}'"

5 跨站请求伪造(CSRF)

跨站请求伪造的工作原理是,通过在页面中包含恶意代码或链接,访问已验证用户才能访问的 Web 应用。如果该 Web 应用的会话未超时,攻击者就能执行未经授权的操作。

解决

首先,根据 W3C 的要求,应该适当地使用 GET 和 POST HTTP 方法。其次,在非 GET 请求中使用安全令牌(security token)可以防止应用受到 CSRF 攻击

为了防止其他各种伪造请求,我们引入了安全令牌,这个安全令牌只有我们自己的网站知道,其他网站不知道。我们把安全令牌包含在请求中,并在服务器上进行验证。安全令牌在应用的控制器中使用下面这行代码设置,这也是新建 Rails 应用的默认值:

protect_from_forgery with: :exception

这行代码会在 Rails 生成的所有表单和 Ajax 请求中包含安全令牌。如果安全令牌验证失败,就会抛出异常。

ActiveRecord::SecureToken::ClassMethods

6 重定向和文件

另一类安全漏洞由 Web 应用中的重定向和文件引起。

1 重定向

Web 应用中的重定向是一个被低估的黑客工具:攻击者不仅能够把用户的访问跳转到恶意网站,还能够发起独立攻击

攻击者发动钓鱼攻击时,或者给用户发送包含恶意链接的邮件,或者通过 XSS 在 Web 应用中注入恶意链接,或者把恶意链接放入其他网站。这些恶意链接一般不会引起用户的怀疑,因为它们以正常的网站 URL 开头,而把恶意网站的 URL 隐藏在重定向参数中

2 文件上传

如果我们把上传的文件储存在 /var/www/uploads 文件夹中,而用户输入了类似 ../../../etc/passwd 的文件名,在没有对文件名进行过滤的情况下,passwd 这个重要文件就有可能被覆盖。

1 解决

在过滤用户输入的文件名时,不要去尝试删除文件名的恶意部分。我们可以设想这样一种情况,Web 应用把文件名中所有的 ../ 都删除了,但攻击者使用的是 ….//,于是过滤后的文件名中仍然包含 ../。最佳策略是使用白名单,只允许在文件名中使用白名单中的字符。

7 注入攻击

注入这种攻击方式,会把恶意代码或参数写入 Web 应用,以便在应用的安全上下文中执行。注入攻击最著名的例子是跨站脚本(XSS)和 SQL 注入攻击。

1 XSS(javaScript)

XSS 攻击的工作原理是:攻击者注入代码,Web 应用保存并在页面中显示这些代码,受害者访问包含恶意代码的页面。

1 手段
  • HTML / JavaScript 注入

2 解决

  1. 白名单 vs 黑名单

对于净化、保护和验证操作,白名单优于黑名单。

黑名单可以包含垃圾电子邮件地址、非公开的控制器动作、造成安全威胁的 HTML 标签等等。与此相反,白名单可以包含可靠的电子邮件地址、公开的控制器动作、安全的 HTML 标签等等。

Rails 2 及更高版本中使用了白名单,下面是使用新版 sanitize() 方法的例子:

通过规定允许使用的标签,sanitize() 完美地完成了过滤输入的任务。不管攻击者使出什么样的花招、设计出多么畸型的标签,都难逃被过滤的命运。

  1. httponly

2 sql注入

攻击者输入 ‘ OR ‘1’=’1

手段
  1. 预编译sql
  2. 为了净化受污染的字符串,在提供查询条件的选项时,我们应该传入数组而不是直接传入字符串:
Ruby on Rails 内置了针对特殊 SQL 字符的过滤器,用于转义 '、"、NULL 和换行符。

Model.where("login = ? AND password = ?", entered_user_name, entered_password).first

数组的第一个元素是包含问号的 SQL 片段,从第二个元素开始都是需要净化的变量,净化后的变量值将用于代替 SQL 片段中的问号。

3 CSS 注入

CSS 注入实际上是 JavaScript 注入,因为有的浏览器(如 IE、某些版本的 Safari 和其他浏览器)允许在 CSS 中使用 JavaScript。因此,在允许 Web 应用使用自定义 CSS 时,请三思而后行。

解决

这个例子再次说明,黑名单永远做不到万无一失。不过,在 Web 应用中使用自定义 CSS 是一个非常罕见的特性,为这个特性编写好用的 CSS 白名单过滤器可能会很难。如果想要允许用户自定义颜色或图片,我们可以让用户在 Web 应用中选择所需的颜色或图片,然后自动生成对应的 CSS。如果确实需要编写 CSS 白名单过滤器,可以参照 Rails 提供的 sanitize() 进行设计。

4 Ajax 注入

对于 Ajax 动作,必须采取和常规控制器动作一样的安全预防措施。不过,至少存在一个例外:如果动作不需要渲染视图,那么在控制器中就应该进行转义。

8 用户管理

1 暴力破解账户

对账户的暴力攻击是指对登录的账号密码进行试错攻击。通过显示较为模糊的错误信息、要求输入验证码等方式,可以增加暴力破解的难度。

像’密码不争取’,’没找到用户名’,会给黑客提供明确的提示,使其更加有针对性的破解,所以要有模糊的提示。

2 账户劫持

1 密码

假设攻击者窃取了用户会话的 cookie,从而能够像用户一样使用应用。此时,如果修改密码很容易,攻击者只需点击几次鼠标就能劫持该账户。另一种可能性是,修改密码的表单容易受到 CSRF 攻击,攻击者可以诱使受害者访问包含精心设计的图像标签的网页,通过 CSRF 窃取密码。针对这种攻击的对策是,在修改密码的表单中加入 CSRF 防护,同时要求用户在修改密码时先输入旧密码。

2 电子邮件

攻击者还能通过修改电子邮件地址来劫持账户。一旦攻击者修改了账户的电子邮件地址,他们就会进入忘记密码页面,通过新邮件地址接收找回密码邮件。针对这种攻击的对策是,要求用户在修改电子邮件地址时同样先输入旧密码。


Show Disqus Comments

Post Directory