diff --git a/CHANGELOG.md b/CHANGELOG.md index c42d7ef..908b809 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ All notable changes to this add-on will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). +## [1.0.1] - 2021-08-19 + - Minor change + - Scan rule will only execute if add-on configuration is specified. ## [1.0.0] - 2021-08-05 - First version of FileUpload Addon. diff --git a/build.gradle.kts b/build.gradle.kts index b3f1399..e5dffa7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -37,7 +37,7 @@ tasks.compileJava { tasks.withType().configureEach { options.encoding = "utf-8"} -version = "1.0.0" +version = "1.0.1" description = "Detect File upload requests and scan them to find related vulnerabilities" zapAddOn { diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java index 211182e..11c6a44 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java @@ -15,6 +15,7 @@ import java.io.IOException; import java.util.List; +import org.apache.commons.lang3.StringUtils; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.parosproxy.paros.core.scanner.AbstractAppParamPlugin; @@ -22,6 +23,7 @@ import org.parosproxy.paros.core.scanner.NameValuePair; import org.parosproxy.paros.network.HttpMessage; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; +import org.sasanlabs.fileupload.configuration.FileUploadConfiguration; import org.sasanlabs.fileupload.i18n.FileUploadI18n; import org.zaproxy.zap.core.scanner.InputVector; import org.zaproxy.zap.core.scanner.InputVectorBuilder; @@ -79,6 +81,19 @@ public void decreaseRequestCount() { this.maxRequestCount--; } + private boolean isConfigured() { + return StringUtils.isNotBlank( + FileUploadConfiguration.getInstance().getStaticLocationURIRegex()) + || StringUtils.isNotBlank( + FileUploadConfiguration.getInstance().getDynamicLocationURIRegex()) + || (StringUtils.isNotBlank( + FileUploadConfiguration.getInstance() + .getParseResponseStartIdentifier()) + && StringUtils.isNotBlank( + FileUploadConfiguration.getInstance() + .getParseResponseEndIdentifier())); + } + @Override protected void scan(List nameValuePairs) { try { @@ -99,7 +114,7 @@ protected void scan(List nameValuePairs) { } } } - if (isMultipart) { + if (isMultipart && isConfigured()) { FileUploadAttackExecutor fileUploadAttackExecutor = new FileUploadAttackExecutor( this, nameValuePairs, originalFileName, originalContentType); diff --git a/src/main/java/org/sasanlabs/fileupload/configuration/FileUploadConfiguration.java b/src/main/java/org/sasanlabs/fileupload/configuration/FileUploadConfiguration.java index c912275..e62b3e6 100644 --- a/src/main/java/org/sasanlabs/fileupload/configuration/FileUploadConfiguration.java +++ b/src/main/java/org/sasanlabs/fileupload/configuration/FileUploadConfiguration.java @@ -35,15 +35,15 @@ public class FileUploadConfiguration extends VersionedAbstractParam { PARAM_BASE_KEY + ".staticlocation.uriregex"; private static final String PARAM_DYNAMIC_LOCATION_CONFIGURATION_URI_REGEX = PARAM_BASE_KEY + ".dynamiclocation.uriregex"; - private static final String PARAM_DYNAMIC_LOCATION_CONFIGURATION_START_IDENTIFIER = - PARAM_BASE_KEY + ".dynamiclocation.startidentifier"; - private static final String PARAM_DYNAMIC_LOCATION_CONFIGURATION_END_IDENTIFIER = - PARAM_BASE_KEY + ".dynamiclocation.endidentifier"; + private static final String PARAM_PARSE_RESPONSE_CONFIGURATION_START_IDENTIFIER = + PARAM_BASE_KEY + ".parseresponse.startidentifier"; + private static final String PARAM_PARSE_RESPONSE_CONFIGURATION_END_IDENTIFIER = + PARAM_BASE_KEY + ".parseresponse.endidentifier"; private String staticLocationURIRegex; private String dynamicLocationURIRegex; - private String dynamicLocationStartIdentifier; - private String dynamicLocationEndIdentifier; + private String parseResponseStartIdentifier; + private String parseResponseEndIdentifier; private static volatile FileUploadConfiguration fileUploadConfiguration; @@ -81,28 +81,28 @@ public void setDynamicLocationURIRegex(String dynamicLocationURIRegex) { PARAM_DYNAMIC_LOCATION_CONFIGURATION_URI_REGEX, dynamicLocationURIRegex); } - public String getDynamicLocationStartIdentifier() { - return dynamicLocationStartIdentifier; + public String getParseResponseStartIdentifier() { + return parseResponseStartIdentifier; } - public void setDynamicLocationStartIdentifier(String dynamicLocationStartIdentifier) { - this.dynamicLocationStartIdentifier = dynamicLocationStartIdentifier; + public void setParseResponseStartIdentifier(String parseResponseStartIdentifier) { + this.parseResponseStartIdentifier = parseResponseStartIdentifier; this.getConfig() .setProperty( - PARAM_DYNAMIC_LOCATION_CONFIGURATION_START_IDENTIFIER, - dynamicLocationStartIdentifier); + PARAM_PARSE_RESPONSE_CONFIGURATION_START_IDENTIFIER, + parseResponseStartIdentifier); } - public String getDynamicLocationEndIdentifier() { - return dynamicLocationEndIdentifier; + public String getParseResponseEndIdentifier() { + return parseResponseEndIdentifier; } - public void setDynamicLocationEndIdentifier(String dynamicLocationEndIdentifier) { - this.dynamicLocationEndIdentifier = dynamicLocationEndIdentifier; + public void setParseResponseEndIdentifier(String parseResponseEndIdentifier) { + this.parseResponseEndIdentifier = parseResponseEndIdentifier; this.getConfig() .setProperty( - PARAM_DYNAMIC_LOCATION_CONFIGURATION_END_IDENTIFIER, - dynamicLocationEndIdentifier); + PARAM_PARSE_RESPONSE_CONFIGURATION_END_IDENTIFIER, + parseResponseEndIdentifier); } @Override @@ -121,10 +121,10 @@ protected void parseImpl() { getConfig().getString(PARAM_STATIC_LOCATION_CONFIGURATION_URI_REGEX)); this.setDynamicLocationURIRegex( getConfig().getString(PARAM_DYNAMIC_LOCATION_CONFIGURATION_URI_REGEX)); - this.setDynamicLocationStartIdentifier( - getConfig().getString(PARAM_DYNAMIC_LOCATION_CONFIGURATION_START_IDENTIFIER)); - this.setDynamicLocationEndIdentifier( - getConfig().getString(PARAM_DYNAMIC_LOCATION_CONFIGURATION_END_IDENTIFIER)); + this.setParseResponseStartIdentifier( + getConfig().getString(PARAM_PARSE_RESPONSE_CONFIGURATION_START_IDENTIFIER)); + this.setParseResponseEndIdentifier( + getConfig().getString(PARAM_PARSE_RESPONSE_CONFIGURATION_END_IDENTIFIER)); } @Override diff --git a/src/main/java/org/sasanlabs/fileupload/locator/URILocatorImpl.java b/src/main/java/org/sasanlabs/fileupload/locator/URILocatorImpl.java index b150eb7..7423865 100644 --- a/src/main/java/org/sasanlabs/fileupload/locator/URILocatorImpl.java +++ b/src/main/java/org/sasanlabs/fileupload/locator/URILocatorImpl.java @@ -69,13 +69,13 @@ private URI parseResponseAndGetCompleteURI( .toString() .indexOf( FileUploadConfiguration.getInstance() - .getDynamicLocationStartIdentifier()); + .getParseResponseStartIdentifier()); int endIndex = msg.getResponseBody() .toString() .indexOf( FileUploadConfiguration.getInstance() - .getDynamicLocationEndIdentifier()); + .getParseResponseEndIdentifier()); if (startIndex < 0 || endIndex < 0 || startIndex > endIndex) { throw new FileUploadException( "StartIndex or EndIndex configuration is either not present in the response or invalid. Start index:" @@ -89,7 +89,7 @@ private URI parseResponseAndGetCompleteURI( .substring( startIndex + FileUploadConfiguration.getInstance() - .getDynamicLocationStartIdentifier() + .getParseResponseStartIdentifier() .length(), endIndex); return this.getCompleteURI(uriRegex, fileName, originalMsg); @@ -126,10 +126,10 @@ public URI get( } else { if (StringUtils.isNotBlank( FileUploadConfiguration.getInstance() - .getDynamicLocationStartIdentifier()) + .getParseResponseStartIdentifier()) && StringUtils.isNotBlank( FileUploadConfiguration.getInstance() - .getDynamicLocationEndIdentifier())) { + .getParseResponseEndIdentifier())) { try { return this.parseResponseAndGetCompleteURI(msg, fileName, msg); } catch (FileUploadException e) { diff --git a/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java b/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java index 07ffec3..7224663 100644 --- a/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java +++ b/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java @@ -237,9 +237,8 @@ public void initParam(Object optionParams) { dynamicLocationConfigurationURIRegex.setText( fileUploadConfiguration.getDynamicLocationURIRegex()); parseResponseStartIdentifier.setText( - fileUploadConfiguration.getDynamicLocationStartIdentifier()); - parseResponseEndIdentifier.setText( - fileUploadConfiguration.getDynamicLocationEndIdentifier()); + fileUploadConfiguration.getParseResponseStartIdentifier()); + parseResponseEndIdentifier.setText(fileUploadConfiguration.getParseResponseEndIdentifier()); } @Override @@ -257,12 +256,16 @@ public void validateParam(Object optionParams) throws Exception { && (isDynamicUrlPresent || isStartIdentifierPresent || isEndIdentifierPresent)) { throw new IllegalArgumentException( FileUploadI18n.getMessage( - "fileupload.settings.alert.static.dynamicconfiguration.both.present")); + "fileupload.settings.alert.static.dynamicconfiguration.parseconfiguration.present")); } else if ((isStartIdentifierPresent && !isEndIdentifierPresent) || (!isStartIdentifierPresent && isEndIdentifierPresent)) { throw new IllegalArgumentException( FileUploadI18n.getMessage( "fileupload.settings.alert.invalid.httpresponseparseconfiguration")); + } else if (isDynamicUrlPresent && !isStartIdentifierPresent) { + throw new IllegalArgumentException( + FileUploadI18n.getMessage( + "fileupload.settings.alert.invalid.dynamicconfiguration.parseidentifier.not.present")); } } @@ -279,9 +282,9 @@ public void saveParam(Object optionParams) throws Exception { this.staticLocationConfigurationURIRegex.getText()); fileUploadConfiguration.setDynamicLocationURIRegex( this.dynamicLocationConfigurationURIRegex.getText()); - fileUploadConfiguration.setDynamicLocationStartIdentifier( + fileUploadConfiguration.setParseResponseStartIdentifier( this.parseResponseStartIdentifier.getText()); - fileUploadConfiguration.setDynamicLocationEndIdentifier( + fileUploadConfiguration.setParseResponseEndIdentifier( this.parseResponseEndIdentifier.getText()); } } diff --git a/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties b/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties index 4d1224f..860c33b 100755 --- a/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties +++ b/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties @@ -7,12 +7,13 @@ fileupload.settings.urilocator.staticlocation.uriregex=URI Regex fileupload.settings.urilocator.dynamiclocation.title=Dynamic Location Configuration fileupload.settings.urilocator.dynamiclocation.uriregex=URI Regex -fileupload.settings.urilocator.parseresponseconfiguration.title=Parse Http Response Configuration +fileupload.settings.urilocator.parseresponseconfiguration.title=Parse HTTP Response Configuration fileupload.settings.urilocator.parseresponseconfiguration.startidentifer=Start Identifier fileupload.settings.urilocator.parseresponseconfiguration.endidentifer=End Identifier -fileupload.settings.alert.invalid.httpresponseparseconfiguration=Both dynamic start and end identifier should be present. -fileupload.settings.alert.static.dynamicconfiguration.both.present=Only one of the static and dynamic configuration should be present. +fileupload.settings.alert.invalid.httpresponseparseconfiguration=Both parse HTTP response start and end identifier should be present. +fileupload.settings.alert.static.dynamicconfiguration.parseconfiguration.present=Static configuration should not be present with dynamic or parse HTTP response configuration. +fileupload.settings.alert.invalid.dynamicconfiguration.parseidentifier.not.present=Both dynamic configuration and parse HTTP response configuration should be present. # Alert details fileupload.alert.attack=Retrieval Request: {0} \n Retrieval Response: {1}