Skip to content

Commit

Permalink
CSRF protection for ImportingController
Browse files Browse the repository at this point in the history
  • Loading branch information
wetneb committed Oct 14, 2019
1 parent 70e37b9 commit 91cead2
Show file tree
Hide file tree
Showing 7 changed files with 223 additions and 177 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ public class ImportingControllerCommand extends Command {
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
if(!checkCSRF(request)) {
respondCSRFError(response);
return;
}

ImportingController controller = getController(request);
if (controller != null) {
Expand Down Expand Up @@ -92,4 +96,14 @@ private ImportingController getController(HttpServletRequest request) {
}
return null;
}

/**
* Checks the validity of a CSRF token, without reading the whole POST body.
* See above for details.
*/
private boolean checkCSRF(HttpServletRequest request) {
Properties options = ParsingUtilities.parseUrlParameters(request);
String token = options.getProperty("csrf_token");
return token != null && csrfFactory.validToken(token);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.google.refine.commands.importing;

import com.google.refine.commands.CommandTestBase;
import java.io.IOException;

import javax.servlet.ServletException;

import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

public class ImportingControllerCommandTests extends CommandTestBase {

@BeforeMethod
public void setUpCommand() {
command = new ImportingControllerCommand();
}

@Test
public void testCSRFProtection() throws ServletException, IOException {
command.doPost(request, response);
assertCSRFCheckFailed();
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -157,15 +157,13 @@ ExpressionPreviewDialog.Widget.prototype.getExpression = function(commit) {

s = this._getLanguage() + ":" + s;
if (commit) {
Refine.wrapCSRF(function(token) {
$.post(
"command/core/log-expression?" + $.param({ project: theProject.id }),
{ expression: s, csrf_token: token },
function(data) {
},
"json"
);
});
Refine.postCSRF(
"command/core/log-expression?" + $.param({ project: theProject.id }),
{ expression: s },
function(data) {
},
"json"
);
}

return s;
Expand Down Expand Up @@ -286,21 +284,18 @@ ExpressionPreviewDialog.Widget.prototype._renderExpressionHistory = function(dat
.addClass(entry.starred ? "data-table-star-on" : "data-table-star-off")
.appendTo(tr.insertCell(0))
.click(function() {
Refine.wrapCSRF(function(token) {
$.post(
"command/core/toggle-starred-expression",
{
expression: entry.code,
csrf_token: token
},
function(data) {
entry.starred = !entry.starred;
renderEntry(self,tr,entry);
self._renderStarredExpressionsTab();
},
"json"
);
});
Refine.postCSRF(
"command/core/toggle-starred-expression",
{
expression: entry.code
},
function(data) {
entry.starred = !entry.starred;
renderEntry(self,tr,entry);
self._renderStarredExpressionsTab();
},
"json"
);
});

$('<a href="javascript:{}">'+$.i18n('core-dialogs/reuse')+'</a>').appendTo(tr.insertCell(1)).click(function() {
Expand Down Expand Up @@ -355,17 +350,15 @@ ExpressionPreviewDialog.Widget.prototype._renderStarredExpressions = function(da
var o = Scripting.parse(entry.code);

$('<a href="javascript:{}">'+$.i18n('core-dialogs/remove')+'</a>').appendTo(tr.insertCell(0)).click(function() {
Refine.wrapCSRF(function(token) {
$.post(
"command/core/toggle-starred-expression",
{ expression: entry.code, returnList: true, csrf_token: token },
function(data) {
self._renderStarredExpressions(data);
self._renderExpressionHistoryTab();
},
"json"
);
});
Refine.postCSRF(
"command/core/toggle-starred-expression",
{ expression: entry.code, returnList: true },
function(data) {
self._renderStarredExpressions(data);
self._renderExpressionHistoryTab();
},
"json"
);
});

$('<a href="javascript:{}">Reuse</a>').appendTo(tr.insertCell(1)).click(function() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ Refine.DefaultImportingController.prototype.startImportJob = function(form, prog
.attr("action", "command/core/importing-controller?" + $.param({
"controller": "core/default-importing-controller",
"jobID": jobID,
"subCommand": "load-raw-data"
"subCommand": "load-raw-data",
"csrf_token": token
}));
form[0].submit();

Expand Down Expand Up @@ -182,27 +183,30 @@ Refine.DefaultImportingController.prototype._ensureFormatParserUIHasInitializati
if (!(format in this._parserOptions)) {
var self = this;
var dismissBusy = DialogSystem.showBusy($.i18n('core-index-import/inspecting'));
$.post(
"command/core/importing-controller?" + $.param({
"controller": "core/default-importing-controller",
"jobID": this._jobID,
"subCommand": "initialize-parser-ui",
"format": format
}),
null,
function(data) {
dismissBusy();

if (data.options) {
self._parserOptions[format] = data.options;
onDone();
}
},
"json"
)
.fail(function() {
dismissBusy();
alert($.i18n('core-views/check-format'));
Refine.wrapCSRF(function(token) {
$.post(
"command/core/importing-controller?" + $.param({
"controller": "core/default-importing-controller",
"jobID": this._jobID,
"subCommand": "initialize-parser-ui",
"format": format,
"csrf_token": token
}),
null,
function(data) {
dismissBusy();

if (data.options) {
self._parserOptions[format] = data.options;
onDone();
}
},
"json"
)
.fail(function() {
dismissBusy();
alert($.i18n('core-views/check-format'));
});
});
} else {
onDone();
Expand All @@ -211,32 +215,35 @@ Refine.DefaultImportingController.prototype._ensureFormatParserUIHasInitializati

Refine.DefaultImportingController.prototype.updateFormatAndOptions = function(options, callback, finallyCallBack) {
var self = this;
$.post(
"command/core/importing-controller?" + $.param({
"controller": "core/default-importing-controller",
"jobID": this._jobID,
"subCommand": "update-format-and-options"
}),
{
"format" : this._format,
"options" : JSON.stringify(options)
},
function(o) {
if (o.status == 'error') {
if (o.message) {
alert(o.message);
Refine.wrapCSRF(function(token) {
$.post(
"command/core/importing-controller?" + $.param({
"controller": "core/default-importing-controller",
"jobID": this._jobID,
"subCommand": "update-format-and-options",
"csrf_token": token
}),
{
"format" : this._format,
"options" : JSON.stringify(options)
},
function(o) {
if (o.status == 'error') {
if (o.message) {
alert(o.message);
} else {
var messages = [];
$.each(o.errors, function() { messages.push(this.message); });
alert(messages.join('\n\n'));
}
finallyCallBack();
} else {
var messages = [];
$.each(o.errors, function() { messages.push(this.message); });
alert(messages.join('\n\n'));
callback(o);
}
finallyCallBack();
} else {
callback(o);
}
},
"json"
);
},
"json"
);
});
};

Refine.DefaultImportingController.prototype.getPreviewData = function(callback, numRows) {
Expand Down Expand Up @@ -286,56 +293,59 @@ Refine.DefaultImportingController.prototype._createProject = function() {
var options = this._formatParserUI.getOptions();
options.projectName = projectName;
options.projectTags = projectTags;
$.post(
"command/core/importing-controller?" + $.param({
"controller": "core/default-importing-controller",
"jobID": this._jobID,
"subCommand": "create-project"
}),
{
"format" : this._format,
"options" : JSON.stringify(options)
},
function(o) {
if (o.status == 'error') {
alert(o.message);
return;
}

var start = new Date();
var timerID = window.setInterval(
function() {
self._createProjectUI.pollImportJob(
start,
self._jobID,
timerID,
function(job) {
return "projectID" in job.config;
},
function(jobID, job) {
Refine.CreateProjectUI.cancelImportingJob(jobID);
document.location = "project?project=" + job.config.projectID;
},
function(job) {
alert($.i18n('core-index-import/errors')+'\n' + Refine.CreateProjectUI.composeErrorMessage(job));
self._onImportJobReady();
}
Refine.wrapCSRF(function(token) {
$.post(
"command/core/importing-controller?" + $.param({
"controller": "core/default-importing-controller",
"jobID": this._jobID,
"subCommand": "create-project",
"csrf_token": token
}),
{
"format" : this._format,
"options" : JSON.stringify(options)
},
function(o) {
if (o.status == 'error') {
alert(o.message);
return;
}

var start = new Date();
var timerID = window.setInterval(
function() {
self._createProjectUI.pollImportJob(
start,
self._jobID,
timerID,
function(job) {
return "projectID" in job.config;
},
function(jobID, job) {
Refine.CreateProjectUI.cancelImportingJob(jobID);
document.location = "project?project=" + job.config.projectID;
},
function(job) {
alert($.i18n('core-index-import/errors')+'\n' + Refine.CreateProjectUI.composeErrorMessage(job));
self._onImportJobReady();
}
);
},
1000
);
},
1000
);
self._createProjectUI.showImportProgressPanel($.i18n('core-index-import/creating-proj'), function() {
// stop the timed polling
window.clearInterval(timerID);
self._createProjectUI.showImportProgressPanel($.i18n('core-index-import/creating-proj'), function() {
// stop the timed polling
window.clearInterval(timerID);

// explicitly cancel the import job
Refine.CreateProjectUI.cancelImportingJob(self._jobID);
// explicitly cancel the import job
Refine.CreateProjectUI.cancelImportingJob(self._jobID);

self._createProjectUI.showSourceSelectionPanel();
});
},
"json"
);
self._createProjectUI.showSourceSelectionPanel();
});
},
"json"
);
});
}
};

Expand Down

0 comments on commit 91cead2

Please sign in to comment.