asp.net mvc webapi cross domain request with web.config customheaders - asp.net

I have a set of webapi which accepts cross domain requests.
So, I have these customheaders setup in web.config
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="*" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
</customHeaders>
This has been working fine with cross domain request for a long time.
Now, I added a new method for an web api endpoint to accept file uploads. I tried to call this webapi from a different domain, and I get a "405 method not allowed" response from the server. The request method is OPTIONS.
Now before anyone closes this as duplicate, let me clarify that I have seen examples with other approach like EnableCors attributes. So, my question is not how to accept cross domain requests. As already mentioned above, I have been accepting cross domain request on other endpoints for quite sometime.
My questions are:
a) Why is the call to this particular endpoint (with OPTIONS method request) ending in a 405 error, while other endpoints work fine? (please note that "Access-Control-Allow-Methods" value has OPTIONS included in value).
b) how to resolve this problem, and get the api call to go successfully? (without going for other approaches like enablecors atribute)

Related

How do I ensure that X-HTTP-Method headers are ignored?

I'm currently applying security fixes for a vulnerability which was found by a third party software. This is the issue (Often Misused: HTTP Method Override vulnerability).
The request from the software was similar to:
POST /Home/ViewProfile HTTP/1.1
Referer: https://somesite.com/Home/ViewProfile?qrystr=blahblah
[...]
X-HTTP-METHOD: PUT
X-HTTP-Method-Override: PUT
X-METHOD-OVERRIDE: PUT
[...]
And the response was:
HTTP/1.1 200 OK
[...]
The web application is not a RESTful API, it's just a an ASP.NET MVC site which only has GET and POST actions.
I have a few questions:
Is this a false positive given the type of app?
By default, does ASP.NET do anything with these headers X-HTTP-Method, X-HTTP-Method-Override, X-METHOD-OVERRIDE if not explicitly told to do so such as in this example?
Regarding the first linked issue above, what is the best way to go about achieving the recommended remediations if they're necessary/applicable based on my case:
"Ensure that only the required headers are allowed, and that the allowed headers are properly configured."
and
"Ensure that no workarounds are implemented to bypass security measures implemented by user-agents, frameworks, or web servers."
Another thing to note is I don't have access to modify IIS settings, but I can modify the Web.Config.
I had the same problem with a scan from my security team. What I did was limiting the size of those requests to zero (0) in the web.config. The server then returns a "HTTP Error 431.0 - Request Header Fields Too Large", effectively blocking the overrides.
</system.webServer>
...
<security>
<requestFiltering>
<requestLimits>
<headerLimits>
<add header="X-Http-Method-Override" sizeLimit="0" />
<add header="X-Method-Override" sizeLimit="0" />
<add header="X-HTTP-Method" sizeLimit="0" />
</headerLimits>
</requestLimits>
...
</requestFiltering>
</security>
...
</system.webServer>
However, I haven't checked yet if this effectively cancels the alert by the security scanner. I suspect it might still show, but I'm ready to report back as a false positive because the server is blocking all calls with those headers. I'll let you know as soon as I get a response from the security team.

ASP.NET CORS blocking font request

I built an ASP.NET Web API service and enabled CORS in that service. This service is used for serving report templates resources (html, image, css, font). The web client loads the template and display report based on downloaded template.
So, given the service enpoint: http://templates.domain.com,
and I try access the service (REST, Image, Font) from a web app (http://client.domain.com), then the web client app will load:
http://templates.domain.com/templates/:templateName
http://templates.domain.com/templates/:templateName/css/style.css
http://templates.domain.com/templates/:templateName/image/header.jpg
http://templates.domain.com/templates/:templateName/font/test.ttf
In the above, the REST API, CSS, and images from the service working well, but the font is blocked/failed.
Font from origin 'http://localhost:49350' has been blocked from
loading by Cross-Origin Resource Sharing policy: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'null'
So far, I've tried the solutions below, but the font is still blocked.
Microsoft.Owin.Cors:
app.UseCors(CorsOptions.AllowAll);
Microsoft.AspNet.WebApi.Cors:
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
Are you using OWIN or WebAPI?
For a AspNet WebAPI the following would allow everything through:
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
</system.webServer>
It is important to point out that allowing "*" is potential security vulnerability as you are saying anyone from anywere can invoke these methods.

Access-Control-Allow-Origin header vs cross domain policy

So I'm reading up on these and am a little confused. I'm using an iframe of a site on another domain. I get No 'Access-Control-Allow-Origin' header is present on the requested resource.” Reading up on this I can just set the header in the web.config. However, I want multiple specific domains and not just the wildcard "*". I was reading up on the cross domain policy. Creating an xml file Is this by any means related or are these two completely different things?
This xml policy
<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="domain1.com"/>
<allow-access-from domain="domain2.com"/>
</cross-domain-policy>
vs this in the web.config
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="site1.com" />
</customHeaders>
</httpProtocol>
</system.webServer>
CORS works by adding a special header to responses from a server to the client. If a response contains the Access-Control-Allow-Origin header, and if the browser supports CORS, then there is a chance you can load the resource directly with Ajax no need for a proxy.
When you set, Access-Control-Allow-Origin value as “site1.com”.
With this configuration, only scripts that originate from http://site1.com are allowed to load resources. Any other domain trying to use Ajax to load resources will be given the standard security error message. In this way, site owners can limit which domains are allowed to load their resources with CORS.
Alternatively, site owners can grant wide-open access with the always ready to party asterisk:
Access-Control-Allow-Origin: *.
Now, any site that wants to load a resource directly using Ajax can do so without getting the browser security error. It's a very helpful technique for modern apps that often load data using JavaScript, and hopefully more modern web APIs will start to support CORS.

Why are OPTIONS requests not arriving in my ASP.NET application?

I can't seem to receive HTTP OPTIONS requests in my IIS6 hosted ASP.NET application. I'm testing it using a debug breakpoint (and file-log) in my Global.asax's Application_BeginRequest method. The breakpoint is never hit and the client gets a HTTP 403 Forbidden, I'm assuming from IIS6 directly (GETs and POSTs work fine btw).
I've tried several things in the web.config, including adding the following line to either and both the <system.webServer><handlers> and <system.web><httpHandlers> sections.
<add name="OptionsHandler" verb="OPTIONS" path="*" type="System.Web.DefaultHttpHandler"/>
I've also played with the <system.webServer><security><requestFiltering><verbs> settings and allowUnlisted="true" and <add verb="OPTIONS" allowed="true"/>.
Also, I'm not using URLScan or any other tools that might intercept the calls. In case you're interested in IISLogs:
2011-07-11 20:26:05 W3SVC1215124377 127.0.0.1 OPTIONS /test.aspx - 80 - 127.0.0.1 Mozilla/5.0+(Windows+NT+5.2;+rv:5.0)+Gecko/20100101+Firefox/5.0 403 1 0
Is there a way to receive OPTIONS request in an ASP.NET Application?
For IIS6, you will have to enable the OPTIONS verb explicitly in the management console, and you will also need to map it to be handlded by ASP .NET. Only then, you will be able to register your handler in <system.web> and get the request processed by ASP .NET.
(Note, <system.webServer> settings only applies to IIS7).

Caching the response of an ASP.NET HTTP Handler server and client side

Is it possible to cache the response of a http handler on the server and on the client?
This doesn't seem to be doing the trick:
_context.Response.Cache.SetCacheability(HttpCacheability.Public);
_context.Response.Cache.SetExpires(DateTime.Now.AddDays(7));
The _context is the HTTPContext passed as an argument to the ProcessRequest method on the IHttpHandler implementation.
Any ideas?
Update: The client does cache images that are loaded through the httphandler, but if another client does the same call, the server hasn't got it cached. So for each client that asks for the image, the server goes to the database (and filestream). If we use a aspx page instead of a httphandler together with a caching profile, then the images are cached both on the client and the server.
With IIS7, this can be done in web.config.
For example, suppose your ashx url is:
/ashxfiles/myhandler.ashx
...and you want to vary by querystring params:
id, lang
Add the following to your web.config:
<location path="ashxfiles">
<system.webServer>
<caching>
<profiles>
<add extension=".ashx" policy="CacheForTimePeriod" duration="00:00:10" varyByQueryString="id, lang" />
</profiles>
</caching>
</system.webServer>
</location>
This rule applies to all .ashx files in the directory, so you might want to put your .ashx files in separate folders if you need more granular control of the cache settings.
Thanks for your answer in the comments.
Cache.SetCacheability is used to define whether a proxy or the client is allowed to cache, not on the server.
Have a look at IIS 7 where it is explained how to cache the output of an HTTP handler at the server.

Resources