For content security policy how do I allow self and a static url as well as unsafe JS? - http-headers

I am trying to configure this in an ASP.NET MVC application in the web.config as follows:
<nwebsec>
<httpHeaderSecurityModule xmlns="http://nwebsec.com/HttpHeaderSecurityModuleConfig.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="NWebsecConfig/HttpHeaderSecurityModuleConfig.xsd">
<securityHttpHeaders>
<content-Security-Policy-Report-Only enabled="true">
<default-src self="true">
<add source="https://static.mydomain.com" />
<add source="unsafe-inline" />
<add source="unsafe-eval" />
</default-src>
</content-Security-Policy-Report-Only>
</securityHttpHeaders>
</httpHeaderSecurityModule>
</nwebsec>
which means I end up with a header that looks as follows:
default-src 'self' https://static.mydomain.com unsafe-inline unsafe-eval
but this is still failing my page because inline scripts are not allowed. I am guessing I want my header to look like:
default-src 'self unsafe-inline unsafe-eval' https://static.ozcruising.com.au
So my question is how do I change my NWebSec configuration to allow inline scripts to be allowed from the page itself (same origin) as well as support serving content from https://static.mydomain.com?

Unsafe-inline is only relevant for script-src and style-src and unsafe-eval is only relevant for script-src. Thus these cannot be configured at the default-src level. You have to do it this way:
<default-src self="true">
<add source="https://static.mydomain.com" />
</default-src>
<script-src self="true" unsafeInline="true" unsafeEval="true">
<add source="https://static.mydomain.com" />
</script-src>
<style-src self="true" unsafeInline="true">
<add source="https://static.mydomain.com" />
</style-src>
You have to specify self and static.mydomain.com again in script-src and style-src because more specific *-src clears everything default-src had specified.

Related

Filepond http uploading files IIS server setup problem 405

I'm trying to get a uploading script running, filepond, uploading files through webpage. On IIS10, on co-located server.
When uploading, using POST, I get the following error:
HTTP Error 405.0 - Method Not Allowed
The page you are looking for cannot be displayed because an invalid method (HTTP verb) is being used.
in details:
Module DirectoryListingModule
Notification ExecuteRequestHandler
Handler StaticFile
Error Code 0x80070001
Requested URL https://www.example.com:443/upl/files/
Physical Path W:\www.example.com\www\upl\files\
Logon Method Anonymous
Logon User Anonymous
Request Tracing Directory C:\inetpub\logs\FailedReqLogFiles
port 443 is open.
The folder has the following web.config:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<handlers accessPolicy="Read, Write, Execute, Script">
<remove name="StaticFile" />
<add name="StaticFile" path="*" verb="GET,HEAD,POST,DEBUG" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Write" />
</handlers>
</system.webServer>
</configuration>
The folder has the following attributes:
IIS > site > folder > configuration Editor > system.webServer/handlers
FROM SITE/upl/files Web.config > accesPolicy: Read, Write, Execute, Script
FROM SITE/upl Web.config > accesPolicy: Read, Execute, Script (no solution when adding "Write")
FROM ApplicationHost.config accesPolicy: "Read, Execute, Script"
Athentication: Anonymous Athentication status enabled, rest disabled
Handler Mappings > Static File
Path: *, State: enabled,
PathType: File or Folder,
Handler: StaticFileModule,DefaultDocumentModule,DirectoryListingModule,
Entry Type: Local
EDIT > Request Restrictions > Mapping : selected Invoke handler only if request is mapped to File or folder, Verbs: GET,HEAD,POST,DEBUG,
Access: Write ( I dont understant why there is no Read/Write option, only read / write / script / execute )
Properties > security >
even when giving full control on that folder to Everyone + IUSR + IIS_IUSRS + Users : still same error.
I did notice in Handler Mappings there is no *.js record.
In Handler Mappings changing the *.asp > edit > "file" to "file and folder" had no effect either.
Jic: I could not find Filepond using a temp folder that I forgot to give acces rights to.
Jic; these are my present FilePond server settings:
FilePond.setOptions({
server: {
url: 'https://www.example.com/upl/',
timeout: 3000,
process: {
url: 'files/',
method: 'POST',
headers: {
'x-customheader': 'Hello World',
},
withCredentials: false,
onload: (response) => response.key,
onerror: (response) => response.data,
ondata: (formData) => {
formData.append('Hello', 'World');
return formData;
},
},
revert: './revert',
restore: './restore/',
load: './load/',
fetch: './fetch/',
}
});
I looked at all the previous answers here and elsewhere for over a day now, but seem to miss a tiny vital thing. Any help is very much appreciated !!
Alex
------------ replying to Samwu:
Thank you for helping.
The above represents most of the solutions I looked at.
I followed the link, found this earlier and here are some findings:
the client makes a Hypertext Transfer Protocol (HTTP) request by using an HTTP method that doesn't comply with the HTTP specifications.
In the ApplicationHost.config file, Make sure that all the handlers use valid HTTP methods.
from my applicationHost.config:
<handlers accessPolicy="Read, Execute, Script">
<add name="ASPClassic" path="*.asp" verb="GET,HEAD,POST" modules="IsapiModule" scriptProcessor="%windir%\system32\inetsrv\asp.dll" resourceType="File" />
<add name="StaticFile" path="*" verb="GET,POST" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Write" />
</handlers>
<sectionGroup name="webdav">
<section name="globalSettings" overrideModeDefault="Deny" />
<section name="authoring" overrideModeDefault="Deny" />
<section name="authoringRules" overrideModeDefault="Deny" />
</sectionGroup>
all the modules are stated in applicationHost.config modules
I did notice however something: in the www root there is a web.config that says:
<remove name="ASPClassic" />
<remove name="StaticFile" />
<add name="StaticFile" path="*" verb="GET,HEAD,POST,DEBUG" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Script" />
<add name="ASPClassic" path="*.asp" verb="GET,HEAD,POST" modules="IsapiModule" scriptProcessor="%windir%\system32\inetsrv\asp.dll" resourceType="Either" requireAccess="Script" />
</handlers>
in the upl / files / dir there is a webconfig saying:
<system.webServer>
<handlers accessPolicy="Read, Write, Execute, Script">
<remove name="StaticFile" />
<add name="StaticFile" path="*" verb="GET,HEAD,POST,DEBUG" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Write" />
</handlers>
</system.webServer>
notice the " requireAccess="Script" instead of Write
"Send the POST request to a page that's configured to be handled by a handler other than the StaticFile handler. For example, the ASPClassic handler. "
I assume that if my filepond js module is included in a .asp page that this is what I am all ready doing.
WebDav is not installed, it is still stated in the applicationHost.config. Removing that gives an error on restarting the site in IIS.
I hope that clearifies.

How can I enable cors when using signalR in asp.net mvc?

I use signalR in asp.net mvc for web api and I need to enable cors in web.config.
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="GET, PUT, POST, DELETE, HEAD, OPTIONS" />
<add name="Access-Control-Allow-Credentials" value="true"/>
<add name="Access-Control-Allow-Headers" value="X-Requested-With, origin, content-type, accept" />
But when I'm going to connect to signalR, it displays the following error:
has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include
Follows the code to the startup.cs:
[EnableCors("CorsPolicy")]
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
How can I fix it?
As your error says:
The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*'.
And you have:
<add name="Access-Control-Allow-Origin" value="*" />
So in this case you should provide the origin from where you are connecting. If you are trying to connect from the front-end you can use this as an example:
<add name="Access-Control-Allow-Origin" value="https://localhost:4200"/>

Set default webpage in vb.Net web-project

I have a class api, and a function test in my web-project. To call this function, I type the link http://localhost/api/test in my browser. Now my question is it possible to call a default page, for example index.html, if i just call the class without the function like: http://localhost/api ?
"I doesn't use ASP.Net"
I solved the problem with a redirect with the following code in my web.config file.
<configuration>
<system.webServer>
<httpRedirect enabled="true" exactDestination="true" httpResponseStatus="Found">
<add wildcard="*api" destination="/index.htm" />
<add wildcard="*api/" destination="/index.htm" />
</httpRedirect>
</system.webServer>
</configuration>

How to gzip static content in ASP.NET Core in a self host environment

Is there are way to serve gzip static cotent when using self host environment to publish an ASP.NET Core website?
[Edit 2016-11-13]
There is another way to serve gzipped files that replaces steps 2 and 3. It's basically quite the same idea, but there is a nuget package that does it all for you readily available. It basically checks if the is .gz or .br file that matches the requested one. If it exists it returns it with the appropriate headers. It does verify that the request has a header for the corresponding algorithm. Github code if you want to compile it yourself is here.
There is also an issue to support that in the official repository, so I really hope Microsoft will have the standard plugin to do that, since it's rather common and logical to use that nowadays.
I think I have found the most optimized way of serving the compressed content. The main idea is to pre-compress the files and since the default ASP.NET 5 way is to use gulp to build js, it is as easy to do as this:
1. Add a gulp step to gzip the bundled libraries:
gulp.task("buildApplication:js", function () {
return gulp.src(...)
...
.pipe(gzip())
...
});
This will produce something like libraries.js.gz in your bundles folder
2. Refernce the libraries.js.gz instead of libraries.js in the cshtml file
3. Amend the static file handler to fix the returned headers
We need to add Content-Encoding and change the Content-Type from default application/x-gzip to application/javascript because not all browsers are smart enough to read js properly from x-gzip
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = context =>
{
if (headers.ContentType.MediaType == "application/x-gzip")
{
if (context.File.Name.EndsWith("js.gz"))
{
headers.ContentType = new MediaTypeHeaderValue("application/javascript");
}
else if (context.File.Name.EndsWith("css.gz"))
{
headers.ContentType = new MediaTypeHeaderValue("text/css");
}
context.Context.Response.Headers.Add("Content-Encoding", "gzip");
}
}
});
Now all there is no CPU cycles to waste to gzip the same content all the time and it's the best possible performance in serving the files. To improve it even further all of js has to be bunlded and minified before gzipping. Another upgrade is to set CacheControl max age in the same OnPrepareResponse to cache for one year and add asp-append-version="true" in the cshtml.
P.S. If you will host behind IIS you might need to turn off the static compression of js and css not to double compress, I am not sure how it will behave in this situation.
This is a fixed version of method 3 from Ilyas answer that works with ASP.NET Core 1 RTM, and it serves pre-zipped javascript files:
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = context =>
{
IHeaderDictionary headers = context.Context.Response.Headers;
string contentType = headers["Content-Type"];
if (contentType == "application/x-gzip")
{
if (context.File.Name.EndsWith("js.gz"))
{
contentType = "application/javascript";
}
else if (context.File.Name.EndsWith("css.gz"))
{
contentType = "text/css";
}
headers.Add("Content-Encoding", "gzip");
headers["Content-Type"] = contentType;
}
}
});
#Ilya's Answer is very good but here are two alternatives if you are not using Gulp.
ASP.NET Core Response Compression Middleware
In the ASP.NET Core BasicMiddlware repository, you can find (at time of writing) a pull request (PR) for Response Compression Middleware. You can download the code and add it to you IApplicationBuilder like so (at time of writing):
public void Configure(IApplicationBuilder app)
{
app.UseResponseCompression(
new ResponseCompressionOptions()
{
MimeTypes = new string[] { "text/plain" }
});
// ...Omitted
}
IIS (Internet Information Server)
IIS (Internet Information Server) has a native static file module that is independent of the ASP.NET static file middleware components that you’ve learned about in this article. As the ASP.NET modules are run before the IIS native module, they take precedence over the IIS native module. As of ASP.NET Beta 7, the IIS host has changed so that requests that are not handled by ASP.NET will return empty 404 responses instead of allowing the IIS native modules to run. To opt into running the IIS native modules, add the following call to the end of Startup.Configure.
public void Configure(IApplicationBuilder app)
{
// ...Omitted
// Enable the IIS native module to run after the ASP.NET middleware components.
// This call should be placed at the end of your Startup.Configure method so that
// it doesn't interfere with other middleware functionality.
app.RunIISPipeline();
}
Then in your Web.config use the following settings to turn on GZIP compression (Note that I included some extra lines to compress things like .json files which are otherwise left uncompressed by IIS):
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<!-- httpCompression - GZip compress static file content. Overrides the server default which only compresses static
files over 2700 bytes. See http://zoompf.com/blog/2012/02/lose-the-wait-http-compression and
http://www.iis.net/configreference/system.webserver/httpcompression -->
<!-- minFileSizeForComp - The minimum file size to compress. -->
<httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files" minFileSizeForComp="1024">
<scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll" />
<dynamicTypes>
<add mimeType="text/*" enabled="true" />
<add mimeType="message/*" enabled="true" />
<add mimeType="application/x-javascript" enabled="true" />
<!-- Compress XML files -->
<add mimeType="application/xml" enabled="true" />
<!-- Compress JavaScript files -->
<add mimeType="application/javascript" enabled="true" />
<!-- Compress JSON files -->
<add mimeType="application/json" enabled="true" />
<!-- Compress SVG files -->
<add mimeType="image/svg+xml" enabled="true" />
<!-- Compress RSS feeds -->
<add mimeType="application/rss+xml" enabled="true" />
<!-- Compress Atom feeds -->
<add mimeType="application/atom+xml" enabled="true" />
<add mimeType="*/*" enabled="false" />
</dynamicTypes>
<staticTypes>
<add mimeType="text/*" enabled="true" />
<add mimeType="message/*" enabled="true" />
<add mimeType="application/x-javascript" enabled="true" />
<add mimeType="application/atom+xml" enabled="true" />
<add mimeType="application/xaml+xml" enabled="true" />
<!-- Compress ICO icon files (Note that most .ico files are uncompressed but there are some that can contain
PNG compressed images. If you are doing this, remove this line). -->
<add mimeType="image/x-icon" enabled="true" />
<!-- Compress XML files -->
<add mimeType="application/xml" enabled="true" />
<add mimeType="application/xml; charset=UTF-8" enabled="true" />
<!-- Compress JavaScript files -->
<add mimeType="application/javascript" enabled="true" />
<!-- Compress JSON files -->
<add mimeType="application/json" enabled="true" />
<!-- Compress SVG files -->
<add mimeType="image/svg+xml" enabled="true" />
<!-- Compress EOT font files -->
<add mimeType="application/vnd.ms-fontobject" enabled="true" />
<!-- Compress TTF font files - application/font-ttf will probably be the new correct MIME type. IIS still uses application/x-font-ttf. -->
<!--<add mimeType="application/font-ttf" enabled="true" />-->
<add mimeType="application/x-font-ttf" enabled="true" />
<!-- Compress OTF font files - application/font-opentype will probably be the new correct MIME type. IIS still uses font/otf. -->
<!--<add mimeType="application/font-opentype" enabled="true" />-->
<add mimeType="font/otf" enabled="true" />
<!-- Compress RSS feeds -->
<add mimeType="application/rss+xml" enabled="true" />
<add mimeType="application/rss+xml; charset=UTF-8" enabled="true" />
<add mimeType="*/*" enabled="false" />
</staticTypes>
</httpCompression>
<!-- Enable gzip and deflate HTTP compression. See http://www.iis.net/configreference/system.webserver/urlcompression
doDynamicCompression - enables or disables dynamic content compression at the site, application, or folder level.
doStaticCompression - enables or disables static content compression at the site, application, or folder level.
dynamicCompressionBeforeCache - specifies whether IIS will dynamically compress content that has not been cached.
When the dynamicCompressionBeforeCache attribute is true, IIS dynamically compresses
the response the first time a request is made and queues the content for compression.
Subsequent requests are served dynamically until the compressed response has been
added to the cache directory. Once the compressed response is added to the cache
directory, the cached response is sent to clients for subsequent requests. When
dynamicCompressionBeforeCache is false, IIS returns the uncompressed response until
the compressed response has been added to the cache directory.
Note: This is set to false in Debug mode to enable Browser Link to work when debugging.
The value is set to true in Release mode (See web.Release.config).-->
<urlCompression doDynamicCompression="true" doStaticCompression="true" dynamicCompressionBeforeCache="false" />
</system.webServer>
</configuration>
You could implement an action filter that compresses the contents of the response if the client supports it.
Here is an example from MVC5. You should be able to modify that to work with MVC 6:
http://www.erwinvandervalk.net/2015/02/enabling-gzip-compression-in-webapi-and.html

Enable CORS in Azure web

What I´m trying to do is to enable CORS (Cross-origin Resource Sharing) for .net MVC 5 Azure website when calling a https service (not my own) from my JavaScript.
I always get the same error
XMLHttpRequest cannot load https://someservice-I-have-no-control-over. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://my.azurewebsites.net' is therefore not allowed access. The response had HTTP status code 400.
I have managed to enable this when developing locally, setting my project to https and adding the following to web.config
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="GET, POST, OPTIONS"/>
<add name="Access-Control-Allow-Headers" value="Content-Type, Accept, SOAPAction"/>
<add name="Access-Control-Max-Age" value="1728000"/>
</customHeaders>
</httpProtocol>
</system.webServer>
That adds the 'Access-Control-Allow-Origin' header. But that does not seem to work on the Azure website.
And I can´t find any settings like in the Mobile Services where you can allow this like you see here.
Since I know you are all going to ask for code (that works locally btw) there you have the simple Jquery call to the service
$.ajax({
url: 'https://someservice-I-have-no-control-over',
dataType: 'json',
contentType: 'application/json',
type: 'GET',
success: function (response) {
$.each(response, function (key, value) {
console.log("success"); //Doesn´t happen! :-(
});
},
error: function (xhr, text, error) {
if ($.isFunction(onError)) {
onError(xhr.responseJSON);
}
}
});
So any thoughts?
Edit 1
Just to clarify a little.
I am calling a service that I have no control over that is a https one, in a javascript (not a controller) that is mine.
Edit 2
Ok I thought that I could intercept the response from the third party service and add this header before the browser rejects it. As I see it that is not possible (right?). But how come it works locally?
If I capture the call to this service with e.g LiveHTTPHeaders I get the following response where there is not a "Access-Control-Allow-Origin" restriction (so way does it work locally?).
Request (to https://someservice-I-have-no-control-over.com)
GET /someservice-I-have-no-control-over/SomeAction/44 HTTP/1.1
Host: someservice-I-have-no-control-over.com
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:37.0) Gecko/20100101 Firefox/37.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
If-None-Match: "53867cff-96b0-411f-88b7-d84765f9f8e8"
Cache-Control: max-age=0
Reply
HTTP/1.1 304 Not Modified
Cache-Control: max-age=900
Server: Microsoft-IIS/8.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Date: Tue, 24 Feb 2015 11:06:53 GMT
Not possible.
It works locally because it's the server that must have the allow headers, and when you call your own webserver from your javascript you can add those headers.
When you call the real website they do probably not add the CORS allow header (Access-Control-Allow-Origin) and your request is therefore denied.
What you could do is either to use JSONP or proxy all requests through your own website.
You could for instance use my CORS proxy: https://github.com/jgauffin/corsproxy. It's intended usage is for IE9 and below, but works just as fine for all requests.
WebApiConfig I set it the WebApiConfig class and it worked. I also had issues on Azurewebsites when trying to set it via web.config.
Try this in WebApiConfig:
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
You can edit the "", "", "*" if you don't want to allow everything.
If you're using Owin, you can do this in the Startup.cs file:
app.UseCors(CorsOptions.AllowAll);
Use this if and only if you intentionally plan to expose your API to all origins and headers.
Else, you can try it this way by decorating your controller or specific methods:
[EnableCors(origins: "http://someCallingService", headers: "*", methods: "*")]
Check out THIS article
I addressed this by installing the following package:
Microsoft.AspNet.WebApi.Cors
...then using the Config.EnableCors() as described above and altering my web.config transform:
In WebApiConfig.cs:
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
config.EnableCors();
// Continue configuration as you wish...
}
Then, in the web.config transform, in my case named web.PPE.config because it's for Pre-Production:
<system.webServer>
<httpProtocol>
<!-- custom headers necessary for CORS -->
<customHeaders xdt:Transform="Replace">
<clear /> <!-- the clear here is important! -->
<add name="Access-Control-Allow-Origin" value="http://url-that-is-allowed-to-communicate-with-this-server.com" />
<!-- must match server DNS address or SignalR can't communicate with Hub remotely -->
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
<add name="Access-Control-Allow-Credentials" value="true" />
</customHeaders>
</httpProtocol>
</system.webServer>
YMMV on whether to include the Allow-Credentials option. I found that necessary with my need, which was to enable access to a SignalR hub on a remote Azure webserver/app instance.
Good luck!