• Rails每周一题(六): Security Guide(上) (转载)


    此篇文章总结自:http://guides.rubyonrails.org/security.html


    谢谢某同学的提醒。

     

    Web应用存在的安全问题包括账号劫持,绕过访问控制,读取或者修改敏感信息或者显示欺诈内容等。通过security guide系列篇让我们一起来看看应该如何正确使用Rails来克服这些问题。

     

    在上篇中,主要描述对session的攻击,以及应对方法。

     

    首先简单介绍一下session的基本概念和一些普遍攻击方法。

     

     

    什么是Session

     

    Session是一个保存特定用户信息的哈希,用一个session id来识别不同的session。从服务器端发送到客户端浏览器的每一个响应中,cookie都包含一个session id。

     

    在Rails里面通过此种方式保存和获取session哈希内的值:

     

    Ruby代码  收藏代码
    1. session[:user_id] = @current_user.id   
    2. User.find(session[:user_id])   
     

    一个session id由一个随机字符串的哈希值组。这个随机字符串由当前时间,0和1之间的随机数,Ruby解释器的进程id和一个字符串常量组成。所以基本上不可能暴力破解session id。

     

    Session劫持

     

     通过盗取用户的session id,可以让攻击者以被盗取用户的名义使用web应用。

     

    现在大多数网站所使用的认证方式是form-based认证方式 。所以,只要黑客盗取了用户的session id,它既可以以被盗取用户的名义使用web应用。

     

    盗取session id的方式有以下几种:

     

    • 监听非安全网络盗取cookie,比如无线网络。可以通过提供基于SSL的安全连接来避免这个问题。
    • 很多人在公共场合使用了网站之后,忘记登出。所以网站要提供明显的logout功能。
    • 定置用户的session id。

    Session使用准则

     几条关于使用cookie的准则。

     

         1. 不要在session里面存储大量信息。正确的方式是在数据库里存储对象信息,而在session里只存储id。这不仅会缓解session同步问题,而且在对象结构改变时不需要担心遗留在session里面的数据结构不一致问题。

     

         2. 不要在session里面存储重要数据,以免丢失。特别是当你使用客户端保存session时,要当心被盗问题。(客户端保存session,指的是session在服务器端和客户端之间传输整个session,而不是session id。)

     

    Session存储机制

    — Rails提供了多种session存储机制,最重要的是ActiveRecordStore和CookieStore。

     

    因为性能和可维护性,大多数人选择ActiveRecordStore而不是文件存储。

     

    而CookieStore由于在服务器和客户端之间传输整个session,虽然此种方式缓解了服务器的压力,但却有很多限制:

     

    1. Cookie有严格的大小控制 -- 4K。

     

    2. 因为session信息在客户端以明文形式存储(Base64编码),所以有很大的安全隐患。当然,我们可以通过加密方式来防止信息的盗看。方法很简单,在environment.rb里面加上此句:

     

    Ruby代码  收藏代码
    1. config.action_controller.session = {  :key => '_app_session',  :secret => '0x0dkfj3927dkc7djdh36rkckdfzsg...' }   
     

    要注意的是需使用一个复杂的secret。

     

     

     

     

     

     

     

    介绍完session的一些基本概念之后,来让我们来看看几种对session的攻击方法和应对策略。

     

     

    CookieStore Session的重放攻击

     

    假设我们使用CookieStore来存储session,将会带来这样的安全问题:

     

    1. 用户获取信用卡信息,余额存储于session(很差的主意,示范之用。)

    2. 用户购买了一些东西。

    3. 现在在session里面存储的余额是购买之后扣去购买费用之后的余额。

    4. 用户用第一步中的session替换现在的session。

    5. 用户的余额被恢复到初始时。

     

    我们可以通过nonce 解决这个问题,但nonce需要服务器端数据库的跟踪,所以这已经违背了使用CookieStore避免使用数据库的初衷。

     

    所以,问题的关键所在还是在于不应在session里面存储重要信息。

     

    Session定置

    — 攻击者通过定置其他用户的session id,而非盗取session id的方式来使用其它用户的账户。

     

    session fixation

     

     

    让我们看看这种攻击是如何发生的:

    1. 攻击者访问网站,并从cookie中获取session。 (见图中第1 和 第2步).
    2. 攻击者通过不断访问网站使session保持不过期。
    3. 攻击者强迫受害者使用他的session id(见图中第3步)。由于不可能更改另一个域的cookie(由于同一来源策略 -- ), 攻击者通过在被攻击网站上运行一段如下的JavaScript代码来更改受害者的cookie。JavaScript代码的注入通过XSS的协助完成。 same origin policy
      Js代码  收藏代码
      1. <script>
document.cookie="_session_id=16d5b78abb28e3d6206b60f22a03c8d9";
</script>.  
    4. 受害者在浏览被注入恶意代码的网页时被更改了cookie值。
    5. 服务器发现此session id并未登录,就要求受害者重新登录。
    6. 从此刻开始,攻击者和受害者使用的是通过一个session id。而受害者对此一无所知。

     

    应对策略:

     

    只需要一行代码:

     

    Ruby代码  收藏代码
    1. reset_session   

     

    reset_session会清空旧session里的所有值,并且创建一个新session。在用户登录成功后运行此句,会让session定置攻击失效。不过要注意的是,需要转移旧session中的值到新session。如果你使用的是RestfulAuthentication插件,那么在SessionsController#create 方法中加入此句。

     

    还有一种应对方法是在session里面加上一些用户特定的信息,比如IP地址等。但用此种方法得注意IP地址并不一定直接对应到确定的用户,很多用户在proxy后面访问。

     

     

     

    Session过期问题

     

     

    让session在很长的时间内都不过期,会增大安全隐患。

     

    让session过期有两种方式:

     

    1. 在客户端:在session id cookie上设置一个过期时间。但用户可以通过修改cookie来改变过期时限。

     

    2. 在服务端,我们可以通过如下代码来清除未使用时间超过20分钟的session:

     

    Ruby代码  收藏代码
    1. class Session < ActiveRecord::Base <br><br><br><br><br><br><br>  
    2.   def self.sweep(time_ago = nil) 
 <br><br><br><br><br><br><br>  
    3.      time = case time_ago 
 <br><br><br><br><br><br><br>  
    4.           when /^(\d+)m$/ then Time.now - $1.to_i.minute 
 <br><br><br><br><br><br><br>  
    5.           when /^(\d+)h$/ then Time.now - $1.to_i.hour 
 <br><br><br><br><br><br><br>  
    6.           when /^(\d+)d$/ then Time.now - $1.to_i.day 
 <br><br><br><br><br><br><br>  
    7.           else Time.now - 1.hour 
 <br><br><br><br><br><br><br>  
    8.      end 
 <br><br><br><br><br><br><br>  
    9.      self.delete_all "updated_at < '#{time.to_s(:db)}'" 
 <br><br><br><br><br><br><br>  
    10.   end <br><br><br><br><br><br><br>  
    11. end   
     

    当然,攻击者可以通过每隔几分钟访问一次网站来保持session,可以加上这一段代码来清除创建时间过久的session:

     

    Ruby代码  收藏代码
    1. self.delete_all "updated_at < '#{time.to_s(:db)}' OR created_at < '#{2.days.ago.to_s(:db)}'"   

     

     

    未完待续,请看Security Guide中篇 和下篇 。

  • 相关阅读:
    WDSL文件中的XML元素
    Cookie跨域setDomain和setPath
    Cookie/Session机制详解
    Java服务端对Cookie的简单操作
    Nginx配置详解 http://www.cnblogs.com/knowledgesea/p/5175711.html
    如何在mac里面,把xcode代码同步到 tfs 的 git库(新git库)
    如何在mac里面,把xcode代码同步到 tfs 的 git库(克隆git篇)
    Centos7 安装 MySql
    如何在Centos里面,把.net core程序设为开机自启动
    Typescript编译设置
  • 原文地址:https://www.cnblogs.com/ToDoToTry/p/2118935.html
Copyright © 2020-2023  润新知