krakenjs / lusca

Application security for express apps.
Other
1.78k stars 123 forks source link

Basic Security with Node, Express and Lusca #88

Open ghost opened 8 years ago

ghost commented 8 years ago

I am trying to build a basic Express app with some security protocols implemented using Lusca.

I am facing two issues. The first is with CSP (content security policy), for some reason when a violation is caught the browser doesn't carry out report-uri http://localhost:3000/r, and the network monitor gives a canceled status. Can someone explain the problem here?

vgizu

The second issue is with CSRF (cross-site request forgery), I keep getting an CSRF token missing error when I submit the form, I cannot tell why. How can I avoid having this error displayed and how can I validate the token itself? with sessions?

I have followed the docs very carefully, but with no luck. Here is my code:

var express    = require('express'),
    session    = require('express-session'),
    lusca      = require('lusca'),
    bodyParser = require('body-parser'),
    fs         = require('fs');
var app = express();

app.use(session({
    secret: 'abc',
    resave: true,
    saveUninitialized: true,
    cookie: { httpOnly: true }//, secure: true } // https only
}));

app.use(lusca({
    csrf: { secret: 'abc' },
    csp: {
        policy: { 'default-src': '\'self\'' },
        reportUri: 'http://localhost:3000/report'
    },
    xframe: 'DENY', // i never use frames, hence DENY instead of SAMEORIGN
    p3p: 'This is not a P3P policy.', // is this needed?
    //hsts: {maxAge: 31536000, preload: true}, // https only
    xssProtection: true,
    nosniff: true
    // any notes on these settings?
}));

app.disable('x-powered-by');

app.use(bodyParser.json({ type: 'application/json' }));
app.use(bodyParser.json({ type: 'application/csp-report' }));
// are these two lines enough?

app.post('/r', (req, res) => {
    fs.writeFile('r/' + new Date().getTime() + '.json', '{ headers: ' + JSON.stringify(req.headers) + ', body: ' + JSON.stringify(req.body) + ' }');
    res.end();
});

app.get('/', (req, res) => {
    res.send('<form method="post">\
                <input type="hidden" name="_csrf" value="' + res.locals._csrf + '">\
                <input type="button" value="inline" onclick="alert(123);">\
                <input type="submit">\
              </form>');
});

app.post('/', (req, res) => {
    // is _csrf valid? how can i check?
});

app.listen(3000, () => { console.log('running ..'); });
jonathansamines commented 7 years ago

Hi I guess you cannot actually validate that, but the handler will only be called if the csrf is present and is ok. See: https://github.com/krakenjs/lusca/blob/master/lib/csrf.js#L80.

However I guess you can use req.csrfToken() to issue a new one and verify everything is ok (See https://github.com/krakenjs/lusca/blob/master/lib/csrf.js#L60).

Regarding the CSP problem, It would be helpful to get the actual request from your chrome network inspector. Also seems like the "notify" url is not the same as the referenced from the CSP configuration (/r vs /report)

Hope this helps.