Browse Source

Implement CSRF protection

Enabled for all POST endpoints, as well as for GET /rpc-browser when the
"execute" query string argument is specified.
fix-133-memory-crash
Nadav Ivgi 6 years ago
parent
commit
44d676650f
  1. 6
      app.js
  2. 1
      package.json
  3. 9
      routes/baseActionsRouter.js
  4. 1
      views/browser.pug
  5. 2
      views/connect.pug
  6. 2
      views/layout.pug
  7. 1
      views/search.pug
  8. 3
      views/terminal.pug

6
app.js

@ -11,6 +11,7 @@ var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require("express-session");
var csurf = require("csurf");
var config = require("./app/config.js");
var simpleGit = require('simple-git');
var utils = require("./app/utils.js");
@ -454,6 +455,11 @@ app.use(function(req, res, next) {
next();
});
app.use(csurf(), (req, res, next) => {
res.locals.csrfToken = req.csrfToken();
next();
});
app.use('/', baseActionsRouter);
/// catch 404 and forwarding to error handler

1
package.json

@ -28,6 +28,7 @@
"body-parser": "~1.18.2",
"cookie-parser": "~1.4.3",
"crypto-js": "3.1.9-1",
"csurf": "^1.9.0",
"debug": "~2.6.0",
"decimal.js": "7.2.3",
"dotenv": "^6.2.0",

9
routes/baseActionsRouter.js

@ -1,4 +1,5 @@
var express = require('express');
var csurf = require('csurf');
var router = express.Router();
var util = require('util');
var moment = require('moment');
@ -14,6 +15,8 @@ var coins = require("./../app/coins.js");
var config = require("./../app/config.js");
var coreApi = require("./../app/api/coreApi.js");
const forceCsrf = csurf({ ignoreMethods: [] });
router.get("/", function(req, res) {
if (req.session.host == null || req.session.host.trim() == "") {
if (req.cookies['rpc-host']) {
@ -815,7 +818,7 @@ router.post("/rpc-terminal", function(req, res) {
});
});
router.get("/rpc-browser", function(req, res) {
router.get("/rpc-browser", function(req, res, next) {
if (!config.demoSite) {
var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
var match = config.ipWhitelistForRpcCommands.exec(ip);
@ -883,6 +886,9 @@ router.get("/rpc-browser", function(req, res) {
return;
}
forceCsrf(req, res, err => {
if (err) return next(err);
console.log("Executing RPC '" + req.query.method + "' with params: [" + argValues + "]");
client.command([{method:req.query.method, parameters:argValues}], function(err3, result3, resHeaders3) {
@ -904,6 +910,7 @@ router.get("/rpc-browser", function(req, res) {
res.render("browser");
});
});
} else {
res.render("browser");
}

1
views/browser.pug

@ -46,6 +46,7 @@ block content
hr
form(method="get")
input(type="hidden", name="_csrf", value=csrfToken)
input(type="hidden", name="method", value=method)
div(class="h5 mb-3") Arguments

2
views/connect.pug

@ -5,6 +5,8 @@ block content
hr
form(method="post", action="/connect")
input(type="hidden", name="_csrf", value=csrfToken)
div(class="form-group")
label(for="input-host") Host / IP
input(id="input-host", type="text", name="host", class="form-control", placeholder="Host / IP", value=host)

2
views/layout.pug

@ -2,6 +2,7 @@ doctype html
html(lang="en")
head
meta(charset="utf-8")
meta(name="csrf-token", content=csrfToken)
meta(name="viewport", content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0, shrink-to-fit=no")
if (session.uiTheme && session.uiTheme == "dark")
@ -86,6 +87,7 @@ html(lang="en")
span Dark
form(method="post", action="/search", class="form-inline")
input(type="hidden", name="_csrf", value=csrfToken)
div(class="input-group input-group-sm")
input(type="text", class="form-control form-control-sm", name="query", placeholder="block height/hash, txid, address", value=(query), style="width: 300px;")
div(class="input-group-append")

1
views/search.pug

@ -9,6 +9,7 @@ block content
div(class="mb-5")
form(method="post", action="/search", class="form")
input(type="hidden", name="_csrf", value=csrfToken)
div(class="input-group input-group-lg")
input(type="text", class="form-control form-control-sm", name="query", placeholder="block height/hash, txid, address", value=(query), style="width: 300px;")
div(class="input-group-append")

3
views/terminal.pug

@ -33,6 +33,8 @@ block content
block endOfBody
script.
var csrfToken = $('meta[name=csrf-token]').attr('content');
$(document).ready(function() {
$("#terminal-form").submit(function(e) {
e.preventDefault();
@ -41,6 +43,7 @@ block endOfBody
var postData = {};
postData.cmd = cmd;
postData._csrf = csrfToken;
$.post(
"/rpc-terminal",

Loading…
Cancel
Save