利用 HttpModule,基于输出,统一控制、干预、处理(例如: 过滤关键字、AntiXSS) ASP.Net WebForm Control 展现属性的方案原型




/*

利用 HttpModule 统一干预、处理(例如: 过滤关键字) ASP.Net WebForm Control 的输出渲染

前几天在阅读老赵的《一个较完整的关键字过滤解决方案》上中下,

http://www.cnblogs.com/JeffreyZhao/archive/2008/12/22/filter-forbidden-word-solution.html

当时提出了一个在 HttpModule "输出流"中转"字符串"后利用"替换",实现"基于输出干预处理"的过滤方案,

《HttpModule 实现 ASP.Net (*.aspx) 中文简繁体的自动转换,不用修改原有的任何代码,直接部署即可!》

http://microshaoft.cnblogs.com/archive/2005/12/03/289665.html

我也承认那个方案是有性能问题的。

最近在想一个实现全局解决"跨站脚本攻击"的统一通用干预处理,实现安全输出的方案。

"跨站脚本攻击"的一般解决方案就是在"输出"时,也就是先做"HTML/JavaScript Encode",然后输出 Safe Html/JavaScript。

ASP.Net WebControl 及其属性,有很多其实都不会自动 Encode 后输出的,即不是天然免疫 XSS Attack 的

《What's wrong with ASP.NET? HTML encoding》

http://msmvps.com/blogs/calinoiu/archive/2006/06/13/102957.aspx

《Which ASP.NET Controls Automatically Encodes?》

https://blogs.msdn.com/sfaust/archive/2008/09/02/which-asp-net-controls-automatically-encodes.aspx

《下面是一个很全的 "不安全控件及属性" 的 "黑名单"》

https://blogs.msdn.com/sfaust/attachment/8918996.ashx

我的方案目前还只是一个原型

就是只将 ASP.Net WebForm Sever WebControl/HtmlControl 的一些与"文本展现或输出"相关的属性统一处理的方案

目前在遍历所有控件的过程中,利用反射(性能)只处理了

System.Web.UI.WebControls 命名空间下的控件的"Text"属性

System.Web.UI.HtmlControls 命名空间下的控件的"Value"属性

发现天然能够干预处理程序代码动态 Add 的 Control

漏处理了其他命名的展现相关属性

而且还有一些过多处理了 WebForm Page 默认自动添加的控件的情况,因此还很不完善。

不能处理其他形式的 Response 输出(例如: Response.Write、前代码的<%= 后代码类成员变量%>),

自定义的 UserControl、WebCustomControl 的控件如果非"Text"或"Value"命名的展现属性也无法处理,

当然也有可能误伤与展现无关的"Text"或"Value"属性。

该方案逐步完善后,理论上,应该能"忽略"掉不必处理的控件及属性,而且还要按不安全"控件及其属性"的各种情况,分别处理,还是有一定的工作量。

另外性能尚未评估,遍历控件可能存在一定瓶颈,

其实我认为使用 HttpModule.dll、HttpHandler.dll、Global.asax 本身也存在一些性能瓶颈,因为所有的请求与输出都要流经此处。

以下完整代码

ControlsPropertyFilterHttpModule.cs

web.config

test.aspx (注意有XSS Attack 测试代码,不必惊慌只是 alert)

*/

//ControlsPropertyFilterHttpModule.cs

namespace Microshaoft

{

    using System;

    using System.Web;

    using System.Web.UI;

    using System.Reflection;

    public class ControlsPropertyFilterHttpModule : IHttpModule

    {

        private HttpApplication _contextApplication;

        public void Init(HttpApplication context)

        {

            _contextApplication = context;

            _contextApplication.PostMapRequestHandler += new EventHandler(_contextApplication_PostMapRequestHandlerProcess);

        }

        public void Dispose()

        {

            _contextApplication = null;

            _contextApplication.Dispose();

        }

        public void _contextApplication_PostMapRequestHandlerProcess(object sender, EventArgs e)

        {

            IHttpHandler handler = null;

            if (_contextApplication == null)

            {

                return;

            }

            if (_contextApplication.Context.Handler is Page)

            {

                handler = _contextApplication.Context.Handler;

            }

            if (handler != null)

            {

                Page page = handler as Page;

                //page.PreRender += new EventHandler(page_PreRender);

                page.PreRenderComplete += new EventHandler(page_PreRender);

            }

        }

        private void page_PreRender(object sender, EventArgs e)

        {

            Page page = sender as Page;

            ControlCollection cc = page.Controls;

            RecursiveProcessControls(cc);

        }

        private static void RecursiveProcessControls(ControlCollection cc)

        {

            foreach (Control c in cc)

            {

                Type t = c.GetType();

                //需要按控件种类分情况处理各种文本显示相关的属性

                //目前只处理 Text 和 Value 属性

                PropertyInfo pi = t.GetProperty("Text"); //Server WebControls

                if (pi != null)

                {

                    string s = (string) (pi.GetValue(c, null));

                    s = string.Format("Microshaoft处理了[{0}]", s);

                    //s = HttpUtility.HtmlEncode(s); //AntiXSS

                    pi.SetValue(c, s, null);

                }

                pi = t.GetProperty("Value"); //Server HtmlControls

                if (pi != null)

                {

                    string s = (string) (pi.GetValue(c, null));

                    s = string.Format("Microshaoft处理了[{0}]", s);

                    //s = HttpUtility.HtmlEncode(s); //AntiXSS

                    pi.SetValue(c, s, null);

                }

                if (c.HasControls())

                {

                    RecursiveProcessControls(c.Controls);

                }

            }

        }

    }

}






//test.aspx

<%@ Page language="c#" AutoEventWireup ="true"%>

<%@ Import Namespace="System.Data" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >

<HTML>

 <HEAD>

 <title>WebForm1</title>

 <meta name="generator" content="editplus" />

 <meta name="author" content="" />

 <meta name="keywords" content="" />

 <meta name="description" content="" />

 <script language="C#" runat="server">

    protected void Page_Load(object sender, EventArgs ea) 

    {

        h1.Text += "<script>alert('HL Xss Attack')" + "</scr" + "ipt>";

        DataTable dt = MakeTable("F1","F2");

        string expression = "1 = 1 or f1 = '2'"; 

        DataView dv = dt.DefaultView; 

        dv.Sort = "f1 desc"; 

        dv.RowFilter = expression; 

        datagrid1.DataSource = dv;

        datagrid1.DataBind();

        gridview1.DataSource = dv;

        gridview1.DataBind();

        TextBox tb = new TextBox();

        tb.Text = "动态 TextBox";

        p1.Controls.Add(tb);

    }

    void datagrid1_ItemDataBound(object sender, DataGridItemEventArgs e) 

    {

/// foreach (TableCell cell in e.Item.Cells)

/// {

/// if (cell.Text != string.Empty)

/// {

/// cell.Text = HttpUtility.HtmlEncode(cell.Text);

/// }

/// }

    }

    void gridview1_RowDataBound(object sender, GridViewRowEventArgs e) 

    {

/// foreach (TableCell cell in e.Row.Cells)

/// {

/// if (cell.Text != string.Empty)

/// {

/// cell.Text = HttpUtility.HtmlEncode(cell.Text);

/// }

/// }

    }

    private static DataTable MakeTable

                        (

                            string c1Name

                            , string c2Name

                        )

    {

        DataTable table= new DataTable();

        DataColumn column = new DataColumn(c1Name, typeof(int));

        table.Columns.Add(column);

        column = new DataColumn(c2Name, typeof(string));

        table.Columns.Add(column);

        table.Rows.Add(1,"<script>alert('datagrid xss attack')</scr" + "ipt>");

        table.Rows.Add(2, "\u003c" + "scr" + "ipt\u003ealert\u0028\u0022gridview XSS \u0041ttack\u0022\u0029\u003c/script\u003e");

        return table;

    }

    </script>

 </HEAD>

 <body MS_POSITIONING="GridLayout">

 <form id="Form1" method="post" runat="server">

 <asp:TextBox ID="tb1" Text="静态 textBox" runat="server" />

 <asp:Label ID="l1" Text="静态 label" runat="server" />

 <asp:Panel id="p1" runat="server"/>

 <asp:Hyperlink ID="h1" NavigateUrl="http://www.baidu.com" runat="server">

 百度 Hyperlink<script>alert('HL Xss Attack')</script>

 </asp:Hyperlink>

 <input ID="Value2" Type="Text" Value="静态 HtmlControls HtmlInputText" runat="server"/>

 <asp:ListBox ID="lb1" Width="" runat="server">

 <asp:ListItem><script>alert('LB Xss Attack')</script></asp:ListItem>

 <asp:ListItem></asp:ListItem>

 </asp:ListBox>

 <ASP:DataGrid ID="datagrid1" runat="server"

                AutoGenerateColumns="True"

                OnItemDataBound = "datagrid1_ItemDataBound"

            />

 <ASP:GridView ID="gridview1" runat="server"

                AutoGenerateColumns="True"

                OnRowDataBound = "gridview1_RowDataBound"

            />

 </form>

 </body>

</HTML>



你可能感兴趣的:(asp.net)