2

我的目标是创建一个 IIS 托管模块,它查看请求并从 POST 中过滤掉内容(XSS 攻击、SQL 注入等)。
但是,我现在挂断了实际过滤请求的过程。这是我到目前为止所得到的:

在模块的 Init 中,我将 HttpApplication.BeginRequest 设置为本地事件处理程序。在该事件处理程序中,我设置了以下几行:

if (application.Context.Request.HttpMethod == "POST")
    {
        application.Context.Request.Filter = new HttpRequestFilter(application.Context.Request.Filter);
    }

我还在 application.Context.Response.Filter 上设置了一个 HttpResponseFilter

HttpRequestFilter 和 HttpResponseFilter 是 Stream 的实现。

在响应过滤器中,我进行了以下设置(Stream.Write 的覆盖):

public override void Write(byte[] buffer, int offset, int count)
    {
        var Content = UTF8Encoding.UTF8.GetString(buffer);
        Content = ResponseFilter.Filter(Content);
        _responseStream.Write(UTF8Encoding.UTF8.GetBytes(Content), offset, UTF8Encoding.UTF8.GetByteCount(Content));
    }

ResponseFilter.Filter 是一个简单的 String.Replace,事实上,它确实可以正确地替换文本。

然而,在请求过滤器中,有两个问题。我目前在 RequestFilter 中的代码(Stream.Read 的覆盖):

public override int Read(byte[] buffer, int offset, int count)
{
    var Content = UTF8Encoding.UTF8.GetString(buffer);
    Content = RequestFilter.Filter(Content);
    if (buffer[0]!= 0)
    {
        return _requestStream.Read(UTF8Encoding.UTF8.GetBytes(Content), offset, UTF8Encoding.UTF8.GetByteCount(Content));
    }
    return _requestStream.Read(buffer, offset, count);
}

这有两个问题。首先,过滤器被调用两次,而不是一次,其中一个请求基本上是 /0 的流。(如果检查缓冲区 [0] 目前过滤了这个,但我认为我设置错了)

其次,即使我在读取中正确地使用 .GetString 抓取内容,然后在 RequestFilter.Filter(一个美化的 string.replace())中更改它,当我在 if 语句中返回字节编码的内容时,输入是未修改。

这是我想要弄清楚的:

1)我可以在过滤器之前检查什么,以确保我检查的只是 POST 而不是其他时间被调用?我没有正确设置 Application.Context.Request.Filter 吗?

2)我真的很困惑为什么没有出现将内容重写到_requestStream(我发送给班级的HttpApplication.Context.Request.Filter)。任何关于我做错的事情的意见将不胜感激。

另外,HttpApplication.Request 和 HttpApplication.Context.Request 之间有什么区别吗?

编辑:有关更多信息,我正在一个简单的 .aspx 页面上进行测试,该页面有一个文本框、一个按钮和一个标签,并且在按钮单击时将文本框文本分配给标签的文本。理想情况下,如果我将内容放在应该过滤的文本框中,我的理解是通过拦截和重写帖子,我可以使内容按修改后的方式访问服务器。我已经在模块和代码中使用断点运行测试,并且模块在 .aspx 页面上的代码被命中之前完成。.aspx 页面获取从表单传递的值,并忽略我尝试执行的任何过滤。

4

1 回答 1

0

这里发生了一些问题,但为了将来参考,解释接收未过滤帖子的页面以及被评估两次的过滤器是您可能在设置 Request.Filter 之前以某种方式访问​​请求对象. 这可能会导致它评估输入流,按原样运行当前设置的过滤器链,并返回该流。

例如,简单地访问 Request.Form["something"] 会导致它评估输入流,在那个时间点运行整个过滤器链。在此时间点之后对 Request.Filters 的任何修改都将无效,并且似乎该过滤器被忽略了。

您想做的事情是可能的,而且 ASP.NET 还提供了请求验证来解决其中一些问题 (XSS)。但是,通常通过从不通过字符串连接构造查询来避免 Sql 注入,而不是通过输入清理,尽管深度防御通常是一个好主意。

于 2016-02-23T17:55:24.970 回答