web/account: add referrer check
This commit is contained in:
parent
b876c8907a
commit
875337d9a6
13
NEWS.md
13
NEWS.md
|
@ -1,3 +1,16 @@
|
|||
2017-11-05
|
||||
==========
|
||||
|
||||
The latest commit introduces a referrer check in the account page handlers.
|
||||
This is added as a short-term mitigation for a recent report that account
|
||||
management functions (such as deleting channels) can be executed without the
|
||||
user's consent if placed in channel JS.
|
||||
|
||||
Longer term options are being considered, such as moving account management to a
|
||||
separate subdomain to take advantage of cross-origin checks in browsers, and
|
||||
requiring the user to re-enter their password to demonstrate intent. As always,
|
||||
I recommend admins take extreme caution when accepting channel JS.
|
||||
|
||||
2017-09-26
|
||||
==========
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"author": "Calvin Montgomery",
|
||||
"name": "CyTube",
|
||||
"description": "Online media synchronizer and chat",
|
||||
"version": "3.51.2",
|
||||
"version": "3.51.3",
|
||||
"repository": {
|
||||
"url": "http://github.com/calzoneman/sync"
|
||||
},
|
||||
|
|
|
@ -15,7 +15,7 @@ var session = require("../session");
|
|||
var csrf = require("./csrf");
|
||||
const url = require("url");
|
||||
|
||||
const LOGGER = require('@calzoneman/jsli')('database/accounts');
|
||||
const LOGGER = require('@calzoneman/jsli')('web/accounts');
|
||||
|
||||
let globalMessageBus;
|
||||
let emailConfig;
|
||||
|
@ -28,12 +28,42 @@ function handleAccountEditPage(req, res) {
|
|||
sendPug(res, "account-edit", {});
|
||||
}
|
||||
|
||||
function verifyReferrer(req, expected) {
|
||||
const referrer = req.header('referer');
|
||||
|
||||
if (!referrer) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
const parsed = url.parse(referrer);
|
||||
|
||||
if (parsed.pathname !== expected) {
|
||||
LOGGER.warn(
|
||||
'Possible attempted forgery: %s POSTed to %s',
|
||||
referrer,
|
||||
expected
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a POST request to edit a user"s account
|
||||
*/
|
||||
function handleAccountEdit(req, res) {
|
||||
csrf.verify(req);
|
||||
|
||||
if (!verifyReferrer(req, '/account/edit')) {
|
||||
res.status(403).send('Mismatched referrer');
|
||||
return;
|
||||
}
|
||||
|
||||
var action = req.body.action;
|
||||
switch(action) {
|
||||
case "change_password":
|
||||
|
@ -43,7 +73,7 @@ function handleAccountEdit(req, res) {
|
|||
handleChangeEmail(req, res);
|
||||
break;
|
||||
default:
|
||||
res.send(400);
|
||||
res.sendStatus(400);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -197,6 +227,11 @@ async function handleAccountChannelPage(req, res) {
|
|||
function handleAccountChannel(req, res) {
|
||||
csrf.verify(req);
|
||||
|
||||
if (!verifyReferrer(req, '/account/channels')) {
|
||||
res.status(403).send('Mismatched referrer');
|
||||
return;
|
||||
}
|
||||
|
||||
var action = req.body.action;
|
||||
switch(action) {
|
||||
case "new_channel":
|
||||
|
@ -395,6 +430,11 @@ function validateProfileImage(image, callback) {
|
|||
async function handleAccountProfile(req, res) {
|
||||
csrf.verify(req);
|
||||
|
||||
if (!verifyReferrer(req, '/account/profile')) {
|
||||
res.status(403).send('Mismatched referrer');
|
||||
return;
|
||||
}
|
||||
|
||||
const user = await webserver.authorize(req);
|
||||
// TODO: error message
|
||||
if (!user) {
|
||||
|
@ -465,6 +505,11 @@ function handlePasswordResetPage(req, res) {
|
|||
function handlePasswordReset(req, res) {
|
||||
csrf.verify(req);
|
||||
|
||||
if (!verifyReferrer(req, '/account/passwordreset')) {
|
||||
res.status(403).send('Mismatched referrer');
|
||||
return;
|
||||
}
|
||||
|
||||
var name = req.body.name,
|
||||
email = req.body.email;
|
||||
|
||||
|
|
Loading…
Reference in a new issue