X-FRAME-OPTIONS set to deny but still opening iframes in clickjackers - node.js

I am trying to avoid clickjacking for the application. So, I set the x-frame-options header to deny but it is still opening iframes and any clickjack testing sites.
app.all('*', (req, res, next) => {
console.log('Before processing - ', req.url, req.method);
res.header('Access-Control-Allow-Credentials', true);
res.header('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0');
res.header('Access-Control-Allow-Origin', req.headers.origin);
res.header('Strict-Transport-Security', 'maxAge=100000');
res.header('X-Frame-Options', 'DENY');
res.header('Content-Security-Policy', "frame-ancestors 'none'");
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Cookies, cookies, x-access-token, Origin, Content-Type, Accept');
return next();
});

Try to set your X-Frame-Options header using npm package helmet. Run npm install helmet --save in your app. And in your server file make these changes:
const express = require("express");
const helmet = require("helmet");
const app = express();
app.use(helmet());
Now to set X-Frame-Options as DENY, Add:
app.use(helmet.frameguard({ action: 'deny' }));
For more details, see https://helmetjs.github.io/docs/frameguard/. This setting denies all <iframe> content.

Sorry for interfere, but all works as intented, see https://repl.it/#egranty/Test-for-Anita.
After push green start button the NodeJS sanbox is started. Test page can be opened in a separate tab and be insetred into https://www.lookout.net/test/clickjack.html or https://clickjacker.io/test?url=https://test-for-anita--egranty.repl.co/.
Here is results in Chrome:
Note that if are published both X-Frame-Options and Content-Security-Policy: frame-ancestors at the same time, the last one overrides the X-Frame-Options in the modern browsers except Safari.
That's why browser console shows lock in the frame-ancestors 'none', but not in the X-Frame-Options.
So, you have a work NodeJS code, a work clickjacking test tools and as we can observe, X-FRAME-OPTIONS / CSP frame-ancestors definitely prohibits embedding pages.
May be some browser plugins interfere or it need to clear browser cache. But I think your nodeJS installation is broken and you need to reinstall it.

Related

Content Security Policy issues with new form

What is the easiest way for me to set the content security policy for a new form I am using? I have a frontend to backend form working for my registration but this form is a lot more complicated and is throwing me the errors below. I am aware this is to do with webpack and I have tried inserting code into my publ;ic index.html file which just stopped the page from rendering.
Would this have anything to do with my CORS settings in the backend? I have the below code which references headers and the I have been getting error messages about setting headings in other forms that I am having the same issues with.
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header(
'Access-Control-Allow-headers',
'Origin, X-Requested-With, Content-Type, Accept',
);
next();
});
The errors described have nothing to do with your CORS settings in the backend. They are related to CSP (Content-Security-Policy) header, which you, it would seem, do not use. But for nonexistent pages node JS is published CSP header on its own.
Pay attention to status code 404 Not Found. If you do not handle this kinds of errors, nodeJS uses own finalhandler to carry out of those by default.
Last versions of this finalhandler publish the CSP default-src 'none'; all the nitty-gritty is here.
Looks like you do not serve routes to root / folder in you server config, therefore /favicon.ico and similar urls are not found -> finalhandler publishes default-src 'none'; -> you observe CSP violation in the browser console (along with the 404 not found messages).
You have to add into server.js something like that:
app.use(express.static('client/public'));
app.get("/favicon.ico", (req, res) => {
res.sendFile(path.resolve(__dirname, "/favicon.ico"));
});
The above will solve the issue with "/favicon.ico Not Found", for other "non existent" Urls you need to add routes too.

How to configure Content-Policy-Security header on ExpressJs app?

I'm want to create a link in my website who download a PDF file but I get a white window with:
Cannot GET /file
and a Content Security Policy (CSP) error:
Content Security Policy: The page settings prevented a resource from loading at inline ("default-src").
I use ExpressJs and Nginx for the back-end.
I've tried to set CSP default-src header like this in my app.js file:
//Headers setup
app.use((req, res, next) => {
res.setHeader('Content-Security-Policy',"default-src 'self' https://www.mydomain.fr");
next();
});
i've also tried to add this in my .conf file in Nginx:
add_header Content-Security-Policy "default-src 'self';" always;
It is still not working. Do you have any idea what is wrong?
My router:
const express = require('express');
const router = express.Router();
const fileController = require('../controllers/file');
router.get('/', fileController.getFile);
module.exports = router;
My controller:
const path = require('path');
exports.getFile = (req, res, next) => {
res.set({'Content-Type':'application/pdf'});
res.set({'Content-Disposition':'attachment, filename=file.pdf'});
const filePath = path.join(__dirname, '/public/documents/file.pdf');
res.download(filePath, 'file.pdf', (e) => {res.status(404).json({e: e})});
}
I guess your resource is embedded inline (see the csp error).
To allow that use unsafe-inline:
app.use((req, res, next) => {
res.setHeader('Content-Security-Policy',"default-src 'self' 'unsafe-inline'");
next();
});
SabSab43, you have been given the correct leads in the comments and answers, but you shouldn't recklessly publish the CSP. You can publish CSP in several ways:
add_header in Nginx
HTTP header via res.setHeader()
specialized Helmet package
using <meta http-equiv='Content-Security-Policy' content="...CSP rules here..."> in the HTML code.
But if you do use all of above at the same time, you'll publish a several different CSPs and as result more restrictive one will acts.
Therefore remove all CSP you added and lets go step by step:
Do check the jonrsharpe's remark abt Helmet. The fact is that if you have Helmet 4 connected to Express, it issues the restrictive default-src 'self' policy by default.
Therefore after removing all your CSPs, check do you have CSP header in browser, tutorial is here. If CSP header is presents - some middleware (like Helmet) does publish it. You need to find it and modify the policy in it, or switch it off and use your res.setHeader(...)
If there is no header (and there is no meta tag either), publish the CSP with any of the methods, and add 'unsafe-inline' to it, as kmgt said. You need to have policy:
"default-src 'self' 'unsafe-inline' https://www.mydomain.fr"
to get rid of "The page settings prevented a resource from loading at inline ("default-src")"
Note that 'prevented a resource from loading at inline' can be about not only inline <script>, but about inline <style> too. But since you use `default-src', it covers both.
PS: Chrome's console more verbose than Firefox's one. If you fail to fix this issue, pls show the message about the blocking from the Сhrome's console - it will show the rules that block.
I've deleted all my CSP Rules (I don't use Helmet or any CSP dependencies) in my app and Nginx .conf file and when I look in browsers developers tools I see again the CSP Rule.
In chrome:
capture
In Firefox:
capture
therefore, I've tried to put this code:
app.use((req, res, next) => {
res.set({"Content-Security-Policy":"default-src 'self' 'unsafe-inline' https://www.myDomain.fr"});
next();
});
I've the same result than without the CSP Rules...
In Chrome I juste have a 404 error:
GET https://www.myDomain.fr/file 404 (Not found)
In Firefox
GET https://www.myDomain.fr/file [HTTP/1.1 404 Not found 96ms]
Content Security Policy: The page settings prevented a resource from loading at inline ("default-src").
The 404 is probably caused by the CSP Error...

CORS origin header is incomplete in Internet Explorer 10 when compared with Chrome and FireFox

I have web server running node server running on a server. The node server set the in the response header 'Access control' to a specific web site to allow only that website accessing the resources served by my node server:
header["Access-Control-Allow-Origin"] = "https://www.mywebsite.com";
In mywebsite.com when calls are made to get resources from the node server, the request works fine since they are coming from the authorized web site. I tested this on Chrome and FireFox. When I tried the same thing using IE10, the resources were not served ok.
When looking at the header request and response for IE 10, I noticed that the 'origin' is not filled correctly while it was filled ok using Firefox and Chrome.
Here is the Chrome header:
Chrome header values
While IE 10 header was:
Internet Explorer header values for same get request
On IE 10, the origin is filled with 'blob://'
While on Chrome and Firefox the origin web site domain is listed correctly allowing the CORS to work properly.
The resources served by the node server are mbtiles with .pbf that are binary streams.
Any idea why IE10 seems to put incorrect origin in the header request ? and may be a work around or solution for it ?
Thanks
I'm not sure if this will solve your problem but I have never had an issue using this method:
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', 'http://www.website.com');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization, Access-Control-Allow-Credentials');
res.header('Access-Control-Allow-Credentials', 'true');
next();
});

Cross origin Node js in Cloud 9 ide

I have a client in a workspace and server side in the another workspace.
I have Cross orgin in the server workspace.
res.header('Access-Conrol-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, OPTIONS');
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Max-Age', '86400');
res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
But While calling from the client side getting below error
Mixed Content: The page at 'https://blogclient-vignesh55.c9users.io/?_c9_id=livepreview1&_c9_host=https://ide.c9.io#/home' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://10.237.69.147:15871/cgi-bin/blockpage.cgi?ws-session=18446744072714596624'. This request has been blocked; the content must be served over HTTPS
Your problem here is not the Same Origin Policy, but that your page is mixing http and https calls. Make sure to either use protocol-independent urls like //someurl.com or that you only use one protocol throughout your project.
PS: If you actually read the error message, it tells you exactly this:
the content must be served over HTTPS
and you try to call it via http:
http://xx.xx.xx.xx:15871/cgi-bin/blockpage.cgi?ws-session=XXX

Disable CORS in Expres.io for socket.io calls

I try to connect from angular to a Express.io socket, but I have error 404 CORS. How can I solve this?
XMLHttpRequest cannot load http://localhost:3000/socket.io/?EIO=3&transport=polling&t=1447367208172-29. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access.
If I load this route directly from browser directly, it works well But from localhost:80 angular to localhot:3000 express.io not works.
In my express.io I disabled the CORS, and it works well for the normal ajax requests, but not for socket.io :
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Origin', req.headers.origin);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
next();
});
My initialization of socket.io in express.io:
app.http().io()
Are you running this angular app in chrome? I imagine its the same way for most browsers but on chrome CORS will not work with localhost: https://code.google.com/p/chromium/issues/detail?id=67743
What I've done to get around this in the past is alter my hosts (if on Windows). You can also use lvh.me instead of localhost if you do not want to alter your hosts file on Windows.

Resources