CSRF protection for gdata extension

This commit is contained in:
Antonin Delpeuch 2019-10-17 09:54:53 +01:00
parent b52c009491
commit 24feda600a
7 changed files with 192 additions and 105 deletions

View File

@ -109,10 +109,12 @@ Refine.GDataSourceUI.prototype._listDocuments = function() {
this._elmts.progressPage.show();
var self = this;
Refine.wrapCSRF(function(token) {
$.post(
"command/core/importing-controller?" + $.param({
"controller": "gdata/gdata-importing-controller",
"subCommand": "list-documents"
"subCommand": "list-documents",
"csrf_token": token
}),
null,
function(o) {
@ -120,6 +122,7 @@ Refine.GDataSourceUI.prototype._listDocuments = function() {
},
"json"
);
});
};
Refine.GDataSourceUI.prototype._renderDocuments = function(o) {

View File

@ -71,16 +71,18 @@ Refine.GDataImportingController.prototype.startImportingDocument = function(doc)
var dismiss = DialogSystem.showBusy($.i18n('gdata-import/preparing'));
var self = this;
$.post(
Refine.postCSRF(
"command/core/create-importing-job",
null,
function(data) {
Refine.wrapCSRF(function(token) {
$.post(
"command/core/importing-controller?" + $.param({
"controller": "gdata/gdata-importing-controller",
"subCommand": "initialize-parser-ui",
"docUrl": doc.docSelfLink,
"docType": doc.type
"docType": doc.type,
"csrf_token": token
}),
null,
function(data2) {
@ -98,6 +100,7 @@ Refine.GDataImportingController.prototype.startImportingDocument = function(doc)
},
"json"
);
});
},
"json"
);
@ -315,11 +318,13 @@ Refine.GDataImportingController.prototype._updatePreview = function() {
this._parsingPanelElmts.dataPanel.hide();
this._parsingPanelElmts.progressPanel.show();
Refine.wrapCSRF(function(token) {
$.post(
"command/core/importing-controller?" + $.param({
"controller": "gdata/gdata-importing-controller",
"jobID": this._jobID,
"subCommand": "parse-preview"
"subCommand": "parse-preview",
"csrf_token": token
}),
{
"options" : JSON.stringify(this.getOptions())
@ -340,6 +345,7 @@ Refine.GDataImportingController.prototype._updatePreview = function() {
},
"json"
);
});
};
Refine.GDataImportingController.prototype._getPreviewData = function(callback, numRows) {
@ -385,11 +391,13 @@ Refine.GDataImportingController.prototype._createProject = function() {
var self = this;
var options = this.getOptions();
options.projectName = projectName;
Refine.wrapCSRF(function(token) {
$.post(
"command/core/importing-controller?" + $.param({
"controller": "gdata/gdata-importing-controller",
"jobID": this._jobID,
"subCommand": "create-project"
"subCommand": "create-project",
"csrf_token": token
}),
{
"options" : JSON.stringify(options)
@ -433,4 +441,5 @@ Refine.GDataImportingController.prototype._createProject = function() {
},
"json"
);
});
};

View File

@ -54,7 +54,7 @@ $.i18n().load(dictionary, lang);
var name = window.prompt(prompt, theProject.metadata.name);
if (name) {
var dismiss = DialogSystem.showBusy($.i18n('gdata-exporter/uploading'));
$.post(
Refine.postCSRF(
"command/gdata/upload",
{
"project" : theProject.id,

View File

@ -66,7 +66,9 @@
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire.version}</version>
<configuration>
<skip>true</skip>
<suiteXmlFiles>
<suiteXmlFile>tests/conf/tests.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
<plugin>
@ -162,6 +164,12 @@
<version>6.9.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.23.4</version>
<scope>test</scope>
</dependency>
</dependencies>

View File

@ -43,6 +43,10 @@ public class UploadCommand extends Command {
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
if(!hasValidCSRFToken(request)) {
respondCSRFError(response);
return;
}
String token = TokenCookie.getToken(request);
if (token == null) {

View File

@ -0,0 +1,14 @@
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="GData extension">
<test name="tests">
<groups>
<run>
<exclude name="broken" />
</run>
</groups>
<packages>
<package name="com.google.refine.extension.gdata.*" />
</packages>
</test>
</suite>

View File

@ -0,0 +1,49 @@
package com.google.refine.extension.gdata;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.refine.commands.Command;
import com.google.refine.util.ParsingUtilities;
public class UploadCommandTest {
protected HttpServletRequest request = null;
protected HttpServletResponse response = null;
protected Command command = null;
protected StringWriter writer = null;
@BeforeMethod
public void setUpRequestResponse() {
request = mock(HttpServletRequest.class);
response = mock(HttpServletResponse.class);
writer = new StringWriter();
command = new UploadCommand();
try {
when(response.getWriter()).thenReturn(new PrintWriter(writer));
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void testCsrfProtection() throws ServletException, IOException {
command.doPost(request, response);
Assert.assertEquals(
ParsingUtilities.mapper.readValue("{\"code\":\"error\",\"message\":\"Missing or invalid csrf_token parameter\"}", ObjectNode.class),
ParsingUtilities.mapper.readValue(writer.toString(), ObjectNode.class));
}
}