问题
I have a .Net website with custom error pages configured using the web.config httpErrors
section:
<httpErrors errorMode="Custom" existingResponse="Replace">
<clear/>
<error statusCode="400" path="/page-not-found/" responseMode="ExecuteURL" />
<error statusCode="404" path="/page-not-found/" responseMode="ExecuteURL" />
<error statusCode="500" path="/error/" responseMode="ExecuteURL" />
</httpErrors>
and
<httpRuntime requestValidationMode="2.0" targetFramework="4.5" />
When I visit http://www.example.com/< the site displays the correct "page not found" page, however if I visit http://www.example.com/<a it displays a YSOD with a 500 status code response header.
I have Elmah hooked up and both URLs predictably throw exactly the same error System.Web.HttpException: A potentially dangerous Request.Path value was detected from the client (<).
But why are the two URLs not handled the same? Why is one rewritten to my custom error page, and the other not? I would expect the same behaviour from any exception.
Edit:
I should have mentioned up front that this was an Umbraco project. I thought that this wasn't a contributing factor but I created a barebones .Net project with no dependencies and this worked as expected, i.e. both URLs obeyed the httpErrors configuration. So this must be something Umbraco specific, probably a module.
回答1:
The validate helper method first calls validation for input and then paths.
The default values that are set in the default configuration for the validate helper method when validating input from the default web.config setting located at "syste.web/httRuntime" requestPathInvalidCharactersArray attribute are:
<,>,*,%,&,:,\,?
source: https://msdn.microsoft.com/en-us/library/system.web.configuration.httpruntimesection.requestpathinvalidcharacters(v=vs.110).aspx
As you can see "<" is being treated as an invalid PATH whereas "<a" would be treated as invalid INPUT and that is why you get two behaviors.
If you're curious as to how I figured this out, I just looked at the source code for the validate helper method and followed it back to the source.
[EDIT]
The ValidateInputIfRequiredByConfig Method shows it throwing a 400
[EDIT 2]
public NameValueCollection QueryString
{
get
{
this.EnsureQueryString();
if (this._flags[1])
{
this._flags.Clear(1);
this.ValidateHttpValueCollection(this._queryString, RequestValidationSource.QueryString);
}
return this._queryString;
}
}
Calls to this property hit the ValidateHttpValueCollection can validate the querystring if the validation source is Querystring, which it is in this property.
In this method there is a method called ValidateString. In ValidateString it determines if it's a valid string or not and if not it throws a HttpRequestValidationException
回答2:
After a fair amount of digging, I can see that this was actually caused by a 3rd party module called ClientDependency. Removal of this and the normal behaviour returned but obviously in this case the backoffice will not function properly.
A patch on the project is required and I've submitted this.
Update:
This bug in ClientDependency has been fixed as of v1.8.3
来源:https://stackoverflow.com/questions/28429594/why-do-some-potentially-dangerous-request-path-httpexceptions-ignore-httperror