4

I have an ASP.NET MVC application with Windows Identity Foundation authentication enabled with ADFS as STS. The application is now on .NET 4.5 with MVC 4. When I change the ASP.NET requestValidation from 2.0 to 4.5, I get this error:

A potentially dangerous Request.Form value was detected from the client 
(wresult="<t:RequestSecurityTo...").

I guess this is the redirect from ADFS. How can I fix this?

Arion
  • 31,011
  • 10
  • 70
  • 88
Jaap
  • 2,252
  • 2
  • 20
  • 24

5 Answers5

18

Upgrade your application to use WIF 4.5 included in the framework: http://msdn.microsoft.com/en-us/library/jj157089.aspx

Set RequestValidation to 4.5 mode:

<httpRuntime targetFramework="4.5" requestValidationMode="4.5" />

WIF 4.5 plays nicely with the request validation in ASP.NET 4.5.

klings
  • 963
  • 6
  • 12
  • 1
    THIS! If you scour the web like I did, you'll find the idea of setting requestValidationMode to 2.0 or , or else writing your own validator. This was not necessary! All that was required for me was to set the targetFramework to 4.5 (I didn't even set the requestValidationMode) and it worked. Cheers! – ctb Mar 14 '14 at 22:59
  • I love correct and easy fixes! Thanks a bunch for sharing! – Captain America Sep 18 '15 at 18:11
5

Eugenio guided me to the right direction. But the sample he is refering to is not working anymore in ASP.NET 4.5. As I already commented on his answer, it is resulting in a stackoverflow. This is because requestvalidation is now done when data is requested. So the validation is done when WSFederationMessage.CreateFromFormPost requests the data. This triggers our requestvalidator. And this requestvalidator calls WSFederationMessage.CreateFromFormPost again and so on. After some digging in the WIF code, I have now a slightly modified requestvalidator which is working. Instead of CreateFromFormPost we use CreateFromNameValueCollection (which is also used by CreateFromFormPost), but now we can feed it with Request.Unvalidated.Form.

public class RequestValidator : System.Web.Util.RequestValidator
{
    protected override bool IsValidRequestString(HttpContext context, string value, RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex)
    {
        validationFailureIndex = 0;
        if (requestValidationSource == RequestValidationSource.Form &&
            collectionKey.Equals(WSFederationConstants.Parameters.Result, StringComparison.Ordinal))
        {
            if (WSFederationMessage.CreateFromNameValueCollection(WSFederationMessage.GetBaseUrl(context.Request.Url), context.Request.Unvalidated.Form) as SignInResponseMessage != null)
            {
                return true;
            }
        }
        return base.IsValidRequestString(context, value, requestValidationSource, collectionKey, out validationFailureIndex);
    }
}
Jaap
  • 2,252
  • 2
  • 20
  • 24
  • Thanks @Jaap, your answer saved my day. We were experiencing a stack overflow in a different scenario on a 4.0 site. This was happening if a cached STS url was being it. I changed the function as above to fix it. The only one difference from above was the way to get the unvalidated form object as Request.Unvalidated.Form was not directly available in 4.0. var unvalidatedRequestFormValues = System.Web.Helpers.Validation.Unvalidated(context.Request).Form; – dreamerkumar May 09 '12 at 20:54
  • For anyone on .net 4.5, check out @klings answer, simply set targetFramework to 4.5 in your web.config's httpRuntime element. – ctb Mar 14 '14 at 23:01
  • @ctb, kings answer wasn't working for me too. I had similar code as above but was for .Net 4.0, so was same as what Vishal has mentioned. My code was migrated to .Net 4.6 from .Net 4.0 and answer here worked for me. – GL_monk-342435 Mar 17 '17 at 02:58
3

Yes, this is the SAML token posted back from the STS (ADFS) in your case. You can disable validation as Garrett suggests or better yet, you can supply a proper validator that understands SAML tokens, which is very easy to do.

See this other question/answer: Potentially dangerous Request.Form in WSFederationAuthenticationModule.IsSignInResponse

Community
  • 1
  • 1
Eugenio Pace
  • 14,094
  • 1
  • 34
  • 43
  • Is there perhaps something changed in .NET 4.5 in respect with this? If I implement that requestvalidator, I get an stack overflow exception when the STS redirects back. – Jaap Mar 19 '12 at 15:54
  • When I remove the call to WSFederationMessage.CreateFromFormPost, it is working (but less secure ofcourse). I guess the stackoverflow is cause by the fact that CreateFromFormPost triggers the validator again? – Jaap Mar 19 '12 at 16:06
  • I remember now that I have read somewhere that the form values are only validated when you request them, now in ASP.NET 4.5. So I guess validation is now triggered when WIF reads the form value. That triggers the validation which in turn triggers WIF again to read, and so on. So this sample is not valid anymore for ASP.NET 4.5, I think. Is there another way to validate the value of the wresult form parameter? – Jaap Mar 19 '12 at 16:11
0

We had the same problem, but needed for our validator to continue to be built against 4.0 so that it can be used in either 4.0 or 4.5 environments so we couldn't use the solution that Jaap posted. Our solution was to drop a marker in HttpContext.Items to let us know that a validation is already in progress so that when the nested validation is triggered we can simply let it pass through.


public class WifRequestValidator : RequestValidator
{
    protected override bool IsValidRequestString(HttpContext context, string value, RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex)
    {
        validationFailureIndex = 0;

        if (requestValidationSource == RequestValidationSource.Form && collectionKey.Equals(WSFederationConstants.Parameters.Result, StringComparison.Ordinal))
        {
            if(AlreadyValidating(context))
            {
                return true; // Allows us to bypass check that happens as a result of trying to use context.Request.Form
            }

            StartValidating(context);
            if (IsWsFedSigninResponse(context))
            {
                return true;
            }
            EndValidating(context);
        }

        return base.IsValidRequestString(context, value, requestValidationSource, collectionKey, out validationFailureIndex);
    }

    private static bool AlreadyValidating(HttpContext context)
    {
        return context.Items["__ApprendaRequestValidatorInProgress"] != null;
    }

    private static void StartValidating(HttpContext context)
    {
        context.Items["__ApprendaRequestValidatorInProgress"] = new object();
    }

    private static bool IsWsFedSigninResponse(HttpContext context)
    {
        return WSFederationMessage.CreateFromFormPost(context.Request) as SignInResponseMessage != null;
    }

    private static void EndValidating(HttpContext context)
    {
        context.Items["__ApprendaRequestValidatorInProgress"] = null;
    }
}
Jon Norton
  • 2,969
  • 21
  • 20
0

Note, with 4.5 request validation mode you may still have some additional work to do if your asp.net server side code uses the Request object during siginin (i.e. when SAML token is posted). By default, use of Request.Params will throw when SAML token is posted even with 4.5 request validation mode turned on.

user2368632
  • 990
  • 1
  • 12
  • 33