views:

435

answers:

3

I'm converting an old classic asp website to asp.net.

The application is basically an extension of a tool set for a given set of users but it is hosted at an external vendor.

To perform a seamless transfer to this application it POSTS some xml data which is firing off the "potentially dangerous Request.Form value". I know I could turn off the validateRequest flag but I would rather not do this.

I have written an httpmodule which takes this data and uses it to authenticate the user, is it possible to use the same module, or a different module for that matter, to remove these "bad" values in the post data before that data is "validated"?

Otherwise if none of these ideas work, I am open to other suggestions.

Thanks.

A: 

I'd be tempted to factor out the poor pattern of placing XML data in a field post via HTML Form. I understand you want to port "seamlessly" which I take it means you want to be able to maintain both ASP and ASPX pages for a time. However in this case you should consider changing both the form and the action target of the form at the same time.

I guess the this is similar to advice I gave here. Only in this case the situation is worse in that the pattern of code in the original ASP falls short of the desirable, even within the limitations of classic ASP.

If you don't want to completely port the ASP form and its action page at the same time then consider modifying the ASP page to use XHR to post the XML to an ashx that places the XML somewhere safe and returns a GUID. Place the returned GUID in a hidden field instead of the field that held the XML originally. In the receiving ASPX page use the GUID to retrieve the previously posted XML.

AnthonyWJones
The application which is posting the data I have no control over. I do plan on transitioning the entire vendor application from asp to aspx though. I am waiting for a response on it and am hoping that I may be able to have the form action changed but I am unsure exactly how flexible the department will be.
Dave
A: 

Sounds like a lot of hassle. What's so bad about about using the validateRequest flag a page level?

Just make sure you sanitise the input correctly and encode it if you need to store it anywhere and/or make sure you don't spit back the field to the browser without encoding it.

Alex
since the client can post these credentials to any page I would need to turn off validate request for each page
Dave
I was going to suggest an filter on the input stream but that has its own set of headaches to deal with. CptSkippy has a good solution!
Alex
+3  A: 

Yes. The following class implements the IHttpModule Interface and registers and event that will fire before the HttpRequestValidationException check occurs. It checks that the request is a POST and that "testinput" is not null and then HTML Encodes it. The Class needs to be registered in your Web.config as an httpModule.

class...

using System;
using System.Collections.Specialized;
using System.Reflection;
using System.Web;

public class PrevalidationSanitizer : System.Web.IHttpModule
{
    private HttpApplication httpApp;

    public void Init(HttpApplication httpApp)
    {
        this.httpApp = httpApp;
        httpApp.PreRequestHandlerExecute += new System.EventHandler(PreRequestHandlerExecute_Event);
    }

    public void Dispose() { }

    public void PreRequestHandlerExecute_Event(object sender, System.EventArgs args)
    {
        NameValueCollection form = httpApp.Request.Form;

        Type type = form.GetType();

        PropertyInfo prop = type.GetProperty("IsReadOnly", BindingFlags.Instance 
            | BindingFlags.IgnoreCase | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy);

        prop.SetValue(form, false, null);

        if (httpApp.Request.RequestType == "POST" != null 
            && httpApp.Request.Form["testinput"])
                httpApp.Request.Form.Set("testinput"
                    , httpApp.Server.HtmlEncode(httpApp.Request.Form["testinput"]));
    }
}

web.config entry...

<system.web>
  <httpModules>
    <add type="PrevalidationSanitizer" name="PrevalidationSanitizer" />
...
CptSkippy
Ah, that's clever! I didn't know you could make the form object writeable like that. I guess the solution for Dave's problem would be to parse the security credentials and remove them from the Form collection object using Form.Remove()
Alex
how nice, marking this as answer, however I've not tested it myself
Dave
I tested this and it worked like a charm however I've never done modification of read-only objects like this before so I'm not sure of the consequences of doing so however I suspect that the collections in the request are made read-only by nature of what they are and not because they need to be.
CptSkippy