2013年5月30日星期四

网络安全---Web框架安全

2012-08-14 11:31:37|  分类: 网络 |字号 订阅
一、MVC框架安全:
从数 据的流入来看,用户提交的数据先后流经了View层、Controller、Model层,数据的流出则反过来。在设计安全方案时,要牢牢把握住数据这个 关键因素。在MVC框架中,通过切片、过滤器等方式,往往能对数据进行全局处理,这位设计安全方案提供了极大的便利。
比如在Spring Security中,通过URL Pattern实现的访问控制,需要由框架来处理所有用户请求,在Spring Security获取了URL handler基础上,才有可能将后续的安全检查落实。在Spring Security的配置中,第一步就是在web.xml文件中增加一个filter,接管用户数据:
...
然而数据的处理是复杂的,数据 经过不同的应用逻辑处理后,其内容可能会发生改变。比如数据经过toLowercase,会把大写变成小写;而一些编码解码,则可能会把GBK变成 Unicode码。这些处理都会改变数据的内容,因此在设计安全方案时,要考虑到数据可能的变化,认真斟酌安全检查插入的时机。

在正确的地方,做正确的事。

举 例来说,在”注入攻击“一章中,我们并没有使用PHP的magic_quotes_gpc作为一项对抗SQL注入的防御方案,这是因为 magic_quotes_gpc是有缺陷的,它并没有在正确的地方解决问题。magic_quotes_gpc实际上是调用了一次 addslashes(),将一些特殊符号(比如单引号)进行转义,变成了\'。
对应到MVC框架里,它是在View层做这件事情的,而SQL注入是Model层需要解决的问题,结果如何呢?黑客们找到了多种绕过magic_quotes_gpc的办法,比如使用GBK编码、使用无单引号的注入等。
PHP官方在若干年后终于开始正视这个问题,于是在官方文档的描述中不再推荐大家使用它。
所以Model层的事情搞到View层去解决,效果只会适得其反。
一般来说,我们需要先想清楚要解决什么问题,深入理解这些问题后,再在”正确“的地方对数据进行安全检查。一些主要的Web安全威胁,如XSS、CSRF、SQL注入、访问控制、认证、URL跳转等不涉及业务逻辑的安全问题,都可以集中放在MVC框架中解决。
在框架中实施安全方案,比由程序员在业务中修复一个个具体的bug,有着更多的优势。
首先,有些安全问题可以在框架中统一解决,能够大大节省程序员的工作量,节约人力成本。当代吗的规模大到一定程度时,在业务的压力下,专门花时间去一个个修补漏洞几乎成为不可能完成的任务。
其次,对于一些常见的漏洞来说,由程序员一个个修补可能会出现遗漏,而在框架中统一解决,有可能解决”遗漏“的问题。这需要制定相关的代码规范和工具配合。
最后,在每个业务里修补安全漏洞,补丁的标准难以统一,而在框架中集中实施的安全方案,可以使所有基于框架开发的业务都能受益,从安全方案的有效性来说,更容易把握。

二、模版引擎与XSS防御:
在 View层,可以解决XSS问题。在本书的”跨站脚本攻击“一章中,阐述了”输入检查“与”输出编码“这两种方法在XSS防御效果上的差异。XSS攻击是 在用户的浏览器上执行的,其形成过程则是在服务器端页面渲染时,注入了恶意的HTML代码导致的。从MVC架构来说,是发生在View层,因此使用”输出 编码“的防御方法更加合理,这意味着需要针对不同上下文的XSS攻击场景,使用不同的编码方式。
在”跨站脚本攻击“一章中,我们将”输出编码“的防御方法总结为以下几种:
1)在HTML标签中输出变量。
2)在HTML属性中输出变量。
3)在script标签中输出变量。
4)在事件中输出变量。
5)在CSS中输出变量
6)在URL中输出变量。
针对不同的情况,使用不同的编码函数。那么现在流行的MVC框架是否符合这样的设计呢?答案是否定的。
在 当前流行的MVC框架中,View层常用的技术是使用模版引擎对页面进行渲染,比如在”跨站脚本攻击“一章中所提到的Django,就使用了Django Templates作为模版引擎。默认引擎本身,可能会提供一些编码方法,比如,在Django Templates中,使用filters中的escape作为HtmlEncode的方法:
<h1>Hello,{{ name|escape }}!</h1>
Django Templates同时支持auto-escape,这符合Secure by Default原则。现在的Django Templates,默认是将auto-escape开启的,所有的变量都会经过HtmlEncode后输出。默认是编码了5个字符:
< = &lt;
> = &gt;
' = &#39
" = &quot;
& = &amp;
如果要关闭auto-escape,则需要使用以下办法:
{{ data|safe }}
或者
{% autoescape off %}
     Hello {{ name }}
{% endautoescape %}
为了方便,很多程序员可能会选择关闭auto-escape。要检查auto-escape是否被关闭也很简单,搜索代码里是否出现上面两种情况即可。

但是正如前文所述,最好的XSS防御方案,在不同的场景需要使用不同的编码函数,如果统一使用这5个字符的HtmlEncode,则很可能会被攻击者绕过。由此看来,这种auto-escape的方案,看起来也变得不那么美好了。
再看看非常流行的模版引擎Velocity,它也提供了类似的机制,但是有所不同的是,Velocity默认是没有开启HtmlEncode的。

在Velocity中,可以通过Event Handler来进行HtmlEncode。
eventhandler.referenceinsertion.class=org.apache.velocity.app.event.implement.EscapeHtmlReference
eventhandler.escape.html.match=/msg.*/
使用方法如下例,这里同时还加入了一个转义SQL语句的EventHandler。

...

import org.apache.velocity.app.event.EventCartridge;
import ...

...
public class Test
{
  public void myTest()
  {
     EventCartridge ec=new EventCartridge();
     ec.addEventHandler(new EscapeHtmlReference());
     ec.addEventHandler(new EscapeSqlReference());

     ec.attachToContext(context);
     ...
  }
}
但 Velocity提供的处理机制,与Django的auto-escape所提供的机制是类似的,都只进行了HtmlEncode,而未细分编码使用的具 体场景。不过幸运的是,在模版引擎中,可以实现自定义的编码函数,应用于不同的场景。在Django中是使用自定义filters,在Velocity中 则可以使用”宏“(velocimacro),比如:

XML编码输出,将会执行XML Encode输出
#SXML($xml)

JS编码输出,将会执行Javascript Encode输出
#SJS($js)

通过自定义的方法,使得XSS防御的功能得到完善;同时在模版系统中,搜索不安全的变量也有了依据,甚至在代码检测工具中,可以自动判断出需要使用哪一种安全的编码方法。这在安全开发流程中是非常重要的。
在 其他的模版引擎中,也可以依据“是否有细分场景使用不同的编码方式”来判断XSS的安全方案是否完整。在很多Web框架官方文档中推荐的用法,就是存在缺 陷的。Web框架的开发者在涉及安全方案时,有时会缺乏来自安全专家的建议。所以开发者在使用框架时,应该慎重对待安全问题,不可盲从官方指导文档。

三、Web框架与CSRF防御
关于CSRF的攻击原理和防御方案,在本书“跨站点请求伪造”一章中有所阐述。在Web框架中,可以使用security token解决CSRF攻击的问题。
CSRF 攻击的目标,一般都会产生“写数据”操作的URL,比如“增、删、改“;而读数据操作并不是CSRF攻击的目标,因为在CSRF的攻击过程中攻击者无法获 取到服务器端返回的数据,攻击者只是借用户之手触发服务器操作,所以读数据对于CSRF来说并无直接的意义(但是如果同事存在XSS漏洞或者其他的跨域漏 洞,则可能会引起别的问题,在这里,仅仅就CSRF对抗本身进行讨论)。
因此,在Web应用开发中,有必要对”读操作“和”写操作"予以区分,比如要求所有的“写操作”都使用HTTP POST。
在 很多讲述CSRF防御的文章中,都要求使用HTTP POST进行防御,但实际上POST本身并不足以对抗CSRF,因为POST也是可以自动提交的。但是POST的使用,对于保护token有着积极的意 义,而security token的私密性(不可预测性原则),是防御CSRF攻击的基础。
对于Web框架来说,可以自动地在所有涉及POST的代码中添加token,这些地方包括所有的form表单、所有的ajax POST请求等。
完整的CSRF防御方案,对于Web框架来说有以下几处地方需要改动。
1)在Session中绑定token。如果不能保存到服务器端session中,则可以替代为保存到Cookie里。
2)在Form表单中自动填入token字段,比如<input type=hidden name="anti_csrf_token" value="$token" />
3)在Ajax请求中自动添加token,这可能需要已有的Ajax封装实现的支持。
4)在服务器端对比POST提交参数的token与Session中绑定的token是否一致,以验证CSRF攻击。

在Rails中,要做到这一切非常简单,只需要在Application Controller中增加一行即可:
protect_from_forgery : secret => "123456789012345678901234567890..."
它将根据secret和服务器端的随机因子自动生成token,并自动添加到所有的form和由Rails生成的Ajax请求中。通过框架实现的这一功能大大简化了程序员的开发工作。
在Django中也有类似的功能,但是配置稍微要复杂点。
。。。

四、Http Headers管理
在Web框架中,可以对HTTP头进行全局化的处理,因此一些基于HTTP头的安全方案可以很好的实施。

五、数据持久层与SQL注入:使用ORM(Object Relation Mapping)框架对SQL注入是有积极意义的。
六、还能想到什么:
七、Web框架自身安全
1、Struts 2 命令执行漏洞
3、Spring MVC命令执行漏洞
4、Djaogo命令执行漏洞

没有评论:

发表评论