input validation for database connection data

This commit is contained in:
tcbuzor 2019-09-08 23:22:22 -05:00
parent 1981a23b51
commit 575a7d4979
6 changed files with 156 additions and 21 deletions

View File

@ -44,5 +44,10 @@
"database-parsing/limit-next": "Load at most",
"database-parsing/limit": "row(s) of data",
"database-parsing/store-row": "Store blank rows",
"database-parsing/store-cell": "Store blank cells as nulls"
"database-parsing/store-cell": "Store blank cells as nulls",
"database-source/alert-conn-name-invalid-character": "Connection Name Input Error: Illegal Character in Input. Only [a-zA-Z0-9._-] Allowed",
"database-source/alert-db-host-invalid-character": "Database Host Error: Illegal Character in Input. Only Alphanumeric characters allowed",
"database-source/alert-db-user-invalid-character": "Database User Error: Illegal Character in Input. Only Alphanumeric characters allowed",
"database-source/alert-db-port-invalid-character": "Database Port Error: Illegal Character in Input. Only Numeric values allowed."
}

View File

@ -127,11 +127,11 @@ Refine.DatabaseSourceUI.prototype.attachUI = function(body) {
this._elmts.saveConnectionButton.click(function(evt) {
if(self._validateNewConnectionForm() == true){
var connectionNameInput = $.trim(self._elmts.connectionNameInput[0].value);
var connectionNameInput = $.trim(self._elmts.connectionNameInput[0].value);
if (connectionNameInput.length === 0) {
window.alert($.i18n('database-source/alert-connection-name'));
} else{
self._saveConnection(self._getConnectionInfo());
self._saveConnection(self._getConnectionInfo());
}
}
@ -431,6 +431,9 @@ Refine.DatabaseSourceUI.prototype._getConnectionInfo = function() {
var self = this;
var jdbcConnectionInfo = {};
jdbcConnectionInfo.connectionName = $.trim(self._elmts.connectionNameInput[0].value);
// window.alert('input:' + jdbcConnectionInfo.connectionName + ' output:' + self._removeScriptTag(jdbcConnectionInfo.connectionName) );
jdbcConnectionInfo.databaseType = $.trim(self._elmts.databaseTypeSelect[0].value);
jdbcConnectionInfo.databaseServer = $.trim(self._elmts.databaseHostInput[0].value);
jdbcConnectionInfo.databasePort = $.trim(self._elmts.databasePortInput[0].value);
@ -442,6 +445,18 @@ Refine.DatabaseSourceUI.prototype._getConnectionInfo = function() {
}
Refine.DatabaseSourceUI.prototype._removeScriptTag = function(input) {
var div = document.createElement('div');
div.innerHTML = s;
var scripts = div.getElementsByTagName('script');
var i = scripts.length;
while (i--) {
scripts[i].parentNode.removeChild(scripts[i]);
}
return div.innerHTML;
};
Refine.DatabaseSourceUI.prototype._validateNewConnectionForm = function() {
var self = this;
@ -454,21 +469,45 @@ Refine.DatabaseSourceUI.prototype._validateNewConnectionForm = function() {
var initialDatabaseInput = $.trim(self._elmts.initialDatabaseInput[0].value);
var initialSchemaInput = $.trim(self._elmts.initialSchemaInput[0].value);
if (databaseHostInput.length === 0) {
var alphaNumRE = /^[a-zA-Z0-9._-]*$/;
var numRE = /^[0-9]*$/;
var alphaNumConnNameTestResult = alphaNumRE.test(connectionNameInput);
var databaseHostTestResult = alphaNumRE.test(databaseHostInput);
var databasePortTestResult = numRE.test(databasePortInput);
var databaseUserTestResult = alphaNumRE.test(databaseUserInput);
if(alphaNumConnNameTestResult == false){
window.alert($.i18n('database-source/alert-conn-name-invalid-character'));
return false;
}else if(connectionNameInput.contains("<script>") || connectionNameInput.contains("<img>")){
window.alert($.i18n('database-source/alert-conn-name-invalid-character'));
return false;
}else if (databaseHostInput.length === 0) {
window.alert($.i18n('database-source/alert-server'));
return false;
}else if(databaseHostInput.contains("<script>") || databaseHostInput.contains("<img>")){
window.alert($.i18n('database-source/alert-db-host-invalid-character'));
return false;
}else if(databasePortInput.length === 0){
window.alert($.i18n('database-source/alert-port'));
return false;
window.alert($.i18n('database-source/alert-port'));
return false;
}else if(databaseUserInput.length === 0){
window.alert($.i18n('database-source/alert-user'));
return false;
window.alert($.i18n('database-source/alert-user'));
return false;
}else if(databaseUserInput.contains("<script>") || databaseUserInput.contains("<img>")){
window.alert($.i18n('database-source/alert-db-user-invalid-character'));
return false;
}else if(initialDatabaseInput.length === 0){
window.alert($.i18n('database-source/alert-initial-database'));
return false;
window.alert($.i18n('database-source/alert-initial-database'));
return false;
}else if(databasePortTestResult == false){
window.alert($.i18n('database-source/alert-db-port-invalid-character'));
return false;
}
else{
return true;
return true;
}

View File

@ -166,6 +166,13 @@
<artifactId>commons-lang3</artifactId>
<version>3.6</version>
</dependency>
<dependency>
<groupId>org.owasp.encoder</groupId>
<artifactId>encoder</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>

View File

@ -314,7 +314,7 @@ public class DatabaseUtils {
String fileSep = System.getProperty("file.separator");
String filename = dir.getPath() + fileSep + DATABASE_EXTENSION_DIR + fileSep + SETTINGS_FILE_NAME;
// logger.info("** extension file name: {} **", filename);
logger.debug("** extension file name: {} **", filename);
return filename;
}
public static String getExtensionFolder(){

View File

@ -31,12 +31,15 @@ package com.google.refine.extension.database.cmd;
import java.io.IOException;
import java.io.Writer;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.http.HttpStatus;
import org.owasp.encoder.Encode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -50,6 +53,9 @@ public class SavedConnectionCommand extends DatabaseCommand {
private static final Logger logger = LoggerFactory.getLogger("SavedConnectionCommand");
private static final Pattern CONN_NAME_PATTERN = Pattern.compile("^[a-zA-Z0-9._-]*");
private static final Pattern DATABASE_PORT_PATTERN = Pattern.compile("^[0-9]*");
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
@ -126,16 +132,24 @@ public class SavedConnectionCommand extends DatabaseCommand {
writer.writeArrayFieldStart(DatabaseUtils.SAVED_CONNECTION_KEY);
writer.writeStartObject();
writer.writeStringField("connectionName", savedConnection.getConnectionName());
String sanitizedConnName = Encode.forHtml(savedConnection.getConnectionName());
// writer.writeStringField("connectionName", savedConnection.getConnectionName());
writer.writeStringField("connectionName", sanitizedConnName);
writer.writeStringField("databaseType", savedConnection.getDatabaseType());
writer.writeStringField("databaseHost", savedConnection.getDatabaseHost());
String sanitizedHost = Encode.forHtml(savedConnection.getDatabaseHost());
// writer.writeStringField("databaseHost", savedConnection.getDatabaseHost());
writer.writeStringField("databaseHost", sanitizedHost);
writer.writeNumberField("databasePort", savedConnection.getDatabasePort());
writer.writeStringField("databaseName", savedConnection.getDatabaseName());
String sanitizedDbName = Encode.forHtml(savedConnection.getDatabaseName());
// writer.writeStringField("databaseName", savedConnection.getDatabaseName());
writer.writeStringField("databaseName", sanitizedDbName);
String dbPasswd = savedConnection.getDatabasePassword();
if(dbPasswd != null && !dbPasswd.isEmpty()) {
dbPasswd = DatabaseUtils.decrypt(savedConnection.getDatabasePassword());
@ -143,8 +157,11 @@ public class SavedConnectionCommand extends DatabaseCommand {
writer.writeStringField("databasePassword", dbPasswd);
writer.writeStringField("databaseSchema", savedConnection.getDatabaseSchema());
String sanitizedDbUser = Encode.forHtml(savedConnection.getDatabaseUser());
// writer.writeStringField("databaseUser", savedConnection.getDatabaseUser());
writer.writeStringField("databaseUser", sanitizedDbUser);
writer.writeStringField("databaseUser", savedConnection.getDatabaseUser());
logger.info("Input DB User:{}, SanitizedDbUser:{}", savedConnection.getDatabaseUser(), sanitizedDbUser);
writer.writeEndObject();
writer.writeEndArray();
@ -228,6 +245,7 @@ public class SavedConnectionCommand extends DatabaseCommand {
if(logger.isDebugEnabled()) {
logger.debug("doPost Connection: {}", request.getParameter("connectionName"));
}
DatabaseConfiguration jdbcConfig = getJdbcConfiguration(request);
@ -240,6 +258,21 @@ public class SavedConnectionCommand extends DatabaseCommand {
response.flushBuffer();
return;
}
if(!validateInput(jdbcConfig.getConnectionName(), CONN_NAME_PATTERN)) {
logger.warn("Invalid Connection Name: {}", jdbcConfig.getConnectionName());
response.sendError(HttpStatus.SC_BAD_REQUEST, "Connection Name is Invalid. Expecting [a-zA-Z0-9._-]");
response.flushBuffer();
return;
}
if(!validateInput("" + jdbcConfig.getDatabasePort(), DATABASE_PORT_PATTERN)) {
logger.warn("Invalid Database Port: {}", jdbcConfig.getDatabasePort());
response.sendError(HttpStatus.SC_BAD_REQUEST, "Database Port Invalid. Expecting Numeric values only");
response.flushBuffer();
return;
}
DatabaseConfiguration savedConn = DatabaseUtils.getSavedConnection(jdbcConfig.getConnectionName());
if(savedConn != null) {
@ -266,8 +299,14 @@ public class SavedConnectionCommand extends DatabaseCommand {
}
}
private boolean validateInput(String input, Pattern pattern){
Matcher matcher = pattern.matcher(input);
if(matcher.matches()){
return true;
}
return false;
}
@Override
public void doPut(HttpServletRequest request, HttpServletResponse response)

View File

@ -1,6 +1,9 @@
package com.google.refine.extension.database.cmd;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotEquals;
import static org.testng.Assert.assertNotNull;
import java.io.File;
import java.io.IOException;
@ -154,8 +157,11 @@ public class SavedConnectionCommandTest extends DBExtensionTests{
SUT.doPost(request, response);
String result = sw.getBuffer().toString().trim();
assertNotNull(result);
assertFalse(result.isEmpty(), "Valid response Message expected!");
ObjectNode json = ParsingUtilities.mapper.readValue(result, ObjectNode.class);
System.out.println("json:" + json);
ArrayNode savedConnections = (ArrayNode) json.get("savedConnections");
Assert.assertNotNull(savedConnections);
@ -229,7 +235,7 @@ public class SavedConnectionCommandTest extends DBExtensionTests{
Assert.assertEquals(savedConnections.size(), 1);
ObjectNode sc = (ObjectNode)savedConnections.get(0);
System.out.println("sc" + sc);
//System.out.println("sc" + sc);
String newDbHost = sc.get("databaseHost").asText();
Assert.assertEquals(newDbHost, newHost);
}
@ -288,5 +294,44 @@ public class SavedConnectionCommandTest extends DBExtensionTests{
e.printStackTrace();
}
}
/**
* Added to check XSS invalid tokens
* @throws IOException
* @throws ServletException
*/
@Test
public void testDoPostInvalidConnectionName() throws IOException, ServletException {
when(request.getParameter("connectionName")).thenReturn("<img></img>");
when(request.getParameter("databaseType")).thenReturn(MySQLDatabaseService.DB_NAME);
when(request.getParameter("databaseServer")).thenReturn(testDbConfig.getDatabaseHost());
when(request.getParameter("databasePort")).thenReturn("" + testDbConfig.getDatabasePort());
when(request.getParameter("databaseUser")).thenReturn(testDbConfig.getDatabaseUser());
when(request.getParameter("databasePassword")).thenReturn(testDbConfig.getDatabasePassword());
when(request.getParameter("initialDatabase")).thenReturn(testDbConfig.getDatabaseName());
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
when(response.getWriter()).thenReturn(pw);
SUT.doPost(request, response);
String result = sw.getBuffer().toString().trim();
assertNotNull(result);
assertFalse(result.isEmpty(), "Valid response Message expected!");
ObjectNode json = ParsingUtilities.mapper.readValue(result, ObjectNode.class);
System.out.println("json:" + json);
ArrayNode savedConnections = (ArrayNode) json.get("savedConnections");
Assert.assertNotNull(savedConnections);
int len = savedConnections.size();
Assert.assertEquals(len, 1);
}
}