代码改变世界

晒一下我的web过滤器

2011-11-14 22:49  熬夜的虫子  阅读(2469)  评论(5编辑  收藏  举报

背景

  Xss跨站脚本的烦恼大部分程序员应该都碰到过,防不胜防。关于跨站的实例可以看这里。如果在项目开发前期开始控制还容易点,但是如果是历史项目还是相当庞大的,那么你该纠结了。本章给大家介绍一种解决方案。当然作为过滤器本身不单单是防跨站的作用。


概述

  提交数据时提供post、get、head、cookies4种方式的过滤 ,浏览页面时提供服务器端控件的check,以及页面输出流的check和更新,IP黑白过滤


Demo概要流程

step.1 配置过滤类别 post get head cookies大家都懂的 other为自定义扩展 outputcontrol为服务器端控件检查 outputhtml为页面输出流

step.2 以get方式为例 应用类型1表示get 过滤正则以未转义的参考 因为最后的配置媒介为xml 至于原因 下面会描述  

step.3 根据配置类型设置参数 以post方式为例 例如UserInfo.aspx页面过滤Email,ICQ,QQ 默认过滤全部页面 全部参数

step.4 在配置类别页面生成Xml固化文本 这么做的原因为了减少主站的复杂度并且各个应用站点可以灵活扩展自己的特性 最主要的是忽略网络传输异常的风险 毕竟安全的优先级最高

 step.5 应用端附加组件 关于组件下面概要设计中会详细描述

step.6 看效果 简单以get方式为例

加些敏感字符 设置异常跳转页面为http://t.163.com/notfound

敲下回车


 概要设计 

这套web过滤器还算不上系统的层级,主要是一个设计思路。我想很多同学在看完文章以后会有种恍然大悟的感觉,原来如此简单。不错,关心项目周边的细节你还会发现很多有趣又有用的内容。.net项目的一个优势就是在应用程序周期的大部分环节都可以很好的控制。对于上述功能可能会有很多同学想到AOP,但是AOP做不到通用。

下面为大家揭开过滤器的真实面貌。

你没看错,确实只有这么一些。

XssCheck负责实际的check动作。

例如白名单外的IP 恶意访问超过5次以上 应用端缓存下记录 应用端拒绝访问12小时-跳转页面 不再汇总警报数据 恶意访问5次,拒绝访问跳转至自定义的页面。

根据不同的配置类型 进行不同的check动作

页面输出流的处理比较特殊 对于流的处理虫子这里分为2类 是只check还是包含更新操作 。这里需要区分2个概念HttpModule和HttpHandler


 HttpModule msdn的原版解释

An HTTP module is an assembly that is called on every request made to your application. HTTP modules are called as part of the ASP.NET request pipeline and have access to life cycle events throughout the request. HTTP modules therefore give you the opportunity to examine incoming and outgoing requests and take action based on the request. The topics in this section provide information on how HTTP modules work and how to create them.

一句话来说我们可以自定义编程HttpModule来实现对HttpRequest中的内容做一个处理或者过滤。也就是订阅管线事件,并在事件处理器中执行所需的相关操作。

至于具体有哪些管线事件参考
http://msdn.microsoft.com/library/chs/default.asp?url=/library/CHS/cpref/html/frlrfsystemwebhttpapplicationclasstopic.asp

HttpHanlder msdn的原版解释

 定义 ASP.NET 为使用自定义 HTTP 处理程序同步处理 HTTP Web 请求而实现的协定。

一句话来HttpHandler是一个HTTP请求的真正处理中心,也正是在这个HttpHandler容器中,ASP.NET Framework才真正地对客户端请求的服务器页面做出编译和执行。

HttpModule 与HttpHanlder 的关系。

HttpHanlder 将处理过后的信息附加在HTTP请求信息流中再次返回到HttpModule中。

当一个HTTP请求经同HttpModule容器传递到HttpHandler容器中时,ASP.NET Framework会调用HttpHandler的ProcessRequest成员方法来对这个HTTP请求进行真正的处理。以一个ASPX页面为例,正是在这里一个ASPX页面才被系统处理解析,并将处理完成的结果继续经由HttpModule传递下去,直至到达客户端。HttpHanlder 中的过渡方法为PostRequestHandlerExecute。还想更详细了解的同学可以参考msdn中ASP.NET的管道处理。


 了解到上述概念后,明白的同学应该了解到流的处理是在哪个阶段了。因为页面输出流已经是服务端处理完首次请求向客户端发送数据的环节。这里流的处理我们放在HttpHanlder中,如何在HttpModule中的BeginRequest管线事件中跳到Handler环节,这里虫子用了一个取巧方法,细心的同学已经发现了

 <add verb="*" path="*.xss.aspx" type="BBS.XssCheck.XssHandler,BBS.XssCheck" />

虫子对URL进行了重写,在第二次请求中组建会根据url直接pass掉其他管线方法直接到HttpHanlder中处理。具体处理过程就不赘述了。

还值得一说的地方就是对服务器端控件的check 服务器端的控件获取方法

部分代码 比较丑陋 现在懒得改了 喜欢编程之美的同学自己琢磨着改吧

 int nPageControls = page.Controls.Count;

            System.Collections.Specialized.NameValueCollection controlcollection = new System.Collections.Specialized.NameValueCollection();

            for (int i = 0; i < nPageControls; i++)
            {
                foreach (System.Web.UI.Control control in page.Controls[i].Controls)
                {
                    if (control is Button)
                    {
                        controlcollection.Add(control.ID, ((Button)control).Text);
                    }
                    else if (control is Label)
                    {
                        controlcollection.Add(control.ID, ((Label)control).Text);
                    }
                    else if (control is HtmlAnchor)
                    {
                        controlcollection.Add(control.ID, ((HtmlAnchor)control).HRef);
                    }
                    else if (control is TextBox)
                    {
                        controlcollection.Add(control.ID, ((TextBox)control).Text);
                    }
                    else if (control is HtmlImage)
                    {
                        controlcollection.Add(control.ID, ((HtmlImage)control).Src);
                    }
                    if (mode)
                    {
                        try
                        {
                            if (r.IsMatch(controlcollection[control.ID]))
                            {
                                XssLog(context, 5, control.ID, controlcollection[control.ID]);
                                break;
                            }
                        }
                        catch { }
                    }
                }
            }

 XssControl实现IHttpModule

get、post、head、cookies都在BeginRequest管线事件

 服务器端控件检查是在PostRequestHandlerExecute管线事件

XssHandler实现IHttpHandler

XssWebUtils实现一些通用的web处理方法


大概如此了 欢迎有兴趣的同学发表自己的观点