From 4ff65b691f0b4c2814d17ccb4931c27b8be3eb13 Mon Sep 17 00:00:00 2001 From: karan preet singh sasan Date: Mon, 21 Dec 2020 01:00:23 +0530 Subject: [PATCH 01/53] First commit --- CHANGELOG.md | 17 ++ README.md | 2 + owasp-zap-fileupload-addon.gradle.kts | 50 ++++++ settings.gradle.kts | 1 + .../org/sasanlabs/fileupload/Constants.java | 7 + .../fileupload/FileUploadExtension.java | 68 ++++++++ .../fileupload/FileUploadScanRule.java | 128 +++++++++++++++ .../fileupload/PreflightResourceLocator.java | 17 ++ .../PreflightResourceLocatorImpl.java | 15 ++ .../fileupload/attacks/AttackVector.java | 148 ++++++++++++++++++ .../attacks/FileUploadAttackExecutor.java | 57 +++++++ .../attacks/FileUploadException.java | 19 +++ .../attacks/impl/ExtensionContentType.java | 21 +++ .../attacks/impl/FileParameter.java | 52 ++++++ .../ImageBasedJSPRemoteCodeExecution.java | 18 +++ .../attacks/impl/PathTraversal.java | 36 +++++ .../fileupload/attacks/impl/PhpRCE.java | 11 ++ .../impl/PlainOldJSPRemoteCodeExecution.java | 67 ++++++++ .../attacks/impl/XSSByHtmlUpload.java | 94 +++++++++++ .../fileupload/matcher/ContentMatcher.java | 13 ++ .../matcher/impl/MD5HashResponseMatcher.java | 56 +++++++ .../fileupload/redownloader/Redownloader.java | 4 + .../attackvectors/images/1*1_Default.gif | Bin 0 -> 37 bytes .../images/1*1_Default_JSP_Injected_EXIF.gif | Bin 0 -> 80 bytes 24 files changed, 901 insertions(+) create mode 100644 CHANGELOG.md create mode 100644 README.md create mode 100644 owasp-zap-fileupload-addon.gradle.kts create mode 100644 settings.gradle.kts create mode 100644 src/main/java/org/sasanlabs/fileupload/Constants.java create mode 100644 src/main/java/org/sasanlabs/fileupload/FileUploadExtension.java create mode 100644 src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java create mode 100644 src/main/java/org/sasanlabs/fileupload/PreflightResourceLocator.java create mode 100644 src/main/java/org/sasanlabs/fileupload/PreflightResourceLocatorImpl.java create mode 100644 src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java create mode 100644 src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java create mode 100644 src/main/java/org/sasanlabs/fileupload/attacks/FileUploadException.java create mode 100644 src/main/java/org/sasanlabs/fileupload/attacks/impl/ExtensionContentType.java create mode 100644 src/main/java/org/sasanlabs/fileupload/attacks/impl/FileParameter.java create mode 100644 src/main/java/org/sasanlabs/fileupload/attacks/impl/ImageBasedJSPRemoteCodeExecution.java create mode 100644 src/main/java/org/sasanlabs/fileupload/attacks/impl/PathTraversal.java create mode 100644 src/main/java/org/sasanlabs/fileupload/attacks/impl/PhpRCE.java create mode 100644 src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPRemoteCodeExecution.java create mode 100644 src/main/java/org/sasanlabs/fileupload/attacks/impl/XSSByHtmlUpload.java create mode 100644 src/main/java/org/sasanlabs/fileupload/matcher/ContentMatcher.java create mode 100644 src/main/java/org/sasanlabs/fileupload/matcher/impl/MD5HashResponseMatcher.java create mode 100644 src/main/java/org/sasanlabs/fileupload/redownloader/Redownloader.java create mode 100644 src/main/resources/org/sasanlabs/attackvectors/images/1*1_Default.gif create mode 100644 src/main/resources/org/sasanlabs/attackvectors/images/1*1_Default_JSP_Injected_EXIF.gif diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..4394de8 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,17 @@ +# Changelog +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/). + +## Unreleased + +### Added + - Increased the number of requests for High threshold to 18 from 12. + - Client side configuration alerts will not stop the scanner from scanning server side configurations. + - Support for validating usage of publicly well known HMac secrets for signing JWT. + +## [1.0.0] - 2020-09-03 + + - First version of JWT Support. + - Contains scanning rules for basic JWT related vulnerabilities. + - Contains JWT Fuzzer for fuzzing the JWT's present in the request. diff --git a/README.md b/README.md new file mode 100644 index 0000000..3ceda5c --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# owasp-zap-fileupload-addon +File Upload Scan Rule diff --git a/owasp-zap-fileupload-addon.gradle.kts b/owasp-zap-fileupload-addon.gradle.kts new file mode 100644 index 0000000..830a26e --- /dev/null +++ b/owasp-zap-fileupload-addon.gradle.kts @@ -0,0 +1,50 @@ + +import org.zaproxy.gradle.addon.AddOnStatus +import org.zaproxy.gradle.addon.misc.ConvertMarkdownToHtml + +plugins { + // id("com.diffplug.gradle.spotless") version "3.27.2" + // id("com.github.ben-manes.versions") version "0.28.0" + `java-library` + // id("org.zaproxy.add-on") version "0.3.0" +} + +repositories { + mavenCentral() +} + +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} + +spotless { + java { + // Don't enforce the license, just the format. + clearSteps() + googleJavaFormat().aosp() + } +} + +tasks.withType().configureEach { options.encoding = "utf-8" } + +version = "1.0.0" +description = "Detect File upload requests and scan them to find related vulnerabilities" + +zapAddOn { + addOnName.set("File upload Scan Rule") + zapVersion.set("2.9.0") + addOnStatus.set(AddOnStatus.ALPHA) + + manifest { + author.set("KSASAN preetkaran20@gmail.com") + repo.set("https://github.com/SasanLabs/owasp-zap-fileupload-addon/") + dependencies { + } + changesFile.set(tasks.named("generateManifestChanges").flatMap { it.html }) + } +} + +dependencies { + // implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar")))) +} diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..5dbda81 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1 @@ +rootProject.name = "fileupload" diff --git a/src/main/java/org/sasanlabs/fileupload/Constants.java b/src/main/java/org/sasanlabs/fileupload/Constants.java new file mode 100644 index 0000000..2f03727 --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/Constants.java @@ -0,0 +1,7 @@ +package org.sasanlabs.fileupload; + +public interface Constants { + String EMPTY_STRING = ""; + String PERIOD = "."; + String NULL_BYTE_CHARACTER = String.valueOf((char) 0); +} diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadExtension.java b/src/main/java/org/sasanlabs/fileupload/FileUploadExtension.java new file mode 100644 index 0000000..e9b6174 --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadExtension.java @@ -0,0 +1,68 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2019 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sasanlabs.fileupload; + +import org.apache.log4j.Logger; +import org.parosproxy.paros.extension.ExtensionAdaptor; +import org.parosproxy.paros.extension.ExtensionHook; +import org.parosproxy.paros.extension.ViewDelegate; + +/** + * @author KSASAN preetkaran20@gmail.com + * @since TODO add version + */ +public class FileUploadExtension extends ExtensionAdaptor { + + protected static final Logger LOGGER = Logger.getLogger(FileUploadExtension.class); + + @Override + public String getAuthor() { + return "KSASAN preetkaran20@gmail.com"; + } + + @Override + public void init() {} + + @Override + public void initView(ViewDelegate view) { + super.initView(view); + } + + @Override + public void hook(ExtensionHook extensionHook) { + super.hook(extensionHook); + LOGGER.debug("FileUpload Extension loaded successfully"); + } + + @Override + public void unload() { + super.unload(); + } + + @Override + public boolean supportsDb(String type) { + return true; + } + + @Override + public boolean canUnload() { + return true; + } +} diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java new file mode 100644 index 0000000..2ed209b --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java @@ -0,0 +1,128 @@ +package org.sasanlabs.fileupload; + +import java.io.IOException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.apache.log4j.Logger; +import org.parosproxy.paros.core.scanner.AbstractAppVariantPlugin; +import org.parosproxy.paros.core.scanner.Category; +import org.parosproxy.paros.core.scanner.NameValuePair; +import org.parosproxy.paros.core.scanner.Variant; +import org.parosproxy.paros.core.scanner.VariantMultipartFormParameters; +import org.parosproxy.paros.network.HttpMessage; +import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; + +/** @author KSASAN preetkaran20@gmail.com */ +public class FileUploadScanRule extends AbstractAppVariantPlugin { + + private static final int PLUGIN_ID = 110009; + private static final String NAME = "File Upload"; // JWTI18n.getMessage("jwt.scanner.name"); + private static final String DESCRIPTION = + "File Upload"; // JWTI18n.getMessage("jwt.scanner.description"); + private static final String SOLUTION = "File Upload"; // JWTI18n.getMessage("jwt.scanner.soln"); + private static final String REFERENCE = + "File Upload"; // JWTI18n.getMessage("jwt.scanner.refs"); + private static final Logger LOGGER = Logger.getLogger(FileUploadScanRule.class); + + private static final Set ALLOWED_TYPES = + new HashSet( + Arrays.asList( + NameValuePair.TYPE_MULTIPART_DATA_FILE_CONTENTTYPE, + NameValuePair.TYPE_MULTIPART_DATA_FILE_NAME, + NameValuePair.TYPE_MULTIPART_DATA_FILE_PARAM, + NameValuePair.TYPE_MULTIPART_DATA_PARAM)); + /* + * Need to check what to include do we need to include XXE/XSS/Path Traversal in + * this addon or we need to correct those. Persistent XXS/XXE/PathTraversal + * might be different + * + * Will not include the reflected XSS because it should work and i have checked + * it works. + */ + + // debug if all these types will be there in all Multipart requests + // @Override + public void scan(HttpMessage msg, Variant variant) { + try { + if (variant instanceof VariantMultipartFormParameters) { + List nameValuePairs = variant.getParamList(); + nameValuePairs.forEach( + (nameValuePair) -> + LOGGER.error( + nameValuePair.getName() + " " + nameValuePair.getValue())); + FileUploadAttackExecutor fileUploadAttackExecutor = + new FileUploadAttackExecutor(msg, this, variant); + fileUploadAttackExecutor.executeAttack(); + } + } catch (Exception ex) { + + } + } + + public void raiseAlert( + int risk, + int confidence, + String name, + String description, + String uri, + String param, + String attack, + String otherInfo, + String solution, + HttpMessage msg) { + newAlert() + .setRisk(risk) + .setConfidence(confidence) + .setName(name) + .setDescription(description) + .setUri(uri) + .setParam(param) + .setAttack(attack) + .setOtherInfo(otherInfo) + .setSolution(solution) + .setMessage(msg) + .raise(); + } + + public void sendAndRecieve(HttpMessage msg) throws IOException { + this.sendAndReceive(msg); + } + + @Override + public int getId() { + return PLUGIN_ID; + } + + @Override + public String getName() { + return NAME; + } + + @Override + public String getDescription() { + return DESCRIPTION; + } + + @Override + public String getSolution() { + return SOLUTION; + } + + @Override + public String getReference() { + return REFERENCE; + } + + @Override + public int getCategory() { + return Category.MISC; + } + + // @Override + public void scan(HttpMessage msg, String param, String value) { + // TODO Auto-generated method stub + LOGGER.error("Done"); + } +} diff --git a/src/main/java/org/sasanlabs/fileupload/PreflightResourceLocator.java b/src/main/java/org/sasanlabs/fileupload/PreflightResourceLocator.java new file mode 100644 index 0000000..b3959dd --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/PreflightResourceLocator.java @@ -0,0 +1,17 @@ +package org.sasanlabs.fileupload; + +import org.apache.commons.httpclient.URI; +import org.apache.commons.httpclient.URIException; +import org.parosproxy.paros.network.HttpMessage; + +/** + * {@code PreflightResourceLocator} class is used to find the URL either by parsing the {@code + * HttpMessage} or reading the configuration mentioned in the options tab. + * + *

This class also handles the "regex based configuration" e.g "url/$fileName" + * + * @author preetkaran20@gmail.com KSASAN + */ +public interface PreflightResourceLocator { + URI get(HttpMessage msg) throws URIException; +} diff --git a/src/main/java/org/sasanlabs/fileupload/PreflightResourceLocatorImpl.java b/src/main/java/org/sasanlabs/fileupload/PreflightResourceLocatorImpl.java new file mode 100644 index 0000000..b1bf759 --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/PreflightResourceLocatorImpl.java @@ -0,0 +1,15 @@ +package org.sasanlabs.fileupload; + +import org.apache.commons.httpclient.URI; +import org.apache.commons.httpclient.URIException; +import org.parosproxy.paros.network.HttpMessage; + +public class PreflightResourceLocatorImpl implements PreflightResourceLocator { + + @Override + public URI get(HttpMessage msg) throws URIException { + byte[] responseBody = msg.getResponseBody().getBytes(); + // Say static configuration + return new URI("http://localhost:9090/contentDispositionUpload/karan.html"); + } +} diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java new file mode 100644 index 0000000..659070d --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java @@ -0,0 +1,148 @@ +package org.sasanlabs.fileupload.attacks; + +import java.io.IOException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; +import java.util.Base64; +import java.util.List; +import org.apache.commons.httpclient.URIException; +import org.parosproxy.paros.core.scanner.NameValuePair; +import org.parosproxy.paros.network.HttpMessage; +import org.sasanlabs.fileupload.FileUploadScanRule; +import org.sasanlabs.fileupload.PreflightResourceLocatorImpl; +import org.sasanlabs.fileupload.attacks.impl.FileParameter; +import org.sasanlabs.fileupload.matcher.ContentMatcher; + +/** + * {@code AttackVector} interface is implemented by various attack vector implementations e.g. XSS, + * JSP RCE, PHP RCE etc. + * + * @author KSASAN preetkaran20@gmail.com + */ +public interface AttackVector { + + /** + * @param modifiedMsg + * @param fileUploadScanRule + * @return + * @throws IOException + */ + default HttpMessage executePreflightRequest( + HttpMessage modifiedMsg, FileUploadScanRule fileUploadScanRule) throws IOException { + HttpMessage preflightMsg = new HttpMessage(); + preflightMsg.getRequestHeader().setURI(new PreflightResourceLocatorImpl().get(modifiedMsg)); + preflightMsg.getRequestHeader().setMethod("GET"); + preflightMsg.getRequestHeader().setCookies(modifiedMsg.getRequestHeader().getHttpCookies()); + fileUploadScanRule.sendAndRecieve(preflightMsg); + return preflightMsg; + } + + default boolean genericAttackExecutor( + FileUploadAttackExecutor fileUploadAttackExecutor, + ContentMatcher md5HashResponseMatcher, + String payload, + String baseFileName, + List fileParameters) + throws IOException { + List nameValuePairs = fileUploadAttackExecutor.getVariant().getParamList(); + HttpMessage originalMsg = fileUploadAttackExecutor.getOriginalHttpMessage(); + FileUploadScanRule fileUploadScanRule = fileUploadAttackExecutor.getFileUploadScanRule(); + String originalFileName = null; + for (NameValuePair nameValuePair : nameValuePairs) { + if (nameValuePair.getType() == NameValuePair.TYPE_MULTIPART_DATA_FILE_NAME) { + originalFileName = nameValuePair.getValue(); + } + } + for (FileParameter fileParameter : fileParameters) { + HttpMessage newMsg = originalMsg.cloneRequest(); + for (NameValuePair nameValuePair : nameValuePairs) { + if (nameValuePair.getType() == NameValuePair.TYPE_MULTIPART_DATA_FILE_NAME) { + fileUploadScanRule.setParameter( + newMsg, + nameValuePair, + nameValuePair.getName(), + fileParameter.getFileName(originalFileName, baseFileName)); + } + if (nameValuePair.getType() == NameValuePair.TYPE_MULTIPART_DATA_FILE_PARAM) { + fileUploadScanRule.setParameter( + newMsg, nameValuePair, nameValuePair.getName(), payload); + } + if (nameValuePair.getType() == NameValuePair.TYPE_MULTIPART_DATA_FILE_CONTENTTYPE) { + fileUploadScanRule.setParameter( + newMsg, + nameValuePair, + nameValuePair.getName(), + fileParameter.getContentType()); + } + } + fileUploadScanRule.sendAndRecieve(newMsg); + HttpMessage preflightMsg = this.executePreflightRequest(newMsg, fileUploadScanRule); + if (md5HashResponseMatcher.match(preflightMsg)) { + return true; + } + } + return false; + } + + // Flexi Injector is quite easy as in case uploaded files are base64 encoded or + // something like that + // the scanner asks for the input file and then compare the request (whcih might + // be encoded) with the input and then operate accordingly. + default boolean executeAttackAndRaiseAlert( + HttpMessage originalMsg, + HttpMessage modifiedMsg, + FileUploadScanRule fileUploadScanRule, + ContentMatcher responseMatcher) + throws URIException, NullPointerException, IOException { + HttpMessage preflightMsg = new HttpMessage(); + preflightMsg.getRequestHeader().setURI(new PreflightResourceLocatorImpl().get(modifiedMsg)); + preflightMsg.getRequestHeader().setMethod("GET"); + preflightMsg.getRequestHeader().setCookies(modifiedMsg.getRequestHeader().getHttpCookies()); + fileUploadScanRule.sendAndRecieve(preflightMsg); + + // For XSS only + String headerValue = preflightMsg.getResponseHeader().getHeader("Content-Disposition"); + if (headerValue == null || headerValue.equals("inline")) { + // check content disposition + // preflightMsg.getResponseHeader(). + try { + MessageDigest messageDigest = MessageDigest.getInstance("MD5"); + byte[] digest = + messageDigest.digest( + Base64.getEncoder() + .encode(preflightMsg.getResponseBody().getBytes())); + return Arrays.equals( + digest, + messageDigest.digest( + Base64.getEncoder() + .encode(modifiedMsg.getResponseBody().getBytes()))); + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + // Try finding the URL in msg + // if found + // do a preflight request + // compare the results + // if not + // check if static url is selected + // do prefligh request with the same file name + // compare result + // try guessing the name + // if found compare result + return false; + }; + + /** + * Executes the attack and checks if it is successful or not and then raise alert in case of + * successful execution. + * + * @param fileUploadAttackExecutor + * @return {@code true} if attack is successful else {@code false} + * @throws FileUploadException + */ + boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) throws FileUploadException; +} diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java b/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java new file mode 100644 index 0000000..baf7133 --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java @@ -0,0 +1,57 @@ +package org.sasanlabs.fileupload.attacks; + +import java.util.Arrays; +import java.util.List; +import org.parosproxy.paros.core.scanner.Variant; +import org.parosproxy.paros.network.HttpMessage; +import org.sasanlabs.fileupload.FileUploadScanRule; +import org.sasanlabs.fileupload.attacks.impl.XSSByHtmlUpload; + +/** + * {@code FileUploadAttackExecutor} class is used to find File Upload vulnerability by executing + * list of attack vector. + * + * @author KSASAN preetkaran20@gmail.com + */ +public class FileUploadAttackExecutor { + + private HttpMessage originalHttpMessage; + private FileUploadScanRule fileUploadScanRule; + private Variant variant; + private List attackVectors = Arrays.asList(new XSSByHtmlUpload()); + + public FileUploadAttackExecutor( + HttpMessage originalHttpMessage, + FileUploadScanRule fileUploadScanRule, + Variant variant) { + super(); + this.originalHttpMessage = originalHttpMessage; + this.fileUploadScanRule = fileUploadScanRule; + this.variant = variant; + } + + public boolean executeAttack() throws FileUploadException { + for (AttackVector attackVector : attackVectors) { + if (attackVector.execute(this)) { + return true; + } + } + return false; + } + + public HttpMessage getOriginalHttpMessage() { + return originalHttpMessage; + } + + public FileUploadScanRule getFileUploadScanRule() { + return fileUploadScanRule; + } + + public Variant getVariant() { + return variant; + } + + public List getAttackVectors() { + return attackVectors; + } +} diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadException.java b/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadException.java new file mode 100644 index 0000000..aa0dd10 --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadException.java @@ -0,0 +1,19 @@ +package org.sasanlabs.fileupload.attacks; + +/** + * {@code FileUploadException} is an exception class for FileUpload Scan Rule. It wraps around + * multiple other types of exception and might be very useful in future. + * + * @author preetkaran20@gmail.com KSASAN + */ +public class FileUploadException extends Exception { + private static final long serialVersionUID = 372527297369183960L; + + public FileUploadException(Throwable th) { + super(th); + } + + public FileUploadException(String message, Throwable th) { + super(message, th); + } +} diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/impl/ExtensionContentType.java b/src/main/java/org/sasanlabs/fileupload/attacks/impl/ExtensionContentType.java new file mode 100644 index 0000000..60a41a7 --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/attacks/impl/ExtensionContentType.java @@ -0,0 +1,21 @@ +package org.sasanlabs.fileupload.attacks.impl; + +/** @author KSASAN preetkaran20@gmail.com */ +public class ExtensionContentType { + private String extension; + private String contentType; + + public ExtensionContentType(String extension, String contentType) { + super(); + this.extension = extension; + this.contentType = contentType; + } + + public String getExtension() { + return extension; + } + + public String getContentType() { + return contentType; + } +} diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/impl/FileParameter.java b/src/main/java/org/sasanlabs/fileupload/attacks/impl/FileParameter.java new file mode 100644 index 0000000..88c17bf --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/attacks/impl/FileParameter.java @@ -0,0 +1,52 @@ +package org.sasanlabs.fileupload.attacks.impl; + +import java.util.Date; +import java.util.Random; +import org.sasanlabs.fileupload.Constants; + +/** + * {@code FileParameter} class is used to represent the file object ... + * + * @author KSASAN preetkaran20@gmail.com + */ +public class FileParameter { + + private String baseFileName; + private String extension; + private String contentType; + private boolean useOriginalExtention = false; + + public FileParameter(String extension, String contentType) { + super(); + this.baseFileName = String.valueOf(new Random(new Date().getTime()).nextLong()); + this.extension = extension; + this.contentType = contentType; + } + + public FileParameter(String extension, String contentType, boolean useOriginalExtension) { + super(); + this.baseFileName = String.valueOf(new Random(new Date().getTime()).nextLong()); + this.extension = extension; + this.contentType = contentType; + this.useOriginalExtention = useOriginalExtension; + } + + public String getContentType() { + return contentType; + } + + public String getFileName(String originalFileName, String newBaseFileName) { + String extension; + if (this.useOriginalExtention && originalFileName != null) { + int firstIndexOfPeriodCharacter = originalFileName.indexOf(Constants.PERIOD); + String originalExtension = ""; + if (firstIndexOfPeriodCharacter >= 0) { + originalExtension = originalFileName.substring(firstIndexOfPeriodCharacter + 1); + } + extension = originalExtension + this.extension; + } else { + extension = this.extension; + } + return String.valueOf(newBaseFileName) + this.baseFileName + Constants.PERIOD + extension; + } +} diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/impl/ImageBasedJSPRemoteCodeExecution.java b/src/main/java/org/sasanlabs/fileupload/attacks/impl/ImageBasedJSPRemoteCodeExecution.java new file mode 100644 index 0000000..702fe1f --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/attacks/impl/ImageBasedJSPRemoteCodeExecution.java @@ -0,0 +1,18 @@ +package org.sasanlabs.fileupload.attacks.impl; + +import org.sasanlabs.fileupload.attacks.AttackVector; +import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; +import org.sasanlabs.fileupload.attacks.FileUploadException; + +public class ImageBasedJSPRemoteCodeExecution implements AttackVector { + + private static final String GIF_IMAGE_JSP_INJECTED_IN_EXIF_BASE64_ENCODED = + "R0lGODlhAQABAHAAACH5BAUAAAAAIf4nPCVAIHBhZ2UgaW1wb3J0PWphdmEudXRpbC4qLGphdmEuaW8uKiU+ACwAAAAAAQABAAACAkQBADs="; + + @Override + public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) + throws FileUploadException { + // TODO Auto-generated method stub + return false; + } +} diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/impl/PathTraversal.java b/src/main/java/org/sasanlabs/fileupload/attacks/impl/PathTraversal.java new file mode 100644 index 0000000..12646eb --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/attacks/impl/PathTraversal.java @@ -0,0 +1,36 @@ +package org.sasanlabs.fileupload.attacks.impl; + +/** @author KSASAN preetkaran20@gmail.com */ +public class PathTraversal /*implements AttackVector*/ { + // + // private static final String XSS_UPLOADED_FILE_BASE_NAME = "XSSByHtmlUpload_"; + // private static final String XSS_PAYLOAD_HTML_FILE = "Testing + // XSS"; + // + // private static final List HTML_EXTENSIONS = Arrays.asList("htm", "html", "xhtml"); + // private static final List CONTENT_TYPES = + // Arrays.asList(Constants.EMPTY_STRING,"text/html", "text/plain"); + // + // private static final ContentMatcher CONTENT_MATCHER = new MD5HashResponseMatcher(); + // + // @Override + // public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) throws + // FileUploadException { + // // TODO Auto-generated method stub + // return false; + // } + + // private boolean isContentDispositionInline(HttpMessage preflightMsg) { + // String headerValue = preflightMsg.getResponseHeader().getHeader("Content-Disposition"); + // if (headerValue == null || headerValue.trim().equals(Constants.EMPTY_STRING) || + // headerValue.equals("inline")) { + // return true; + // } + // return false; + // } + + /** + * Execute the experiment 1. change only content type 2. change only html or htm 3. change html + * extension and text/plain 4. change htm extension and text/plain or text/html + */ +} diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/impl/PhpRCE.java b/src/main/java/org/sasanlabs/fileupload/attacks/impl/PhpRCE.java new file mode 100644 index 0000000..8d533d8 --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/attacks/impl/PhpRCE.java @@ -0,0 +1,11 @@ +package org.sasanlabs.fileupload.attacks.impl; +/** + * https://vulp3cula.gitbook.io/hackers-grimoire/exploitation/web-application/file-upload-bypass + * + * @author KSASAN preetkaran20@gmail.com + *

Eicar -> try uploading and downloading file and if you are able to do so that means there + * is no antivirus present on server hence we know that any virus can impact the server. + * https://www.youtube.com/watch?v=gPo-NPvuqbs (For Vulnerable Application we might need to have + * some docker with antivirus in it.) + */ +public class PhpRCE {} diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPRemoteCodeExecution.java b/src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPRemoteCodeExecution.java new file mode 100644 index 0000000..922bd63 --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPRemoteCodeExecution.java @@ -0,0 +1,67 @@ +package org.sasanlabs.fileupload.attacks.impl; + +import static org.sasanlabs.fileupload.Constants.NULL_BYTE_CHARACTER; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import org.sasanlabs.fileupload.Constants; +import org.sasanlabs.fileupload.attacks.AttackVector; +import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; +import org.sasanlabs.fileupload.attacks.FileUploadException; +import org.sasanlabs.fileupload.matcher.ContentMatcher; +import org.sasanlabs.fileupload.matcher.impl.MD5HashResponseMatcher; + +/** @author KSASAN preetkaran20@gmail.com */ + +// TODO check if we need to have case sensitive extensions like JsP or jSP or hTML or HtmL or hTmL +// etc +public class PlainOldJSPRemoteCodeExecution implements AttackVector { + + private static final String JSP_UPLOADED_FILE_BASE_NAME = "JSPUploaded_"; + private static final String JSP_PAYLOAD = "<% out.print(\"Sasan\"); %>"; + + private static final ContentMatcher CONTENT_MATCHER = new MD5HashResponseMatcher("Sasan"); + + private static final List FILE_PARAMETERS = + Arrays.asList( + new FileParameter("jsp", Constants.EMPTY_STRING), + new FileParameter("jsp", "application/x-jsp"), + new FileParameter("jsp.", Constants.EMPTY_STRING, true), + new FileParameter("jsp.", "application/x-jsp", true), + new FileParameter("jsp." + NULL_BYTE_CHARACTER, Constants.EMPTY_STRING, true), + new FileParameter("jsp." + NULL_BYTE_CHARACTER, "application/x-jsp", true)); + + @Override + public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) + throws FileUploadException { + boolean result = false; + try { + result = + this.genericAttackExecutor( + fileUploadAttackExecutor, + CONTENT_MATCHER, + JSP_PAYLOAD, + JSP_UPLOADED_FILE_BASE_NAME, + FILE_PARAMETERS); + if (result) { + fileUploadAttackExecutor + .getFileUploadScanRule() + .raiseAlert( + 1, + 1, + "", + "", + "", + "", + "", + "", + "", + fileUploadAttackExecutor.getOriginalHttpMessage()); + } + } catch (IOException e) { + throw new FileUploadException(e); + } + return result; + } +} diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/impl/XSSByHtmlUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/impl/XSSByHtmlUpload.java new file mode 100644 index 0000000..33ab5e5 --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/attacks/impl/XSSByHtmlUpload.java @@ -0,0 +1,94 @@ +package org.sasanlabs.fileupload.attacks.impl; + +import static org.sasanlabs.fileupload.Constants.NULL_BYTE_CHARACTER; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import org.parosproxy.paros.network.HttpMessage; +import org.sasanlabs.fileupload.Constants; +import org.sasanlabs.fileupload.attacks.AttackVector; +import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; +import org.sasanlabs.fileupload.attacks.FileUploadException; +import org.sasanlabs.fileupload.matcher.ContentMatcher; +import org.sasanlabs.fileupload.matcher.impl.MD5HashResponseMatcher; + +/** @author preetkaran20@gmail.com KSASAN */ +public class XSSByHtmlUpload implements AttackVector { + + private static final String XSS_UPLOADED_FILE_BASE_NAME = "XSSByHtmlUpload_"; + private static final String XSS_PAYLOAD_HTML_FILE = + "Testing XSS"; + + private static final ContentMatcher CONTENT_MATCHER = + new MD5HashResponseMatcher( + httpMsg -> isContentDispositionInline(httpMsg), XSS_PAYLOAD_HTML_FILE); + + private static boolean isContentDispositionInline(HttpMessage preflightMsg) { + String headerValue = preflightMsg.getResponseHeader().getHeader("Content-Disposition"); + if (headerValue == null + || headerValue.trim().equals(Constants.EMPTY_STRING) + || headerValue.equals("inline")) { + return true; + } + return false; + } + + private static final List FILE_PARAMETERS = + Arrays.asList( + new FileParameter("htm", Constants.EMPTY_STRING), + new FileParameter("html", Constants.EMPTY_STRING), + new FileParameter("xhtml", Constants.EMPTY_STRING), + new FileParameter("htm", "text/html"), + new FileParameter("html", "text/html"), + new FileParameter("xhtml", "text/html"), + new FileParameter("htm", "text/plain"), + new FileParameter("html", "text/plain"), + new FileParameter("xhtml", "text/plain"), + new FileParameter("htm.", "text/html", true), + new FileParameter("html.", "text/html", true), + new FileParameter("xhtml.", "text/html", true), + new FileParameter("htm." + NULL_BYTE_CHARACTER, "text/html", true), + new FileParameter("html." + NULL_BYTE_CHARACTER, "text/html", true), + new FileParameter("xhtml." + NULL_BYTE_CHARACTER, "text/html", true), + new FileParameter("htm." + NULL_BYTE_CHARACTER, "text/plain", true), + new FileParameter("html." + NULL_BYTE_CHARACTER, "text/plain", true), + new FileParameter("xhtml." + NULL_BYTE_CHARACTER, "text/plain", true)); + + /** + * @throws FileUploadException + * @throws IOException + */ + @Override + public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) + throws FileUploadException { + boolean result = false; + try { + result = + this.genericAttackExecutor( + fileUploadAttackExecutor, + CONTENT_MATCHER, + XSS_PAYLOAD_HTML_FILE, + XSS_UPLOADED_FILE_BASE_NAME, + FILE_PARAMETERS); + if (result) { + fileUploadAttackExecutor + .getFileUploadScanRule() + .raiseAlert( + 1, + 1, + "", + "", + "", + "", + "", + "", + "", + fileUploadAttackExecutor.getOriginalHttpMessage()); + } + } catch (IOException e) { + throw new FileUploadException(e); + } + return result; + } +} diff --git a/src/main/java/org/sasanlabs/fileupload/matcher/ContentMatcher.java b/src/main/java/org/sasanlabs/fileupload/matcher/ContentMatcher.java new file mode 100644 index 0000000..d259756 --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/matcher/ContentMatcher.java @@ -0,0 +1,13 @@ +package org.sasanlabs.fileupload.matcher; + +import org.parosproxy.paros.network.HttpMessage; + +/** + * {@code ContentMatcher} class is used to compare the contents of + * + * @author preetkaran20@gmail.com KSASAN + */ +public interface ContentMatcher { + + boolean match(HttpMessage msg); +} diff --git a/src/main/java/org/sasanlabs/fileupload/matcher/impl/MD5HashResponseMatcher.java b/src/main/java/org/sasanlabs/fileupload/matcher/impl/MD5HashResponseMatcher.java new file mode 100644 index 0000000..ee942f5 --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/matcher/impl/MD5HashResponseMatcher.java @@ -0,0 +1,56 @@ +package org.sasanlabs.fileupload.matcher.impl; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; +import java.util.Objects; +import java.util.function.Predicate; +import org.apache.log4j.Logger; +import org.parosproxy.paros.network.HttpMessage; +import org.sasanlabs.fileupload.matcher.ContentMatcher; + +/** + * {@code MD5HashResponseMatcher} matches {@code MD5} hashes of both the contents + * + * @author KSASAN preetkaran20@gmail.com + */ +public class MD5HashResponseMatcher implements ContentMatcher { + private static final Logger LOGGER = Logger.getLogger(MD5HashResponseMatcher.class); + + private static final Predicate DEFAULT_PRECONDITION = (httpMessage) -> true; + + private Predicate precondition; + private String expectedValue; + + public MD5HashResponseMatcher(String expectedValue) { + this.precondition = DEFAULT_PRECONDITION; + this.expectedValue = expectedValue; + } + + public MD5HashResponseMatcher(Predicate precondition, String expectedValue) { + Objects.requireNonNull(precondition, "Precondition cannot be null"); + this.precondition = precondition; + this.expectedValue = expectedValue; + } + + @Override + public boolean match(HttpMessage msg) { + if (!this.precondition.test(msg)) { + return false; + } + try { + MessageDigest messageDigest = MessageDigest.getInstance("MD5"); + byte[] digest = messageDigest.digest(msg.getRequestBody().getBytes()); + String charSet = msg.getRequestHeader().getCharset(); + Charset responseCharSet = + charSet != null ? Charset.forName(charSet) : StandardCharsets.UTF_8; + return Arrays.equals( + digest, messageDigest.digest(expectedValue.getBytes(responseCharSet))); + } catch (NoSuchAlgorithmException ex) { + LOGGER.debug("Error occurred while comparing MD5 Hash ", ex); + } + return false; + } +} diff --git a/src/main/java/org/sasanlabs/fileupload/redownloader/Redownloader.java b/src/main/java/org/sasanlabs/fileupload/redownloader/Redownloader.java new file mode 100644 index 0000000..0caae4b --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/redownloader/Redownloader.java @@ -0,0 +1,4 @@ +package org.sasanlabs.fileupload.redownloader; + +/** @author KSASAN preetkaran20@gmail.com */ +public interface Redownloader {} diff --git a/src/main/resources/org/sasanlabs/attackvectors/images/1*1_Default.gif b/src/main/resources/org/sasanlabs/attackvectors/images/1*1_Default.gif new file mode 100644 index 0000000000000000000000000000000000000000..57aeed3dba476ea689dadc094cad38a911288797 GIT binary patch literal 37 mcmZ?wbhEHbWMp7uC}3bv{K>+~00cT90wl)3#N@)rU=09cqXX~& literal 0 HcmV?d00001 diff --git a/src/main/resources/org/sasanlabs/attackvectors/images/1*1_Default_JSP_Injected_EXIF.gif b/src/main/resources/org/sasanlabs/attackvectors/images/1*1_Default_JSP_Injected_EXIF.gif new file mode 100644 index 0000000000000000000000000000000000000000..b4acb4471ab4d2a219f75db42498be4fafdacd5f GIT binary patch literal 80 zcmZ?wbhEHbWMp7uC}3bv{K>+~00fHv)NNE96bcg4Qx!6E3-XIfY_k%}67@<;GIR8_ abinM)d_65yI|dz)dXRPoCMFj~25SHpSrP#N literal 0 HcmV?d00001 From 5146f57e59401e8b47156c7bdb54f91ce521eb4f Mon Sep 17 00:00:00 2001 From: karan preet singh sasan Date: Mon, 21 Dec 2020 01:01:19 +0530 Subject: [PATCH 02/53] Small Fix --- CHANGELOG.md | 0 README.md | 0 owasp-zap-fileupload-addon.gradle.kts | 0 settings.gradle.kts | 0 4 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 CHANGELOG.md mode change 100644 => 100755 README.md mode change 100644 => 100755 owasp-zap-fileupload-addon.gradle.kts mode change 100644 => 100755 settings.gradle.kts diff --git a/CHANGELOG.md b/CHANGELOG.md old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/owasp-zap-fileupload-addon.gradle.kts b/owasp-zap-fileupload-addon.gradle.kts old mode 100644 new mode 100755 diff --git a/settings.gradle.kts b/settings.gradle.kts old mode 100644 new mode 100755 From 3192b92d8da4467036df01703d33482236820452 Mon Sep 17 00:00:00 2001 From: karan preet singh sasan Date: Tue, 22 Dec 2020 01:51:16 +0530 Subject: [PATCH 03/53] Small changes --- .../fileupload/AbstractAppVariantPlugin.java | 88 ++++++++++++++++++ .../fileupload/FileUploadScanRule.java | 38 +++++++- .../ImageBasedJSPRemoteCodeExecution.java | 58 +++++++++++- .../impl/ContainsExpectedValueMatcher.java | 40 ++++++++ .../matcher/impl/MD5HashResponseMatcher.java | 12 +-- .../images/1*1_Default_JSP_Injected_EXIF.gif | Bin 80 -> 79 bytes 6 files changed, 226 insertions(+), 10 deletions(-) create mode 100644 src/main/java/org/sasanlabs/fileupload/AbstractAppVariantPlugin.java create mode 100644 src/main/java/org/sasanlabs/fileupload/matcher/impl/ContainsExpectedValueMatcher.java diff --git a/src/main/java/org/sasanlabs/fileupload/AbstractAppVariantPlugin.java b/src/main/java/org/sasanlabs/fileupload/AbstractAppVariantPlugin.java new file mode 100644 index 0000000..68a69ae --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/AbstractAppVariantPlugin.java @@ -0,0 +1,88 @@ +package org.sasanlabs.fileupload; + +import java.util.List; +import org.apache.log4j.Logger; +import org.parosproxy.paros.Constant; +import org.parosproxy.paros.core.scanner.AbstractAppPlugin; +import org.parosproxy.paros.core.scanner.NameValuePair; +import org.parosproxy.paros.core.scanner.Variant; +import org.parosproxy.paros.model.Model; +import org.parosproxy.paros.network.HttpMessage; +import org.zaproxy.zap.extension.ascan.VariantFactory; + +/** + * {@code AbstractAppVariantPlugin} is the abstract base class which is used to run per variant to + * modify multiple name value pairs of the {@code HttpMessage} per variant. + * + * @author KSASAN preetkaran20@gmail.com + */ +public abstract class AbstractAppVariantPlugin extends AbstractAppPlugin { + + private final Logger logger = Logger.getLogger(this.getClass()); + + @Override + public void scan() { + VariantFactory factory = Model.getSingleton().getVariantFactory(); + + List listVariant = + factory.createVariants(this.getParent().getScannerParam(), this.getBaseMsg()); + + if (listVariant.isEmpty()) { + getParent() + .pluginSkipped( + this, + Constant.messages.getString( + "ascan.progress.label.skipped.reason.noinputvectors")); + return; + } + + for (int i = 0; i < listVariant.size() && !isStop(); i++) { + + HttpMessage msg = getNewMsg(); + // ZAP: Removed unnecessary cast. + Variant variant = listVariant.get(i); + try { + variant.setMessage(msg); + scanVariant(variant); + + } catch (Exception e) { + logger.error( + "Error occurred while scanning with variant " + + variant.getClass().getCanonicalName(), + e); + } + + // ZAP: Implement pause and resume + while (getParent().isPaused() && !isStop()) { + try { + Thread.sleep(500); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + } + + /** Scan the current message using the current Variant */ + private void scanVariant(Variant variant) { + HttpMessage msg = getNewMsg(); + try { + scan(msg, variant); + } catch (Exception e) { + logger.error("Error occurred while scanning a message:", e); + } + } + + /** + * Plugin method that need to be implemented for the specific test. The passed message is a copy + * which maintains only the Request's information so if the plugin need to manage the original + * Response body a getBaseMsg() call should be done. the param name and the value are the + * original value retrieved by the crawler and the current applied Variant. + * + * @param msg a copy of the HTTP message currently under scanning + * @param variant + */ + public abstract void scan(HttpMessage msg, Variant variant); + +} diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java index 2ed209b..a4b232a 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java @@ -6,7 +6,6 @@ import java.util.List; import java.util.Set; import org.apache.log4j.Logger; -import org.parosproxy.paros.core.scanner.AbstractAppVariantPlugin; import org.parosproxy.paros.core.scanner.Category; import org.parosproxy.paros.core.scanner.NameValuePair; import org.parosproxy.paros.core.scanner.Variant; @@ -25,7 +24,7 @@ public class FileUploadScanRule extends AbstractAppVariantPlugin { private static final String REFERENCE = "File Upload"; // JWTI18n.getMessage("jwt.scanner.refs"); private static final Logger LOGGER = Logger.getLogger(FileUploadScanRule.class); - + private Variant variant = null; private static final Set ALLOWED_TYPES = new HashSet( Arrays.asList( @@ -46,6 +45,7 @@ public class FileUploadScanRule extends AbstractAppVariantPlugin { // @Override public void scan(HttpMessage msg, Variant variant) { try { + this.variant = variant; if (variant instanceof VariantMultipartFormParameters) { List nameValuePairs = variant.getParamList(); nameValuePairs.forEach( @@ -125,4 +125,38 @@ public void scan(HttpMessage msg, String param, String value) { // TODO Auto-generated method stub LOGGER.error("Done"); } + + /** + * Sets the parameter into the given {@code message}. If both parameter name and value are + * {@code null}, the parameter will be removed. + * + * @param message the message that will be changed + * @param originalPair original name value pair + * @param param the name of the parameter + * @param value the value of the parameter + * @return the parameter set + * @see #setEscapedParameter(HttpMessage, NameValuePair, String, String) + */ + public String setParameter( + HttpMessage message, NameValuePair originalPair, String param, String value) { + return variant.setParameter(message, originalPair, param, value); + } + + /** + * Sets the parameter into the given {@code message}. If both parameter name and value are + * {@code null}, the parameter will be removed. + * + *

The value is expected to be properly encoded/escaped. + * + * @param message the message that will be changed + * @param originalPair original name value pair + * @param param the name of the parameter + * @param value the value of the parameter + * @return the parameter set + * @see #setParameter(HttpMessage,NameValuePair, String, String) + */ + public String setEscapedParameter( + HttpMessage message, NameValuePair originalPair, String param, String value) { + return variant.setEscapedParameter(message, originalPair, param, value); + } } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/impl/ImageBasedJSPRemoteCodeExecution.java b/src/main/java/org/sasanlabs/fileupload/attacks/impl/ImageBasedJSPRemoteCodeExecution.java index 702fe1f..29a85d5 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/impl/ImageBasedJSPRemoteCodeExecution.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/impl/ImageBasedJSPRemoteCodeExecution.java @@ -1,18 +1,72 @@ package org.sasanlabs.fileupload.attacks.impl; +import static org.sasanlabs.fileupload.Constants.NULL_BYTE_CHARACTER; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Base64; +import java.util.List; +import org.parosproxy.paros.network.HttpMessage; +import org.sasanlabs.fileupload.Constants; import org.sasanlabs.fileupload.attacks.AttackVector; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; import org.sasanlabs.fileupload.attacks.FileUploadException; +import org.sasanlabs.fileupload.matcher.impl.ContainsExpectedValueMatcher; public class ImageBasedJSPRemoteCodeExecution implements AttackVector { private static final String GIF_IMAGE_JSP_INJECTED_IN_EXIF_BASE64_ENCODED = - "R0lGODlhAQABAHAAACH5BAUAAAAAIf4nPCVAIHBhZ2UgaW1wb3J0PWphdmEudXRpbC4qLGphdmEuaW8uKiU+ACwAAAAAAQABAAACAkQBADs="; + "R0lGODlhAQABAHAAACH5BAUAAAAAIf4mPCU9ICJTYXNhbkxhYnNfIiArICJaQVBfSWRlbnRpZmllciIgJT4ALAAAAAABAAEAAAICRAEAOw=="; + + private static final String EXPECTED_VALUE = "SasanLabs_ZAP_Identifier"; + private static final String BASE_FILE_NAME = "ImageBasedJSPRCE_"; + + private static final List FILE_PARAMETERS = + Arrays.asList( + new FileParameter("jsp", Constants.EMPTY_STRING), + new FileParameter("jsp", "application/x-jsp"), + new FileParameter("jsp.", Constants.EMPTY_STRING, true), + new FileParameter("jsp.", "application/x-jsp", true), + new FileParameter("jsp." + NULL_BYTE_CHARACTER, Constants.EMPTY_STRING, true), + new FileParameter("jsp." + NULL_BYTE_CHARACTER, "application/x-jsp", true)); @Override public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) throws FileUploadException { - // TODO Auto-generated method stub + try { + byte[] imagePayload = + Base64.getDecoder().decode(GIF_IMAGE_JSP_INJECTED_IN_EXIF_BASE64_ENCODED); + HttpMessage originalMessage = fileUploadAttackExecutor.getOriginalHttpMessage(); + String charSet = originalMessage.getRequestHeader().getCharset(); + Charset requestCharSet = + charSet != null ? Charset.forName(charSet) : StandardCharsets.ISO_8859_1; + String requestPayload = new String(imagePayload, requestCharSet); + System.out.print(charSet); + if (this.genericAttackExecutor( + fileUploadAttackExecutor, + new ContainsExpectedValueMatcher(EXPECTED_VALUE), + requestPayload, + BASE_FILE_NAME, + FILE_PARAMETERS)) { + fileUploadAttackExecutor + .getFileUploadScanRule() + .raiseAlert( + 1, + 1, + this.getClass().getName(), + "", + "", + "", + "", + "", + "", + fileUploadAttackExecutor.getOriginalHttpMessage()); + } + } catch (IOException e) { + throw new FileUploadException(e); + } return false; } } diff --git a/src/main/java/org/sasanlabs/fileupload/matcher/impl/ContainsExpectedValueMatcher.java b/src/main/java/org/sasanlabs/fileupload/matcher/impl/ContainsExpectedValueMatcher.java new file mode 100644 index 0000000..6ea9345 --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/matcher/impl/ContainsExpectedValueMatcher.java @@ -0,0 +1,40 @@ +package org.sasanlabs.fileupload.matcher.impl; + +import java.util.Objects; +import java.util.function.Predicate; +import org.parosproxy.paros.network.HttpMessage; +import org.sasanlabs.fileupload.matcher.ContentMatcher; + +/** + * {@code ContainsExpectedValueMatcher} is used to match if the expected value is present in the + * {@code HttpMessage} response body or not. + * + * @author KSASAN preetkaran20@gmail.com + */ +public class ContainsExpectedValueMatcher implements ContentMatcher { + + private static final Predicate DEFAULT_PRECONDITION = (httpMessage) -> true; + + private Predicate precondition; + private String expectedValue; + + public ContainsExpectedValueMatcher(String expectedValue) { + this.precondition = DEFAULT_PRECONDITION; + this.expectedValue = expectedValue; + } + + public ContainsExpectedValueMatcher(Predicate precondition, String expectedValue) { + Objects.requireNonNull(precondition, "Precondition cannot be null"); + this.precondition = precondition; + this.expectedValue = expectedValue; + } + + @Override + public boolean match(HttpMessage msg) { + if (!this.precondition.test(msg)) { + return false; + } + // Assumption is toString is handled correctly by Owasp ZAP. + return msg.getResponseBody().toString().contains(this.expectedValue); + } +} diff --git a/src/main/java/org/sasanlabs/fileupload/matcher/impl/MD5HashResponseMatcher.java b/src/main/java/org/sasanlabs/fileupload/matcher/impl/MD5HashResponseMatcher.java index ee942f5..854f887 100644 --- a/src/main/java/org/sasanlabs/fileupload/matcher/impl/MD5HashResponseMatcher.java +++ b/src/main/java/org/sasanlabs/fileupload/matcher/impl/MD5HashResponseMatcher.java @@ -1,6 +1,5 @@ package org.sasanlabs.fileupload.matcher.impl; -import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -42,12 +41,13 @@ public boolean match(HttpMessage msg) { } try { MessageDigest messageDigest = MessageDigest.getInstance("MD5"); - byte[] digest = messageDigest.digest(msg.getRequestBody().getBytes()); - String charSet = msg.getRequestHeader().getCharset(); - Charset responseCharSet = - charSet != null ? Charset.forName(charSet) : StandardCharsets.UTF_8; + // Assumption is ZAP will check the charset and returns the response body as "String" as + // per the charset. + byte[] digest = + messageDigest.digest( + msg.getResponseBody().toString().getBytes(StandardCharsets.UTF_8)); return Arrays.equals( - digest, messageDigest.digest(expectedValue.getBytes(responseCharSet))); + digest, messageDigest.digest(expectedValue.getBytes(StandardCharsets.UTF_8))); } catch (NoSuchAlgorithmException ex) { LOGGER.debug("Error occurred while comparing MD5 Hash ", ex); } diff --git a/src/main/resources/org/sasanlabs/attackvectors/images/1*1_Default_JSP_Injected_EXIF.gif b/src/main/resources/org/sasanlabs/attackvectors/images/1*1_Default_JSP_Injected_EXIF.gif index b4acb4471ab4d2a219f75db42498be4fafdacd5f..e5c457414f2a8d79033a0fe12bb28649e7f9e933 100644 GIT binary patch delta 61 zcmWIWpCE3bW}|AWpcI@~oS5g6m{c6Eq@b;!6y+EY@0pUCSCW~QnOdZzplZjU!vF+~ NK*+$v_PcZlmg;P>`6Os*ssmkY7|{o0V9Ws8?E&nWLwr17>ID>uIUlG3YP=0V5DH LFfq9>GFSruMYRtk From e8eaf4f5dd563b201da34e4d9aaa8d68eec7f743 Mon Sep 17 00:00:00 2001 From: karan preet singh sasan Date: Tue, 22 Dec 2020 23:56:36 +0530 Subject: [PATCH 04/53] Some more addition --- .../fileupload/AbstractAppVariantPlugin.java | 12 +- .../fileupload/FileUploadExtension.java | 2 + .../fileupload/FileUploadScanRule.java | 4 +- ...htResourceLocator.java => URILocator.java} | 4 +- ...ceLocatorImpl.java => URILocatorImpl.java} | 3 +- .../fileupload/attacks/AttackVector.java | 8 +- .../{impl => beans}/FileParameter.java | 2 +- .../attacks/impl/ExtensionContentType.java | 21 -- .../ImageBasedJSPRemoteCodeExecution.java | 3 +- .../impl/PlainOldJSPRemoteCodeExecution.java | 9 +- .../impl/PlainOldJSPXRemoteCodeExecution.java | 77 +++++ .../attacks/impl/XSSByHtmlUpload.java | 1 + .../fileupload/ui/FileUploadOptionsPanel.java | 318 ++++++++++++++++++ .../attackvectors/files/jspx_payload.jspx | 7 + 14 files changed, 429 insertions(+), 42 deletions(-) rename src/main/java/org/sasanlabs/fileupload/{PreflightResourceLocator.java => URILocator.java} (76%) rename src/main/java/org/sasanlabs/fileupload/{PreflightResourceLocatorImpl.java => URILocatorImpl.java} (84%) rename src/main/java/org/sasanlabs/fileupload/attacks/{impl => beans}/FileParameter.java (97%) delete mode 100644 src/main/java/org/sasanlabs/fileupload/attacks/impl/ExtensionContentType.java create mode 100644 src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPXRemoteCodeExecution.java create mode 100644 src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java create mode 100644 src/main/resources/org/sasanlabs/attackvectors/files/jspx_payload.jspx diff --git a/src/main/java/org/sasanlabs/fileupload/AbstractAppVariantPlugin.java b/src/main/java/org/sasanlabs/fileupload/AbstractAppVariantPlugin.java index 68a69ae..a98e1f6 100644 --- a/src/main/java/org/sasanlabs/fileupload/AbstractAppVariantPlugin.java +++ b/src/main/java/org/sasanlabs/fileupload/AbstractAppVariantPlugin.java @@ -4,7 +4,6 @@ import org.apache.log4j.Logger; import org.parosproxy.paros.Constant; import org.parosproxy.paros.core.scanner.AbstractAppPlugin; -import org.parosproxy.paros.core.scanner.NameValuePair; import org.parosproxy.paros.core.scanner.Variant; import org.parosproxy.paros.model.Model; import org.parosproxy.paros.network.HttpMessage; @@ -55,11 +54,11 @@ public void scan() { // ZAP: Implement pause and resume while (getParent().isPaused() && !isStop()) { try { - Thread.sleep(500); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } + Thread.sleep(500); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } } } } @@ -84,5 +83,4 @@ private void scanVariant(Variant variant) { * @param variant */ public abstract void scan(HttpMessage msg, Variant variant); - } diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadExtension.java b/src/main/java/org/sasanlabs/fileupload/FileUploadExtension.java index e9b6174..d8fc7f9 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadExtension.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadExtension.java @@ -23,6 +23,7 @@ import org.parosproxy.paros.extension.ExtensionAdaptor; import org.parosproxy.paros.extension.ExtensionHook; import org.parosproxy.paros.extension.ViewDelegate; +import org.sasanlabs.fileupload.ui.FileUploadOptionsPanel; /** * @author KSASAN preetkaran20@gmail.com @@ -48,6 +49,7 @@ public void initView(ViewDelegate view) { @Override public void hook(ExtensionHook extensionHook) { super.hook(extensionHook); + extensionHook.getHookView().addOptionPanel(new FileUploadOptionsPanel()); LOGGER.debug("FileUpload Extension loaded successfully"); } diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java index a4b232a..41ff6fa 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java @@ -45,7 +45,7 @@ public class FileUploadScanRule extends AbstractAppVariantPlugin { // @Override public void scan(HttpMessage msg, Variant variant) { try { - this.variant = variant; + this.variant = variant; if (variant instanceof VariantMultipartFormParameters) { List nameValuePairs = variant.getParamList(); nameValuePairs.forEach( @@ -125,7 +125,7 @@ public void scan(HttpMessage msg, String param, String value) { // TODO Auto-generated method stub LOGGER.error("Done"); } - + /** * Sets the parameter into the given {@code message}. If both parameter name and value are * {@code null}, the parameter will be removed. diff --git a/src/main/java/org/sasanlabs/fileupload/PreflightResourceLocator.java b/src/main/java/org/sasanlabs/fileupload/URILocator.java similarity index 76% rename from src/main/java/org/sasanlabs/fileupload/PreflightResourceLocator.java rename to src/main/java/org/sasanlabs/fileupload/URILocator.java index b3959dd..520cb4c 100644 --- a/src/main/java/org/sasanlabs/fileupload/PreflightResourceLocator.java +++ b/src/main/java/org/sasanlabs/fileupload/URILocator.java @@ -5,13 +5,13 @@ import org.parosproxy.paros.network.HttpMessage; /** - * {@code PreflightResourceLocator} class is used to find the URL either by parsing the {@code + * {@code URILocator} class is used to find the URL either by parsing the {@code * HttpMessage} or reading the configuration mentioned in the options tab. * *

This class also handles the "regex based configuration" e.g "url/$fileName" * * @author preetkaran20@gmail.com KSASAN */ -public interface PreflightResourceLocator { +public interface URILocator { URI get(HttpMessage msg) throws URIException; } diff --git a/src/main/java/org/sasanlabs/fileupload/PreflightResourceLocatorImpl.java b/src/main/java/org/sasanlabs/fileupload/URILocatorImpl.java similarity index 84% rename from src/main/java/org/sasanlabs/fileupload/PreflightResourceLocatorImpl.java rename to src/main/java/org/sasanlabs/fileupload/URILocatorImpl.java index b1bf759..2c8d130 100644 --- a/src/main/java/org/sasanlabs/fileupload/PreflightResourceLocatorImpl.java +++ b/src/main/java/org/sasanlabs/fileupload/URILocatorImpl.java @@ -4,11 +4,12 @@ import org.apache.commons.httpclient.URIException; import org.parosproxy.paros.network.HttpMessage; -public class PreflightResourceLocatorImpl implements PreflightResourceLocator { +public class URILocatorImpl implements URILocator { @Override public URI get(HttpMessage msg) throws URIException { byte[] responseBody = msg.getResponseBody().getBytes(); + // Say static configuration return new URI("http://localhost:9090/contentDispositionUpload/karan.html"); } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java index 659070d..420aae2 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java @@ -10,8 +10,8 @@ import org.parosproxy.paros.core.scanner.NameValuePair; import org.parosproxy.paros.network.HttpMessage; import org.sasanlabs.fileupload.FileUploadScanRule; -import org.sasanlabs.fileupload.PreflightResourceLocatorImpl; -import org.sasanlabs.fileupload.attacks.impl.FileParameter; +import org.sasanlabs.fileupload.URILocatorImpl; +import org.sasanlabs.fileupload.attacks.beans.FileParameter; import org.sasanlabs.fileupload.matcher.ContentMatcher; /** @@ -31,7 +31,7 @@ public interface AttackVector { default HttpMessage executePreflightRequest( HttpMessage modifiedMsg, FileUploadScanRule fileUploadScanRule) throws IOException { HttpMessage preflightMsg = new HttpMessage(); - preflightMsg.getRequestHeader().setURI(new PreflightResourceLocatorImpl().get(modifiedMsg)); + preflightMsg.getRequestHeader().setURI(new URILocatorImpl().get(modifiedMsg)); preflightMsg.getRequestHeader().setMethod("GET"); preflightMsg.getRequestHeader().setCookies(modifiedMsg.getRequestHeader().getHttpCookies()); fileUploadScanRule.sendAndRecieve(preflightMsg); @@ -96,7 +96,7 @@ default boolean executeAttackAndRaiseAlert( ContentMatcher responseMatcher) throws URIException, NullPointerException, IOException { HttpMessage preflightMsg = new HttpMessage(); - preflightMsg.getRequestHeader().setURI(new PreflightResourceLocatorImpl().get(modifiedMsg)); + preflightMsg.getRequestHeader().setURI(new URILocatorImpl().get(modifiedMsg)); preflightMsg.getRequestHeader().setMethod("GET"); preflightMsg.getRequestHeader().setCookies(modifiedMsg.getRequestHeader().getHttpCookies()); fileUploadScanRule.sendAndRecieve(preflightMsg); diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/impl/FileParameter.java b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java similarity index 97% rename from src/main/java/org/sasanlabs/fileupload/attacks/impl/FileParameter.java rename to src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java index 88c17bf..0de00e0 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/impl/FileParameter.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java @@ -1,4 +1,4 @@ -package org.sasanlabs.fileupload.attacks.impl; +package org.sasanlabs.fileupload.attacks.beans; import java.util.Date; import java.util.Random; diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/impl/ExtensionContentType.java b/src/main/java/org/sasanlabs/fileupload/attacks/impl/ExtensionContentType.java deleted file mode 100644 index 60a41a7..0000000 --- a/src/main/java/org/sasanlabs/fileupload/attacks/impl/ExtensionContentType.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.sasanlabs.fileupload.attacks.impl; - -/** @author KSASAN preetkaran20@gmail.com */ -public class ExtensionContentType { - private String extension; - private String contentType; - - public ExtensionContentType(String extension, String contentType) { - super(); - this.extension = extension; - this.contentType = contentType; - } - - public String getExtension() { - return extension; - } - - public String getContentType() { - return contentType; - } -} diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/impl/ImageBasedJSPRemoteCodeExecution.java b/src/main/java/org/sasanlabs/fileupload/attacks/impl/ImageBasedJSPRemoteCodeExecution.java index 29a85d5..31aab2a 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/impl/ImageBasedJSPRemoteCodeExecution.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/impl/ImageBasedJSPRemoteCodeExecution.java @@ -13,13 +13,14 @@ import org.sasanlabs.fileupload.attacks.AttackVector; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; import org.sasanlabs.fileupload.attacks.FileUploadException; +import org.sasanlabs.fileupload.attacks.beans.FileParameter; import org.sasanlabs.fileupload.matcher.impl.ContainsExpectedValueMatcher; public class ImageBasedJSPRemoteCodeExecution implements AttackVector { private static final String GIF_IMAGE_JSP_INJECTED_IN_EXIF_BASE64_ENCODED = "R0lGODlhAQABAHAAACH5BAUAAAAAIf4mPCU9ICJTYXNhbkxhYnNfIiArICJaQVBfSWRlbnRpZmllciIgJT4ALAAAAAABAAEAAAICRAEAOw=="; - + // Need to correct expected value these private static final String EXPECTED_VALUE = "SasanLabs_ZAP_Identifier"; private static final String BASE_FILE_NAME = "ImageBasedJSPRCE_"; diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPRemoteCodeExecution.java b/src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPRemoteCodeExecution.java index 922bd63..3e4d5cd 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPRemoteCodeExecution.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPRemoteCodeExecution.java @@ -9,6 +9,7 @@ import org.sasanlabs.fileupload.attacks.AttackVector; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; import org.sasanlabs.fileupload.attacks.FileUploadException; +import org.sasanlabs.fileupload.attacks.beans.FileParameter; import org.sasanlabs.fileupload.matcher.ContentMatcher; import org.sasanlabs.fileupload.matcher.impl.MD5HashResponseMatcher; @@ -18,10 +19,12 @@ // etc public class PlainOldJSPRemoteCodeExecution implements AttackVector { - private static final String JSP_UPLOADED_FILE_BASE_NAME = "JSPUploaded_"; - private static final String JSP_PAYLOAD = "<% out.print(\"Sasan\"); %>"; + private static final String JSP_UPLOADED_FILE_BASE_NAME = "PlainOldJSPRemoteCodeExecution_"; + private static final String JSP_PAYLOAD = + "<% out.print(\"PlainOldJSPRemoteCodeExecution\"); out.print(\"_SasanLabs_ZAP_Identifier\"); %>"; - private static final ContentMatcher CONTENT_MATCHER = new MD5HashResponseMatcher("Sasan"); + private static final ContentMatcher CONTENT_MATCHER = + new MD5HashResponseMatcher("PlainOldJSPRemoteCodeExecution_SasanLabs_ZAP_Identifier"); private static final List FILE_PARAMETERS = Arrays.asList( diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPXRemoteCodeExecution.java b/src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPXRemoteCodeExecution.java new file mode 100644 index 0000000..d3005d3 --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPXRemoteCodeExecution.java @@ -0,0 +1,77 @@ +package org.sasanlabs.fileupload.attacks.impl; + +import static org.sasanlabs.fileupload.Constants.NULL_BYTE_CHARACTER; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import org.sasanlabs.fileupload.Constants; +import org.sasanlabs.fileupload.attacks.AttackVector; +import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; +import org.sasanlabs.fileupload.attacks.FileUploadException; +import org.sasanlabs.fileupload.attacks.beans.FileParameter; +import org.sasanlabs.fileupload.matcher.ContentMatcher; +import org.sasanlabs.fileupload.matcher.impl.MD5HashResponseMatcher; + +/** @author KSASAN preetkaran20@gmail.com */ +public class PlainOldJSPXRemoteCodeExecution implements AttackVector { + + private static final String JSPX_UPLOADED_FILE_BASE_NAME = "PlainOldJSPXRemoteCodeExecution_"; + // Payload from resource file: "jspx_payload.jspx" + private static final String JSPX_PAYLOAD = + " \n" + + " \n" + + " \n" + + " out.print(\"PlainOldJSPXRemoteCodeExecution_\"); \n" + + " out.print(\"SasanLabs_ZAP_Identifier\");" + + " \n" + + ""; + + private static final ContentMatcher CONTENT_MATCHER = + new MD5HashResponseMatcher("PlainOldJSPXRemoteCodeExecution_SasanLabs_ZAP_Identifier"); + + // Need to validate + // application/x-httpd-jsp + // text/x-jsp + private static final List FILE_PARAMETERS = + Arrays.asList( + new FileParameter("jspx", Constants.EMPTY_STRING), + new FileParameter("jspx", "application/x-jsp"), + new FileParameter("jspx.", Constants.EMPTY_STRING, true), + new FileParameter("jspx.", "application/x-jsp", true), + new FileParameter("jspx." + NULL_BYTE_CHARACTER, Constants.EMPTY_STRING, true), + new FileParameter("jspx." + NULL_BYTE_CHARACTER, "application/x-jsp", true)); + + @Override + public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) + throws FileUploadException { + boolean result = false; + try { + result = + this.genericAttackExecutor( + fileUploadAttackExecutor, + CONTENT_MATCHER, + JSPX_PAYLOAD, + JSPX_UPLOADED_FILE_BASE_NAME, + FILE_PARAMETERS); + if (result) { + fileUploadAttackExecutor + .getFileUploadScanRule() + .raiseAlert( + 1, + 1, + "", + "", + "", + "", + "", + "", + "", + fileUploadAttackExecutor.getOriginalHttpMessage()); + } + } catch (IOException e) { + throw new FileUploadException(e); + } + return result; + } +} diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/impl/XSSByHtmlUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/impl/XSSByHtmlUpload.java index 33ab5e5..d99bb2d 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/impl/XSSByHtmlUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/impl/XSSByHtmlUpload.java @@ -10,6 +10,7 @@ import org.sasanlabs.fileupload.attacks.AttackVector; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; import org.sasanlabs.fileupload.attacks.FileUploadException; +import org.sasanlabs.fileupload.attacks.beans.FileParameter; import org.sasanlabs.fileupload.matcher.ContentMatcher; import org.sasanlabs.fileupload.matcher.impl.MD5HashResponseMatcher; diff --git a/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java b/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java new file mode 100644 index 0000000..dc04b7f --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java @@ -0,0 +1,318 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2020 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sasanlabs.fileupload.ui; + +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.io.File; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JFileChooser; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JPasswordField; +import javax.swing.JScrollPane; +import javax.swing.JTextField; +import javax.swing.ScrollPaneConstants; +import javax.swing.border.TitledBorder; +import javax.swing.filechooser.FileFilter; +import org.parosproxy.paros.view.AbstractParamPanel; + +// import org.zaproxy.zap.extension.jwt.JWTConfiguration; +// import org.zaproxy.zap.extension.jwt.JWTI18n; +// import org.zaproxy.zap.extension.jwt.utils.JWTUIUtils; + +/** + * FileUpload options panel for specifying settings which are used by {@code FileUploadScanRule} + * for finding vulnerabilities related to FileUpload functionality in the applications. + * + * @author KSASAN preetkaran20@gmail.com + * @since TODO add version + */ +public class FileUploadOptionsPanel extends AbstractParamPanel { + private static final long serialVersionUID = 1L; + + private String trustStorePath; + private JScrollPane settingsScrollPane; + private JPanel footerPanel; + private JFileChooser trustStoreFileChooser; + private JPasswordField trustStorePasswordField; + private String trustStorePassword; + private JButton trustStoreFileChooserButton; + private JTextField trustStoreFileChooserTextField; + private JCheckBox enableClientConfigurationScanCheckBox; + + /** JWT Fuzzer Options * */ + private JPasswordField jwtHMacSignatureKey; + + /** + * Going ahead with .pem format for private keys instead of .p12 format because of ease of use. + */ + // TODO Need to move truststore also to .pem format. + // private String jwtRsaPrivateKeyFileChooserPath; + + // private JTextField jwtRsaPrivateKeyFileChooserTextField; + + /** Custom JWT configuration */ + public FileUploadOptionsPanel() { + super(); + // this.setName(JWTI18n.getMessage("jwt.settings.title")); + this.setName("Sasan"); + this.setLayout(new BorderLayout()); + JPanel settingsPanel = new JPanel(); + settingsPanel.setLayout(new BoxLayout(settingsPanel, BoxLayout.Y_AXIS)); + settingsScrollPane = + new JScrollPane( + settingsPanel, + ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, + ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); + this.add(settingsScrollPane, BorderLayout.NORTH); + footerPanel = new JPanel(); + this.add(footerPanel, BorderLayout.SOUTH); + footerPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0)); + this.addFileChooserTextField(); + this.trustStoreFileChooserButton(); + init(settingsPanel); + } + + private void init(JPanel settingsPanel) { + settingsPanel.add(this.rsaSettingsSection()); + settingsPanel.add(this.generalSettingsSection()); + settingsPanel.add(this.getFuzzerSettingsSection()); + footerPanel.add(getResetButton()); + } + + private JButton getResetButton() { + JButton resetButton = new JButton(); + // resetButton.setText(JWTI18n.getMessage("jwt.settings.button.reset")); + resetButton.setText("Reset"); + resetButton.addActionListener( + new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + resetOptionsPanel(); + } + }); + return resetButton; + } + + private void trustStoreFileChooserButton() { + + trustStoreFileChooserButton = new JButton("jwt.settings.filechooser.button"); + trustStoreFileChooserButton.addActionListener( + new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + trustStoreFileChooser = new JFileChooser(); + trustStoreFileChooser.setFileFilter( + new FileFilter() { + + @Override + public String getDescription() { + return "jwt.settings.rsa.trustStoreFileDescription"; + } + + @Override + public boolean accept(File f) { + return f.getName().endsWith(".p12") || f.isDirectory(); + } + }); + trustStoreFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); + String path = trustStoreFileChooserTextField.getText(); + if (!path.isEmpty()) { + File file = new File(path); + if (file.exists()) { + trustStoreFileChooser.setSelectedFile(file); + } + } + if (trustStoreFileChooser.showOpenDialog(null) + == JFileChooser.APPROVE_OPTION) { + final File selectedFile = trustStoreFileChooser.getSelectedFile(); + trustStorePath = selectedFile.getAbsolutePath(); + trustStoreFileChooserTextField.setText(selectedFile.getAbsolutePath()); + } + } + }); + } + + private void addFileChooserTextField() { + trustStoreFileChooserTextField = new JTextField(); + trustStoreFileChooserTextField.setEditable(false); + trustStoreFileChooserTextField.setColumns(15); + } + + private JPanel rsaSettingsSection() { + JPanel rsaPanel = new JPanel(); + rsaPanel.setSize(rsaPanel.getPreferredSize()); + GridBagLayout gridBagLayout = new GridBagLayout(); + rsaPanel.setLayout(gridBagLayout); + GridBagConstraints gridBagConstraints = getGridBagConstraints(); + TitledBorder rsaPanelBorder = new TitledBorder("jwt.settings.rsa.header"); + rsaPanel.setBorder(rsaPanelBorder); + JLabel lblTrustStorePathAttribute = new JLabel("jwt.settings.rsa.trustStorePath"); + rsaPanel.add(lblTrustStorePathAttribute, gridBagConstraints); + gridBagConstraints.gridx++; + + rsaPanel.add(trustStoreFileChooserTextField, gridBagConstraints); + gridBagConstraints.gridx++; + rsaPanel.add(trustStoreFileChooserButton, gridBagConstraints); + + gridBagConstraints.gridy++; + gridBagConstraints.gridx = 0; + JLabel lblTrustStorePassword = new JLabel("jwt.settings.rsa.trustStorePassword"); + rsaPanel.add(lblTrustStorePassword, gridBagConstraints); + + gridBagConstraints.gridx++; + trustStorePasswordField = new JPasswordField(); + trustStorePasswordField.setColumns(15); + trustStorePasswordField.addFocusListener( + new FocusListener() { + @Override + public void focusLost(FocusEvent e) { + if (trustStorePasswordField.getPassword() != null) { + trustStorePassword = new String(trustStorePasswordField.getPassword()); + } + } + + @Override + public void focusGained(FocusEvent e) {} + }); + lblTrustStorePassword.setLabelFor(trustStorePasswordField); + rsaPanel.add(trustStorePasswordField, gridBagConstraints); + return rsaPanel; + } + + private JPanel generalSettingsSection() { + JPanel generalSettingsPanel = new JPanel(new FlowLayout(FlowLayout.LEADING)); + TitledBorder generalSettingsBorder = + // JWTUIUtils.getTitledBorder("jwt.settings.general.header"); + new TitledBorder("dsasdasd"); + generalSettingsPanel.setBorder(generalSettingsBorder); + enableClientConfigurationScanCheckBox = new JCheckBox("checkBox"); + generalSettingsPanel.add(enableClientConfigurationScanCheckBox); + return generalSettingsPanel; + } + + private JPanel getFuzzerSettingsSection() { + JPanel fuzzerSettingsPanel = new JPanel(new GridBagLayout()); + TitledBorder fuzzerSettingsBorder = + // JWTUIUtils.getTitledBorder("jwt.settings.fuzzer.header"); + new TitledBorder("somerhtingdakdnak"); + fuzzerSettingsPanel.setBorder(fuzzerSettingsBorder); + GridBagConstraints gridBagConstraints = getGridBagConstraints(); + gridBagConstraints.gridy++; + fuzzerSettingsPanel.add(getHMACSignaturePanel(), gridBagConstraints); + return fuzzerSettingsPanel; + } + + public static GridBagConstraints getGridBagConstraints() { + GridBagConstraints gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.fill = GridBagConstraints.BOTH; + gridBagConstraints.anchor = GridBagConstraints.NORTHWEST; + gridBagConstraints.gridy = 0; + gridBagConstraints.gridx = 0; + gridBagConstraints.weightx = 1.0D; + gridBagConstraints.weighty = 1.0D; + return gridBagConstraints; + } + + private JPanel getHMACSignaturePanel() { + JPanel hmacSignaturePanel = new JPanel(); + hmacSignaturePanel.setLayout(new GridBagLayout()); + hmacSignaturePanel.setSize(hmacSignaturePanel.getPreferredSize()); + TitledBorder hmacSignaturePanelBorder = + // JWTUIUtils.getTitledBorder("jwt.settings.fuzzer.hmac.signature.configuration"); + new TitledBorder("Something"); + hmacSignaturePanel.setBorder(hmacSignaturePanelBorder); + GridBagConstraints gridBagConstraints = // JWTUIUtils.getGridBagConstraints(); + getGridBagConstraints(); + JLabel jwtHmacPrivateKeyLabel = new JLabel("something sasan"); + jwtHMacSignatureKey = new JPasswordField(); + jwtHMacSignatureKey.setEditable(true); + jwtHMacSignatureKey.setColumns(15); + gridBagConstraints.gridx = 0; + hmacSignaturePanel.add(jwtHmacPrivateKeyLabel, gridBagConstraints); + gridBagConstraints.gridx++; + hmacSignaturePanel.add(jwtHMacSignatureKey, gridBagConstraints); + gridBagConstraints.gridx++; + return hmacSignaturePanel; + } + + /** Resets entire panel to default values. */ + private void resetOptionsPanel() { + // trustStorePasswordField.setText(""); + // trustStoreFileChooserTextField.setText(""); + // trustStorePassword = null; + // enableClientConfigurationScanCheckBox.setSelected(false); + // trustStorePath = ""; + // jwtRsaPrivateKeyFileChooserTextField.setText(""); + // jwtRsaPrivateKeyFileChooserPath = ""; + // jwtHMacSignatureKey.setText(""); + } + + private void populateOptionsPanel() { + // trustStoreFileChooserTextField.setText(trustStorePath); + // trustStorePasswordField.setText(trustStorePassword); + // if (jwtRsaPrivateKeyFileChooserPath != null) { + // this.jwtRsaPrivateKeyFileChooserTextField.setText(jwtRsaPrivateKeyFileChooserPath); + // } + } + + @Override + public void initParam(Object optionParams) { + this.resetOptionsPanel(); + // JWTConfiguration jwtConfiguration = + // ((OptionsParam) optionParams).getParamSet(JWTConfiguration.class); + // trustStorePath = jwtConfiguration.getTrustStorePath(); + // trustStorePassword = jwtConfiguration.getTrustStorePassword(); + // enableClientConfigurationScanCheckBox.setSelected( + // jwtConfiguration.isEnableClientConfigurationScan()); + // if (jwtConfiguration.getHMacSignatureKey() != null) { + // this.jwtHMacSignatureKey.setText(new + // String(jwtConfiguration.getHMacSignatureKey())); + // } + // this.jwtRsaPrivateKeyFileChooserPath = + // jwtConfiguration.getRsaPrivateKeyFileChooserPath(); + // this.populateOptionsPanel(); + } + + @Override + public void validateParam(Object optionParams) throws Exception {} + + @Override + public void saveParam(Object optionParams) throws Exception { + // JWTConfiguration jwtConfiguration = + // ((OptionsParam) optionParams).getParamSet(JWTConfiguration.class); + // jwtConfiguration.setTrustStorePath(trustStorePath); + // jwtConfiguration.setTrustStorePassword(trustStorePassword); + // jwtConfiguration.setEnableClientConfigurationScan( + // enableClientConfigurationScanCheckBox.isSelected()); + // jwtConfiguration.setHMacSignatureKey(jwtHMacSignatureKey.getPassword()); + // jwtConfiguration.setRsaPrivateKeyFileChooserPath(jwtRsaPrivateKeyFileChooserPath); + } +} diff --git a/src/main/resources/org/sasanlabs/attackvectors/files/jspx_payload.jspx b/src/main/resources/org/sasanlabs/attackvectors/files/jspx_payload.jspx new file mode 100644 index 0000000..15829d7 --- /dev/null +++ b/src/main/resources/org/sasanlabs/attackvectors/files/jspx_payload.jspx @@ -0,0 +1,7 @@ + + + + out.print("PlainOldJSPXRemoteCodeExecution_"); + out.print("SasanLabs_ZAP_Identifier"); + + \ No newline at end of file From 3e21e27bc59c4760aea00f9da41271445c4adc7f Mon Sep 17 00:00:00 2001 From: karan preet singh sasan Date: Sat, 26 Dec 2020 01:06:35 +0530 Subject: [PATCH 05/53] UI building --- .../fileupload/FileUploadExtension.java | 4 + .../fileupload/attacks/AttackVector.java | 2 +- .../FileUploadConfiguration.java | 119 ++++++ .../fileupload/configuration/URILocator.java | 17 + .../configuration/URILocatorImpl.java | 16 + .../fileupload/i18n/FileUploadI18n.java | 32 ++ .../fileupload/ui/FileUploadOptionsPanel.java | 347 +++++++----------- .../attackvectors/files/jspx_payload.jspx | 7 + .../fileupload/i18n/Messages.properties | 10 + 9 files changed, 337 insertions(+), 217 deletions(-) create mode 100644 src/main/java/org/sasanlabs/fileupload/configuration/FileUploadConfiguration.java create mode 100644 src/main/java/org/sasanlabs/fileupload/configuration/URILocator.java create mode 100644 src/main/java/org/sasanlabs/fileupload/configuration/URILocatorImpl.java create mode 100644 src/main/java/org/sasanlabs/fileupload/i18n/FileUploadI18n.java create mode 100644 src/main/resources/org/sasanlabs/fileupload/attackvectors/files/jspx_payload.jspx create mode 100755 src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadExtension.java b/src/main/java/org/sasanlabs/fileupload/FileUploadExtension.java index d8fc7f9..7e1065f 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadExtension.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadExtension.java @@ -23,6 +23,8 @@ import org.parosproxy.paros.extension.ExtensionAdaptor; import org.parosproxy.paros.extension.ExtensionHook; import org.parosproxy.paros.extension.ViewDelegate; +import org.sasanlabs.fileupload.configuration.FileUploadConfiguration; +import org.sasanlabs.fileupload.i18n.FileUploadI18n; import org.sasanlabs.fileupload.ui.FileUploadOptionsPanel; /** @@ -48,9 +50,11 @@ public void initView(ViewDelegate view) { @Override public void hook(ExtensionHook extensionHook) { + FileUploadI18n.init(); super.hook(extensionHook); extensionHook.getHookView().addOptionPanel(new FileUploadOptionsPanel()); LOGGER.debug("FileUpload Extension loaded successfully"); + extensionHook.addOptionsParamSet(FileUploadConfiguration.getInstance()); } @Override diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java index 420aae2..b64f343 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java @@ -10,8 +10,8 @@ import org.parosproxy.paros.core.scanner.NameValuePair; import org.parosproxy.paros.network.HttpMessage; import org.sasanlabs.fileupload.FileUploadScanRule; -import org.sasanlabs.fileupload.URILocatorImpl; import org.sasanlabs.fileupload.attacks.beans.FileParameter; +import org.sasanlabs.fileupload.configuration.URILocatorImpl; import org.sasanlabs.fileupload.matcher.ContentMatcher; /** diff --git a/src/main/java/org/sasanlabs/fileupload/configuration/FileUploadConfiguration.java b/src/main/java/org/sasanlabs/fileupload/configuration/FileUploadConfiguration.java new file mode 100644 index 0000000..6bac98a --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/configuration/FileUploadConfiguration.java @@ -0,0 +1,119 @@ +package org.sasanlabs.fileupload.configuration; + +import org.apache.log4j.Logger; +import org.zaproxy.zap.common.VersionedAbstractParam; + +/** + * This class holds configuration related to FileUpload Addon. + * + * @author KSASAN preetkaran20@gmail.com + * @since TODO add version + */ +public class FileUploadConfiguration extends VersionedAbstractParam { + + protected static final Logger LOGGER = Logger.getLogger(FileUploadConfiguration.class); + + /** The base configuration key for all fileupload configurations. */ + private static final String PARAM_BASE_KEY = "fileupload"; + + private static final String CONFIG_VERSION_KEY = PARAM_BASE_KEY + VERSION_ATTRIBUTE; + private static final int CURRENT_CONFIG_VERSION = 1; + private static final String PARAM_STATIC_LOCATION_CONFIGURATION_URI_REGEX = + 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 String staticLocationURIRegex; + private String dynamicLocationURIRegex; + private String dynamicLocationStartIdentifier; + private String dynamicLocationEndIdentifier; + + private static volatile FileUploadConfiguration fileUploadConfiguration; + + private FileUploadConfiguration() {} + + public static FileUploadConfiguration getInstance() { + if (fileUploadConfiguration == null) { + synchronized (FileUploadConfiguration.class) { + if (fileUploadConfiguration == null) { + fileUploadConfiguration = new FileUploadConfiguration(); + } + } + } + return fileUploadConfiguration; + } + + public String getStaticLocationURIRegex() { + return staticLocationURIRegex; + } + + public void setStaticLocationURIRegex(String staticLocationURIRegex) { + this.staticLocationURIRegex = staticLocationURIRegex; + this.getConfig() + .setProperty(PARAM_STATIC_LOCATION_CONFIGURATION_URI_REGEX, staticLocationURIRegex); + } + + public String getDynamicLocationURIRegex() { + return dynamicLocationURIRegex; + } + + public void setDynamicLocationURIRegex(String dynamicLocationURIRegex) { + this.dynamicLocationURIRegex = dynamicLocationURIRegex; + this.getConfig() + .setProperty( + PARAM_DYNAMIC_LOCATION_CONFIGURATION_URI_REGEX, dynamicLocationURIRegex); + } + + public String getDynamicLocationStartIdentifier() { + return dynamicLocationStartIdentifier; + } + + public void setDynamicLocationStartIdentifier(String dynamicLocationStartIdentifier) { + this.dynamicLocationStartIdentifier = dynamicLocationStartIdentifier; + this.getConfig() + .setProperty( + PARAM_DYNAMIC_LOCATION_CONFIGURATION_START_IDENTIFIER, + dynamicLocationStartIdentifier); + } + + public String getDynamicLocationEndIdentifier() { + return dynamicLocationEndIdentifier; + } + + public void setDynamicLocationEndIdentifier(String dynamicLocationEndIdentifier) { + this.dynamicLocationEndIdentifier = dynamicLocationEndIdentifier; + this.getConfig() + .setProperty( + PARAM_DYNAMIC_LOCATION_CONFIGURATION_END_IDENTIFIER, + dynamicLocationEndIdentifier); + } + + @Override + protected String getConfigVersionKey() { + return CONFIG_VERSION_KEY; + } + + @Override + protected int getCurrentVersion() { + return CURRENT_CONFIG_VERSION; + } + + @Override + protected void parseImpl() { + this.setStaticLocationURIRegex( + 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)); + } + + @Override + protected void updateConfigsImpl(int fileVersion) {} +} diff --git a/src/main/java/org/sasanlabs/fileupload/configuration/URILocator.java b/src/main/java/org/sasanlabs/fileupload/configuration/URILocator.java new file mode 100644 index 0000000..2168cb5 --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/configuration/URILocator.java @@ -0,0 +1,17 @@ +package org.sasanlabs.fileupload.configuration; + +import org.apache.commons.httpclient.URI; +import org.apache.commons.httpclient.URIException; +import org.parosproxy.paros.network.HttpMessage; + +/** + * {@code URILocator} class is used to find the URL either by parsing the {@code HttpMessage} or + * reading the configuration mentioned in the options tab. + * + *

This class also handles the "regex based configuration" e.g "url/$fileName" + * + * @author preetkaran20@gmail.com KSASAN + */ +public interface URILocator { + URI get(HttpMessage msg) throws URIException; +} diff --git a/src/main/java/org/sasanlabs/fileupload/configuration/URILocatorImpl.java b/src/main/java/org/sasanlabs/fileupload/configuration/URILocatorImpl.java new file mode 100644 index 0000000..d26bf32 --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/configuration/URILocatorImpl.java @@ -0,0 +1,16 @@ +package org.sasanlabs.fileupload.configuration; + +import org.apache.commons.httpclient.URI; +import org.apache.commons.httpclient.URIException; +import org.parosproxy.paros.network.HttpMessage; + +public class URILocatorImpl implements URILocator { + + @Override + public URI get(HttpMessage msg) throws URIException { + byte[] responseBody = msg.getResponseBody().getBytes(); + + // Say static configuration + return new URI("http://localhost:9090/contentDispositionUpload/karan.html"); + } +} diff --git a/src/main/java/org/sasanlabs/fileupload/i18n/FileUploadI18n.java b/src/main/java/org/sasanlabs/fileupload/i18n/FileUploadI18n.java new file mode 100644 index 0000000..506af3a --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/i18n/FileUploadI18n.java @@ -0,0 +1,32 @@ +package org.sasanlabs.fileupload.i18n; + +import java.util.ResourceBundle; +import org.parosproxy.paros.Constant; + +/** + * Message Bundle + * + * @author KSASAN preetkaran20@gmail.com + * @since TODO add version + */ +public class FileUploadI18n { + private static ResourceBundle message; + + public static void init() { + message = + ResourceBundle.getBundle( + FileUploadI18n.class.getPackage().getName() + ".Messages", + Constant.getLocale()); + } + + public static String getMessage(String key) { + if (key != null && message != null && message.containsKey(key)) { + return message.getString(key); + } + return ""; + } + + public static ResourceBundle getResourceBundle() { + return message; + } +} diff --git a/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java b/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java index dc04b7f..060da78 100644 --- a/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java +++ b/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java @@ -1,22 +1,3 @@ -/* - * Zed Attack Proxy (ZAP) and its related class files. - * - * ZAP is an HTTP/HTTPS proxy for assessing web application security. - * - * Copyright 2020 The ZAP Development Team - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ package org.sasanlabs.fileupload.ui; import java.awt.BorderLayout; @@ -25,30 +6,22 @@ import java.awt.GridBagLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.awt.event.FocusEvent; -import java.awt.event.FocusListener; -import java.io.File; import javax.swing.BoxLayout; import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JFileChooser; import javax.swing.JLabel; import javax.swing.JPanel; -import javax.swing.JPasswordField; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.ScrollPaneConstants; import javax.swing.border.TitledBorder; -import javax.swing.filechooser.FileFilter; +import org.parosproxy.paros.model.OptionsParam; import org.parosproxy.paros.view.AbstractParamPanel; - -// import org.zaproxy.zap.extension.jwt.JWTConfiguration; -// import org.zaproxy.zap.extension.jwt.JWTI18n; -// import org.zaproxy.zap.extension.jwt.utils.JWTUIUtils; +import org.sasanlabs.fileupload.configuration.FileUploadConfiguration; +import org.sasanlabs.fileupload.i18n.FileUploadI18n; /** - * FileUpload options panel for specifying settings which are used by {@code FileUploadScanRule} - * for finding vulnerabilities related to FileUpload functionality in the applications. + * FileUpload options panel for specifying settings which are used by {@code FileUploadScanRule} for + * finding vulnerabilities related to FileUpload functionality in the applications. * * @author KSASAN preetkaran20@gmail.com * @since TODO add version @@ -56,32 +29,18 @@ public class FileUploadOptionsPanel extends AbstractParamPanel { private static final long serialVersionUID = 1L; - private String trustStorePath; private JScrollPane settingsScrollPane; private JPanel footerPanel; - private JFileChooser trustStoreFileChooser; - private JPasswordField trustStorePasswordField; - private String trustStorePassword; - private JButton trustStoreFileChooserButton; - private JTextField trustStoreFileChooserTextField; - private JCheckBox enableClientConfigurationScanCheckBox; - - /** JWT Fuzzer Options * */ - private JPasswordField jwtHMacSignatureKey; - /** - * Going ahead with .pem format for private keys instead of .p12 format because of ease of use. - */ - // TODO Need to move truststore also to .pem format. - // private String jwtRsaPrivateKeyFileChooserPath; + // UI components + private JTextField staticLocationConfigurationURIRegex; + private JTextField dynamicLocationConfigurationURIRegex; + private JTextField dynamicLocationConfigurationStartIdentifier; + private JTextField dynamicLocationConfigurationEndIdentifier; - // private JTextField jwtRsaPrivateKeyFileChooserTextField; - - /** Custom JWT configuration */ public FileUploadOptionsPanel() { super(); - // this.setName(JWTI18n.getMessage("jwt.settings.title")); - this.setName("Sasan"); + this.setName(FileUploadI18n.getMessage("fileupload.settings.title")); this.setLayout(new BorderLayout()); JPanel settingsPanel = new JPanel(); settingsPanel.setLayout(new BoxLayout(settingsPanel, BoxLayout.Y_AXIS)); @@ -94,22 +53,17 @@ public FileUploadOptionsPanel() { footerPanel = new JPanel(); this.add(footerPanel, BorderLayout.SOUTH); footerPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0)); - this.addFileChooserTextField(); - this.trustStoreFileChooserButton(); init(settingsPanel); } private void init(JPanel settingsPanel) { - settingsPanel.add(this.rsaSettingsSection()); - settingsPanel.add(this.generalSettingsSection()); - settingsPanel.add(this.getFuzzerSettingsSection()); + settingsPanel.add(uriLocatorConfiguration()); footerPanel.add(getResetButton()); } private JButton getResetButton() { JButton resetButton = new JButton(); - // resetButton.setText(JWTI18n.getMessage("jwt.settings.button.reset")); - resetButton.setText("Reset"); + resetButton.setText(FileUploadI18n.getMessage("fileupload.settings.button.reset")); resetButton.addActionListener( new ActionListener() { @Override @@ -120,114 +74,110 @@ public void actionPerformed(ActionEvent e) { return resetButton; } - private void trustStoreFileChooserButton() { - - trustStoreFileChooserButton = new JButton("jwt.settings.filechooser.button"); - trustStoreFileChooserButton.addActionListener( - new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - trustStoreFileChooser = new JFileChooser(); - trustStoreFileChooser.setFileFilter( - new FileFilter() { - - @Override - public String getDescription() { - return "jwt.settings.rsa.trustStoreFileDescription"; - } - - @Override - public boolean accept(File f) { - return f.getName().endsWith(".p12") || f.isDirectory(); - } - }); - trustStoreFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); - String path = trustStoreFileChooserTextField.getText(); - if (!path.isEmpty()) { - File file = new File(path); - if (file.exists()) { - trustStoreFileChooser.setSelectedFile(file); - } - } - if (trustStoreFileChooser.showOpenDialog(null) - == JFileChooser.APPROVE_OPTION) { - final File selectedFile = trustStoreFileChooser.getSelectedFile(); - trustStorePath = selectedFile.getAbsolutePath(); - trustStoreFileChooserTextField.setText(selectedFile.getAbsolutePath()); - } - } - }); + private JPanel staticURILocatorConfiguration() { + GridBagLayout gridBagLayout = new GridBagLayout(); + JPanel staticLocationConfigurationPanel = new JPanel(); + staticLocationConfigurationPanel.setLayout(gridBagLayout); + TitledBorder staticLocationConfigurationPanelBorder = + new TitledBorder( + FileUploadI18n.getMessage( + "fileupload.settings.urilocator.staticlocation.title")); + staticLocationConfigurationPanel.setBorder(staticLocationConfigurationPanelBorder); + GridBagConstraints staticLocationConfigurationGridBagConstriants = getGridBagConstraints(); + JLabel uriRegexLabel = + new JLabel( + FileUploadI18n.getMessage( + "fileupload.settings.urilocator.staticlocation.uriregex")); + staticLocationConfigurationPanel.add( + uriRegexLabel, staticLocationConfigurationGridBagConstriants); + staticLocationConfigurationGridBagConstriants.gridx++; + staticLocationConfigurationURIRegex = new JTextField(); + staticLocationConfigurationURIRegex.setColumns(15); + staticLocationConfigurationPanel.add( + staticLocationConfigurationURIRegex, staticLocationConfigurationGridBagConstriants); + staticLocationConfigurationGridBagConstriants.gridy++; + staticLocationConfigurationGridBagConstriants.gridx = 0; + return staticLocationConfigurationPanel; } - private void addFileChooserTextField() { - trustStoreFileChooserTextField = new JTextField(); - trustStoreFileChooserTextField.setEditable(false); - trustStoreFileChooserTextField.setColumns(15); + private JPanel dynamicURILocatorConfiguration() { + TitledBorder dynamicLocationConfigurationPanelBorder = + new TitledBorder( + FileUploadI18n.getMessage( + "fileupload.settings.urilocator.dynamiclocation.title")); + JPanel dynamicLocationConfigurationPanel = new JPanel(); + GridBagLayout gridBagLayout = new GridBagLayout(); + dynamicLocationConfigurationPanel.setLayout(gridBagLayout); + dynamicLocationConfigurationPanel.setBorder(dynamicLocationConfigurationPanelBorder); + GridBagConstraints dynamicLocationConfigurationGridBagConstriants = getGridBagConstraints(); + JLabel dynamicLocationConfigurationURIRegexLabel = + new JLabel( + FileUploadI18n.getMessage( + "fileupload.settings.urilocator.dynamiclocation.uriregex")); + dynamicLocationConfigurationPanel.add( + dynamicLocationConfigurationURIRegexLabel, + dynamicLocationConfigurationGridBagConstriants); + dynamicLocationConfigurationGridBagConstriants.gridx++; + dynamicLocationConfigurationURIRegex = new JTextField(); + dynamicLocationConfigurationURIRegex.setColumns(15); + dynamicLocationConfigurationPanel.add( + dynamicLocationConfigurationURIRegex, + dynamicLocationConfigurationGridBagConstriants); + dynamicLocationConfigurationGridBagConstriants.gridy++; + dynamicLocationConfigurationGridBagConstriants.gridx = 0; + + JLabel dynamicLocationConfigurationStartIdentifierLabel = + new JLabel( + FileUploadI18n.getMessage( + "fileupload.settings.urilocator.dynamiclocation.startidentifer")); + dynamicLocationConfigurationPanel.add( + dynamicLocationConfigurationStartIdentifierLabel, + dynamicLocationConfigurationGridBagConstriants); + dynamicLocationConfigurationGridBagConstriants.gridx++; + dynamicLocationConfigurationStartIdentifier = new JTextField(); + dynamicLocationConfigurationURIRegex.setColumns(15); + dynamicLocationConfigurationPanel.add( + dynamicLocationConfigurationStartIdentifier, + dynamicLocationConfigurationGridBagConstriants); + dynamicLocationConfigurationGridBagConstriants.gridy++; + dynamicLocationConfigurationGridBagConstriants.gridx = 0; + + JLabel dynamicLocationConfigurationEndIdentifierLabel = + new JLabel( + FileUploadI18n.getMessage( + "fileupload.settings.urilocator.dynamiclocation.endidentifer")); + dynamicLocationConfigurationPanel.add( + dynamicLocationConfigurationEndIdentifierLabel, + dynamicLocationConfigurationGridBagConstriants); + dynamicLocationConfigurationGridBagConstriants.gridx++; + dynamicLocationConfigurationEndIdentifier = new JTextField(); + dynamicLocationConfigurationURIRegex.setColumns(15); + dynamicLocationConfigurationPanel.add( + dynamicLocationConfigurationEndIdentifier, + dynamicLocationConfigurationGridBagConstriants); + dynamicLocationConfigurationGridBagConstriants.gridy++; + dynamicLocationConfigurationGridBagConstriants.gridx = 0; + return dynamicLocationConfigurationPanel; } - private JPanel rsaSettingsSection() { - JPanel rsaPanel = new JPanel(); - rsaPanel.setSize(rsaPanel.getPreferredSize()); + private JPanel uriLocatorConfiguration() { + JPanel uriLocatorConfigurationPanel = new JPanel(); + uriLocatorConfigurationPanel.setSize(uriLocatorConfigurationPanel.getPreferredSize()); GridBagLayout gridBagLayout = new GridBagLayout(); - rsaPanel.setLayout(gridBagLayout); + uriLocatorConfigurationPanel.setLayout(gridBagLayout); GridBagConstraints gridBagConstraints = getGridBagConstraints(); - TitledBorder rsaPanelBorder = new TitledBorder("jwt.settings.rsa.header"); - rsaPanel.setBorder(rsaPanelBorder); - JLabel lblTrustStorePathAttribute = new JLabel("jwt.settings.rsa.trustStorePath"); - rsaPanel.add(lblTrustStorePathAttribute, gridBagConstraints); - gridBagConstraints.gridx++; - rsaPanel.add(trustStoreFileChooserTextField, gridBagConstraints); - gridBagConstraints.gridx++; - rsaPanel.add(trustStoreFileChooserButton, gridBagConstraints); + TitledBorder uriLocatorPanelBorder = + new TitledBorder(FileUploadI18n.getMessage("fileupload.settings.urilocator.title")); + uriLocatorConfigurationPanel.setBorder(uriLocatorPanelBorder); + // Static Configuration + uriLocatorConfigurationPanel.add(this.staticURILocatorConfiguration(), gridBagConstraints); gridBagConstraints.gridy++; - gridBagConstraints.gridx = 0; - JLabel lblTrustStorePassword = new JLabel("jwt.settings.rsa.trustStorePassword"); - rsaPanel.add(lblTrustStorePassword, gridBagConstraints); - - gridBagConstraints.gridx++; - trustStorePasswordField = new JPasswordField(); - trustStorePasswordField.setColumns(15); - trustStorePasswordField.addFocusListener( - new FocusListener() { - @Override - public void focusLost(FocusEvent e) { - if (trustStorePasswordField.getPassword() != null) { - trustStorePassword = new String(trustStorePasswordField.getPassword()); - } - } - - @Override - public void focusGained(FocusEvent e) {} - }); - lblTrustStorePassword.setLabelFor(trustStorePasswordField); - rsaPanel.add(trustStorePasswordField, gridBagConstraints); - return rsaPanel; - } - - private JPanel generalSettingsSection() { - JPanel generalSettingsPanel = new JPanel(new FlowLayout(FlowLayout.LEADING)); - TitledBorder generalSettingsBorder = - // JWTUIUtils.getTitledBorder("jwt.settings.general.header"); - new TitledBorder("dsasdasd"); - generalSettingsPanel.setBorder(generalSettingsBorder); - enableClientConfigurationScanCheckBox = new JCheckBox("checkBox"); - generalSettingsPanel.add(enableClientConfigurationScanCheckBox); - return generalSettingsPanel; - } - - private JPanel getFuzzerSettingsSection() { - JPanel fuzzerSettingsPanel = new JPanel(new GridBagLayout()); - TitledBorder fuzzerSettingsBorder = - // JWTUIUtils.getTitledBorder("jwt.settings.fuzzer.header"); - new TitledBorder("somerhtingdakdnak"); - fuzzerSettingsPanel.setBorder(fuzzerSettingsBorder); - GridBagConstraints gridBagConstraints = getGridBagConstraints(); + // Dynamic Configuration + uriLocatorConfigurationPanel.add(this.dynamicURILocatorConfiguration(), gridBagConstraints); gridBagConstraints.gridy++; - fuzzerSettingsPanel.add(getHMACSignaturePanel(), gridBagConstraints); - return fuzzerSettingsPanel; + return uriLocatorConfigurationPanel; } public static GridBagConstraints getGridBagConstraints() { @@ -241,64 +191,27 @@ public static GridBagConstraints getGridBagConstraints() { return gridBagConstraints; } - private JPanel getHMACSignaturePanel() { - JPanel hmacSignaturePanel = new JPanel(); - hmacSignaturePanel.setLayout(new GridBagLayout()); - hmacSignaturePanel.setSize(hmacSignaturePanel.getPreferredSize()); - TitledBorder hmacSignaturePanelBorder = - // JWTUIUtils.getTitledBorder("jwt.settings.fuzzer.hmac.signature.configuration"); - new TitledBorder("Something"); - hmacSignaturePanel.setBorder(hmacSignaturePanelBorder); - GridBagConstraints gridBagConstraints = // JWTUIUtils.getGridBagConstraints(); - getGridBagConstraints(); - JLabel jwtHmacPrivateKeyLabel = new JLabel("something sasan"); - jwtHMacSignatureKey = new JPasswordField(); - jwtHMacSignatureKey.setEditable(true); - jwtHMacSignatureKey.setColumns(15); - gridBagConstraints.gridx = 0; - hmacSignaturePanel.add(jwtHmacPrivateKeyLabel, gridBagConstraints); - gridBagConstraints.gridx++; - hmacSignaturePanel.add(jwtHMacSignatureKey, gridBagConstraints); - gridBagConstraints.gridx++; - return hmacSignaturePanel; - } - /** Resets entire panel to default values. */ private void resetOptionsPanel() { - // trustStorePasswordField.setText(""); - // trustStoreFileChooserTextField.setText(""); - // trustStorePassword = null; - // enableClientConfigurationScanCheckBox.setSelected(false); - // trustStorePath = ""; - // jwtRsaPrivateKeyFileChooserTextField.setText(""); - // jwtRsaPrivateKeyFileChooserPath = ""; - // jwtHMacSignatureKey.setText(""); - } - - private void populateOptionsPanel() { - // trustStoreFileChooserTextField.setText(trustStorePath); - // trustStorePasswordField.setText(trustStorePassword); - // if (jwtRsaPrivateKeyFileChooserPath != null) { - // this.jwtRsaPrivateKeyFileChooserTextField.setText(jwtRsaPrivateKeyFileChooserPath); - // } + staticLocationConfigurationURIRegex.setText(""); + dynamicLocationConfigurationURIRegex.setText(""); + dynamicLocationConfigurationStartIdentifier.setText(""); + dynamicLocationConfigurationEndIdentifier.setText(""); } @Override public void initParam(Object optionParams) { this.resetOptionsPanel(); - // JWTConfiguration jwtConfiguration = - // ((OptionsParam) optionParams).getParamSet(JWTConfiguration.class); - // trustStorePath = jwtConfiguration.getTrustStorePath(); - // trustStorePassword = jwtConfiguration.getTrustStorePassword(); - // enableClientConfigurationScanCheckBox.setSelected( - // jwtConfiguration.isEnableClientConfigurationScan()); - // if (jwtConfiguration.getHMacSignatureKey() != null) { - // this.jwtHMacSignatureKey.setText(new - // String(jwtConfiguration.getHMacSignatureKey())); - // } - // this.jwtRsaPrivateKeyFileChooserPath = - // jwtConfiguration.getRsaPrivateKeyFileChooserPath(); - // this.populateOptionsPanel(); + FileUploadConfiguration fileUploadConfiguration = + ((OptionsParam) optionParams).getParamSet(FileUploadConfiguration.class); + staticLocationConfigurationURIRegex.setText( + fileUploadConfiguration.getStaticLocationURIRegex()); + dynamicLocationConfigurationURIRegex.setText( + fileUploadConfiguration.getDynamicLocationURIRegex()); + dynamicLocationConfigurationStartIdentifier.setText( + fileUploadConfiguration.getDynamicLocationStartIdentifier()); + dynamicLocationConfigurationEndIdentifier.setText( + fileUploadConfiguration.getDynamicLocationEndIdentifier()); } @Override @@ -306,13 +219,15 @@ public void validateParam(Object optionParams) throws Exception {} @Override public void saveParam(Object optionParams) throws Exception { - // JWTConfiguration jwtConfiguration = - // ((OptionsParam) optionParams).getParamSet(JWTConfiguration.class); - // jwtConfiguration.setTrustStorePath(trustStorePath); - // jwtConfiguration.setTrustStorePassword(trustStorePassword); - // jwtConfiguration.setEnableClientConfigurationScan( - // enableClientConfigurationScanCheckBox.isSelected()); - // jwtConfiguration.setHMacSignatureKey(jwtHMacSignatureKey.getPassword()); - // jwtConfiguration.setRsaPrivateKeyFileChooserPath(jwtRsaPrivateKeyFileChooserPath); + FileUploadConfiguration fileUploadConfiguration = + ((OptionsParam) optionParams).getParamSet(FileUploadConfiguration.class); + fileUploadConfiguration.setStaticLocationURIRegex( + this.staticLocationConfigurationURIRegex.getText()); + fileUploadConfiguration.setDynamicLocationURIRegex( + this.dynamicLocationConfigurationURIRegex.getText()); + fileUploadConfiguration.setDynamicLocationStartIdentifier( + this.dynamicLocationConfigurationStartIdentifier.getText()); + fileUploadConfiguration.setDynamicLocationEndIdentifier( + this.dynamicLocationConfigurationEndIdentifier.getText()); } } diff --git a/src/main/resources/org/sasanlabs/fileupload/attackvectors/files/jspx_payload.jspx b/src/main/resources/org/sasanlabs/fileupload/attackvectors/files/jspx_payload.jspx new file mode 100644 index 0000000..15829d7 --- /dev/null +++ b/src/main/resources/org/sasanlabs/fileupload/attackvectors/files/jspx_payload.jspx @@ -0,0 +1,7 @@ + + + + out.print("PlainOldJSPXRemoteCodeExecution_"); + out.print("SasanLabs_ZAP_Identifier"); + + \ No newline at end of file diff --git a/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties b/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties new file mode 100755 index 0000000..490faf1 --- /dev/null +++ b/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties @@ -0,0 +1,10 @@ +fileupload.settings.title=File Upload +fileupload.settings.button.reset=Reset +fileupload.settings.urilocator.title=URI Locator +fileupload.settings.urilocator.staticlocation.title=Static Location Configuration +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.dynamiclocation.startidentifer=Start Identifier +fileupload.settings.urilocator.dynamiclocation.endidentifer=End Identifier From f7bd201df5ae4763fac51c600179a59364197a95 Mon Sep 17 00:00:00 2001 From: karan preet singh sasan Date: Sat, 26 Dec 2020 14:07:58 +0530 Subject: [PATCH 06/53] URI Locator --- build.gradle.kts | 51 ++++++ build/libs/fileupload-1.0.0.jar | Bin 0 -> 21809 bytes .../attackvectors/images/1*1_Default.gif | Bin 0 -> 37 bytes .../images/1*1_Default_JSP_Injected_EXIF.gif | Bin 0 -> 80 bytes build/tmp/jar/MANIFEST.MF | 2 + build/tmp/jarZapAddOn/MANIFEST.MF | 2 + build/zapAddOn/ZapAddOn.xml | 20 ++ build/zapAddOn/bin/fileupload-alpha-1.0.0.zap | Bin 0 -> 21809 bytes build/zapAddOn/latest-changes.md | 4 + build/zapAddOn/manifest-changes.html | 6 + gradle.properties | 2 + gradle/spotless/License.java | 15 ++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 55190 bytes gradle/wrapper/gradle-wrapper.properties | 5 + gradlew | 172 ++++++++++++++++++ gradlew.bat | 84 +++++++++ .../fileupload/AbstractAppVariantPlugin.java | 13 ++ .../org/sasanlabs/fileupload/Constants.java | 16 ++ .../fileupload/FileUploadExtension.java | 22 +-- .../fileupload/FileUploadScanRule.java | 13 ++ .../fileupload/attacks/AttackVector.java | 37 +++- .../attacks/ConsumerWithException.java | 19 ++ .../attacks/FileUploadAttackExecutor.java | 13 ++ .../attacks/FileUploadException.java | 17 ++ .../attacks/beans/FileParameter.java | 13 ++ .../ImageBasedJSPRemoteCodeExecution.java | 13 ++ .../attacks/impl/PathTraversal.java | 13 ++ .../fileupload/attacks/impl/PhpRCE.java | 13 ++ .../impl/PlainOldJSPRemoteCodeExecution.java | 13 ++ .../impl/PlainOldJSPXRemoteCodeExecution.java | 13 ++ .../attacks/impl/XSSByHtmlUpload.java | 13 ++ .../FileUploadConfiguration.java | 13 ++ .../fileupload/configuration/URILocator.java | 25 ++- .../configuration/URILocatorImpl.java | 119 +++++++++++- .../fileupload/i18n/FileUploadI18n.java | 13 ++ .../fileupload/matcher/ContentMatcher.java | 13 ++ .../impl/ContainsExpectedValueMatcher.java | 13 ++ .../matcher/impl/MD5HashResponseMatcher.java | 13 ++ .../fileupload/redownloader/Redownloader.java | 13 ++ .../fileupload/ui/FileUploadOptionsPanel.java | 13 ++ 40 files changed, 812 insertions(+), 27 deletions(-) create mode 100755 build.gradle.kts create mode 100644 build/libs/fileupload-1.0.0.jar create mode 100644 build/resources/main/org/sasanlabs/attackvectors/images/1*1_Default.gif create mode 100644 build/resources/main/org/sasanlabs/attackvectors/images/1*1_Default_JSP_Injected_EXIF.gif create mode 100644 build/tmp/jar/MANIFEST.MF create mode 100644 build/tmp/jarZapAddOn/MANIFEST.MF create mode 100644 build/zapAddOn/ZapAddOn.xml create mode 100644 build/zapAddOn/bin/fileupload-alpha-1.0.0.zap create mode 100644 build/zapAddOn/latest-changes.md create mode 100644 build/zapAddOn/manifest-changes.html create mode 100755 gradle.properties create mode 100644 gradle/spotless/License.java create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100755 gradlew.bat create mode 100644 src/main/java/org/sasanlabs/fileupload/attacks/ConsumerWithException.java diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100755 index 0000000..0e6d8af --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,51 @@ +import org.zaproxy.gradle.addon.AddOnPlugin +import org.zaproxy.gradle.addon.AddOnStatus +import org.zaproxy.gradle.addon.misc.ConvertMarkdownToHtml +import org.zaproxy.gradle.addon.misc.CreateGitHubRelease +import org.zaproxy.gradle.addon.misc.ExtractLatestChangesFromChangelog + +plugins { + id("com.diffplug.gradle.spotless") version "3.27.2" + id("com.github.ben-manes.versions") version "0.28.0" + `java-library` + id("org.zaproxy.add-on") version "0.3.0" +} + +repositories { + mavenCentral() +} + +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} + +spotless { + java { + licenseHeaderFile("./gradle/spotless/License.java") + googleJavaFormat().aosp() + } +} + +tasks.withType().configureEach { options.encoding = "utf-8" } + +version = "1.0.0" +description = "Detect File upload requests and scan them to find related vulnerabilities" + +zapAddOn { + addOnName.set("File upload Scan Rule") + zapVersion.set("2.9.0") + addOnStatus.set(AddOnStatus.ALPHA) + + manifest { + author.set("KSASAN preetkaran20@gmail.com") + repo.set("https://github.com/SasanLabs/owasp-zap-fileupload-addon/") + dependencies { + } + changesFile.set(tasks.named("generateManifestChanges").flatMap { it.html }) + } +} + +dependencies { + //implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar")))) +} diff --git a/build/libs/fileupload-1.0.0.jar b/build/libs/fileupload-1.0.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..844d0260f780a4808b88d5efb2fda9c47a2317cb GIT binary patch literal 21809 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 OUG!6;1}{);$N2|6I}i*2 literal 0 HcmV?d00001 diff --git a/build/resources/main/org/sasanlabs/attackvectors/images/1*1_Default.gif b/build/resources/main/org/sasanlabs/attackvectors/images/1*1_Default.gif new file mode 100644 index 0000000000000000000000000000000000000000..57aeed3dba476ea689dadc094cad38a911288797 GIT binary patch literal 37 mcmZ?wbhEHbWMp7uC}3bv{K>+~00cT90wl)3#N@)rU=09cqXX~& literal 0 HcmV?d00001 diff --git a/build/resources/main/org/sasanlabs/attackvectors/images/1*1_Default_JSP_Injected_EXIF.gif b/build/resources/main/org/sasanlabs/attackvectors/images/1*1_Default_JSP_Injected_EXIF.gif new file mode 100644 index 0000000000000000000000000000000000000000..b4acb4471ab4d2a219f75db42498be4fafdacd5f GIT binary patch literal 80 zcmZ?wbhEHbWMp7uC}3bv{K>+~00fHv)NNE96bcg4Qx!6E3-XIfY_k%}67@<;GIR8_ abinM)d_65yI|dz)dXRPoCMFj~25SHpSrP#N literal 0 HcmV?d00001 diff --git a/build/tmp/jar/MANIFEST.MF b/build/tmp/jar/MANIFEST.MF new file mode 100644 index 0000000..58630c0 --- /dev/null +++ b/build/tmp/jar/MANIFEST.MF @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 + diff --git a/build/tmp/jarZapAddOn/MANIFEST.MF b/build/tmp/jarZapAddOn/MANIFEST.MF new file mode 100644 index 0000000..58630c0 --- /dev/null +++ b/build/tmp/jarZapAddOn/MANIFEST.MF @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 + diff --git a/build/zapAddOn/ZapAddOn.xml b/build/zapAddOn/ZapAddOn.xml new file mode 100644 index 0000000..3b3fd87 --- /dev/null +++ b/build/zapAddOn/ZapAddOn.xml @@ -0,0 +1,20 @@ + + File upload Scan Rule + 1.0.0 + alpha + Detect File upload requests and scan them to find related vulnerabilities + KSASAN preetkaran20@gmail.com + <h3>Added</h3> +<ul> +<li>Increased the number of requests for High threshold to 18 from 12.</li> +<li>Client side configuration alerts will not stop the scanner from scanning server side configurations.</li> +<li>Support for validating usage of publicly well known HMac secrets for signing JWT.</li> +</ul> + + https://github.com/SasanLabs/owasp-zap-fileupload-addon/ + + + org.sasanlabs.fileupload.FileUploadExtension + + 2.9.0 + diff --git a/build/zapAddOn/bin/fileupload-alpha-1.0.0.zap b/build/zapAddOn/bin/fileupload-alpha-1.0.0.zap new file mode 100644 index 0000000000000000000000000000000000000000..885e6475ab5309c8d09e65daf326301921d63799 GIT binary patch literal 21809 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

wte_r-v{k+jD_*bm=cP%o)EaG|&rk^$3 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 F`3u^_$R+>) literal 0 HcmV?d00001 diff --git a/build/zapAddOn/latest-changes.md b/build/zapAddOn/latest-changes.md new file mode 100644 index 0000000..e9fe5ab --- /dev/null +++ b/build/zapAddOn/latest-changes.md @@ -0,0 +1,4 @@ +### Added + - Increased the number of requests for High threshold to 18 from 12. + - Client side configuration alerts will not stop the scanner from scanning server side configurations. + - Support for validating usage of publicly well known HMac secrets for signing JWT. \ No newline at end of file diff --git a/build/zapAddOn/manifest-changes.html b/build/zapAddOn/manifest-changes.html new file mode 100644 index 0000000..dcef059 --- /dev/null +++ b/build/zapAddOn/manifest-changes.html @@ -0,0 +1,6 @@ +

Added

+
    +
  • Increased the number of requests for High threshold to 18 from 12.
  • +
  • Client side configuration alerts will not stop the scanner from scanning server side configurations.
  • +
  • Support for validating usage of publicly well known HMac secrets for signing JWT.
  • +
diff --git a/gradle.properties b/gradle.properties new file mode 100755 index 0000000..ee0ff81 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,2 @@ +org.gradle.caching=true +org.gradle.parallel=false \ No newline at end of file diff --git a/gradle/spotless/License.java b/gradle/spotless/License.java new file mode 100644 index 0000000..047b094 --- /dev/null +++ b/gradle/spotless/License.java @@ -0,0 +1,15 @@ +/** + * Copyright $YEAR SasanLabs + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + **/ \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..87b738cbd051603d91cc39de6cb000dd98fe6b02 GIT binary patch literal 55190 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 z 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 \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100755 index 0000000..0f8d593 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/src/main/java/org/sasanlabs/fileupload/AbstractAppVariantPlugin.java b/src/main/java/org/sasanlabs/fileupload/AbstractAppVariantPlugin.java index a98e1f6..0c9f33a 100644 --- a/src/main/java/org/sasanlabs/fileupload/AbstractAppVariantPlugin.java +++ b/src/main/java/org/sasanlabs/fileupload/AbstractAppVariantPlugin.java @@ -1,3 +1,16 @@ +/** + * Copyright 2020 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ package org.sasanlabs.fileupload; import java.util.List; diff --git a/src/main/java/org/sasanlabs/fileupload/Constants.java b/src/main/java/org/sasanlabs/fileupload/Constants.java index 2f03727..cbc8909 100644 --- a/src/main/java/org/sasanlabs/fileupload/Constants.java +++ b/src/main/java/org/sasanlabs/fileupload/Constants.java @@ -1,7 +1,23 @@ +/** + * Copyright 2020 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ package org.sasanlabs.fileupload; public interface Constants { String EMPTY_STRING = ""; String PERIOD = "."; + String SLASH = "/"; String NULL_BYTE_CHARACTER = String.valueOf((char) 0); + String HTTP_SCHEME = "http://"; + String HTTP_SECURED_SCHEME = "https://"; } diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadExtension.java b/src/main/java/org/sasanlabs/fileupload/FileUploadExtension.java index 7e1065f..da05a4a 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadExtension.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadExtension.java @@ -1,20 +1,14 @@ -/* - * Zed Attack Proxy (ZAP) and its related class files. - * - * ZAP is an HTTP/HTTPS proxy for assessing web application security. - * - * Copyright 2019 The ZAP Development Team +/** + * Copyright 2020 SasanLabs * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + *

http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ package org.sasanlabs.fileupload; diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java index 41ff6fa..5fdccab 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java @@ -1,3 +1,16 @@ +/** + * Copyright 2020 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ package org.sasanlabs.fileupload; import java.io.IOException; diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java index b64f343..f30e8de 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java @@ -1,3 +1,16 @@ +/** + * Copyright 2020 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ package org.sasanlabs.fileupload.attacks; import java.io.IOException; @@ -27,11 +40,21 @@ public interface AttackVector { * @param fileUploadScanRule * @return * @throws IOException + * @throws FileUploadException */ default HttpMessage executePreflightRequest( - HttpMessage modifiedMsg, FileUploadScanRule fileUploadScanRule) throws IOException { + HttpMessage modifiedMsg, String fileName, FileUploadScanRule fileUploadScanRule) + throws IOException, FileUploadException { HttpMessage preflightMsg = new HttpMessage(); - preflightMsg.getRequestHeader().setURI(new URILocatorImpl().get(modifiedMsg)); + preflightMsg + .getRequestHeader() + .setURI( + new URILocatorImpl() + .get( + modifiedMsg, + fileName, + (httpmessage) -> + fileUploadScanRule.sendAndRecieve(httpmessage))); preflightMsg.getRequestHeader().setMethod("GET"); preflightMsg.getRequestHeader().setCookies(modifiedMsg.getRequestHeader().getHttpCookies()); fileUploadScanRule.sendAndRecieve(preflightMsg); @@ -44,7 +67,7 @@ default boolean genericAttackExecutor( String payload, String baseFileName, List fileParameters) - throws IOException { + throws IOException, FileUploadException { List nameValuePairs = fileUploadAttackExecutor.getVariant().getParamList(); HttpMessage originalMsg = fileUploadAttackExecutor.getOriginalHttpMessage(); FileUploadScanRule fileUploadScanRule = fileUploadAttackExecutor.getFileUploadScanRule(); @@ -77,7 +100,11 @@ default boolean genericAttackExecutor( } } fileUploadScanRule.sendAndRecieve(newMsg); - HttpMessage preflightMsg = this.executePreflightRequest(newMsg, fileUploadScanRule); + HttpMessage preflightMsg = + this.executePreflightRequest( + newMsg, + fileParameter.getFileName(originalFileName, baseFileName), + fileUploadScanRule); if (md5HashResponseMatcher.match(preflightMsg)) { return true; } @@ -96,7 +123,7 @@ default boolean executeAttackAndRaiseAlert( ContentMatcher responseMatcher) throws URIException, NullPointerException, IOException { HttpMessage preflightMsg = new HttpMessage(); - preflightMsg.getRequestHeader().setURI(new URILocatorImpl().get(modifiedMsg)); + // preflightMsg.getRequestHeader().setURI(new URILocatorImpl().get(modifiedMsg)); preflightMsg.getRequestHeader().setMethod("GET"); preflightMsg.getRequestHeader().setCookies(modifiedMsg.getRequestHeader().getHttpCookies()); fileUploadScanRule.sendAndRecieve(preflightMsg); diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/ConsumerWithException.java b/src/main/java/org/sasanlabs/fileupload/attacks/ConsumerWithException.java new file mode 100644 index 0000000..d9d52db --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/attacks/ConsumerWithException.java @@ -0,0 +1,19 @@ +/** + * Copyright 2020 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sasanlabs.fileupload.attacks; + +@FunctionalInterface +public interface ConsumerWithException { + void accept(T val) throws E; +} diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java b/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java index baf7133..36c4974 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java @@ -1,3 +1,16 @@ +/** + * Copyright 2020 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ package org.sasanlabs.fileupload.attacks; import java.util.Arrays; diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadException.java b/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadException.java index aa0dd10..2c42239 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadException.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadException.java @@ -1,3 +1,16 @@ +/** + * Copyright 2020 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ package org.sasanlabs.fileupload.attacks; /** @@ -13,6 +26,10 @@ public FileUploadException(Throwable th) { super(th); } + public FileUploadException(String message) { + super(message); + } + public FileUploadException(String message, Throwable th) { super(message, th); } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java index 0de00e0..b19374f 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java @@ -1,3 +1,16 @@ +/** + * Copyright 2020 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ package org.sasanlabs.fileupload.attacks.beans; import java.util.Date; diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/impl/ImageBasedJSPRemoteCodeExecution.java b/src/main/java/org/sasanlabs/fileupload/attacks/impl/ImageBasedJSPRemoteCodeExecution.java index 31aab2a..509dd3b 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/impl/ImageBasedJSPRemoteCodeExecution.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/impl/ImageBasedJSPRemoteCodeExecution.java @@ -1,3 +1,16 @@ +/** + * Copyright 2020 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ package org.sasanlabs.fileupload.attacks.impl; import static org.sasanlabs.fileupload.Constants.NULL_BYTE_CHARACTER; diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/impl/PathTraversal.java b/src/main/java/org/sasanlabs/fileupload/attacks/impl/PathTraversal.java index 12646eb..ce5d7c2 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/impl/PathTraversal.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/impl/PathTraversal.java @@ -1,3 +1,16 @@ +/** + * Copyright 2020 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ package org.sasanlabs.fileupload.attacks.impl; /** @author KSASAN preetkaran20@gmail.com */ diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/impl/PhpRCE.java b/src/main/java/org/sasanlabs/fileupload/attacks/impl/PhpRCE.java index 8d533d8..94ea46e 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/impl/PhpRCE.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/impl/PhpRCE.java @@ -1,3 +1,16 @@ +/** + * Copyright 2020 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ package org.sasanlabs.fileupload.attacks.impl; /** * https://vulp3cula.gitbook.io/hackers-grimoire/exploitation/web-application/file-upload-bypass diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPRemoteCodeExecution.java b/src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPRemoteCodeExecution.java index 3e4d5cd..cd697e6 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPRemoteCodeExecution.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPRemoteCodeExecution.java @@ -1,3 +1,16 @@ +/** + * Copyright 2020 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ package org.sasanlabs.fileupload.attacks.impl; import static org.sasanlabs.fileupload.Constants.NULL_BYTE_CHARACTER; diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPXRemoteCodeExecution.java b/src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPXRemoteCodeExecution.java index d3005d3..3566361 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPXRemoteCodeExecution.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPXRemoteCodeExecution.java @@ -1,3 +1,16 @@ +/** + * Copyright 2020 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ package org.sasanlabs.fileupload.attacks.impl; import static org.sasanlabs.fileupload.Constants.NULL_BYTE_CHARACTER; diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/impl/XSSByHtmlUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/impl/XSSByHtmlUpload.java index d99bb2d..95b9adf 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/impl/XSSByHtmlUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/impl/XSSByHtmlUpload.java @@ -1,3 +1,16 @@ +/** + * Copyright 2020 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ package org.sasanlabs.fileupload.attacks.impl; import static org.sasanlabs.fileupload.Constants.NULL_BYTE_CHARACTER; diff --git a/src/main/java/org/sasanlabs/fileupload/configuration/FileUploadConfiguration.java b/src/main/java/org/sasanlabs/fileupload/configuration/FileUploadConfiguration.java index 6bac98a..639878e 100644 --- a/src/main/java/org/sasanlabs/fileupload/configuration/FileUploadConfiguration.java +++ b/src/main/java/org/sasanlabs/fileupload/configuration/FileUploadConfiguration.java @@ -1,3 +1,16 @@ +/** + * Copyright 2020 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ package org.sasanlabs.fileupload.configuration; import org.apache.log4j.Logger; diff --git a/src/main/java/org/sasanlabs/fileupload/configuration/URILocator.java b/src/main/java/org/sasanlabs/fileupload/configuration/URILocator.java index 2168cb5..8517f39 100644 --- a/src/main/java/org/sasanlabs/fileupload/configuration/URILocator.java +++ b/src/main/java/org/sasanlabs/fileupload/configuration/URILocator.java @@ -1,17 +1,36 @@ +/** + * Copyright 2020 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ package org.sasanlabs.fileupload.configuration; +import java.io.IOException; import org.apache.commons.httpclient.URI; -import org.apache.commons.httpclient.URIException; import org.parosproxy.paros.network.HttpMessage; +import org.sasanlabs.fileupload.attacks.ConsumerWithException; +import org.sasanlabs.fileupload.attacks.FileUploadException; /** * {@code URILocator} class is used to find the URL either by parsing the {@code HttpMessage} or * reading the configuration mentioned in the options tab. * - *

This class also handles the "regex based configuration" e.g "url/$fileName" + *

This class also handles the "regex based configuration" e.g "url/{$fileName}" * * @author preetkaran20@gmail.com KSASAN */ public interface URILocator { - URI get(HttpMessage msg) throws URIException; + URI get( + HttpMessage msg, + String fileName, + ConsumerWithException sendAndRecieve) + throws FileUploadException, IOException; } diff --git a/src/main/java/org/sasanlabs/fileupload/configuration/URILocatorImpl.java b/src/main/java/org/sasanlabs/fileupload/configuration/URILocatorImpl.java index d26bf32..89fb497 100644 --- a/src/main/java/org/sasanlabs/fileupload/configuration/URILocatorImpl.java +++ b/src/main/java/org/sasanlabs/fileupload/configuration/URILocatorImpl.java @@ -1,16 +1,125 @@ +/** + * Copyright 2020 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ package org.sasanlabs.fileupload.configuration; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; import org.apache.commons.httpclient.URI; import org.apache.commons.httpclient.URIException; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.text.StringSubstitutor; +import org.apache.log4j.Logger; import org.parosproxy.paros.network.HttpMessage; +import org.sasanlabs.fileupload.Constants; +import org.sasanlabs.fileupload.attacks.ConsumerWithException; +import org.sasanlabs.fileupload.attacks.FileUploadException; public class URILocatorImpl implements URILocator { - @Override - public URI get(HttpMessage msg) throws URIException { - byte[] responseBody = msg.getResponseBody().getBytes(); + protected static final Logger LOGGER = Logger.getLogger(URILocatorImpl.class); + + private URI getCompleteURI(String uriRegex, String fileName, HttpMessage msg) + throws URIException, FileUploadException { + Map replacerKeyValuePair = new HashMap<>(); + replacerKeyValuePair.put("filename", fileName); + StringSubstitutor stringSubstitutor = new StringSubstitutor(replacerKeyValuePair); + String uriFragment = stringSubstitutor.replace(uriRegex); + if (uriFragment.startsWith(Constants.HTTP_SCHEME) + || uriRegex.startsWith(Constants.HTTP_SECURED_SCHEME)) { + return new URI(uriFragment, true); + } else if (uriFragment.startsWith(Constants.SLASH)) { + String authority = msg.getRequestHeader().getURI().getAuthority(); + String scheme = msg.getRequestHeader().getURI().getScheme(); + return new URI(scheme, authority + uriFragment, ""); + } else { + throw new FileUploadException("FileUpload configuration is invalid."); + } + } - // Say static configuration - return new URI("http://localhost:9090/contentDispositionUpload/karan.html"); + private URI parseResponseAndGetCompleteURI( + HttpMessage msg, String fileName, HttpMessage originalMsg) + throws FileUploadException, URIException { + int startIndex = + msg.getResponseBody() + .toString() + .indexOf( + FileUploadConfiguration.getInstance() + .getDynamicLocationStartIdentifier()); + int endIndex = + msg.getResponseBody() + .toString() + .indexOf( + FileUploadConfiguration.getInstance() + .getDynamicLocationEndIdentifier()); + 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:" + + startIndex + + " End index:" + + endIndex); + } + String uriRegex = msg.getResponseBody().toString().substring(startIndex, endIndex); + return this.getCompleteURI(uriRegex, fileName, originalMsg); + } + + @Override + public URI get( + HttpMessage msg, + String fileName, + ConsumerWithException sendAndRecieve) + throws FileUploadException, IOException { + URI uri = null; + try { + if (StringUtils.isNotBlank( + FileUploadConfiguration.getInstance().getStaticLocationURIRegex())) { + return this.getCompleteURI( + FileUploadConfiguration.getInstance().getStaticLocationURIRegex(), + fileName, + msg); + } else if (StringUtils.isNotBlank( + FileUploadConfiguration.getInstance().getDynamicLocationURIRegex())) { + // Do an HttpCall and then find URI of uploaded content in Response. + HttpMessage preflightRequest = msg.cloneRequest(); + preflightRequest + .getRequestHeader() + .setURI( + this.getCompleteURI( + FileUploadConfiguration.getInstance() + .getDynamicLocationURIRegex(), + fileName, + msg)); + sendAndRecieve.accept(preflightRequest); + return this.parseResponseAndGetCompleteURI(preflightRequest, fileName, msg); + } else { + if (StringUtils.isNotBlank( + FileUploadConfiguration.getInstance() + .getDynamicLocationStartIdentifier()) + && StringUtils.isNotBlank( + FileUploadConfiguration.getInstance() + .getDynamicLocationEndIdentifier())) { + try { + return this.parseResponseAndGetCompleteURI(msg, fileName, msg); + } catch (FileUploadException e) { + // Eating exception because upload request might not have the uri + LOGGER.debug(e); + } + } + } + } catch (URIException ex) { + throw new FileUploadException(ex); + } + return uri; } } diff --git a/src/main/java/org/sasanlabs/fileupload/i18n/FileUploadI18n.java b/src/main/java/org/sasanlabs/fileupload/i18n/FileUploadI18n.java index 506af3a..d555ba6 100644 --- a/src/main/java/org/sasanlabs/fileupload/i18n/FileUploadI18n.java +++ b/src/main/java/org/sasanlabs/fileupload/i18n/FileUploadI18n.java @@ -1,3 +1,16 @@ +/** + * Copyright 2020 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ package org.sasanlabs.fileupload.i18n; import java.util.ResourceBundle; diff --git a/src/main/java/org/sasanlabs/fileupload/matcher/ContentMatcher.java b/src/main/java/org/sasanlabs/fileupload/matcher/ContentMatcher.java index d259756..4c659ec 100644 --- a/src/main/java/org/sasanlabs/fileupload/matcher/ContentMatcher.java +++ b/src/main/java/org/sasanlabs/fileupload/matcher/ContentMatcher.java @@ -1,3 +1,16 @@ +/** + * Copyright 2020 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ package org.sasanlabs.fileupload.matcher; import org.parosproxy.paros.network.HttpMessage; diff --git a/src/main/java/org/sasanlabs/fileupload/matcher/impl/ContainsExpectedValueMatcher.java b/src/main/java/org/sasanlabs/fileupload/matcher/impl/ContainsExpectedValueMatcher.java index 6ea9345..7f6112d 100644 --- a/src/main/java/org/sasanlabs/fileupload/matcher/impl/ContainsExpectedValueMatcher.java +++ b/src/main/java/org/sasanlabs/fileupload/matcher/impl/ContainsExpectedValueMatcher.java @@ -1,3 +1,16 @@ +/** + * Copyright 2020 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ package org.sasanlabs.fileupload.matcher.impl; import java.util.Objects; diff --git a/src/main/java/org/sasanlabs/fileupload/matcher/impl/MD5HashResponseMatcher.java b/src/main/java/org/sasanlabs/fileupload/matcher/impl/MD5HashResponseMatcher.java index 854f887..a89c7a2 100644 --- a/src/main/java/org/sasanlabs/fileupload/matcher/impl/MD5HashResponseMatcher.java +++ b/src/main/java/org/sasanlabs/fileupload/matcher/impl/MD5HashResponseMatcher.java @@ -1,3 +1,16 @@ +/** + * Copyright 2020 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ package org.sasanlabs.fileupload.matcher.impl; import java.nio.charset.StandardCharsets; diff --git a/src/main/java/org/sasanlabs/fileupload/redownloader/Redownloader.java b/src/main/java/org/sasanlabs/fileupload/redownloader/Redownloader.java index 0caae4b..68be8c5 100644 --- a/src/main/java/org/sasanlabs/fileupload/redownloader/Redownloader.java +++ b/src/main/java/org/sasanlabs/fileupload/redownloader/Redownloader.java @@ -1,3 +1,16 @@ +/** + * Copyright 2020 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ package org.sasanlabs.fileupload.redownloader; /** @author KSASAN preetkaran20@gmail.com */ diff --git a/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java b/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java index 060da78..dffc134 100644 --- a/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java +++ b/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java @@ -1,3 +1,16 @@ +/** + * Copyright 2020 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ package org.sasanlabs.fileupload.ui; import java.awt.BorderLayout; From c1de48eec0ce37f2145ade486a9dc33636898f72 Mon Sep 17 00:00:00 2001 From: karan preet singh sasan Date: Sat, 26 Dec 2020 14:14:47 +0530 Subject: [PATCH 07/53] SmallFix --- owasp-zap-fileupload-addon.gradle.kts | 50 ------------------- .../org/sasanlabs/fileupload/URILocator.java | 17 ++++++- .../sasanlabs/fileupload/URILocatorImpl.java | 13 +++++ 3 files changed, 28 insertions(+), 52 deletions(-) delete mode 100755 owasp-zap-fileupload-addon.gradle.kts diff --git a/owasp-zap-fileupload-addon.gradle.kts b/owasp-zap-fileupload-addon.gradle.kts deleted file mode 100755 index 830a26e..0000000 --- a/owasp-zap-fileupload-addon.gradle.kts +++ /dev/null @@ -1,50 +0,0 @@ - -import org.zaproxy.gradle.addon.AddOnStatus -import org.zaproxy.gradle.addon.misc.ConvertMarkdownToHtml - -plugins { - // id("com.diffplug.gradle.spotless") version "3.27.2" - // id("com.github.ben-manes.versions") version "0.28.0" - `java-library` - // id("org.zaproxy.add-on") version "0.3.0" -} - -repositories { - mavenCentral() -} - -java { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 -} - -spotless { - java { - // Don't enforce the license, just the format. - clearSteps() - googleJavaFormat().aosp() - } -} - -tasks.withType().configureEach { options.encoding = "utf-8" } - -version = "1.0.0" -description = "Detect File upload requests and scan them to find related vulnerabilities" - -zapAddOn { - addOnName.set("File upload Scan Rule") - zapVersion.set("2.9.0") - addOnStatus.set(AddOnStatus.ALPHA) - - manifest { - author.set("KSASAN preetkaran20@gmail.com") - repo.set("https://github.com/SasanLabs/owasp-zap-fileupload-addon/") - dependencies { - } - changesFile.set(tasks.named("generateManifestChanges").flatMap { it.html }) - } -} - -dependencies { - // implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar")))) -} diff --git a/src/main/java/org/sasanlabs/fileupload/URILocator.java b/src/main/java/org/sasanlabs/fileupload/URILocator.java index 520cb4c..2c8029f 100644 --- a/src/main/java/org/sasanlabs/fileupload/URILocator.java +++ b/src/main/java/org/sasanlabs/fileupload/URILocator.java @@ -1,3 +1,16 @@ +/** + * Copyright 2020 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ package org.sasanlabs.fileupload; import org.apache.commons.httpclient.URI; @@ -5,8 +18,8 @@ import org.parosproxy.paros.network.HttpMessage; /** - * {@code URILocator} class is used to find the URL either by parsing the {@code - * HttpMessage} or reading the configuration mentioned in the options tab. + * {@code URILocator} class is used to find the URL either by parsing the {@code HttpMessage} or + * reading the configuration mentioned in the options tab. * *

This class also handles the "regex based configuration" e.g "url/$fileName" * diff --git a/src/main/java/org/sasanlabs/fileupload/URILocatorImpl.java b/src/main/java/org/sasanlabs/fileupload/URILocatorImpl.java index 2c8d130..eb41faa 100644 --- a/src/main/java/org/sasanlabs/fileupload/URILocatorImpl.java +++ b/src/main/java/org/sasanlabs/fileupload/URILocatorImpl.java @@ -1,3 +1,16 @@ +/** + * Copyright 2020 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ package org.sasanlabs.fileupload; import org.apache.commons.httpclient.URI; From 295e3183defd86bdd4bdaee5bf2b1fb85b86835e Mon Sep 17 00:00:00 2001 From: karan preet singh sasan Date: Sat, 26 Dec 2020 14:15:57 +0530 Subject: [PATCH 08/53] SmallFix --- build/libs/fileupload-1.0.0.jar | Bin 21809 -> 0 bytes .../attackvectors/images/1*1_Default.gif | Bin 37 -> 0 bytes .../images/1*1_Default_JSP_Injected_EXIF.gif | Bin 80 -> 0 bytes build/tmp/jar/MANIFEST.MF | 2 -- build/tmp/jarZapAddOn/MANIFEST.MF | 2 -- build/zapAddOn/ZapAddOn.xml | 20 ------------------ build/zapAddOn/bin/fileupload-alpha-1.0.0.zap | Bin 21809 -> 0 bytes build/zapAddOn/latest-changes.md | 4 ---- build/zapAddOn/manifest-changes.html | 6 ------ 9 files changed, 34 deletions(-) delete mode 100644 build/libs/fileupload-1.0.0.jar delete mode 100644 build/resources/main/org/sasanlabs/attackvectors/images/1*1_Default.gif delete mode 100644 build/resources/main/org/sasanlabs/attackvectors/images/1*1_Default_JSP_Injected_EXIF.gif delete mode 100644 build/tmp/jar/MANIFEST.MF delete mode 100644 build/tmp/jarZapAddOn/MANIFEST.MF delete mode 100644 build/zapAddOn/ZapAddOn.xml delete mode 100644 build/zapAddOn/bin/fileupload-alpha-1.0.0.zap delete mode 100644 build/zapAddOn/latest-changes.md delete mode 100644 build/zapAddOn/manifest-changes.html diff --git a/build/libs/fileupload-1.0.0.jar b/build/libs/fileupload-1.0.0.jar deleted file mode 100644 index 844d0260f780a4808b88d5efb2fda9c47a2317cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21809 zcmbTeb9m-Uvo@McY#TGNZQFJxn%K56v2EM7@x-?6i6%Bq)?V+%TKhZed(U~UtMgZP zHLAM0?z`$2c_|Q3Xdoa+NFZ&9L;op{9iiO`Fy#+ z`Rsu8*--yyM;QTG2~iOxWm*~08=3JjX(<}o88|5#%E|GmdPVwqrtO2>gD?L>nAYEB z1^pCeV{h`83IE;){$G6@^c?i8E%o#r{?hyJ`}kvte@OiA-o|E@MozYtHhPBtYoK)P zO(GjG5KzfyBmbv?LN?Y8j(XOP4zvcAdJYaoF=MiQ@`ynnxy$I(7y`=kfp%axZFa>B zy&8!HUnmj-&^Q8T6Xq9h`#iAN1_Kecg|OrpHg~^|?{hgAzduc_y^K-$qTr${2z3Gh zuOVY2J41$fb2X68#Twl|F9oF48d4QKQ`;^mAiMc_NRpfBA(Byx501;>VYP$Wm85s} z7Dn(0cKVoL&V`2-$~C4}tt?P)5D%L$ZNYTxXMAf|H4xN+IfBpCclDc-`)x&5mvVlS zzDq8hpXzX6B>z4e#Vr*@(RS zZtM83kfXEVKBi-+)}gy_=;+gv0~S!<<-H zp#1K44#+pNcW?1^it$putPG6w4E#VuAWSia`ntgX<68V-#PSRguq&UpkpvtFi1D8` zBKm31D*s{6BCd``)(&Pi)_-mxQE5#PMF5cpt0>Une{o?PPQjvCGr>qUr%)18CH@EbWK2VYSyNM>_b-8)7#Mz9Z-GA;k5q@ z?BG5xZE`4eU5R1N5q&5{YU;&c1oyb}985>!tzT}w@}{mhU7Jkrv|2N6Ew&X~z(*9DSdxIOI^4N!`5oT`i zs!(-Gtdt>=$oH@jO%1wfiQ>$eO%8XUCOH9U46}2^k#zFuGQ2OgP;ZjQj8*;np(*PM z;$9r0ook}!;w2yw8w^f^BWVY$gi;~QM=34*#|gsGQFuA|1Cym^pm*ODpw-|NYJWyl z?WUb1S4maeQ7(>3Ro<#OqPKPBw-=@sFZ!9yW)PejuQ}d?TH~_~la*>pds`Px%#UB8 ze2*E7i9<1ClJ}wKsPgLTp$I9pB@JHh-c{ALGfoqk z%@s-fei8r8Wrebes9{$ik&bVcUi9FV{UPXcUTkB$6z9pmfBAF^(e1{R<}%s7IQ8~$ zG6&?mv!&p;hY#iqg4;slc%KH|fnKe2`Aja@qUQU8+CdPe+QAU^azzTfN!j=p)3(FUnIkk$KLW-Ce2zG5_QVqd zU5cPVoiRtP2}d!O{9&vU2;?`3prl(fE75SAwA5%5Elsu?9#}Z95$WHy=Ev&hw!Q=z zSklq1riScp>>L@m$0Vcj?w7-{`}9K8Rx3{}s?&Ax+}7$(+QoZjRM|(YcIMIrbN)l| zUd2(7a3oByW88KkYHYh$7qgM#qEqQ}a!%*oMA1;1EJm$eQe8!jMCDl^DWlWetVxDvU?>P437 zu-vPxVo0kwRe~l+NC*AQ$fl+h+U;ORBZ|3&j*zL1)EORBCee(46uD$|zL@KB$)7V} z;YMQVX>_Z`Xi=zO34=~DLSYRbp7upv9YohS@#-+)88 zl9rHargbg1Ec<}cM{ruIma<(5Po)8+FWiwfrH@TOQ;?TdDrP4IHyGp~MfV)i!l|c;W6HCvssLtD7`72`B1ix9>D-IiE*yV4y2_NlUXV*B0-PH0I31GD=M&V)hnD=)s_zz zN}Vt+%=<3-{Qefm(28_&)K`9N#xS>y3@@&Yuww8ro1vP@L*LtL9nm~fp!r^taIr!t z(JPNvzn!G}GH!fazKQz0@UWSa=)6axK*t~_hhwrZW7QH=jC^@J4R~@HhZUuRw3;*G zNJiMxwQ4D<*;l{9D3C^YT&WB^?ACGOtjlm-v>g;>erfN)-|l5vZz=g!k~POH%tJfO zX2ioXjos}Jt5yrR9;mOOdLM9C-!dLe*=mnN zRxV-Qh6b!Pr3eaX~fRyB+@gN4%YIzw|(rFdRxM16^u}wG5Qv2l!Qd+_ljM* z$M&$foT1Iyc{ROdbp?JllL`uaxv`zk7@1YzVV{1UUVDY&vG|d;zM@p$Z|BK8_zAXy z*ISv%0o-M^BYi15_7E}5>}}xfIJATJyeY8z-aIIFMq3u_@W(AV%L<_8{`sNCZ&jGh zYmKS}Z4C*c6aM_9ChnfgPSfpc{+ra{xy!`b7O#!mME0eo2wUMz=XD1}WWb!G=p|4l zWN5^q?hr{0%=PFPWYE4I3_P-OCye+uV&$z}0B`o=cTTw3w)|79d7g+$Z8bz)%;T;w z_igB(PRzuCgPdG#v;r%dU(4wTJYSKX*So)QILGxOwNdO_38!q!+5@ai355&_o{bgT z<54$cC5I$71)gkTzrA&VOW=z7S_jyIiUl$=uFc8mQgmoZF8ir{lR>|GQFToK5#|sl z(*xy1puj|C-3Zm&D*Bjy1J`(POhD9D5d@qd&tD*82R_Tx>Ozg_=OU*WNJ6m<^pQ05 z6Oydsh9}i@1ZYyyuFGVBQy>zf5f%s%L0J>@RubE>K&|r=Hh&W$#U~OG8$MRZ^SrvNNoh{&TJGbf*N~gpD$jk2I=?5P znXbF8b+dCWqn!M5z@BgB2yAwC&a}pkRtsy=kB0*+O;Dk;xk-RZ~5Wg6B z=<&-E%}85?RrWc7$dU5rw`)+SAVfT>)@3I8caPp-ITAhvGJI3hrD3x7HQKjryWEu+n47 z%wuRH2?{W0R%V?M6BvOxGzOze%be(@*6k5iskP6CGWKw+HVGCbZvN_Y{^sgOB97WI zQKboqDxgcc93wh1-oCnxmk{v1cdZ($H<8^7a>YyvwvnC{ zORhu3l%Yn{s=ZRwtihuNX8|jlf=e(@hCsRb zDmxwm3lFNQr&4o?J9tw+Sjhl2X~_cLB(Gn=pjpeh8n~NHsVK1TM-s~#1iyFCW?Nmdh zyJXQ|Wl_hn%Hp?dqG~yg`GzIU1<_M0hoh!pa!~HsrqKa9W`U#^lXbFT&$veoEpLqK zL^D8zsryZ1pnUmT#0KUZhi8%$iKEIo0>RRR1$J`Vm^>gxz_9CLzI4^4U9V==O zOPh!&!$s`4Aw^6zhvdwTscj@?rg`-_B0(cf60?;YbS9ejNi+lR_9kvj)KiVNL1}SZ zA+zairQs0v*g2}KsbV8Yw3c9)!Ws7#am9wp{7kOU@P4pdvT%!uj~4HOcSYIA8-Q%} zH#>T+^|)MWgGBGRfzWMxaCX^ji*yK&!FEKbId+(Dvv3O-pdBDMzE1a?x(We^JZ_r( zh+JcKQZK!xrd-iSQcF|0jIc9nJD@u!8^+{YBkFkb_r$=xBeG2~pL|9qd*rT|;5PEJ zFu-%^FavAO(EO{2y*DF|*gIDul}1^*zb&YujZ<&xr_bnmlRu^$1EV}8kOINz6U9J6Eb9T<|z17JqRG%ME%-CnkmP+uk zQeA4Gd`}=VNw8#FsUepLukt5WuY+$x-V*4g99nSh!pgD1>sm|fv(cQkY&UmOt@;i5 zTE!Gq$^1ms%-|zO50!-^jcq;`a6yAdT1Z}Inr&@5!zj+>S~7kqwx{d=?b2BB*3e;s z*Zn!}2tzpV0&jDpa{}jR=H+7fa6Rub91if(ZPWgS!GvqZjz$pTi;f`m$_NX}alr<}} zhX_~B{(*SPAOqp{15M+Dr+-tZ!)Kd^_#L;_h@%MVC*%nvC)9#W4z8U0X~gjm5Mm{& zFM8@`92 z*qlqcs4eTwL2pOMUZFlY^>npSRW30d!50ozLjL=*w~duMKom={UFqGyS+~8tEVqNd zkxOCRP%mqPw6ptpqrOLRY{JeK5uC6|Yf5uVPKdHc?J-x`(q5J_0DOey;-yx2pfYc> zcPD<4`wDgN3AMg8JlVY?@5{#DLp@uAd}LHQ2u~p)Agtk+J6J3X2i|v}y;HjFTZW z1BXKBWr~N;5uWuh1JMzl64s0kB`K12A5)o(E+hK0=(7D-6ku}+@tVY)2p%DYjiADP z^YyPU?+$4wcj4z#H~HCE{+%c9lSTd{>>U5{%Be(j!UGGS22KrVC?nGe^jbMehLVQ} z7Pq$#)-8@38^3m@^?|sO*Tz?7?Cw)dy6|o-;q;(xVA@5%6SRfMMF(8j8d(k&s_#i! z;7?(Hr}AODAD8+))@U!w$bxeY*;(1Ts!SsrNCQVT{=}EygazF|SA1s@3EQmZ5 zZ0=42L*&sl&-K0p`S#78fOAhKu6({3Dga!tM8q@?4N_qNuEFQO_x%SsFQ~&IP5Q}H zGJUf5T>rFhd3z&cOEVKw$ItiO#>w8mNZQ6g&(X$S;xmBw^Nr6`(v(9HKz%Ptu+}cu zMf;6$;si6So5vu(C)5cVM_8nVyf^2F)daGZIWd_t|D%vD#&j3qQVeU#5^6MDxqgMi zVbb%6%YpW0?`Y{a5Wc~p7}k=f))3rRHoGx^Ar{M5k@b7qA%Hf*1E%DZa^9IkP;5?D zue@h28wo&NisX92x|*n-WhQh)(dw6cKMtXiEFUwvl^Rx1F-@k(IwVn?x+CnCV(q$& z0S)WZnzZ!*<;iLjvpXA1VSX*A=1HNQ|4-3b#tKjl0ZK-zS?S+*5Sm%yFA64Ho-?bC z-?51ZS4xiLW5a5w+)6xnGBGzv_%W$c)w?!z>^pc+7^LCk#^gr|BtoTG?~Jo^FS|yz zyH{b1%+XSL*2%nBrgj?bN0#1`*3Oz9zfoS=tpfa^zs&PUtI$Vc*>f|11i6{0Z*x1V z{5ChhI6OK$g3MCy>ri%7$zLB>gmBtKN)Q{_)tSwSwv|W)MPM~nr zFxDzH#p#@8dM9C~H!nP$;J{p{4|W$)}YcNkO3MH1e^6mGb7fWj?g}-fj4T1?`j)AIcQ%7Z!r_82N~o&^IMd(rl@XIA`sxTkW~3EhKSlI#0m8^boqZ z8eTg5`(iWP&j&W1{IfKtxuiu(|5qSlXRzJyBCBT?FzZ832WNNECa?swVo?c?up+C3 zv==nMMjRTI?tyY)BaL?alvVLA9}ACPYu?_Xlbri(li|SJLrJnRz}`?Mxr?s+heuoM zR*mC@olx6+p-s!Y@rbXOWEb?>BtPt%w^Uu_xChy zCY^)_R@fy+b1J#gLP{s$ylSXh&P--H+!tAn+vP#FF_S}Y>-a)${nBK8QjN!czhsZqw&AR@d-K}L5@xm z=+pEg9hsXxT+0KiGs zVJzo5(d2e@K`J6LlAiwjsr1e5 znuIpU7nLTX(uY!*vD1{_Cc_cPDYl6BIb<400lSy@skl~{X9Li#K2YiVE~FUE5T8OA z3I1gqv9VsbRh=lyt168Y0ZB+B*5_VJ@;Koll6L0=)Xgfg5Bqz}T( zDCL7fJuKDr?ao@YX?~2whyIcOWV8 zzKELcPN{FHS0Nk#7vph zmVg8uU&T?8UEoqMGz@w)#hlqyJLF(yiFne|XXMIrnO$cCh##hWVHjC4uG=7wt&MTiu>uKydhn1Tg8)>ngfZejcFCRH|;ec(Y*~B~BV3uoZ}a-C z<4is5f_zyy&&2lwBeLc2OKdy35oN4(a~-$rE!5ejpE1ZKd!w=?!1qA%Gv|R6Gw&xn zgfSL7nMUDG4fAcK3^zE;5G!L#gWU4sV`! zIjdSjv?N`SS;SaUKz*Hqq=w^FD1ra#YXQ{$gjBHHK@brbe$EzD-1JVI!1hO2H} zMGwm`3i(HN8vek-Yj(}15X}jrJ`iy3001##q zVRHn2W7+fLt%yti^Az1#a$~2e52rJk@orW_aZ_$*wVE;SX}9dA+eYzxi}+J1Ddp@9 zQD#zJGiXEianF=HfM|HTy(c`_00x~PShW`--j4)VSQYK)G^E57YIT4t+s{){37Y*# zQQpre1EwCd1(?dTHl!x#dt67fj;MXzS096_qVdS@w_y}&r?x12&9*en&NxG&VOvjs zBOf!u+DqO)VSpPra|&--2sFY-*_;)v&qh>zGk*9%hAAOtB* z8RLu2qjd-GqrFXsi}$OCn=PRA9(Pa-dOT68U1(!L@c??NQp13tR>%uo-T*L;t;lVI z0@MODL&9TzRRP)nIl^OM9RY%Xyq^P*%G80EW{}wnqJX zZVd_-ZXMUt3%4w5(}yA1d+0=80TWnxRKX<&+n zli>&)3{+Zb`|-4AWsG|?XS9P_4K${(wAkuJ6B$!5ERx6yYWLepJy~JTATnxr~3k8 z0vAQC=ValuOhWsC7zvHjh6ARDyoxm^vLfP!K~f)CMGROpyGL!d5~{Yv3TWazv4AkejekKG`u%Rqq_h-SW}8=Y<%9|ko@cv5Q6hE) z8C^|HfCsFS02l{#~s47b)8z&y+08(gDlQw%LHXR)f|igGxR# zY8EBeXquzkCb2YIQJr4uM#$jPst}yMT!RmerW)H<;&-|X0|?3=iCxS10lQ%aJV`V& zTPIO?pvkXe!Iuch5qMJ9S*UP|643RMP7WyxAQi>}v)`SJ(3MKBrAt$&$qs*|%Ay`9 zeZ8&-`Ud#5EN~Z^8Fy!6w{G`{qV~K!3Nt~E*`B@nV}?uiY}2Dd=BpS+k1Z1LEeZ?& zsnjjc!cW$`trej$FLxx<4LVKct6aLKCmnKFPdXc$%dU0xqlHLxJ#IW#uGb4s?HTK z1lp|^FBP*j4ix8_B1mEBG|@LkWUcp=nwWB6y`q_yI;Dd*O2OIWw#!2^m*Que-<0aG;4TaP$VIh` z59R$k71C-R(LlXNY{C!qEPH|F7F(SRUx8L>c46Z)sI0C$~dK zYh1o4XGKT=QD_BA^ZLXd=PyP<39j;ea0N$wzu+e^8Jmt2gHO1l zz=S$zwM!?l;3>x@#uCkw305zk1I8N*sA$RZvo5(hjv#p^>s#jzy5^rcFjblvbxWGL zeRRRNx2pgieojPq3|L(FzcsZethd0Da3k@`pDMd*Y7^j9^8hQylSL}UlhNZ228y@z3jy-FV_t!+Q`XKO-Gmi&gNG#I z2?~tGN6lrAzI(z9?|2Vi&_Q&2CWxK_PMgkP8Hf7SL)AO@!`6u;rgqBGp_ z2cLRW{?zHekA&s*98Hz&^_-3D9rXT_K9j4J1<)gUEfqlp@Rz>}u<7=I(EF)VGKlyJ zFTBO2Ee=Fdt^M+0AYixz_C)Ptpw@1U&${Sr_b7gOet!hD4OEEYjbh3$#6+IeTp;%m zJI>CUfEt;nCe~9g6Xk74mt4hC<0Rjkov%2uR2ll{@2^fE(n=nr4Kx^vJRA+hC^Twc z2*UW;dGx#h)wp7Q)$h$x-x0r9+eNTHRn*wnp?1}y^PoS$MH{2b-|`yFr8mz3IWeKg zt!nYzLwXt}+eLuD->HY09*KjV-3OvGFfW)|7kdB{0yumN7?&{mRLrjI@oy1_u-j;$ z(siLaJ6^5RI9HAXxg-q$@BM#aHWCpB32gPgc;R}U)Dh9aSE2O0Sc6jf=Sq5>oDoyxj}>9Gdh!^&OFxZ0b;i4LcEcaze$r7r zLId`uOc-0o_DXB}qS{vUOg7`#F`khDM3>K@=22c~*{Cy%6Qdvd5yrV(BR|d8t9_)%EHY z!^wJ_raeungRZF?hb-&KWSTeR%4mn=DI8vk3$oG)yE)c3@1Q~T2Vx=9X^NQFrUWyb z{KO|Lz{EAy7@~sx^?KTV6~(bG!+x@K^v;Ntc`+tDHT=uXqEV~F>Y5B45Lq!L$^hsNt3DXgqco?56v@CfB`+ibD((Qec68l&8~_wHHJ!Ji2$(x2HYvlUL*x3*?|chK^Q<5+zK}d?(8M;X7RQK_Gf;P{tP~Dt(mqRx~p_Y z^O03V1>kbY2&kobD?=klg@oH0pxO_nkP8l)V+Yv2$HL zLc{TeZ=1pK4dDoG&|yyU3To!63Id~i@s_|7?2pPd%jIl(9Q;|Wc2t&;Ok=&OvQE)^ zL-i&6O)23dP`A#B0-vad1W-cx4z9wY`>SLXH+lsX%hn}eVh@*!w{HmIe>u3F8y>WNZ zjwo|jT4Lbjk{*dcwVp@0-mas=(ok1;PJ`XFllBzJa~kO~NA>lYaKrLhmCE9wtmeH` ztVzNBqWawUdOfQogM4p+$X%^r%>l`Yd#Zd5YUb_;6nq~VZwC-Vwk#wMEm24B`2`<2gXBcz5%Xn1VGry7r2 zd&)$dlu=R#f52@H?s%A(*|LkdHg(;hexK7*9$A809y(^5zS_zB!(g1kWm8bP`XW84 zb-sZGZjskSD${L(r_A(0pGoU+QTT0F+K+tHb<#|Vq15t(Ukj}IN~f3&Ek{^}W8F(H zIK$;SN`Q4*^`NEiMjan!ZNUuf>a6%y^<~%Z9UJK`5UoZ=(wy|r?}7pwNqn%uzoP*P zoRgh7&c29mufG5kX{WaarNEWKe6>-FAw@?>6Kex7fs0dPcMo}?hqr?Hzm*#D=EUi! znC~ilJ81}h7u(cptp~y&R?|Z9<6@X854;fRdWTNKF=w597Zqx-!^&0u&1aY6f+eG1 zgteoVdnc-CY7ZilTR2GalU4HSya0$@ybnGXF8G%R=+KNn_iB_x;!BzS6)dvi0RgP| z7I>(+0Dz0VN>>~+tDod2wC1}|F4WAU^xi<$X1aX7M#CMcGj0C)ZZ8hIG^>bUZb{vH z_M$Tl(KD%r*l+zQD#;!P zBel#URX>A>KvvOX$G6O50*}e~)+zlI;#eaA&;iQ;Lr9)CVlomE|1%p;h~gFBpN=r1 zW(2}9JV+`D%SDzOgI$GiEAD4mmXTxAfmgX2Wh;Ckd3^WJ+Gp8q{viCyn!N_iIih(! zA}`8&+RwsYqbaG_Q&OQNPUQJnBu;GkSs;dq;uOCaCPG6DQ=*j$aFrRt;l!}m@;8ZJ zo8F3>f(?bJl6ZM0ZW8>ORM9}W)pnGr+!nq)W|Z9&j_4XY)(LE=3dXI5S!us`&SX`1A84zJDjO{qK(-1pXsg@h4qn^RLW6p^B!% zoG9x1qGClq5-}X2q%Y8pF%^a#)InU#VgP@Rtf1W~#jTk^lW2}OzC_SIo;PT>F9yDD z5G-gBUe*)FD_oHhdwZR~0hjMiugO#vPqIz7!@k$cN4XDh1W~pi!XR7*v6Wtm-6! zq;o2Sw>tdmL85vi57Neif4g($Z&0DFtthH@@^;?tL^}K5?gNFe`IJJ#LKm%`3=M^H zB2UZ7Y3mfBcF_><4}?KGi;dyl-_Byba3d`TE~oA`U6St(w1X)`ynZu0p4ixVXweSE zU7F;`b^JBTMG`HR=&Ngl6Gg@rj70{2ZmI1TN->(8;mA#vrtg~a?w+=qmk$Td2nO!8 z+AZR8I>M2aQcX=0w(ZhIo<5y?6TYre)liLncibc->; z{^%S-4@^+*oWj)w#$S z;=rsZi(hTd^X<5ZTq&2eGe13d+0fgAg1y}?;Duad4pEK`tJ}y?$*mh1HLwF5usQL} zMGBLO*<;iurzwId>ov3WowEHt`{^|>am92b@)Re9#STnO=GLG%ROeMU4`EH(atI!z zJ8f7ms;IZ0J4l*(J1um}Hgo5UZHk_u`q;5mtqueIH=?KhI|@LJ5Xts{ZBsPz?z_ql z;apW=qj7NHAG!CWZsco2w(M_eRY(Bg@I{*qQ@vxy#ojv`%y4YeCm;9p;2Zta4ktO9 zHH)mfh2iRF0w(Fg?!B)B4k!@ErN45MC5n#%vBfn6@8v7!MH>}edN1>5T?izeft=&l zg_43Bmdqy9>3XQ&z7kuTR_AWG0`q(zY)*5K{GPGFMp-27n-tMoj(y! zWxwz7qz5h^+ujup1!a-H4nBB zJ=_%7<)Q8fOziIiSzdL;w!3Jc$Yo_rb+~vs^yFi^dA@r6q6-pEJDXB(v?;LC`$bQ2 zY#5`Ag6KS0U{5!hKR94r7SojI%N#0YQmXXbg+S*6w^ebFX<0YC~UhlwO#c9Vi;n zGl`Gs(0h5{_eyB2pu65<=ueZF;V}%FP@!->T9I=fjd=NMBaq&0fN~>X>(=qI6fqBy zE6A4YM4Q}X?WR=AIyu)dA*cFB%YM9DN(5%1c=> z&lIc!1%iZ4^O`sz94Uja;mh%fjYv{Z9``7J)h7JG*y{YJ7ca#8EDZT~wE3t1Ry8vC zEC~4%k4>n%>7uG(eaO^}SUQtI03#>mLnK2HTT)C53f4kN5LhA4g3h9AIMt zjZ+i5Hkn!>HPWbr=P7E2L#WKx9msc-FTONYK6ojgey0iC{oT1ioF2oU^c>8u)Ag|V z;Pu<1`?u@XoS3Nw<2scGN2s96;21I z=hW5$v01M;M~5zm4b+Zn6SE($MG3ZDxr4%&Vwon0t=u)7eY;ZMUJdA=MYE(;Oy1+C zdVq(&E6ygZ`sU7%7x38t*PE*v(95MY-zG|rM=hW4%N1|$6+aNd?i(<70Eqq`2(TyO zSH-IxpfX$e0RSa$Ue5Y48zIz`sY66o3fB4EYGfr8;12by!n7&Vl)Z|p3CHE^-47M3 z3D&0l+!Ct#uERBar_Fu7Br&7v;zU*Yw>^NzcwD^SplK7YD`+2F!dcj{oCk@?oQkYU z&CjNB!-|~Tnw2J>WoF5U{q(L1Q%y4cJOuxA9#3g}E}XY|$q_AJs9EfRo2PC7ZfRsI zQ?$Px4T8Ub9e-63SR&a{kYoG7q2wAia1Ar{VeLb$Mq#ng@R07%U}eBr z(BPz+fn4=kYBEW_jKbItP+~W_OUtYXhfFIj6Tq9z?9K9i-+?cEObLrFe*`^k4ii(x zH4ZfzQIVh46Q$XZV(%D<|M>0Zm^&SIo1R5`MNxlRapAn-7}=JxQ#1N?vT5|=_m+Rf zRXj@}os+UZR$}!+1*$Hs%}L58|7Y>8=6v)8v%zGMI~cT=4ufRg!iBi7`>DQyvG39v zo3bB;)>*{lfo^rK3rsz$Hi|g*!%U;7ISffrVP<EV5VDqq2e+ znzlNH-+)^%D3K!B9kpUCFQgcrgA8}Rot#U`m2c^id{n$Dr3d)S&o7b{MYWQCou+XtH>T^s(23{j=ZcHx_3Am%mMNuo6x!@`?=$SM*@rk8WDBs7}wUez!7%dg$Sz>Lm-X(W10@zds1Ln+0 z-%EGdf*H##1K7ZsWE(0w+t$o)Js8)YG+wAVQW=M{6~aK-tWc~9_l+T+NER#Z^GSkU zHpR!AB68(aa=$HBVPb5VnsTzQ;rjWImu@!VN-gg|c{=)4%1;e43CDK+_dOR3W zOgD0zhJe^+a&OUz|#0 zPfEhYHbJd10V_AZwgCbN?GlnB7~L}1rD(C39Qv zOzmv7avR}S^>|VrO#YnbP#;7SKaqSVkJIqOHouyy(wMZbWwbg{dHo)k{7KLp;s%H5 z^QQ_DK}Y9_3&`+}>|!SxNJRc9rGPy6IzU_nA?TM+u2O^H0Lt=RZ;QK-6cd`1q0w;C z8x&MURmpaH93{77hA=o-c$6ZKl%Y}-M_CJ#QrckvG*MLxl~R%_3+XzzAtobOuvcDS zIJy6p*myl=H>LAyJQI6au*>0v*wbg~)i`Ve#N+~btlu4&?M;k4IW!b6UP;@tw5Y})}VkjEF=lIY;X$y4)lxSI5S33&&7QonzlWb*;>+)MabKr1p> zAy}y3E5Q*I^JRNp>=rWIYk)eS%7;et?sPest^P$Pym%(eqy~N}PiCa|PLg0XQNKb> zvR2^vh4jNF&rH6vK8dAChwu}&!QsD$CMideimV~ec z{i@KN-C3!)mIhM3gbz$;p{K(7_>_8#a>*n7-VSV*0{mXj-upOW%D56~eSygA8Iq)O zMzv_&9f95~VHP4O0kVsJT4f{`B)#*LzS?kbF?y7ZaT|Z$(_A{4XEUZ&n)NT~7#pM7 z5MCh;jqy@y5Gd!jFT{gA{ri2xx^RC>^ca3+VUqZqO#ZV8f40B=W0L>dgg-tD zbACuzn|~gNk>L*!bqUe`wT<#F*@8fIQE>4 zd-BkzaDn5+xW_nylagYHf?ND;sjau?FH4_j%;l4ff&E;nhMui}p`n~Lt*e!#mC{Ju zJUwjZl-hAWjh%~wo?YRweyJYMw0uUQx`fu=@}Lyk<=yc2G80|0Uo5!{tW zR}R4+Y6GPhNu@bhOWBHN3Q&)m6+p%L>#W7Grik});79>$S~X!dperrjkH~h@g1r!CFHv zO3{NgYKt@#A{0DHN&SH$F-AdBp@H>MsTAp{T2aC7p&$woiPeJ#e^A7OUc3k*B6tu% zJg5kw?`1Q2yI*D};}n|E&ilUE*_qjWGw*#b7pJcLd~&G}U%l^5X8OR}fls^NZ$C1$ z>rrCt_4up&gZAR%3qLxm2bW@lqm|UH>(?sl7Uol1yvy(UdM55p(=JEi%f>%LM=y3B zdN_4;CboA&Y&LiEcl&5EUcNC`xIfl?XEL_*D|z^Pek4^{HIncBknQh{f1K^e6emxZ z<|YpS9;@ear%o426HUo}^zX(zPC#9AAz!n5Hyf+TDumrq=0BNQ9{@LR6(?^1q4nLzF@FW9Tz!x|m?835<8RKw;c~6%u zvrSYk@?vC~@GjD0*6xZMD{NDo8nR*Bl(3b0Y}qtXR7is%MnZFMt1XQ-;0THE^izn= zZ?hnhhg4c~7K&te+#+OU(#>mmtAq>=Uyuh60)%IHrv;CHDZyg_Bw#?bp0N|@7k(xd z$;S#`NZ7?PA+bxTkp8A`w?L|UhX{xcrh@d`Z+3v-ZX!PVlY*ZcFkgDJJFE9DkrCZO zVeA+TJBet?HPvlmf5I<(o7U|2+p4?^lO=l>Vz~n>+1D^xv#%l6;~H!6JhGV;^v32m OUG!6;1}{);$N2|6I}i*2 diff --git a/build/resources/main/org/sasanlabs/attackvectors/images/1*1_Default.gif b/build/resources/main/org/sasanlabs/attackvectors/images/1*1_Default.gif deleted file mode 100644 index 57aeed3dba476ea689dadc094cad38a911288797..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37 mcmZ?wbhEHbWMp7uC}3bv{K>+~00cT90wl)3#N@)rU=09cqXX~& diff --git a/build/resources/main/org/sasanlabs/attackvectors/images/1*1_Default_JSP_Injected_EXIF.gif b/build/resources/main/org/sasanlabs/attackvectors/images/1*1_Default_JSP_Injected_EXIF.gif deleted file mode 100644 index b4acb4471ab4d2a219f75db42498be4fafdacd5f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 80 zcmZ?wbhEHbWMp7uC}3bv{K>+~00fHv)NNE96bcg4Qx!6E3-XIfY_k%}67@<;GIR8_ abinM)d_65yI|dz)dXRPoCMFj~25SHpSrP#N diff --git a/build/tmp/jar/MANIFEST.MF b/build/tmp/jar/MANIFEST.MF deleted file mode 100644 index 58630c0..0000000 --- a/build/tmp/jar/MANIFEST.MF +++ /dev/null @@ -1,2 +0,0 @@ -Manifest-Version: 1.0 - diff --git a/build/tmp/jarZapAddOn/MANIFEST.MF b/build/tmp/jarZapAddOn/MANIFEST.MF deleted file mode 100644 index 58630c0..0000000 --- a/build/tmp/jarZapAddOn/MANIFEST.MF +++ /dev/null @@ -1,2 +0,0 @@ -Manifest-Version: 1.0 - diff --git a/build/zapAddOn/ZapAddOn.xml b/build/zapAddOn/ZapAddOn.xml deleted file mode 100644 index 3b3fd87..0000000 --- a/build/zapAddOn/ZapAddOn.xml +++ /dev/null @@ -1,20 +0,0 @@ - - File upload Scan Rule - 1.0.0 - alpha - Detect File upload requests and scan them to find related vulnerabilities - KSASAN preetkaran20@gmail.com - <h3>Added</h3> -<ul> -<li>Increased the number of requests for High threshold to 18 from 12.</li> -<li>Client side configuration alerts will not stop the scanner from scanning server side configurations.</li> -<li>Support for validating usage of publicly well known HMac secrets for signing JWT.</li> -</ul> - - https://github.com/SasanLabs/owasp-zap-fileupload-addon/ - - - org.sasanlabs.fileupload.FileUploadExtension - - 2.9.0 - diff --git a/build/zapAddOn/bin/fileupload-alpha-1.0.0.zap b/build/zapAddOn/bin/fileupload-alpha-1.0.0.zap deleted file mode 100644 index 885e6475ab5309c8d09e65daf326301921d63799..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21809 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

wte_r-v{k+jD_*bm=cP%o)EaG|&rk^$3 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 F`3u^_$R+>) diff --git a/build/zapAddOn/latest-changes.md b/build/zapAddOn/latest-changes.md deleted file mode 100644 index e9fe5ab..0000000 --- a/build/zapAddOn/latest-changes.md +++ /dev/null @@ -1,4 +0,0 @@ -### Added - - Increased the number of requests for High threshold to 18 from 12. - - Client side configuration alerts will not stop the scanner from scanning server side configurations. - - Support for validating usage of publicly well known HMac secrets for signing JWT. \ No newline at end of file diff --git a/build/zapAddOn/manifest-changes.html b/build/zapAddOn/manifest-changes.html deleted file mode 100644 index dcef059..0000000 --- a/build/zapAddOn/manifest-changes.html +++ /dev/null @@ -1,6 +0,0 @@ -

Added

-
    -
  • Increased the number of requests for High threshold to 18 from 12.
  • -
  • Client side configuration alerts will not stop the scanner from scanning server side configurations.
  • -
  • Support for validating usage of publicly well known HMac secrets for signing JWT.
  • -
From 1e109d18af9ca6869ff37fb261a18595bd5f99db Mon Sep 17 00:00:00 2001 From: karan preet singh sasan Date: Sat, 26 Dec 2020 19:49:29 +0530 Subject: [PATCH 09/53] First Runnable tested code --- build.gradle.kts | 4 +- .../org/sasanlabs/fileupload/Constants.java | 2 +- .../fileupload/FileUploadScanRule.java | 6 -- .../fileupload/attacks/AttackVector.java | 23 +++-- .../attacks/ConsumerWithException.java | 1 + .../attacks/FileUploadAttackExecutor.java | 11 ++- .../attacks/beans/FileExtensionOperation.java | 87 +++++++++++++++++++ .../attacks/beans/FileParameter.java | 29 +++---- .../ImageBasedJSPRemoteCodeExecution.java | 22 ++++- .../impl/PlainOldJSPRemoteCodeExecution.java | 21 ++++- .../impl/PlainOldJSPXRemoteCodeExecution.java | 21 ++++- .../attacks/impl/XSSByHtmlUpload.java | 40 +++++++-- .../configuration/URILocatorImpl.java | 6 +- 13 files changed, 217 insertions(+), 56 deletions(-) create mode 100644 src/main/java/org/sasanlabs/fileupload/attacks/beans/FileExtensionOperation.java diff --git a/build.gradle.kts b/build.gradle.kts index 0e6d8af..c9c5a71 100755 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -34,7 +34,7 @@ description = "Detect File upload requests and scan them to find related vulnera zapAddOn { addOnName.set("File upload Scan Rule") - zapVersion.set("2.9.0") + zapVersion.set("2.10.0") addOnStatus.set(AddOnStatus.ALPHA) manifest { @@ -48,4 +48,4 @@ zapAddOn { dependencies { //implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar")))) -} +} \ No newline at end of file diff --git a/src/main/java/org/sasanlabs/fileupload/Constants.java b/src/main/java/org/sasanlabs/fileupload/Constants.java index cbc8909..7a1f3f1 100644 --- a/src/main/java/org/sasanlabs/fileupload/Constants.java +++ b/src/main/java/org/sasanlabs/fileupload/Constants.java @@ -12,7 +12,7 @@ * limitations under the License. */ package org.sasanlabs.fileupload; - +/** @author preetkaran20@gmail.com KSASAN */ public interface Constants { String EMPTY_STRING = ""; String PERIOD = "."; diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java index 5fdccab..c5cbb41 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java @@ -133,12 +133,6 @@ public int getCategory() { return Category.MISC; } - // @Override - public void scan(HttpMessage msg, String param, String value) { - // TODO Auto-generated method stub - LOGGER.error("Done"); - } - /** * Sets the parameter into the given {@code message}. If both parameter name and value are * {@code null}, the parameter will be removed. diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java index f30e8de..0542d74 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java @@ -63,7 +63,7 @@ default HttpMessage executePreflightRequest( default boolean genericAttackExecutor( FileUploadAttackExecutor fileUploadAttackExecutor, - ContentMatcher md5HashResponseMatcher, + ContentMatcher contentMatcher, String payload, String baseFileName, List fileParameters) @@ -75,37 +75,46 @@ default boolean genericAttackExecutor( for (NameValuePair nameValuePair : nameValuePairs) { if (nameValuePair.getType() == NameValuePair.TYPE_MULTIPART_DATA_FILE_NAME) { originalFileName = nameValuePair.getValue(); + break; } } for (FileParameter fileParameter : fileParameters) { HttpMessage newMsg = originalMsg.cloneRequest(); - for (NameValuePair nameValuePair : nameValuePairs) { + for (int i = 0; i < nameValuePairs.size(); i++) { + NameValuePair nameValuePair = nameValuePairs.get(i); if (nameValuePair.getType() == NameValuePair.TYPE_MULTIPART_DATA_FILE_NAME) { fileUploadScanRule.setParameter( newMsg, nameValuePair, nameValuePair.getName(), fileParameter.getFileName(originalFileName, baseFileName)); - } - if (nameValuePair.getType() == NameValuePair.TYPE_MULTIPART_DATA_FILE_PARAM) { + } else if (nameValuePair.getType() + == NameValuePair.TYPE_MULTIPART_DATA_FILE_PARAM) { fileUploadScanRule.setParameter( newMsg, nameValuePair, nameValuePair.getName(), payload); - } - if (nameValuePair.getType() == NameValuePair.TYPE_MULTIPART_DATA_FILE_CONTENTTYPE) { + } else if (nameValuePair.getType() + == NameValuePair.TYPE_MULTIPART_DATA_FILE_CONTENTTYPE) { fileUploadScanRule.setParameter( newMsg, nameValuePair, nameValuePair.getName(), fileParameter.getContentType()); + } else { + continue; } + // Reinitialize the name-value pair positions + fileUploadAttackExecutor.getVariant().setMessage(newMsg); + nameValuePairs = fileUploadAttackExecutor.getVariant().getParamList(); } + // Reset variant + fileUploadAttackExecutor.getVariant().setMessage(originalMsg); fileUploadScanRule.sendAndRecieve(newMsg); HttpMessage preflightMsg = this.executePreflightRequest( newMsg, fileParameter.getFileName(originalFileName, baseFileName), fileUploadScanRule); - if (md5HashResponseMatcher.match(preflightMsg)) { + if (contentMatcher.match(preflightMsg)) { return true; } } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/ConsumerWithException.java b/src/main/java/org/sasanlabs/fileupload/attacks/ConsumerWithException.java index d9d52db..b062eec 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/ConsumerWithException.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/ConsumerWithException.java @@ -13,6 +13,7 @@ */ package org.sasanlabs.fileupload.attacks; +/** @author preetkaran20@gmail.com KSASAN */ @FunctionalInterface public interface ConsumerWithException { void accept(T val) throws E; diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java b/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java index 36c4974..e5a8c02 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java @@ -15,9 +15,13 @@ import java.util.Arrays; import java.util.List; + import org.parosproxy.paros.core.scanner.Variant; import org.parosproxy.paros.network.HttpMessage; import org.sasanlabs.fileupload.FileUploadScanRule; +import org.sasanlabs.fileupload.attacks.impl.ImageBasedJSPRemoteCodeExecution; +import org.sasanlabs.fileupload.attacks.impl.PlainOldJSPRemoteCodeExecution; +import org.sasanlabs.fileupload.attacks.impl.PlainOldJSPXRemoteCodeExecution; import org.sasanlabs.fileupload.attacks.impl.XSSByHtmlUpload; /** @@ -31,7 +35,12 @@ public class FileUploadAttackExecutor { private HttpMessage originalHttpMessage; private FileUploadScanRule fileUploadScanRule; private Variant variant; - private List attackVectors = Arrays.asList(new XSSByHtmlUpload()); + private List attackVectors = + Arrays.asList( + new XSSByHtmlUpload(), + new PlainOldJSPRemoteCodeExecution(), + new PlainOldJSPXRemoteCodeExecution(), + new ImageBasedJSPRemoteCodeExecution()); public FileUploadAttackExecutor( HttpMessage originalHttpMessage, diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileExtensionOperation.java b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileExtensionOperation.java new file mode 100644 index 0000000..4ee32a3 --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileExtensionOperation.java @@ -0,0 +1,87 @@ +/** + * Copyright 2020 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sasanlabs.fileupload.attacks.beans; + +import org.apache.commons.lang3.StringUtils; +import org.sasanlabs.fileupload.Constants; +import org.sasanlabs.fileupload.attacks.FileUploadException; + +/** + * {@code FileExtensionOperation} is used to denote the operation on the file name extensions. + * + * @author preetkaran20@gmail.com KSASAN + */ +public enum FileExtensionOperation { + + /** + * appends the Original File Extension before the provided extension. e.g. if provided extension + * is {@code html} and original file extension is {@code pdf} then the final extension will be + * {@code pdf.html} + */ + PREFIX_ORIGINAL_EXTENSION, + + /** + * appends the Original File Extension after the provided extension e.g. if provided extension + * is {@code html%00} and original file extension is {@code pdf} then the final extension will + * be {@code html%00.pdf} + */ + SUFFIX_ORIGINAL_EXTENSION, + + /** + * only appends the provided extension e.g. if provided extension is {@code html} and original + * file extension is {@code pdf} then final extension will be {@code .html} + */ + ONLY_PROVIDED_EXTENSION; + + public static String appendPeriodCharacter(String extension) { + if (StringUtils.isBlank(extension)) { + return extension; + } else { + if (extension.startsWith(Constants.PERIOD)) { + return extension; + } + return Constants.PERIOD + extension; + } + } + + public String operator(String providedExtension, String originalFileName) + throws FileUploadException { + if (StringUtils.isBlank(providedExtension)) { + throw new FileUploadException("Provided extension is null"); + } + String extension; + int firstIndexOfPeriodCharacter; + String originalExtension = ""; + if (originalFileName != null) { + firstIndexOfPeriodCharacter = originalFileName.indexOf(Constants.PERIOD); + if (firstIndexOfPeriodCharacter >= 0) { + originalExtension = originalFileName.substring(firstIndexOfPeriodCharacter + 1); + } + } + switch (this) { + case PREFIX_ORIGINAL_EXTENSION: + extension = originalExtension + appendPeriodCharacter(providedExtension); + break; + case SUFFIX_ORIGINAL_EXTENSION: + extension = providedExtension + appendPeriodCharacter(originalExtension); + break; + case ONLY_PROVIDED_EXTENSION: + extension = providedExtension; + break; + default: + extension = providedExtension; + } + return extension; + } +} diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java index b19374f..ed70ef4 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java @@ -15,7 +15,7 @@ import java.util.Date; import java.util.Random; -import org.sasanlabs.fileupload.Constants; +import org.sasanlabs.fileupload.attacks.FileUploadException; /** * {@code FileParameter} class is used to represent the file object ... @@ -27,7 +27,8 @@ public class FileParameter { private String baseFileName; private String extension; private String contentType; - private boolean useOriginalExtention = false; + private FileExtensionOperation fileExtensionOperation = + FileExtensionOperation.ONLY_PROVIDED_EXTENSION; public FileParameter(String extension, String contentType) { super(); @@ -36,30 +37,24 @@ public FileParameter(String extension, String contentType) { this.contentType = contentType; } - public FileParameter(String extension, String contentType, boolean useOriginalExtension) { + public FileParameter( + String extension, String contentType, FileExtensionOperation fileExtensionOperation) { super(); this.baseFileName = String.valueOf(new Random(new Date().getTime()).nextLong()); this.extension = extension; this.contentType = contentType; - this.useOriginalExtention = useOriginalExtension; + this.fileExtensionOperation = fileExtensionOperation; } public String getContentType() { return contentType; } - public String getFileName(String originalFileName, String newBaseFileName) { - String extension; - if (this.useOriginalExtention && originalFileName != null) { - int firstIndexOfPeriodCharacter = originalFileName.indexOf(Constants.PERIOD); - String originalExtension = ""; - if (firstIndexOfPeriodCharacter >= 0) { - originalExtension = originalFileName.substring(firstIndexOfPeriodCharacter + 1); - } - extension = originalExtension + this.extension; - } else { - extension = this.extension; - } - return String.valueOf(newBaseFileName) + this.baseFileName + Constants.PERIOD + extension; + public String getFileName(String originalFileName, String newBaseFileName) + throws FileUploadException { + return String.valueOf(newBaseFileName) + + this.baseFileName + + FileExtensionOperation.appendPeriodCharacter( + fileExtensionOperation.operator(this.extension, originalFileName)); } } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/impl/ImageBasedJSPRemoteCodeExecution.java b/src/main/java/org/sasanlabs/fileupload/attacks/impl/ImageBasedJSPRemoteCodeExecution.java index 509dd3b..55b0fed 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/impl/ImageBasedJSPRemoteCodeExecution.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/impl/ImageBasedJSPRemoteCodeExecution.java @@ -26,9 +26,11 @@ import org.sasanlabs.fileupload.attacks.AttackVector; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; import org.sasanlabs.fileupload.attacks.FileUploadException; +import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; import org.sasanlabs.fileupload.attacks.beans.FileParameter; import org.sasanlabs.fileupload.matcher.impl.ContainsExpectedValueMatcher; +/** @author preetkaran20@gmail.com KSASAN */ public class ImageBasedJSPRemoteCodeExecution implements AttackVector { private static final String GIF_IMAGE_JSP_INJECTED_IN_EXIF_BASE64_ENCODED = @@ -41,10 +43,22 @@ public class ImageBasedJSPRemoteCodeExecution implements AttackVector { Arrays.asList( new FileParameter("jsp", Constants.EMPTY_STRING), new FileParameter("jsp", "application/x-jsp"), - new FileParameter("jsp.", Constants.EMPTY_STRING, true), - new FileParameter("jsp.", "application/x-jsp", true), - new FileParameter("jsp." + NULL_BYTE_CHARACTER, Constants.EMPTY_STRING, true), - new FileParameter("jsp." + NULL_BYTE_CHARACTER, "application/x-jsp", true)); + new FileParameter( + "jsp", + Constants.EMPTY_STRING, + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "jsp", + "application/x-jsp", + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "jsp" + NULL_BYTE_CHARACTER, + Constants.EMPTY_STRING, + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "jsp" + NULL_BYTE_CHARACTER, + "application/x-jsp", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION)); @Override public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPRemoteCodeExecution.java b/src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPRemoteCodeExecution.java index cd697e6..429b966 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPRemoteCodeExecution.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPRemoteCodeExecution.java @@ -22,6 +22,7 @@ import org.sasanlabs.fileupload.attacks.AttackVector; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; import org.sasanlabs.fileupload.attacks.FileUploadException; +import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; import org.sasanlabs.fileupload.attacks.beans.FileParameter; import org.sasanlabs.fileupload.matcher.ContentMatcher; import org.sasanlabs.fileupload.matcher.impl.MD5HashResponseMatcher; @@ -43,10 +44,22 @@ public class PlainOldJSPRemoteCodeExecution implements AttackVector { Arrays.asList( new FileParameter("jsp", Constants.EMPTY_STRING), new FileParameter("jsp", "application/x-jsp"), - new FileParameter("jsp.", Constants.EMPTY_STRING, true), - new FileParameter("jsp.", "application/x-jsp", true), - new FileParameter("jsp." + NULL_BYTE_CHARACTER, Constants.EMPTY_STRING, true), - new FileParameter("jsp." + NULL_BYTE_CHARACTER, "application/x-jsp", true)); + new FileParameter( + "jsp", + Constants.EMPTY_STRING, + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "jsp", + "application/x-jsp", + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "jsp" + NULL_BYTE_CHARACTER, + Constants.EMPTY_STRING, + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "jsp" + NULL_BYTE_CHARACTER, + "application/x-jsp", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION)); @Override public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPXRemoteCodeExecution.java b/src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPXRemoteCodeExecution.java index 3566361..0b59a2f 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPXRemoteCodeExecution.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPXRemoteCodeExecution.java @@ -22,6 +22,7 @@ import org.sasanlabs.fileupload.attacks.AttackVector; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; import org.sasanlabs.fileupload.attacks.FileUploadException; +import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; import org.sasanlabs.fileupload.attacks.beans.FileParameter; import org.sasanlabs.fileupload.matcher.ContentMatcher; import org.sasanlabs.fileupload.matcher.impl.MD5HashResponseMatcher; @@ -50,10 +51,22 @@ public class PlainOldJSPXRemoteCodeExecution implements AttackVector { Arrays.asList( new FileParameter("jspx", Constants.EMPTY_STRING), new FileParameter("jspx", "application/x-jsp"), - new FileParameter("jspx.", Constants.EMPTY_STRING, true), - new FileParameter("jspx.", "application/x-jsp", true), - new FileParameter("jspx." + NULL_BYTE_CHARACTER, Constants.EMPTY_STRING, true), - new FileParameter("jspx." + NULL_BYTE_CHARACTER, "application/x-jsp", true)); + new FileParameter( + "jspx", + Constants.EMPTY_STRING, + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "jspx", + "application/x-jsp", + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "jspx" + NULL_BYTE_CHARACTER, + Constants.EMPTY_STRING, + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "jspx" + NULL_BYTE_CHARACTER, + "application/x-jsp", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION)); @Override public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/impl/XSSByHtmlUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/impl/XSSByHtmlUpload.java index 95b9adf..7602513 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/impl/XSSByHtmlUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/impl/XSSByHtmlUpload.java @@ -23,6 +23,7 @@ import org.sasanlabs.fileupload.attacks.AttackVector; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; import org.sasanlabs.fileupload.attacks.FileUploadException; +import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; import org.sasanlabs.fileupload.attacks.beans.FileParameter; import org.sasanlabs.fileupload.matcher.ContentMatcher; import org.sasanlabs.fileupload.matcher.impl.MD5HashResponseMatcher; @@ -59,15 +60,36 @@ private static boolean isContentDispositionInline(HttpMessage preflightMsg) { new FileParameter("htm", "text/plain"), new FileParameter("html", "text/plain"), new FileParameter("xhtml", "text/plain"), - new FileParameter("htm.", "text/html", true), - new FileParameter("html.", "text/html", true), - new FileParameter("xhtml.", "text/html", true), - new FileParameter("htm." + NULL_BYTE_CHARACTER, "text/html", true), - new FileParameter("html." + NULL_BYTE_CHARACTER, "text/html", true), - new FileParameter("xhtml." + NULL_BYTE_CHARACTER, "text/html", true), - new FileParameter("htm." + NULL_BYTE_CHARACTER, "text/plain", true), - new FileParameter("html." + NULL_BYTE_CHARACTER, "text/plain", true), - new FileParameter("xhtml." + NULL_BYTE_CHARACTER, "text/plain", true)); + new FileParameter( + "htm", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "html", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "xhtml", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "htm" + NULL_BYTE_CHARACTER, + "text/html", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "html" + NULL_BYTE_CHARACTER, + "text/html", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "xhtml" + NULL_BYTE_CHARACTER, + "text/html", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "htm" + NULL_BYTE_CHARACTER, + "text/plain", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "html" + NULL_BYTE_CHARACTER, + "text/plain", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "xhtml" + NULL_BYTE_CHARACTER, + "text/plain", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION)); /** * @throws FileUploadException diff --git a/src/main/java/org/sasanlabs/fileupload/configuration/URILocatorImpl.java b/src/main/java/org/sasanlabs/fileupload/configuration/URILocatorImpl.java index 89fb497..025450e 100644 --- a/src/main/java/org/sasanlabs/fileupload/configuration/URILocatorImpl.java +++ b/src/main/java/org/sasanlabs/fileupload/configuration/URILocatorImpl.java @@ -26,12 +26,16 @@ import org.sasanlabs.fileupload.attacks.ConsumerWithException; import org.sasanlabs.fileupload.attacks.FileUploadException; +/** @author preetkaran20@gmail.com KSASAN */ public class URILocatorImpl implements URILocator { protected static final Logger LOGGER = Logger.getLogger(URILocatorImpl.class); private URI getCompleteURI(String uriRegex, String fileName, HttpMessage msg) throws URIException, FileUploadException { + if (fileName.contains(Constants.NULL_BYTE_CHARACTER)) { + fileName = fileName.substring(0, fileName.indexOf(Constants.NULL_BYTE_CHARACTER)); + } Map replacerKeyValuePair = new HashMap<>(); replacerKeyValuePair.put("filename", fileName); StringSubstitutor stringSubstitutor = new StringSubstitutor(replacerKeyValuePair); @@ -42,7 +46,7 @@ private URI getCompleteURI(String uriRegex, String fileName, HttpMessage msg) } else if (uriFragment.startsWith(Constants.SLASH)) { String authority = msg.getRequestHeader().getURI().getAuthority(); String scheme = msg.getRequestHeader().getURI().getScheme(); - return new URI(scheme, authority + uriFragment, ""); + return new URI(scheme, authority, uriFragment, ""); } else { throw new FileUploadException("FileUpload configuration is invalid."); } From 6f9e137eda855b1e0f52e76eb056f765520b396a Mon Sep 17 00:00:00 2001 From: karan preet singh sasan Date: Sat, 26 Dec 2020 19:56:36 +0530 Subject: [PATCH 10/53] Fixing ChangeLog --- CHANGELOG.md | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4394de8..3383d68 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,14 +4,7 @@ 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/). ## Unreleased - -### Added - - Increased the number of requests for High threshold to 18 from 12. - - Client side configuration alerts will not stop the scanner from scanning server side configurations. - - Support for validating usage of publicly well known HMac secrets for signing JWT. - -## [1.0.0] - 2020-09-03 +## [1.0.0] - 2020-12-26 - - First version of JWT Support. - - Contains scanning rules for basic JWT related vulnerabilities. - - Contains JWT Fuzzer for fuzzing the JWT's present in the request. + - First version of FileUpload Addon. + - Contains scan rule for finding vulnerabilities related to File Upload. From f03bde78d9c4ac5eb470b94f9bbde00a39c0dd41 Mon Sep 17 00:00:00 2001 From: karan preet singh sasan Date: Sun, 27 Dec 2020 00:04:25 +0530 Subject: [PATCH 11/53] Formatting --- .../org/sasanlabs/fileupload/Constants.java | 7 +- .../fileupload/FileUploadScanRule.java | 49 ++- .../org/sasanlabs/fileupload/URILocator.java | 30 -- .../fileupload/attacks/AttackVector.java | 54 +-- .../attacks/FileUploadAttackExecutor.java | 12 +- .../EicarAntivirusTestFileUpload.java} | 19 +- .../attacks/beans/FileExtensionOperation.java | 2 +- .../attacks/beans/FileParameter.java | 2 +- .../attacks/impl/XSSByHtmlUpload.java | 130 ------- .../attacks/{impl => rce}/PathTraversal.java | 2 +- .../ImageBasedJSPRemoteCodeExecution.java | 4 +- .../jsp}/PlainOldJSPRemoteCodeExecution.java | 4 +- .../jsp}/PlainOldJSPXRemoteCodeExecution.java | 4 +- .../attacks/{impl => rce/php}/PhpRCE.java | 2 +- .../attacks/xss/HtmlFileUpload.java | 362 ++++++++++++++++++ .../FileUploadException.java | 2 +- .../ConsumerWithException.java | 2 +- .../URILocator.java | 6 +- .../URILocatorImpl.java | 7 +- .../fileupload/redownloader/Redownloader.java | 17 - .../attackvectors/files/jspx_payload.jspx | 7 - .../fileupload/i18n/Messages.properties | 7 + 22 files changed, 442 insertions(+), 289 deletions(-) delete mode 100644 src/main/java/org/sasanlabs/fileupload/URILocator.java rename src/main/java/org/sasanlabs/fileupload/{URILocatorImpl.java => attacks/antivirus/EicarAntivirusTestFileUpload.java} (55%) delete mode 100644 src/main/java/org/sasanlabs/fileupload/attacks/impl/XSSByHtmlUpload.java rename src/main/java/org/sasanlabs/fileupload/attacks/{impl => rce}/PathTraversal.java (97%) rename src/main/java/org/sasanlabs/fileupload/attacks/{impl => rce/jsp}/ImageBasedJSPRemoteCodeExecution.java (97%) rename src/main/java/org/sasanlabs/fileupload/attacks/{impl => rce/jsp}/PlainOldJSPRemoteCodeExecution.java (97%) rename src/main/java/org/sasanlabs/fileupload/attacks/{impl => rce/jsp}/PlainOldJSPXRemoteCodeExecution.java (97%) rename src/main/java/org/sasanlabs/fileupload/attacks/{impl => rce/php}/PhpRCE.java (95%) create mode 100644 src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java rename src/main/java/org/sasanlabs/fileupload/{attacks => exception}/FileUploadException.java (96%) rename src/main/java/org/sasanlabs/fileupload/{attacks => function}/ConsumerWithException.java (94%) rename src/main/java/org/sasanlabs/fileupload/{configuration => locator}/URILocator.java (87%) rename src/main/java/org/sasanlabs/fileupload/{configuration => locator}/URILocatorImpl.java (96%) delete mode 100644 src/main/java/org/sasanlabs/fileupload/redownloader/Redownloader.java delete mode 100644 src/main/resources/org/sasanlabs/attackvectors/files/jspx_payload.jspx diff --git a/src/main/java/org/sasanlabs/fileupload/Constants.java b/src/main/java/org/sasanlabs/fileupload/Constants.java index 7a1f3f1..096dab2 100644 --- a/src/main/java/org/sasanlabs/fileupload/Constants.java +++ b/src/main/java/org/sasanlabs/fileupload/Constants.java @@ -12,7 +12,12 @@ * limitations under the License. */ package org.sasanlabs.fileupload; -/** @author preetkaran20@gmail.com KSASAN */ + +/** + * Contains the String constants or other utility constants used by the File Upload Addon. + * + * @author preetkaran20@gmail.com KSASAN + */ public interface Constants { String EMPTY_STRING = ""; String PERIOD = "."; diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java index c5cbb41..ce13ace 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java @@ -14,10 +14,8 @@ package org.sasanlabs.fileupload; import java.io.IOException; -import java.util.Arrays; -import java.util.HashSet; import java.util.List; -import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; import org.apache.log4j.Logger; import org.parosproxy.paros.core.scanner.Category; import org.parosproxy.paros.core.scanner.NameValuePair; @@ -25,26 +23,43 @@ import org.parosproxy.paros.core.scanner.VariantMultipartFormParameters; import org.parosproxy.paros.network.HttpMessage; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; +import org.sasanlabs.fileupload.i18n.FileUploadI18n; /** @author KSASAN preetkaran20@gmail.com */ public class FileUploadScanRule extends AbstractAppVariantPlugin { private static final int PLUGIN_ID = 110009; - private static final String NAME = "File Upload"; // JWTI18n.getMessage("jwt.scanner.name"); + private static final String NAME = FileUploadI18n.getMessage("fileupload.scanrule.name"); private static final String DESCRIPTION = - "File Upload"; // JWTI18n.getMessage("jwt.scanner.description"); - private static final String SOLUTION = "File Upload"; // JWTI18n.getMessage("jwt.scanner.soln"); - private static final String REFERENCE = - "File Upload"; // JWTI18n.getMessage("jwt.scanner.refs"); + FileUploadI18n.getMessage("fileupload.scanrule.description"); + private static final String SOLUTION = FileUploadI18n.getMessage("fileupload.scanrule.soln"); + private static final String REFERENCE = FileUploadI18n.getMessage("fileupload.scanrule.refs"); private static final Logger LOGGER = Logger.getLogger(FileUploadScanRule.class); private Variant variant = null; - private static final Set ALLOWED_TYPES = - new HashSet( - Arrays.asList( - NameValuePair.TYPE_MULTIPART_DATA_FILE_CONTENTTYPE, - NameValuePair.TYPE_MULTIPART_DATA_FILE_NAME, - NameValuePair.TYPE_MULTIPART_DATA_FILE_PARAM, - NameValuePair.TYPE_MULTIPART_DATA_PARAM)); + + private AtomicInteger maxRequestCount; + + @Override + public void init() { + switch (this.getAttackStrength()) { + case LOW: + maxRequestCount = new AtomicInteger(20); + break; + case MEDIUM: + maxRequestCount = new AtomicInteger(30); + break; + case HIGH: + maxRequestCount = new AtomicInteger(40); + break; + case INSANE: + maxRequestCount = new AtomicInteger(50); + break; + default: + maxRequestCount = new AtomicInteger(30); + break; + } + } + /* * Need to check what to include do we need to include XXE/XSS/Path Traversal in * this addon or we need to correct those. Persistent XXS/XXE/PathTraversal @@ -53,9 +68,7 @@ public class FileUploadScanRule extends AbstractAppVariantPlugin { * Will not include the reflected XSS because it should work and i have checked * it works. */ - - // debug if all these types will be there in all Multipart requests - // @Override + @Override public void scan(HttpMessage msg, Variant variant) { try { this.variant = variant; diff --git a/src/main/java/org/sasanlabs/fileupload/URILocator.java b/src/main/java/org/sasanlabs/fileupload/URILocator.java deleted file mode 100644 index 2c8029f..0000000 --- a/src/main/java/org/sasanlabs/fileupload/URILocator.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright 2020 SasanLabs - * - *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of the License at - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sasanlabs.fileupload; - -import org.apache.commons.httpclient.URI; -import org.apache.commons.httpclient.URIException; -import org.parosproxy.paros.network.HttpMessage; - -/** - * {@code URILocator} class is used to find the URL either by parsing the {@code HttpMessage} or - * reading the configuration mentioned in the options tab. - * - *

This class also handles the "regex based configuration" e.g "url/$fileName" - * - * @author preetkaran20@gmail.com KSASAN - */ -public interface URILocator { - URI get(HttpMessage msg) throws URIException; -} diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java index 0542d74..5e88444 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java @@ -14,17 +14,13 @@ package org.sasanlabs.fileupload.attacks; import java.io.IOException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Arrays; -import java.util.Base64; import java.util.List; -import org.apache.commons.httpclient.URIException; import org.parosproxy.paros.core.scanner.NameValuePair; import org.parosproxy.paros.network.HttpMessage; import org.sasanlabs.fileupload.FileUploadScanRule; import org.sasanlabs.fileupload.attacks.beans.FileParameter; -import org.sasanlabs.fileupload.configuration.URILocatorImpl; +import org.sasanlabs.fileupload.exception.FileUploadException; +import org.sasanlabs.fileupload.locator.URILocatorImpl; import org.sasanlabs.fileupload.matcher.ContentMatcher; /** @@ -125,52 +121,6 @@ default boolean genericAttackExecutor( // something like that // the scanner asks for the input file and then compare the request (whcih might // be encoded) with the input and then operate accordingly. - default boolean executeAttackAndRaiseAlert( - HttpMessage originalMsg, - HttpMessage modifiedMsg, - FileUploadScanRule fileUploadScanRule, - ContentMatcher responseMatcher) - throws URIException, NullPointerException, IOException { - HttpMessage preflightMsg = new HttpMessage(); - // preflightMsg.getRequestHeader().setURI(new URILocatorImpl().get(modifiedMsg)); - preflightMsg.getRequestHeader().setMethod("GET"); - preflightMsg.getRequestHeader().setCookies(modifiedMsg.getRequestHeader().getHttpCookies()); - fileUploadScanRule.sendAndRecieve(preflightMsg); - - // For XSS only - String headerValue = preflightMsg.getResponseHeader().getHeader("Content-Disposition"); - if (headerValue == null || headerValue.equals("inline")) { - // check content disposition - // preflightMsg.getResponseHeader(). - try { - MessageDigest messageDigest = MessageDigest.getInstance("MD5"); - byte[] digest = - messageDigest.digest( - Base64.getEncoder() - .encode(preflightMsg.getResponseBody().getBytes())); - return Arrays.equals( - digest, - messageDigest.digest( - Base64.getEncoder() - .encode(modifiedMsg.getResponseBody().getBytes()))); - } catch (NoSuchAlgorithmException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - // Try finding the URL in msg - // if found - // do a preflight request - // compare the results - // if not - // check if static url is selected - // do prefligh request with the same file name - // compare result - // try guessing the name - // if found compare result - return false; - }; /** * Executes the attack and checks if it is successful or not and then raise alert in case of diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java b/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java index e5a8c02..0deb812 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java @@ -15,14 +15,14 @@ import java.util.Arrays; import java.util.List; - import org.parosproxy.paros.core.scanner.Variant; import org.parosproxy.paros.network.HttpMessage; import org.sasanlabs.fileupload.FileUploadScanRule; -import org.sasanlabs.fileupload.attacks.impl.ImageBasedJSPRemoteCodeExecution; -import org.sasanlabs.fileupload.attacks.impl.PlainOldJSPRemoteCodeExecution; -import org.sasanlabs.fileupload.attacks.impl.PlainOldJSPXRemoteCodeExecution; -import org.sasanlabs.fileupload.attacks.impl.XSSByHtmlUpload; +import org.sasanlabs.fileupload.attacks.rce.jsp.ImageBasedJSPRemoteCodeExecution; +import org.sasanlabs.fileupload.attacks.rce.jsp.PlainOldJSPRemoteCodeExecution; +import org.sasanlabs.fileupload.attacks.rce.jsp.PlainOldJSPXRemoteCodeExecution; +import org.sasanlabs.fileupload.attacks.xss.HtmlFileUpload; +import org.sasanlabs.fileupload.exception.FileUploadException; /** * {@code FileUploadAttackExecutor} class is used to find File Upload vulnerability by executing @@ -37,7 +37,7 @@ public class FileUploadAttackExecutor { private Variant variant; private List attackVectors = Arrays.asList( - new XSSByHtmlUpload(), + new HtmlFileUpload(), new PlainOldJSPRemoteCodeExecution(), new PlainOldJSPXRemoteCodeExecution(), new ImageBasedJSPRemoteCodeExecution()); diff --git a/src/main/java/org/sasanlabs/fileupload/URILocatorImpl.java b/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java similarity index 55% rename from src/main/java/org/sasanlabs/fileupload/URILocatorImpl.java rename to src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java index eb41faa..38c2861 100644 --- a/src/main/java/org/sasanlabs/fileupload/URILocatorImpl.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java @@ -11,19 +11,18 @@ * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ -package org.sasanlabs.fileupload; +package org.sasanlabs.fileupload.attacks.antivirus; -import org.apache.commons.httpclient.URI; -import org.apache.commons.httpclient.URIException; -import org.parosproxy.paros.network.HttpMessage; +import org.sasanlabs.fileupload.attacks.AttackVector; +import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; +import org.sasanlabs.fileupload.exception.FileUploadException; -public class URILocatorImpl implements URILocator { +public class EicarAntivirusTestFileUpload implements AttackVector { @Override - public URI get(HttpMessage msg) throws URIException { - byte[] responseBody = msg.getResponseBody().getBytes(); - - // Say static configuration - return new URI("http://localhost:9090/contentDispositionUpload/karan.html"); + public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) + throws FileUploadException { + // TODO Auto-generated method stub + return false; } } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileExtensionOperation.java b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileExtensionOperation.java index 4ee32a3..d19dede 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileExtensionOperation.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileExtensionOperation.java @@ -15,7 +15,7 @@ import org.apache.commons.lang3.StringUtils; import org.sasanlabs.fileupload.Constants; -import org.sasanlabs.fileupload.attacks.FileUploadException; +import org.sasanlabs.fileupload.exception.FileUploadException; /** * {@code FileExtensionOperation} is used to denote the operation on the file name extensions. diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java index ed70ef4..787f81b 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java @@ -15,7 +15,7 @@ import java.util.Date; import java.util.Random; -import org.sasanlabs.fileupload.attacks.FileUploadException; +import org.sasanlabs.fileupload.exception.FileUploadException; /** * {@code FileParameter} class is used to represent the file object ... diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/impl/XSSByHtmlUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/impl/XSSByHtmlUpload.java deleted file mode 100644 index 7602513..0000000 --- a/src/main/java/org/sasanlabs/fileupload/attacks/impl/XSSByHtmlUpload.java +++ /dev/null @@ -1,130 +0,0 @@ -/** - * Copyright 2020 SasanLabs - * - *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of the License at - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sasanlabs.fileupload.attacks.impl; - -import static org.sasanlabs.fileupload.Constants.NULL_BYTE_CHARACTER; - -import java.io.IOException; -import java.util.Arrays; -import java.util.List; -import org.parosproxy.paros.network.HttpMessage; -import org.sasanlabs.fileupload.Constants; -import org.sasanlabs.fileupload.attacks.AttackVector; -import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; -import org.sasanlabs.fileupload.attacks.FileUploadException; -import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; -import org.sasanlabs.fileupload.attacks.beans.FileParameter; -import org.sasanlabs.fileupload.matcher.ContentMatcher; -import org.sasanlabs.fileupload.matcher.impl.MD5HashResponseMatcher; - -/** @author preetkaran20@gmail.com KSASAN */ -public class XSSByHtmlUpload implements AttackVector { - - private static final String XSS_UPLOADED_FILE_BASE_NAME = "XSSByHtmlUpload_"; - private static final String XSS_PAYLOAD_HTML_FILE = - "Testing XSS"; - - private static final ContentMatcher CONTENT_MATCHER = - new MD5HashResponseMatcher( - httpMsg -> isContentDispositionInline(httpMsg), XSS_PAYLOAD_HTML_FILE); - - private static boolean isContentDispositionInline(HttpMessage preflightMsg) { - String headerValue = preflightMsg.getResponseHeader().getHeader("Content-Disposition"); - if (headerValue == null - || headerValue.trim().equals(Constants.EMPTY_STRING) - || headerValue.equals("inline")) { - return true; - } - return false; - } - - private static final List FILE_PARAMETERS = - Arrays.asList( - new FileParameter("htm", Constants.EMPTY_STRING), - new FileParameter("html", Constants.EMPTY_STRING), - new FileParameter("xhtml", Constants.EMPTY_STRING), - new FileParameter("htm", "text/html"), - new FileParameter("html", "text/html"), - new FileParameter("xhtml", "text/html"), - new FileParameter("htm", "text/plain"), - new FileParameter("html", "text/plain"), - new FileParameter("xhtml", "text/plain"), - new FileParameter( - "htm", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "html", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "xhtml", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "htm" + NULL_BYTE_CHARACTER, - "text/html", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "html" + NULL_BYTE_CHARACTER, - "text/html", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "xhtml" + NULL_BYTE_CHARACTER, - "text/html", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "htm" + NULL_BYTE_CHARACTER, - "text/plain", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "html" + NULL_BYTE_CHARACTER, - "text/plain", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "xhtml" + NULL_BYTE_CHARACTER, - "text/plain", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION)); - - /** - * @throws FileUploadException - * @throws IOException - */ - @Override - public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) - throws FileUploadException { - boolean result = false; - try { - result = - this.genericAttackExecutor( - fileUploadAttackExecutor, - CONTENT_MATCHER, - XSS_PAYLOAD_HTML_FILE, - XSS_UPLOADED_FILE_BASE_NAME, - FILE_PARAMETERS); - if (result) { - fileUploadAttackExecutor - .getFileUploadScanRule() - .raiseAlert( - 1, - 1, - "", - "", - "", - "", - "", - "", - "", - fileUploadAttackExecutor.getOriginalHttpMessage()); - } - } catch (IOException e) { - throw new FileUploadException(e); - } - return result; - } -} diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/impl/PathTraversal.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/PathTraversal.java similarity index 97% rename from src/main/java/org/sasanlabs/fileupload/attacks/impl/PathTraversal.java rename to src/main/java/org/sasanlabs/fileupload/attacks/rce/PathTraversal.java index ce5d7c2..e28636a 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/impl/PathTraversal.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/PathTraversal.java @@ -11,7 +11,7 @@ * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ -package org.sasanlabs.fileupload.attacks.impl; +package org.sasanlabs.fileupload.attacks.rce; /** @author KSASAN preetkaran20@gmail.com */ public class PathTraversal /*implements AttackVector*/ { diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/impl/ImageBasedJSPRemoteCodeExecution.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageBasedJSPRemoteCodeExecution.java similarity index 97% rename from src/main/java/org/sasanlabs/fileupload/attacks/impl/ImageBasedJSPRemoteCodeExecution.java rename to src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageBasedJSPRemoteCodeExecution.java index 55b0fed..41047e6 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/impl/ImageBasedJSPRemoteCodeExecution.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageBasedJSPRemoteCodeExecution.java @@ -11,7 +11,7 @@ * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ -package org.sasanlabs.fileupload.attacks.impl; +package org.sasanlabs.fileupload.attacks.rce.jsp; import static org.sasanlabs.fileupload.Constants.NULL_BYTE_CHARACTER; @@ -25,9 +25,9 @@ import org.sasanlabs.fileupload.Constants; import org.sasanlabs.fileupload.attacks.AttackVector; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; -import org.sasanlabs.fileupload.attacks.FileUploadException; import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; import org.sasanlabs.fileupload.attacks.beans.FileParameter; +import org.sasanlabs.fileupload.exception.FileUploadException; import org.sasanlabs.fileupload.matcher.impl.ContainsExpectedValueMatcher; /** @author preetkaran20@gmail.com KSASAN */ diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPRemoteCodeExecution.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/PlainOldJSPRemoteCodeExecution.java similarity index 97% rename from src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPRemoteCodeExecution.java rename to src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/PlainOldJSPRemoteCodeExecution.java index 429b966..081b18f 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPRemoteCodeExecution.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/PlainOldJSPRemoteCodeExecution.java @@ -11,7 +11,7 @@ * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ -package org.sasanlabs.fileupload.attacks.impl; +package org.sasanlabs.fileupload.attacks.rce.jsp; import static org.sasanlabs.fileupload.Constants.NULL_BYTE_CHARACTER; @@ -21,9 +21,9 @@ import org.sasanlabs.fileupload.Constants; import org.sasanlabs.fileupload.attacks.AttackVector; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; -import org.sasanlabs.fileupload.attacks.FileUploadException; import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; import org.sasanlabs.fileupload.attacks.beans.FileParameter; +import org.sasanlabs.fileupload.exception.FileUploadException; import org.sasanlabs.fileupload.matcher.ContentMatcher; import org.sasanlabs.fileupload.matcher.impl.MD5HashResponseMatcher; diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPXRemoteCodeExecution.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/PlainOldJSPXRemoteCodeExecution.java similarity index 97% rename from src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPXRemoteCodeExecution.java rename to src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/PlainOldJSPXRemoteCodeExecution.java index 0b59a2f..bb7c4a7 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/impl/PlainOldJSPXRemoteCodeExecution.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/PlainOldJSPXRemoteCodeExecution.java @@ -11,7 +11,7 @@ * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ -package org.sasanlabs.fileupload.attacks.impl; +package org.sasanlabs.fileupload.attacks.rce.jsp; import static org.sasanlabs.fileupload.Constants.NULL_BYTE_CHARACTER; @@ -21,9 +21,9 @@ import org.sasanlabs.fileupload.Constants; import org.sasanlabs.fileupload.attacks.AttackVector; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; -import org.sasanlabs.fileupload.attacks.FileUploadException; import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; import org.sasanlabs.fileupload.attacks.beans.FileParameter; +import org.sasanlabs.fileupload.exception.FileUploadException; import org.sasanlabs.fileupload.matcher.ContentMatcher; import org.sasanlabs.fileupload.matcher.impl.MD5HashResponseMatcher; diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/impl/PhpRCE.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/php/PhpRCE.java similarity index 95% rename from src/main/java/org/sasanlabs/fileupload/attacks/impl/PhpRCE.java rename to src/main/java/org/sasanlabs/fileupload/attacks/rce/php/PhpRCE.java index 94ea46e..273a959 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/impl/PhpRCE.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/php/PhpRCE.java @@ -11,7 +11,7 @@ * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ -package org.sasanlabs.fileupload.attacks.impl; +package org.sasanlabs.fileupload.attacks.rce.php; /** * https://vulp3cula.gitbook.io/hackers-grimoire/exploitation/web-application/file-upload-bypass * diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java new file mode 100644 index 0000000..0645b60 --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java @@ -0,0 +1,362 @@ +/** + * Copyright 2020 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sasanlabs.fileupload.attacks.xss; + +import static org.sasanlabs.fileupload.Constants.NULL_BYTE_CHARACTER; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import org.parosproxy.paros.core.scanner.Plugin.AttackStrength; +import org.parosproxy.paros.network.HttpMessage; +import org.sasanlabs.fileupload.Constants; +import org.sasanlabs.fileupload.attacks.AttackVector; +import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; +import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; +import org.sasanlabs.fileupload.attacks.beans.FileParameter; +import org.sasanlabs.fileupload.exception.FileUploadException; +import org.sasanlabs.fileupload.matcher.ContentMatcher; +import org.sasanlabs.fileupload.matcher.impl.MD5HashResponseMatcher; + +/** + * {@code HtmlFileUpload} attack vector will upload {@code html}, {@code htm}, {@code xhtml} etc + * schemes in order to evaluate whether the application is vulnerable to {@code XSS} vulnerability. + *
+ * General logic is if Application is allowing to upload {@code html} file and while downloading the + * same file it is shown {@code inline} by the browser which is controlled by {@code + * Content-Disposition} header then it is vulnerable to Stored XSS. + * + * @author preetkaran20@gmail.com KSASAN + */ +public class HtmlFileUpload implements AttackVector { + + private static final String XSS_UPLOADED_FILE_BASE_NAME = "HtmlFileUpload_"; + private static final String XSS_PAYLOAD_HTML_FILE = + "Testing XSS"; + + private static final ContentMatcher CONTENT_MATCHER = + new MD5HashResponseMatcher( + httpMsg -> isContentDispositionInline(httpMsg), XSS_PAYLOAD_HTML_FILE); + + private static boolean isContentDispositionInline(HttpMessage preflightMsg) { + String headerValue = preflightMsg.getResponseHeader().getHeader("Content-Disposition"); + if (headerValue == null + || headerValue.trim().equals(Constants.EMPTY_STRING) + || headerValue.equals("inline")) { + return true; + } + return false; + } + + // Extended list for breaking black-listing strategy. + private static final List FILE_PARAMETERS_EXTENDED = + Arrays.asList( + new FileParameter("Htm", Constants.EMPTY_STRING), + new FileParameter("hTM", Constants.EMPTY_STRING), + new FileParameter("HTM", Constants.EMPTY_STRING), + new FileParameter("Html", Constants.EMPTY_STRING), + new FileParameter("HtMl", Constants.EMPTY_STRING), + new FileParameter("HTMl", Constants.EMPTY_STRING), + new FileParameter("HTML", Constants.EMPTY_STRING), + new FileParameter("Xhtml", Constants.EMPTY_STRING), + new FileParameter("xHTml", Constants.EMPTY_STRING), + new FileParameter("xhTML", Constants.EMPTY_STRING), + new FileParameter("xHTML", Constants.EMPTY_STRING), + new FileParameter("XHTML", Constants.EMPTY_STRING), + new FileParameter("Htm", "text/html"), + new FileParameter("hTM", "text/html"), + new FileParameter("HTM", "text/html"), + new FileParameter("Html", "text/html"), + new FileParameter("HtMl", "text/html"), + new FileParameter("HTMl", "text/html"), + new FileParameter("HTML", "text/html"), + new FileParameter("Xhtml", "text/html"), + new FileParameter("xHTml", "text/html"), + new FileParameter("xhTML", "text/html"), + new FileParameter("xHTML", "text/html"), + new FileParameter("XHTML", "text/html"), + new FileParameter("Htm", "text/plain"), + new FileParameter("hTM", "text/plain"), + new FileParameter("HTM", "text/plain"), + new FileParameter("Html", "text/plain"), + new FileParameter("HtMl", "text/plain"), + new FileParameter("HTMl", "text/plain"), + new FileParameter("HTML", "text/plain"), + new FileParameter("Xhtml", "text/plain"), + new FileParameter("xHTml", "text/plain"), + new FileParameter("xhTML", "text/plain"), + new FileParameter("xHTML", "text/plain"), + new FileParameter("XHTML", "text/plain"), + new FileParameter( + "Htm", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "hTM", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "HTM", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "Html", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "HtMl", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "HTMl", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "HTML", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "Xhtml", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "xHTml", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "xhTML", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "xHTML", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "XHTML", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "Htm", "text/plain", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "hTM", "text/plain", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "HTM", "text/plain", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "Html", "text/plain", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "HtMl", "text/plain", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "HTMl", "text/plain", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "HTML", "text/plain", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "Xhtml", + "text/plain", + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "xHTml", + "text/plain", + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "xhTML", + "text/plain", + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "xHTML", + "text/plain", + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "XHTML", + "text/plain", + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "Htm" + NULL_BYTE_CHARACTER, + "text/plain", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "hTM" + NULL_BYTE_CHARACTER, + "text/plain", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "HTM" + NULL_BYTE_CHARACTER, + "text/plain", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "Html" + NULL_BYTE_CHARACTER, + "text/plain", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "HtMl" + NULL_BYTE_CHARACTER, + "text/plain", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "HTMl" + NULL_BYTE_CHARACTER, + "text/plain", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "HTML" + NULL_BYTE_CHARACTER, + "text/plain", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "Xhtml" + NULL_BYTE_CHARACTER, + "text/plain", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "xHTml" + NULL_BYTE_CHARACTER, + "text/plain", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "xhTML" + NULL_BYTE_CHARACTER, + "text/plain", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "xHTML" + NULL_BYTE_CHARACTER, + "text/plain", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "XHTML" + NULL_BYTE_CHARACTER, + "text/plain", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "Htm" + NULL_BYTE_CHARACTER, + "text/html", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "hTM" + NULL_BYTE_CHARACTER, + "text/html", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "HTM" + NULL_BYTE_CHARACTER, + "text/html", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "Html" + NULL_BYTE_CHARACTER, + "text/html", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "HtMl" + NULL_BYTE_CHARACTER, + "text/html", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "HTMl" + NULL_BYTE_CHARACTER, + "text/html", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "HTML" + NULL_BYTE_CHARACTER, + "text/html", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "Xhtml" + NULL_BYTE_CHARACTER, + "text/html", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "xHTml" + NULL_BYTE_CHARACTER, + "text/html", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "xhTML" + NULL_BYTE_CHARACTER, + "text/html", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "xHTML" + NULL_BYTE_CHARACTER, + "text/html", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "XHTML" + NULL_BYTE_CHARACTER, + "text/html", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION)); + + private static final List FILE_PARAMETERS_DEFAULT = + Arrays.asList( + new FileParameter("htm", Constants.EMPTY_STRING), + new FileParameter("html", Constants.EMPTY_STRING), + new FileParameter("xhtml", Constants.EMPTY_STRING), + new FileParameter("htm", "text/html"), + new FileParameter("html", "text/html"), + new FileParameter("xhtml", "text/html"), + new FileParameter("htm", "text/plain"), + new FileParameter("html", "text/plain"), + new FileParameter("xhtml", "text/plain"), + new FileParameter( + "htm", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "html", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "xhtml", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "htm" + NULL_BYTE_CHARACTER, + "text/html", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "html" + NULL_BYTE_CHARACTER, + "text/html", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "xhtml" + NULL_BYTE_CHARACTER, + "text/html", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "htm" + NULL_BYTE_CHARACTER, + "text/plain", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "html" + NULL_BYTE_CHARACTER, + "text/plain", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "xhtml" + NULL_BYTE_CHARACTER, + "text/plain", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION)); + + /** + * @throws FileUploadException + * @throws IOException + */ + @Override + public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) + throws FileUploadException { + boolean result = false; + try { + result = + this.genericAttackExecutor( + fileUploadAttackExecutor, + CONTENT_MATCHER, + XSS_PAYLOAD_HTML_FILE, + XSS_UPLOADED_FILE_BASE_NAME, + FILE_PARAMETERS_DEFAULT); + if (result) { + fileUploadAttackExecutor + .getFileUploadScanRule() + .raiseAlert( + 1, + 1, + "", + "", + "", + "", + "", + "", + "", + fileUploadAttackExecutor.getOriginalHttpMessage()); + } else { + if (fileUploadAttackExecutor + .getFileUploadScanRule() + .getAttackStrength() + .equals(AttackStrength.INSANE)) { + result = + this.genericAttackExecutor( + fileUploadAttackExecutor, + CONTENT_MATCHER, + XSS_PAYLOAD_HTML_FILE, + XSS_UPLOADED_FILE_BASE_NAME, + FILE_PARAMETERS_EXTENDED); + if (result) { + fileUploadAttackExecutor + .getFileUploadScanRule() + .raiseAlert( + 1, + 1, + "", + "", + "", + "", + "", + "", + "", + fileUploadAttackExecutor.getOriginalHttpMessage()); + } + } + } + } catch (IOException e) { + throw new FileUploadException(e); + } + return result; + } +} diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadException.java b/src/main/java/org/sasanlabs/fileupload/exception/FileUploadException.java similarity index 96% rename from src/main/java/org/sasanlabs/fileupload/attacks/FileUploadException.java rename to src/main/java/org/sasanlabs/fileupload/exception/FileUploadException.java index 2c42239..642a90d 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadException.java +++ b/src/main/java/org/sasanlabs/fileupload/exception/FileUploadException.java @@ -11,7 +11,7 @@ * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ -package org.sasanlabs.fileupload.attacks; +package org.sasanlabs.fileupload.exception; /** * {@code FileUploadException} is an exception class for FileUpload Scan Rule. It wraps around diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/ConsumerWithException.java b/src/main/java/org/sasanlabs/fileupload/function/ConsumerWithException.java similarity index 94% rename from src/main/java/org/sasanlabs/fileupload/attacks/ConsumerWithException.java rename to src/main/java/org/sasanlabs/fileupload/function/ConsumerWithException.java index b062eec..df9e831 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/ConsumerWithException.java +++ b/src/main/java/org/sasanlabs/fileupload/function/ConsumerWithException.java @@ -11,7 +11,7 @@ * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ -package org.sasanlabs.fileupload.attacks; +package org.sasanlabs.fileupload.function; /** @author preetkaran20@gmail.com KSASAN */ @FunctionalInterface diff --git a/src/main/java/org/sasanlabs/fileupload/configuration/URILocator.java b/src/main/java/org/sasanlabs/fileupload/locator/URILocator.java similarity index 87% rename from src/main/java/org/sasanlabs/fileupload/configuration/URILocator.java rename to src/main/java/org/sasanlabs/fileupload/locator/URILocator.java index 8517f39..b8af491 100644 --- a/src/main/java/org/sasanlabs/fileupload/configuration/URILocator.java +++ b/src/main/java/org/sasanlabs/fileupload/locator/URILocator.java @@ -11,13 +11,13 @@ * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ -package org.sasanlabs.fileupload.configuration; +package org.sasanlabs.fileupload.locator; import java.io.IOException; import org.apache.commons.httpclient.URI; import org.parosproxy.paros.network.HttpMessage; -import org.sasanlabs.fileupload.attacks.ConsumerWithException; -import org.sasanlabs.fileupload.attacks.FileUploadException; +import org.sasanlabs.fileupload.exception.FileUploadException; +import org.sasanlabs.fileupload.function.ConsumerWithException; /** * {@code URILocator} class is used to find the URL either by parsing the {@code HttpMessage} or diff --git a/src/main/java/org/sasanlabs/fileupload/configuration/URILocatorImpl.java b/src/main/java/org/sasanlabs/fileupload/locator/URILocatorImpl.java similarity index 96% rename from src/main/java/org/sasanlabs/fileupload/configuration/URILocatorImpl.java rename to src/main/java/org/sasanlabs/fileupload/locator/URILocatorImpl.java index 025450e..974e393 100644 --- a/src/main/java/org/sasanlabs/fileupload/configuration/URILocatorImpl.java +++ b/src/main/java/org/sasanlabs/fileupload/locator/URILocatorImpl.java @@ -11,7 +11,7 @@ * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ -package org.sasanlabs.fileupload.configuration; +package org.sasanlabs.fileupload.locator; import java.io.IOException; import java.util.HashMap; @@ -23,8 +23,9 @@ import org.apache.log4j.Logger; import org.parosproxy.paros.network.HttpMessage; import org.sasanlabs.fileupload.Constants; -import org.sasanlabs.fileupload.attacks.ConsumerWithException; -import org.sasanlabs.fileupload.attacks.FileUploadException; +import org.sasanlabs.fileupload.configuration.FileUploadConfiguration; +import org.sasanlabs.fileupload.exception.FileUploadException; +import org.sasanlabs.fileupload.function.ConsumerWithException; /** @author preetkaran20@gmail.com KSASAN */ public class URILocatorImpl implements URILocator { diff --git a/src/main/java/org/sasanlabs/fileupload/redownloader/Redownloader.java b/src/main/java/org/sasanlabs/fileupload/redownloader/Redownloader.java deleted file mode 100644 index 68be8c5..0000000 --- a/src/main/java/org/sasanlabs/fileupload/redownloader/Redownloader.java +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Copyright 2020 SasanLabs - * - *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of the License at - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sasanlabs.fileupload.redownloader; - -/** @author KSASAN preetkaran20@gmail.com */ -public interface Redownloader {} diff --git a/src/main/resources/org/sasanlabs/attackvectors/files/jspx_payload.jspx b/src/main/resources/org/sasanlabs/attackvectors/files/jspx_payload.jspx deleted file mode 100644 index 15829d7..0000000 --- a/src/main/resources/org/sasanlabs/attackvectors/files/jspx_payload.jspx +++ /dev/null @@ -1,7 +0,0 @@ - - - - out.print("PlainOldJSPXRemoteCodeExecution_"); - out.print("SasanLabs_ZAP_Identifier"); - - \ No newline at end of file diff --git a/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties b/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties index 490faf1..811860a 100755 --- a/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties +++ b/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties @@ -1,3 +1,4 @@ +# Options Panel fileupload.settings.title=File Upload fileupload.settings.button.reset=Reset fileupload.settings.urilocator.title=URI Locator @@ -8,3 +9,9 @@ fileupload.settings.urilocator.dynamiclocation.title=Dynamic Location Configurat fileupload.settings.urilocator.dynamiclocation.uriregex=URI Regex fileupload.settings.urilocator.dynamiclocation.startidentifer=Start Identifier fileupload.settings.urilocator.dynamiclocation.endidentifer=End Identifier + +# FileUpload Scan Rule +fileupload.scanrule.name=File Upload +fileupload.scanrule.description=File Upload scan rule is used to scan the vulnerabilities in the File Upload functionality of web applications. +fileupload.scanrule.refs= +fileupload.scanrule.soln= \ No newline at end of file From 35cd91c7874bac60df9e71935441714290582d9d Mon Sep 17 00:00:00 2001 From: karan preet singh sasan Date: Mon, 28 Dec 2020 01:36:52 +0530 Subject: [PATCH 12/53] More modifications --- .../org/sasanlabs/fileupload/Constants.java | 12 + .../fileupload/FileUploadScanRule.java | 9 + .../fileupload/attacks/AttackVector.java | 11 +- .../attacks/FileUploadAttackExecutor.java | 8 +- .../EicarAntivirusTestFileUpload.java | 16 + .../htaccess/ApachehtaccessFileUpload.java | 16 + .../attacks/beans/FileParameter.java | 20 +- .../jsp/ImageBasedJSPRemoteCodeExecution.java | 9 +- .../jsp/PlainOldJSPRemoteCodeExecution.java | 9 +- .../jsp/PlainOldJSPXRemoteCodeExecution.java | 9 +- .../attacks/xss/HtmlFileUpload.java | 273 ++++++------------ .../fileupload/attacks/xss/SVGFileUpload.java | 189 ++++++++++++ .../attackvectors/files/svg_xss_payload.svg | 5 + 13 files changed, 366 insertions(+), 220 deletions(-) create mode 100644 src/main/java/org/sasanlabs/fileupload/attacks/apache/htaccess/ApachehtaccessFileUpload.java create mode 100644 src/main/java/org/sasanlabs/fileupload/attacks/xss/SVGFileUpload.java create mode 100644 src/main/resources/org/sasanlabs/fileupload/attackvectors/files/svg_xss_payload.svg diff --git a/src/main/java/org/sasanlabs/fileupload/Constants.java b/src/main/java/org/sasanlabs/fileupload/Constants.java index 096dab2..dcc4db8 100644 --- a/src/main/java/org/sasanlabs/fileupload/Constants.java +++ b/src/main/java/org/sasanlabs/fileupload/Constants.java @@ -13,6 +13,8 @@ */ package org.sasanlabs.fileupload; +import org.parosproxy.paros.network.HttpMessage; + /** * Contains the String constants or other utility constants used by the File Upload Addon. * @@ -25,4 +27,14 @@ public interface Constants { String NULL_BYTE_CHARACTER = String.valueOf((char) 0); String HTTP_SCHEME = "http://"; String HTTP_SECURED_SCHEME = "https://"; + + static boolean isContentDispositionInline(HttpMessage preflightMsg) { + String headerValue = preflightMsg.getResponseHeader().getHeader("Content-Disposition"); + if (headerValue == null + || headerValue.trim().equals(Constants.EMPTY_STRING) + || headerValue.equals("inline")) { + return true; + } + return false; + } } diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java index ce13ace..4f02ff7 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java @@ -60,6 +60,15 @@ public void init() { } } + @Override + public boolean isStop() { + return super.isStop() || (this.maxRequestCount.get() <= 0); + } + + public void decreaseRequestCount() { + this.maxRequestCount.getAndDecrement(); + } + /* * Need to check what to include do we need to include XXE/XSS/Path Traversal in * this addon or we need to correct those. Persistent XXS/XXE/PathTraversal diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java index 5e88444..c68b3ae 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java @@ -68,13 +68,20 @@ default boolean genericAttackExecutor( HttpMessage originalMsg = fileUploadAttackExecutor.getOriginalHttpMessage(); FileUploadScanRule fileUploadScanRule = fileUploadAttackExecutor.getFileUploadScanRule(); String originalFileName = null; + String originalContentType = null; for (NameValuePair nameValuePair : nameValuePairs) { if (nameValuePair.getType() == NameValuePair.TYPE_MULTIPART_DATA_FILE_NAME) { originalFileName = nameValuePair.getValue(); - break; + } else if (nameValuePair.getType() + == NameValuePair.TYPE_MULTIPART_DATA_FILE_CONTENTTYPE) { + originalContentType = nameValuePair.getValue(); } } for (FileParameter fileParameter : fileParameters) { + if (fileUploadAttackExecutor.getFileUploadScanRule().isStop()) { + return false; + } + fileUploadAttackExecutor.getFileUploadScanRule().decreaseRequestCount(); HttpMessage newMsg = originalMsg.cloneRequest(); for (int i = 0; i < nameValuePairs.size(); i++) { NameValuePair nameValuePair = nameValuePairs.get(i); @@ -94,7 +101,7 @@ default boolean genericAttackExecutor( newMsg, nameValuePair, nameValuePair.getName(), - fileParameter.getContentType()); + fileParameter.getContentType(originalContentType)); } else { continue; } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java b/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java index 0deb812..75894e2 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java @@ -54,8 +54,12 @@ public FileUploadAttackExecutor( public boolean executeAttack() throws FileUploadException { for (AttackVector attackVector : attackVectors) { - if (attackVector.execute(this)) { - return true; + if (this.fileUploadScanRule.isStop()) { + return false; + } else { + if (attackVector.execute(this)) { + return true; + } } } return false; diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java index 38c2861..6bc2e36 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java @@ -17,8 +17,24 @@ import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; import org.sasanlabs.fileupload.exception.FileUploadException; +/** + * {@code EicarAntivirusTestFileUpload} attack vector is used to check the if antivirus is present + * and working properly by upload the Eicar file. General idea is to upload the Eicar Test file and + * if we are able to download it again then that means there are chances that Antivirus is either + * not present or not working properly. + * + *

For more information about Eicar file please visit Eicar File Wiki link + * + * @author KSASAN preetkaran20@gmail.com + */ public class EicarAntivirusTestFileUpload implements AttackVector { + private static final String EICAR_FILE_CONTENT = + "WDVPIVAlQEFQWzRcUFpYNTQ" + + "oUF4pN0NDKTd9JEVJQ0FSLVNUQU5EQVJELUFOVEl" + + "WSVJVUy1URVNULUZJTEUhJEgrSCo="; + @Override public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) throws FileUploadException { diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/apache/htaccess/ApachehtaccessFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/apache/htaccess/ApachehtaccessFileUpload.java new file mode 100644 index 0000000..349e835 --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/attacks/apache/htaccess/ApachehtaccessFileUpload.java @@ -0,0 +1,16 @@ +/** + * Copyright 2020 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sasanlabs.fileupload.attacks.apache.htaccess; + +public class ApachehtaccessFileUpload {} diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java index 787f81b..ce02ad3 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java @@ -30,24 +30,30 @@ public class FileParameter { private FileExtensionOperation fileExtensionOperation = FileExtensionOperation.ONLY_PROVIDED_EXTENSION; - public FileParameter(String extension, String contentType) { + public FileParameter(String extension) { super(); this.baseFileName = String.valueOf(new Random(new Date().getTime()).nextLong()); this.extension = extension; + } + + public FileParameter(String extension, String contentType) { + this(extension); this.contentType = contentType; } + public FileParameter(String extension, FileExtensionOperation fileExtensionOperation) { + this(extension); + this.fileExtensionOperation = fileExtensionOperation; + } + public FileParameter( String extension, String contentType, FileExtensionOperation fileExtensionOperation) { - super(); - this.baseFileName = String.valueOf(new Random(new Date().getTime()).nextLong()); - this.extension = extension; + this(extension, fileExtensionOperation); this.contentType = contentType; - this.fileExtensionOperation = fileExtensionOperation; } - public String getContentType() { - return contentType; + public String getContentType(String originalContentType) { + return contentType == null ? originalContentType : this.contentType; } public String getFileName(String originalFileName, String newBaseFileName) diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageBasedJSPRemoteCodeExecution.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageBasedJSPRemoteCodeExecution.java index 41047e6..78a269e 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageBasedJSPRemoteCodeExecution.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageBasedJSPRemoteCodeExecution.java @@ -22,7 +22,6 @@ import java.util.Base64; import java.util.List; import org.parosproxy.paros.network.HttpMessage; -import org.sasanlabs.fileupload.Constants; import org.sasanlabs.fileupload.attacks.AttackVector; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; @@ -41,19 +40,15 @@ public class ImageBasedJSPRemoteCodeExecution implements AttackVector { private static final List FILE_PARAMETERS = Arrays.asList( - new FileParameter("jsp", Constants.EMPTY_STRING), + new FileParameter("jsp"), new FileParameter("jsp", "application/x-jsp"), - new FileParameter( - "jsp", - Constants.EMPTY_STRING, - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter("jsp", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), new FileParameter( "jsp", "application/x-jsp", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), new FileParameter( "jsp" + NULL_BYTE_CHARACTER, - Constants.EMPTY_STRING, FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), new FileParameter( "jsp" + NULL_BYTE_CHARACTER, diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/PlainOldJSPRemoteCodeExecution.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/PlainOldJSPRemoteCodeExecution.java index 081b18f..aecb08c 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/PlainOldJSPRemoteCodeExecution.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/PlainOldJSPRemoteCodeExecution.java @@ -18,7 +18,6 @@ import java.io.IOException; import java.util.Arrays; import java.util.List; -import org.sasanlabs.fileupload.Constants; import org.sasanlabs.fileupload.attacks.AttackVector; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; @@ -42,19 +41,15 @@ public class PlainOldJSPRemoteCodeExecution implements AttackVector { private static final List FILE_PARAMETERS = Arrays.asList( - new FileParameter("jsp", Constants.EMPTY_STRING), + new FileParameter("jsp"), new FileParameter("jsp", "application/x-jsp"), - new FileParameter( - "jsp", - Constants.EMPTY_STRING, - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter("jsp", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), new FileParameter( "jsp", "application/x-jsp", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), new FileParameter( "jsp" + NULL_BYTE_CHARACTER, - Constants.EMPTY_STRING, FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), new FileParameter( "jsp" + NULL_BYTE_CHARACTER, diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/PlainOldJSPXRemoteCodeExecution.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/PlainOldJSPXRemoteCodeExecution.java index bb7c4a7..ffa735e 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/PlainOldJSPXRemoteCodeExecution.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/PlainOldJSPXRemoteCodeExecution.java @@ -18,7 +18,6 @@ import java.io.IOException; import java.util.Arrays; import java.util.List; -import org.sasanlabs.fileupload.Constants; import org.sasanlabs.fileupload.attacks.AttackVector; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; @@ -49,19 +48,15 @@ public class PlainOldJSPXRemoteCodeExecution implements AttackVector { // text/x-jsp private static final List FILE_PARAMETERS = Arrays.asList( - new FileParameter("jspx", Constants.EMPTY_STRING), + new FileParameter("jspx"), new FileParameter("jspx", "application/x-jsp"), - new FileParameter( - "jspx", - Constants.EMPTY_STRING, - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter("jspx", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), new FileParameter( "jspx", "application/x-jsp", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), new FileParameter( "jspx" + NULL_BYTE_CHARACTER, - Constants.EMPTY_STRING, FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), new FileParameter( "jspx" + NULL_BYTE_CHARACTER, diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java index 0645b60..815172d 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java @@ -19,7 +19,6 @@ import java.util.Arrays; import java.util.List; import org.parosproxy.paros.core.scanner.Plugin.AttackStrength; -import org.parosproxy.paros.network.HttpMessage; import org.sasanlabs.fileupload.Constants; import org.sasanlabs.fileupload.attacks.AttackVector; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; @@ -41,39 +40,36 @@ */ public class HtmlFileUpload implements AttackVector { - private static final String XSS_UPLOADED_FILE_BASE_NAME = "HtmlFileUpload_"; + private static final String XSS_UPLOADED_FILE_BASE_NAME = "HtmlFileUpload_XSS_"; private static final String XSS_PAYLOAD_HTML_FILE = "Testing XSS"; - private static final ContentMatcher CONTENT_MATCHER = + static final ContentMatcher CONTENT_MATCHER = new MD5HashResponseMatcher( - httpMsg -> isContentDispositionInline(httpMsg), XSS_PAYLOAD_HTML_FILE); - - private static boolean isContentDispositionInline(HttpMessage preflightMsg) { - String headerValue = preflightMsg.getResponseHeader().getHeader("Content-Disposition"); - if (headerValue == null - || headerValue.trim().equals(Constants.EMPTY_STRING) - || headerValue.equals("inline")) { - return true; - } - return false; - } + httpMsg -> Constants.isContentDispositionInline(httpMsg), + XSS_PAYLOAD_HTML_FILE); // Extended list for breaking black-listing strategy. private static final List FILE_PARAMETERS_EXTENDED = Arrays.asList( - new FileParameter("Htm", Constants.EMPTY_STRING), - new FileParameter("hTM", Constants.EMPTY_STRING), - new FileParameter("HTM", Constants.EMPTY_STRING), - new FileParameter("Html", Constants.EMPTY_STRING), - new FileParameter("HtMl", Constants.EMPTY_STRING), - new FileParameter("HTMl", Constants.EMPTY_STRING), - new FileParameter("HTML", Constants.EMPTY_STRING), - new FileParameter("Xhtml", Constants.EMPTY_STRING), - new FileParameter("xHTml", Constants.EMPTY_STRING), - new FileParameter("xhTML", Constants.EMPTY_STRING), - new FileParameter("xHTML", Constants.EMPTY_STRING), - new FileParameter("XHTML", Constants.EMPTY_STRING), + new FileParameter("Htm"), + new FileParameter("hTM"), + new FileParameter("HTM"), + new FileParameter("Html"), + new FileParameter("HtMl"), + new FileParameter("HTMl"), + new FileParameter("HTML"), + new FileParameter("Xhtml"), + new FileParameter("xHTml"), + new FileParameter("xhTML"), + new FileParameter("xHTML"), + new FileParameter("XHTML"), + new FileParameter("dHtml"), + new FileParameter("sHtml"), + new FileParameter("dHTml"), + new FileParameter("sHTml"), + new FileParameter("dHTML"), + new FileParameter("sHTML"), new FileParameter("Htm", "text/html"), new FileParameter("hTM", "text/html"), new FileParameter("HTM", "text/html"), @@ -86,6 +82,12 @@ private static boolean isContentDispositionInline(HttpMessage preflightMsg) { new FileParameter("xhTML", "text/html"), new FileParameter("xHTML", "text/html"), new FileParameter("XHTML", "text/html"), + new FileParameter("dHtml", "text/html"), + new FileParameter("sHtml", "text/html"), + new FileParameter("dHTml", "text/html"), + new FileParameter("sHTml", "text/html"), + new FileParameter("dHTML", "text/html"), + new FileParameter("sHTML", "text/html"), new FileParameter("Htm", "text/plain"), new FileParameter("hTM", "text/plain"), new FileParameter("HTM", "text/plain"), @@ -98,188 +100,60 @@ private static boolean isContentDispositionInline(HttpMessage preflightMsg) { new FileParameter("xhTML", "text/plain"), new FileParameter("xHTML", "text/plain"), new FileParameter("XHTML", "text/plain"), + new FileParameter("dHtml", "text/plain"), + new FileParameter("sHtml", "text/plain"), + new FileParameter("dHTml", "text/plain"), + new FileParameter("sHTml", "text/plain"), + new FileParameter("dHTML", "text/plain"), + new FileParameter("sHTML", "text/plain"), new FileParameter( "Htm", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "hTM", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "HTM", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "Html", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "HtMl", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "HTMl", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), new FileParameter( "HTML", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), new FileParameter( "Xhtml", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "xHTml", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "xhTML", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "xHTML", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), new FileParameter( "XHTML", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "Htm", "text/plain", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "hTM", "text/plain", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "HTM", "text/plain", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "Html", "text/plain", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "HtMl", "text/plain", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "HTMl", "text/plain", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "HTML", "text/plain", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "Xhtml", - "text/plain", - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "xHTml", - "text/plain", - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "xhTML", - "text/plain", - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "xHTML", - "text/plain", - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "XHTML", - "text/plain", - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "Htm" + NULL_BYTE_CHARACTER, - "text/plain", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "hTM" + NULL_BYTE_CHARACTER, - "text/plain", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "HTM" + NULL_BYTE_CHARACTER, - "text/plain", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "Html" + NULL_BYTE_CHARACTER, - "text/plain", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "HtMl" + NULL_BYTE_CHARACTER, - "text/plain", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "HTMl" + NULL_BYTE_CHARACTER, - "text/plain", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "HTML" + NULL_BYTE_CHARACTER, - "text/plain", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "Xhtml" + NULL_BYTE_CHARACTER, - "text/plain", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "xHTml" + NULL_BYTE_CHARACTER, - "text/plain", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "xhTML" + NULL_BYTE_CHARACTER, - "text/plain", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "xHTML" + NULL_BYTE_CHARACTER, - "text/plain", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "XHTML" + NULL_BYTE_CHARACTER, - "text/plain", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "Htm" + NULL_BYTE_CHARACTER, - "text/html", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "hTM" + NULL_BYTE_CHARACTER, - "text/html", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "HTM" + NULL_BYTE_CHARACTER, - "text/html", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "Html" + NULL_BYTE_CHARACTER, - "text/html", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "HtMl" + NULL_BYTE_CHARACTER, - "text/html", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "HTMl" + NULL_BYTE_CHARACTER, - "text/html", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "HTML" + NULL_BYTE_CHARACTER, - "text/html", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "Xhtml" + NULL_BYTE_CHARACTER, - "text/html", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "xHTml" + NULL_BYTE_CHARACTER, - "text/html", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "xhTML" + NULL_BYTE_CHARACTER, - "text/html", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "xHTML" + NULL_BYTE_CHARACTER, - "text/html", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "XHTML" + NULL_BYTE_CHARACTER, - "text/html", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION)); + new FileParameter("Htm", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter("HTML", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter("Xhtml", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter("XHTML", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION)); private static final List FILE_PARAMETERS_DEFAULT = Arrays.asList( - new FileParameter("htm", Constants.EMPTY_STRING), - new FileParameter("html", Constants.EMPTY_STRING), - new FileParameter("xhtml", Constants.EMPTY_STRING), + new FileParameter("htm"), + new FileParameter("html"), + new FileParameter("xhtml"), + /** + * Server Parsed Html for server side includes + * https://stackoverflow.com/questions/519619/what-is-the-purpose-and-uniqueness-shtml + */ + new FileParameter("shtml"), + new FileParameter("dhtml"), new FileParameter("htm", "text/html"), new FileParameter("html", "text/html"), new FileParameter("xhtml", "text/html"), + new FileParameter("shtml", "text/html"), + new FileParameter("dhtml", "text/html"), new FileParameter("htm", "text/plain"), new FileParameter("html", "text/plain"), new FileParameter("xhtml", "text/plain"), + new FileParameter("shtml", "text/plain"), + new FileParameter("dhtml", "text/plain"), new FileParameter( "htm", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), new FileParameter( "html", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), new FileParameter( "xhtml", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter("htm", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter("html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter("xhtml", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), new FileParameter( "htm" + NULL_BYTE_CHARACTER, - "text/html", FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), new FileParameter( - "html" + NULL_BYTE_CHARACTER, - "text/html", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "xhtml" + NULL_BYTE_CHARACTER, + "htm" + NULL_BYTE_CHARACTER, "text/html", FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), new FileParameter( @@ -287,13 +161,36 @@ private static boolean isContentDispositionInline(HttpMessage preflightMsg) { "text/plain", FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), new FileParameter( - "html" + NULL_BYTE_CHARACTER, - "text/plain", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "xhtml" + NULL_BYTE_CHARACTER, - "text/plain", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION)); + "htm" + NULL_BYTE_CHARACTER, + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + + /** + * My thought is that if server is vulnerable to Null Byte then it is sure that + * "htm" only will work and there is no need to verify other extensions * + */ + /* + new FileParameter( + "html" + NULL_BYTE_CHARACTER, + "text/html", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "xhtml" + NULL_BYTE_CHARACTER, + "text/html", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "htm" + NULL_BYTE_CHARACTER, + "text/plain", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "html" + NULL_BYTE_CHARACTER, + "text/plain", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "xhtml" + NULL_BYTE_CHARACTER, + "text/plain", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + */ + ); /** * @throws FileUploadException diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/xss/SVGFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/xss/SVGFileUpload.java new file mode 100644 index 0000000..6b89cbc --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/attacks/xss/SVGFileUpload.java @@ -0,0 +1,189 @@ +/** + * Copyright 2020 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sasanlabs.fileupload.attacks.xss; + +import static org.sasanlabs.fileupload.Constants.NULL_BYTE_CHARACTER; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import org.parosproxy.paros.core.scanner.Plugin.AttackStrength; +import org.sasanlabs.fileupload.attacks.AttackVector; +import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; +import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; +import org.sasanlabs.fileupload.attacks.beans.FileParameter; +import org.sasanlabs.fileupload.exception.FileUploadException; + +/** + * {@code SVGFileUpload} attack vector will upload {@code svg} and its various different extension + * schemes in order to evaluate whether the application is vulnerable to {@code XSS} vulnerability. + *
+ * General logic is if Application is allowing to upload {@code svg} file and while downloading the + * same file it is shown {@code inline} by the browser which is controlled by {@code + * Content-Disposition} header then it is vulnerable to Stored XSS. + * + * @author preetkaran20@gmail.com KSASAN + */ +public class SVGFileUpload implements AttackVector { + + private static final String XSS_UPLOADED_FILE_BASE_NAME = "SVGFileUpload_XSS_"; + private static final String XSS_PAYLOAD_SVG_FILE = + "\n" + + "\n" + + ""; + + // Extended list for breaking black-listing strategy. + private static final List FILE_PARAMETERS_EXTENDED = + Arrays.asList( + new FileParameter("Svg"), + new FileParameter("SvG"), + new FileParameter("SVG"), + new FileParameter("Svgz"), + new FileParameter("SvGz"), + new FileParameter("SVGZ"), + new FileParameter("xML"), + new FileParameter("Xml"), + new FileParameter("XML"), + new FileParameter("Svg", "image/svg+xml"), + new FileParameter("SvG", "image/svg+xml"), + new FileParameter("SVG", "image/svg+xml"), + new FileParameter("Svgz", "image/svg+xml"), + new FileParameter("SvGz", "image/svg+xml"), + new FileParameter("SVGZ", "image/svg+xml"), + new FileParameter("xML", "text/xml"), + new FileParameter("Xml", "text/xml"), + new FileParameter("XML", "text/xml"), + new FileParameter( + "Svg", + "image/svg+xml", + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter("Svg", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "SVG", + "image/svg+xml", + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter("SVG", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "Svgz", + "image/svg+xml", + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter("Svgz", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "SVGZ", + "image/svg+xml", + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter("SVGZ", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "Xml", "text/xml", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter("Xml", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "XML", "text/xml", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter("XML", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION)); + + /** + * Extensions working with SVG payload for XSS: svg,html,xml,htm,xhtml,Null byte + * (assumption),shtml,svgz,dhtml Extensions not working: png,gif,swf,pdf,mvg,xbm,ssi,jpeg + * + *

Didn't pick html and its related variant extensions because those attack vectors will be + * covered under {@link HtmlFileUpload}. + */ + private static final List FILE_PARAMETERS_DEFAULT = + Arrays.asList( + new FileParameter("svg"), + // if html works then html file upload will only work + // new FileParameter("htm"), + // new FileParameter("html"), + new FileParameter("xml"), + new FileParameter("svgz"), + new FileParameter("svg", "image/svg+xml"), + new FileParameter("xml", "text/xml"), + new FileParameter("svgz", "image/svg+xml"), + new FileParameter("svg", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter("xml", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter("svgz", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "svg" + NULL_BYTE_CHARACTER, + "image/svg+xml", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "svg" + NULL_BYTE_CHARACTER, + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION)); + + /** + * @throws FileUploadException + * @throws IOException + */ + @Override + public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) + throws FileUploadException { + boolean result = false; + try { + result = + this.genericAttackExecutor( + fileUploadAttackExecutor, + HtmlFileUpload.CONTENT_MATCHER, + XSS_PAYLOAD_SVG_FILE, + XSS_UPLOADED_FILE_BASE_NAME, + FILE_PARAMETERS_DEFAULT); + if (result) { + fileUploadAttackExecutor + .getFileUploadScanRule() + .raiseAlert( + 1, + 1, + "", + "", + "", + "", + "", + "", + "", + fileUploadAttackExecutor.getOriginalHttpMessage()); + } else { + if (fileUploadAttackExecutor + .getFileUploadScanRule() + .getAttackStrength() + .equals(AttackStrength.INSANE)) { + result = + this.genericAttackExecutor( + fileUploadAttackExecutor, + HtmlFileUpload.CONTENT_MATCHER, + XSS_PAYLOAD_SVG_FILE, + XSS_UPLOADED_FILE_BASE_NAME, + FILE_PARAMETERS_EXTENDED); + if (result) { + fileUploadAttackExecutor + .getFileUploadScanRule() + .raiseAlert( + 1, + 1, + "", + "", + "", + "", + "", + "", + "", + fileUploadAttackExecutor.getOriginalHttpMessage()); + } + } + } + } catch (IOException e) { + throw new FileUploadException(e); + } + return result; + } +} diff --git a/src/main/resources/org/sasanlabs/fileupload/attackvectors/files/svg_xss_payload.svg b/src/main/resources/org/sasanlabs/fileupload/attackvectors/files/svg_xss_payload.svg new file mode 100644 index 0000000..3afdbe9 --- /dev/null +++ b/src/main/resources/org/sasanlabs/fileupload/attackvectors/files/svg_xss_payload.svg @@ -0,0 +1,5 @@ + + + \ No newline at end of file From 468a48c99fc804df1f974b3612c6c9307a2fc165 Mon Sep 17 00:00:00 2001 From: karan preet singh sasan Date: Thu, 31 Dec 2020 02:01:42 +0530 Subject: [PATCH 13/53] Eicar Addon --- .../EicarAntivirusTestFileUpload.java | 98 +++++++++++++++++-- .../attacks/beans/FileExtensionOperation.java | 16 ++- .../attacks/beans/FileParameter.java | 6 ++ .../ImageMagickRemoteCodeExecution.java | 28 ++++++ .../fileupload/attacks/rce/leftItems.java | 24 +++++ .../attacks/xss/HtmlFileUpload.java | 9 ++ 6 files changed, 170 insertions(+), 11 deletions(-) create mode 100644 src/main/java/org/sasanlabs/fileupload/attacks/rce/imagetragick/ImageMagickRemoteCodeExecution.java create mode 100644 src/main/java/org/sasanlabs/fileupload/attacks/rce/leftItems.java diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java index 6bc2e36..17b0642 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java @@ -13,32 +13,114 @@ */ package org.sasanlabs.fileupload.attacks.antivirus; +import static org.sasanlabs.fileupload.Constants.NULL_BYTE_CHARACTER; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Base64; +import java.util.List; import org.sasanlabs.fileupload.attacks.AttackVector; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; +import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; +import org.sasanlabs.fileupload.attacks.beans.FileParameter; import org.sasanlabs.fileupload.exception.FileUploadException; +import org.sasanlabs.fileupload.matcher.ContentMatcher; +import org.sasanlabs.fileupload.matcher.impl.MD5HashResponseMatcher; /** * {@code EicarAntivirusTestFileUpload} attack vector is used to check the if antivirus is present - * and working properly by upload the Eicar file. General idea is to upload the Eicar Test file and - * if we are able to download it again then that means there are chances that Antivirus is either - * not present or not working properly. + * and working properly by uploading the Eicar test file. General idea is to upload the Eicar Test + * file and if we are able to download it again then that means there are chances that Antivirus is + * either not present or not working properly. * *

For more information about Eicar file please visit Eicar File Wiki link * + *

Tested Eicar test file on {@link https://www.virustotal.com/} 63 out of 67 AV softwares detect + * it as a virus. + * * @author KSASAN preetkaran20@gmail.com */ public class EicarAntivirusTestFileUpload implements AttackVector { private static final String EICAR_FILE_CONTENT = - "WDVPIVAlQEFQWzRcUFpYNTQ" - + "oUF4pN0NDKTd9JEVJQ0FSLVNUQU5EQVJELUFOVEl" - + "WSVJVUy1URVNULUZJTEUhJEgrSCo="; + new String( + Base64.getDecoder() + .decode( + "WDVPIVAlQEFQWzRcUFpYNTQ" + + "oUF4pN0NDKTd9JEVJQ0FSLVNUQU5EQVJELUFOVEl" + + "WSVJVUy1URVNULUZJTEUhJEgrSCo="), + StandardCharsets.UTF_8); + private static final String UPLOADED_BASE_FILE_NAME = "EicarAntivirusTestFileUpload_"; + + private static final ContentMatcher CONTENT_MATCHER = + new MD5HashResponseMatcher(EICAR_FILE_CONTENT); + + private static final List FILE_PARAMETERS_DEFAULT = + Arrays.asList( + /** + * Tested that the file content only matters in case of Eicar file and any + * extension with the same content will be flagged as a Virus file. Tested this + * hypothesis with {@link https://github.com/malice-plugins/mcafee} as well as + * on {@link https://www.virustotal.com/} Out of 67 antivirus softwares 63 + * detect the Eicar file as virus file. + */ + new FileParameter(), + // Below file parameters might not be needed but just for a safe side added + // those. + new FileParameter("com"), + new FileParameter("exe"), + new FileParameter("com", "application/octet-stream"), + new FileParameter("exe", "vnd.microsoft.portable-executable"), + new FileParameter( + "com", + "application/octet-stream", + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "exe", + "vnd.microsoft.portable-executable", + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter("com", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter("exe", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + new FileParameter( + "exe" + NULL_BYTE_CHARACTER, + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameter( + "exe" + NULL_BYTE_CHARACTER, + "vnd.microsoft.portable-executable", + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION)); @Override public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) throws FileUploadException { - // TODO Auto-generated method stub - return false; + boolean result = false; + try { + result = + this.genericAttackExecutor( + fileUploadAttackExecutor, + CONTENT_MATCHER, + EICAR_FILE_CONTENT, + UPLOADED_BASE_FILE_NAME, + FILE_PARAMETERS_DEFAULT); + if (result) { + fileUploadAttackExecutor + .getFileUploadScanRule() + .raiseAlert( + 1, + 1, + "", + "", + "", + "", + "", + "", + "", + fileUploadAttackExecutor.getOriginalHttpMessage()); + } + } catch (IOException e) { + throw new FileUploadException(e); + } + return result; } } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileExtensionOperation.java b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileExtensionOperation.java index d19dede..58a70fc 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileExtensionOperation.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileExtensionOperation.java @@ -42,7 +42,14 @@ public enum FileExtensionOperation { * only appends the provided extension e.g. if provided extension is {@code html} and original * file extension is {@code pdf} then final extension will be {@code .html} */ - ONLY_PROVIDED_EXTENSION; + ONLY_PROVIDED_EXTENSION, + + /** + * don't change the extension of original file and use the original extension. e.g. if provided + * extension is {@code html} and original file extension is {@code pdf} then final extension + * will be {@code .pdf} + */ + ONLY_ORIGINAL_EXTENSION; public static String appendPeriodCharacter(String extension) { if (StringUtils.isBlank(extension)) { @@ -57,8 +64,9 @@ public static String appendPeriodCharacter(String extension) { public String operator(String providedExtension, String originalFileName) throws FileUploadException { - if (StringUtils.isBlank(providedExtension)) { - throw new FileUploadException("Provided extension is null"); + if (StringUtils.isBlank(providedExtension) && !this.equals(ONLY_ORIGINAL_EXTENSION)) { + throw new FileUploadException( + "Provided extension cannot be null for FileExtensionOperation: " + this.name()); } String extension; int firstIndexOfPeriodCharacter; @@ -79,6 +87,8 @@ public String operator(String providedExtension, String originalFileName) case ONLY_PROVIDED_EXTENSION: extension = providedExtension; break; + case ONLY_ORIGINAL_EXTENSION: + extension = originalExtension; default: extension = providedExtension; } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java index ce02ad3..b9f682c 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java @@ -30,6 +30,12 @@ public class FileParameter { private FileExtensionOperation fileExtensionOperation = FileExtensionOperation.ONLY_PROVIDED_EXTENSION; + public FileParameter() { + super(); + this.baseFileName = String.valueOf(new Random(new Date().getTime()).nextLong()); + this.fileExtensionOperation = FileExtensionOperation.ONLY_ORIGINAL_EXTENSION; + } + public FileParameter(String extension) { super(); this.baseFileName = String.valueOf(new Random(new Date().getTime()).nextLong()); diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/imagetragick/ImageMagickRemoteCodeExecution.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/imagetragick/ImageMagickRemoteCodeExecution.java new file mode 100644 index 0000000..6b6aec3 --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/imagetragick/ImageMagickRemoteCodeExecution.java @@ -0,0 +1,28 @@ +/** + * Copyright 2020 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sasanlabs.fileupload.attacks.rce.imagetragick; + +import org.sasanlabs.fileupload.attacks.AttackVector; +import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; +import org.sasanlabs.fileupload.exception.FileUploadException; + +public class ImageMagickRemoteCodeExecution implements AttackVector { + + @Override + public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) + throws FileUploadException { + // TODO Auto-generated method stub + return false; + } +} diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/leftItems.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/leftItems.java new file mode 100644 index 0000000..547c72e --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/leftItems.java @@ -0,0 +1,24 @@ +/** + * Copyright 2020 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sasanlabs.fileupload.attacks.rce; +/** + * https://book.hacktricks.xyz/pentesting-web/file-upload + * + *

reverse double extension attack + * + *

https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload + * https://blog.doyensec.com/2020/04/30/polymorphic-images-for-xss.html + * https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a + */ +public class leftItems {} diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java index 815172d..1f64450 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java @@ -160,6 +160,15 @@ public class HtmlFileUpload implements AttackVector { "htm" + NULL_BYTE_CHARACTER, "text/plain", FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + /** + * * + * + *

As per owasp file upload use both NULL BYtes with URL encoded and decoded + * + *

we need to do the same in our code. Important. + * + *

ADD This + */ new FileParameter( "htm" + NULL_BYTE_CHARACTER, FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) From 6b914f60c7e63be26aa3894c1a2c1477ceefb398 Mon Sep 17 00:00:00 2001 From: karan preet singh sasan Date: Fri, 1 Jan 2021 13:16:42 +0530 Subject: [PATCH 14/53] Creating builder --- .../fileupload/AbstractAppVariantPlugin.java | 2 +- .../org/sasanlabs/fileupload/Constants.java | 40 - .../fileupload/FileUploadExtension.java | 2 +- .../fileupload/FileUploadScanRule.java | 2 +- .../sasanlabs/fileupload/FileUploadUtils.java | 92 ++ .../fileupload/attacks/AttackVector.java | 7 +- .../attacks/FileUploadAttackExecutor.java | 2 +- .../EicarAntivirusTestFileUpload.java | 126 ++- .../htaccess/ApachehtaccessFileUpload.java | 2 +- .../attacks/beans/FileExtensionOperation.java | 46 +- .../attacks/beans/FileParameter.java | 55 +- .../attacks/beans/FileParameterBuilder.java | 76 ++ .../attacks/beans/FileParameterImpl.java | 83 ++ .../fileupload/attacks/rce/PathTraversal.java | 2 +- .../ImageMagickRemoteCodeExecution.java | 2 +- .../jsp/ImageBasedJSPRemoteCodeExecution.java | 89 +- .../jsp/PlainOldJSPRemoteCodeExecution.java | 90 +- .../jsp/PlainOldJSPXRemoteCodeExecution.java | 89 +- .../fileupload/attacks/rce/leftItems.java | 4 +- .../fileupload/attacks/rce/php/PhpRCE.java | 2 +- .../attacks/xss/HtmlFileUpload.java | 936 +++++++++++++++--- .../fileupload/attacks/xss/SVGFileUpload.java | 430 ++++++-- .../FileUploadConfiguration.java | 2 +- .../exception/FileUploadException.java | 2 +- .../function/ConsumerWithException.java | 2 +- .../fileupload/i18n/FileUploadI18n.java | 2 +- .../fileupload/locator/URILocator.java | 2 +- .../fileupload/locator/URILocatorImpl.java | 14 +- .../fileupload/matcher/ContentMatcher.java | 2 +- .../impl/ContainsExpectedValueMatcher.java | 2 +- .../matcher/impl/MD5HashResponseMatcher.java | 2 +- .../fileupload/ui/FileUploadOptionsPanel.java | 2 +- 32 files changed, 1784 insertions(+), 427 deletions(-) delete mode 100644 src/main/java/org/sasanlabs/fileupload/Constants.java create mode 100644 src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java create mode 100644 src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameterBuilder.java create mode 100644 src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameterImpl.java diff --git a/src/main/java/org/sasanlabs/fileupload/AbstractAppVariantPlugin.java b/src/main/java/org/sasanlabs/fileupload/AbstractAppVariantPlugin.java index 0c9f33a..dccd099 100644 --- a/src/main/java/org/sasanlabs/fileupload/AbstractAppVariantPlugin.java +++ b/src/main/java/org/sasanlabs/fileupload/AbstractAppVariantPlugin.java @@ -1,5 +1,5 @@ /** - * Copyright 2020 SasanLabs + * Copyright 2021 SasanLabs * *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at diff --git a/src/main/java/org/sasanlabs/fileupload/Constants.java b/src/main/java/org/sasanlabs/fileupload/Constants.java deleted file mode 100644 index dcc4db8..0000000 --- a/src/main/java/org/sasanlabs/fileupload/Constants.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Copyright 2020 SasanLabs - * - *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of the License at - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sasanlabs.fileupload; - -import org.parosproxy.paros.network.HttpMessage; - -/** - * Contains the String constants or other utility constants used by the File Upload Addon. - * - * @author preetkaran20@gmail.com KSASAN - */ -public interface Constants { - String EMPTY_STRING = ""; - String PERIOD = "."; - String SLASH = "/"; - String NULL_BYTE_CHARACTER = String.valueOf((char) 0); - String HTTP_SCHEME = "http://"; - String HTTP_SECURED_SCHEME = "https://"; - - static boolean isContentDispositionInline(HttpMessage preflightMsg) { - String headerValue = preflightMsg.getResponseHeader().getHeader("Content-Disposition"); - if (headerValue == null - || headerValue.trim().equals(Constants.EMPTY_STRING) - || headerValue.equals("inline")) { - return true; - } - return false; - } -} diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadExtension.java b/src/main/java/org/sasanlabs/fileupload/FileUploadExtension.java index da05a4a..2bf1b31 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadExtension.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadExtension.java @@ -1,5 +1,5 @@ /** - * Copyright 2020 SasanLabs + * Copyright 2021 SasanLabs * *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java index 4f02ff7..9fbbfff 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java @@ -1,5 +1,5 @@ /** - * Copyright 2020 SasanLabs + * Copyright 2021 SasanLabs * *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java b/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java new file mode 100644 index 0000000..8c80839 --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java @@ -0,0 +1,92 @@ +/** + * Copyright 2021 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sasanlabs.fileupload; + +import java.util.Objects; +import org.apache.commons.lang3.StringUtils; +import org.parosproxy.paros.network.HttpHeader; +import org.parosproxy.paros.network.HttpMessage; + +/** + * Contains the String constants or other utility constants used by the File Upload Addon. + * + * @author preetkaran20@gmail.com KSASAN + */ +public interface FileUploadUtils { + String EMPTY_STRING = ""; + String PERIOD = "."; + String SLASH = "/"; + String NULL_BYTE_CHARACTER = String.valueOf((char) 0); + String HTTP_SCHEME = "http://"; + String HTTP_SECURED_SCHEME = "https://"; + String HTML_MIME_TYPE = "text/html"; + String XHTML_MIME_TYPE = "application/xhtml+xml"; + String SVG_MIME_TYPE = "image/svg+xml"; + + /** + * Appends the Period Character to the provided String. + * + * @param extension + * @return + */ + static String appendPeriodCharacter(String extension) { + if (StringUtils.isBlank(extension)) { + return extension; + } else { + if (extension.startsWith(FileUploadUtils.PERIOD)) { + return extension; + } + return FileUploadUtils.PERIOD + extension; + } + } + + /** + * returns the extension of the provided fileName. + * + * @param fileName + * @return extension of the provided fileName + * @throws Null Pointer Exception if fileName is null + */ + static String getExtension(String fileName) { + Objects.requireNonNull(fileName, "FileName cannot be null"); + int firstIndexOfPeriodCharacter = fileName.indexOf(FileUploadUtils.PERIOD); + if (firstIndexOfPeriodCharacter >= 0) { + return fileName.substring(firstIndexOfPeriodCharacter + 1); + } + return null; + } + + static boolean isContentDispositionInline(HttpMessage preflightMsg) { + String headerValue = preflightMsg.getResponseHeader().getHeader("Content-Disposition"); + if (headerValue == null + || headerValue.trim().equals(FileUploadUtils.EMPTY_STRING) + || headerValue.equals("inline")) { + return true; + } + return false; + } + + static boolean isContentTypeHeaderPresent(HttpMessage preflightMsg) { + String headerValue = preflightMsg.getResponseHeader().getHeader(HttpHeader.CONTENT_TYPE); + return StringUtils.isNotBlank(headerValue); + } + + static boolean isContentTypeCausesJavascriptExecution(HttpMessage preflightMsg) { + String headerValue = preflightMsg.getResponseHeader().getHeader(HttpHeader.CONTENT_TYPE); + return StringUtils.isNotBlank(headerValue) + && (headerValue.equalsIgnoreCase(HTML_MIME_TYPE) + || headerValue.equalsIgnoreCase(XHTML_MIME_TYPE) + || headerValue.equalsIgnoreCase(XHTML_MIME_TYPE)); + } +} diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java index c68b3ae..c39f5ee 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java @@ -1,5 +1,5 @@ /** - * Copyright 2020 SasanLabs + * Copyright 2021 SasanLabs * *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at @@ -61,7 +61,6 @@ default boolean genericAttackExecutor( FileUploadAttackExecutor fileUploadAttackExecutor, ContentMatcher contentMatcher, String payload, - String baseFileName, List fileParameters) throws IOException, FileUploadException { List nameValuePairs = fileUploadAttackExecutor.getVariant().getParamList(); @@ -90,7 +89,7 @@ default boolean genericAttackExecutor( newMsg, nameValuePair, nameValuePair.getName(), - fileParameter.getFileName(originalFileName, baseFileName)); + fileParameter.getFileName(originalFileName)); } else if (nameValuePair.getType() == NameValuePair.TYPE_MULTIPART_DATA_FILE_PARAM) { fileUploadScanRule.setParameter( @@ -115,7 +114,7 @@ default boolean genericAttackExecutor( HttpMessage preflightMsg = this.executePreflightRequest( newMsg, - fileParameter.getFileName(originalFileName, baseFileName), + fileParameter.getFileName(originalFileName), fileUploadScanRule); if (contentMatcher.match(preflightMsg)) { return true; diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java b/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java index 75894e2..df91fb1 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java @@ -1,5 +1,5 @@ /** - * Copyright 2020 SasanLabs + * Copyright 2021 SasanLabs * *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java index 17b0642..0f10679 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java @@ -1,5 +1,5 @@ /** - * Copyright 2020 SasanLabs + * Copyright 2021 SasanLabs * *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at @@ -13,7 +13,7 @@ */ package org.sasanlabs.fileupload.attacks.antivirus; -import static org.sasanlabs.fileupload.Constants.NULL_BYTE_CHARACTER; +import static org.sasanlabs.fileupload.FileUploadUtils.NULL_BYTE_CHARACTER; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -24,6 +24,7 @@ import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; import org.sasanlabs.fileupload.attacks.beans.FileParameter; +import org.sasanlabs.fileupload.attacks.beans.FileParameterBuilder; import org.sasanlabs.fileupload.exception.FileUploadException; import org.sasanlabs.fileupload.matcher.ContentMatcher; import org.sasanlabs.fileupload.matcher.impl.MD5HashResponseMatcher; @@ -66,30 +67,106 @@ public class EicarAntivirusTestFileUpload implements AttackVector { * on {@link https://www.virustotal.com/} Out of 67 antivirus softwares 63 * detect the Eicar file as virus file. */ - new FileParameter(), + new FileParameterBuilder() + .withFileExtensionOperation( + FileExtensionOperation.ONLY_ORIGINAL_EXTENSION) + .build(), + + // new FileParameter(FileExtensionOperation.ONLY_ORIGINAL_EXTENSION), // Below file parameters might not be needed but just for a safe side added // those. - new FileParameter("com"), - new FileParameter("exe"), - new FileParameter("com", "application/octet-stream"), - new FileParameter("exe", "vnd.microsoft.portable-executable"), - new FileParameter( - "com", - "application/octet-stream", - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "exe", - "vnd.microsoft.portable-executable", - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter("com", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter("exe", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "exe" + NULL_BYTE_CHARACTER, - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "exe" + NULL_BYTE_CHARACTER, - "vnd.microsoft.portable-executable", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION)); + new FileParameterBuilder() + .withBaseFileName(UPLOADED_BASE_FILE_NAME) + .withExtension("com") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(UPLOADED_BASE_FILE_NAME) + .withExtension("exe") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(UPLOADED_BASE_FILE_NAME) + .withExtension("com") + .withContentType("application/octet-stream") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(UPLOADED_BASE_FILE_NAME) + .withExtension("exe") + .withContentType("vnd.microsoft.portable-executable") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(UPLOADED_BASE_FILE_NAME) + .withExtension("com") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(UPLOADED_BASE_FILE_NAME) + .withExtension("exe") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(UPLOADED_BASE_FILE_NAME) + .withExtension("com") + .withContentType("application/octet-stream") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(UPLOADED_BASE_FILE_NAME) + .withExtension("exe") + .withContentType("vnd.microsoft.portable-executable") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(UPLOADED_BASE_FILE_NAME) + .withExtension("com" + NULL_BYTE_CHARACTER) + .withContentType("application/octet-stream") + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(UPLOADED_BASE_FILE_NAME) + .withExtension("exe" + NULL_BYTE_CHARACTER) + .withContentType("vnd.microsoft.portable-executable") + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build() + + // new FileParameter("com"), + // new FileParameter("exe"), + // new FileParameter("com", "application/octet-stream"), + // new FileParameter("exe", + // "vnd.microsoft.portable-executable"), + // new FileParameter( + // "com", + // "application/octet-stream", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter( + // "exe", + // "vnd.microsoft.portable-executable", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter("com", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter("exe", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter( + // "exe" + NULL_BYTE_CHARACTER, + // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + // new FileParameter( + // "exe" + NULL_BYTE_CHARACTER, + // "vnd.microsoft.portable-executable", + // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + ); @Override public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) @@ -101,7 +178,6 @@ public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) fileUploadAttackExecutor, CONTENT_MATCHER, EICAR_FILE_CONTENT, - UPLOADED_BASE_FILE_NAME, FILE_PARAMETERS_DEFAULT); if (result) { fileUploadAttackExecutor diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/apache/htaccess/ApachehtaccessFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/apache/htaccess/ApachehtaccessFileUpload.java index 349e835..18fdbf0 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/apache/htaccess/ApachehtaccessFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/apache/htaccess/ApachehtaccessFileUpload.java @@ -1,5 +1,5 @@ /** - * Copyright 2020 SasanLabs + * Copyright 2021 SasanLabs * *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileExtensionOperation.java b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileExtensionOperation.java index 58a70fc..0251780 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileExtensionOperation.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileExtensionOperation.java @@ -1,5 +1,5 @@ /** - * Copyright 2020 SasanLabs + * Copyright 2021 SasanLabs * *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at @@ -14,7 +14,7 @@ package org.sasanlabs.fileupload.attacks.beans; import org.apache.commons.lang3.StringUtils; -import org.sasanlabs.fileupload.Constants; +import org.sasanlabs.fileupload.FileUploadUtils; import org.sasanlabs.fileupload.exception.FileUploadException; /** @@ -24,6 +24,8 @@ */ public enum FileExtensionOperation { + /** doesn't append any extension to the filename. */ + NO_EXTENSION, /** * appends the Original File Extension before the provided extension. e.g. if provided extension * is {@code html} and original file extension is {@code pdf} then the final extension will be @@ -51,46 +53,40 @@ public enum FileExtensionOperation { */ ONLY_ORIGINAL_EXTENSION; - public static String appendPeriodCharacter(String extension) { - if (StringUtils.isBlank(extension)) { - return extension; - } else { - if (extension.startsWith(Constants.PERIOD)) { - return extension; - } - return Constants.PERIOD + extension; - } - } - - public String operator(String providedExtension, String originalFileName) + public String operate(String providedExtension, String originalFileName) throws FileUploadException { - if (StringUtils.isBlank(providedExtension) && !this.equals(ONLY_ORIGINAL_EXTENSION)) { + if (StringUtils.isBlank(providedExtension) + && !(this.equals(ONLY_ORIGINAL_EXTENSION) || this.equals(NO_EXTENSION))) { throw new FileUploadException( "Provided extension cannot be null for FileExtensionOperation: " + this.name()); } String extension; - int firstIndexOfPeriodCharacter; String originalExtension = ""; if (originalFileName != null) { - firstIndexOfPeriodCharacter = originalFileName.indexOf(Constants.PERIOD); - if (firstIndexOfPeriodCharacter >= 0) { - originalExtension = originalFileName.substring(firstIndexOfPeriodCharacter + 1); - } + originalExtension = FileUploadUtils.getExtension(originalFileName); } switch (this) { case PREFIX_ORIGINAL_EXTENSION: - extension = originalExtension + appendPeriodCharacter(providedExtension); + extension = + FileUploadUtils.appendPeriodCharacter( + originalExtension + + FileUploadUtils.appendPeriodCharacter(providedExtension)); break; case SUFFIX_ORIGINAL_EXTENSION: - extension = providedExtension + appendPeriodCharacter(originalExtension); + extension = + FileUploadUtils.appendPeriodCharacter( + providedExtension + + FileUploadUtils.appendPeriodCharacter(originalExtension)); break; case ONLY_PROVIDED_EXTENSION: - extension = providedExtension; + extension = FileUploadUtils.appendPeriodCharacter(providedExtension); break; case ONLY_ORIGINAL_EXTENSION: - extension = originalExtension; + extension = FileUploadUtils.appendPeriodCharacter(originalExtension); + case NO_EXTENSION: + extension = ""; default: - extension = providedExtension; + extension = FileUploadUtils.appendPeriodCharacter(providedExtension); } return extension; } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java index b9f682c..146d742 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java @@ -1,5 +1,5 @@ /** - * Copyright 2020 SasanLabs + * Copyright 2021 SasanLabs * *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at @@ -13,60 +13,15 @@ */ package org.sasanlabs.fileupload.attacks.beans; -import java.util.Date; -import java.util.Random; import org.sasanlabs.fileupload.exception.FileUploadException; /** - * {@code FileParameter} class is used to represent the file object ... + * {@code FileParameter} interface is used to represent the new file properties. * * @author KSASAN preetkaran20@gmail.com */ -public class FileParameter { +public interface FileParameter { + String getContentType(String originalContentType); - private String baseFileName; - private String extension; - private String contentType; - private FileExtensionOperation fileExtensionOperation = - FileExtensionOperation.ONLY_PROVIDED_EXTENSION; - - public FileParameter() { - super(); - this.baseFileName = String.valueOf(new Random(new Date().getTime()).nextLong()); - this.fileExtensionOperation = FileExtensionOperation.ONLY_ORIGINAL_EXTENSION; - } - - public FileParameter(String extension) { - super(); - this.baseFileName = String.valueOf(new Random(new Date().getTime()).nextLong()); - this.extension = extension; - } - - public FileParameter(String extension, String contentType) { - this(extension); - this.contentType = contentType; - } - - public FileParameter(String extension, FileExtensionOperation fileExtensionOperation) { - this(extension); - this.fileExtensionOperation = fileExtensionOperation; - } - - public FileParameter( - String extension, String contentType, FileExtensionOperation fileExtensionOperation) { - this(extension, fileExtensionOperation); - this.contentType = contentType; - } - - public String getContentType(String originalContentType) { - return contentType == null ? originalContentType : this.contentType; - } - - public String getFileName(String originalFileName, String newBaseFileName) - throws FileUploadException { - return String.valueOf(newBaseFileName) - + this.baseFileName - + FileExtensionOperation.appendPeriodCharacter( - fileExtensionOperation.operator(this.extension, originalFileName)); - } + String getFileName(String originalFileName) throws FileUploadException; } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameterBuilder.java b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameterBuilder.java new file mode 100644 index 0000000..03d49b3 --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameterBuilder.java @@ -0,0 +1,76 @@ +/** + * Copyright 2021 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sasanlabs.fileupload.attacks.beans; + +import java.util.Objects; + +/** + * {@code FileParameterBuilder} is used to build the complex {@code FileParameter} object. + * + * @author KSASAN preetkaran20@gmail.com + */ +public class FileParameterBuilder { + private FileParameterImpl fileParameterImpl; + + public FileParameterBuilder() {} + + public FileParameterBuilder withFileNameAsOriginalExtension() { + fileParameterImpl = new FileParameterImpl(); + return this; + } + + public FileParameterBuilder withFileName(String fileName) { + Objects.requireNonNull(fileName, "BaseFileName cannot be null"); + fileParameterImpl = new FileParameterImpl(fileName, false); + return this; + } + + public FileParameterBuilder withBaseFileName(String baseFileName) { + Objects.requireNonNull(baseFileName, "BaseFileName cannot be null"); + fileParameterImpl = new FileParameterImpl(baseFileName); + return this; + } + + public FileParameterBuilder withFileExtensionOperation( + FileExtensionOperation fileExtensionOperation) { + fileParameterImpl.setFileExtensionOperation(fileExtensionOperation); + return this; + } + + public FileParameterBuilder withExtension(String providedExtension) { + fileParameterImpl.setExtension(providedExtension); + return this; + } + + public FileParameterBuilder withContentType(String contentType) { + fileParameterImpl.setContentType(contentType); + return this; + } + + public FileParameter build() { + if ((fileParameterImpl + .getFileExtensionOperation() + .equals(FileExtensionOperation.NO_EXTENSION) + || fileParameterImpl + .getFileExtensionOperation() + .equals(FileExtensionOperation.ONLY_ORIGINAL_EXTENSION)) + && fileParameterImpl.getExtension() != null) { + throw new RuntimeException( + "Invalid combination, For FileExtensionOperation: " + + this.fileParameterImpl.getFileExtensionOperation() + + " and ProvidedExtension should be null"); + } + return fileParameterImpl; + } +} diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameterImpl.java b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameterImpl.java new file mode 100644 index 0000000..414966e --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameterImpl.java @@ -0,0 +1,83 @@ +/** + * Copyright 2021 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sasanlabs.fileupload.attacks.beans; + +import java.util.Date; +import java.util.Random; +import org.sasanlabs.fileupload.FileUploadUtils; +import org.sasanlabs.fileupload.exception.FileUploadException; + +/** @author KSASAN preetkaran20@gmail.com */ +class FileParameterImpl implements FileParameter { + private String fileName; + private String extension; + private String contentType; + private boolean originalExtensionAsFileName = false; + private FileExtensionOperation fileExtensionOperation = FileExtensionOperation.NO_EXTENSION; + + FileParameterImpl() { + originalExtensionAsFileName = true; + } + + FileParameterImpl(String fileName) { + this.fileName = fileName; + } + + FileParameterImpl(String baseFileName, boolean appendRandomCharacters) { + this.fileName = baseFileName; + if (appendRandomCharacters) { + this.fileName = this.fileName + new Random(new Date().getTime()).nextLong(); + } + } + + void setExtension(String extension) { + this.extension = extension; + } + + void setContentType(String contentType) { + this.contentType = contentType; + } + + void setFileExtensionOperation(FileExtensionOperation fileExtensionOperation) { + this.fileExtensionOperation = fileExtensionOperation; + } + + String getExtension() { + return extension; + } + + public boolean isOriginalExtensionAsFileName() { + return originalExtensionAsFileName; + } + + FileExtensionOperation getFileExtensionOperation() { + return fileExtensionOperation; + } + + @Override + public String getContentType(String originalContentType) { + return contentType == null ? originalContentType : this.contentType; + } + + @Override + public String getFileName(String originalFileName) throws FileUploadException { + if (originalFileName == null) { + throw new FileUploadException("Provided original File Name is null"); + } + if (originalExtensionAsFileName) { + return FileUploadUtils.getExtension(originalFileName); + } + return this.fileName + fileExtensionOperation.operate(this.extension, originalFileName); + } +} diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/PathTraversal.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/PathTraversal.java index e28636a..b683e72 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/PathTraversal.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/PathTraversal.java @@ -1,5 +1,5 @@ /** - * Copyright 2020 SasanLabs + * Copyright 2021 SasanLabs * *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/imagetragick/ImageMagickRemoteCodeExecution.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/imagetragick/ImageMagickRemoteCodeExecution.java index 6b6aec3..4a89577 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/imagetragick/ImageMagickRemoteCodeExecution.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/imagetragick/ImageMagickRemoteCodeExecution.java @@ -1,5 +1,5 @@ /** - * Copyright 2020 SasanLabs + * Copyright 2021 SasanLabs * *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageBasedJSPRemoteCodeExecution.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageBasedJSPRemoteCodeExecution.java index 78a269e..381ca2d 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageBasedJSPRemoteCodeExecution.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageBasedJSPRemoteCodeExecution.java @@ -1,5 +1,5 @@ /** - * Copyright 2020 SasanLabs + * Copyright 2021 SasanLabs * *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at @@ -13,7 +13,7 @@ */ package org.sasanlabs.fileupload.attacks.rce.jsp; -import static org.sasanlabs.fileupload.Constants.NULL_BYTE_CHARACTER; +import static org.sasanlabs.fileupload.FileUploadUtils.NULL_BYTE_CHARACTER; import java.io.IOException; import java.nio.charset.Charset; @@ -26,6 +26,7 @@ import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; import org.sasanlabs.fileupload.attacks.beans.FileParameter; +import org.sasanlabs.fileupload.attacks.beans.FileParameterBuilder; import org.sasanlabs.fileupload.exception.FileUploadException; import org.sasanlabs.fileupload.matcher.impl.ContainsExpectedValueMatcher; @@ -40,20 +41,75 @@ public class ImageBasedJSPRemoteCodeExecution implements AttackVector { private static final List FILE_PARAMETERS = Arrays.asList( - new FileParameter("jsp"), - new FileParameter("jsp", "application/x-jsp"), - new FileParameter("jsp", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "jsp", - "application/x-jsp", - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "jsp" + NULL_BYTE_CHARACTER, - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "jsp" + NULL_BYTE_CHARACTER, - "application/x-jsp", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION)); + new FileParameterBuilder() + .withBaseFileName(BASE_FILE_NAME) + .withExtension("jsp") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(BASE_FILE_NAME) + .withExtension("jsp") + .withContentType("application/x-jsp") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(BASE_FILE_NAME) + .withExtension("jsp") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(BASE_FILE_NAME) + .withExtension("jsp") + .withContentType("application/x-jsp") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(BASE_FILE_NAME) + .withExtension("jsp" + NULL_BYTE_CHARACTER) + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(BASE_FILE_NAME) + .withExtension("jsp" + NULL_BYTE_CHARACTER) + .withContentType("application/x-jsp") + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(BASE_FILE_NAME) + .withExtension("jsp%00") + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(BASE_FILE_NAME) + .withExtension("jsp%00") + .withContentType("application/x-jsp") + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build() + + // new FileParameter("jsp"), + // new FileParameter("jsp", "application/x-jsp"), + // new FileParameter("jsp", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter( + // "jsp", + // "application/x-jsp", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter( + // "jsp" + NULL_BYTE_CHARACTER, + // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + // new FileParameter( + // "jsp" + NULL_BYTE_CHARACTER, + // "application/x-jsp", + // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + ); @Override public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) @@ -71,7 +127,6 @@ public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) fileUploadAttackExecutor, new ContainsExpectedValueMatcher(EXPECTED_VALUE), requestPayload, - BASE_FILE_NAME, FILE_PARAMETERS)) { fileUploadAttackExecutor .getFileUploadScanRule() diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/PlainOldJSPRemoteCodeExecution.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/PlainOldJSPRemoteCodeExecution.java index aecb08c..e56fe1d 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/PlainOldJSPRemoteCodeExecution.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/PlainOldJSPRemoteCodeExecution.java @@ -1,5 +1,5 @@ /** - * Copyright 2020 SasanLabs + * Copyright 2021 SasanLabs * *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at @@ -13,7 +13,7 @@ */ package org.sasanlabs.fileupload.attacks.rce.jsp; -import static org.sasanlabs.fileupload.Constants.NULL_BYTE_CHARACTER; +import static org.sasanlabs.fileupload.FileUploadUtils.NULL_BYTE_CHARACTER; import java.io.IOException; import java.util.Arrays; @@ -22,6 +22,7 @@ import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; import org.sasanlabs.fileupload.attacks.beans.FileParameter; +import org.sasanlabs.fileupload.attacks.beans.FileParameterBuilder; import org.sasanlabs.fileupload.exception.FileUploadException; import org.sasanlabs.fileupload.matcher.ContentMatcher; import org.sasanlabs.fileupload.matcher.impl.MD5HashResponseMatcher; @@ -41,20 +42,76 @@ public class PlainOldJSPRemoteCodeExecution implements AttackVector { private static final List FILE_PARAMETERS = Arrays.asList( - new FileParameter("jsp"), - new FileParameter("jsp", "application/x-jsp"), - new FileParameter("jsp", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "jsp", - "application/x-jsp", - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "jsp" + NULL_BYTE_CHARACTER, - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "jsp" + NULL_BYTE_CHARACTER, - "application/x-jsp", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION)); + new FileParameterBuilder() + .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + .withExtension("jsp") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + .withExtension("jsp") + .withContentType("application/x-jsp") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + .withExtension("jsp") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + .withExtension("jsp") + .withContentType("application/x-jsp") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + .withExtension("jsp" + NULL_BYTE_CHARACTER) + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + .withExtension("jsp" + NULL_BYTE_CHARACTER) + .withContentType("application/x-jsp") + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + .withExtension("jsp%00") + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + .withExtension("jsp%00") + .withContentType("application/x-jsp") + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build() + + // + // new FileParameter("jsp"), + // new FileParameter("jsp", "application/x-jsp"), + // new FileParameter("jsp", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter( + // "jsp", + // "application/x-jsp", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter( + // "jsp" + NULL_BYTE_CHARACTER, + // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + // new FileParameter( + // "jsp" + NULL_BYTE_CHARACTER, + // "application/x-jsp", + // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + ); @Override public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) @@ -66,7 +123,6 @@ public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) fileUploadAttackExecutor, CONTENT_MATCHER, JSP_PAYLOAD, - JSP_UPLOADED_FILE_BASE_NAME, FILE_PARAMETERS); if (result) { fileUploadAttackExecutor diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/PlainOldJSPXRemoteCodeExecution.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/PlainOldJSPXRemoteCodeExecution.java index ffa735e..87dd425 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/PlainOldJSPXRemoteCodeExecution.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/PlainOldJSPXRemoteCodeExecution.java @@ -1,5 +1,5 @@ /** - * Copyright 2020 SasanLabs + * Copyright 2021 SasanLabs * *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at @@ -13,7 +13,7 @@ */ package org.sasanlabs.fileupload.attacks.rce.jsp; -import static org.sasanlabs.fileupload.Constants.NULL_BYTE_CHARACTER; +import static org.sasanlabs.fileupload.FileUploadUtils.NULL_BYTE_CHARACTER; import java.io.IOException; import java.util.Arrays; @@ -22,6 +22,7 @@ import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; import org.sasanlabs.fileupload.attacks.beans.FileParameter; +import org.sasanlabs.fileupload.attacks.beans.FileParameterBuilder; import org.sasanlabs.fileupload.exception.FileUploadException; import org.sasanlabs.fileupload.matcher.ContentMatcher; import org.sasanlabs.fileupload.matcher.impl.MD5HashResponseMatcher; @@ -48,20 +49,75 @@ public class PlainOldJSPXRemoteCodeExecution implements AttackVector { // text/x-jsp private static final List FILE_PARAMETERS = Arrays.asList( - new FileParameter("jspx"), - new FileParameter("jspx", "application/x-jsp"), - new FileParameter("jspx", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "jspx", - "application/x-jsp", - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "jspx" + NULL_BYTE_CHARACTER, - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "jspx" + NULL_BYTE_CHARACTER, - "application/x-jsp", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION)); + new FileParameterBuilder() + .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + .withExtension("jspx") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + .withExtension("jspx") + .withContentType("application/x-jsp") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + .withExtension("jspx") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + .withExtension("jspx") + .withContentType("application/x-jsp") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + .withExtension("jspx" + NULL_BYTE_CHARACTER) + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + .withExtension("jspx" + NULL_BYTE_CHARACTER) + .withContentType("application/x-jsp") + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + .withExtension("jspx%00") + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + .withExtension("jspx%00") + .withContentType("application/x-jsp") + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build() + + // new FileParameter("jspx"), + // new FileParameter("jspx", "application/x-jsp"), + // new FileParameter("jspx", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter( + // "jspx", + // "application/x-jsp", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter( + // "jspx" + NULL_BYTE_CHARACTER, + // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + // new FileParameter( + // "jspx" + NULL_BYTE_CHARACTER, + // "application/x-jsp", + // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + ); @Override public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) @@ -73,7 +129,6 @@ public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) fileUploadAttackExecutor, CONTENT_MATCHER, JSPX_PAYLOAD, - JSPX_UPLOADED_FILE_BASE_NAME, FILE_PARAMETERS); if (result) { fileUploadAttackExecutor diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/leftItems.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/leftItems.java index 547c72e..7658cad 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/leftItems.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/leftItems.java @@ -1,5 +1,5 @@ /** - * Copyright 2020 SasanLabs + * Copyright 2021 SasanLabs * *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at @@ -20,5 +20,7 @@ *

https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload * https://blog.doyensec.com/2020/04/30/polymorphic-images-for-xss.html * https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a + * + *

BIT MAP based XSS */ public class leftItems {} diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/php/PhpRCE.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/php/PhpRCE.java index 273a959..2bfb868 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/php/PhpRCE.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/php/PhpRCE.java @@ -1,5 +1,5 @@ /** - * Copyright 2020 SasanLabs + * Copyright 2021 SasanLabs * *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java index 1f64450..df0dc56 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java @@ -1,5 +1,5 @@ /** - * Copyright 2020 SasanLabs + * Copyright 2021 SasanLabs * *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at @@ -13,17 +13,18 @@ */ package org.sasanlabs.fileupload.attacks.xss; -import static org.sasanlabs.fileupload.Constants.NULL_BYTE_CHARACTER; +import static org.sasanlabs.fileupload.FileUploadUtils.NULL_BYTE_CHARACTER; import java.io.IOException; import java.util.Arrays; import java.util.List; import org.parosproxy.paros.core.scanner.Plugin.AttackStrength; -import org.sasanlabs.fileupload.Constants; +import org.sasanlabs.fileupload.FileUploadUtils; import org.sasanlabs.fileupload.attacks.AttackVector; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; import org.sasanlabs.fileupload.attacks.beans.FileParameter; +import org.sasanlabs.fileupload.attacks.beans.FileParameterBuilder; import org.sasanlabs.fileupload.exception.FileUploadException; import org.sasanlabs.fileupload.matcher.ContentMatcher; import org.sasanlabs.fileupload.matcher.impl.MD5HashResponseMatcher; @@ -44,161 +45,818 @@ public class HtmlFileUpload implements AttackVector { private static final String XSS_PAYLOAD_HTML_FILE = "Testing XSS"; + /** + * Precondition:
+ * 1. ContentDisposition should be inline
+ * 2. ContentType should be {@link FileUploadUtils#HTML_MIME_TYPE} or {@link + * FileUploadUtils#XHTML_MIME_TYPE}
+ * or blank Note: here we are not considering the invalid content type header values because + * that should not be there. + */ static final ContentMatcher CONTENT_MATCHER = new MD5HashResponseMatcher( - httpMsg -> Constants.isContentDispositionInline(httpMsg), + httpMsg -> + FileUploadUtils.isContentDispositionInline(httpMsg) + && (!FileUploadUtils.isContentTypeHeaderPresent(httpMsg) + || FileUploadUtils + .isContentTypeCausesJavascriptExecution( + httpMsg)), XSS_PAYLOAD_HTML_FILE); // Extended list for breaking black-listing strategy. private static final List FILE_PARAMETERS_EXTENDED = Arrays.asList( - new FileParameter("Htm"), - new FileParameter("hTM"), - new FileParameter("HTM"), - new FileParameter("Html"), - new FileParameter("HtMl"), - new FileParameter("HTMl"), - new FileParameter("HTML"), - new FileParameter("Xhtml"), - new FileParameter("xHTml"), - new FileParameter("xhTML"), - new FileParameter("xHTML"), - new FileParameter("XHTML"), - new FileParameter("dHtml"), - new FileParameter("sHtml"), - new FileParameter("dHTml"), - new FileParameter("sHTml"), - new FileParameter("dHTML"), - new FileParameter("sHTML"), - new FileParameter("Htm", "text/html"), - new FileParameter("hTM", "text/html"), - new FileParameter("HTM", "text/html"), - new FileParameter("Html", "text/html"), - new FileParameter("HtMl", "text/html"), - new FileParameter("HTMl", "text/html"), - new FileParameter("HTML", "text/html"), - new FileParameter("Xhtml", "text/html"), - new FileParameter("xHTml", "text/html"), - new FileParameter("xhTML", "text/html"), - new FileParameter("xHTML", "text/html"), - new FileParameter("XHTML", "text/html"), - new FileParameter("dHtml", "text/html"), - new FileParameter("sHtml", "text/html"), - new FileParameter("dHTml", "text/html"), - new FileParameter("sHTml", "text/html"), - new FileParameter("dHTML", "text/html"), - new FileParameter("sHTML", "text/html"), - new FileParameter("Htm", "text/plain"), - new FileParameter("hTM", "text/plain"), - new FileParameter("HTM", "text/plain"), - new FileParameter("Html", "text/plain"), - new FileParameter("HtMl", "text/plain"), - new FileParameter("HTMl", "text/plain"), - new FileParameter("HTML", "text/plain"), - new FileParameter("Xhtml", "text/plain"), - new FileParameter("xHTml", "text/plain"), - new FileParameter("xhTML", "text/plain"), - new FileParameter("xHTML", "text/plain"), - new FileParameter("XHTML", "text/plain"), - new FileParameter("dHtml", "text/plain"), - new FileParameter("sHtml", "text/plain"), - new FileParameter("dHTml", "text/plain"), - new FileParameter("sHTml", "text/plain"), - new FileParameter("dHTML", "text/plain"), - new FileParameter("sHTML", "text/plain"), - new FileParameter( - "Htm", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "HTML", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "Xhtml", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "XHTML", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter("Htm", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter("HTML", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter("Xhtml", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter("XHTML", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION)); + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("Htm") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("hTM") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("HTM") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("Html") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("HtML") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("HTMl") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("HTML") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("Xhtml") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("xHTml") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("xhTML") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("xHTML") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("XHTML") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("dHtml") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("sHtml") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("dHTml") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("sHTml") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("dHTML") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("sHTML") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("Htm") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("hTM") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("HTM") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("Html") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("HtML") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("HTMl") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("HTML") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("Xhtml") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("xHTml") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("xhTML") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("xHTML") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("XHTML") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("dHtml") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("sHtml") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("dHTml") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("sHTml") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("dHTML") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("sHTML") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("Htm") + .withContentType("text/plain") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("hTM") + .withContentType("text/plain") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("HTM") + .withContentType("text/plain") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("Html") + .withContentType("text/plain") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("HtML") + .withContentType("text/plain") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("HTMl") + .withContentType("text/plain") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("HTML") + .withContentType("text/plain") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("Xhtml") + .withContentType("text/plain") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("xHTml") + .withContentType("text/plain") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("xhTML") + .withContentType("text/plain") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("xHTML") + .withContentType("text/plain") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("XHTML") + .withContentType("text/plain") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("dHtml") + .withContentType("text/plain") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("sHtml") + .withContentType("text/plain") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("dHTml") + .withContentType("text/plain") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("sHTml") + .withContentType("text/plain") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("dHTML") + .withContentType("text/plain") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("sHTML") + .withContentType("text/plain") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + + // new FileParameter("Htm"), + // new FileParameter("hTM"), + // new FileParameter("HTM"), + // new FileParameter("Html"), + // new FileParameter("HtMl"), + // new FileParameter("HTMl"), + // new FileParameter("HTML"), + // new FileParameter("Xhtml"), + // new FileParameter("xHTml"), + // new FileParameter("xhTML"), + // new FileParameter("xHTML"), + // new FileParameter("XHTML"), + // new FileParameter("dHtml"), + // new FileParameter("sHtml"), + // new FileParameter("dHTml"), + // new FileParameter("sHTml"), + // new FileParameter("dHTML"), + // new FileParameter("sHTML"), + // new FileParameter("Htm", "text/html"), + // new FileParameter("hTM", "text/html"), + // new FileParameter("HTM", "text/html"), + // new FileParameter("Html", "text/html"), + // new FileParameter("HtMl", "text/html"), + // new FileParameter("HTMl", "text/html"), + // new FileParameter("HTML", "text/html"), + // new FileParameter("Xhtml", "text/html"), + // new FileParameter("xHTml", "text/html"), + // new FileParameter("xhTML", "text/html"), + // new FileParameter("xHTML", "text/html"), + // new FileParameter("XHTML", "text/html"), + // new FileParameter("dHtml", "text/html"), + // new FileParameter("sHtml", "text/html"), + // new FileParameter("dHTml", "text/html"), + // new FileParameter("sHTml", "text/html"), + // new FileParameter("dHTML", "text/html"), + // new FileParameter("sHTML", "text/html"), + // new FileParameter("Htm", "text/plain"), + // new FileParameter("hTM", "text/plain"), + // new FileParameter("HTM", "text/plain"), + // new FileParameter("Html", "text/plain"), + // new FileParameter("HtMl", "text/plain"), + // new FileParameter("HTMl", "text/plain"), + // new FileParameter("HTML", "text/plain"), + // new FileParameter("Xhtml", "text/plain"), + // new FileParameter("xHTml", "text/plain"), + // new FileParameter("xhTML", "text/plain"), + // new FileParameter("xHTML", "text/plain"), + // new FileParameter("XHTML", "text/plain"), + // new FileParameter("dHtml", "text/plain"), + // new FileParameter("sHtml", "text/plain"), + // new FileParameter("dHTml", "text/plain"), + // new FileParameter("sHTml", "text/plain"), + // new FileParameter("dHTML", "text/plain"), + // new FileParameter("sHTML", "text/plain"), + + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("Htm") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("HTML") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("Xhtml") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("XHTML") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("Htm") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("Htm") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("HTML") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("Xhtml") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("XHTML") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("Htm") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build() + + // new FileParameter( + // "Htm", "text/html", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter( + // "HTML", "text/html", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter( + // "Xhtml", "text/html", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter( + // "XHTML", "text/html", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter("Htm", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter("HTML", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter("Xhtml", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter("XHTML", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + ); private static final List FILE_PARAMETERS_DEFAULT = Arrays.asList( - new FileParameter("htm"), - new FileParameter("html"), - new FileParameter("xhtml"), + /** + * No extension is required actually browser reads the content-type header of + * response from server and if that is not present then it tried to guess the + * file type based on the extension and in case content type and extensions are + * missing then browser finds it by reading the response called content + * sniffing. More information :
+ * {@link https://en.wikipedia.org/wiki/Content_sniffing}
+ * {@link + * https://stackoverflow.com/questions/2148443/does-file-extensions-matter-for-browsers} + */ + /** + * Sometimes the logic is broken in a way that it fetches fileName after {@code + * .} character if dot is not present then it returns the entire fileName and + * then compares it with valid extension list. + * + *

e.g. php code {@code + * strtolower(end(explode('.',$_FILES['image']['name'])));} + */ + new FileParameterBuilder().withFileNameAsOriginalExtension().build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withFileExtensionOperation(FileExtensionOperation.NO_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("htm") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("html") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("xhtml") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + + // new FileParameter(), + // new FileParameter("htm"), + // new FileParameter("html"), + // new FileParameter("xhtml"), /** * Server Parsed Html for server side includes * https://stackoverflow.com/questions/519619/what-is-the-purpose-and-uniqueness-shtml */ - new FileParameter("shtml"), - new FileParameter("dhtml"), - new FileParameter("htm", "text/html"), - new FileParameter("html", "text/html"), - new FileParameter("xhtml", "text/html"), - new FileParameter("shtml", "text/html"), - new FileParameter("dhtml", "text/html"), - new FileParameter("htm", "text/plain"), - new FileParameter("html", "text/plain"), - new FileParameter("xhtml", "text/plain"), - new FileParameter("shtml", "text/plain"), - new FileParameter("dhtml", "text/plain"), - new FileParameter( - "htm", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "html", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "xhtml", "text/html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter("htm", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter("html", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter("xhtml", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "htm" + NULL_BYTE_CHARACTER, - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "htm" + NULL_BYTE_CHARACTER, - "text/html", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "htm" + NULL_BYTE_CHARACTER, - "text/plain", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("dhtml") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("shtml") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + + // new FileParameter("shtml"), + // new FileParameter("dhtml"), /** - * * - * - *

As per owasp file upload use both NULL BYtes with URL encoded and decoded - * - *

we need to do the same in our code. Important. - * - *

ADD This + * The way apache server considers the file extension is: it takes the right + * most valid extension type which in this case is html. so this can bypass the + * blacklist validation of extensions. For more information {@link + * https://www.acunetix.com/websitesecurity/upload-forms-threat/#:~:text=Double%20Extensions} */ - new FileParameter( - "htm" + NULL_BYTE_CHARACTER, - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("html.123") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("htm") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("html") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("xhtml") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("shtml") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("dhtml") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("htm") + .withContentType("text/plain") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("html") + .withContentType("text/plain") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("xhtml") + .withContentType("text/plain") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("shtml") + .withContentType("text/plain") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("dhtml") + .withContentType("text/plain") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + + // new FileParameter("html.123"), + // new FileParameter("htm", "text/html"), + // new FileParameter("html", "text/html"), + // new FileParameter("xhtml", "text/html"), + // new FileParameter("shtml", "text/html"), + // new FileParameter("dhtml", "text/html"), + // new FileParameter("htm", "text/plain"), + // new FileParameter("html", "text/plain"), + // new FileParameter("xhtml", "text/plain"), + // new FileParameter("shtml", "text/plain"), + // new FileParameter("dhtml", "text/plain"), + /** + * Say original extension is {@code .gif} then this will change it to {@code + * .gif.html} If validator only validates contains {@code .gif} extension then + * validator will be bypassed. + */ + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("htm") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("html") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("xhtml") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("htm") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("html") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("xhtml") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("htm" + NULL_BYTE_CHARACTER) + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("htm" + NULL_BYTE_CHARACTER) + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("htm" + NULL_BYTE_CHARACTER) + .withContentType("text/plain") + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("htm%00") + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("htm%00") + .withContentType("text/html") + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("htm%00") + .withContentType("text/plain") + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build() + + // new FileParameter( + // "htm", "text/html", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter( + // "html", "text/html", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter( + // "xhtml", "text/html", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter("htm", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter("html", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter("xhtml", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter( + // "htm" + NULL_BYTE_CHARACTER, + // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + // new FileParameter( + // "htm" + NULL_BYTE_CHARACTER, + // "text/html", + // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + // new FileParameter( + // "htm" + NULL_BYTE_CHARACTER, + // "text/plain", + // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + // new FileParameter("htm%00", + // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + // new FileParameter( + // "htm%00", + // "text/html", + // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + // new FileParameter( + // "htm%00", + // "text/plain", + // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) /** * My thought is that if server is vulnerable to Null Byte then it is sure that - * "htm" only will work and there is no need to verify other extensions * + * "htm" only will work and there is no need to verify other extensions */ - /* - new FileParameter( - "html" + NULL_BYTE_CHARACTER, - "text/html", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "xhtml" + NULL_BYTE_CHARACTER, - "text/html", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "htm" + NULL_BYTE_CHARACTER, - "text/plain", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "html" + NULL_BYTE_CHARACTER, - "text/plain", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "xhtml" + NULL_BYTE_CHARACTER, - "text/plain", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) - */ ); /** @@ -215,7 +873,6 @@ public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) fileUploadAttackExecutor, CONTENT_MATCHER, XSS_PAYLOAD_HTML_FILE, - XSS_UPLOADED_FILE_BASE_NAME, FILE_PARAMETERS_DEFAULT); if (result) { fileUploadAttackExecutor @@ -241,7 +898,6 @@ public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) fileUploadAttackExecutor, CONTENT_MATCHER, XSS_PAYLOAD_HTML_FILE, - XSS_UPLOADED_FILE_BASE_NAME, FILE_PARAMETERS_EXTENDED); if (result) { fileUploadAttackExecutor diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/xss/SVGFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/xss/SVGFileUpload.java index 6b89cbc..32e4637 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/xss/SVGFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/xss/SVGFileUpload.java @@ -1,5 +1,5 @@ /** - * Copyright 2020 SasanLabs + * Copyright 2021 SasanLabs * *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at @@ -13,7 +13,7 @@ */ package org.sasanlabs.fileupload.attacks.xss; -import static org.sasanlabs.fileupload.Constants.NULL_BYTE_CHARACTER; +import static org.sasanlabs.fileupload.FileUploadUtils.NULL_BYTE_CHARACTER; import java.io.IOException; import java.util.Arrays; @@ -23,6 +23,7 @@ import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; import org.sasanlabs.fileupload.attacks.beans.FileParameter; +import org.sasanlabs.fileupload.attacks.beans.FileParameterBuilder; import org.sasanlabs.fileupload.exception.FileUploadException; /** @@ -48,50 +49,261 @@ public class SVGFileUpload implements AttackVector { // Extended list for breaking black-listing strategy. private static final List FILE_PARAMETERS_EXTENDED = Arrays.asList( - new FileParameter("Svg"), - new FileParameter("SvG"), - new FileParameter("SVG"), - new FileParameter("Svgz"), - new FileParameter("SvGz"), - new FileParameter("SVGZ"), - new FileParameter("xML"), - new FileParameter("Xml"), - new FileParameter("XML"), - new FileParameter("Svg", "image/svg+xml"), - new FileParameter("SvG", "image/svg+xml"), - new FileParameter("SVG", "image/svg+xml"), - new FileParameter("Svgz", "image/svg+xml"), - new FileParameter("SvGz", "image/svg+xml"), - new FileParameter("SVGZ", "image/svg+xml"), - new FileParameter("xML", "text/xml"), - new FileParameter("Xml", "text/xml"), - new FileParameter("XML", "text/xml"), - new FileParameter( - "Svg", - "image/svg+xml", - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter("Svg", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "SVG", - "image/svg+xml", - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter("SVG", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "Svgz", - "image/svg+xml", - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter("Svgz", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "SVGZ", - "image/svg+xml", - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter("SVGZ", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "Xml", "text/xml", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter("Xml", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "XML", "text/xml", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter("XML", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION)); + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("Svg") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("SvG") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("SVG") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("Svgz") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("SvGz") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("SVGZ") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("xML") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("Xml") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("XML") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("Svg") + .withContentType("image/svg+xml") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("SvG") + .withContentType("image/svg+xml") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("SVG") + .withContentType("image/svg+xml") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("Svgz") + .withContentType("image/svg+xml") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("SvGz") + .withContentType("image/svg+xml") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("SVGZ") + .withContentType("image/svg+xml") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("xML") + .withContentType("text/xml") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("Xml") + .withContentType("text/xml") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("XML") + .withContentType("text/xml") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("Svg") + .withContentType("image/svg+xml") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("SVG") + .withContentType("image/svg+xml") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("Svgz") + .withContentType("image/svg+xml") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("SVGZ") + .withContentType("image/svg+xml") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("xML") + .withContentType("text/xml") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("XML") + .withContentType("text/xml") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("Svg") + .withContentType("image/svg+xml") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("SVG") + .withContentType("image/svg+xml") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("Svgz") + .withContentType("image/svg+xml") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("SVGZ") + .withContentType("image/svg+xml") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("xML") + .withContentType("text/xml") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("XML") + .withContentType("text/xml") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build() + + // new FileParameter("Svg"), + // new FileParameter("SvG"), + // new FileParameter("SVG"), + // new FileParameter("Svgz"), + // new FileParameter("SvGz"), + // new FileParameter("SVGZ"), + // new FileParameter("xML"), + // new FileParameter("Xml"), + // new FileParameter("XML"), + // new FileParameter("Svg", "image/svg+xml"), + // new FileParameter("SvG", "image/svg+xml"), + // new FileParameter("SVG", "image/svg+xml"), + // new FileParameter("Svgz", "image/svg+xml"), + // new FileParameter("SvGz", "image/svg+xml"), + // new FileParameter("SVGZ", "image/svg+xml"), + // new FileParameter("xML", "text/xml"), + // new FileParameter("Xml", "text/xml"), + // new FileParameter("XML", "text/xml"), + // new FileParameter( + // "Svg", + // "image/svg+xml", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter("Svg", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter( + // "SVG", + // "image/svg+xml", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter("SVG", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter( + // "Svgz", + // "image/svg+xml", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter("Svgz", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter( + // "SVGZ", + // "image/svg+xml", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter("SVGZ", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter( + // "Xml", "text/xml", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter("Xml", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter( + // "XML", "text/xml", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter("XML", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + ); /** * Extensions working with SVG payload for XSS: svg,html,xml,htm,xhtml,Null byte @@ -102,25 +314,111 @@ public class SVGFileUpload implements AttackVector { */ private static final List FILE_PARAMETERS_DEFAULT = Arrays.asList( - new FileParameter("svg"), - // if html works then html file upload will only work - // new FileParameter("htm"), - // new FileParameter("html"), - new FileParameter("xml"), - new FileParameter("svgz"), - new FileParameter("svg", "image/svg+xml"), - new FileParameter("xml", "text/xml"), - new FileParameter("svgz", "image/svg+xml"), - new FileParameter("svg", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter("xml", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter("svgz", FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - new FileParameter( - "svg" + NULL_BYTE_CHARACTER, - "image/svg+xml", - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - new FileParameter( - "svg" + NULL_BYTE_CHARACTER, - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION)); + // Not adding empty extension for svg because it is not working in browsers + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("svg") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("xml") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("svgz") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("svg") + .withContentType("image/svg+xml") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("xml") + .withContentType("text/xml") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("svgz") + .withContentType("image/svg+xml") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("svg") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("xml") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("svgz") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("svg" + NULL_BYTE_CHARACTER) + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("svg" + NULL_BYTE_CHARACTER) + .withContentType("image/svg+xml") + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("svg%00") + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + .withExtension("svg%00") + .withContentType("image/svg+xml") + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build() + + // new FileParameter("svg"), + // new FileParameter("xml"), + // new FileParameter("svgz"), + // new FileParameter("svg", "image/svg+xml"), + // new FileParameter("xml", "text/xml"), + // new FileParameter("svgz", "image/svg+xml"), + // new FileParameter("svg", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter("xml", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter("svgz", + // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), + // new FileParameter( + // "svg" + NULL_BYTE_CHARACTER, + // "image/svg+xml", + // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), + // new FileParameter( + // "svg" + NULL_BYTE_CHARACTER, + // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + ); /** * @throws FileUploadException @@ -136,7 +434,6 @@ public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) fileUploadAttackExecutor, HtmlFileUpload.CONTENT_MATCHER, XSS_PAYLOAD_SVG_FILE, - XSS_UPLOADED_FILE_BASE_NAME, FILE_PARAMETERS_DEFAULT); if (result) { fileUploadAttackExecutor @@ -162,7 +459,6 @@ public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) fileUploadAttackExecutor, HtmlFileUpload.CONTENT_MATCHER, XSS_PAYLOAD_SVG_FILE, - XSS_UPLOADED_FILE_BASE_NAME, FILE_PARAMETERS_EXTENDED); if (result) { fileUploadAttackExecutor diff --git a/src/main/java/org/sasanlabs/fileupload/configuration/FileUploadConfiguration.java b/src/main/java/org/sasanlabs/fileupload/configuration/FileUploadConfiguration.java index 639878e..3a649c9 100644 --- a/src/main/java/org/sasanlabs/fileupload/configuration/FileUploadConfiguration.java +++ b/src/main/java/org/sasanlabs/fileupload/configuration/FileUploadConfiguration.java @@ -1,5 +1,5 @@ /** - * Copyright 2020 SasanLabs + * Copyright 2021 SasanLabs * *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at diff --git a/src/main/java/org/sasanlabs/fileupload/exception/FileUploadException.java b/src/main/java/org/sasanlabs/fileupload/exception/FileUploadException.java index 642a90d..2d8c53c 100644 --- a/src/main/java/org/sasanlabs/fileupload/exception/FileUploadException.java +++ b/src/main/java/org/sasanlabs/fileupload/exception/FileUploadException.java @@ -1,5 +1,5 @@ /** - * Copyright 2020 SasanLabs + * Copyright 2021 SasanLabs * *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at diff --git a/src/main/java/org/sasanlabs/fileupload/function/ConsumerWithException.java b/src/main/java/org/sasanlabs/fileupload/function/ConsumerWithException.java index df9e831..dfc0bae 100644 --- a/src/main/java/org/sasanlabs/fileupload/function/ConsumerWithException.java +++ b/src/main/java/org/sasanlabs/fileupload/function/ConsumerWithException.java @@ -1,5 +1,5 @@ /** - * Copyright 2020 SasanLabs + * Copyright 2021 SasanLabs * *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at diff --git a/src/main/java/org/sasanlabs/fileupload/i18n/FileUploadI18n.java b/src/main/java/org/sasanlabs/fileupload/i18n/FileUploadI18n.java index d555ba6..aa8a6fb 100644 --- a/src/main/java/org/sasanlabs/fileupload/i18n/FileUploadI18n.java +++ b/src/main/java/org/sasanlabs/fileupload/i18n/FileUploadI18n.java @@ -1,5 +1,5 @@ /** - * Copyright 2020 SasanLabs + * Copyright 2021 SasanLabs * *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at diff --git a/src/main/java/org/sasanlabs/fileupload/locator/URILocator.java b/src/main/java/org/sasanlabs/fileupload/locator/URILocator.java index b8af491..b34508c 100644 --- a/src/main/java/org/sasanlabs/fileupload/locator/URILocator.java +++ b/src/main/java/org/sasanlabs/fileupload/locator/URILocator.java @@ -1,5 +1,5 @@ /** - * Copyright 2020 SasanLabs + * Copyright 2021 SasanLabs * *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at diff --git a/src/main/java/org/sasanlabs/fileupload/locator/URILocatorImpl.java b/src/main/java/org/sasanlabs/fileupload/locator/URILocatorImpl.java index 974e393..abaa4ad 100644 --- a/src/main/java/org/sasanlabs/fileupload/locator/URILocatorImpl.java +++ b/src/main/java/org/sasanlabs/fileupload/locator/URILocatorImpl.java @@ -1,5 +1,5 @@ /** - * Copyright 2020 SasanLabs + * Copyright 2021 SasanLabs * *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at @@ -22,7 +22,7 @@ import org.apache.commons.text.StringSubstitutor; import org.apache.log4j.Logger; import org.parosproxy.paros.network.HttpMessage; -import org.sasanlabs.fileupload.Constants; +import org.sasanlabs.fileupload.FileUploadUtils; import org.sasanlabs.fileupload.configuration.FileUploadConfiguration; import org.sasanlabs.fileupload.exception.FileUploadException; import org.sasanlabs.fileupload.function.ConsumerWithException; @@ -34,17 +34,17 @@ public class URILocatorImpl implements URILocator { private URI getCompleteURI(String uriRegex, String fileName, HttpMessage msg) throws URIException, FileUploadException { - if (fileName.contains(Constants.NULL_BYTE_CHARACTER)) { - fileName = fileName.substring(0, fileName.indexOf(Constants.NULL_BYTE_CHARACTER)); + if (fileName.contains(FileUploadUtils.NULL_BYTE_CHARACTER)) { + fileName = fileName.substring(0, fileName.indexOf(FileUploadUtils.NULL_BYTE_CHARACTER)); } Map replacerKeyValuePair = new HashMap<>(); replacerKeyValuePair.put("filename", fileName); StringSubstitutor stringSubstitutor = new StringSubstitutor(replacerKeyValuePair); String uriFragment = stringSubstitutor.replace(uriRegex); - if (uriFragment.startsWith(Constants.HTTP_SCHEME) - || uriRegex.startsWith(Constants.HTTP_SECURED_SCHEME)) { + if (uriFragment.startsWith(FileUploadUtils.HTTP_SCHEME) + || uriRegex.startsWith(FileUploadUtils.HTTP_SECURED_SCHEME)) { return new URI(uriFragment, true); - } else if (uriFragment.startsWith(Constants.SLASH)) { + } else if (uriFragment.startsWith(FileUploadUtils.SLASH)) { String authority = msg.getRequestHeader().getURI().getAuthority(); String scheme = msg.getRequestHeader().getURI().getScheme(); return new URI(scheme, authority, uriFragment, ""); diff --git a/src/main/java/org/sasanlabs/fileupload/matcher/ContentMatcher.java b/src/main/java/org/sasanlabs/fileupload/matcher/ContentMatcher.java index 4c659ec..89c29c3 100644 --- a/src/main/java/org/sasanlabs/fileupload/matcher/ContentMatcher.java +++ b/src/main/java/org/sasanlabs/fileupload/matcher/ContentMatcher.java @@ -1,5 +1,5 @@ /** - * Copyright 2020 SasanLabs + * Copyright 2021 SasanLabs * *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at diff --git a/src/main/java/org/sasanlabs/fileupload/matcher/impl/ContainsExpectedValueMatcher.java b/src/main/java/org/sasanlabs/fileupload/matcher/impl/ContainsExpectedValueMatcher.java index 7f6112d..3656d26 100644 --- a/src/main/java/org/sasanlabs/fileupload/matcher/impl/ContainsExpectedValueMatcher.java +++ b/src/main/java/org/sasanlabs/fileupload/matcher/impl/ContainsExpectedValueMatcher.java @@ -1,5 +1,5 @@ /** - * Copyright 2020 SasanLabs + * Copyright 2021 SasanLabs * *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at diff --git a/src/main/java/org/sasanlabs/fileupload/matcher/impl/MD5HashResponseMatcher.java b/src/main/java/org/sasanlabs/fileupload/matcher/impl/MD5HashResponseMatcher.java index a89c7a2..42cc057 100644 --- a/src/main/java/org/sasanlabs/fileupload/matcher/impl/MD5HashResponseMatcher.java +++ b/src/main/java/org/sasanlabs/fileupload/matcher/impl/MD5HashResponseMatcher.java @@ -1,5 +1,5 @@ /** - * Copyright 2020 SasanLabs + * Copyright 2021 SasanLabs * *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at diff --git a/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java b/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java index dffc134..d7f3edd 100644 --- a/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java +++ b/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java @@ -1,5 +1,5 @@ /** - * Copyright 2020 SasanLabs + * Copyright 2021 SasanLabs * *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at From 5fe76bc26d66d106902f54a50f85f5824b9908d2 Mon Sep 17 00:00:00 2001 From: karan preet singh sasan Date: Sat, 2 Jan 2021 01:51:29 +0530 Subject: [PATCH 15/53] Few more --- .../attacks/FileUploadAttackExecutor.java | 12 +- .../jsp/ImageBasedJSPRemoteCodeExecution.java | 150 ----------- .../jsp/ImageWithJSPSnippetFileUpload.java | 232 ++++++++++++++++++ ...xecution.java => SimpleJSPFileUpload.java} | 119 +++++++-- ...ecution.java => SimpleJSPXFileUpload.java} | 110 +++++++-- .../attacks/xss/HtmlFileUpload.java | 138 +---------- .../fileupload/attacks/xss/SVGFileUpload.java | 79 +----- .../attackvectors/images/1*1_Default.gif | Bin 37 -> 43 bytes .../attackvectors/images/1*1_Default.jpeg | Bin 0 -> 631 bytes .../images/1*1_Default_JSP_Injected_EXIF.gif | Bin 79 -> 0 bytes .../attackvectors/images/1*1_JSP_Appended.gif | Bin 0 -> 117 bytes .../images/1*1_JSP_Appended.jpeg | Bin 0 -> 705 bytes .../images/1*1_JSP_EXIF_Comment.gif | Bin 0 -> 120 bytes .../images/1*1_JSP_EXIF_Comment.jpeg | Bin 0 -> 708 bytes 14 files changed, 423 insertions(+), 417 deletions(-) delete mode 100644 src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageBasedJSPRemoteCodeExecution.java create mode 100644 src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageWithJSPSnippetFileUpload.java rename src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/{PlainOldJSPRemoteCodeExecution.java => SimpleJSPFileUpload.java} (53%) rename src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/{PlainOldJSPXRemoteCodeExecution.java => SimpleJSPXFileUpload.java} (57%) create mode 100644 src/main/resources/org/sasanlabs/attackvectors/images/1*1_Default.jpeg delete mode 100644 src/main/resources/org/sasanlabs/attackvectors/images/1*1_Default_JSP_Injected_EXIF.gif create mode 100644 src/main/resources/org/sasanlabs/attackvectors/images/1*1_JSP_Appended.gif create mode 100644 src/main/resources/org/sasanlabs/attackvectors/images/1*1_JSP_Appended.jpeg create mode 100644 src/main/resources/org/sasanlabs/attackvectors/images/1*1_JSP_EXIF_Comment.gif create mode 100644 src/main/resources/org/sasanlabs/attackvectors/images/1*1_JSP_EXIF_Comment.jpeg diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java b/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java index df91fb1..060ef98 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java @@ -18,9 +18,9 @@ import org.parosproxy.paros.core.scanner.Variant; import org.parosproxy.paros.network.HttpMessage; import org.sasanlabs.fileupload.FileUploadScanRule; -import org.sasanlabs.fileupload.attacks.rce.jsp.ImageBasedJSPRemoteCodeExecution; -import org.sasanlabs.fileupload.attacks.rce.jsp.PlainOldJSPRemoteCodeExecution; -import org.sasanlabs.fileupload.attacks.rce.jsp.PlainOldJSPXRemoteCodeExecution; +import org.sasanlabs.fileupload.attacks.rce.jsp.ImageWithJSPSnippetFileUpload; +import org.sasanlabs.fileupload.attacks.rce.jsp.SimpleJSPFileUpload; +import org.sasanlabs.fileupload.attacks.rce.jsp.SimpleJSPXFileUpload; import org.sasanlabs.fileupload.attacks.xss.HtmlFileUpload; import org.sasanlabs.fileupload.exception.FileUploadException; @@ -38,9 +38,9 @@ public class FileUploadAttackExecutor { private List attackVectors = Arrays.asList( new HtmlFileUpload(), - new PlainOldJSPRemoteCodeExecution(), - new PlainOldJSPXRemoteCodeExecution(), - new ImageBasedJSPRemoteCodeExecution()); + new SimpleJSPFileUpload(), + new SimpleJSPXFileUpload(), + new ImageWithJSPSnippetFileUpload()); public FileUploadAttackExecutor( HttpMessage originalHttpMessage, diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageBasedJSPRemoteCodeExecution.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageBasedJSPRemoteCodeExecution.java deleted file mode 100644 index 381ca2d..0000000 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageBasedJSPRemoteCodeExecution.java +++ /dev/null @@ -1,150 +0,0 @@ -/** - * Copyright 2021 SasanLabs - * - *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of the License at - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sasanlabs.fileupload.attacks.rce.jsp; - -import static org.sasanlabs.fileupload.FileUploadUtils.NULL_BYTE_CHARACTER; - -import java.io.IOException; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.Base64; -import java.util.List; -import org.parosproxy.paros.network.HttpMessage; -import org.sasanlabs.fileupload.attacks.AttackVector; -import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; -import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; -import org.sasanlabs.fileupload.attacks.beans.FileParameter; -import org.sasanlabs.fileupload.attacks.beans.FileParameterBuilder; -import org.sasanlabs.fileupload.exception.FileUploadException; -import org.sasanlabs.fileupload.matcher.impl.ContainsExpectedValueMatcher; - -/** @author preetkaran20@gmail.com KSASAN */ -public class ImageBasedJSPRemoteCodeExecution implements AttackVector { - - private static final String GIF_IMAGE_JSP_INJECTED_IN_EXIF_BASE64_ENCODED = - "R0lGODlhAQABAHAAACH5BAUAAAAAIf4mPCU9ICJTYXNhbkxhYnNfIiArICJaQVBfSWRlbnRpZmllciIgJT4ALAAAAAABAAEAAAICRAEAOw=="; - // Need to correct expected value these - private static final String EXPECTED_VALUE = "SasanLabs_ZAP_Identifier"; - private static final String BASE_FILE_NAME = "ImageBasedJSPRCE_"; - - private static final List FILE_PARAMETERS = - Arrays.asList( - new FileParameterBuilder() - .withBaseFileName(BASE_FILE_NAME) - .withExtension("jsp") - .withFileExtensionOperation( - FileExtensionOperation.ONLY_PROVIDED_EXTENSION) - .build(), - new FileParameterBuilder() - .withBaseFileName(BASE_FILE_NAME) - .withExtension("jsp") - .withContentType("application/x-jsp") - .withFileExtensionOperation( - FileExtensionOperation.ONLY_PROVIDED_EXTENSION) - .build(), - new FileParameterBuilder() - .withBaseFileName(BASE_FILE_NAME) - .withExtension("jsp") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder() - .withBaseFileName(BASE_FILE_NAME) - .withExtension("jsp") - .withContentType("application/x-jsp") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder() - .withBaseFileName(BASE_FILE_NAME) - .withExtension("jsp" + NULL_BYTE_CHARACTER) - .withFileExtensionOperation( - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder() - .withBaseFileName(BASE_FILE_NAME) - .withExtension("jsp" + NULL_BYTE_CHARACTER) - .withContentType("application/x-jsp") - .withFileExtensionOperation( - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder() - .withBaseFileName(BASE_FILE_NAME) - .withExtension("jsp%00") - .withFileExtensionOperation( - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder() - .withBaseFileName(BASE_FILE_NAME) - .withExtension("jsp%00") - .withContentType("application/x-jsp") - .withFileExtensionOperation( - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) - .build() - - // new FileParameter("jsp"), - // new FileParameter("jsp", "application/x-jsp"), - // new FileParameter("jsp", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter( - // "jsp", - // "application/x-jsp", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter( - // "jsp" + NULL_BYTE_CHARACTER, - // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - // new FileParameter( - // "jsp" + NULL_BYTE_CHARACTER, - // "application/x-jsp", - // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) - ); - - @Override - public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) - throws FileUploadException { - try { - byte[] imagePayload = - Base64.getDecoder().decode(GIF_IMAGE_JSP_INJECTED_IN_EXIF_BASE64_ENCODED); - HttpMessage originalMessage = fileUploadAttackExecutor.getOriginalHttpMessage(); - String charSet = originalMessage.getRequestHeader().getCharset(); - Charset requestCharSet = - charSet != null ? Charset.forName(charSet) : StandardCharsets.ISO_8859_1; - String requestPayload = new String(imagePayload, requestCharSet); - System.out.print(charSet); - if (this.genericAttackExecutor( - fileUploadAttackExecutor, - new ContainsExpectedValueMatcher(EXPECTED_VALUE), - requestPayload, - FILE_PARAMETERS)) { - fileUploadAttackExecutor - .getFileUploadScanRule() - .raiseAlert( - 1, - 1, - this.getClass().getName(), - "", - "", - "", - "", - "", - "", - fileUploadAttackExecutor.getOriginalHttpMessage()); - } - } catch (IOException e) { - throw new FileUploadException(e); - } - return false; - } -} diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageWithJSPSnippetFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageWithJSPSnippetFileUpload.java new file mode 100644 index 0000000..2834a64 --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageWithJSPSnippetFileUpload.java @@ -0,0 +1,232 @@ +/** + * Copyright 2021 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sasanlabs.fileupload.attacks.rce.jsp; + +import static org.sasanlabs.fileupload.FileUploadUtils.NULL_BYTE_CHARACTER; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Base64; +import java.util.List; +import org.parosproxy.paros.core.scanner.Plugin.AttackStrength; +import org.parosproxy.paros.network.HttpMessage; +import org.sasanlabs.fileupload.attacks.AttackVector; +import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; +import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; +import org.sasanlabs.fileupload.attacks.beans.FileParameter; +import org.sasanlabs.fileupload.attacks.beans.FileParameterBuilder; +import org.sasanlabs.fileupload.exception.FileUploadException; +import org.sasanlabs.fileupload.matcher.impl.ContainsExpectedValueMatcher; + +/** @author preetkaran20@gmail.com KSASAN */ +public class ImageWithJSPSnippetFileUpload implements AttackVector { + + private static final String GIF_IMAGE_JSP_INJECTED_IN_EXIF_BASE64_ENCODED = + "R0lGODlhAQABAIAAAP///wAAACH5BAAAAAAAIf5JPCU9ICJJbWFnZVdpdGhKU1BTbmlwcGV0RmlsZVVwbG9hZF8iICsgIlNhc2FuTGFic18iICsgIlpBUF9JZGVudGlmaWVyIiAlPgAsAAAAAAEAAQAAAgJEAQA7"; + private static final String GIF_IMAGE_APPENDED_WITH_JSP_SNIPPET_BASE64_ENCODED = + "R0lGODlhAQABAIAAAP///wAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOzwlPSAiSW1hZ2VXaXRoSlNQU25pcHBldEZpbGVVcGxvYWRfIiArICJTYXNhbkxhYnNfIiArICJaQVBfSWRlbnRpZmllciIgJT4K"; + + // As JPEG is most widely used format for images hence in case application is specifically + // looking for JPEG magic numbers then this below configuration can help + private static final String JPEG_IMAGE_JSP_INJECTED_IN_EXIF_BASE64_ENCODED = + "/9j/4AAQSkZJRgABAQEAYABgAAD//gBLPCU9ICJJbWFnZVdpdGhKU1BTbmlwcGV0RmlsZVVwbG9hZF8iICsgIlNhc2FuTGFic18iICsgIlpBUF9JZGVudGlmaWVyIiAlPv/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicgIiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAAEAAQMBIgACEQEDEQH/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2gAMAwEAAhEDEQA/APf6KKKAP//Z"; + private static final String JPEG_IMAGE_APPENDED_WITH_JSP_SNIPPET_BASE64_ENCODED = + "/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAABAAEDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD3+iiigD//2TwlPSAiSW1hZ2VXaXRoSlNQU25pcHBldEZpbGVVcGxvYWRfIiArICJTYXNhbkxhYnNfIiArICJaQVBfSWRlbnRpZmllciIgJT4K"; + + private static final String FILE_EXPECTED_VALUE = + "ImageWithJSPSnippetFileUpload_SasanLabs_ZAP_Identifier"; + + private static final String BASE_FILE_NAME = "ImageWithJSPSnippetFileUpload_"; + + private static final List PAYLOADS = + Arrays.asList( + GIF_IMAGE_JSP_INJECTED_IN_EXIF_BASE64_ENCODED, + GIF_IMAGE_APPENDED_WITH_JSP_SNIPPET_BASE64_ENCODED, + JPEG_IMAGE_JSP_INJECTED_IN_EXIF_BASE64_ENCODED, + JPEG_IMAGE_APPENDED_WITH_JSP_SNIPPET_BASE64_ENCODED); + + private static final List FILE_PARAMETERS_EXTENDED = + Arrays.asList( + new FileParameterBuilder() + .withBaseFileName(BASE_FILE_NAME) + .withExtension("Jsp") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(BASE_FILE_NAME) + .withExtension("JSP") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(BASE_FILE_NAME) + .withExtension("Jsp") + .withContentType("application/x-jsp") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(BASE_FILE_NAME) + .withExtension("JSP") + .withContentType("application/x-jsp") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(BASE_FILE_NAME) + .withExtension("Jsp") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(BASE_FILE_NAME) + .withExtension("JSP") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(BASE_FILE_NAME) + .withExtension("Jsp") + .withContentType("application/x-jsp") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(BASE_FILE_NAME) + .withExtension("JSP") + .withContentType("application/x-jsp") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build()); + + private static final List FILE_PARAMETERS_DEFAULT = + Arrays.asList( + new FileParameterBuilder() + .withBaseFileName(BASE_FILE_NAME) + .withExtension("jsp") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(BASE_FILE_NAME) + .withExtension("jsp") + .withContentType("application/x-jsp") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(BASE_FILE_NAME) + .withExtension("jsp") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(BASE_FILE_NAME) + .withExtension("jsp") + .withContentType("application/x-jsp") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(BASE_FILE_NAME) + .withExtension("jsp" + NULL_BYTE_CHARACTER) + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(BASE_FILE_NAME) + .withExtension("jsp" + NULL_BYTE_CHARACTER) + .withContentType("application/x-jsp") + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(BASE_FILE_NAME) + .withExtension("jsp%00") + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(BASE_FILE_NAME) + .withExtension("jsp%00") + .withContentType("application/x-jsp") + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build()); + + @Override + public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) + throws FileUploadException { + for (String payloads : PAYLOADS) { + try { + byte[] imagePayload = Base64.getDecoder().decode(payloads); + HttpMessage originalMessage = fileUploadAttackExecutor.getOriginalHttpMessage(); + String charSet = originalMessage.getRequestHeader().getCharset(); + Charset requestCharSet = + charSet != null ? Charset.forName(charSet) : StandardCharsets.ISO_8859_1; + String requestPayload = new String(imagePayload, requestCharSet); + if (this.genericAttackExecutor( + fileUploadAttackExecutor, + new ContainsExpectedValueMatcher(FILE_EXPECTED_VALUE), + requestPayload, + FILE_PARAMETERS_DEFAULT)) { + fileUploadAttackExecutor + .getFileUploadScanRule() + .raiseAlert( + 1, + 1, + this.getClass().getName(), + "", + "", + "", + "", + "", + "", + fileUploadAttackExecutor.getOriginalHttpMessage()); + } else { + if (fileUploadAttackExecutor + .getFileUploadScanRule() + .getAttackStrength() + .equals(AttackStrength.INSANE)) { + if (this.genericAttackExecutor( + fileUploadAttackExecutor, + new ContainsExpectedValueMatcher(FILE_EXPECTED_VALUE), + requestPayload, + FILE_PARAMETERS_EXTENDED)) { + fileUploadAttackExecutor + .getFileUploadScanRule() + .raiseAlert( + 1, + 1, + "", + "", + "", + "", + "", + "", + "", + fileUploadAttackExecutor.getOriginalHttpMessage()); + } + } + } + } catch (IOException e) { + throw new FileUploadException(e); + } + } + return false; + } +} diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/PlainOldJSPRemoteCodeExecution.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPFileUpload.java similarity index 53% rename from src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/PlainOldJSPRemoteCodeExecution.java rename to src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPFileUpload.java index e56fe1d..b774c33 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/PlainOldJSPRemoteCodeExecution.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPFileUpload.java @@ -18,6 +18,7 @@ import java.io.IOException; import java.util.Arrays; import java.util.List; +import org.parosproxy.paros.core.scanner.Plugin.AttackStrength; import org.sasanlabs.fileupload.attacks.AttackVector; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; @@ -31,16 +32,75 @@ // TODO check if we need to have case sensitive extensions like JsP or jSP or hTML or HtmL or hTmL // etc -public class PlainOldJSPRemoteCodeExecution implements AttackVector { +public class SimpleJSPFileUpload implements AttackVector { - private static final String JSP_UPLOADED_FILE_BASE_NAME = "PlainOldJSPRemoteCodeExecution_"; + private static final String JSP_UPLOADED_FILE_BASE_NAME = "SimpleJSPFileUpload_"; + /** + * using tag based attack too here. e.g. "${'InJeCtTe'}" _jsp_gen_payload_expression_lang in + * burp extension + */ private static final String JSP_PAYLOAD = - "<% out.print(\"PlainOldJSPRemoteCodeExecution\"); out.print(\"_SasanLabs_ZAP_Identifier\"); %>"; + "<% out.print(\"SimpleJSPFileUpload\"); out.print(\"_SasanLabs_ZAP_Identifier\"); %>"; private static final ContentMatcher CONTENT_MATCHER = - new MD5HashResponseMatcher("PlainOldJSPRemoteCodeExecution_SasanLabs_ZAP_Identifier"); + new MD5HashResponseMatcher("SimpleJSPFileUpload_SasanLabs_ZAP_Identifier"); - private static final List FILE_PARAMETERS = + private static final List FILE_PARAMETERS_EXTENDED = + Arrays.asList( + new FileParameterBuilder() + .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + .withExtension("Jsp") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + .withExtension("JSP") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + .withExtension("Jsp") + .withContentType("application/x-jsp") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + .withExtension("JSP") + .withContentType("application/x-jsp") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + .withExtension("Jsp") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + .withExtension("JSP") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + .withExtension("Jsp") + .withContentType("application/x-jsp") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + .withExtension("JSP") + .withContentType("application/x-jsp") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build()); + + private static final List FILE_PARAMETERS_DEFAULT = Arrays.asList( new FileParameterBuilder() .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) @@ -93,25 +153,7 @@ public class PlainOldJSPRemoteCodeExecution implements AttackVector { .withContentType("application/x-jsp") .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) - .build() - - // - // new FileParameter("jsp"), - // new FileParameter("jsp", "application/x-jsp"), - // new FileParameter("jsp", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter( - // "jsp", - // "application/x-jsp", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter( - // "jsp" + NULL_BYTE_CHARACTER, - // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - // new FileParameter( - // "jsp" + NULL_BYTE_CHARACTER, - // "application/x-jsp", - // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) - ); + .build()); @Override public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) @@ -123,7 +165,7 @@ public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) fileUploadAttackExecutor, CONTENT_MATCHER, JSP_PAYLOAD, - FILE_PARAMETERS); + FILE_PARAMETERS_DEFAULT); if (result) { fileUploadAttackExecutor .getFileUploadScanRule() @@ -138,6 +180,33 @@ public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) "", "", fileUploadAttackExecutor.getOriginalHttpMessage()); + } else { + if (fileUploadAttackExecutor + .getFileUploadScanRule() + .getAttackStrength() + .equals(AttackStrength.INSANE)) { + result = + this.genericAttackExecutor( + fileUploadAttackExecutor, + CONTENT_MATCHER, + JSP_PAYLOAD, + FILE_PARAMETERS_EXTENDED); + if (result) { + fileUploadAttackExecutor + .getFileUploadScanRule() + .raiseAlert( + 1, + 1, + "", + "", + "", + "", + "", + "", + "", + fileUploadAttackExecutor.getOriginalHttpMessage()); + } + } } } catch (IOException e) { throw new FileUploadException(e); diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/PlainOldJSPXRemoteCodeExecution.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPXFileUpload.java similarity index 57% rename from src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/PlainOldJSPXRemoteCodeExecution.java rename to src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPXFileUpload.java index 87dd425..05150e0 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/PlainOldJSPXRemoteCodeExecution.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPXFileUpload.java @@ -18,6 +18,7 @@ import java.io.IOException; import java.util.Arrays; import java.util.List; +import org.parosproxy.paros.core.scanner.Plugin.AttackStrength; import org.sasanlabs.fileupload.attacks.AttackVector; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; @@ -28,21 +29,76 @@ import org.sasanlabs.fileupload.matcher.impl.MD5HashResponseMatcher; /** @author KSASAN preetkaran20@gmail.com */ -public class PlainOldJSPXRemoteCodeExecution implements AttackVector { +public class SimpleJSPXFileUpload implements AttackVector { - private static final String JSPX_UPLOADED_FILE_BASE_NAME = "PlainOldJSPXRemoteCodeExecution_"; + private static final String JSPX_UPLOADED_FILE_BASE_NAME = "SimpleJSPXFileUpload_"; // Payload from resource file: "jspx_payload.jspx" private static final String JSPX_PAYLOAD = " \n" + " \n" + " \n" - + " out.print(\"PlainOldJSPXRemoteCodeExecution_\"); \n" + + " out.print(\"SimpleJSPXFileUpload_\"); \n" + " out.print(\"SasanLabs_ZAP_Identifier\");" + " \n" + ""; private static final ContentMatcher CONTENT_MATCHER = - new MD5HashResponseMatcher("PlainOldJSPXRemoteCodeExecution_SasanLabs_ZAP_Identifier"); + new MD5HashResponseMatcher("SimpleJSPXFileUpload_SasanLabs_ZAP_Identifier"); + + private static final List FILE_PARAMETERS_EXTENDED = + Arrays.asList( + new FileParameterBuilder() + .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + .withExtension("JspX") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + .withExtension("JSPX") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + .withExtension("JspX") + .withContentType("application/x-jsp") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + .withExtension("JSPX") + .withContentType("application/x-jsp") + .withFileExtensionOperation( + FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + .withExtension("JspX") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + .withExtension("JSPX") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + .withExtension("JspX") + .withContentType("application/x-jsp") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileParameterBuilder() + .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + .withExtension("JSPX") + .withContentType("application/x-jsp") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build()); // Need to validate // application/x-httpd-jsp @@ -100,24 +156,7 @@ public class PlainOldJSPXRemoteCodeExecution implements AttackVector { .withContentType("application/x-jsp") .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) - .build() - - // new FileParameter("jspx"), - // new FileParameter("jspx", "application/x-jsp"), - // new FileParameter("jspx", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter( - // "jspx", - // "application/x-jsp", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter( - // "jspx" + NULL_BYTE_CHARACTER, - // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - // new FileParameter( - // "jspx" + NULL_BYTE_CHARACTER, - // "application/x-jsp", - // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) - ); + .build()); @Override public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) @@ -144,6 +183,33 @@ public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) "", "", fileUploadAttackExecutor.getOriginalHttpMessage()); + } else { + if (fileUploadAttackExecutor + .getFileUploadScanRule() + .getAttackStrength() + .equals(AttackStrength.INSANE)) { + result = + this.genericAttackExecutor( + fileUploadAttackExecutor, + CONTENT_MATCHER, + JSPX_PAYLOAD, + FILE_PARAMETERS_EXTENDED); + if (result) { + fileUploadAttackExecutor + .getFileUploadScanRule() + .raiseAlert( + 1, + 1, + "", + "", + "", + "", + "", + "", + "", + fileUploadAttackExecutor.getOriginalHttpMessage()); + } + } } } catch (IOException e) { throw new FileUploadException(e); diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java index df0dc56..69a959c 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java @@ -426,62 +426,6 @@ public class HtmlFileUpload implements AttackVector { .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - - // new FileParameter("Htm"), - // new FileParameter("hTM"), - // new FileParameter("HTM"), - // new FileParameter("Html"), - // new FileParameter("HtMl"), - // new FileParameter("HTMl"), - // new FileParameter("HTML"), - // new FileParameter("Xhtml"), - // new FileParameter("xHTml"), - // new FileParameter("xhTML"), - // new FileParameter("xHTML"), - // new FileParameter("XHTML"), - // new FileParameter("dHtml"), - // new FileParameter("sHtml"), - // new FileParameter("dHTml"), - // new FileParameter("sHTml"), - // new FileParameter("dHTML"), - // new FileParameter("sHTML"), - // new FileParameter("Htm", "text/html"), - // new FileParameter("hTM", "text/html"), - // new FileParameter("HTM", "text/html"), - // new FileParameter("Html", "text/html"), - // new FileParameter("HtMl", "text/html"), - // new FileParameter("HTMl", "text/html"), - // new FileParameter("HTML", "text/html"), - // new FileParameter("Xhtml", "text/html"), - // new FileParameter("xHTml", "text/html"), - // new FileParameter("xhTML", "text/html"), - // new FileParameter("xHTML", "text/html"), - // new FileParameter("XHTML", "text/html"), - // new FileParameter("dHtml", "text/html"), - // new FileParameter("sHtml", "text/html"), - // new FileParameter("dHTml", "text/html"), - // new FileParameter("sHTml", "text/html"), - // new FileParameter("dHTML", "text/html"), - // new FileParameter("sHTML", "text/html"), - // new FileParameter("Htm", "text/plain"), - // new FileParameter("hTM", "text/plain"), - // new FileParameter("HTM", "text/plain"), - // new FileParameter("Html", "text/plain"), - // new FileParameter("HtMl", "text/plain"), - // new FileParameter("HTMl", "text/plain"), - // new FileParameter("HTML", "text/plain"), - // new FileParameter("Xhtml", "text/plain"), - // new FileParameter("xHTml", "text/plain"), - // new FileParameter("xhTML", "text/plain"), - // new FileParameter("xHTML", "text/plain"), - // new FileParameter("XHTML", "text/plain"), - // new FileParameter("dHtml", "text/plain"), - // new FileParameter("sHtml", "text/plain"), - // new FileParameter("dHTml", "text/plain"), - // new FileParameter("sHTml", "text/plain"), - // new FileParameter("dHTML", "text/plain"), - // new FileParameter("sHTML", "text/plain"), - new FileParameterBuilder() .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Htm") @@ -546,29 +490,7 @@ public class HtmlFileUpload implements AttackVector { .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build() - - // new FileParameter( - // "Htm", "text/html", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter( - // "HTML", "text/html", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter( - // "Xhtml", "text/html", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter( - // "XHTML", "text/html", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter("Htm", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter("HTML", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter("Xhtml", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter("XHTML", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - ); + .build()); private static final List FILE_PARAMETERS_DEFAULT = Arrays.asList( @@ -613,11 +535,6 @@ public class HtmlFileUpload implements AttackVector { .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - - // new FileParameter(), - // new FileParameter("htm"), - // new FileParameter("html"), - // new FileParameter("xhtml"), /** * Server Parsed Html for server side includes * https://stackoverflow.com/questions/519619/what-is-the-purpose-and-uniqueness-shtml @@ -634,9 +551,6 @@ public class HtmlFileUpload implements AttackVector { .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - - // new FileParameter("shtml"), - // new FileParameter("dhtml"), /** * The way apache server considers the file extension is: it takes the right * most valid extension type which in this case is html. so this can bypass the @@ -719,18 +633,6 @@ public class HtmlFileUpload implements AttackVector { .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - - // new FileParameter("html.123"), - // new FileParameter("htm", "text/html"), - // new FileParameter("html", "text/html"), - // new FileParameter("xhtml", "text/html"), - // new FileParameter("shtml", "text/html"), - // new FileParameter("dhtml", "text/html"), - // new FileParameter("htm", "text/plain"), - // new FileParameter("html", "text/plain"), - // new FileParameter("xhtml", "text/plain"), - // new FileParameter("shtml", "text/plain"), - // new FileParameter("dhtml", "text/plain"), /** * Say original extension is {@code .gif} then this will change it to {@code * .gif.html} If validator only validates contains {@code .gif} extension then @@ -815,44 +717,6 @@ public class HtmlFileUpload implements AttackVector { .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) .build() - - // new FileParameter( - // "htm", "text/html", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter( - // "html", "text/html", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter( - // "xhtml", "text/html", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter("htm", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter("html", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter("xhtml", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter( - // "htm" + NULL_BYTE_CHARACTER, - // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - // new FileParameter( - // "htm" + NULL_BYTE_CHARACTER, - // "text/html", - // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - // new FileParameter( - // "htm" + NULL_BYTE_CHARACTER, - // "text/plain", - // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - // new FileParameter("htm%00", - // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - // new FileParameter( - // "htm%00", - // "text/html", - // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - // new FileParameter( - // "htm%00", - // "text/plain", - // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) - /** * My thought is that if server is vulnerable to Null Byte then it is sure that * "htm" only will work and there is no need to verify other extensions diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/xss/SVGFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/xss/SVGFileUpload.java index 32e4637..87eafc7 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/xss/SVGFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/xss/SVGFileUpload.java @@ -249,61 +249,7 @@ public class SVGFileUpload implements AttackVector { .withContentType("text/xml") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build() - - // new FileParameter("Svg"), - // new FileParameter("SvG"), - // new FileParameter("SVG"), - // new FileParameter("Svgz"), - // new FileParameter("SvGz"), - // new FileParameter("SVGZ"), - // new FileParameter("xML"), - // new FileParameter("Xml"), - // new FileParameter("XML"), - // new FileParameter("Svg", "image/svg+xml"), - // new FileParameter("SvG", "image/svg+xml"), - // new FileParameter("SVG", "image/svg+xml"), - // new FileParameter("Svgz", "image/svg+xml"), - // new FileParameter("SvGz", "image/svg+xml"), - // new FileParameter("SVGZ", "image/svg+xml"), - // new FileParameter("xML", "text/xml"), - // new FileParameter("Xml", "text/xml"), - // new FileParameter("XML", "text/xml"), - // new FileParameter( - // "Svg", - // "image/svg+xml", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter("Svg", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter( - // "SVG", - // "image/svg+xml", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter("SVG", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter( - // "Svgz", - // "image/svg+xml", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter("Svgz", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter( - // "SVGZ", - // "image/svg+xml", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter("SVGZ", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter( - // "Xml", "text/xml", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter("Xml", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter( - // "XML", "text/xml", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter("XML", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - ); + .build()); /** * Extensions working with SVG payload for XSS: svg,html,xml,htm,xhtml,Null byte @@ -397,28 +343,7 @@ public class SVGFileUpload implements AttackVector { .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) - .build() - - // new FileParameter("svg"), - // new FileParameter("xml"), - // new FileParameter("svgz"), - // new FileParameter("svg", "image/svg+xml"), - // new FileParameter("xml", "text/xml"), - // new FileParameter("svgz", "image/svg+xml"), - // new FileParameter("svg", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter("xml", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter("svgz", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter( - // "svg" + NULL_BYTE_CHARACTER, - // "image/svg+xml", - // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - // new FileParameter( - // "svg" + NULL_BYTE_CHARACTER, - // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) - ); + .build()); /** * @throws FileUploadException diff --git a/src/main/resources/org/sasanlabs/attackvectors/images/1*1_Default.gif b/src/main/resources/org/sasanlabs/attackvectors/images/1*1_Default.gif index 57aeed3dba476ea689dadc094cad38a911288797..2799b45c6591f1db05c8c00bd1fd0c5c01f57614 100644 GIT binary patch delta 29 kcmY$@7I*h_v#?BLWME`yU|{(F|33o*gW^vXhKYhA0A}?EV*mgE literal 37 mcmZ?wbhEHbWMp7uC}3bv{K>+~00cT90wl)3#N@)rU=09cqXX~& diff --git a/src/main/resources/org/sasanlabs/attackvectors/images/1*1_Default.jpeg b/src/main/resources/org/sasanlabs/attackvectors/images/1*1_Default.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..1cda9a53dc357ce07d3c67051b7615ebf7dc2f64 GIT binary patch literal 631 zcmex=^(PF6}rMnOeST|r4lSw=>~TvNxu(8R<ECr+Na zbot8FYu9hwy!G(W<0ns_J%91?)yGetzkL1n{m0K=Ab&A3Fhjfr_ZgbM1cClyVqsxs zVF&q(k*OSrnFU!`6%E;h90S=C3x$=88aYIqCNA7~kW<+>=!0ld(M2vX6_bamA3L7B$%azX<@d&d)*s literal 0 HcmV?d00001 diff --git a/src/main/resources/org/sasanlabs/attackvectors/images/1*1_Default_JSP_Injected_EXIF.gif b/src/main/resources/org/sasanlabs/attackvectors/images/1*1_Default_JSP_Injected_EXIF.gif deleted file mode 100644 index e5c457414f2a8d79033a0fe12bb28649e7f9e933..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 79 zcmZ?wbhEHbWMp7uC}3bv{K>+~00fHv)NE936_kP#ixcyF5|fJKl@zoUl%gC1;yqJR c^GY()GE<9`6jbdPbU?~Mx*3?5To@Uw0nBv}jQ{`u diff --git a/src/main/resources/org/sasanlabs/attackvectors/images/1*1_JSP_Appended.gif b/src/main/resources/org/sasanlabs/attackvectors/images/1*1_JSP_Appended.gif new file mode 100644 index 0000000000000000000000000000000000000000..c4d2f643e902ef0f64948115b65fbc5f0b14c50d GIT binary patch literal 117 zcmZ?wbhEHbWMp7uXkcLY|NlP&1B2pE79h#MpaUX6G7L;iE{qJ;HmbG?N}joi>8atF zB^h490l|5h1qG=kZkai$p#?eli7D|)3fc-v!HLC*c|M6r#Sm_kV?exTN@`w7W?E)y Kk&=R{9TxywmL8k{ literal 0 HcmV?d00001 diff --git a/src/main/resources/org/sasanlabs/attackvectors/images/1*1_JSP_Appended.jpeg b/src/main/resources/org/sasanlabs/attackvectors/images/1*1_JSP_Appended.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..122adf4fc771d1e1402cdbeafae6f0dfeeb49d63 GIT binary patch literal 705 zcmex=^(PF6}rMnOeST|r4lSw=>~TvNxu(8R<ECr+Na zbot8FYu9hwy!G(W<0ns_J%91?)yGetzkL1n{m0K=Ab&A3Fhjfr_ZgbM1cClyVqsxs zVF&q(k*OSrnFU!`6%E;h90S=C3x$=88aYIqCNA7~kW<+>=!0ld(M2vX6_bamA3L7B$%aziFdttDxkWo0y&&o>`LN6&w(p zmswDdTH=J> E056&5<^TWy literal 0 HcmV?d00001 diff --git a/src/main/resources/org/sasanlabs/attackvectors/images/1*1_JSP_EXIF_Comment.gif b/src/main/resources/org/sasanlabs/attackvectors/images/1*1_JSP_EXIF_Comment.gif new file mode 100644 index 0000000000000000000000000000000000000000..d8245a5635c8331ffe9e4dbffac1ed4fb642faec GIT binary patch literal 120 zcmZ?wbhEHbWMp7uXkcLY|NlP&1B2pE79a_v|9RS|+A1h{<|d}6hG&*!cm)Rp=VcZY zq?Wj4=A?!exuHFSDQ^wZttm zCpEMnCqFSIUP(b)K`A(~I5E#BF{v2BjdBc#_e@F6E6GgDOf6DUP__Gio57iZgN==y zjg^C)ot=}DgNsLmmxr61M^Z?bUqn_)UQSj@Mn*wJPhCMtM_EQj!(3Cxz|h3RL|)y} z*22g}&)CEWWC$ZCCnpa#j|4BTgps0*q7lj9{{aR;4hBXBMrKAO1|~s9WR;@QBE$5`HGdR zHf`Rrb=&qGJ9iyAeB|h{<0np@x^(%<)oa&p+`RSh(c>pipFMx^^3}&rpTB(l_Wj4t zUm$-mGB88D1@{@6zXXB)Vq#%oW?={Ui;<}uh?xahSQQP~gd79e6AOivj2byaoF*>Z zc#u=sIOv0DQqe^&F%^@CsvkjK1N)3Pk2R6yGq}eP{<_7$!^{YbJZ3=#dxr17G!`}3 H|Gx Date: Sun, 28 Feb 2021 21:01:47 +0530 Subject: [PATCH 16/53] Small Fix --- .../fileupload/attacks/AttackVector.java | 37 +++++++++++++--- .../attacks/beans/VulnerabilityType.java | 44 +++++++++++++++++++ 2 files changed, 76 insertions(+), 5 deletions(-) create mode 100644 src/main/java/org/sasanlabs/fileupload/attacks/beans/VulnerabilityType.java diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java index c39f5ee..8752585 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java @@ -15,11 +15,14 @@ import java.io.IOException; import java.util.List; +import org.parosproxy.paros.core.scanner.Alert; import org.parosproxy.paros.core.scanner.NameValuePair; import org.parosproxy.paros.network.HttpMessage; import org.sasanlabs.fileupload.FileUploadScanRule; import org.sasanlabs.fileupload.attacks.beans.FileParameter; +import org.sasanlabs.fileupload.attacks.beans.VulnerabilityType; import org.sasanlabs.fileupload.exception.FileUploadException; +import org.sasanlabs.fileupload.i18n.FileUploadI18n; import org.sasanlabs.fileupload.locator.URILocatorImpl; import org.sasanlabs.fileupload.matcher.ContentMatcher; @@ -57,11 +60,38 @@ default HttpMessage executePreflightRequest( return preflightMsg; } + /** + * @param fileUploadScanRule + * @param vulnerabilityType + * @param payload + * @param newMsg + * @param preflight + */ + default void raiseAlert( + FileUploadScanRule fileUploadScanRule, + VulnerabilityType vulnerabilityType, + String payload, + HttpMessage newMsg, + HttpMessage preflight) { + fileUploadScanRule.raiseAlert( + vulnerabilityType.getAlertLevel(), + Alert.CONFIDENCE_MEDIUM, + FileUploadI18n.getMessage(vulnerabilityType.getMessageKey() + "name"), + FileUploadI18n.getMessage(vulnerabilityType.getMessageKey() + "desc"), + newMsg.getRequestHeader().getURI().toString(), + newMsg.toString(), + payload, + FileUploadI18n.getMessage(vulnerabilityType.getMessageKey() + "refs"), + FileUploadI18n.getMessage(vulnerabilityType.getMessageKey() + "soln"), + preflight); + } + default boolean genericAttackExecutor( FileUploadAttackExecutor fileUploadAttackExecutor, ContentMatcher contentMatcher, String payload, - List fileParameters) + List fileParameters, + VulnerabilityType vulnerabilityType) throws IOException, FileUploadException { List nameValuePairs = fileUploadAttackExecutor.getVariant().getParamList(); HttpMessage originalMsg = fileUploadAttackExecutor.getOriginalHttpMessage(); @@ -104,12 +134,8 @@ default boolean genericAttackExecutor( } else { continue; } - // Reinitialize the name-value pair positions - fileUploadAttackExecutor.getVariant().setMessage(newMsg); nameValuePairs = fileUploadAttackExecutor.getVariant().getParamList(); } - // Reset variant - fileUploadAttackExecutor.getVariant().setMessage(originalMsg); fileUploadScanRule.sendAndRecieve(newMsg); HttpMessage preflightMsg = this.executePreflightRequest( @@ -117,6 +143,7 @@ default boolean genericAttackExecutor( fileParameter.getFileName(originalFileName), fileUploadScanRule); if (contentMatcher.match(preflightMsg)) { + raiseAlert(fileUploadScanRule, vulnerabilityType, payload, newMsg, preflightMsg); return true; } } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/beans/VulnerabilityType.java b/src/main/java/org/sasanlabs/fileupload/attacks/beans/VulnerabilityType.java new file mode 100644 index 0000000..f9d6ac9 --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/attacks/beans/VulnerabilityType.java @@ -0,0 +1,44 @@ +/** + * Copyright 2021 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sasanlabs.fileupload.attacks.beans; + +import org.parosproxy.paros.core.scanner.Alert; + +public enum VulnerabilityType { + XSS_HTML_FILE("xssHtmlFile", Alert.RISK_MEDIUM), + XSS_SVG_FILE("xssSvgFile", Alert.RISK_MEDIUM), + RCE_PHP_FILE("rcePhpFile", Alert.RISK_HIGH), + RCE_JSP_FILE("rceJspFile", Alert.RISK_HIGH), + RCE_GIF_JSP_FILE("rceGifJspFile", Alert.RISK_HIGH), + RCE_JPEG_JSP_FILE("rceJpegJspFile", Alert.RISK_HIGH), + RCE_JSPX_FILE("rceJspxFile", Alert.RISK_HIGH), + EICAR_FILE("rceEicarFile", Alert.RISK_MEDIUM); + + private String messageKey; + private int alertLevel; + private static final String PREFIX = "fileupload.scanner.vulnerability."; + + private VulnerabilityType(String message, int alertLevel) { + this.messageKey = message; + this.alertLevel = alertLevel; + } + + public String getMessageKey() { + return PREFIX + this.messageKey; + } + + public int getAlertLevel() { + return this.alertLevel; + } +} From 1ecafbbdc70ba2ce6099f7cd06eff458a0ac06b1 Mon Sep 17 00:00:00 2001 From: karan preet singh sasan Date: Sun, 28 Feb 2021 21:41:43 +0530 Subject: [PATCH 17/53] Adding Alert related code --- .../EicarAntivirusTestFileUpload.java | 30 ++--- .../jsp/ImageWithJSPSnippetFileUpload.java | 115 +++++++++--------- .../attacks/rce/jsp/SimpleJSPFileUpload.java | 61 +++------- .../attacks/rce/jsp/SimpleJSPXFileUpload.java | 57 +++------ .../attacks/xss/HtmlFileUpload.java | 57 +++------ .../fileupload/attacks/xss/SVGFileUpload.java | 57 +++------ 6 files changed, 124 insertions(+), 253 deletions(-) diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java index 0f10679..e84dc3d 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java @@ -25,6 +25,7 @@ import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; import org.sasanlabs.fileupload.attacks.beans.FileParameter; import org.sasanlabs.fileupload.attacks.beans.FileParameterBuilder; +import org.sasanlabs.fileupload.attacks.beans.VulnerabilityType; import org.sasanlabs.fileupload.exception.FileUploadException; import org.sasanlabs.fileupload.matcher.ContentMatcher; import org.sasanlabs.fileupload.matcher.impl.MD5HashResponseMatcher; @@ -171,32 +172,15 @@ public class EicarAntivirusTestFileUpload implements AttackVector { @Override public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) throws FileUploadException { - boolean result = false; try { - result = - this.genericAttackExecutor( - fileUploadAttackExecutor, - CONTENT_MATCHER, - EICAR_FILE_CONTENT, - FILE_PARAMETERS_DEFAULT); - if (result) { - fileUploadAttackExecutor - .getFileUploadScanRule() - .raiseAlert( - 1, - 1, - "", - "", - "", - "", - "", - "", - "", - fileUploadAttackExecutor.getOriginalHttpMessage()); - } + return this.genericAttackExecutor( + fileUploadAttackExecutor, + CONTENT_MATCHER, + EICAR_FILE_CONTENT, + FILE_PARAMETERS_DEFAULT, + VulnerabilityType.EICAR_FILE); } catch (IOException e) { throw new FileUploadException(e); } - return result; } } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageWithJSPSnippetFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageWithJSPSnippetFileUpload.java index 2834a64..c1d48be 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageWithJSPSnippetFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageWithJSPSnippetFileUpload.java @@ -20,7 +20,9 @@ import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Base64; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.parosproxy.paros.core.scanner.Plugin.AttackStrength; import org.parosproxy.paros.network.HttpMessage; import org.sasanlabs.fileupload.attacks.AttackVector; @@ -28,6 +30,7 @@ import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; import org.sasanlabs.fileupload.attacks.beans.FileParameter; import org.sasanlabs.fileupload.attacks.beans.FileParameterBuilder; +import org.sasanlabs.fileupload.attacks.beans.VulnerabilityType; import org.sasanlabs.fileupload.exception.FileUploadException; import org.sasanlabs.fileupload.matcher.impl.ContainsExpectedValueMatcher; @@ -39,7 +42,8 @@ public class ImageWithJSPSnippetFileUpload implements AttackVector { private static final String GIF_IMAGE_APPENDED_WITH_JSP_SNIPPET_BASE64_ENCODED = "R0lGODlhAQABAIAAAP///wAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOzwlPSAiSW1hZ2VXaXRoSlNQU25pcHBldEZpbGVVcGxvYWRfIiArICJTYXNhbkxhYnNfIiArICJaQVBfSWRlbnRpZmllciIgJT4K"; - // As JPEG is most widely used format for images hence in case application is specifically + // As JPEG is most widely used format for images hence in case application is + // specifically // looking for JPEG magic numbers then this below configuration can help private static final String JPEG_IMAGE_JSP_INJECTED_IN_EXIF_BASE64_ENCODED = "/9j/4AAQSkZJRgABAQEAYABgAAD//gBLPCU9ICJJbWFnZVdpdGhKU1BTbmlwcGV0RmlsZVVwbG9hZF8iICsgIlNhc2FuTGFic18iICsgIlpBUF9JZGVudGlmaWVyIiAlPv/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicgIiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAAEAAQMBIgACEQEDEQH/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2gAMAwEAAhEDEQA/APf6KKKAP//Z"; @@ -51,12 +55,20 @@ public class ImageWithJSPSnippetFileUpload implements AttackVector { private static final String BASE_FILE_NAME = "ImageWithJSPSnippetFileUpload_"; - private static final List PAYLOADS = - Arrays.asList( - GIF_IMAGE_JSP_INJECTED_IN_EXIF_BASE64_ENCODED, - GIF_IMAGE_APPENDED_WITH_JSP_SNIPPET_BASE64_ENCODED, - JPEG_IMAGE_JSP_INJECTED_IN_EXIF_BASE64_ENCODED, - JPEG_IMAGE_APPENDED_WITH_JSP_SNIPPET_BASE64_ENCODED); + private static final Map> PAYLOADS = new HashMap<>(); + + { + PAYLOADS.put( + VulnerabilityType.RCE_GIF_JSP_FILE, + Arrays.asList( + GIF_IMAGE_JSP_INJECTED_IN_EXIF_BASE64_ENCODED, + GIF_IMAGE_APPENDED_WITH_JSP_SNIPPET_BASE64_ENCODED)); + PAYLOADS.put( + VulnerabilityType.RCE_JPEG_JSP_FILE, + Arrays.asList( + JPEG_IMAGE_JSP_INJECTED_IN_EXIF_BASE64_ENCODED, + JPEG_IMAGE_APPENDED_WITH_JSP_SNIPPET_BASE64_ENCODED)); + } private static final List FILE_PARAMETERS_EXTENDED = Arrays.asList( @@ -171,62 +183,47 @@ public class ImageWithJSPSnippetFileUpload implements AttackVector { @Override public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) throws FileUploadException { - for (String payloads : PAYLOADS) { - try { - byte[] imagePayload = Base64.getDecoder().decode(payloads); - HttpMessage originalMessage = fileUploadAttackExecutor.getOriginalHttpMessage(); - String charSet = originalMessage.getRequestHeader().getCharset(); - Charset requestCharSet = - charSet != null ? Charset.forName(charSet) : StandardCharsets.ISO_8859_1; - String requestPayload = new String(imagePayload, requestCharSet); - if (this.genericAttackExecutor( - fileUploadAttackExecutor, - new ContainsExpectedValueMatcher(FILE_EXPECTED_VALUE), - requestPayload, - FILE_PARAMETERS_DEFAULT)) { - fileUploadAttackExecutor - .getFileUploadScanRule() - .raiseAlert( - 1, - 1, - this.getClass().getName(), - "", - "", - "", - "", - "", - "", - fileUploadAttackExecutor.getOriginalHttpMessage()); - } else { - if (fileUploadAttackExecutor - .getFileUploadScanRule() - .getAttackStrength() - .equals(AttackStrength.INSANE)) { - if (this.genericAttackExecutor( - fileUploadAttackExecutor, - new ContainsExpectedValueMatcher(FILE_EXPECTED_VALUE), - requestPayload, - FILE_PARAMETERS_EXTENDED)) { - fileUploadAttackExecutor + boolean result = false; + for (VulnerabilityType vulnerabilityType : PAYLOADS.keySet()) { + for (String payloads : PAYLOADS.get(vulnerabilityType)) { + try { + byte[] imagePayload = Base64.getDecoder().decode(payloads); + HttpMessage originalMessage = fileUploadAttackExecutor.getOriginalHttpMessage(); + String charSet = originalMessage.getRequestHeader().getCharset(); + Charset requestCharSet = + charSet != null + ? Charset.forName(charSet) + : StandardCharsets.ISO_8859_1; + String requestPayload = new String(imagePayload, requestCharSet); + result = + this.genericAttackExecutor( + fileUploadAttackExecutor, + new ContainsExpectedValueMatcher(FILE_EXPECTED_VALUE), + requestPayload, + FILE_PARAMETERS_DEFAULT, + vulnerabilityType); + + if (!result + && fileUploadAttackExecutor .getFileUploadScanRule() - .raiseAlert( - 1, - 1, - "", - "", - "", - "", - "", - "", - "", - fileUploadAttackExecutor.getOriginalHttpMessage()); - } + .getAttackStrength() + .equals(AttackStrength.INSANE)) { + result = + this.genericAttackExecutor( + fileUploadAttackExecutor, + new ContainsExpectedValueMatcher(FILE_EXPECTED_VALUE), + requestPayload, + FILE_PARAMETERS_EXTENDED, + vulnerabilityType); + } + if (result) { + return result; } + } catch (IOException e) { + throw new FileUploadException(e); } - } catch (IOException e) { - throw new FileUploadException(e); } } - return false; + return result; } } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPFileUpload.java index b774c33..a4ccc47 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPFileUpload.java @@ -24,14 +24,12 @@ import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; import org.sasanlabs.fileupload.attacks.beans.FileParameter; import org.sasanlabs.fileupload.attacks.beans.FileParameterBuilder; +import org.sasanlabs.fileupload.attacks.beans.VulnerabilityType; import org.sasanlabs.fileupload.exception.FileUploadException; import org.sasanlabs.fileupload.matcher.ContentMatcher; import org.sasanlabs.fileupload.matcher.impl.MD5HashResponseMatcher; /** @author KSASAN preetkaran20@gmail.com */ - -// TODO check if we need to have case sensitive extensions like JsP or jSP or hTML or HtmL or hTmL -// etc public class SimpleJSPFileUpload implements AttackVector { private static final String JSP_UPLOADED_FILE_BASE_NAME = "SimpleJSPFileUpload_"; @@ -165,48 +163,21 @@ public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) fileUploadAttackExecutor, CONTENT_MATCHER, JSP_PAYLOAD, - FILE_PARAMETERS_DEFAULT); - if (result) { - fileUploadAttackExecutor - .getFileUploadScanRule() - .raiseAlert( - 1, - 1, - "", - "", - "", - "", - "", - "", - "", - fileUploadAttackExecutor.getOriginalHttpMessage()); - } else { - if (fileUploadAttackExecutor - .getFileUploadScanRule() - .getAttackStrength() - .equals(AttackStrength.INSANE)) { - result = - this.genericAttackExecutor( - fileUploadAttackExecutor, - CONTENT_MATCHER, - JSP_PAYLOAD, - FILE_PARAMETERS_EXTENDED); - if (result) { - fileUploadAttackExecutor - .getFileUploadScanRule() - .raiseAlert( - 1, - 1, - "", - "", - "", - "", - "", - "", - "", - fileUploadAttackExecutor.getOriginalHttpMessage()); - } - } + FILE_PARAMETERS_DEFAULT, + VulnerabilityType.RCE_JSP_FILE); + + if (!result + && fileUploadAttackExecutor + .getFileUploadScanRule() + .getAttackStrength() + .equals(AttackStrength.INSANE)) { + result = + this.genericAttackExecutor( + fileUploadAttackExecutor, + CONTENT_MATCHER, + JSP_PAYLOAD, + FILE_PARAMETERS_EXTENDED, + VulnerabilityType.RCE_JSP_FILE); } } catch (IOException e) { throw new FileUploadException(e); diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPXFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPXFileUpload.java index 05150e0..e5d54aa 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPXFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPXFileUpload.java @@ -24,6 +24,7 @@ import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; import org.sasanlabs.fileupload.attacks.beans.FileParameter; import org.sasanlabs.fileupload.attacks.beans.FileParameterBuilder; +import org.sasanlabs.fileupload.attacks.beans.VulnerabilityType; import org.sasanlabs.fileupload.exception.FileUploadException; import org.sasanlabs.fileupload.matcher.ContentMatcher; import org.sasanlabs.fileupload.matcher.impl.MD5HashResponseMatcher; @@ -168,48 +169,20 @@ public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) fileUploadAttackExecutor, CONTENT_MATCHER, JSPX_PAYLOAD, - FILE_PARAMETERS); - if (result) { - fileUploadAttackExecutor - .getFileUploadScanRule() - .raiseAlert( - 1, - 1, - "", - "", - "", - "", - "", - "", - "", - fileUploadAttackExecutor.getOriginalHttpMessage()); - } else { - if (fileUploadAttackExecutor - .getFileUploadScanRule() - .getAttackStrength() - .equals(AttackStrength.INSANE)) { - result = - this.genericAttackExecutor( - fileUploadAttackExecutor, - CONTENT_MATCHER, - JSPX_PAYLOAD, - FILE_PARAMETERS_EXTENDED); - if (result) { - fileUploadAttackExecutor - .getFileUploadScanRule() - .raiseAlert( - 1, - 1, - "", - "", - "", - "", - "", - "", - "", - fileUploadAttackExecutor.getOriginalHttpMessage()); - } - } + FILE_PARAMETERS, + VulnerabilityType.RCE_JSPX_FILE); + if (!result + && fileUploadAttackExecutor + .getFileUploadScanRule() + .getAttackStrength() + .equals(AttackStrength.INSANE)) { + result = + this.genericAttackExecutor( + fileUploadAttackExecutor, + CONTENT_MATCHER, + JSPX_PAYLOAD, + FILE_PARAMETERS_EXTENDED, + VulnerabilityType.RCE_JSPX_FILE); } } catch (IOException e) { throw new FileUploadException(e); diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java index 69a959c..deb5c91 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java @@ -25,6 +25,7 @@ import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; import org.sasanlabs.fileupload.attacks.beans.FileParameter; import org.sasanlabs.fileupload.attacks.beans.FileParameterBuilder; +import org.sasanlabs.fileupload.attacks.beans.VulnerabilityType; import org.sasanlabs.fileupload.exception.FileUploadException; import org.sasanlabs.fileupload.matcher.ContentMatcher; import org.sasanlabs.fileupload.matcher.impl.MD5HashResponseMatcher; @@ -737,48 +738,20 @@ public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) fileUploadAttackExecutor, CONTENT_MATCHER, XSS_PAYLOAD_HTML_FILE, - FILE_PARAMETERS_DEFAULT); - if (result) { - fileUploadAttackExecutor - .getFileUploadScanRule() - .raiseAlert( - 1, - 1, - "", - "", - "", - "", - "", - "", - "", - fileUploadAttackExecutor.getOriginalHttpMessage()); - } else { - if (fileUploadAttackExecutor - .getFileUploadScanRule() - .getAttackStrength() - .equals(AttackStrength.INSANE)) { - result = - this.genericAttackExecutor( - fileUploadAttackExecutor, - CONTENT_MATCHER, - XSS_PAYLOAD_HTML_FILE, - FILE_PARAMETERS_EXTENDED); - if (result) { - fileUploadAttackExecutor - .getFileUploadScanRule() - .raiseAlert( - 1, - 1, - "", - "", - "", - "", - "", - "", - "", - fileUploadAttackExecutor.getOriginalHttpMessage()); - } - } + FILE_PARAMETERS_DEFAULT, + VulnerabilityType.XSS_HTML_FILE); + if (!result + && fileUploadAttackExecutor + .getFileUploadScanRule() + .getAttackStrength() + .equals(AttackStrength.INSANE)) { + result = + this.genericAttackExecutor( + fileUploadAttackExecutor, + CONTENT_MATCHER, + XSS_PAYLOAD_HTML_FILE, + FILE_PARAMETERS_EXTENDED, + VulnerabilityType.XSS_HTML_FILE); } } catch (IOException e) { throw new FileUploadException(e); diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/xss/SVGFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/xss/SVGFileUpload.java index 87eafc7..772c062 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/xss/SVGFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/xss/SVGFileUpload.java @@ -24,6 +24,7 @@ import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; import org.sasanlabs.fileupload.attacks.beans.FileParameter; import org.sasanlabs.fileupload.attacks.beans.FileParameterBuilder; +import org.sasanlabs.fileupload.attacks.beans.VulnerabilityType; import org.sasanlabs.fileupload.exception.FileUploadException; /** @@ -359,48 +360,20 @@ public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) fileUploadAttackExecutor, HtmlFileUpload.CONTENT_MATCHER, XSS_PAYLOAD_SVG_FILE, - FILE_PARAMETERS_DEFAULT); - if (result) { - fileUploadAttackExecutor - .getFileUploadScanRule() - .raiseAlert( - 1, - 1, - "", - "", - "", - "", - "", - "", - "", - fileUploadAttackExecutor.getOriginalHttpMessage()); - } else { - if (fileUploadAttackExecutor - .getFileUploadScanRule() - .getAttackStrength() - .equals(AttackStrength.INSANE)) { - result = - this.genericAttackExecutor( - fileUploadAttackExecutor, - HtmlFileUpload.CONTENT_MATCHER, - XSS_PAYLOAD_SVG_FILE, - FILE_PARAMETERS_EXTENDED); - if (result) { - fileUploadAttackExecutor - .getFileUploadScanRule() - .raiseAlert( - 1, - 1, - "", - "", - "", - "", - "", - "", - "", - fileUploadAttackExecutor.getOriginalHttpMessage()); - } - } + FILE_PARAMETERS_DEFAULT, + VulnerabilityType.XSS_SVG_FILE); + if (!result + && fileUploadAttackExecutor + .getFileUploadScanRule() + .getAttackStrength() + .equals(AttackStrength.INSANE)) { + result = + this.genericAttackExecutor( + fileUploadAttackExecutor, + HtmlFileUpload.CONTENT_MATCHER, + XSS_PAYLOAD_SVG_FILE, + FILE_PARAMETERS_EXTENDED, + VulnerabilityType.XSS_SVG_FILE); } } catch (IOException e) { throw new FileUploadException(e); From ddf3ad7e5b5870b60aca5fbb2b43a97c0e5015ce Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Sun, 9 May 2021 13:42:12 +0530 Subject: [PATCH 18/53] Little refinement --- README.md | 1 + gradle/wrapper/gradle-wrapper.properties | 3 +- .../fileupload/FileUploadScanRule.java | 2 +- .../fileupload/attacks/AttackVector.java | 34 ++++---- .../attacks/beans/VulnerabilityType.java | 2 +- .../fileupload/attacks/rce/PathTraversal.java | 4 - .../fileupload/locator/URILocatorImpl.java | 9 +- .../fileupload/ui/FileUploadOptionsPanel.java | 26 +++++- .../fileupload/i18n/Messages.properties | 86 ++++++++++++++++++- 9 files changed, 141 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 3ceda5c..022ff1e 100755 --- a/README.md +++ b/README.md @@ -1,2 +1,3 @@ # owasp-zap-fileupload-addon File Upload Scan Rule + diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ee69dd6..9d17479 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip +distributionSha256Sum=81003f83b0056d20eedf48cddd4f52a9813163d4ba185bcf8abd34b8eeea4cbd +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java index 9fbbfff..d94f793 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java @@ -92,7 +92,7 @@ public void scan(HttpMessage msg, Variant variant) { fileUploadAttackExecutor.executeAttack(); } } catch (Exception ex) { - + LOGGER.error("Error occurred while scanning", ex); } } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java index 8752585..f794ad0 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java @@ -15,6 +15,8 @@ import java.io.IOException; import java.util.List; +import java.util.Objects; +import org.apache.commons.httpclient.URI; import org.parosproxy.paros.core.scanner.Alert; import org.parosproxy.paros.core.scanner.NameValuePair; import org.parosproxy.paros.network.HttpMessage; @@ -37,7 +39,7 @@ public interface AttackVector { /** * @param modifiedMsg * @param fileUploadScanRule - * @return + * @return httpMessage of preflight request * @throws IOException * @throws FileUploadException */ @@ -45,15 +47,17 @@ default HttpMessage executePreflightRequest( HttpMessage modifiedMsg, String fileName, FileUploadScanRule fileUploadScanRule) throws IOException, FileUploadException { HttpMessage preflightMsg = new HttpMessage(); - preflightMsg - .getRequestHeader() - .setURI( - new URILocatorImpl() - .get( - modifiedMsg, - fileName, - (httpmessage) -> - fileUploadScanRule.sendAndRecieve(httpmessage))); + URI uri = + new URILocatorImpl() + .get( + modifiedMsg, + fileName, + (httpmessage) -> fileUploadScanRule.sendAndRecieve(httpmessage)); + if (Objects.isNull(uri)) { + return null; + } + + preflightMsg.getRequestHeader().setURI(uri); preflightMsg.getRequestHeader().setMethod("GET"); preflightMsg.getRequestHeader().setCookies(modifiedMsg.getRequestHeader().getHttpCookies()); fileUploadScanRule.sendAndRecieve(preflightMsg); @@ -76,13 +80,13 @@ default void raiseAlert( fileUploadScanRule.raiseAlert( vulnerabilityType.getAlertLevel(), Alert.CONFIDENCE_MEDIUM, - FileUploadI18n.getMessage(vulnerabilityType.getMessageKey() + "name"), - FileUploadI18n.getMessage(vulnerabilityType.getMessageKey() + "desc"), + FileUploadI18n.getMessage(vulnerabilityType.getMessageKey() + ".name"), + FileUploadI18n.getMessage(vulnerabilityType.getMessageKey() + ".desc"), newMsg.getRequestHeader().getURI().toString(), newMsg.toString(), payload, - FileUploadI18n.getMessage(vulnerabilityType.getMessageKey() + "refs"), - FileUploadI18n.getMessage(vulnerabilityType.getMessageKey() + "soln"), + FileUploadI18n.getMessage(vulnerabilityType.getMessageKey() + ".refs"), + FileUploadI18n.getMessage(vulnerabilityType.getMessageKey() + ".soln"), preflight); } @@ -142,7 +146,7 @@ default boolean genericAttackExecutor( newMsg, fileParameter.getFileName(originalFileName), fileUploadScanRule); - if (contentMatcher.match(preflightMsg)) { + if (Objects.nonNull(preflightMsg) && contentMatcher.match(preflightMsg)) { raiseAlert(fileUploadScanRule, vulnerabilityType, payload, newMsg, preflightMsg); return true; } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/beans/VulnerabilityType.java b/src/main/java/org/sasanlabs/fileupload/attacks/beans/VulnerabilityType.java index f9d6ac9..4b48bd4 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/beans/VulnerabilityType.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/beans/VulnerabilityType.java @@ -23,7 +23,7 @@ public enum VulnerabilityType { RCE_GIF_JSP_FILE("rceGifJspFile", Alert.RISK_HIGH), RCE_JPEG_JSP_FILE("rceJpegJspFile", Alert.RISK_HIGH), RCE_JSPX_FILE("rceJspxFile", Alert.RISK_HIGH), - EICAR_FILE("rceEicarFile", Alert.RISK_MEDIUM); + EICAR_FILE("antiVirusEicarFile", Alert.RISK_MEDIUM); private String messageKey; private int alertLevel; diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/PathTraversal.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/PathTraversal.java index b683e72..57d906a 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/PathTraversal.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/PathTraversal.java @@ -42,8 +42,4 @@ public class PathTraversal /*implements AttackVector*/ { // return false; // } - /** - * Execute the experiment 1. change only content type 2. change only html or htm 3. change html - * extension and text/plain 4. change htm extension and text/plain or text/html - */ } diff --git a/src/main/java/org/sasanlabs/fileupload/locator/URILocatorImpl.java b/src/main/java/org/sasanlabs/fileupload/locator/URILocatorImpl.java index abaa4ad..0f05590 100644 --- a/src/main/java/org/sasanlabs/fileupload/locator/URILocatorImpl.java +++ b/src/main/java/org/sasanlabs/fileupload/locator/URILocatorImpl.java @@ -27,7 +27,14 @@ import org.sasanlabs.fileupload.exception.FileUploadException; import org.sasanlabs.fileupload.function.ConsumerWithException; -/** @author preetkaran20@gmail.com KSASAN */ +/** + * {@code URILocatorImpl} class is used to find the URL either by 1. returning the static url + * mentioned by user in Options tab 2. parsing the original {@code HttpMessage} and using dynamic + * configuration to find the complete URI. 3. Invokes the preflight request as mentioned by dynamic + * configuration and then parsing the preflighted {@code HttpMessage} + * + * @author preetkaran20@gmail.com KSASAN + */ public class URILocatorImpl implements URILocator { protected static final Logger LOGGER = Logger.getLogger(URILocatorImpl.class); diff --git a/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java b/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java index d7f3edd..25c1167 100644 --- a/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java +++ b/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java @@ -27,6 +27,7 @@ import javax.swing.JTextField; import javax.swing.ScrollPaneConstants; import javax.swing.border.TitledBorder; +import org.apache.commons.lang3.StringUtils; import org.parosproxy.paros.model.OptionsParam; import org.parosproxy.paros.view.AbstractParamPanel; import org.sasanlabs.fileupload.configuration.FileUploadConfiguration; @@ -228,7 +229,30 @@ public void initParam(Object optionParams) { } @Override - public void validateParam(Object optionParams) throws Exception {} + public void validateParam(Object optionParams) throws Exception { + FileUploadConfiguration fileUploadConfiguration = + ((OptionsParam) optionParams).getParamSet(FileUploadConfiguration.class); + boolean isStaticUrlPresent = + StringUtils.isNotEmpty(fileUploadConfiguration.getStaticLocationURIRegex()); + boolean isDynamicUrlPresent = + StringUtils.isNotEmpty(fileUploadConfiguration.getDynamicLocationURIRegex()); + boolean isStartIdentifierPresent = + StringUtils.isNotEmpty(fileUploadConfiguration.getDynamicLocationStartIdentifier()); + boolean isEndIdentifierPresent = + StringUtils.isNotEmpty(fileUploadConfiguration.getDynamicLocationEndIdentifier()); + + if (isStaticUrlPresent + && (isDynamicUrlPresent || isStartIdentifierPresent || isEndIdentifierPresent)) { + throw new IllegalArgumentException( + FileUploadI18n.getMessage( + "fileupload.settings.alert.static.dynamicconfiguration.both.present")); + } else if ((isStartIdentifierPresent && !isEndIdentifierPresent) + || (!isStartIdentifierPresent && isEndIdentifierPresent)) { + throw new IllegalArgumentException( + FileUploadI18n.getMessage( + "fileupload.settings.alert.invalid.dynamicconfigutation")); + } + } @Override public void saveParam(Object optionParams) throws Exception { diff --git a/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties b/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties index 811860a..f1d8495 100755 --- a/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties +++ b/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties @@ -10,8 +10,90 @@ fileupload.settings.urilocator.dynamiclocation.uriregex=URI Regex fileupload.settings.urilocator.dynamiclocation.startidentifer=Start Identifier fileupload.settings.urilocator.dynamiclocation.endidentifer=End Identifier +fileupload.settings.alert.invalid.dynamicconfigutation=Both dynamic start and end regex should be present. +fileupload.settings.alert.static.dynamicconfiguration.both.present=Only one of the static and dynamic configuration should be present. + # FileUpload Scan Rule fileupload.scanrule.name=File Upload fileupload.scanrule.description=File Upload scan rule is used to scan the vulnerabilities in the File Upload functionality of web applications. -fileupload.scanrule.refs= -fileupload.scanrule.soln= \ No newline at end of file +fileupload.scanrule.refs=https://cwe.mitre.org/data/definitions/434.html +fileupload.scanrule.soln=Follow the suggestions mentioned in following links: \ +1. https://portswigger.net/kb/issues/00500980_file-upload-functionality \ +2. https://www.youtube.com/watch?v=CmF9sEyKZNo +3. https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload + +fileupload.scanner.vulnerability.xssHtmlFile.name=Upload and download of html/htm/xhtml or other variants extension file. +fileupload.scanner.vulnerability.xssHtmlFile.description=Html or its variants if rendered in the browser can cause client-side attacks like XSS. +fileupload.scanner.vulnerability.xssHtmlFile.refs=https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload +fileupload.scanner.vulnerability.xssHtmlFile.soln=Follow the suggestions mentioned in following links: \ +1. https://wiki.owasp.org/index.php/Testing_for_Stored_Cross_site_scripting_(OTG-INPVAL-002)#:~:text=File%20Upload \ +2. https://portswigger.net/kb/issues/00500980_file-upload-functionality \ +3. https://www.youtube.com/watch?v=CmF9sEyKZNo \ + +fileupload.scanner.vulnerability.xssSvgFile.name=Upload and download of svg or other variants extension file. +fileupload.scanner.vulnerability.xssSvgFile.description=svg or its variants if rendered in the browser can cause client-side attacks like XSS. +fileupload.scanner.vulnerability.xssSvgFile.refs=https://cwe.mitre.org/data/definitions/434.html +fileupload.scanner.vulnerability.xssSvgFile.soln=Follow the suggestions mentioned in following links: \ +1. https://wiki.owasp.org/index.php/Testing_for_Stored_Cross_site_scripting_(OTG-INPVAL-002)#:~:text=File%20Upload \ +2. https://portswigger.net/kb/issues/00500980_file-upload-functionality \ +3. https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload \ +4. https://www.youtube.com/watch?v=CmF9sEyKZNo + +fileupload.scanner.vulnerability.rcePhpFile.name=Remote code execution by uploading Php file. +fileupload.scanner.vulnerability.rcePhpFile.description=Php file can be uploaded and executed on server hence server is Vulnerable to Remote code execution vulnerability. +fileupload.scanner.vulnerability.rcePhpFile.refs=https://cwe.mitre.org/data/definitions/434.html +fileupload.scanner.vulnerability.rcePhpFile.soln=Follow the suggestions mentioned in following links: \ +1. https://portswigger.net/kb/issues/00500980_file-upload-functionality \ +2. https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload \ +3. https://www.youtube.com/watch?v=CmF9sEyKZNo + +fileupload.scanner.vulnerability.rceJspFile.name=Remote code execution by uploading Jsp file. +fileupload.scanner.vulnerability.rceJspFile.description=Jsp file can be uploaded and executed on server hence server is Vulnerable to Remote code execution vulnerability. +fileupload.scanner.vulnerability.rceJspFile.refs=https://cwe.mitre.org/data/definitions/434.html +fileupload.scanner.vulnerability.rceJspFile.soln=Follow the suggestions mentioned in following links: \ +1. https://portswigger.net/kb/issues/00500980_file-upload-functionality \ +2. https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload \ +3. https://www.youtube.com/watch?v=CmF9sEyKZNo \ +4. https://cwe.mitre.org/data/definitions/434.html + +fileupload.scanner.vulnerability.rceGifJspFile.name=Remote code execution by uploading Gif image containing Jsp content. +fileupload.scanner.vulnerability.rceGifJspFile.description=Gif file containing Jsp content can be uploaded and Jsp code is executed on server hence server is Vulnerable to Remote code execution vulnerability. +fileupload.scanner.vulnerability.rceGifJspFile.refs=https://cwe.mitre.org/data/definitions/434.html +fileupload.scanner.vulnerability.rceGifJspFile.soln=Follow the suggestions mentioned in following links: \ +1. https://portswigger.net/kb/issues/00500980_file-upload-functionality \ +2. https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload \ +3. https://www.youtube.com/watch?v=CmF9sEyKZNo \ +4. https://cwe.mitre.org/data/definitions/434.html + +fileupload.scanner.vulnerability.rceJpegJspFile.name=Remote code execution by uploading Jpeg image containing Jsp content. +fileupload.scanner.vulnerability.rceJpegJspFile.description=Jpeg file containing Jsp content can be uploaded and Jsp code is executed on server hence server is Vulnerable to Remote code execution vulnerability. +fileupload.scanner.vulnerability.rceJpegJspFile.refs=https://cwe.mitre.org/data/definitions/434.html +fileupload.scanner.vulnerability.rceJpegJspFile.soln=Follow the suggestions mentioned in following links: \ +1. https://portswigger.net/kb/issues/00500980_file-upload-functionality \ +2. https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload \ +3. https://www.youtube.com/watch?v=CmF9sEyKZNo \ +4. https://cwe.mitre.org/data/definitions/434.html + +fileupload.scanner.vulnerability.rceJspxFile.name=Remote code execution by uploading Jspx file. +fileupload.scanner.vulnerability.rceJspxFile.description=Jspx file can be uploaded and executed on server hence server is Vulnerable to Remote code execution vulnerability. +fileupload.scanner.vulnerability.rceJspxFile.refs=https://cwe.mitre.org/data/definitions/434.html +fileupload.scanner.vulnerability.rceJspxFile.soln=Follow the suggestions mentioned in following links: \ +1. https://portswigger.net/kb/issues/00500980_file-upload-functionality \ +2. https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload \ +3. https://www.youtube.com/watch?v=CmF9sEyKZNo \ +4. https://cwe.mitre.org/data/definitions/434.html + +fileupload.scanner.vulnerability.antiVirusEicarFile.name=Eicar antivirus file upload attack +fileupload.scanner.vulnerability.antiVirusEicarFile.description=Eicar antivirus file was uploaded and downloaded which should be\ +detected by the antivirus. This means that either antivirus is not present or antivirus doesn't support Eicar. As per https://www.virustotal.com/ eicar file is supported by 63 Antiviruses out of 67. +fileupload.scanner.vulnerability.antiVirusEicarFile.refs=https://en.wikipedia.org/wiki/EICAR_test_file +fileupload.scanner.vulnerability.antiVirusEicarFile.soln= Consider checking the antivirus setup in server, in case the antivirus supports Eicar standards and still doesn't report issue, try fixing it.\ +https://owasp.org/www-project-web-security-testing-guide/stable/4-Web_Application_Security_Testing/10-Business_Logic_Testing/09-Test_Upload_of_Malicious_Files.html#malware + + + + + + + + From 914851aa2bc77277ca0e568f4d1216eac787b94b Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Sun, 9 May 2021 14:01:24 +0530 Subject: [PATCH 19/53] Small issue fix --- .../fileupload/ui/FileUploadOptionsPanel.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java b/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java index 25c1167..c54f835 100644 --- a/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java +++ b/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java @@ -230,16 +230,14 @@ public void initParam(Object optionParams) { @Override public void validateParam(Object optionParams) throws Exception { - FileUploadConfiguration fileUploadConfiguration = - ((OptionsParam) optionParams).getParamSet(FileUploadConfiguration.class); boolean isStaticUrlPresent = - StringUtils.isNotEmpty(fileUploadConfiguration.getStaticLocationURIRegex()); + StringUtils.isNotEmpty(staticLocationConfigurationURIRegex.getText()); boolean isDynamicUrlPresent = - StringUtils.isNotEmpty(fileUploadConfiguration.getDynamicLocationURIRegex()); + StringUtils.isNotEmpty(dynamicLocationConfigurationURIRegex.getText()); boolean isStartIdentifierPresent = - StringUtils.isNotEmpty(fileUploadConfiguration.getDynamicLocationStartIdentifier()); + StringUtils.isNotEmpty(dynamicLocationConfigurationStartIdentifier.getText()); boolean isEndIdentifierPresent = - StringUtils.isNotEmpty(fileUploadConfiguration.getDynamicLocationEndIdentifier()); + StringUtils.isNotEmpty(dynamicLocationConfigurationEndIdentifier.getText()); if (isStaticUrlPresent && (isDynamicUrlPresent || isStartIdentifierPresent || isEndIdentifierPresent)) { From 2d264eeda4a144596e879d7956b8a7a04c1a45a9 Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Sun, 9 May 2021 16:12:01 +0530 Subject: [PATCH 20/53] Removing AbstractAppVariantPlugin --- .../fileupload/AbstractAppVariantPlugin.java | 99 ------------------- .../fileupload/FileUploadScanRule.java | 49 +++------ .../fileupload/attacks/AttackVector.java | 35 ++++--- .../attacks/FileUploadAttackExecutor.java | 17 ++-- .../fileupload/i18n/Messages.properties | 2 +- 5 files changed, 47 insertions(+), 155 deletions(-) delete mode 100644 src/main/java/org/sasanlabs/fileupload/AbstractAppVariantPlugin.java diff --git a/src/main/java/org/sasanlabs/fileupload/AbstractAppVariantPlugin.java b/src/main/java/org/sasanlabs/fileupload/AbstractAppVariantPlugin.java deleted file mode 100644 index dccd099..0000000 --- a/src/main/java/org/sasanlabs/fileupload/AbstractAppVariantPlugin.java +++ /dev/null @@ -1,99 +0,0 @@ -/** - * Copyright 2021 SasanLabs - * - *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of the License at - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sasanlabs.fileupload; - -import java.util.List; -import org.apache.log4j.Logger; -import org.parosproxy.paros.Constant; -import org.parosproxy.paros.core.scanner.AbstractAppPlugin; -import org.parosproxy.paros.core.scanner.Variant; -import org.parosproxy.paros.model.Model; -import org.parosproxy.paros.network.HttpMessage; -import org.zaproxy.zap.extension.ascan.VariantFactory; - -/** - * {@code AbstractAppVariantPlugin} is the abstract base class which is used to run per variant to - * modify multiple name value pairs of the {@code HttpMessage} per variant. - * - * @author KSASAN preetkaran20@gmail.com - */ -public abstract class AbstractAppVariantPlugin extends AbstractAppPlugin { - - private final Logger logger = Logger.getLogger(this.getClass()); - - @Override - public void scan() { - VariantFactory factory = Model.getSingleton().getVariantFactory(); - - List listVariant = - factory.createVariants(this.getParent().getScannerParam(), this.getBaseMsg()); - - if (listVariant.isEmpty()) { - getParent() - .pluginSkipped( - this, - Constant.messages.getString( - "ascan.progress.label.skipped.reason.noinputvectors")); - return; - } - - for (int i = 0; i < listVariant.size() && !isStop(); i++) { - - HttpMessage msg = getNewMsg(); - // ZAP: Removed unnecessary cast. - Variant variant = listVariant.get(i); - try { - variant.setMessage(msg); - scanVariant(variant); - - } catch (Exception e) { - logger.error( - "Error occurred while scanning with variant " - + variant.getClass().getCanonicalName(), - e); - } - - // ZAP: Implement pause and resume - while (getParent().isPaused() && !isStop()) { - try { - Thread.sleep(500); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - } - } - - /** Scan the current message using the current Variant */ - private void scanVariant(Variant variant) { - HttpMessage msg = getNewMsg(); - try { - scan(msg, variant); - } catch (Exception e) { - logger.error("Error occurred while scanning a message:", e); - } - } - - /** - * Plugin method that need to be implemented for the specific test. The passed message is a copy - * which maintains only the Request's information so if the plugin need to manage the original - * Response body a getBaseMsg() call should be done. the param name and the value are the - * original value retrieved by the crawler and the current applied Variant. - * - * @param msg a copy of the HTTP message currently under scanning - * @param variant - */ - public abstract void scan(HttpMessage msg, Variant variant); -} diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java index d94f793..7c93423 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java @@ -17,9 +17,9 @@ import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import org.apache.log4j.Logger; +import org.parosproxy.paros.core.scanner.AbstractAppVariantPlugin; import org.parosproxy.paros.core.scanner.Category; import org.parosproxy.paros.core.scanner.NameValuePair; -import org.parosproxy.paros.core.scanner.Variant; import org.parosproxy.paros.core.scanner.VariantMultipartFormParameters; import org.parosproxy.paros.network.HttpMessage; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; @@ -35,7 +35,7 @@ public class FileUploadScanRule extends AbstractAppVariantPlugin { private static final String SOLUTION = FileUploadI18n.getMessage("fileupload.scanrule.soln"); private static final String REFERENCE = FileUploadI18n.getMessage("fileupload.scanrule.refs"); private static final Logger LOGGER = Logger.getLogger(FileUploadScanRule.class); - private Variant variant = null; + private List nameValuePairs = null; private AtomicInteger maxRequestCount; @@ -78,17 +78,16 @@ public void decreaseRequestCount() { * it works. */ @Override - public void scan(HttpMessage msg, Variant variant) { + public void scan(HttpMessage msg, List nameValuePairs) { try { - this.variant = variant; - if (variant instanceof VariantMultipartFormParameters) { - List nameValuePairs = variant.getParamList(); + this.nameValuePairs = nameValuePairs; + if (nameValuePairs instanceof VariantMultipartFormParameters) { nameValuePairs.forEach( (nameValuePair) -> LOGGER.error( nameValuePair.getName() + " " + nameValuePair.getValue())); FileUploadAttackExecutor fileUploadAttackExecutor = - new FileUploadAttackExecutor(msg, this, variant); + new FileUploadAttackExecutor(msg, this, nameValuePairs); fileUploadAttackExecutor.executeAttack(); } } catch (Exception ex) { @@ -156,36 +155,20 @@ public int getCategory() { } /** - * Sets the parameter into the given {@code message}. If both parameter name and value are + * Sets the parameters into the given {@code message}. If both parameter name and value are * {@code null}, the parameter will be removed. * * @param message the message that will be changed - * @param originalPair original name value pair - * @param param the name of the parameter - * @param value the value of the parameter + * @param nameValuePairs of the message + * @param params list of name of the parameter + * @param values list of value of the parameter * @return the parameter set - * @see #setEscapedParameter(HttpMessage, NameValuePair, String, String) */ - public String setParameter( - HttpMessage message, NameValuePair originalPair, String param, String value) { - return variant.setParameter(message, originalPair, param, value); - } - - /** - * Sets the parameter into the given {@code message}. If both parameter name and value are - * {@code null}, the parameter will be removed. - * - *

The value is expected to be properly encoded/escaped. - * - * @param message the message that will be changed - * @param originalPair original name value pair - * @param param the name of the parameter - * @param value the value of the parameter - * @return the parameter set - * @see #setParameter(HttpMessage,NameValuePair, String, String) - */ - public String setEscapedParameter( - HttpMessage message, NameValuePair originalPair, String param, String value) { - return variant.setEscapedParameter(message, originalPair, param, value); + public String setParameters( + HttpMessage message, + List nameValuePairs, + List params, + List values) { + return super.setParameters(message, nameValuePairs, params, values); } } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java index f794ad0..da2c00f 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java @@ -14,6 +14,7 @@ package org.sasanlabs.fileupload.attacks; import java.io.IOException; +import java.util.ArrayList; import java.util.List; import java.util.Objects; import org.apache.commons.httpclient.URI; @@ -97,7 +98,7 @@ default boolean genericAttackExecutor( List fileParameters, VulnerabilityType vulnerabilityType) throws IOException, FileUploadException { - List nameValuePairs = fileUploadAttackExecutor.getVariant().getParamList(); + List nameValuePairs = fileUploadAttackExecutor.getNameValuePairs(); HttpMessage originalMsg = fileUploadAttackExecutor.getOriginalHttpMessage(); FileUploadScanRule fileUploadScanRule = fileUploadAttackExecutor.getFileUploadScanRule(); String originalFileName = null; @@ -116,30 +117,32 @@ default boolean genericAttackExecutor( } fileUploadAttackExecutor.getFileUploadScanRule().decreaseRequestCount(); HttpMessage newMsg = originalMsg.cloneRequest(); + List newNameValuePairs = new ArrayList<>(); + List newParamNames = new ArrayList<>(); + List newParamValues = new ArrayList<>(); for (int i = 0; i < nameValuePairs.size(); i++) { NameValuePair nameValuePair = nameValuePairs.get(i); + if (nameValuePair.getType() == NameValuePair.TYPE_MULTIPART_DATA_FILE_NAME + || nameValuePair.getType() == NameValuePair.TYPE_MULTIPART_DATA_FILE_PARAM + || nameValuePair.getType() + == NameValuePair.TYPE_MULTIPART_DATA_FILE_CONTENTTYPE) { + newNameValuePairs.add(nameValuePair); + newParamNames.add(nameValuePair.getName()); + } else { + continue; + } if (nameValuePair.getType() == NameValuePair.TYPE_MULTIPART_DATA_FILE_NAME) { - fileUploadScanRule.setParameter( - newMsg, - nameValuePair, - nameValuePair.getName(), - fileParameter.getFileName(originalFileName)); + newParamValues.add(fileParameter.getFileName(originalFileName)); } else if (nameValuePair.getType() == NameValuePair.TYPE_MULTIPART_DATA_FILE_PARAM) { - fileUploadScanRule.setParameter( - newMsg, nameValuePair, nameValuePair.getName(), payload); + newParamValues.add(fileParameter.getFileName(payload)); } else if (nameValuePair.getType() == NameValuePair.TYPE_MULTIPART_DATA_FILE_CONTENTTYPE) { - fileUploadScanRule.setParameter( - newMsg, - nameValuePair, - nameValuePair.getName(), - fileParameter.getContentType(originalContentType)); - } else { - continue; + newParamValues.add(fileParameter.getFileName(originalContentType)); } - nameValuePairs = fileUploadAttackExecutor.getVariant().getParamList(); } + fileUploadScanRule.setParameters( + newMsg, newNameValuePairs, newParamNames, newParamValues); fileUploadScanRule.sendAndRecieve(newMsg); HttpMessage preflightMsg = this.executePreflightRequest( diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java b/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java index 060ef98..60b8661 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java @@ -13,9 +13,10 @@ */ package org.sasanlabs.fileupload.attacks; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import org.parosproxy.paros.core.scanner.Variant; +import org.parosproxy.paros.core.scanner.NameValuePair; import org.parosproxy.paros.network.HttpMessage; import org.sasanlabs.fileupload.FileUploadScanRule; import org.sasanlabs.fileupload.attacks.rce.jsp.ImageWithJSPSnippetFileUpload; @@ -34,7 +35,7 @@ public class FileUploadAttackExecutor { private HttpMessage originalHttpMessage; private FileUploadScanRule fileUploadScanRule; - private Variant variant; + private List nameValuePairs = new ArrayList<>(); private List attackVectors = Arrays.asList( new HtmlFileUpload(), @@ -45,11 +46,11 @@ public class FileUploadAttackExecutor { public FileUploadAttackExecutor( HttpMessage originalHttpMessage, FileUploadScanRule fileUploadScanRule, - Variant variant) { + List variant) { super(); this.originalHttpMessage = originalHttpMessage; this.fileUploadScanRule = fileUploadScanRule; - this.variant = variant; + this.nameValuePairs = variant; } public boolean executeAttack() throws FileUploadException { @@ -73,8 +74,12 @@ public FileUploadScanRule getFileUploadScanRule() { return fileUploadScanRule; } - public Variant getVariant() { - return variant; + public List getNameValuePairs() { + return nameValuePairs; + } + + public void setNameValuePairs(List nameValuePairs) { + this.nameValuePairs = nameValuePairs; } public List getAttackVectors() { diff --git a/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties b/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties index f1d8495..4b0fe18 100755 --- a/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties +++ b/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties @@ -10,7 +10,7 @@ fileupload.settings.urilocator.dynamiclocation.uriregex=URI Regex fileupload.settings.urilocator.dynamiclocation.startidentifer=Start Identifier fileupload.settings.urilocator.dynamiclocation.endidentifer=End Identifier -fileupload.settings.alert.invalid.dynamicconfigutation=Both dynamic start and end regex should be present. +fileupload.settings.alert.invalid.dynamicconfigutation=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 Scan Rule From a509b335bf90ef5f77d58de121fa569fda21b101 Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Sun, 9 May 2021 16:16:31 +0530 Subject: [PATCH 21/53] Removing commented code --- .../EicarAntivirusTestFileUpload.java | 28 +------------------ 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java index e84dc3d..3d8c7b6 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java @@ -141,33 +141,7 @@ public class EicarAntivirusTestFileUpload implements AttackVector { .withContentType("vnd.microsoft.portable-executable") .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) - .build() - - // new FileParameter("com"), - // new FileParameter("exe"), - // new FileParameter("com", "application/octet-stream"), - // new FileParameter("exe", - // "vnd.microsoft.portable-executable"), - // new FileParameter( - // "com", - // "application/octet-stream", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter( - // "exe", - // "vnd.microsoft.portable-executable", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter("com", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter("exe", - // FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION), - // new FileParameter( - // "exe" + NULL_BYTE_CHARACTER, - // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION), - // new FileParameter( - // "exe" + NULL_BYTE_CHARACTER, - // "vnd.microsoft.portable-executable", - // FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) - ); + .build()); @Override public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) From 0a6dfddda699fb145f90871ae27872d14cca06d6 Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Sun, 16 May 2021 17:36:26 +0530 Subject: [PATCH 22/53] Small Fix --- build.gradle.kts | 4 +- .../fileupload/AbstractAppVariantPlugin.java | 173 ++++++++++++++++++ .../fileupload/FileUploadScanRule.java | 32 +++- .../fileupload/attacks/AttackVector.java | 6 +- .../fileupload/locator/URILocatorImpl.java | 17 +- 5 files changed, 213 insertions(+), 19 deletions(-) create mode 100644 src/main/java/org/sasanlabs/fileupload/AbstractAppVariantPlugin.java diff --git a/build.gradle.kts b/build.gradle.kts index c9c5a71..a5cbceb 100755 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -13,6 +13,7 @@ plugins { repositories { mavenCentral() + mavenLocal() } java { @@ -34,7 +35,7 @@ description = "Detect File upload requests and scan them to find related vulnera zapAddOn { addOnName.set("File upload Scan Rule") - zapVersion.set("2.10.0") + zapVersion.set("2.11.0-SNAPSHOT") addOnStatus.set(AddOnStatus.ALPHA) manifest { @@ -47,5 +48,4 @@ zapAddOn { } dependencies { - //implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar")))) } \ No newline at end of file diff --git a/src/main/java/org/sasanlabs/fileupload/AbstractAppVariantPlugin.java b/src/main/java/org/sasanlabs/fileupload/AbstractAppVariantPlugin.java new file mode 100644 index 0000000..c14512a --- /dev/null +++ b/src/main/java/org/sasanlabs/fileupload/AbstractAppVariantPlugin.java @@ -0,0 +1,173 @@ +/** + * Copyright 2021 SasanLabs + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sasanlabs.fileupload; + +import java.util.List; +import org.apache.log4j.Logger; +import org.parosproxy.paros.Constant; +import org.parosproxy.paros.core.scanner.AbstractAppPlugin; +import org.parosproxy.paros.core.scanner.NameValuePair; +import org.parosproxy.paros.core.scanner.Variant; +import org.parosproxy.paros.model.Model; +import org.parosproxy.paros.network.HttpMessage; +import org.zaproxy.zap.extension.ascan.VariantFactory; + +/** + * {@code AbstractAppVariantPlugin} is the abstract base class which is used to run per variant to + * modify multiple name value pairs of the {@code HttpMessage} per variant. + * + * @author KSASAN preetkaran20@gmail.com + */ +public abstract class AbstractAppVariantPlugin extends AbstractAppPlugin { + + private final Logger logger = Logger.getLogger(this.getClass()); + private Variant variant; + + @Override + public void scan() { + VariantFactory factory = Model.getSingleton().getVariantFactory(); + + List listVariant = + factory.createVariants(this.getParent().getScannerParam(), this.getBaseMsg()); + + if (listVariant.isEmpty()) { + getParent() + .pluginSkipped( + this, + Constant.messages.getString( + "ascan.progress.label.skipped.reason.noinputvectors")); + return; + } + + for (int i = 0; i < listVariant.size() && !isStop(); i++) { + + HttpMessage msg = getNewMsg(); + // ZAP: Removed unnecessary cast. + Variant variant = listVariant.get(i); + try { + variant.setMessage(msg); + scanVariant(variant); + + } catch (Exception e) { + logger.error( + "Error occurred while scanning with variant " + + variant.getClass().getCanonicalName(), + e); + } + + // ZAP: Implement pause and resume + while (getParent().isPaused() && !isStop()) { + try { + Thread.sleep(500); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + } + + /** Scan the current message using the current Variant */ + private void scanVariant(Variant variant) { + HttpMessage msg = getNewMsg(); + try { + this.variant = variant; + scan(msg, variant.getParamList()); + } catch (Exception e) { + logger.error("Error occurred while scanning a message:", e); + } + } + + /** + * Scan the current message using the provided Variant + * + * @param msg a copy of the HTTP message currently under scanning + * @param nameValuePairs ParamList of a Variant + */ + public abstract void scan(HttpMessage msg, List nameValuePairs); + + /** + * Sets the parameter into the given {@code message}. If both parameter name and value are + * {@code null}, the parameter will be removed. + * + * @param message the message that will be changed + * @param nameValuePair of the message + * @param param the name of the parameter + * @param value the value of the parameter + * @return the parameter set + * @see #setEscapedParameter(HttpMessage, NameValuePair, String, String) + */ + protected String setParameter( + HttpMessage message, NameValuePair nameValuePair, String param, String value) { + return variant.setParameter(message, nameValuePair, param, value); + } + + /** + * Sets the parameters into the given {@code message}. If both parameter name and value are + * {@code null}, the parameter will be removed. + * + *

The value is expected to be properly encoded/escaped. + * + * @param message the message that will be changed + * @param nameValuePairs of the message + * @param params list of name of the parameter + * @param values list of value of the parameter + * @return the parameter set + * @see #setParameters(HttpMessage, List, List, List) + */ + protected String setEscapedParameters( + HttpMessage message, + List nameValuePairs, + List params, + List values) { + return variant.setEscapedParameters(message, nameValuePairs, params, values); + } + + /** + * Sets the parameters into the given {@code message}. If both parameter name and value are + * {@code null}, the parameter will be removed. + * + * @param message the message that will be changed + * @param nameValuePairs of the message + * @param params list of name of the parameter + * @param values list of value of the parameter + * @return the parameter set + * @see #setEscapedParameters(HttpMessage, List, List, List) + */ + protected String setParameters( + HttpMessage message, + List nameValuePairs, + List params, + List values) { + return variant.setParameters(message, nameValuePairs, params, values); + } + + /** + * Sets the parameter into the given {@code message}. If both parameter name and value are + * {@code null}, the parameter will be removed. + * + *

The value is expected to be properly encoded/escaped. + * + * @param message the message that will be changed + * @param nameValuePair of the message + * @param param the name of the parameter + * @param value the value of the parameter + * @return the parameter set + * @see #setParameter(HttpMessage, NameValuePair, String, String) + */ + protected String setEscapedParameter( + HttpMessage message, NameValuePair nameValuePair, String param, String value) { + return variant.setEscapedParameter(message, nameValuePair, param, value); + } +} diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java index 7c93423..7d1b487 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java @@ -17,10 +17,8 @@ import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import org.apache.log4j.Logger; -import org.parosproxy.paros.core.scanner.AbstractAppVariantPlugin; import org.parosproxy.paros.core.scanner.Category; import org.parosproxy.paros.core.scanner.NameValuePair; -import org.parosproxy.paros.core.scanner.VariantMultipartFormParameters; import org.parosproxy.paros.network.HttpMessage; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; import org.sasanlabs.fileupload.i18n.FileUploadI18n; @@ -35,7 +33,6 @@ public class FileUploadScanRule extends AbstractAppVariantPlugin { private static final String SOLUTION = FileUploadI18n.getMessage("fileupload.scanrule.soln"); private static final String REFERENCE = FileUploadI18n.getMessage("fileupload.scanrule.refs"); private static final Logger LOGGER = Logger.getLogger(FileUploadScanRule.class); - private List nameValuePairs = null; private AtomicInteger maxRequestCount; @@ -43,19 +40,19 @@ public class FileUploadScanRule extends AbstractAppVariantPlugin { public void init() { switch (this.getAttackStrength()) { case LOW: - maxRequestCount = new AtomicInteger(20); + maxRequestCount = new AtomicInteger(30); break; case MEDIUM: - maxRequestCount = new AtomicInteger(30); + maxRequestCount = new AtomicInteger(60); break; case HIGH: - maxRequestCount = new AtomicInteger(40); + maxRequestCount = new AtomicInteger(90); break; case INSANE: - maxRequestCount = new AtomicInteger(50); + maxRequestCount = new AtomicInteger(150); break; default: - maxRequestCount = new AtomicInteger(30); + maxRequestCount = new AtomicInteger(60); break; } } @@ -80,8 +77,23 @@ public void decreaseRequestCount() { @Override public void scan(HttpMessage msg, List nameValuePairs) { try { - this.nameValuePairs = nameValuePairs; - if (nameValuePairs instanceof VariantMultipartFormParameters) { + boolean isMultipart = false; + if (nameValuePairs != null) { + isMultipart = + nameValuePairs.stream() + .anyMatch( + nameValuePair -> + nameValuePair.getType() + == NameValuePair + .TYPE_MULTIPART_DATA_FILE_NAME + || nameValuePair.getType() + == NameValuePair + .TYPE_MULTIPART_DATA_FILE_PARAM + || nameValuePair.getType() + == NameValuePair + .TYPE_MULTIPART_DATA_FILE_CONTENTTYPE); + } + if (isMultipart) { nameValuePairs.forEach( (nameValuePair) -> LOGGER.error( diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java index da2c00f..edf06e9 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java @@ -84,7 +84,7 @@ default void raiseAlert( FileUploadI18n.getMessage(vulnerabilityType.getMessageKey() + ".name"), FileUploadI18n.getMessage(vulnerabilityType.getMessageKey() + ".desc"), newMsg.getRequestHeader().getURI().toString(), - newMsg.toString(), + newMsg.getRequestBody().toString(), payload, FileUploadI18n.getMessage(vulnerabilityType.getMessageKey() + ".refs"), FileUploadI18n.getMessage(vulnerabilityType.getMessageKey() + ".soln"), @@ -135,10 +135,10 @@ default boolean genericAttackExecutor( newParamValues.add(fileParameter.getFileName(originalFileName)); } else if (nameValuePair.getType() == NameValuePair.TYPE_MULTIPART_DATA_FILE_PARAM) { - newParamValues.add(fileParameter.getFileName(payload)); + newParamValues.add(payload); } else if (nameValuePair.getType() == NameValuePair.TYPE_MULTIPART_DATA_FILE_CONTENTTYPE) { - newParamValues.add(fileParameter.getFileName(originalContentType)); + newParamValues.add(fileParameter.getContentType(originalContentType)); } } fileUploadScanRule.setParameters( diff --git a/src/main/java/org/sasanlabs/fileupload/locator/URILocatorImpl.java b/src/main/java/org/sasanlabs/fileupload/locator/URILocatorImpl.java index 0f05590..22b13c6 100644 --- a/src/main/java/org/sasanlabs/fileupload/locator/URILocatorImpl.java +++ b/src/main/java/org/sasanlabs/fileupload/locator/URILocatorImpl.java @@ -51,12 +51,13 @@ private URI getCompleteURI(String uriRegex, String fileName, HttpMessage msg) if (uriFragment.startsWith(FileUploadUtils.HTTP_SCHEME) || uriRegex.startsWith(FileUploadUtils.HTTP_SECURED_SCHEME)) { return new URI(uriFragment, true); - } else if (uriFragment.startsWith(FileUploadUtils.SLASH)) { + } else { + if (!uriFragment.startsWith(FileUploadUtils.SLASH)) { + uriFragment = FileUploadUtils.SLASH + uriFragment; + } String authority = msg.getRequestHeader().getURI().getAuthority(); String scheme = msg.getRequestHeader().getURI().getScheme(); return new URI(scheme, authority, uriFragment, ""); - } else { - throw new FileUploadException("FileUpload configuration is invalid."); } } @@ -82,7 +83,15 @@ private URI parseResponseAndGetCompleteURI( + " End index:" + endIndex); } - String uriRegex = msg.getResponseBody().toString().substring(startIndex, endIndex); + String uriRegex = + msg.getResponseBody() + .toString() + .substring( + startIndex + + FileUploadConfiguration.getInstance() + .getDynamicLocationStartIdentifier() + .length(), + endIndex); return this.getCompleteURI(uriRegex, fileName, originalMsg); } From 933ab3a35e9fca027ccb9d6fad404c0d9904dfad Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Sun, 16 May 2021 18:13:20 +0530 Subject: [PATCH 23/53] Updating javadoc --- CHANGELOG.md | 6 +++++ .../fileupload/FileUploadScanRule.java | 19 ++++++++-------- .../sasanlabs/fileupload/FileUploadUtils.java | 22 ++++++++++++++++++- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3383d68..9e1cb19 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,3 +8,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - First version of FileUpload Addon. - Contains scan rule for finding vulnerabilities related to File Upload. + - Types of uploaded files include: + - Html and its variants + - JSP and its variants + - Jpeg and Gif images + - Eicar file + - SVG images \ No newline at end of file diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java index 7d1b487..2c6c94d 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java @@ -23,7 +23,16 @@ import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; import org.sasanlabs.fileupload.i18n.FileUploadI18n; -/** @author KSASAN preetkaran20@gmail.com */ +/** + * {@code FileUploadScanRule} is used to find the vulnerabilities in File Upload functionality of + * applications. The scan rule uploads multiple types of files containing vulnerable code to check + * if the application is vulnerable. + * + *

This addon fires a lot of requests to the target application hence can impacts the performance + * of the targeted application. So please run this addon in non-prod environment only. + * + * @author KSASAN preetkaran20@gmail.com + */ public class FileUploadScanRule extends AbstractAppVariantPlugin { private static final int PLUGIN_ID = 110009; @@ -66,14 +75,6 @@ public void decreaseRequestCount() { this.maxRequestCount.getAndDecrement(); } - /* - * Need to check what to include do we need to include XXE/XSS/Path Traversal in - * this addon or we need to correct those. Persistent XXS/XXE/PathTraversal - * might be different - * - * Will not include the reflected XSS because it should work and i have checked - * it works. - */ @Override public void scan(HttpMessage msg, List nameValuePairs) { try { diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java b/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java index 8c80839..f8df316 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java @@ -67,6 +67,16 @@ static String getExtension(String fileName) { return null; } + /** + * Checks whether {@code Content-Disposition} header is inline and if so returns {@code True} + * else {@code False} + * + *

This utility is useful to find if XSS is possible or not because if {@code + * Content-Disposition} header is inline then only XSS is possible. + * + * @param preflightMsg + * @return {@code True} if {@code Content-Disposition} header is inline + */ static boolean isContentDispositionInline(HttpMessage preflightMsg) { String headerValue = preflightMsg.getResponseHeader().getHeader("Content-Disposition"); if (headerValue == null @@ -82,11 +92,21 @@ static boolean isContentTypeHeaderPresent(HttpMessage preflightMsg) { return StringUtils.isNotBlank(headerValue); } + /** + * References {@link + * https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#RULE_.233.1_-_HTML_escape_JSON_values_in_an_HTML_context_and_read_the_data_with_JSON.parse:#:~:text=Good%20HTTP%20response:} + * and {@link + * https://security.stackexchange.com/questions/169427/impact-of-the-response-content-type-on-the-exploitability-of-xss} + * + * @param preflightMsg + * @return {@code True} is content type is one of {@code FileUploadUtils#HTML_MIME_TYPE} or + * {@code FileUploadUtils#XHTML_MIME_TYPE} or {@code FileUploadUtils#SVG_MIME_TYPE} + */ static boolean isContentTypeCausesJavascriptExecution(HttpMessage preflightMsg) { String headerValue = preflightMsg.getResponseHeader().getHeader(HttpHeader.CONTENT_TYPE); return StringUtils.isNotBlank(headerValue) && (headerValue.equalsIgnoreCase(HTML_MIME_TYPE) || headerValue.equalsIgnoreCase(XHTML_MIME_TYPE) - || headerValue.equalsIgnoreCase(XHTML_MIME_TYPE)); + || headerValue.equalsIgnoreCase(SVG_MIME_TYPE)); } } From bab146e35b019c496e4a14730dc7c2d5870c82fd Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Sun, 16 May 2021 19:29:12 +0530 Subject: [PATCH 24/53] Updating comments --- .../sasanlabs/fileupload/FileUploadUtils.java | 2 +- .../fileupload/attacks/AttackVector.java | 44 ++++++++++++++++--- .../attacks/FileUploadAttackExecutor.java | 2 + .../EicarAntivirusTestFileUpload.java | 6 +-- .../attacks/beans/FileParameter.java | 14 ++++++ .../attacks/beans/VulnerabilityType.java | 6 +++ .../fileupload/attacks/rce/PathTraversal.java | 38 +++++----------- .../fileupload/attacks/rce/leftItems.java | 26 ----------- .../fileupload/attacks/rce/php/PhpRCE.java | 24 +++++----- .../fileupload/matcher/ContentMatcher.java | 8 +++- .../matcher/impl/MD5HashResponseMatcher.java | 3 +- .../fileupload/i18n/Messages.properties | 10 +---- 12 files changed, 99 insertions(+), 84 deletions(-) delete mode 100644 src/main/java/org/sasanlabs/fileupload/attacks/rce/leftItems.java diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java b/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java index f8df316..c64ebd8 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java @@ -19,7 +19,7 @@ import org.parosproxy.paros.network.HttpMessage; /** - * Contains the String constants or other utility constants used by the File Upload Addon. + * Contains the String constants or other utility functions used by the Addon. * * @author preetkaran20@gmail.com KSASAN */ diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java index edf06e9..8335280 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java @@ -30,14 +30,22 @@ import org.sasanlabs.fileupload.matcher.ContentMatcher; /** - * {@code AttackVector} interface is implemented by various attack vector implementations e.g. XSS, - * JSP RCE, PHP RCE etc. + * {@code AttackVector} is a common interface for file upload attacks which implements this + * interface. This interface also contains few utility methods for raising alerts and firing + * Preflight requests. * * @author KSASAN preetkaran20@gmail.com */ public interface AttackVector { /** + * In general file upload functionalities, file is uploaded from a one endpoint and retrieved + * from a another endpoint which makes it extremely difficult to automate. Preflight request is + * the request to another endpoint for retrieval of uploaded file. + * + *

This method finds the url of the file retrieval endpoint, invokes that endpoint and + * returns the {@code HttpMessage}. + * * @param modifiedMsg * @param fileUploadScanRule * @return httpMessage of preflight request @@ -66,6 +74,8 @@ default HttpMessage executePreflightRequest( } /** + * This method is used to raise the alert if a vulnerability is found. + * * @param fileUploadScanRule * @param vulnerabilityType * @param payload @@ -91,6 +101,25 @@ default void raiseAlert( preflight); } + /** + * For File Upload vulnerability there are 3 important steps: 1. modify the actual {@code + * HttpMessage} based on the type of attack 2. firing Preflight request 3. response content + * matching to validate if vulnerability is present or not. + * + *

This method executes all these steps. It modifies the {@code HttpMessage} based on the + * {@code fileParameters} then uses {@link #executePreflightRequest(HttpMessage, String, + * FileUploadScanRule)} to execute the Preflight request and then uses the {@code + * ContentMatcher} for validating whether vulnerability is present or not. + * + * @param fileUploadAttackExecutor + * @param contentMatcher + * @param payload + * @param fileParameters + * @param vulnerabilityType + * @return {@code True} if attack is successful else {@code False} + * @throws IOException + * @throws FileUploadException + */ default boolean genericAttackExecutor( FileUploadAttackExecutor fileUploadAttackExecutor, ContentMatcher contentMatcher, @@ -157,10 +186,13 @@ default boolean genericAttackExecutor( return false; } - // Flexi Injector is quite easy as in case uploaded files are base64 encoded or - // something like that - // the scanner asks for the input file and then compare the request (whcih might - // be encoded) with the input and then operate accordingly. + /** + * TODO: As we are only handling Multipart requests hence in case User interface of Application + * is using Javascript filereader Api or using some other ways our scan rule will not work. + * + *

Upload Scanner addon of Burp has handled this by asking the sample request {@link + * https://github.com/portswigger/upload-scanner#flexiinjector---detecting-requests-with-uploads} + */ /** * Executes the attack and checks if it is successful or not and then raise alert in case of diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java b/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java index 60b8661..85ac496 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java @@ -23,6 +23,7 @@ import org.sasanlabs.fileupload.attacks.rce.jsp.SimpleJSPFileUpload; import org.sasanlabs.fileupload.attacks.rce.jsp.SimpleJSPXFileUpload; import org.sasanlabs.fileupload.attacks.xss.HtmlFileUpload; +import org.sasanlabs.fileupload.attacks.xss.SVGFileUpload; import org.sasanlabs.fileupload.exception.FileUploadException; /** @@ -39,6 +40,7 @@ public class FileUploadAttackExecutor { private List attackVectors = Arrays.asList( new HtmlFileUpload(), + new SVGFileUpload(), new SimpleJSPFileUpload(), new SimpleJSPXFileUpload(), new ImageWithJSPSnippetFileUpload()); diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java index 3d8c7b6..cb3b4c0 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java @@ -31,9 +31,9 @@ import org.sasanlabs.fileupload.matcher.impl.MD5HashResponseMatcher; /** - * {@code EicarAntivirusTestFileUpload} attack vector is used to check the if antivirus is present - * and working properly by uploading the Eicar test file. General idea is to upload the Eicar Test - * file and if we are able to download it again then that means there are chances that Antivirus is + * {@code EicarAntivirusTestFileUpload} attack vector is used to check if antivirus is present and + * working properly by uploading the Eicar test file. General idea is to upload the Eicar Test file + * and if we are able to download it again then that means there are chances that Antivirus is * either not present or not working properly. * *

For more information about Eicar file please visit HTML_EXTENSIONS = Arrays.asList("htm", "html", "xhtml"); - // private static final List CONTENT_TYPES = - // Arrays.asList(Constants.EMPTY_STRING,"text/html", "text/plain"); - // - // private static final ContentMatcher CONTENT_MATCHER = new MD5HashResponseMatcher(); - // - // @Override - // public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) throws - // FileUploadException { - // // TODO Auto-generated method stub - // return false; - // } +import org.sasanlabs.fileupload.attacks.AttackVector; +import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; +import org.sasanlabs.fileupload.exception.FileUploadException; - // private boolean isContentDispositionInline(HttpMessage preflightMsg) { - // String headerValue = preflightMsg.getResponseHeader().getHeader("Content-Disposition"); - // if (headerValue == null || headerValue.trim().equals(Constants.EMPTY_STRING) || - // headerValue.equals("inline")) { - // return true; - // } - // return false; - // } +/** @author KSASAN preetkaran20@gmail.com */ +public class PathTraversal implements AttackVector { + @Override + public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) + throws FileUploadException { + // TODO Auto-generated method stub + return false; + } } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/leftItems.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/leftItems.java deleted file mode 100644 index 7658cad..0000000 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/leftItems.java +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Copyright 2021 SasanLabs - * - *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of the License at - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sasanlabs.fileupload.attacks.rce; -/** - * https://book.hacktricks.xyz/pentesting-web/file-upload - * - *

reverse double extension attack - * - *

https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload - * https://blog.doyensec.com/2020/04/30/polymorphic-images-for-xss.html - * https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a - * - *

BIT MAP based XSS - */ -public class leftItems {} diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/php/PhpRCE.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/php/PhpRCE.java index 2bfb868..db7ffd1 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/php/PhpRCE.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/php/PhpRCE.java @@ -12,13 +12,17 @@ * limitations under the License. */ package org.sasanlabs.fileupload.attacks.rce.php; -/** - * https://vulp3cula.gitbook.io/hackers-grimoire/exploitation/web-application/file-upload-bypass - * - * @author KSASAN preetkaran20@gmail.com - *

Eicar -> try uploading and downloading file and if you are able to do so that means there - * is no antivirus present on server hence we know that any virus can impact the server. - * https://www.youtube.com/watch?v=gPo-NPvuqbs (For Vulnerable Application we might need to have - * some docker with antivirus in it.) - */ -public class PhpRCE {} + +import org.sasanlabs.fileupload.attacks.AttackVector; +import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; +import org.sasanlabs.fileupload.exception.FileUploadException; + +public class PhpRCE implements AttackVector { + + @Override + public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) + throws FileUploadException { + // TODO Auto-generated method stub + return false; + } +} diff --git a/src/main/java/org/sasanlabs/fileupload/matcher/ContentMatcher.java b/src/main/java/org/sasanlabs/fileupload/matcher/ContentMatcher.java index 89c29c3..8438191 100644 --- a/src/main/java/org/sasanlabs/fileupload/matcher/ContentMatcher.java +++ b/src/main/java/org/sasanlabs/fileupload/matcher/ContentMatcher.java @@ -16,11 +16,17 @@ import org.parosproxy.paros.network.HttpMessage; /** - * {@code ContentMatcher} class is used to compare the contents of + * {@code ContentMatcher} class is used to match the contents of provided Preflight {@code + * HttpMessage} * * @author preetkaran20@gmail.com KSASAN */ +@FunctionalInterface public interface ContentMatcher { + /** + * @param msg Preflight {@code HttpMessage} + * @return {@code True} if content of Preflight {@code HttpMessage} matches else {@code False} + */ boolean match(HttpMessage msg); } diff --git a/src/main/java/org/sasanlabs/fileupload/matcher/impl/MD5HashResponseMatcher.java b/src/main/java/org/sasanlabs/fileupload/matcher/impl/MD5HashResponseMatcher.java index 42cc057..a08dd7e 100644 --- a/src/main/java/org/sasanlabs/fileupload/matcher/impl/MD5HashResponseMatcher.java +++ b/src/main/java/org/sasanlabs/fileupload/matcher/impl/MD5HashResponseMatcher.java @@ -24,7 +24,8 @@ import org.sasanlabs.fileupload.matcher.ContentMatcher; /** - * {@code MD5HashResponseMatcher} matches {@code MD5} hashes of both the contents + * {@code MD5HashResponseMatcher} matches if the expected value's {@code MD5} hash is same as + * provided {@code HttpMessage} response's {@code MD5} hash. * * @author KSASAN preetkaran20@gmail.com */ diff --git a/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties b/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties index 4b0fe18..7a22277 100755 --- a/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties +++ b/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties @@ -88,12 +88,4 @@ fileupload.scanner.vulnerability.antiVirusEicarFile.description=Eicar antivirus detected by the antivirus. This means that either antivirus is not present or antivirus doesn't support Eicar. As per https://www.virustotal.com/ eicar file is supported by 63 Antiviruses out of 67. fileupload.scanner.vulnerability.antiVirusEicarFile.refs=https://en.wikipedia.org/wiki/EICAR_test_file fileupload.scanner.vulnerability.antiVirusEicarFile.soln= Consider checking the antivirus setup in server, in case the antivirus supports Eicar standards and still doesn't report issue, try fixing it.\ -https://owasp.org/www-project-web-security-testing-guide/stable/4-Web_Application_Security_Testing/10-Business_Logic_Testing/09-Test_Upload_of_Malicious_Files.html#malware - - - - - - - - +https://owasp.org/www-project-web-security-testing-guide/stable/4-Web_Application_Security_Testing/10-Business_Logic_Testing/09-Test_Upload_of_Malicious_Files.html#malware \ No newline at end of file From dfe864bbedd2241cc3aa7b6efdc52b1cf7659052 Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Sun, 16 May 2021 23:03:24 +0530 Subject: [PATCH 25/53] Handling Readme --- README.md | 28 +++++++++++++++++-- .../fileupload/locator/URILocator.java | 2 -- .../fileupload/locator/URILocatorImpl.java | 3 +- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 022ff1e..56ad7f5 100755 --- a/README.md +++ b/README.md @@ -1,3 +1,27 @@ -# owasp-zap-fileupload-addon -File Upload Scan Rule +# owasp-zap-fileupload-addon +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com) ![Java CI with Gradle](https://github.com/SasanLabs/owasp-zap-jwt-addon/workflows/Java%20CI%20with%20Gradle/badge.svg?branch=master) +This project contains the File Upload scan rule which is used to find the vulnerabilities in File Upload functionality. + +## Why this addon is needed +File upload is becoming a more and more essential part of any application, where the user is able to upload their photo, their CV, or a video showcasing a project they are working on. The application should be able to fend off bogus and malicious files in a way to keep the application and the users safe. Generally file upload functionality is quite complex to automate and has huge attack surface hence there is a need to automate the process and also secure it. + +## Configuration +File upload functionality generally has 2 endpoints, one from where file is uploaded and one from where file is retrieved. It neccessary to know both these endpoints. While Active Scanning the application, file upload endpoint is already known but retrieval endpoint is not known to the scan rule hence there are configuration details specific to the retrieval endpoint. + +Under ZAP's Options dialog you will find a JWT section as shown below: +![File Upload Options Panel](./docs/images/fileupload-options-panel.png) + +### Explanation +For finding the url to retrieve the uploaded file, following are the options: +1. In some applications the url to retrieve the uploaded file is static and doesn't change or only the file name is changed. For handling this type of configuration, options panel has `Static Location Configuration` where static url is added into `URI Regex` field. `URI Regex` field also supports the dynamic file name by `${fileName}` +parameter, for e.g. `http:///${fileName}` +2. In some applications the url to retrieve the uploaded file is present in the file upload request's response. For handling this type of configuration, options panel has `Dynamic Location Configuration` which has 2 `Start Identifer` and `End Identifier`. These identifiers are used to locate the Url in the response. +3. In some applications the url to retrieve the uploaded file is present in the response of a different url which is called preflight request. E.g. Profile picture url is part of profile page and hence we need to parse the response of the profile page to find the url of the profile picture. For handling this type of configuration, options panel has `Dynamic Location Configuration` which has a `URI Regex`, `Start Identifier` and `End Identifier`. So File upload addon will invoke the Uri mentioned in `URI Regex` and then part the response using `Start Identifier` and `End Identifier`. `URI Regex` field also supports the dynamic file name by `${fileName}` + +## Contributing guidelines +Contributing guidelines are same as [ZAP](https://github.com/zaproxy/zaproxy). + +## Contact Us +For any Queries/Bugs or Enhancement please raise an issue in this repository or [ZAP](https://github.com/zaproxy/zaproxy). +For any other kind of issues please send an email to karan.sasan@owasp.org \ No newline at end of file diff --git a/src/main/java/org/sasanlabs/fileupload/locator/URILocator.java b/src/main/java/org/sasanlabs/fileupload/locator/URILocator.java index b34508c..b0a83ef 100644 --- a/src/main/java/org/sasanlabs/fileupload/locator/URILocator.java +++ b/src/main/java/org/sasanlabs/fileupload/locator/URILocator.java @@ -23,8 +23,6 @@ * {@code URILocator} class is used to find the URL either by parsing the {@code HttpMessage} or * reading the configuration mentioned in the options tab. * - *

This class also handles the "regex based configuration" e.g "url/{$fileName}" - * * @author preetkaran20@gmail.com KSASAN */ public interface URILocator { diff --git a/src/main/java/org/sasanlabs/fileupload/locator/URILocatorImpl.java b/src/main/java/org/sasanlabs/fileupload/locator/URILocatorImpl.java index 22b13c6..3ae79c6 100644 --- a/src/main/java/org/sasanlabs/fileupload/locator/URILocatorImpl.java +++ b/src/main/java/org/sasanlabs/fileupload/locator/URILocatorImpl.java @@ -29,7 +29,8 @@ /** * {@code URILocatorImpl} class is used to find the URL either by 1. returning the static url - * mentioned by user in Options tab 2. parsing the original {@code HttpMessage} and using dynamic + * mentioned by user in Options tab. This also handles the dynamic file names e.g. + * http:///${fileName} 2. parsing the original {@code HttpMessage} and using dynamic * configuration to find the complete URI. 3. Invokes the preflight request as mentioned by dynamic * configuration and then parsing the preflighted {@code HttpMessage} * From a550e1bfae574de8530df21bc5f08c547d449391 Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Sun, 16 May 2021 23:03:57 +0530 Subject: [PATCH 26/53] Adding images --- docs/DesignDocument.md | 0 docs/fileupload-options-panel.png | Bin 0 -> 209385 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/DesignDocument.md create mode 100644 docs/fileupload-options-panel.png diff --git a/docs/DesignDocument.md b/docs/DesignDocument.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/fileupload-options-panel.png b/docs/fileupload-options-panel.png new file mode 100644 index 0000000000000000000000000000000000000000..fa00c220557a1eff2f3328566c79014d3ef6d9ec GIT binary patch literal 209385 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

g=FuplYr&M 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
+2WWjPwbdbz;ApD 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
PL%I*<-;~3Z<))3o^J$z#R<4X4Fh7%e2Kl}-4 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 literal 0 HcmV?d00001 From 51db1163994fda4a1570de39058b256e9468a65d Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Sun, 16 May 2021 23:08:31 +0530 Subject: [PATCH 27/53] Minor improvement --- docs/DesignDocument.md | 0 docs/fileupload-options-panel.png | Bin 209385 -> 202986 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 docs/DesignDocument.md diff --git a/docs/DesignDocument.md b/docs/DesignDocument.md deleted file mode 100644 index e69de29..0000000 diff --git a/docs/fileupload-options-panel.png b/docs/fileupload-options-panel.png index fa00c220557a1eff2f3328566c79014d3ef6d9ec..7fc48f886c88665b11935174820dacc2130eda29 100644 GIT binary patch literal 202986 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ξB9? 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 literal 209385 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

g=FuplYr&M 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
+2WWjPwbdbz;ApD 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
PL%I*<-;~3Z<))3o^J$z#R<4X4Fh7%e2Kl}-4 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 From a678b4ab519b55e9a224363253e8f60a862ad05f Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Wed, 19 May 2021 22:18:02 +0530 Subject: [PATCH 28/53] Apply suggestions from code review Co-authored-by: Rick M --- README.md | 16 ++++++++-------- .../sasanlabs/fileupload/FileUploadUtils.java | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 56ad7f5..80281d7 100755 --- a/README.md +++ b/README.md @@ -4,24 +4,24 @@ This project contains the File Upload scan rule which is used to find the vulnerabilities in File Upload functionality. ## Why this addon is needed -File upload is becoming a more and more essential part of any application, where the user is able to upload their photo, their CV, or a video showcasing a project they are working on. The application should be able to fend off bogus and malicious files in a way to keep the application and the users safe. Generally file upload functionality is quite complex to automate and has huge attack surface hence there is a need to automate the process and also secure it. +File upload is becoming a more and more essential part of any application, where the user is able to upload their photo, their CV, or a video showcasing a project they are working on. The application should be able to fend off bogus and malicious files in a way to keep the application and the users safe. Generally file upload functionality is quite complex to automate and has huge attack surface hence there is a need to automate the process and also secure it. ## Configuration -File upload functionality generally has 2 endpoints, one from where file is uploaded and one from where file is retrieved. It neccessary to know both these endpoints. While Active Scanning the application, file upload endpoint is already known but retrieval endpoint is not known to the scan rule hence there are configuration details specific to the retrieval endpoint. +File upload functionality generally has 2 endpoints, one from where file is uploaded and one from where file is retrieved. It is necessary to know both these endpoints. While Active Scanning an application, file upload endpoint is already known but retrieval endpoint is not known to the scan rule hence there are configuration details specific to the retrieval endpoint. -Under ZAP's Options dialog you will find a JWT section as shown below: +Under ZAP's Options dialog you will find a File Upload section as shown below: ![File Upload Options Panel](./docs/images/fileupload-options-panel.png) ### Explanation -For finding the url to retrieve the uploaded file, following are the options: -1. In some applications the url to retrieve the uploaded file is static and doesn't change or only the file name is changed. For handling this type of configuration, options panel has `Static Location Configuration` where static url is added into `URI Regex` field. `URI Regex` field also supports the dynamic file name by `${fileName}` +For finding the URL to retrieve/view the uploaded file, here are some options: +1. In some applications the URL to retrieve the uploaded file is static and doesn't change or only the file name is changed. For handling this type of configuration, options panel has `Static Location Configuration` where static URL is added into `URI Regex` field. `URI Regex` field also supports the dynamic file name by `${fileName}`. parameter, for e.g. `http:///${fileName}` -2. In some applications the url to retrieve the uploaded file is present in the file upload request's response. For handling this type of configuration, options panel has `Dynamic Location Configuration` which has 2 `Start Identifer` and `End Identifier`. These identifiers are used to locate the Url in the response. -3. In some applications the url to retrieve the uploaded file is present in the response of a different url which is called preflight request. E.g. Profile picture url is part of profile page and hence we need to parse the response of the profile page to find the url of the profile picture. For handling this type of configuration, options panel has `Dynamic Location Configuration` which has a `URI Regex`, `Start Identifier` and `End Identifier`. So File upload addon will invoke the Uri mentioned in `URI Regex` and then part the response using `Start Identifier` and `End Identifier`. `URI Regex` field also supports the dynamic file name by `${fileName}` +2. In some applications the URL to retrieve the uploaded file is present in the file upload request's response. For handling this type of configuration, options panel has `Dynamic Location Configuration` which has 2 parameters `Start Identifier` and `End Identifier`. These identifiers are used to locate the URL within the response. +3. In some applications the URL to retrieve the uploaded file is present in the response of a different URL which is called a preflight request. E.g. Profile picture URL is part of profile page and hence we need to parse the response of the profile page to find the URL of the profile picture. For handling this type of configuration, the options panel has `Dynamic Location Configuration` which has a `URI Regex`, `Start Identifier`, and `End Identifier`. So the File Upload add-on will invoke the URI mentioned in `URI Regex` and then parse the response using `Start Identifier` and `End Identifier`. `URI Regex` field also supports the dynamic file name by `${fileName}` ## Contributing guidelines Contributing guidelines are same as [ZAP](https://github.com/zaproxy/zaproxy). ## Contact Us For any Queries/Bugs or Enhancement please raise an issue in this repository or [ZAP](https://github.com/zaproxy/zaproxy). -For any other kind of issues please send an email to karan.sasan@owasp.org \ No newline at end of file +For any other kind of issues please send an email to karan.sasan@owasp.org diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java b/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java index c64ebd8..8450a49 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java @@ -99,7 +99,7 @@ static boolean isContentTypeHeaderPresent(HttpMessage preflightMsg) { * https://security.stackexchange.com/questions/169427/impact-of-the-response-content-type-on-the-exploitability-of-xss} * * @param preflightMsg - * @return {@code True} is content type is one of {@code FileUploadUtils#HTML_MIME_TYPE} or + * @return {@code True} if content type is one of {@code FileUploadUtils#HTML_MIME_TYPE} or * {@code FileUploadUtils#XHTML_MIME_TYPE} or {@code FileUploadUtils#SVG_MIME_TYPE} */ static boolean isContentTypeCausesJavascriptExecution(HttpMessage preflightMsg) { From b7200c2d2c56ca0963f61a0cc1e5412ca2b35da5 Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Wed, 19 May 2021 22:38:35 +0530 Subject: [PATCH 29/53] Review comments --- CHANGELOG.md | 6 +++--- README.md | 0 build.gradle.kts | 4 ++-- .../{FileUploadExtension.java => ExtensionFileUpload.java} | 0 4 files changed, 5 insertions(+), 5 deletions(-) mode change 100755 => 100644 CHANGELOG.md mode change 100755 => 100644 README.md mode change 100755 => 100644 build.gradle.kts rename src/main/java/org/sasanlabs/fileupload/{FileUploadExtension.java => ExtensionFileUpload.java} (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md old mode 100755 new mode 100644 index 9e1cb19..03e5e9d --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,8 +9,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - First version of FileUpload Addon. - Contains scan rule for finding vulnerabilities related to File Upload. - Types of uploaded files include: - - Html and its variants + - HTML and its variants - JSP and its variants - - Jpeg and Gif images - - Eicar file + - JPEG and GIF images + - EICAR file - SVG images \ No newline at end of file diff --git a/README.md b/README.md old mode 100755 new mode 100644 diff --git a/build.gradle.kts b/build.gradle.kts old mode 100755 new mode 100644 index a5cbceb..f3bb221 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,9 +6,9 @@ import org.zaproxy.gradle.addon.misc.ExtractLatestChangesFromChangelog plugins { id("com.diffplug.gradle.spotless") version "3.27.2" - id("com.github.ben-manes.versions") version "0.28.0" + id("com.github.ben-manes.versions") version "0.38.0" `java-library` - id("org.zaproxy.add-on") version "0.3.0" + id("org.zaproxy.add-on") version "0.5.0" } repositories { diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadExtension.java b/src/main/java/org/sasanlabs/fileupload/ExtensionFileUpload.java similarity index 100% rename from src/main/java/org/sasanlabs/fileupload/FileUploadExtension.java rename to src/main/java/org/sasanlabs/fileupload/ExtensionFileUpload.java From f6411e2394621fb94df573ecbe1a9c4a8c8d724a Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Wed, 19 May 2021 22:39:34 +0530 Subject: [PATCH 30/53] Incorporating review comments --- .../fileupload/ExtensionFileUpload.java | 29 ++++++------------- .../sasanlabs/fileupload/FileUploadUtils.java | 9 ++---- 2 files changed, 12 insertions(+), 26 deletions(-) diff --git a/src/main/java/org/sasanlabs/fileupload/ExtensionFileUpload.java b/src/main/java/org/sasanlabs/fileupload/ExtensionFileUpload.java index 2bf1b31..9cb8ca2 100644 --- a/src/main/java/org/sasanlabs/fileupload/ExtensionFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/ExtensionFileUpload.java @@ -13,42 +13,36 @@ */ package org.sasanlabs.fileupload; +import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.parosproxy.paros.extension.ExtensionAdaptor; import org.parosproxy.paros.extension.ExtensionHook; -import org.parosproxy.paros.extension.ViewDelegate; import org.sasanlabs.fileupload.configuration.FileUploadConfiguration; import org.sasanlabs.fileupload.i18n.FileUploadI18n; import org.sasanlabs.fileupload.ui.FileUploadOptionsPanel; /** * @author KSASAN preetkaran20@gmail.com - * @since TODO add version + * @since 1.0.0 */ -public class FileUploadExtension extends ExtensionAdaptor { +public class ExtensionFileUpload extends ExtensionAdaptor { - protected static final Logger LOGGER = Logger.getLogger(FileUploadExtension.class); + protected static final Logger LOGGER = LogManager.getLogger(ExtensionFileUpload.class); @Override public String getAuthor() { return "KSASAN preetkaran20@gmail.com"; } - - @Override - public void init() {} - - @Override - public void initView(ViewDelegate view) { - super.initView(view); - } - + @Override public void hook(ExtensionHook extensionHook) { FileUploadI18n.init(); super.hook(extensionHook); - extensionHook.getHookView().addOptionPanel(new FileUploadOptionsPanel()); - LOGGER.debug("FileUpload Extension loaded successfully"); + if(hasView()) { + extensionHook.getHookView().addOptionPanel(new FileUploadOptionsPanel()); + } extensionHook.addOptionsParamSet(FileUploadConfiguration.getInstance()); + LOGGER.debug("FileUpload Extension loaded successfully"); } @Override @@ -56,11 +50,6 @@ public void unload() { super.unload(); } - @Override - public boolean supportsDb(String type) { - return true; - } - @Override public boolean canUnload() { return true; diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java b/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java index 8450a49..e97beb4 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java @@ -38,15 +38,12 @@ public interface FileUploadUtils { * Appends the Period Character to the provided String. * * @param extension - * @return + * @return appends {@link #PERIOD} to the provided extension if not {@code null} or empty else returns same provided extension. */ static String appendPeriodCharacter(String extension) { - if (StringUtils.isBlank(extension)) { + if (StringUtils.isBlank(extension) || extension.startsWith(FileUploadUtils.PERIOD)) { return extension; } else { - if (extension.startsWith(FileUploadUtils.PERIOD)) { - return extension; - } return FileUploadUtils.PERIOD + extension; } } @@ -55,7 +52,7 @@ static String appendPeriodCharacter(String extension) { * returns the extension of the provided fileName. * * @param fileName - * @return extension of the provided fileName + * @return extension of the provided fileName if not null else throws {@code NullPointerException} * @throws Null Pointer Exception if fileName is null */ static String getExtension(String fileName) { From 03e2204b4d49674e0e7d5c3445a26515604caed3 Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Wed, 19 May 2021 22:40:05 +0530 Subject: [PATCH 31/53] Incorporating review comments --- .../java/org/sasanlabs/fileupload/ExtensionFileUpload.java | 6 +++--- src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/sasanlabs/fileupload/ExtensionFileUpload.java b/src/main/java/org/sasanlabs/fileupload/ExtensionFileUpload.java index 9cb8ca2..94a2d16 100644 --- a/src/main/java/org/sasanlabs/fileupload/ExtensionFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/ExtensionFileUpload.java @@ -33,13 +33,13 @@ public class ExtensionFileUpload extends ExtensionAdaptor { public String getAuthor() { return "KSASAN preetkaran20@gmail.com"; } - + @Override public void hook(ExtensionHook extensionHook) { FileUploadI18n.init(); super.hook(extensionHook); - if(hasView()) { - extensionHook.getHookView().addOptionPanel(new FileUploadOptionsPanel()); + if (hasView()) { + extensionHook.getHookView().addOptionPanel(new FileUploadOptionsPanel()); } extensionHook.addOptionsParamSet(FileUploadConfiguration.getInstance()); LOGGER.debug("FileUpload Extension loaded successfully"); diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java b/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java index e97beb4..bb7427e 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java @@ -38,7 +38,8 @@ public interface FileUploadUtils { * Appends the Period Character to the provided String. * * @param extension - * @return appends {@link #PERIOD} to the provided extension if not {@code null} or empty else returns same provided extension. + * @return appends {@link #PERIOD} to the provided extension if not {@code null} or empty else + * returns same provided extension. */ static String appendPeriodCharacter(String extension) { if (StringUtils.isBlank(extension) || extension.startsWith(FileUploadUtils.PERIOD)) { @@ -52,7 +53,8 @@ static String appendPeriodCharacter(String extension) { * returns the extension of the provided fileName. * * @param fileName - * @return extension of the provided fileName if not null else throws {@code NullPointerException} + * @return extension of the provided fileName if not null else throws {@code + * NullPointerException} * @throws Null Pointer Exception if fileName is null */ static String getExtension(String fileName) { From c01be93076ce03eb8e75260c1505715a464915ff Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Wed, 19 May 2021 23:30:37 +0530 Subject: [PATCH 32/53] Small Fix of not showing Preflight request for alert --- .../sasanlabs/fileupload/FileUploadScanRule.java | 3 ++- .../fileupload/attacks/AttackVector.java | 15 +++++++++++---- .../sasanlabs/fileupload/i18n/Messages.properties | 3 +++ 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java index 2c6c94d..5abff0b 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java @@ -16,6 +16,7 @@ import java.io.IOException; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; +import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.parosproxy.paros.core.scanner.Category; import org.parosproxy.paros.core.scanner.NameValuePair; @@ -41,7 +42,7 @@ public class FileUploadScanRule extends AbstractAppVariantPlugin { FileUploadI18n.getMessage("fileupload.scanrule.description"); private static final String SOLUTION = FileUploadI18n.getMessage("fileupload.scanrule.soln"); private static final String REFERENCE = FileUploadI18n.getMessage("fileupload.scanrule.refs"); - private static final Logger LOGGER = Logger.getLogger(FileUploadScanRule.class); + private static final Logger LOGGER = LogManager.getLogger(FileUploadScanRule.class); private AtomicInteger maxRequestCount; diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java index 8335280..34114ab 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java @@ -14,6 +14,7 @@ package org.sasanlabs.fileupload.attacks; import java.io.IOException; +import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -93,12 +94,18 @@ default void raiseAlert( Alert.CONFIDENCE_MEDIUM, FileUploadI18n.getMessage(vulnerabilityType.getMessageKey() + ".name"), FileUploadI18n.getMessage(vulnerabilityType.getMessageKey() + ".desc"), - newMsg.getRequestHeader().getURI().toString(), - newMsg.getRequestBody().toString(), - payload, + preflight.getRequestHeader().getURI().toString(), + newMsg.getRequestHeader().toString() + newMsg.getRequestBody().toString(), + MessageFormat.format( + FileUploadI18n.getMessage("fileupload.alert.attack"), + newMsg.getRequestHeader().toString() + newMsg.getRequestBody().toString(), + preflight.getRequestHeader().toString() + + preflight.getRequestBody().toString(), + preflight.getResponseHeader().toString() + + preflight.getResponseBody().toString()), FileUploadI18n.getMessage(vulnerabilityType.getMessageKey() + ".refs"), FileUploadI18n.getMessage(vulnerabilityType.getMessageKey() + ".soln"), - preflight); + newMsg); } /** diff --git a/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties b/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties index 7a22277..d4a2fde 100755 --- a/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties +++ b/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties @@ -13,6 +13,9 @@ fileupload.settings.urilocator.dynamiclocation.endidentifer=End Identifier fileupload.settings.alert.invalid.dynamicconfigutation=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. +# Alert details +fileupload.alert.attack=Retrieval Request: {1} \n Retrieval Response: {2} + # FileUpload Scan Rule fileupload.scanrule.name=File Upload fileupload.scanrule.description=File Upload scan rule is used to scan the vulnerabilities in the File Upload functionality of web applications. From 0a0f1b56a33f00bc97d43f0c6af5a3e4df88b05a Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Thu, 20 May 2021 08:50:18 +0530 Subject: [PATCH 33/53] Correcting Mesage format --- .../java/org/sasanlabs/fileupload/attacks/AttackVector.java | 1 - .../resources/org/sasanlabs/fileupload/i18n/Messages.properties | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java index 34114ab..c98cf28 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java @@ -98,7 +98,6 @@ default void raiseAlert( newMsg.getRequestHeader().toString() + newMsg.getRequestBody().toString(), MessageFormat.format( FileUploadI18n.getMessage("fileupload.alert.attack"), - newMsg.getRequestHeader().toString() + newMsg.getRequestBody().toString(), preflight.getRequestHeader().toString() + preflight.getRequestBody().toString(), preflight.getResponseHeader().toString() diff --git a/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties b/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties index d4a2fde..1b5adf9 100755 --- a/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties +++ b/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties @@ -14,7 +14,7 @@ fileupload.settings.alert.invalid.dynamicconfigutation=Both dynamic start and en fileupload.settings.alert.static.dynamicconfiguration.both.present=Only one of the static and dynamic configuration should be present. # Alert details -fileupload.alert.attack=Retrieval Request: {1} \n Retrieval Response: {2} +fileupload.alert.attack=Retrieval Request: {0} \n Retrieval Response: {1} # FileUpload Scan Rule fileupload.scanrule.name=File Upload From 2711a2ea9bce7a86d14bbd4a427d30d4a5b01c85 Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Sat, 17 Jul 2021 18:58:18 +0530 Subject: [PATCH 34/53] Small Fixes --- .../fileupload/AbstractAppVariantPlugin.java | 173 ------------------ .../fileupload/FileUploadScanRule.java | 37 ++-- .../fileupload/attacks/AttackVector.java | 50 ++--- .../attacks/FileUploadAttackExecutor.java | 4 +- .../attacks/beans/VulnerabilityType.java | 1 + .../ImageMagickRemoteCodeExecution.java | 28 --- 6 files changed, 39 insertions(+), 254 deletions(-) delete mode 100644 src/main/java/org/sasanlabs/fileupload/AbstractAppVariantPlugin.java delete mode 100644 src/main/java/org/sasanlabs/fileupload/attacks/rce/imagetragick/ImageMagickRemoteCodeExecution.java diff --git a/src/main/java/org/sasanlabs/fileupload/AbstractAppVariantPlugin.java b/src/main/java/org/sasanlabs/fileupload/AbstractAppVariantPlugin.java deleted file mode 100644 index c14512a..0000000 --- a/src/main/java/org/sasanlabs/fileupload/AbstractAppVariantPlugin.java +++ /dev/null @@ -1,173 +0,0 @@ -/** - * Copyright 2021 SasanLabs - * - *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of the License at - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sasanlabs.fileupload; - -import java.util.List; -import org.apache.log4j.Logger; -import org.parosproxy.paros.Constant; -import org.parosproxy.paros.core.scanner.AbstractAppPlugin; -import org.parosproxy.paros.core.scanner.NameValuePair; -import org.parosproxy.paros.core.scanner.Variant; -import org.parosproxy.paros.model.Model; -import org.parosproxy.paros.network.HttpMessage; -import org.zaproxy.zap.extension.ascan.VariantFactory; - -/** - * {@code AbstractAppVariantPlugin} is the abstract base class which is used to run per variant to - * modify multiple name value pairs of the {@code HttpMessage} per variant. - * - * @author KSASAN preetkaran20@gmail.com - */ -public abstract class AbstractAppVariantPlugin extends AbstractAppPlugin { - - private final Logger logger = Logger.getLogger(this.getClass()); - private Variant variant; - - @Override - public void scan() { - VariantFactory factory = Model.getSingleton().getVariantFactory(); - - List listVariant = - factory.createVariants(this.getParent().getScannerParam(), this.getBaseMsg()); - - if (listVariant.isEmpty()) { - getParent() - .pluginSkipped( - this, - Constant.messages.getString( - "ascan.progress.label.skipped.reason.noinputvectors")); - return; - } - - for (int i = 0; i < listVariant.size() && !isStop(); i++) { - - HttpMessage msg = getNewMsg(); - // ZAP: Removed unnecessary cast. - Variant variant = listVariant.get(i); - try { - variant.setMessage(msg); - scanVariant(variant); - - } catch (Exception e) { - logger.error( - "Error occurred while scanning with variant " - + variant.getClass().getCanonicalName(), - e); - } - - // ZAP: Implement pause and resume - while (getParent().isPaused() && !isStop()) { - try { - Thread.sleep(500); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - } - } - - /** Scan the current message using the current Variant */ - private void scanVariant(Variant variant) { - HttpMessage msg = getNewMsg(); - try { - this.variant = variant; - scan(msg, variant.getParamList()); - } catch (Exception e) { - logger.error("Error occurred while scanning a message:", e); - } - } - - /** - * Scan the current message using the provided Variant - * - * @param msg a copy of the HTTP message currently under scanning - * @param nameValuePairs ParamList of a Variant - */ - public abstract void scan(HttpMessage msg, List nameValuePairs); - - /** - * Sets the parameter into the given {@code message}. If both parameter name and value are - * {@code null}, the parameter will be removed. - * - * @param message the message that will be changed - * @param nameValuePair of the message - * @param param the name of the parameter - * @param value the value of the parameter - * @return the parameter set - * @see #setEscapedParameter(HttpMessage, NameValuePair, String, String) - */ - protected String setParameter( - HttpMessage message, NameValuePair nameValuePair, String param, String value) { - return variant.setParameter(message, nameValuePair, param, value); - } - - /** - * Sets the parameters into the given {@code message}. If both parameter name and value are - * {@code null}, the parameter will be removed. - * - *

The value is expected to be properly encoded/escaped. - * - * @param message the message that will be changed - * @param nameValuePairs of the message - * @param params list of name of the parameter - * @param values list of value of the parameter - * @return the parameter set - * @see #setParameters(HttpMessage, List, List, List) - */ - protected String setEscapedParameters( - HttpMessage message, - List nameValuePairs, - List params, - List values) { - return variant.setEscapedParameters(message, nameValuePairs, params, values); - } - - /** - * Sets the parameters into the given {@code message}. If both parameter name and value are - * {@code null}, the parameter will be removed. - * - * @param message the message that will be changed - * @param nameValuePairs of the message - * @param params list of name of the parameter - * @param values list of value of the parameter - * @return the parameter set - * @see #setEscapedParameters(HttpMessage, List, List, List) - */ - protected String setParameters( - HttpMessage message, - List nameValuePairs, - List params, - List values) { - return variant.setParameters(message, nameValuePairs, params, values); - } - - /** - * Sets the parameter into the given {@code message}. If both parameter name and value are - * {@code null}, the parameter will be removed. - * - *

The value is expected to be properly encoded/escaped. - * - * @param message the message that will be changed - * @param nameValuePair of the message - * @param param the name of the parameter - * @param value the value of the parameter - * @return the parameter set - * @see #setParameter(HttpMessage, NameValuePair, String, String) - */ - protected String setEscapedParameter( - HttpMessage message, NameValuePair nameValuePair, String param, String value) { - return variant.setEscapedParameter(message, nameValuePair, param, value); - } -} diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java index 5abff0b..4d66a0f 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java @@ -18,11 +18,14 @@ import java.util.concurrent.atomic.AtomicInteger; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; +import org.parosproxy.paros.core.scanner.AbstractAppParamPlugin; import org.parosproxy.paros.core.scanner.Category; import org.parosproxy.paros.core.scanner.NameValuePair; import org.parosproxy.paros.network.HttpMessage; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; import org.sasanlabs.fileupload.i18n.FileUploadI18n; +import org.zaproxy.zap.core.scanner.InputVector; +import org.zaproxy.zap.core.scanner.InputVectorBuilder; /** * {@code FileUploadScanRule} is used to find the vulnerabilities in File Upload functionality of @@ -34,7 +37,7 @@ * * @author KSASAN preetkaran20@gmail.com */ -public class FileUploadScanRule extends AbstractAppVariantPlugin { +public class FileUploadScanRule extends AbstractAppParamPlugin { private static final int PLUGIN_ID = 110009; private static final String NAME = FileUploadI18n.getMessage("fileupload.scanrule.name"); @@ -77,7 +80,7 @@ public void decreaseRequestCount() { } @Override - public void scan(HttpMessage msg, List nameValuePairs) { + protected void scan(HttpMessage msg, List nameValuePairs) { try { boolean isMultipart = false; if (nameValuePairs != null) { @@ -109,6 +112,16 @@ public void scan(HttpMessage msg, List nameValuePairs) { } } + @Override + public InputVectorBuilder getBuilder() { + return super.getBuilder(); + } + + @Override + public void setParameters(HttpMessage message, List inputVectors) { + super.setParameters(message, inputVectors); + } + public void raiseAlert( int risk, int confidence, @@ -135,7 +148,7 @@ public void raiseAlert( } public void sendAndRecieve(HttpMessage msg) throws IOException { - this.sendAndReceive(msg); + super.sendAndReceive(msg); } @Override @@ -167,22 +180,4 @@ public String getReference() { public int getCategory() { return Category.MISC; } - - /** - * Sets the parameters into the given {@code message}. If both parameter name and value are - * {@code null}, the parameter will be removed. - * - * @param message the message that will be changed - * @param nameValuePairs of the message - * @param params list of name of the parameter - * @param values list of value of the parameter - * @return the parameter set - */ - public String setParameters( - HttpMessage message, - List nameValuePairs, - List params, - List values) { - return super.setParameters(message, nameValuePairs, params, values); - } } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java index c98cf28..d0b765c 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java @@ -15,7 +15,6 @@ import java.io.IOException; import java.text.MessageFormat; -import java.util.ArrayList; import java.util.List; import java.util.Objects; import org.apache.commons.httpclient.URI; @@ -29,6 +28,8 @@ import org.sasanlabs.fileupload.i18n.FileUploadI18n; import org.sasanlabs.fileupload.locator.URILocatorImpl; import org.sasanlabs.fileupload.matcher.ContentMatcher; +import org.zaproxy.zap.core.scanner.InputVector.PayloadFormat; +import org.zaproxy.zap.core.scanner.InputVectorBuilder; /** * {@code AttackVector} is a common interface for file upload attacks which implements this @@ -133,51 +134,40 @@ default boolean genericAttackExecutor( List fileParameters, VulnerabilityType vulnerabilityType) throws IOException, FileUploadException { + List nameValuePairs = fileUploadAttackExecutor.getNameValuePairs(); HttpMessage originalMsg = fileUploadAttackExecutor.getOriginalHttpMessage(); FileUploadScanRule fileUploadScanRule = fileUploadAttackExecutor.getFileUploadScanRule(); - String originalFileName = null; - String originalContentType = null; - for (NameValuePair nameValuePair : nameValuePairs) { - if (nameValuePair.getType() == NameValuePair.TYPE_MULTIPART_DATA_FILE_NAME) { - originalFileName = nameValuePair.getValue(); - } else if (nameValuePair.getType() - == NameValuePair.TYPE_MULTIPART_DATA_FILE_CONTENTTYPE) { - originalContentType = nameValuePair.getValue(); - } - } for (FileParameter fileParameter : fileParameters) { if (fileUploadAttackExecutor.getFileUploadScanRule().isStop()) { return false; } fileUploadAttackExecutor.getFileUploadScanRule().decreaseRequestCount(); HttpMessage newMsg = originalMsg.cloneRequest(); - List newNameValuePairs = new ArrayList<>(); - List newParamNames = new ArrayList<>(); - List newParamValues = new ArrayList<>(); - for (int i = 0; i < nameValuePairs.size(); i++) { - NameValuePair nameValuePair = nameValuePairs.get(i); - if (nameValuePair.getType() == NameValuePair.TYPE_MULTIPART_DATA_FILE_NAME - || nameValuePair.getType() == NameValuePair.TYPE_MULTIPART_DATA_FILE_PARAM - || nameValuePair.getType() - == NameValuePair.TYPE_MULTIPART_DATA_FILE_CONTENTTYPE) { - newNameValuePairs.add(nameValuePair); - newParamNames.add(nameValuePair.getName()); - } else { - continue; - } + InputVectorBuilder inputVectorBuilder = + fileUploadAttackExecutor.getFileUploadScanRule().getBuilder(); + String originalFileName = null; + for (NameValuePair nameValuePair : nameValuePairs) { if (nameValuePair.getType() == NameValuePair.TYPE_MULTIPART_DATA_FILE_NAME) { - newParamValues.add(fileParameter.getFileName(originalFileName)); + originalFileName = nameValuePair.getValue(); + inputVectorBuilder.setValue( + nameValuePair, + fileParameter.getFileName(originalFileName), + PayloadFormat.ALREADY_ESCAPED); } else if (nameValuePair.getType() == NameValuePair.TYPE_MULTIPART_DATA_FILE_PARAM) { - newParamValues.add(payload); + inputVectorBuilder.setValue( + nameValuePair, payload, PayloadFormat.ALREADY_ESCAPED); } else if (nameValuePair.getType() == NameValuePair.TYPE_MULTIPART_DATA_FILE_CONTENTTYPE) { - newParamValues.add(fileParameter.getContentType(originalContentType)); + String originalContentType = nameValuePair.getValue(); + inputVectorBuilder.setValue( + nameValuePair, + fileParameter.getContentType(originalContentType), + PayloadFormat.ALREADY_ESCAPED); } } - fileUploadScanRule.setParameters( - newMsg, newNameValuePairs, newParamNames, newParamValues); + fileUploadScanRule.setParameters(newMsg, inputVectorBuilder.build()); fileUploadScanRule.sendAndRecieve(newMsg); HttpMessage preflightMsg = this.executePreflightRequest( diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java b/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java index 85ac496..2259340 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java @@ -48,11 +48,11 @@ public class FileUploadAttackExecutor { public FileUploadAttackExecutor( HttpMessage originalHttpMessage, FileUploadScanRule fileUploadScanRule, - List variant) { + List nameValuePairs) { super(); this.originalHttpMessage = originalHttpMessage; this.fileUploadScanRule = fileUploadScanRule; - this.nameValuePairs = variant; + this.nameValuePairs = nameValuePairs; } public boolean executeAttack() throws FileUploadException { diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/beans/VulnerabilityType.java b/src/main/java/org/sasanlabs/fileupload/attacks/beans/VulnerabilityType.java index 690e310..6e6181c 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/beans/VulnerabilityType.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/beans/VulnerabilityType.java @@ -33,6 +33,7 @@ public enum VulnerabilityType { private String messageKey; private int alertLevel; + private static final String PREFIX = "fileupload.scanner.vulnerability."; private VulnerabilityType(String message, int alertLevel) { diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/imagetragick/ImageMagickRemoteCodeExecution.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/imagetragick/ImageMagickRemoteCodeExecution.java deleted file mode 100644 index 4a89577..0000000 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/imagetragick/ImageMagickRemoteCodeExecution.java +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Copyright 2021 SasanLabs - * - *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of the License at - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sasanlabs.fileupload.attacks.rce.imagetragick; - -import org.sasanlabs.fileupload.attacks.AttackVector; -import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; -import org.sasanlabs.fileupload.exception.FileUploadException; - -public class ImageMagickRemoteCodeExecution implements AttackVector { - - @Override - public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) - throws FileUploadException { - // TODO Auto-generated method stub - return false; - } -} From d2b4293b27b597554b1c5b9b665812da4ecc703b Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Sat, 17 Jul 2021 19:22:07 +0530 Subject: [PATCH 35/53] Removing logger --- .../java/org/sasanlabs/fileupload/FileUploadScanRule.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java index 4d66a0f..65a378c 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java @@ -99,10 +99,6 @@ protected void scan(HttpMessage msg, List nameValuePairs) { .TYPE_MULTIPART_DATA_FILE_CONTENTTYPE); } if (isMultipart) { - nameValuePairs.forEach( - (nameValuePair) -> - LOGGER.error( - nameValuePair.getName() + " " + nameValuePair.getValue())); FileUploadAttackExecutor fileUploadAttackExecutor = new FileUploadAttackExecutor(msg, this, nameValuePairs); fileUploadAttackExecutor.executeAttack(); From 5fbf9cbc059d995bed0d9af8f81ff0c43126eb35 Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Sat, 17 Jul 2021 23:36:55 +0530 Subject: [PATCH 36/53] Small modifications --- .../sasanlabs/fileupload/FileUploadUtils.java | 2 +- .../EicarAntivirusTestFileUpload.java | 36 +-- .../attacks/beans/FileExtensionOperation.java | 25 +- .../attacks/beans/FileParameter.java | 5 +- .../attacks/beans/FileParameterBuilder.java | 21 +- .../attacks/beans/FileParameterImpl.java | 30 +- .../jsp/ImageWithJSPSnippetFileUpload.java | 48 +-- .../attacks/rce/jsp/SimpleJSPFileUpload.java | 48 +-- .../attacks/rce/jsp/SimpleJSPXFileUpload.java | 48 +-- .../attacks/xss/HtmlFileUpload.java | 283 ++++++------------ .../fileupload/attacks/xss/SVGFileUpload.java | 129 +++----- 11 files changed, 226 insertions(+), 449 deletions(-) diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java b/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java index bb7427e..e1b602f 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java @@ -41,7 +41,7 @@ public interface FileUploadUtils { * @return appends {@link #PERIOD} to the provided extension if not {@code null} or empty else * returns same provided extension. */ - static String appendPeriodCharacter(String extension) { + static String prefixExtensionWithPeriodCharacter(String extension) { if (StringUtils.isBlank(extension) || extension.startsWith(FileUploadUtils.PERIOD)) { return extension; } else { diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java index cb3b4c0..e1bcd6f 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java @@ -68,75 +68,61 @@ public class EicarAntivirusTestFileUpload implements AttackVector { * on {@link https://www.virustotal.com/} Out of 67 antivirus softwares 63 * detect the Eicar file as virus file. */ - new FileParameterBuilder() - .withFileExtensionOperation( - FileExtensionOperation.ONLY_ORIGINAL_EXTENSION) - .build(), + originalFileName -> originalFileName, - // new FileParameter(FileExtensionOperation.ONLY_ORIGINAL_EXTENSION), // Below file parameters might not be needed but just for a safe side added // those. - new FileParameterBuilder() - .withBaseFileName(UPLOADED_BASE_FILE_NAME) + new FileParameterBuilder(UPLOADED_BASE_FILE_NAME) .withExtension("com") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(UPLOADED_BASE_FILE_NAME) + new FileParameterBuilder(UPLOADED_BASE_FILE_NAME) .withExtension("exe") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(UPLOADED_BASE_FILE_NAME) + new FileParameterBuilder(UPLOADED_BASE_FILE_NAME) .withExtension("com") .withContentType("application/octet-stream") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(UPLOADED_BASE_FILE_NAME) + new FileParameterBuilder(UPLOADED_BASE_FILE_NAME) .withExtension("exe") .withContentType("vnd.microsoft.portable-executable") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(UPLOADED_BASE_FILE_NAME) + new FileParameterBuilder(UPLOADED_BASE_FILE_NAME) .withExtension("com") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(UPLOADED_BASE_FILE_NAME) + new FileParameterBuilder(UPLOADED_BASE_FILE_NAME) .withExtension("exe") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(UPLOADED_BASE_FILE_NAME) + new FileParameterBuilder(UPLOADED_BASE_FILE_NAME) .withExtension("com") .withContentType("application/octet-stream") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(UPLOADED_BASE_FILE_NAME) + new FileParameterBuilder(UPLOADED_BASE_FILE_NAME) .withExtension("exe") .withContentType("vnd.microsoft.portable-executable") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(UPLOADED_BASE_FILE_NAME) + new FileParameterBuilder(UPLOADED_BASE_FILE_NAME) .withExtension("com" + NULL_BYTE_CHARACTER) .withContentType("application/octet-stream") .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(UPLOADED_BASE_FILE_NAME) + new FileParameterBuilder(UPLOADED_BASE_FILE_NAME) .withExtension("exe" + NULL_BYTE_CHARACTER) .withContentType("vnd.microsoft.portable-executable") .withFileExtensionOperation( diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileExtensionOperation.java b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileExtensionOperation.java index 0251780..734c466 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileExtensionOperation.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileExtensionOperation.java @@ -24,12 +24,13 @@ */ public enum FileExtensionOperation { - /** doesn't append any extension to the filename. */ + /** don't append any extension to the filename. */ NO_EXTENSION, + /** - * appends the Original File Extension before the provided extension. e.g. if provided extension - * is {@code html} and original file extension is {@code pdf} then the final extension will be - * {@code pdf.html} + * prefixes the Original File Extension before the provided extension. e.g. if provided + * extension is {@code html} and original file extension is {@code pdf} then the final extension + * will be {@code pdf.html} */ PREFIX_ORIGINAL_EXTENSION, @@ -68,25 +69,27 @@ public String operate(String providedExtension, String originalFileName) switch (this) { case PREFIX_ORIGINAL_EXTENSION: extension = - FileUploadUtils.appendPeriodCharacter( + FileUploadUtils.prefixExtensionWithPeriodCharacter( originalExtension - + FileUploadUtils.appendPeriodCharacter(providedExtension)); + + FileUploadUtils.prefixExtensionWithPeriodCharacter( + providedExtension)); break; case SUFFIX_ORIGINAL_EXTENSION: extension = - FileUploadUtils.appendPeriodCharacter( + FileUploadUtils.prefixExtensionWithPeriodCharacter( providedExtension - + FileUploadUtils.appendPeriodCharacter(originalExtension)); + + FileUploadUtils.prefixExtensionWithPeriodCharacter( + originalExtension)); break; case ONLY_PROVIDED_EXTENSION: - extension = FileUploadUtils.appendPeriodCharacter(providedExtension); + extension = FileUploadUtils.prefixExtensionWithPeriodCharacter(providedExtension); break; case ONLY_ORIGINAL_EXTENSION: - extension = FileUploadUtils.appendPeriodCharacter(originalExtension); + extension = FileUploadUtils.prefixExtensionWithPeriodCharacter(originalExtension); case NO_EXTENSION: extension = ""; default: - extension = FileUploadUtils.appendPeriodCharacter(providedExtension); + extension = FileUploadUtils.prefixExtensionWithPeriodCharacter(providedExtension); } return extension; } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java index d0fe304..da6f870 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java @@ -20,6 +20,7 @@ * * @author KSASAN preetkaran20@gmail.com */ +@FunctionalInterface public interface FileParameter { /** @@ -28,7 +29,9 @@ public interface FileParameter { * @param originalContentType * @return content type */ - String getContentType(String originalContentType); + default String getContentType(String originalContentType) { + return originalContentType; + }; /** * Represents the file name parameter. diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameterBuilder.java b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameterBuilder.java index 03d49b3..57db7f7 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameterBuilder.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameterBuilder.java @@ -23,23 +23,9 @@ public class FileParameterBuilder { private FileParameterImpl fileParameterImpl; - public FileParameterBuilder() {} - - public FileParameterBuilder withFileNameAsOriginalExtension() { - fileParameterImpl = new FileParameterImpl(); - return this; - } - - public FileParameterBuilder withFileName(String fileName) { - Objects.requireNonNull(fileName, "BaseFileName cannot be null"); - fileParameterImpl = new FileParameterImpl(fileName, false); - return this; - } - - public FileParameterBuilder withBaseFileName(String baseFileName) { - Objects.requireNonNull(baseFileName, "BaseFileName cannot be null"); + public FileParameterBuilder(String baseFileName) { + Objects.requireNonNull(baseFileName, "FileName cannot be null"); fileParameterImpl = new FileParameterImpl(baseFileName); - return this; } public FileParameterBuilder withFileExtensionOperation( @@ -69,8 +55,9 @@ public FileParameter build() { throw new RuntimeException( "Invalid combination, For FileExtensionOperation: " + this.fileParameterImpl.getFileExtensionOperation() - + " and ProvidedExtension should be null"); + + ", ProvidedExtension should be null"); } + return fileParameterImpl; } } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameterImpl.java b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameterImpl.java index 414966e..1fa8915 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameterImpl.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameterImpl.java @@ -15,30 +15,18 @@ import java.util.Date; import java.util.Random; -import org.sasanlabs.fileupload.FileUploadUtils; import org.sasanlabs.fileupload.exception.FileUploadException; /** @author KSASAN preetkaran20@gmail.com */ class FileParameterImpl implements FileParameter { - private String fileName; + + private String baseFileName; private String extension; private String contentType; - private boolean originalExtensionAsFileName = false; private FileExtensionOperation fileExtensionOperation = FileExtensionOperation.NO_EXTENSION; - FileParameterImpl() { - originalExtensionAsFileName = true; - } - - FileParameterImpl(String fileName) { - this.fileName = fileName; - } - - FileParameterImpl(String baseFileName, boolean appendRandomCharacters) { - this.fileName = baseFileName; - if (appendRandomCharacters) { - this.fileName = this.fileName + new Random(new Date().getTime()).nextLong(); - } + FileParameterImpl(String baseFileName) { + this.baseFileName = baseFileName + new Random(new Date().getTime()).nextLong(); } void setExtension(String extension) { @@ -57,10 +45,6 @@ String getExtension() { return extension; } - public boolean isOriginalExtensionAsFileName() { - return originalExtensionAsFileName; - } - FileExtensionOperation getFileExtensionOperation() { return fileExtensionOperation; } @@ -75,9 +59,7 @@ public String getFileName(String originalFileName) throws FileUploadException { if (originalFileName == null) { throw new FileUploadException("Provided original File Name is null"); } - if (originalExtensionAsFileName) { - return FileUploadUtils.getExtension(originalFileName); - } - return this.fileName + fileExtensionOperation.operate(this.extension, originalFileName); + + return this.baseFileName + fileExtensionOperation.operate(this.extension, originalFileName); } } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageWithJSPSnippetFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageWithJSPSnippetFileUpload.java index c1d48be..2916774 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageWithJSPSnippetFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageWithJSPSnippetFileUpload.java @@ -72,53 +72,45 @@ public class ImageWithJSPSnippetFileUpload implements AttackVector { private static final List FILE_PARAMETERS_EXTENDED = Arrays.asList( - new FileParameterBuilder() - .withBaseFileName(BASE_FILE_NAME) + new FileParameterBuilder(BASE_FILE_NAME) .withExtension("Jsp") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(BASE_FILE_NAME) + new FileParameterBuilder(BASE_FILE_NAME) .withExtension("JSP") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(BASE_FILE_NAME) + new FileParameterBuilder(BASE_FILE_NAME) .withExtension("Jsp") .withContentType("application/x-jsp") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(BASE_FILE_NAME) + new FileParameterBuilder(BASE_FILE_NAME) .withExtension("JSP") .withContentType("application/x-jsp") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(BASE_FILE_NAME) + new FileParameterBuilder(BASE_FILE_NAME) .withExtension("Jsp") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(BASE_FILE_NAME) + new FileParameterBuilder(BASE_FILE_NAME) .withExtension("JSP") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(BASE_FILE_NAME) + new FileParameterBuilder(BASE_FILE_NAME) .withExtension("Jsp") .withContentType("application/x-jsp") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(BASE_FILE_NAME) + new FileParameterBuilder(BASE_FILE_NAME) .withExtension("JSP") .withContentType("application/x-jsp") .withFileExtensionOperation( @@ -127,53 +119,45 @@ public class ImageWithJSPSnippetFileUpload implements AttackVector { private static final List FILE_PARAMETERS_DEFAULT = Arrays.asList( - new FileParameterBuilder() - .withBaseFileName(BASE_FILE_NAME) + new FileParameterBuilder(BASE_FILE_NAME) .withExtension("jsp") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(BASE_FILE_NAME) + new FileParameterBuilder(BASE_FILE_NAME) .withExtension("jsp") .withContentType("application/x-jsp") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(BASE_FILE_NAME) + new FileParameterBuilder(BASE_FILE_NAME) .withExtension("jsp") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(BASE_FILE_NAME) + new FileParameterBuilder(BASE_FILE_NAME) .withExtension("jsp") .withContentType("application/x-jsp") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(BASE_FILE_NAME) + new FileParameterBuilder(BASE_FILE_NAME) .withExtension("jsp" + NULL_BYTE_CHARACTER) .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(BASE_FILE_NAME) + new FileParameterBuilder(BASE_FILE_NAME) .withExtension("jsp" + NULL_BYTE_CHARACTER) .withContentType("application/x-jsp") .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(BASE_FILE_NAME) + new FileParameterBuilder(BASE_FILE_NAME) .withExtension("jsp%00") .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(BASE_FILE_NAME) + new FileParameterBuilder(BASE_FILE_NAME) .withExtension("jsp%00") .withContentType("application/x-jsp") .withFileExtensionOperation( diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPFileUpload.java index a4ccc47..592d9d5 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPFileUpload.java @@ -45,53 +45,45 @@ public class SimpleJSPFileUpload implements AttackVector { private static final List FILE_PARAMETERS_EXTENDED = Arrays.asList( - new FileParameterBuilder() - .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) .withExtension("Jsp") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) .withExtension("JSP") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) .withExtension("Jsp") .withContentType("application/x-jsp") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) .withExtension("JSP") .withContentType("application/x-jsp") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) .withExtension("Jsp") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) .withExtension("JSP") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) .withExtension("Jsp") .withContentType("application/x-jsp") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) .withExtension("JSP") .withContentType("application/x-jsp") .withFileExtensionOperation( @@ -100,53 +92,45 @@ public class SimpleJSPFileUpload implements AttackVector { private static final List FILE_PARAMETERS_DEFAULT = Arrays.asList( - new FileParameterBuilder() - .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) .withExtension("jsp") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) .withExtension("jsp") .withContentType("application/x-jsp") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) .withExtension("jsp") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) .withExtension("jsp") .withContentType("application/x-jsp") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) .withExtension("jsp" + NULL_BYTE_CHARACTER) .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) .withExtension("jsp" + NULL_BYTE_CHARACTER) .withContentType("application/x-jsp") .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) .withExtension("jsp%00") .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(JSP_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) .withExtension("jsp%00") .withContentType("application/x-jsp") .withFileExtensionOperation( diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPXFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPXFileUpload.java index e5d54aa..b250b5f 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPXFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPXFileUpload.java @@ -48,53 +48,45 @@ public class SimpleJSPXFileUpload implements AttackVector { private static final List FILE_PARAMETERS_EXTENDED = Arrays.asList( - new FileParameterBuilder() - .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) .withExtension("JspX") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) .withExtension("JSPX") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) .withExtension("JspX") .withContentType("application/x-jsp") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) .withExtension("JSPX") .withContentType("application/x-jsp") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) .withExtension("JspX") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) .withExtension("JSPX") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) .withExtension("JspX") .withContentType("application/x-jsp") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) .withExtension("JSPX") .withContentType("application/x-jsp") .withFileExtensionOperation( @@ -106,53 +98,45 @@ public class SimpleJSPXFileUpload implements AttackVector { // text/x-jsp private static final List FILE_PARAMETERS = Arrays.asList( - new FileParameterBuilder() - .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) .withExtension("jspx") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) .withExtension("jspx") .withContentType("application/x-jsp") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) .withExtension("jspx") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) .withExtension("jspx") .withContentType("application/x-jsp") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) .withExtension("jspx" + NULL_BYTE_CHARACTER) .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) .withExtension("jspx" + NULL_BYTE_CHARACTER) .withContentType("application/x-jsp") .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) .withExtension("jspx%00") .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(JSPX_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) .withExtension("jspx%00") .withContentType("application/x-jsp") .withFileExtensionOperation( diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java index deb5c91..2434494 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java @@ -67,426 +67,362 @@ public class HtmlFileUpload implements AttackVector { // Extended list for breaking black-listing strategy. private static final List FILE_PARAMETERS_EXTENDED = Arrays.asList( - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Htm") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("hTM") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("HTM") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("HtML") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("HTMl") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("HTML") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Xhtml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xHTml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xhTML") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xHTML") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("XHTML") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("dHtml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("sHtml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("dHTml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("sHTml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("dHTML") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("sHTML") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Htm") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("hTM") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("HTM") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Html") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("HtML") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("HTMl") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("HTML") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Xhtml") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xHTml") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xhTML") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xHTML") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("XHTML") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("dHtml") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("sHtml") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("dHTml") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("sHTml") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("dHTML") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("sHTML") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Htm") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("hTM") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("HTM") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Html") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("HtML") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("HTMl") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("HTML") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Xhtml") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xHTml") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xhTML") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xHTML") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("XHTML") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("dHtml") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("sHtml") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("dHTml") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("sHTml") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("dHTML") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("sHTML") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Htm") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("HTML") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Xhtml") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("XHTML") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Htm") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Htm") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("HTML") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Xhtml") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("XHTML") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Htm") .withContentType("text/html") .withFileExtensionOperation( @@ -496,7 +432,7 @@ public class HtmlFileUpload implements AttackVector { private static final List FILE_PARAMETERS_DEFAULT = Arrays.asList( /** - * No extension is required actually browser reads the content-type header of + * No extension is required, actually browser reads the content-type header of * response from server and if that is not present then it tried to guess the * file type based on the extension and in case content type and extensions are * missing then browser finds it by reading the response called content @@ -513,25 +449,21 @@ public class HtmlFileUpload implements AttackVector { *

e.g. php code {@code * strtolower(end(explode('.',$_FILES['image']['name'])));} */ - new FileParameterBuilder().withFileNameAsOriginalExtension().build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + originalFileName -> FileUploadUtils.getExtension(originalFileName), + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withFileExtensionOperation(FileExtensionOperation.NO_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("htm") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xhtml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) @@ -540,14 +472,12 @@ public class HtmlFileUpload implements AttackVector { * Server Parsed Html for server side includes * https://stackoverflow.com/questions/519619/what-is-the-purpose-and-uniqueness-shtml */ - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("dhtml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("shtml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) @@ -558,77 +488,66 @@ public class HtmlFileUpload implements AttackVector { * blacklist validation of extensions. For more information {@link * https://www.acunetix.com/websitesecurity/upload-forms-threat/#:~:text=Double%20Extensions} */ - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("html.123") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("htm") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("html") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xhtml") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("shtml") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("dhtml") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("htm") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("html") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xhtml") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("shtml") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("dhtml") .withContentType("text/plain") .withFileExtensionOperation( @@ -639,80 +558,68 @@ public class HtmlFileUpload implements AttackVector { * .gif.html} If validator only validates contains {@code .gif} extension then * validator will be bypassed. */ - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("htm") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("html") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xhtml") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("htm") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("html") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xhtml") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("htm" + NULL_BYTE_CHARACTER) .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("htm" + NULL_BYTE_CHARACTER) .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("htm" + NULL_BYTE_CHARACTER) .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("htm%00") .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("htm%00") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("htm%00") .withContentType("text/plain") .withFileExtensionOperation( diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/xss/SVGFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/xss/SVGFileUpload.java index 772c062..dfcf4b1 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/xss/SVGFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/xss/SVGFileUpload.java @@ -50,202 +50,172 @@ public class SVGFileUpload implements AttackVector { // Extended list for breaking black-listing strategy. private static final List FILE_PARAMETERS_EXTENDED = Arrays.asList( - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Svg") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("SvG") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("SVG") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Svgz") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("SvGz") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("SVGZ") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xML") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("XML") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Svg") .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("SvG") .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("SVG") .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Svgz") .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("SvGz") .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("SVGZ") .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xML") .withContentType("text/xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Xml") .withContentType("text/xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("XML") .withContentType("text/xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Svg") .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("SVG") .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Svgz") .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("SVGZ") .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xML") .withContentType("text/xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("XML") .withContentType("text/xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Svg") .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("SVG") .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Svgz") .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("SVGZ") .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xML") .withContentType("text/xml") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("XML") .withContentType("text/xml") .withFileExtensionOperation( @@ -262,84 +232,71 @@ public class SVGFileUpload implements AttackVector { private static final List FILE_PARAMETERS_DEFAULT = Arrays.asList( // Not adding empty extension for svg because it is not working in browsers - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("svg") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("svgz") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("svg") .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xml") .withContentType("text/xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("svgz") .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("svg") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xml") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("svgz") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("svg" + NULL_BYTE_CHARACTER) .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("svg" + NULL_BYTE_CHARACTER) .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("svg%00") .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder() - .withBaseFileName(XSS_UPLOADED_FILE_BASE_NAME) + new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("svg%00") .withContentType("image/svg+xml") .withFileExtensionOperation( From 447b2b3fc07eefa0f4d02bb82837944d1340b24c Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Sun, 18 Jul 2021 19:15:42 +0530 Subject: [PATCH 37/53] Adding EICAR --- .../attacks/FileUploadAttackExecutor.java | 4 ++- .../attacks/beans/FileParameterImpl.java | 2 +- .../attacks/rce/jsp/SimpleJSPFileUpload.java | 33 ++++++++++++++----- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java b/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java index 2259340..f9a9fd1 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java @@ -19,6 +19,7 @@ import org.parosproxy.paros.core.scanner.NameValuePair; import org.parosproxy.paros.network.HttpMessage; import org.sasanlabs.fileupload.FileUploadScanRule; +import org.sasanlabs.fileupload.attacks.antivirus.EicarAntivirusTestFileUpload; import org.sasanlabs.fileupload.attacks.rce.jsp.ImageWithJSPSnippetFileUpload; import org.sasanlabs.fileupload.attacks.rce.jsp.SimpleJSPFileUpload; import org.sasanlabs.fileupload.attacks.rce.jsp.SimpleJSPXFileUpload; @@ -43,7 +44,8 @@ public class FileUploadAttackExecutor { new SVGFileUpload(), new SimpleJSPFileUpload(), new SimpleJSPXFileUpload(), - new ImageWithJSPSnippetFileUpload()); + new ImageWithJSPSnippetFileUpload(), + new EicarAntivirusTestFileUpload()); public FileUploadAttackExecutor( HttpMessage originalHttpMessage, diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameterImpl.java b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameterImpl.java index 1fa8915..15981c8 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameterImpl.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameterImpl.java @@ -26,7 +26,7 @@ class FileParameterImpl implements FileParameter { private FileExtensionOperation fileExtensionOperation = FileExtensionOperation.NO_EXTENSION; FileParameterImpl(String baseFileName) { - this.baseFileName = baseFileName + new Random(new Date().getTime()).nextLong(); + this.baseFileName = baseFileName + (new Random(new Date().getTime()).nextLong()); } void setExtension(String extension) { diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPFileUpload.java index 592d9d5..55293e0 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPFileUpload.java @@ -33,11 +33,11 @@ public class SimpleJSPFileUpload implements AttackVector { private static final String JSP_UPLOADED_FILE_BASE_NAME = "SimpleJSPFileUpload_"; - /** - * using tag based attack too here. e.g. "${'InJeCtTe'}" _jsp_gen_payload_expression_lang in - * burp extension - */ - private static final String JSP_PAYLOAD = + + private static final String JSP_EL_PAYLOAD = + "${\"SimpleJSPFileUpload\"}${\"_SasanLabs_ZAP_Identifier\"}"; + + private static final String JSP_SCRIPTLET_PAYLOAD = "<% out.print(\"SimpleJSPFileUpload\"); out.print(\"_SasanLabs_ZAP_Identifier\"); %>"; private static final ContentMatcher CONTENT_MATCHER = @@ -146,10 +146,18 @@ public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) this.genericAttackExecutor( fileUploadAttackExecutor, CONTENT_MATCHER, - JSP_PAYLOAD, + JSP_SCRIPTLET_PAYLOAD, FILE_PARAMETERS_DEFAULT, VulnerabilityType.RCE_JSP_FILE); - + if (!result) { + result = + this.genericAttackExecutor( + fileUploadAttackExecutor, + CONTENT_MATCHER, + JSP_EL_PAYLOAD, + FILE_PARAMETERS_DEFAULT, + VulnerabilityType.RCE_JSP_FILE); + } if (!result && fileUploadAttackExecutor .getFileUploadScanRule() @@ -159,9 +167,18 @@ public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) this.genericAttackExecutor( fileUploadAttackExecutor, CONTENT_MATCHER, - JSP_PAYLOAD, + JSP_SCRIPTLET_PAYLOAD, FILE_PARAMETERS_EXTENDED, VulnerabilityType.RCE_JSP_FILE); + if (!result) { + result = + this.genericAttackExecutor( + fileUploadAttackExecutor, + CONTENT_MATCHER, + JSP_EL_PAYLOAD, + FILE_PARAMETERS_EXTENDED, + VulnerabilityType.RCE_JSP_FILE); + } } } catch (IOException e) { throw new FileUploadException(e); From ae0a686c1a54b8ed1232e4667b48e610fd69d556 Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Sun, 18 Jul 2021 19:21:56 +0530 Subject: [PATCH 38/53] changing bean to model --- .../org/sasanlabs/fileupload/attacks/AttackVector.java | 4 ++-- .../attacks/antivirus/EicarAntivirusTestFileUpload.java | 8 ++++---- .../attacks/{beans => model}/FileExtensionOperation.java | 2 +- .../attacks/{beans => model}/FileParameter.java | 2 +- .../attacks/{beans => model}/FileParameterBuilder.java | 2 +- .../attacks/{beans => model}/FileParameterImpl.java | 2 +- .../attacks/{beans => model}/VulnerabilityType.java | 2 +- .../attacks/rce/jsp/ImageWithJSPSnippetFileUpload.java | 8 ++++---- .../fileupload/attacks/rce/jsp/SimpleJSPFileUpload.java | 8 ++++---- .../fileupload/attacks/rce/jsp/SimpleJSPXFileUpload.java | 8 ++++---- .../sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java | 8 ++++---- .../sasanlabs/fileupload/attacks/xss/SVGFileUpload.java | 8 ++++---- 12 files changed, 31 insertions(+), 31 deletions(-) rename src/main/java/org/sasanlabs/fileupload/attacks/{beans => model}/FileExtensionOperation.java (98%) rename src/main/java/org/sasanlabs/fileupload/attacks/{beans => model}/FileParameter.java (96%) rename src/main/java/org/sasanlabs/fileupload/attacks/{beans => model}/FileParameterBuilder.java (98%) rename src/main/java/org/sasanlabs/fileupload/attacks/{beans => model}/FileParameterImpl.java (97%) rename src/main/java/org/sasanlabs/fileupload/attacks/{beans => model}/VulnerabilityType.java (97%) diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java index d0b765c..3be1871 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java @@ -22,8 +22,8 @@ import org.parosproxy.paros.core.scanner.NameValuePair; import org.parosproxy.paros.network.HttpMessage; import org.sasanlabs.fileupload.FileUploadScanRule; -import org.sasanlabs.fileupload.attacks.beans.FileParameter; -import org.sasanlabs.fileupload.attacks.beans.VulnerabilityType; +import org.sasanlabs.fileupload.attacks.model.FileParameter; +import org.sasanlabs.fileupload.attacks.model.VulnerabilityType; import org.sasanlabs.fileupload.exception.FileUploadException; import org.sasanlabs.fileupload.i18n.FileUploadI18n; import org.sasanlabs.fileupload.locator.URILocatorImpl; diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java index e1bcd6f..4b315dc 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java @@ -22,10 +22,10 @@ import java.util.List; import org.sasanlabs.fileupload.attacks.AttackVector; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; -import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; -import org.sasanlabs.fileupload.attacks.beans.FileParameter; -import org.sasanlabs.fileupload.attacks.beans.FileParameterBuilder; -import org.sasanlabs.fileupload.attacks.beans.VulnerabilityType; +import org.sasanlabs.fileupload.attacks.model.FileExtensionOperation; +import org.sasanlabs.fileupload.attacks.model.FileParameter; +import org.sasanlabs.fileupload.attacks.model.FileParameterBuilder; +import org.sasanlabs.fileupload.attacks.model.VulnerabilityType; import org.sasanlabs.fileupload.exception.FileUploadException; import org.sasanlabs.fileupload.matcher.ContentMatcher; import org.sasanlabs.fileupload.matcher.impl.MD5HashResponseMatcher; diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileExtensionOperation.java b/src/main/java/org/sasanlabs/fileupload/attacks/model/FileExtensionOperation.java similarity index 98% rename from src/main/java/org/sasanlabs/fileupload/attacks/beans/FileExtensionOperation.java rename to src/main/java/org/sasanlabs/fileupload/attacks/model/FileExtensionOperation.java index 734c466..c2b857b 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileExtensionOperation.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/model/FileExtensionOperation.java @@ -11,7 +11,7 @@ * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ -package org.sasanlabs.fileupload.attacks.beans; +package org.sasanlabs.fileupload.attacks.model; import org.apache.commons.lang3.StringUtils; import org.sasanlabs.fileupload.FileUploadUtils; diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java b/src/main/java/org/sasanlabs/fileupload/attacks/model/FileParameter.java similarity index 96% rename from src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java rename to src/main/java/org/sasanlabs/fileupload/attacks/model/FileParameter.java index da6f870..2c874b0 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameter.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/model/FileParameter.java @@ -11,7 +11,7 @@ * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ -package org.sasanlabs.fileupload.attacks.beans; +package org.sasanlabs.fileupload.attacks.model; import org.sasanlabs.fileupload.exception.FileUploadException; diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameterBuilder.java b/src/main/java/org/sasanlabs/fileupload/attacks/model/FileParameterBuilder.java similarity index 98% rename from src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameterBuilder.java rename to src/main/java/org/sasanlabs/fileupload/attacks/model/FileParameterBuilder.java index 57db7f7..b8bdc14 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameterBuilder.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/model/FileParameterBuilder.java @@ -11,7 +11,7 @@ * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ -package org.sasanlabs.fileupload.attacks.beans; +package org.sasanlabs.fileupload.attacks.model; import java.util.Objects; diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameterImpl.java b/src/main/java/org/sasanlabs/fileupload/attacks/model/FileParameterImpl.java similarity index 97% rename from src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameterImpl.java rename to src/main/java/org/sasanlabs/fileupload/attacks/model/FileParameterImpl.java index 15981c8..1d98a16 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/beans/FileParameterImpl.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/model/FileParameterImpl.java @@ -11,7 +11,7 @@ * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ -package org.sasanlabs.fileupload.attacks.beans; +package org.sasanlabs.fileupload.attacks.model; import java.util.Date; import java.util.Random; diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/beans/VulnerabilityType.java b/src/main/java/org/sasanlabs/fileupload/attacks/model/VulnerabilityType.java similarity index 97% rename from src/main/java/org/sasanlabs/fileupload/attacks/beans/VulnerabilityType.java rename to src/main/java/org/sasanlabs/fileupload/attacks/model/VulnerabilityType.java index 6e6181c..f8440cd 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/beans/VulnerabilityType.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/model/VulnerabilityType.java @@ -11,7 +11,7 @@ * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ -package org.sasanlabs.fileupload.attacks.beans; +package org.sasanlabs.fileupload.attacks.model; import org.parosproxy.paros.core.scanner.Alert; diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageWithJSPSnippetFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageWithJSPSnippetFileUpload.java index 2916774..033559f 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageWithJSPSnippetFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageWithJSPSnippetFileUpload.java @@ -27,10 +27,10 @@ import org.parosproxy.paros.network.HttpMessage; import org.sasanlabs.fileupload.attacks.AttackVector; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; -import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; -import org.sasanlabs.fileupload.attacks.beans.FileParameter; -import org.sasanlabs.fileupload.attacks.beans.FileParameterBuilder; -import org.sasanlabs.fileupload.attacks.beans.VulnerabilityType; +import org.sasanlabs.fileupload.attacks.model.FileExtensionOperation; +import org.sasanlabs.fileupload.attacks.model.FileParameter; +import org.sasanlabs.fileupload.attacks.model.FileParameterBuilder; +import org.sasanlabs.fileupload.attacks.model.VulnerabilityType; import org.sasanlabs.fileupload.exception.FileUploadException; import org.sasanlabs.fileupload.matcher.impl.ContainsExpectedValueMatcher; diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPFileUpload.java index 55293e0..7036cb9 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPFileUpload.java @@ -21,10 +21,10 @@ import org.parosproxy.paros.core.scanner.Plugin.AttackStrength; import org.sasanlabs.fileupload.attacks.AttackVector; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; -import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; -import org.sasanlabs.fileupload.attacks.beans.FileParameter; -import org.sasanlabs.fileupload.attacks.beans.FileParameterBuilder; -import org.sasanlabs.fileupload.attacks.beans.VulnerabilityType; +import org.sasanlabs.fileupload.attacks.model.FileExtensionOperation; +import org.sasanlabs.fileupload.attacks.model.FileParameter; +import org.sasanlabs.fileupload.attacks.model.FileParameterBuilder; +import org.sasanlabs.fileupload.attacks.model.VulnerabilityType; import org.sasanlabs.fileupload.exception.FileUploadException; import org.sasanlabs.fileupload.matcher.ContentMatcher; import org.sasanlabs.fileupload.matcher.impl.MD5HashResponseMatcher; diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPXFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPXFileUpload.java index b250b5f..8afd2d2 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPXFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPXFileUpload.java @@ -21,10 +21,10 @@ import org.parosproxy.paros.core.scanner.Plugin.AttackStrength; import org.sasanlabs.fileupload.attacks.AttackVector; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; -import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; -import org.sasanlabs.fileupload.attacks.beans.FileParameter; -import org.sasanlabs.fileupload.attacks.beans.FileParameterBuilder; -import org.sasanlabs.fileupload.attacks.beans.VulnerabilityType; +import org.sasanlabs.fileupload.attacks.model.FileExtensionOperation; +import org.sasanlabs.fileupload.attacks.model.FileParameter; +import org.sasanlabs.fileupload.attacks.model.FileParameterBuilder; +import org.sasanlabs.fileupload.attacks.model.VulnerabilityType; import org.sasanlabs.fileupload.exception.FileUploadException; import org.sasanlabs.fileupload.matcher.ContentMatcher; import org.sasanlabs.fileupload.matcher.impl.MD5HashResponseMatcher; diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java index 2434494..1316910 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java @@ -22,10 +22,10 @@ import org.sasanlabs.fileupload.FileUploadUtils; import org.sasanlabs.fileupload.attacks.AttackVector; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; -import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; -import org.sasanlabs.fileupload.attacks.beans.FileParameter; -import org.sasanlabs.fileupload.attacks.beans.FileParameterBuilder; -import org.sasanlabs.fileupload.attacks.beans.VulnerabilityType; +import org.sasanlabs.fileupload.attacks.model.FileExtensionOperation; +import org.sasanlabs.fileupload.attacks.model.FileParameter; +import org.sasanlabs.fileupload.attacks.model.FileParameterBuilder; +import org.sasanlabs.fileupload.attacks.model.VulnerabilityType; import org.sasanlabs.fileupload.exception.FileUploadException; import org.sasanlabs.fileupload.matcher.ContentMatcher; import org.sasanlabs.fileupload.matcher.impl.MD5HashResponseMatcher; diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/xss/SVGFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/xss/SVGFileUpload.java index dfcf4b1..b9f6f8f 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/xss/SVGFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/xss/SVGFileUpload.java @@ -21,10 +21,10 @@ import org.parosproxy.paros.core.scanner.Plugin.AttackStrength; import org.sasanlabs.fileupload.attacks.AttackVector; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; -import org.sasanlabs.fileupload.attacks.beans.FileExtensionOperation; -import org.sasanlabs.fileupload.attacks.beans.FileParameter; -import org.sasanlabs.fileupload.attacks.beans.FileParameterBuilder; -import org.sasanlabs.fileupload.attacks.beans.VulnerabilityType; +import org.sasanlabs.fileupload.attacks.model.FileExtensionOperation; +import org.sasanlabs.fileupload.attacks.model.FileParameter; +import org.sasanlabs.fileupload.attacks.model.FileParameterBuilder; +import org.sasanlabs.fileupload.attacks.model.VulnerabilityType; import org.sasanlabs.fileupload.exception.FileUploadException; /** From 3bafd7decd91e94556a4d46d14b35fb49e7b4dea Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Tue, 20 Jul 2021 16:08:04 +0530 Subject: [PATCH 39/53] Aligning changes as per the multiple variant support PR --- .../java/org/sasanlabs/fileupload/FileUploadScanRule.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java index 65a378c..1830d16 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java @@ -80,7 +80,7 @@ public void decreaseRequestCount() { } @Override - protected void scan(HttpMessage msg, List nameValuePairs) { + protected void scan(List nameValuePairs) { try { boolean isMultipart = false; if (nameValuePairs != null) { @@ -100,7 +100,7 @@ protected void scan(HttpMessage msg, List nameValuePairs) { } if (isMultipart) { FileUploadAttackExecutor fileUploadAttackExecutor = - new FileUploadAttackExecutor(msg, this, nameValuePairs); + new FileUploadAttackExecutor(this.getNewMsg(), this, nameValuePairs); fileUploadAttackExecutor.executeAttack(); } } catch (Exception ex) { From ae3c4f2870d442819c55b5af642b450f09a41068 Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Fri, 23 Jul 2021 22:52:45 +0530 Subject: [PATCH 40/53] Apply suggestions from code review Co-authored-by: Rick M --- .../java/org/sasanlabs/fileupload/FileUploadScanRule.java | 2 +- .../java/org/sasanlabs/fileupload/attacks/AttackVector.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java index 1830d16..76caddb 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java @@ -32,7 +32,7 @@ * applications. The scan rule uploads multiple types of files containing vulnerable code to check * if the application is vulnerable. * - *

This addon fires a lot of requests to the target application hence can impacts the performance + *

This addon fires a lot of requests to the target application hence can impact the performance * of the targeted application. So please run this addon in non-prod environment only. * * @author KSASAN preetkaran20@gmail.com diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java index 3be1871..ea18a93 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java @@ -32,8 +32,8 @@ import org.zaproxy.zap.core.scanner.InputVectorBuilder; /** - * {@code AttackVector} is a common interface for file upload attacks which implements this - * interface. This interface also contains few utility methods for raising alerts and firing + * {@code AttackVector} is a common interface for file upload attacks. + * This interface also contains few utility methods for raising alerts and firing * Preflight requests. * * @author KSASAN preetkaran20@gmail.com From 7ad8e4e88c018e1451579e671ffe5bd272a03eca Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Sat, 24 Jul 2021 13:18:18 +0530 Subject: [PATCH 41/53] Doc update --- CHANGELOG.md | 2 -- build.gradle.kts | 1 - .../fileupload/FileUploadScanRule.java | 1 + .../sasanlabs/fileupload/FileUploadUtils.java | 27 +++++++++++-------- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 03e5e9d..c0754fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,9 +3,7 @@ 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/). -## Unreleased ## [1.0.0] - 2020-12-26 - - First version of FileUpload Addon. - Contains scan rule for finding vulnerabilities related to File Upload. - Types of uploaded files include: diff --git a/build.gradle.kts b/build.gradle.kts index f3bb221..8f83c1a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -43,7 +43,6 @@ zapAddOn { repo.set("https://github.com/SasanLabs/owasp-zap-fileupload-addon/") dependencies { } - changesFile.set(tasks.named("generateManifestChanges").flatMap { it.html }) } } diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java index 1830d16..9e6cd69 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java @@ -36,6 +36,7 @@ * of the targeted application. So please run this addon in non-prod environment only. * * @author KSASAN preetkaran20@gmail.com + * @since 1.0.0 */ public class FileUploadScanRule extends AbstractAppParamPlugin { diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java b/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java index e1b602f..28147b9 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java @@ -22,6 +22,7 @@ * Contains the String constants or other utility functions used by the Addon. * * @author preetkaran20@gmail.com KSASAN + * @since 1.0.0 */ public interface FileUploadUtils { String EMPTY_STRING = ""; @@ -37,7 +38,7 @@ public interface FileUploadUtils { /** * Appends the Period Character to the provided String. * - * @param extension + * @param extension, extension of the file * @return appends {@link #PERIOD} to the provided extension if not {@code null} or empty else * returns same provided extension. */ @@ -52,10 +53,9 @@ static String prefixExtensionWithPeriodCharacter(String extension) { /** * returns the extension of the provided fileName. * - * @param fileName + * @param fileName, name of the file * @return extension of the provided fileName if not null else throws {@code * NullPointerException} - * @throws Null Pointer Exception if fileName is null */ static String getExtension(String fileName) { Objects.requireNonNull(fileName, "FileName cannot be null"); @@ -73,11 +73,11 @@ static String getExtension(String fileName) { *

This utility is useful to find if XSS is possible or not because if {@code * Content-Disposition} header is inline then only XSS is possible. * - * @param preflightMsg + * @param httpMsg, HttpMessage representing request and response * @return {@code True} if {@code Content-Disposition} header is inline */ - static boolean isContentDispositionInline(HttpMessage preflightMsg) { - String headerValue = preflightMsg.getResponseHeader().getHeader("Content-Disposition"); + static boolean isContentDispositionInline(HttpMessage httpMsg) { + String headerValue = httpMsg.getResponseHeader().getHeader("Content-Disposition"); if (headerValue == null || headerValue.trim().equals(FileUploadUtils.EMPTY_STRING) || headerValue.equals("inline")) { @@ -86,8 +86,13 @@ static boolean isContentDispositionInline(HttpMessage preflightMsg) { return false; } - static boolean isContentTypeHeaderPresent(HttpMessage preflightMsg) { - String headerValue = preflightMsg.getResponseHeader().getHeader(HttpHeader.CONTENT_TYPE); + /** + * Utility to check if the {@code HttpHeader#CONTENT_TYPE} header is present in the {@code HttpMessage} + * @param httpMsg, HttpMessage representing request and response + * @return {@code True} if {@code HttpHeader#CONTENT_TYPE} header is present in httpMsg else {@code False} + */ + static boolean isContentTypeHeaderPresent(HttpMessage httpMsg) { + String headerValue = httpMsg.getResponseHeader().getHeader(HttpHeader.CONTENT_TYPE); return StringUtils.isNotBlank(headerValue); } @@ -97,12 +102,12 @@ static boolean isContentTypeHeaderPresent(HttpMessage preflightMsg) { * and {@link * https://security.stackexchange.com/questions/169427/impact-of-the-response-content-type-on-the-exploitability-of-xss} * - * @param preflightMsg + * @param httpMsg, HttpMessage representing request and response * @return {@code True} if content type is one of {@code FileUploadUtils#HTML_MIME_TYPE} or * {@code FileUploadUtils#XHTML_MIME_TYPE} or {@code FileUploadUtils#SVG_MIME_TYPE} */ - static boolean isContentTypeCausesJavascriptExecution(HttpMessage preflightMsg) { - String headerValue = preflightMsg.getResponseHeader().getHeader(HttpHeader.CONTENT_TYPE); + static boolean isContentTypeCausesJavascriptExecution(HttpMessage httpMsg) { + String headerValue = httpMsg.getResponseHeader().getHeader(HttpHeader.CONTENT_TYPE); return StringUtils.isNotBlank(headerValue) && (headerValue.equalsIgnoreCase(HTML_MIME_TYPE) || headerValue.equalsIgnoreCase(XHTML_MIME_TYPE) From 5c7f34e218e7dd23ef47808b07a2cd3b91863fb6 Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Sat, 31 Jul 2021 16:44:20 +0530 Subject: [PATCH 42/53] Incorporating review comments --- .../fileupload/FileUploadScanRule.java | 37 ++- .../sasanlabs/fileupload/FileUploadUtils.java | 103 ++++++- .../fileupload/attacks/AttackVector.java | 288 +++++++++++------- .../attacks/FileUploadAttackExecutor.java | 28 +- .../EicarAntivirusTestFileUpload.java | 66 ++-- .../htaccess/ApachehtaccessFileUpload.java | 16 - ...eter.java => FileInformationProvider.java} | 8 +- ...va => FileInformationProviderBuilder.java} | 35 +-- ....java => FileInformationProviderImpl.java} | 4 +- .../fileupload/attacks/rce/PathTraversal.java | 29 -- .../jsp/ImageWithJSPSnippetFileUpload.java | 172 +++-------- .../attacks/rce/jsp/SimpleJSPFileUpload.java | 161 ++-------- .../attacks/rce/jsp/SimpleJSPXFileUpload.java | 111 ++----- .../fileupload/attacks/rce/php/PhpRCE.java | 28 -- .../attacks/xss/HtmlFileUpload.java | 274 +++++++---------- .../fileupload/attacks/xss/SVGFileUpload.java | 163 ++++------ .../fileupload/locator/URILocatorImpl.java | 9 +- .../fileupload/matcher/ContentMatcher.java | 9 +- 18 files changed, 633 insertions(+), 908 deletions(-) delete mode 100644 src/main/java/org/sasanlabs/fileupload/attacks/apache/htaccess/ApachehtaccessFileUpload.java rename src/main/java/org/sasanlabs/fileupload/attacks/model/{FileParameter.java => FileInformationProvider.java} (84%) rename src/main/java/org/sasanlabs/fileupload/attacks/model/{FileParameterBuilder.java => FileInformationProviderBuilder.java} (54%) rename src/main/java/org/sasanlabs/fileupload/attacks/model/{FileParameterImpl.java => FileInformationProviderImpl.java} (94%) delete mode 100644 src/main/java/org/sasanlabs/fileupload/attacks/rce/PathTraversal.java delete mode 100644 src/main/java/org/sasanlabs/fileupload/attacks/rce/php/PhpRCE.java diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java index d21c752..410dc71 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java @@ -40,7 +40,7 @@ */ public class FileUploadScanRule extends AbstractAppParamPlugin { - private static final int PLUGIN_ID = 110009; + private static final int PLUGIN_ID = 40039; private static final String NAME = FileUploadI18n.getMessage("fileupload.scanrule.name"); private static final String DESCRIPTION = FileUploadI18n.getMessage("fileupload.scanrule.description"); @@ -84,24 +84,26 @@ public void decreaseRequestCount() { protected void scan(List nameValuePairs) { try { boolean isMultipart = false; + String originalFileName = null, originalContentType = null; if (nameValuePairs != null) { - isMultipart = - nameValuePairs.stream() - .anyMatch( - nameValuePair -> - nameValuePair.getType() - == NameValuePair - .TYPE_MULTIPART_DATA_FILE_NAME - || nameValuePair.getType() - == NameValuePair - .TYPE_MULTIPART_DATA_FILE_PARAM - || nameValuePair.getType() - == NameValuePair - .TYPE_MULTIPART_DATA_FILE_CONTENTTYPE); + for (NameValuePair nameValuePair : nameValuePairs) { + if (nameValuePair.getType() == NameValuePair.TYPE_MULTIPART_DATA_FILE_NAME) { + originalFileName = nameValuePair.getValue(); + isMultipart = true; + } else if (nameValuePair.getType() + == NameValuePair.TYPE_MULTIPART_DATA_FILE_CONTENTTYPE) { + originalContentType = nameValuePair.getValue(); + isMultipart = true; + } else if (nameValuePair.getType() + == NameValuePair.TYPE_MULTIPART_DATA_FILE_PARAM) { + isMultipart = true; + } + } } if (isMultipart) { FileUploadAttackExecutor fileUploadAttackExecutor = - new FileUploadAttackExecutor(this.getNewMsg(), this, nameValuePairs); + new FileUploadAttackExecutor( + this, nameValuePairs, originalFileName, originalContentType); fileUploadAttackExecutor.executeAttack(); } } catch (Exception ex) { @@ -148,6 +150,11 @@ public void sendAndRecieve(HttpMessage msg) throws IOException { super.sendAndReceive(msg); } + @Override + public HttpMessage getBaseMsg() { + return super.getBaseMsg(); + } + @Override public int getId() { return PLUGIN_ID; diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java b/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java index 28147b9..5fcd32d 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadUtils.java @@ -13,10 +13,15 @@ */ package org.sasanlabs.fileupload; +import java.util.Arrays; +import java.util.List; import java.util.Objects; import org.apache.commons.lang3.StringUtils; import org.parosproxy.paros.network.HttpHeader; import org.parosproxy.paros.network.HttpMessage; +import org.sasanlabs.fileupload.attacks.model.FileExtensionOperation; +import org.sasanlabs.fileupload.attacks.model.FileInformationProvider; +import org.sasanlabs.fileupload.attacks.model.FileInformationProviderBuilder; /** * Contains the String constants or other utility functions used by the Addon. @@ -34,6 +39,9 @@ public interface FileUploadUtils { String HTML_MIME_TYPE = "text/html"; String XHTML_MIME_TYPE = "application/xhtml+xml"; String SVG_MIME_TYPE = "image/svg+xml"; + String GET_HTTP_METHOD = "GET"; + String JSP_FILE_EXTENSION = "jsp"; + String JSPX_FILE_EXTENSION = "jspx"; /** * Appends the Period Character to the provided String. @@ -87,9 +95,12 @@ static boolean isContentDispositionInline(HttpMessage httpMsg) { } /** - * Utility to check if the {@code HttpHeader#CONTENT_TYPE} header is present in the {@code HttpMessage} + * Utility to check if the {@code HttpHeader#CONTENT_TYPE} header is present in the {@code + * HttpMessage} + * * @param httpMsg, HttpMessage representing request and response - * @return {@code True} if {@code HttpHeader#CONTENT_TYPE} header is present in httpMsg else {@code False} + * @return {@code True} if {@code HttpHeader#CONTENT_TYPE} header is present in httpMsg else + * {@code False} */ static boolean isContentTypeHeaderPresent(HttpMessage httpMsg) { String headerValue = httpMsg.getResponseHeader().getHeader(HttpHeader.CONTENT_TYPE); @@ -97,7 +108,10 @@ static boolean isContentTypeHeaderPresent(HttpMessage httpMsg) { } /** - * References {@link + * Documents with active scripts can be executed by browser based on the {@code + * HttpHeader#CONTENT_TYPE} header. + * + *

References {@link * https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#RULE_.233.1_-_HTML_escape_JSON_values_in_an_HTML_context_and_read_the_data_with_JSON.parse:#:~:text=Good%20HTTP%20response:} * and {@link * https://security.stackexchange.com/questions/169427/impact-of-the-response-content-type-on-the-exploitability-of-xss} @@ -113,4 +127,87 @@ static boolean isContentTypeCausesJavascriptExecution(HttpMessage httpMsg) { || headerValue.equalsIgnoreCase(XHTML_MIME_TYPE) || headerValue.equalsIgnoreCase(SVG_MIME_TYPE)); } + + /** + * Provides extended list of FileInformationProvider for JSP. + * + * @param baseFileName, base file name of uploaded jsp file. + * @return list of FileInformationProvider for JSP + */ + static List getFileInformationProvidersExtendedJsp( + String baseFileName) { + return Arrays.asList( + new FileInformationProviderBuilder(baseFileName) + .withExtension("Jsp") + .withFileExtensionOperation(FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileInformationProviderBuilder(baseFileName) + .withExtension("JSP") + .withFileExtensionOperation(FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileInformationProviderBuilder(baseFileName) + .withExtension("Jsp") + .withContentType("application/x-jsp") + .withFileExtensionOperation(FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileInformationProviderBuilder(baseFileName) + .withExtension("JSP") + .withContentType("application/x-jsp") + .withFileExtensionOperation(FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build()); + } + + /** + * Provides default list of FileInformationProvider for JSP. + * + * @param baseFileName, base file name of uploaded jsp file. + * @param extension, extension of the uploaded jsp file. + * @return list of FileInformationProvider for JSP + */ + static List getFileInformationProvidersDefaultJsp( + String baseFileName, String extension) { + return Arrays.asList( + new FileInformationProviderBuilder(baseFileName) + .withExtension(extension) + .withFileExtensionOperation(FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileInformationProviderBuilder(baseFileName) + .withExtension(extension) + .withContentType("application/x-jsp") + .withFileExtensionOperation(FileExtensionOperation.ONLY_PROVIDED_EXTENSION) + .build(), + new FileInformationProviderBuilder(baseFileName) + .withExtension(extension) + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileInformationProviderBuilder(baseFileName) + .withExtension(extension) + .withContentType("application/x-jsp") + .withFileExtensionOperation( + FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) + .build(), + new FileInformationProviderBuilder(baseFileName) + .withExtension(extension + NULL_BYTE_CHARACTER) + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build(), + new FileInformationProviderBuilder(baseFileName) + .withExtension(extension + NULL_BYTE_CHARACTER) + .withContentType("application/x-jsp") + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build(), + new FileInformationProviderBuilder(baseFileName) + .withExtension(extension + "%00") + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build(), + new FileInformationProviderBuilder(baseFileName) + .withExtension(extension + "%00") + .withContentType("application/x-jsp") + .withFileExtensionOperation( + FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) + .build()); + } } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java index ea18a93..45da368 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java @@ -18,13 +18,17 @@ import java.util.List; import java.util.Objects; import org.apache.commons.httpclient.URI; +import org.apache.log4j.LogManager; +import org.apache.log4j.Logger; import org.parosproxy.paros.core.scanner.Alert; import org.parosproxy.paros.core.scanner.NameValuePair; import org.parosproxy.paros.network.HttpMessage; import org.sasanlabs.fileupload.FileUploadScanRule; -import org.sasanlabs.fileupload.attacks.model.FileParameter; +import org.sasanlabs.fileupload.attacks.antivirus.EicarAntivirusTestFileUpload; +import org.sasanlabs.fileupload.attacks.model.FileInformationProvider; import org.sasanlabs.fileupload.attacks.model.VulnerabilityType; import org.sasanlabs.fileupload.exception.FileUploadException; +import org.sasanlabs.fileupload.function.ConsumerWithException; import org.sasanlabs.fileupload.i18n.FileUploadI18n; import org.sasanlabs.fileupload.locator.URILocatorImpl; import org.sasanlabs.fileupload.matcher.ContentMatcher; @@ -32,150 +36,212 @@ import org.zaproxy.zap.core.scanner.InputVectorBuilder; /** - * {@code AttackVector} is a common interface for file upload attacks. - * This interface also contains few utility methods for raising alerts and firing - * Preflight requests. + * {@code AttackVector} is an abstract template class for file upload attacks. This class also + * contains few utility methods for raising alerts and firing Http requests. * * @author KSASAN preetkaran20@gmail.com */ -public interface AttackVector { +public abstract class AttackVector { + + private static final Logger LOGGER = LogManager.getLogger(EicarAntivirusTestFileUpload.class); /** - * In general file upload functionalities, file is uploaded from a one endpoint and retrieved - * from a another endpoint which makes it extremely difficult to automate. Preflight request is - * the request to another endpoint for retrieval of uploaded file. - * - *

This method finds the url of the file retrieval endpoint, invokes that endpoint and - * returns the {@code HttpMessage}. + * In general, for file upload functionalities, file is uploaded from one endpoint and retrieved + * from another endpoint. This method finds the url of the file retrieval endpoint, invokes that + * endpoint to retrieve the uploaded file and returns the {@code HttpMessage}. * - * @param modifiedMsg - * @param fileUploadScanRule - * @return httpMessage of preflight request - * @throws IOException - * @throws FileUploadException + * @param httpMsg, HttpMessage containing uploaded file's request and response + * @param fileName, uploaded file's name + * @param sendAndRecieveHttpMsg, consumer to send and Receive {@code HttpMessage} + * @return {@code HttpMessage}, representing the file retrieval request and response. It returns + * {@code null} if unable to find the uploaded file. + * @throws FileUploadException, in case of failure in retrieval of uploaded file. */ - default HttpMessage executePreflightRequest( - HttpMessage modifiedMsg, String fileName, FileUploadScanRule fileUploadScanRule) - throws IOException, FileUploadException { - HttpMessage preflightMsg = new HttpMessage(); - URI uri = - new URILocatorImpl() - .get( - modifiedMsg, - fileName, - (httpmessage) -> fileUploadScanRule.sendAndRecieve(httpmessage)); - if (Objects.isNull(uri)) { - return null; - } + private HttpMessage getUploadedFileHttpMessage( + HttpMessage httpMsg, + String fileName, + ConsumerWithException sendAndRecieveHttpMsg) + throws FileUploadException { + HttpMessage uploadedFileRetrievalMsg = new HttpMessage(); + URI uri; + try { + uri = + new URILocatorImpl() + .get( + httpMsg, + fileName, + (httpmessage) -> sendAndRecieveHttpMsg.accept(httpmessage)); + + if (Objects.isNull(uri)) { + return null; + } - preflightMsg.getRequestHeader().setURI(uri); - preflightMsg.getRequestHeader().setMethod("GET"); - preflightMsg.getRequestHeader().setCookies(modifiedMsg.getRequestHeader().getHttpCookies()); - fileUploadScanRule.sendAndRecieve(preflightMsg); - return preflightMsg; + uploadedFileRetrievalMsg.getRequestHeader().setURI(uri); + uploadedFileRetrievalMsg.getRequestHeader().setMethod("GET"); + uploadedFileRetrievalMsg + .getRequestHeader() + .setCookies(httpMsg.getRequestHeader().getHttpCookies()); + sendAndRecieveHttpMsg.accept(uploadedFileRetrievalMsg); + } catch (IOException e) { + throw new FileUploadException( + "Following exception occurred while retrieving uploaded file ", e); + } + return uploadedFileRetrievalMsg; } /** - * This method is used to raise the alert if a vulnerability is found. + * This method is used to raise the alert with the provided details. * - * @param fileUploadScanRule - * @param vulnerabilityType - * @param payload - * @param newMsg - * @param preflight + * @param fileUploadScanRule, File Upload scan rule + * @param vulnerabilityType, type of the vulnerability exposed by the {@code modifiedMsg} + * @param modifiedMsg, {@code HttpMessage} representing the uploaded file's request and + * response. + * @param uploadedFileRetrievalMsg, {@code HttpMessage} representing the file retrieval's + * request and response. */ - default void raiseAlert( + private void raiseAlert( FileUploadScanRule fileUploadScanRule, VulnerabilityType vulnerabilityType, - String payload, - HttpMessage newMsg, - HttpMessage preflight) { + HttpMessage modifiedMsg, + HttpMessage uploadedFileRetrievalMsg) { fileUploadScanRule.raiseAlert( vulnerabilityType.getAlertLevel(), Alert.CONFIDENCE_MEDIUM, FileUploadI18n.getMessage(vulnerabilityType.getMessageKey() + ".name"), FileUploadI18n.getMessage(vulnerabilityType.getMessageKey() + ".desc"), - preflight.getRequestHeader().getURI().toString(), - newMsg.getRequestHeader().toString() + newMsg.getRequestBody().toString(), + uploadedFileRetrievalMsg.getRequestHeader().getURI().toString(), + modifiedMsg.getRequestHeader().toString() + modifiedMsg.getRequestBody().toString(), MessageFormat.format( FileUploadI18n.getMessage("fileupload.alert.attack"), - preflight.getRequestHeader().toString() - + preflight.getRequestBody().toString(), - preflight.getResponseHeader().toString() - + preflight.getResponseBody().toString()), + uploadedFileRetrievalMsg.getRequestHeader().toString() + + uploadedFileRetrievalMsg.getRequestBody().toString(), + uploadedFileRetrievalMsg.getResponseHeader().toString() + + uploadedFileRetrievalMsg.getResponseBody().toString()), FileUploadI18n.getMessage(vulnerabilityType.getMessageKey() + ".refs"), FileUploadI18n.getMessage(vulnerabilityType.getMessageKey() + ".soln"), - newMsg); + modifiedMsg); } /** - * For File Upload vulnerability there are 3 important steps: 1. modify the actual {@code - * HttpMessage} based on the type of attack 2. firing Preflight request 3. response content - * matching to validate if vulnerability is present or not. + * Utility method to upload the provided file. It modifies the {@code HttpMessage} based on the + * provided {@code fileInformationProvider}, {@code payload} and then sends the HttpMessage. * - *

This method executes all these steps. It modifies the {@code HttpMessage} based on the - * {@code fileParameters} then uses {@link #executePreflightRequest(HttpMessage, String, - * FileUploadScanRule)} to execute the Preflight request and then uses the {@code - * ContentMatcher} for validating whether vulnerability is present or not. - * - * @param fileUploadAttackExecutor - * @param contentMatcher - * @param payload - * @param fileParameters - * @param vulnerabilityType - * @return {@code True} if attack is successful else {@code False} - * @throws IOException - * @throws FileUploadException + * @param fileUploadAttackExecutor, holds original {@code HttpMessage}, {@code NameValuePair} + * and {@code FileUploadScanRule} + * @param payload, the content of the file which needs to be uploaded + * @param fileInformationProvider, the modifications provider for a file. + * @return {@code HttpMessage}, representing the file retrieval request and response. It returns + * {@code null} if unable to find the uploaded file. + * @throws FileUploadException, in case of any failure while uploadingfile. */ - default boolean genericAttackExecutor( + private HttpMessage uploadFile( FileUploadAttackExecutor fileUploadAttackExecutor, - ContentMatcher contentMatcher, String payload, - List fileParameters, - VulnerabilityType vulnerabilityType) - throws IOException, FileUploadException { - + FileInformationProvider fileInformationProvider) + throws FileUploadException { List nameValuePairs = fileUploadAttackExecutor.getNameValuePairs(); HttpMessage originalMsg = fileUploadAttackExecutor.getOriginalHttpMessage(); FileUploadScanRule fileUploadScanRule = fileUploadAttackExecutor.getFileUploadScanRule(); - for (FileParameter fileParameter : fileParameters) { + HttpMessage uploadFileMsg = originalMsg.cloneRequest(); + InputVectorBuilder inputVectorBuilder = + fileUploadAttackExecutor.getFileUploadScanRule().getBuilder(); + for (NameValuePair nameValuePair : nameValuePairs) { + if (nameValuePair.getType() == NameValuePair.TYPE_MULTIPART_DATA_FILE_NAME) { + inputVectorBuilder.setValue( + nameValuePair, + fileInformationProvider.getFileName( + fileUploadAttackExecutor.getOriginalFileName()), + PayloadFormat.ALREADY_ESCAPED); + } else if (nameValuePair.getType() == NameValuePair.TYPE_MULTIPART_DATA_FILE_PARAM) { + inputVectorBuilder.setValue(nameValuePair, payload, PayloadFormat.ALREADY_ESCAPED); + } else if (nameValuePair.getType() + == NameValuePair.TYPE_MULTIPART_DATA_FILE_CONTENTTYPE) { + inputVectorBuilder.setValue( + nameValuePair, + fileInformationProvider.getContentType( + fileUploadAttackExecutor.getOriginalContentType()), + PayloadFormat.ALREADY_ESCAPED); + } + } + fileUploadScanRule.setParameters(uploadFileMsg, inputVectorBuilder.build()); + try { + fileUploadScanRule.sendAndRecieve(uploadFileMsg); + } catch (IOException ex) { + throw new FileUploadException("Exception occurred while sending modified message", ex); + } + return uploadFileMsg; + } + + /** + * Generic Attack Executor utility method is used to execute attack by uploading a file, finding + * uploaded file and then raising alerts in case attack is successful. + * + * @param fileUploadAttackExecutor, holds original {@code HttpMessage}, {@code NameValuePair} + * and {@code FileUploadScanRule} + * @param payload, content of the file which will be uploaded + * @param fileInformationProvider, provides information about modifications to the file. + * @param contentMatcher, for matching the uploaded file's content with expected file content. + * @param vulnerabilityType, type of the vulnerability in case attack is successful + * @return {@code True} if attack is successful, else {@code False} + */ + private boolean genericAttackExecutor( + FileUploadAttackExecutor fileUploadAttackExecutor, + String payload, + FileInformationProvider fileInformationProvider, + ContentMatcher contentMatcher, + VulnerabilityType vulnerabilityType) { + try { + HttpMessage uploadFileMsg = + this.uploadFile(fileUploadAttackExecutor, payload, fileInformationProvider); + HttpMessage retrieveUploadedFile = + this.getUploadedFileHttpMessage( + uploadFileMsg, + fileUploadAttackExecutor.getOriginalFileName(), + fileUploadAttackExecutor.getFileUploadScanRule()::sendAndRecieve); + if (Objects.nonNull(retrieveUploadedFile) + && contentMatcher.match(retrieveUploadedFile)) { + raiseAlert( + fileUploadAttackExecutor.getFileUploadScanRule(), + vulnerabilityType, + uploadFileMsg, + retrieveUploadedFile); + return true; + } + } catch (FileUploadException e) { + LOGGER.debug("Following exception occurred: ", e); + } + return false; + } + + /** + * Generic Attack Executor utility method is used to execute attack by uploading files, finding + * uploaded files and then raising alerts in case attack is successful. + * + * @param fileUploadAttackExecutor, holds original {@code HttpMessage}, {@code NameValuePair} + * and {@code FileUploadScanRule} + * @param payload, content of the file which will be uploaded + * @param fileInformationProviders, provides list of file property modification details. + * @param contentMatcher, for matching the uploaded file's content with expected file content. + * @param vulnerabilityType, type of the vulnerability in case attack is successful + * @return {@code True} if attack is successful, else {@code False} + */ + protected boolean genericAttackExecutor( + FileUploadAttackExecutor fileUploadAttackExecutor, + String payload, + List fileInformationProviders, + ContentMatcher contentMatcher, + VulnerabilityType vulnerabilityType) { + for (FileInformationProvider fileInformationProvider : fileInformationProviders) { if (fileUploadAttackExecutor.getFileUploadScanRule().isStop()) { return false; } fileUploadAttackExecutor.getFileUploadScanRule().decreaseRequestCount(); - HttpMessage newMsg = originalMsg.cloneRequest(); - InputVectorBuilder inputVectorBuilder = - fileUploadAttackExecutor.getFileUploadScanRule().getBuilder(); - String originalFileName = null; - for (NameValuePair nameValuePair : nameValuePairs) { - if (nameValuePair.getType() == NameValuePair.TYPE_MULTIPART_DATA_FILE_NAME) { - originalFileName = nameValuePair.getValue(); - inputVectorBuilder.setValue( - nameValuePair, - fileParameter.getFileName(originalFileName), - PayloadFormat.ALREADY_ESCAPED); - } else if (nameValuePair.getType() - == NameValuePair.TYPE_MULTIPART_DATA_FILE_PARAM) { - inputVectorBuilder.setValue( - nameValuePair, payload, PayloadFormat.ALREADY_ESCAPED); - } else if (nameValuePair.getType() - == NameValuePair.TYPE_MULTIPART_DATA_FILE_CONTENTTYPE) { - String originalContentType = nameValuePair.getValue(); - inputVectorBuilder.setValue( - nameValuePair, - fileParameter.getContentType(originalContentType), - PayloadFormat.ALREADY_ESCAPED); - } - } - fileUploadScanRule.setParameters(newMsg, inputVectorBuilder.build()); - fileUploadScanRule.sendAndRecieve(newMsg); - HttpMessage preflightMsg = - this.executePreflightRequest( - newMsg, - fileParameter.getFileName(originalFileName), - fileUploadScanRule); - if (Objects.nonNull(preflightMsg) && contentMatcher.match(preflightMsg)) { - raiseAlert(fileUploadScanRule, vulnerabilityType, payload, newMsg, preflightMsg); + if (this.genericAttackExecutor( + fileUploadAttackExecutor, + payload, + fileInformationProvider, + contentMatcher, + vulnerabilityType)) { return true; } } @@ -194,9 +260,11 @@ default boolean genericAttackExecutor( * Executes the attack and checks if it is successful or not and then raise alert in case of * successful execution. * - * @param fileUploadAttackExecutor + * @param fileUploadAttackExecutor, holds original {@code HttpMessage}, {@code NameValuePair} + * and {@code FileUploadScanRule} * @return {@code true} if attack is successful else {@code false} - * @throws FileUploadException + * @throws FileUploadException, in case of any failure while executing attack */ - boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) throws FileUploadException; + public abstract boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) + throws FileUploadException; } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java b/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java index f9a9fd1..645717c 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/FileUploadAttackExecutor.java @@ -15,6 +15,7 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import org.parosproxy.paros.core.scanner.NameValuePair; import org.parosproxy.paros.network.HttpMessage; @@ -29,7 +30,7 @@ /** * {@code FileUploadAttackExecutor} class is used to find File Upload vulnerability by executing - * list of attack vector. + * list of {@code AttackVector}. * * @author KSASAN preetkaran20@gmail.com */ @@ -38,6 +39,8 @@ public class FileUploadAttackExecutor { private HttpMessage originalHttpMessage; private FileUploadScanRule fileUploadScanRule; private List nameValuePairs = new ArrayList<>(); + private String originalFileName; + private String originalContentType; private List attackVectors = Arrays.asList( new HtmlFileUpload(), @@ -48,13 +51,16 @@ public class FileUploadAttackExecutor { new EicarAntivirusTestFileUpload()); public FileUploadAttackExecutor( - HttpMessage originalHttpMessage, FileUploadScanRule fileUploadScanRule, - List nameValuePairs) { + List nameValuePairs, + String originalFileName, + String originalContentType) { super(); - this.originalHttpMessage = originalHttpMessage; + this.originalHttpMessage = fileUploadScanRule.getBaseMsg(); this.fileUploadScanRule = fileUploadScanRule; - this.nameValuePairs = nameValuePairs; + this.nameValuePairs.addAll(nameValuePairs); + this.originalFileName = originalFileName; + this.originalContentType = originalContentType; } public boolean executeAttack() throws FileUploadException { @@ -71,7 +77,7 @@ public boolean executeAttack() throws FileUploadException { } public HttpMessage getOriginalHttpMessage() { - return originalHttpMessage; + return originalHttpMessage.cloneAll(); } public FileUploadScanRule getFileUploadScanRule() { @@ -79,14 +85,14 @@ public FileUploadScanRule getFileUploadScanRule() { } public List getNameValuePairs() { - return nameValuePairs; + return Collections.unmodifiableList(nameValuePairs); } - public void setNameValuePairs(List nameValuePairs) { - this.nameValuePairs = nameValuePairs; + public String getOriginalFileName() { + return originalFileName; } - public List getAttackVectors() { - return attackVectors; + public String getOriginalContentType() { + return originalContentType; } } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java index 4b315dc..b7f012d 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/antivirus/EicarAntivirusTestFileUpload.java @@ -15,7 +15,6 @@ import static org.sasanlabs.fileupload.FileUploadUtils.NULL_BYTE_CHARACTER; -import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Base64; @@ -23,10 +22,9 @@ import org.sasanlabs.fileupload.attacks.AttackVector; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; import org.sasanlabs.fileupload.attacks.model.FileExtensionOperation; -import org.sasanlabs.fileupload.attacks.model.FileParameter; -import org.sasanlabs.fileupload.attacks.model.FileParameterBuilder; +import org.sasanlabs.fileupload.attacks.model.FileInformationProvider; +import org.sasanlabs.fileupload.attacks.model.FileInformationProviderBuilder; import org.sasanlabs.fileupload.attacks.model.VulnerabilityType; -import org.sasanlabs.fileupload.exception.FileUploadException; import org.sasanlabs.fileupload.matcher.ContentMatcher; import org.sasanlabs.fileupload.matcher.impl.MD5HashResponseMatcher; @@ -44,8 +42,7 @@ * * @author KSASAN preetkaran20@gmail.com */ -public class EicarAntivirusTestFileUpload implements AttackVector { - +public class EicarAntivirusTestFileUpload extends AttackVector { private static final String EICAR_FILE_CONTENT = new String( Base64.getDecoder() @@ -59,7 +56,7 @@ public class EicarAntivirusTestFileUpload implements AttackVector { private static final ContentMatcher CONTENT_MATCHER = new MD5HashResponseMatcher(EICAR_FILE_CONTENT); - private static final List FILE_PARAMETERS_DEFAULT = + private static final List FILE_PARAMETERS_DEFAULT = Arrays.asList( /** * Tested that the file content only matters in case of Eicar file and any @@ -72,75 +69,52 @@ public class EicarAntivirusTestFileUpload implements AttackVector { // Below file parameters might not be needed but just for a safe side added // those. - new FileParameterBuilder(UPLOADED_BASE_FILE_NAME) + new FileInformationProviderBuilder(UPLOADED_BASE_FILE_NAME) .withExtension("com") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(UPLOADED_BASE_FILE_NAME) + new FileInformationProviderBuilder(UPLOADED_BASE_FILE_NAME) .withExtension("exe") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(UPLOADED_BASE_FILE_NAME) + new FileInformationProviderBuilder(UPLOADED_BASE_FILE_NAME) .withExtension("com") .withContentType("application/octet-stream") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(UPLOADED_BASE_FILE_NAME) + new FileInformationProviderBuilder(UPLOADED_BASE_FILE_NAME) .withExtension("exe") .withContentType("vnd.microsoft.portable-executable") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(UPLOADED_BASE_FILE_NAME) - .withExtension("com") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(UPLOADED_BASE_FILE_NAME) - .withExtension("exe") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(UPLOADED_BASE_FILE_NAME) + new FileInformationProviderBuilder(UPLOADED_BASE_FILE_NAME) .withExtension("com") - .withContentType("application/octet-stream") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder(UPLOADED_BASE_FILE_NAME) - .withExtension("exe") - .withContentType("vnd.microsoft.portable-executable") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(UPLOADED_BASE_FILE_NAME) + new FileInformationProviderBuilder(UPLOADED_BASE_FILE_NAME) .withExtension("com" + NULL_BYTE_CHARACTER) - .withContentType("application/octet-stream") .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder(UPLOADED_BASE_FILE_NAME) - .withExtension("exe" + NULL_BYTE_CHARACTER) - .withContentType("vnd.microsoft.portable-executable") + new FileInformationProviderBuilder(UPLOADED_BASE_FILE_NAME) + .withExtension("com" + NULL_BYTE_CHARACTER) + .withContentType("application/octet-stream") .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) .build()); @Override - public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) - throws FileUploadException { - try { - return this.genericAttackExecutor( - fileUploadAttackExecutor, - CONTENT_MATCHER, - EICAR_FILE_CONTENT, - FILE_PARAMETERS_DEFAULT, - VulnerabilityType.EICAR_FILE); - } catch (IOException e) { - throw new FileUploadException(e); - } + public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) { + return this.genericAttackExecutor( + fileUploadAttackExecutor, + EICAR_FILE_CONTENT, + FILE_PARAMETERS_DEFAULT, + CONTENT_MATCHER, + VulnerabilityType.EICAR_FILE); } } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/apache/htaccess/ApachehtaccessFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/apache/htaccess/ApachehtaccessFileUpload.java deleted file mode 100644 index 18fdbf0..0000000 --- a/src/main/java/org/sasanlabs/fileupload/attacks/apache/htaccess/ApachehtaccessFileUpload.java +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Copyright 2021 SasanLabs - * - *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of the License at - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sasanlabs.fileupload.attacks.apache.htaccess; - -public class ApachehtaccessFileUpload {} diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/model/FileParameter.java b/src/main/java/org/sasanlabs/fileupload/attacks/model/FileInformationProvider.java similarity index 84% rename from src/main/java/org/sasanlabs/fileupload/attacks/model/FileParameter.java rename to src/main/java/org/sasanlabs/fileupload/attacks/model/FileInformationProvider.java index 2c874b0..8f61974 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/model/FileParameter.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/model/FileInformationProvider.java @@ -16,15 +16,15 @@ import org.sasanlabs.fileupload.exception.FileUploadException; /** - * {@code FileParameter} interface is used to represent the new file properties. + * {@code FileInformationProvider} interface is used to represent the new file properties. * * @author KSASAN preetkaran20@gmail.com */ @FunctionalInterface -public interface FileParameter { +public interface FileInformationProvider { /** - * Represents the content type of the file parameter. + * Represents the content type of the file. * * @param originalContentType * @return content type @@ -34,7 +34,7 @@ default String getContentType(String originalContentType) { }; /** - * Represents the file name parameter. + * Represents the file name. * * @param originalFileName * @return file name diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/model/FileParameterBuilder.java b/src/main/java/org/sasanlabs/fileupload/attacks/model/FileInformationProviderBuilder.java similarity index 54% rename from src/main/java/org/sasanlabs/fileupload/attacks/model/FileParameterBuilder.java rename to src/main/java/org/sasanlabs/fileupload/attacks/model/FileInformationProviderBuilder.java index b8bdc14..f1b270f 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/model/FileParameterBuilder.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/model/FileInformationProviderBuilder.java @@ -16,48 +16,49 @@ import java.util.Objects; /** - * {@code FileParameterBuilder} is used to build the complex {@code FileParameter} object. + * {@code FileInformationProviderBuilder} is used to build the complex {@code + * FileInformationProvider} object. * * @author KSASAN preetkaran20@gmail.com */ -public class FileParameterBuilder { - private FileParameterImpl fileParameterImpl; +public class FileInformationProviderBuilder { + private FileInformationProviderImpl fileInformationProviderImpl; - public FileParameterBuilder(String baseFileName) { + public FileInformationProviderBuilder(String baseFileName) { Objects.requireNonNull(baseFileName, "FileName cannot be null"); - fileParameterImpl = new FileParameterImpl(baseFileName); + fileInformationProviderImpl = new FileInformationProviderImpl(baseFileName); } - public FileParameterBuilder withFileExtensionOperation( + public FileInformationProviderBuilder withFileExtensionOperation( FileExtensionOperation fileExtensionOperation) { - fileParameterImpl.setFileExtensionOperation(fileExtensionOperation); + fileInformationProviderImpl.setFileExtensionOperation(fileExtensionOperation); return this; } - public FileParameterBuilder withExtension(String providedExtension) { - fileParameterImpl.setExtension(providedExtension); + public FileInformationProviderBuilder withExtension(String providedExtension) { + fileInformationProviderImpl.setExtension(providedExtension); return this; } - public FileParameterBuilder withContentType(String contentType) { - fileParameterImpl.setContentType(contentType); + public FileInformationProviderBuilder withContentType(String contentType) { + fileInformationProviderImpl.setContentType(contentType); return this; } - public FileParameter build() { - if ((fileParameterImpl + public FileInformationProvider build() { + if ((fileInformationProviderImpl .getFileExtensionOperation() .equals(FileExtensionOperation.NO_EXTENSION) - || fileParameterImpl + || fileInformationProviderImpl .getFileExtensionOperation() .equals(FileExtensionOperation.ONLY_ORIGINAL_EXTENSION)) - && fileParameterImpl.getExtension() != null) { + && fileInformationProviderImpl.getExtension() != null) { throw new RuntimeException( "Invalid combination, For FileExtensionOperation: " - + this.fileParameterImpl.getFileExtensionOperation() + + this.fileInformationProviderImpl.getFileExtensionOperation() + ", ProvidedExtension should be null"); } - return fileParameterImpl; + return fileInformationProviderImpl; } } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/model/FileParameterImpl.java b/src/main/java/org/sasanlabs/fileupload/attacks/model/FileInformationProviderImpl.java similarity index 94% rename from src/main/java/org/sasanlabs/fileupload/attacks/model/FileParameterImpl.java rename to src/main/java/org/sasanlabs/fileupload/attacks/model/FileInformationProviderImpl.java index 1d98a16..0c3d97a 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/model/FileParameterImpl.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/model/FileInformationProviderImpl.java @@ -18,14 +18,14 @@ import org.sasanlabs.fileupload.exception.FileUploadException; /** @author KSASAN preetkaran20@gmail.com */ -class FileParameterImpl implements FileParameter { +class FileInformationProviderImpl implements FileInformationProvider { private String baseFileName; private String extension; private String contentType; private FileExtensionOperation fileExtensionOperation = FileExtensionOperation.NO_EXTENSION; - FileParameterImpl(String baseFileName) { + FileInformationProviderImpl(String baseFileName) { this.baseFileName = baseFileName + (new Random(new Date().getTime()).nextLong()); } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/PathTraversal.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/PathTraversal.java deleted file mode 100644 index 6ecda8d..0000000 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/PathTraversal.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright 2021 SasanLabs - * - *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of the License at - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sasanlabs.fileupload.attacks.rce; - -import org.sasanlabs.fileupload.attacks.AttackVector; -import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; -import org.sasanlabs.fileupload.exception.FileUploadException; - -/** @author KSASAN preetkaran20@gmail.com */ -public class PathTraversal implements AttackVector { - - @Override - public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) - throws FileUploadException { - // TODO Auto-generated method stub - return false; - } -} diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageWithJSPSnippetFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageWithJSPSnippetFileUpload.java index 033559f..5506037 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageWithJSPSnippetFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/ImageWithJSPSnippetFileUpload.java @@ -13,9 +13,6 @@ */ package org.sasanlabs.fileupload.attacks.rce.jsp; -import static org.sasanlabs.fileupload.FileUploadUtils.NULL_BYTE_CHARACTER; - -import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.Arrays; @@ -25,17 +22,16 @@ import java.util.Map; import org.parosproxy.paros.core.scanner.Plugin.AttackStrength; import org.parosproxy.paros.network.HttpMessage; +import org.sasanlabs.fileupload.FileUploadUtils; import org.sasanlabs.fileupload.attacks.AttackVector; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; -import org.sasanlabs.fileupload.attacks.model.FileExtensionOperation; -import org.sasanlabs.fileupload.attacks.model.FileParameter; -import org.sasanlabs.fileupload.attacks.model.FileParameterBuilder; +import org.sasanlabs.fileupload.attacks.model.FileInformationProvider; import org.sasanlabs.fileupload.attacks.model.VulnerabilityType; import org.sasanlabs.fileupload.exception.FileUploadException; import org.sasanlabs.fileupload.matcher.impl.ContainsExpectedValueMatcher; /** @author preetkaran20@gmail.com KSASAN */ -public class ImageWithJSPSnippetFileUpload implements AttackVector { +public class ImageWithJSPSnippetFileUpload extends AttackVector { private static final String GIF_IMAGE_JSP_INJECTED_IN_EXIF_BASE64_ENCODED = "R0lGODlhAQABAIAAAP///wAAACH5BAAAAAAAIf5JPCU9ICJJbWFnZVdpdGhKU1BTbmlwcGV0RmlsZVVwbG9hZF8iICsgIlNhc2FuTGFic18iICsgIlpBUF9JZGVudGlmaWVyIiAlPgAsAAAAAAEAAQAAAgJEAQA7"; @@ -55,114 +51,28 @@ public class ImageWithJSPSnippetFileUpload implements AttackVector { private static final String BASE_FILE_NAME = "ImageWithJSPSnippetFileUpload_"; - private static final Map> PAYLOADS = new HashMap<>(); + private static final Map> PAYLOADS = getPayloads(); - { - PAYLOADS.put( + private static Map> getPayloads() { + Map> payloads = new HashMap<>(); + payloads.put( VulnerabilityType.RCE_GIF_JSP_FILE, Arrays.asList( GIF_IMAGE_JSP_INJECTED_IN_EXIF_BASE64_ENCODED, GIF_IMAGE_APPENDED_WITH_JSP_SNIPPET_BASE64_ENCODED)); - PAYLOADS.put( + payloads.put( VulnerabilityType.RCE_JPEG_JSP_FILE, Arrays.asList( JPEG_IMAGE_JSP_INJECTED_IN_EXIF_BASE64_ENCODED, JPEG_IMAGE_APPENDED_WITH_JSP_SNIPPET_BASE64_ENCODED)); + return payloads; } - private static final List FILE_PARAMETERS_EXTENDED = - Arrays.asList( - new FileParameterBuilder(BASE_FILE_NAME) - .withExtension("Jsp") - .withFileExtensionOperation( - FileExtensionOperation.ONLY_PROVIDED_EXTENSION) - .build(), - new FileParameterBuilder(BASE_FILE_NAME) - .withExtension("JSP") - .withFileExtensionOperation( - FileExtensionOperation.ONLY_PROVIDED_EXTENSION) - .build(), - new FileParameterBuilder(BASE_FILE_NAME) - .withExtension("Jsp") - .withContentType("application/x-jsp") - .withFileExtensionOperation( - FileExtensionOperation.ONLY_PROVIDED_EXTENSION) - .build(), - new FileParameterBuilder(BASE_FILE_NAME) - .withExtension("JSP") - .withContentType("application/x-jsp") - .withFileExtensionOperation( - FileExtensionOperation.ONLY_PROVIDED_EXTENSION) - .build(), - new FileParameterBuilder(BASE_FILE_NAME) - .withExtension("Jsp") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(BASE_FILE_NAME) - .withExtension("JSP") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(BASE_FILE_NAME) - .withExtension("Jsp") - .withContentType("application/x-jsp") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(BASE_FILE_NAME) - .withExtension("JSP") - .withContentType("application/x-jsp") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build()); - - private static final List FILE_PARAMETERS_DEFAULT = - Arrays.asList( - new FileParameterBuilder(BASE_FILE_NAME) - .withExtension("jsp") - .withFileExtensionOperation( - FileExtensionOperation.ONLY_PROVIDED_EXTENSION) - .build(), - new FileParameterBuilder(BASE_FILE_NAME) - .withExtension("jsp") - .withContentType("application/x-jsp") - .withFileExtensionOperation( - FileExtensionOperation.ONLY_PROVIDED_EXTENSION) - .build(), - new FileParameterBuilder(BASE_FILE_NAME) - .withExtension("jsp") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(BASE_FILE_NAME) - .withExtension("jsp") - .withContentType("application/x-jsp") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(BASE_FILE_NAME) - .withExtension("jsp" + NULL_BYTE_CHARACTER) - .withFileExtensionOperation( - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(BASE_FILE_NAME) - .withExtension("jsp" + NULL_BYTE_CHARACTER) - .withContentType("application/x-jsp") - .withFileExtensionOperation( - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(BASE_FILE_NAME) - .withExtension("jsp%00") - .withFileExtensionOperation( - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(BASE_FILE_NAME) - .withExtension("jsp%00") - .withContentType("application/x-jsp") - .withFileExtensionOperation( - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) - .build()); + private static final List FILE_PARAMETERS_EXTENDED = + FileUploadUtils.getFileInformationProvidersExtendedJsp(BASE_FILE_NAME); + private static final List FILE_PARAMETERS_DEFAULT = + FileUploadUtils.getFileInformationProvidersDefaultJsp( + BASE_FILE_NAME, FileUploadUtils.JSP_FILE_EXTENSION); @Override public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) @@ -170,41 +80,35 @@ public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) boolean result = false; for (VulnerabilityType vulnerabilityType : PAYLOADS.keySet()) { for (String payloads : PAYLOADS.get(vulnerabilityType)) { - try { - byte[] imagePayload = Base64.getDecoder().decode(payloads); - HttpMessage originalMessage = fileUploadAttackExecutor.getOriginalHttpMessage(); - String charSet = originalMessage.getRequestHeader().getCharset(); - Charset requestCharSet = - charSet != null - ? Charset.forName(charSet) - : StandardCharsets.ISO_8859_1; - String requestPayload = new String(imagePayload, requestCharSet); + byte[] imagePayload = Base64.getDecoder().decode(payloads); + HttpMessage originalMessage = fileUploadAttackExecutor.getOriginalHttpMessage(); + String charSet = originalMessage.getRequestHeader().getCharset(); + Charset requestCharSet = + charSet != null ? Charset.forName(charSet) : StandardCharsets.ISO_8859_1; + String requestPayload = new String(imagePayload, requestCharSet); + result = + this.genericAttackExecutor( + fileUploadAttackExecutor, + requestPayload, + FILE_PARAMETERS_DEFAULT, + new ContainsExpectedValueMatcher(FILE_EXPECTED_VALUE), + vulnerabilityType); + + if (!result + && fileUploadAttackExecutor + .getFileUploadScanRule() + .getAttackStrength() + .equals(AttackStrength.INSANE)) { result = this.genericAttackExecutor( fileUploadAttackExecutor, - new ContainsExpectedValueMatcher(FILE_EXPECTED_VALUE), requestPayload, - FILE_PARAMETERS_DEFAULT, + FILE_PARAMETERS_EXTENDED, + new ContainsExpectedValueMatcher(FILE_EXPECTED_VALUE), vulnerabilityType); - - if (!result - && fileUploadAttackExecutor - .getFileUploadScanRule() - .getAttackStrength() - .equals(AttackStrength.INSANE)) { - result = - this.genericAttackExecutor( - fileUploadAttackExecutor, - new ContainsExpectedValueMatcher(FILE_EXPECTED_VALUE), - requestPayload, - FILE_PARAMETERS_EXTENDED, - vulnerabilityType); - } - if (result) { - return result; - } - } catch (IOException e) { - throw new FileUploadException(e); + } + if (result) { + return result; } } } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPFileUpload.java index 7036cb9..e1c7c66 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPFileUpload.java @@ -13,24 +13,19 @@ */ package org.sasanlabs.fileupload.attacks.rce.jsp; -import static org.sasanlabs.fileupload.FileUploadUtils.NULL_BYTE_CHARACTER; - -import java.io.IOException; -import java.util.Arrays; import java.util.List; import org.parosproxy.paros.core.scanner.Plugin.AttackStrength; +import org.sasanlabs.fileupload.FileUploadUtils; import org.sasanlabs.fileupload.attacks.AttackVector; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; -import org.sasanlabs.fileupload.attacks.model.FileExtensionOperation; -import org.sasanlabs.fileupload.attacks.model.FileParameter; -import org.sasanlabs.fileupload.attacks.model.FileParameterBuilder; +import org.sasanlabs.fileupload.attacks.model.FileInformationProvider; import org.sasanlabs.fileupload.attacks.model.VulnerabilityType; import org.sasanlabs.fileupload.exception.FileUploadException; import org.sasanlabs.fileupload.matcher.ContentMatcher; import org.sasanlabs.fileupload.matcher.impl.MD5HashResponseMatcher; /** @author KSASAN preetkaran20@gmail.com */ -public class SimpleJSPFileUpload implements AttackVector { +public class SimpleJSPFileUpload extends AttackVector { private static final String JSP_UPLOADED_FILE_BASE_NAME = "SimpleJSPFileUpload_"; @@ -43,146 +38,54 @@ public class SimpleJSPFileUpload implements AttackVector { private static final ContentMatcher CONTENT_MATCHER = new MD5HashResponseMatcher("SimpleJSPFileUpload_SasanLabs_ZAP_Identifier"); - private static final List FILE_PARAMETERS_EXTENDED = - Arrays.asList( - new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) - .withExtension("Jsp") - .withFileExtensionOperation( - FileExtensionOperation.ONLY_PROVIDED_EXTENSION) - .build(), - new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) - .withExtension("JSP") - .withFileExtensionOperation( - FileExtensionOperation.ONLY_PROVIDED_EXTENSION) - .build(), - new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) - .withExtension("Jsp") - .withContentType("application/x-jsp") - .withFileExtensionOperation( - FileExtensionOperation.ONLY_PROVIDED_EXTENSION) - .build(), - new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) - .withExtension("JSP") - .withContentType("application/x-jsp") - .withFileExtensionOperation( - FileExtensionOperation.ONLY_PROVIDED_EXTENSION) - .build(), - new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) - .withExtension("Jsp") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) - .withExtension("JSP") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) - .withExtension("Jsp") - .withContentType("application/x-jsp") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) - .withExtension("JSP") - .withContentType("application/x-jsp") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build()); - - private static final List FILE_PARAMETERS_DEFAULT = - Arrays.asList( - new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) - .withExtension("jsp") - .withFileExtensionOperation( - FileExtensionOperation.ONLY_PROVIDED_EXTENSION) - .build(), - new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) - .withExtension("jsp") - .withContentType("application/x-jsp") - .withFileExtensionOperation( - FileExtensionOperation.ONLY_PROVIDED_EXTENSION) - .build(), - new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) - .withExtension("jsp") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) - .withExtension("jsp") - .withContentType("application/x-jsp") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) - .withExtension("jsp" + NULL_BYTE_CHARACTER) - .withFileExtensionOperation( - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) - .withExtension("jsp" + NULL_BYTE_CHARACTER) - .withContentType("application/x-jsp") - .withFileExtensionOperation( - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) - .withExtension("jsp%00") - .withFileExtensionOperation( - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(JSP_UPLOADED_FILE_BASE_NAME) - .withExtension("jsp%00") - .withContentType("application/x-jsp") - .withFileExtensionOperation( - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) - .build()); + private static final List FILE_PARAMETERS_EXTENDED = + FileUploadUtils.getFileInformationProvidersExtendedJsp(JSP_UPLOADED_FILE_BASE_NAME); + private static final List FILE_PARAMETERS_DEFAULT = + FileUploadUtils.getFileInformationProvidersDefaultJsp( + JSP_UPLOADED_FILE_BASE_NAME, FileUploadUtils.JSP_FILE_EXTENSION); @Override public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) throws FileUploadException { - boolean result = false; - try { + boolean result = + this.genericAttackExecutor( + fileUploadAttackExecutor, + JSP_SCRIPTLET_PAYLOAD, + FILE_PARAMETERS_DEFAULT, + CONTENT_MATCHER, + VulnerabilityType.RCE_JSP_FILE); + if (!result) { result = this.genericAttackExecutor( fileUploadAttackExecutor, + JSP_EL_PAYLOAD, + FILE_PARAMETERS_DEFAULT, CONTENT_MATCHER, + VulnerabilityType.RCE_JSP_FILE); + } + if (!result + && fileUploadAttackExecutor + .getFileUploadScanRule() + .getAttackStrength() + .equals(AttackStrength.INSANE)) { + result = + this.genericAttackExecutor( + fileUploadAttackExecutor, JSP_SCRIPTLET_PAYLOAD, - FILE_PARAMETERS_DEFAULT, + FILE_PARAMETERS_EXTENDED, + CONTENT_MATCHER, VulnerabilityType.RCE_JSP_FILE); if (!result) { result = this.genericAttackExecutor( fileUploadAttackExecutor, - CONTENT_MATCHER, JSP_EL_PAYLOAD, - FILE_PARAMETERS_DEFAULT, - VulnerabilityType.RCE_JSP_FILE); - } - if (!result - && fileUploadAttackExecutor - .getFileUploadScanRule() - .getAttackStrength() - .equals(AttackStrength.INSANE)) { - result = - this.genericAttackExecutor( - fileUploadAttackExecutor, - CONTENT_MATCHER, - JSP_SCRIPTLET_PAYLOAD, FILE_PARAMETERS_EXTENDED, + CONTENT_MATCHER, VulnerabilityType.RCE_JSP_FILE); - if (!result) { - result = - this.genericAttackExecutor( - fileUploadAttackExecutor, - CONTENT_MATCHER, - JSP_EL_PAYLOAD, - FILE_PARAMETERS_EXTENDED, - VulnerabilityType.RCE_JSP_FILE); - } } - } catch (IOException e) { - throw new FileUploadException(e); } + return result; } } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPXFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPXFileUpload.java index 8afd2d2..645db5c 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPXFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/rce/jsp/SimpleJSPXFileUpload.java @@ -13,24 +13,22 @@ */ package org.sasanlabs.fileupload.attacks.rce.jsp; -import static org.sasanlabs.fileupload.FileUploadUtils.NULL_BYTE_CHARACTER; - -import java.io.IOException; import java.util.Arrays; import java.util.List; import org.parosproxy.paros.core.scanner.Plugin.AttackStrength; +import org.sasanlabs.fileupload.FileUploadUtils; import org.sasanlabs.fileupload.attacks.AttackVector; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; import org.sasanlabs.fileupload.attacks.model.FileExtensionOperation; -import org.sasanlabs.fileupload.attacks.model.FileParameter; -import org.sasanlabs.fileupload.attacks.model.FileParameterBuilder; +import org.sasanlabs.fileupload.attacks.model.FileInformationProvider; +import org.sasanlabs.fileupload.attacks.model.FileInformationProviderBuilder; import org.sasanlabs.fileupload.attacks.model.VulnerabilityType; import org.sasanlabs.fileupload.exception.FileUploadException; import org.sasanlabs.fileupload.matcher.ContentMatcher; import org.sasanlabs.fileupload.matcher.impl.MD5HashResponseMatcher; /** @author KSASAN preetkaran20@gmail.com */ -public class SimpleJSPXFileUpload implements AttackVector { +public class SimpleJSPXFileUpload extends AttackVector { private static final String JSPX_UPLOADED_FILE_BASE_NAME = "SimpleJSPXFileUpload_"; // Payload from resource file: "jspx_payload.jspx" @@ -46,47 +44,47 @@ public class SimpleJSPXFileUpload implements AttackVector { private static final ContentMatcher CONTENT_MATCHER = new MD5HashResponseMatcher("SimpleJSPXFileUpload_SasanLabs_ZAP_Identifier"); - private static final List FILE_PARAMETERS_EXTENDED = + private static final List FILE_PARAMETERS_EXTENDED = Arrays.asList( - new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(JSPX_UPLOADED_FILE_BASE_NAME) .withExtension("JspX") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(JSPX_UPLOADED_FILE_BASE_NAME) .withExtension("JSPX") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(JSPX_UPLOADED_FILE_BASE_NAME) .withExtension("JspX") .withContentType("application/x-jsp") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(JSPX_UPLOADED_FILE_BASE_NAME) .withExtension("JSPX") .withContentType("application/x-jsp") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(JSPX_UPLOADED_FILE_BASE_NAME) .withExtension("JspX") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(JSPX_UPLOADED_FILE_BASE_NAME) .withExtension("JSPX") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(JSPX_UPLOADED_FILE_BASE_NAME) .withExtension("JspX") .withContentType("application/x-jsp") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(JSPX_UPLOADED_FILE_BASE_NAME) .withExtension("JSPX") .withContentType("application/x-jsp") .withFileExtensionOperation( @@ -96,81 +94,34 @@ public class SimpleJSPXFileUpload implements AttackVector { // Need to validate // application/x-httpd-jsp // text/x-jsp - private static final List FILE_PARAMETERS = - Arrays.asList( - new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) - .withExtension("jspx") - .withFileExtensionOperation( - FileExtensionOperation.ONLY_PROVIDED_EXTENSION) - .build(), - new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) - .withExtension("jspx") - .withContentType("application/x-jsp") - .withFileExtensionOperation( - FileExtensionOperation.ONLY_PROVIDED_EXTENSION) - .build(), - new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) - .withExtension("jspx") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) - .withExtension("jspx") - .withContentType("application/x-jsp") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) - .withExtension("jspx" + NULL_BYTE_CHARACTER) - .withFileExtensionOperation( - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) - .withExtension("jspx" + NULL_BYTE_CHARACTER) - .withContentType("application/x-jsp") - .withFileExtensionOperation( - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) - .withExtension("jspx%00") - .withFileExtensionOperation( - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(JSPX_UPLOADED_FILE_BASE_NAME) - .withExtension("jspx%00") - .withContentType("application/x-jsp") - .withFileExtensionOperation( - FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) - .build()); + private static final List FILE_PARAMETERS = + FileUploadUtils.getFileInformationProvidersDefaultJsp( + JSPX_UPLOADED_FILE_BASE_NAME, FileUploadUtils.JSPX_FILE_EXTENSION); @Override public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) throws FileUploadException { - boolean result = false; - try { + boolean result = + this.genericAttackExecutor( + fileUploadAttackExecutor, + JSPX_PAYLOAD, + FILE_PARAMETERS, + CONTENT_MATCHER, + VulnerabilityType.RCE_JSPX_FILE); + if (!result + && fileUploadAttackExecutor + .getFileUploadScanRule() + .getAttackStrength() + .equals(AttackStrength.INSANE)) { result = this.genericAttackExecutor( fileUploadAttackExecutor, - CONTENT_MATCHER, JSPX_PAYLOAD, - FILE_PARAMETERS, + FILE_PARAMETERS_EXTENDED, + CONTENT_MATCHER, VulnerabilityType.RCE_JSPX_FILE); - if (!result - && fileUploadAttackExecutor - .getFileUploadScanRule() - .getAttackStrength() - .equals(AttackStrength.INSANE)) { - result = - this.genericAttackExecutor( - fileUploadAttackExecutor, - CONTENT_MATCHER, - JSPX_PAYLOAD, - FILE_PARAMETERS_EXTENDED, - VulnerabilityType.RCE_JSPX_FILE); - } - } catch (IOException e) { - throw new FileUploadException(e); } + return result; } } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/rce/php/PhpRCE.java b/src/main/java/org/sasanlabs/fileupload/attacks/rce/php/PhpRCE.java deleted file mode 100644 index db7ffd1..0000000 --- a/src/main/java/org/sasanlabs/fileupload/attacks/rce/php/PhpRCE.java +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Copyright 2021 SasanLabs - * - *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of the License at - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sasanlabs.fileupload.attacks.rce.php; - -import org.sasanlabs.fileupload.attacks.AttackVector; -import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; -import org.sasanlabs.fileupload.exception.FileUploadException; - -public class PhpRCE implements AttackVector { - - @Override - public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) - throws FileUploadException { - // TODO Auto-generated method stub - return false; - } -} diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java index 1316910..938499a 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/xss/HtmlFileUpload.java @@ -15,7 +15,6 @@ import static org.sasanlabs.fileupload.FileUploadUtils.NULL_BYTE_CHARACTER; -import java.io.IOException; import java.util.Arrays; import java.util.List; import org.parosproxy.paros.core.scanner.Plugin.AttackStrength; @@ -23,10 +22,9 @@ import org.sasanlabs.fileupload.attacks.AttackVector; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; import org.sasanlabs.fileupload.attacks.model.FileExtensionOperation; -import org.sasanlabs.fileupload.attacks.model.FileParameter; -import org.sasanlabs.fileupload.attacks.model.FileParameterBuilder; +import org.sasanlabs.fileupload.attacks.model.FileInformationProvider; +import org.sasanlabs.fileupload.attacks.model.FileInformationProviderBuilder; import org.sasanlabs.fileupload.attacks.model.VulnerabilityType; -import org.sasanlabs.fileupload.exception.FileUploadException; import org.sasanlabs.fileupload.matcher.ContentMatcher; import org.sasanlabs.fileupload.matcher.impl.MD5HashResponseMatcher; @@ -40,7 +38,7 @@ * * @author preetkaran20@gmail.com KSASAN */ -public class HtmlFileUpload implements AttackVector { +public class HtmlFileUpload extends AttackVector { private static final String XSS_UPLOADED_FILE_BASE_NAME = "HtmlFileUpload_XSS_"; private static final String XSS_PAYLOAD_HTML_FILE = @@ -65,371 +63,316 @@ public class HtmlFileUpload implements AttackVector { XSS_PAYLOAD_HTML_FILE); // Extended list for breaking black-listing strategy. - private static final List FILE_PARAMETERS_EXTENDED = + private static final List FILE_PARAMETERS_EXTENDED = Arrays.asList( - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Htm") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("hTM") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("HTM") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("HtML") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("HTMl") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("HTML") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Xhtml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xHTml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xhTML") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xHTML") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("XHTML") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("dHtml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("sHtml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("dHTml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("sHTml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("dHTML") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("sHTML") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Htm") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("hTM") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("HTM") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Html") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("HtML") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("HTMl") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("HTML") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Xhtml") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xHTml") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xhTML") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xHTML") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("XHTML") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("dHtml") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("sHtml") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("dHTml") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("sHTml") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("dHTML") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("sHTML") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Htm") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("hTM") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("HTM") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Html") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("HtML") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("HTMl") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("HTML") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Xhtml") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xHTml") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xhTML") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xHTML") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("XHTML") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("dHtml") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("sHtml") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("dHTml") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("sHTml") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("dHTML") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("sHTML") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) - .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) - .withExtension("Htm") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) - .withExtension("HTML") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) - .withExtension("Xhtml") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) - .withExtension("XHTML") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) - .withExtension("Htm") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) - .withExtension("Htm") - .withContentType("text/html") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) - .withExtension("HTML") - .withContentType("text/html") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) - .withExtension("Xhtml") - .withContentType("text/html") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) - .withExtension("XHTML") - .withContentType("text/html") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) - .withExtension("Htm") - .withContentType("text/html") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build()); - private static final List FILE_PARAMETERS_DEFAULT = + private static final List FILE_PARAMETERS_DEFAULT = Arrays.asList( /** * No extension is required, actually browser reads the content-type header of @@ -450,20 +393,20 @@ public class HtmlFileUpload implements AttackVector { * strtolower(end(explode('.',$_FILES['image']['name'])));} */ originalFileName -> FileUploadUtils.getExtension(originalFileName), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withFileExtensionOperation(FileExtensionOperation.NO_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("htm") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xhtml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) @@ -472,12 +415,12 @@ public class HtmlFileUpload implements AttackVector { * Server Parsed Html for server side includes * https://stackoverflow.com/questions/519619/what-is-the-purpose-and-uniqueness-shtml */ - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("dhtml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("shtml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) @@ -488,66 +431,66 @@ public class HtmlFileUpload implements AttackVector { * blacklist validation of extensions. For more information {@link * https://www.acunetix.com/websitesecurity/upload-forms-threat/#:~:text=Double%20Extensions} */ - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("html.123") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("htm") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("html") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xhtml") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("shtml") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("dhtml") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("htm") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("html") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xhtml") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("shtml") .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("dhtml") .withContentType("text/plain") .withFileExtensionOperation( @@ -558,68 +501,68 @@ public class HtmlFileUpload implements AttackVector { * .gif.html} If validator only validates contains {@code .gif} extension then * validator will be bypassed. */ - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("htm") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("html") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xhtml") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("htm") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("html") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xhtml") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("htm" + NULL_BYTE_CHARACTER) .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("htm" + NULL_BYTE_CHARACTER) .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("htm" + NULL_BYTE_CHARACTER) .withContentType("text/plain") .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("htm%00") .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("htm%00") .withContentType("text/html") .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("htm%00") .withContentType("text/plain") .withFileExtensionOperation( @@ -631,37 +574,28 @@ public class HtmlFileUpload implements AttackVector { */ ); - /** - * @throws FileUploadException - * @throws IOException - */ @Override - public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) - throws FileUploadException { - boolean result = false; - try { + public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) { + + boolean result = + this.genericAttackExecutor( + fileUploadAttackExecutor, + XSS_PAYLOAD_HTML_FILE, + FILE_PARAMETERS_DEFAULT, + CONTENT_MATCHER, + VulnerabilityType.XSS_HTML_FILE); + if (!result + && fileUploadAttackExecutor + .getFileUploadScanRule() + .getAttackStrength() + .equals(AttackStrength.INSANE)) { result = this.genericAttackExecutor( fileUploadAttackExecutor, - CONTENT_MATCHER, XSS_PAYLOAD_HTML_FILE, - FILE_PARAMETERS_DEFAULT, + FILE_PARAMETERS_EXTENDED, + CONTENT_MATCHER, VulnerabilityType.XSS_HTML_FILE); - if (!result - && fileUploadAttackExecutor - .getFileUploadScanRule() - .getAttackStrength() - .equals(AttackStrength.INSANE)) { - result = - this.genericAttackExecutor( - fileUploadAttackExecutor, - CONTENT_MATCHER, - XSS_PAYLOAD_HTML_FILE, - FILE_PARAMETERS_EXTENDED, - VulnerabilityType.XSS_HTML_FILE); - } - } catch (IOException e) { - throw new FileUploadException(e); } return result; } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/xss/SVGFileUpload.java b/src/main/java/org/sasanlabs/fileupload/attacks/xss/SVGFileUpload.java index b9f6f8f..50d7864 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/xss/SVGFileUpload.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/xss/SVGFileUpload.java @@ -15,17 +15,15 @@ import static org.sasanlabs.fileupload.FileUploadUtils.NULL_BYTE_CHARACTER; -import java.io.IOException; import java.util.Arrays; import java.util.List; import org.parosproxy.paros.core.scanner.Plugin.AttackStrength; import org.sasanlabs.fileupload.attacks.AttackVector; import org.sasanlabs.fileupload.attacks.FileUploadAttackExecutor; import org.sasanlabs.fileupload.attacks.model.FileExtensionOperation; -import org.sasanlabs.fileupload.attacks.model.FileParameter; -import org.sasanlabs.fileupload.attacks.model.FileParameterBuilder; +import org.sasanlabs.fileupload.attacks.model.FileInformationProvider; +import org.sasanlabs.fileupload.attacks.model.FileInformationProviderBuilder; import org.sasanlabs.fileupload.attacks.model.VulnerabilityType; -import org.sasanlabs.fileupload.exception.FileUploadException; /** * {@code SVGFileUpload} attack vector will upload {@code svg} and its various different extension @@ -37,7 +35,7 @@ * * @author preetkaran20@gmail.com KSASAN */ -public class SVGFileUpload implements AttackVector { +public class SVGFileUpload extends AttackVector { private static final String XSS_UPLOADED_FILE_BASE_NAME = "SVGFileUpload_XSS_"; private static final String XSS_PAYLOAD_SVG_FILE = @@ -48,178 +46,142 @@ public class SVGFileUpload implements AttackVector { + ""; // Extended list for breaking black-listing strategy. - private static final List FILE_PARAMETERS_EXTENDED = + private static final List FILE_PARAMETERS_EXTENDED = Arrays.asList( - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Svg") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("SvG") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("SVG") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Svgz") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("SvGz") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("SVGZ") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xML") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("XML") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Svg") .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("SvG") .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("SVG") .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Svgz") .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("SvGz") .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("SVGZ") .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xML") .withContentType("text/xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Xml") .withContentType("text/xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("XML") .withContentType("text/xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Svg") .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("SVG") .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("Svgz") .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("SVGZ") .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xML") .withContentType("text/xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("XML") .withContentType("text/xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) - .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) - .withExtension("Svg") - .withContentType("image/svg+xml") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) - .withExtension("SVG") - .withContentType("image/svg+xml") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) - .withExtension("Svgz") - .withContentType("image/svg+xml") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) - .withExtension("SVGZ") - .withContentType("image/svg+xml") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) - .withExtension("xML") - .withContentType("text/xml") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) - .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) - .withExtension("XML") - .withContentType("text/xml") - .withFileExtensionOperation( - FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build()); /** @@ -229,112 +191,103 @@ public class SVGFileUpload implements AttackVector { *

Didn't pick html and its related variant extensions because those attack vectors will be * covered under {@link HtmlFileUpload}. */ - private static final List FILE_PARAMETERS_DEFAULT = + private static final List FILE_PARAMETERS_DEFAULT = Arrays.asList( // Not adding empty extension for svg because it is not working in browsers - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("svg") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("svgz") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("svg") .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xml") .withContentType("text/xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("svgz") .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.ONLY_PROVIDED_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("svg") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("xml") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("svgz") .withFileExtensionOperation( FileExtensionOperation.PREFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("svg" + NULL_BYTE_CHARACTER) .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("svg" + NULL_BYTE_CHARACTER) .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("svg%00") .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) .build(), - new FileParameterBuilder(XSS_UPLOADED_FILE_BASE_NAME) + new FileInformationProviderBuilder(XSS_UPLOADED_FILE_BASE_NAME) .withExtension("svg%00") .withContentType("image/svg+xml") .withFileExtensionOperation( FileExtensionOperation.SUFFIX_ORIGINAL_EXTENSION) .build()); - /** - * @throws FileUploadException - * @throws IOException - */ @Override - public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) - throws FileUploadException { - boolean result = false; - try { + public boolean execute(FileUploadAttackExecutor fileUploadAttackExecutor) { + boolean result = + this.genericAttackExecutor( + fileUploadAttackExecutor, + XSS_PAYLOAD_SVG_FILE, + FILE_PARAMETERS_DEFAULT, + HtmlFileUpload.CONTENT_MATCHER, + VulnerabilityType.XSS_SVG_FILE); + if (!result + && fileUploadAttackExecutor + .getFileUploadScanRule() + .getAttackStrength() + .equals(AttackStrength.INSANE)) { result = this.genericAttackExecutor( fileUploadAttackExecutor, - HtmlFileUpload.CONTENT_MATCHER, XSS_PAYLOAD_SVG_FILE, - FILE_PARAMETERS_DEFAULT, + FILE_PARAMETERS_EXTENDED, + HtmlFileUpload.CONTENT_MATCHER, VulnerabilityType.XSS_SVG_FILE); - if (!result - && fileUploadAttackExecutor - .getFileUploadScanRule() - .getAttackStrength() - .equals(AttackStrength.INSANE)) { - result = - this.genericAttackExecutor( - fileUploadAttackExecutor, - HtmlFileUpload.CONTENT_MATCHER, - XSS_PAYLOAD_SVG_FILE, - FILE_PARAMETERS_EXTENDED, - VulnerabilityType.XSS_SVG_FILE); - } - } catch (IOException e) { - throw new FileUploadException(e); } + return result; } } diff --git a/src/main/java/org/sasanlabs/fileupload/locator/URILocatorImpl.java b/src/main/java/org/sasanlabs/fileupload/locator/URILocatorImpl.java index 3ae79c6..b150eb7 100644 --- a/src/main/java/org/sasanlabs/fileupload/locator/URILocatorImpl.java +++ b/src/main/java/org/sasanlabs/fileupload/locator/URILocatorImpl.java @@ -14,7 +14,7 @@ package org.sasanlabs.fileupload.locator; import java.io.IOException; -import java.util.HashMap; +import java.util.Collections; import java.util.Map; import org.apache.commons.httpclient.URI; import org.apache.commons.httpclient.URIException; @@ -45,8 +45,7 @@ private URI getCompleteURI(String uriRegex, String fileName, HttpMessage msg) if (fileName.contains(FileUploadUtils.NULL_BYTE_CHARACTER)) { fileName = fileName.substring(0, fileName.indexOf(FileUploadUtils.NULL_BYTE_CHARACTER)); } - Map replacerKeyValuePair = new HashMap<>(); - replacerKeyValuePair.put("filename", fileName); + Map replacerKeyValuePair = Collections.singletonMap("filename", fileName); StringSubstitutor stringSubstitutor = new StringSubstitutor(replacerKeyValuePair); String uriFragment = stringSubstitutor.replace(uriRegex); if (uriFragment.startsWith(FileUploadUtils.HTTP_SCHEME) @@ -101,7 +100,7 @@ public URI get( HttpMessage msg, String fileName, ConsumerWithException sendAndRecieve) - throws FileUploadException, IOException { + throws FileUploadException { URI uri = null; try { if (StringUtils.isNotBlank( @@ -139,7 +138,7 @@ public URI get( } } } - } catch (URIException ex) { + } catch (IOException ex) { throw new FileUploadException(ex); } return uri; diff --git a/src/main/java/org/sasanlabs/fileupload/matcher/ContentMatcher.java b/src/main/java/org/sasanlabs/fileupload/matcher/ContentMatcher.java index 8438191..882db9d 100644 --- a/src/main/java/org/sasanlabs/fileupload/matcher/ContentMatcher.java +++ b/src/main/java/org/sasanlabs/fileupload/matcher/ContentMatcher.java @@ -16,8 +16,8 @@ import org.parosproxy.paros.network.HttpMessage; /** - * {@code ContentMatcher} class is used to match the contents of provided Preflight {@code - * HttpMessage} + * {@code ContentMatcher} class is used to match the contents of provided {@code HttpMessage} with + * the expected values * * @author preetkaran20@gmail.com KSASAN */ @@ -25,8 +25,9 @@ public interface ContentMatcher { /** - * @param msg Preflight {@code HttpMessage} - * @return {@code True} if content of Preflight {@code HttpMessage} matches else {@code False} + * @param msg, {@code HttpMessage} for comparing with the expected values + * @return {@code True} if {@code HttpMessage} matches with the expected values else {@code + * False} */ boolean match(HttpMessage msg); } From 8df34b46643b4914da961a07a3f7b6c4c3145e47 Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Sat, 31 Jul 2021 16:45:42 +0530 Subject: [PATCH 43/53] incorporating review comments --- build.gradle.kts | 2 -- 1 file changed, 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 8f83c1a..407572e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -41,8 +41,6 @@ zapAddOn { manifest { author.set("KSASAN preetkaran20@gmail.com") repo.set("https://github.com/SasanLabs/owasp-zap-fileupload-addon/") - dependencies { - } } } From 221ccf08477a89f9a69919660e15f9c3b084f18d Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Sat, 31 Jul 2021 16:46:48 +0530 Subject: [PATCH 44/53] Update build.gradle.kts --- build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 407572e..dced635 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -40,9 +40,9 @@ zapAddOn { manifest { author.set("KSASAN preetkaran20@gmail.com") - repo.set("https://github.com/SasanLabs/owasp-zap-fileupload-addon/") + repo.set("https://github.com/SasanLabs/owasp-zap-fileupload-addon/") } } dependencies { -} \ No newline at end of file +} From 17f9101ebc4cbbd6dac5cb7e3292dea9048c8118 Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Sat, 31 Jul 2021 16:47:46 +0530 Subject: [PATCH 45/53] small fix --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index dced635..493ed2e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -40,7 +40,7 @@ zapAddOn { manifest { author.set("KSASAN preetkaran20@gmail.com") - repo.set("https://github.com/SasanLabs/owasp-zap-fileupload-addon/") + repo.set("https://github.com/SasanLabs/owasp-zap-fileupload-addon/") } } From e80d0cf0205688158b8488a8c7049e34164e6f32 Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Sat, 31 Jul 2021 16:52:21 +0530 Subject: [PATCH 46/53] Removing TODO --- .../fileupload/configuration/FileUploadConfiguration.java | 2 +- src/main/java/org/sasanlabs/fileupload/i18n/FileUploadI18n.java | 2 +- .../org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/sasanlabs/fileupload/configuration/FileUploadConfiguration.java b/src/main/java/org/sasanlabs/fileupload/configuration/FileUploadConfiguration.java index 3a649c9..c912275 100644 --- a/src/main/java/org/sasanlabs/fileupload/configuration/FileUploadConfiguration.java +++ b/src/main/java/org/sasanlabs/fileupload/configuration/FileUploadConfiguration.java @@ -20,7 +20,7 @@ * This class holds configuration related to FileUpload Addon. * * @author KSASAN preetkaran20@gmail.com - * @since TODO add version + * @since 1.0.0 */ public class FileUploadConfiguration extends VersionedAbstractParam { diff --git a/src/main/java/org/sasanlabs/fileupload/i18n/FileUploadI18n.java b/src/main/java/org/sasanlabs/fileupload/i18n/FileUploadI18n.java index aa8a6fb..118a423 100644 --- a/src/main/java/org/sasanlabs/fileupload/i18n/FileUploadI18n.java +++ b/src/main/java/org/sasanlabs/fileupload/i18n/FileUploadI18n.java @@ -20,7 +20,7 @@ * Message Bundle * * @author KSASAN preetkaran20@gmail.com - * @since TODO add version + * @since 1.0.0 */ public class FileUploadI18n { private static ResourceBundle message; diff --git a/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java b/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java index c54f835..b091225 100644 --- a/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java +++ b/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java @@ -38,7 +38,7 @@ * finding vulnerabilities related to FileUpload functionality in the applications. * * @author KSASAN preetkaran20@gmail.com - * @since TODO add version + * @since 1.0.0 */ public class FileUploadOptionsPanel extends AbstractParamPanel { private static final long serialVersionUID = 1L; From 69c45d0dcaa046b664f8eb5d0fe3b66d79a5d8eb Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Sat, 31 Jul 2021 18:48:44 +0530 Subject: [PATCH 47/53] Adding a new plugin id --- src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java index 410dc71..53220c2 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java @@ -40,7 +40,7 @@ */ public class FileUploadScanRule extends AbstractAppParamPlugin { - private static final int PLUGIN_ID = 40039; + private static final int PLUGIN_ID = 40041; private static final String NAME = FileUploadI18n.getMessage("fileupload.scanrule.name"); private static final String DESCRIPTION = FileUploadI18n.getMessage("fileupload.scanrule.description"); From 94f8aded4afcc19e9473c62723265f88cf063882 Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Thu, 5 Aug 2021 09:13:58 +0530 Subject: [PATCH 48/53] Incorporating review comments --- CHANGELOG.md | 2 +- README.md | 7 +++++-- build.gradle.kts | 3 ++- docs/{ => images}/fileupload-options-panel.png | Bin 4 files changed, 8 insertions(+), 4 deletions(-) rename docs/{ => images}/fileupload-options-panel.png (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index c0754fa..c42d7ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ 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.0] - 2020-12-26 +## [1.0.0] - 2021-08-05 - First version of FileUpload Addon. - Contains scan rule for finding vulnerabilities related to File Upload. - Types of uploaded files include: diff --git a/README.md b/README.md index 80281d7..42591f5 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # owasp-zap-fileupload-addon -[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com) ![Java CI with Gradle](https://github.com/SasanLabs/owasp-zap-jwt-addon/workflows/Java%20CI%20with%20Gradle/badge.svg?branch=master) +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com) ![Java CI with Gradle](https://github.com/SasanLabs/owasp-zap-fileupload-addon/workflows/Java%20CI%20with%20Gradle/badge.svg?branch=master) This project contains the File Upload scan rule which is used to find the vulnerabilities in File Upload functionality. @@ -19,9 +19,12 @@ parameter, for e.g. `http:///${fileName}` 2. In some applications the URL to retrieve the uploaded file is present in the file upload request's response. For handling this type of configuration, options panel has `Dynamic Location Configuration` which has 2 parameters `Start Identifier` and `End Identifier`. These identifiers are used to locate the URL within the response. 3. In some applications the URL to retrieve the uploaded file is present in the response of a different URL which is called a preflight request. E.g. Profile picture URL is part of profile page and hence we need to parse the response of the profile page to find the URL of the profile picture. For handling this type of configuration, the options panel has `Dynamic Location Configuration` which has a `URI Regex`, `Start Identifier`, and `End Identifier`. So the File Upload add-on will invoke the URI mentioned in `URI Regex` and then parse the response using `Start Identifier` and `End Identifier`. `URI Regex` field also supports the dynamic file name by `${fileName}` +### Note: +This addon fires a lot of requests to the target application hence can impact the performance of the targeted application. So please run this addon in non-prod environment only. + ## Contributing guidelines Contributing guidelines are same as [ZAP](https://github.com/zaproxy/zaproxy). ## Contact Us -For any Queries/Bugs or Enhancement please raise an issue in this repository or [ZAP](https://github.com/zaproxy/zaproxy). +For any Queries/Bugs or Enhancement please raise an issue in this repository or ask in [OWASP ZAP Developer Group](https://groups.google.com/g/zaproxy-develop). For any other kind of issues please send an email to karan.sasan@owasp.org diff --git a/build.gradle.kts b/build.gradle.kts index 493ed2e..902d227 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -35,14 +35,15 @@ description = "Detect File upload requests and scan them to find related vulnera zapAddOn { addOnName.set("File upload Scan Rule") - zapVersion.set("2.11.0-SNAPSHOT") addOnStatus.set(AddOnStatus.ALPHA) manifest { author.set("KSASAN preetkaran20@gmail.com") + notBeforeVersion.set("2.11.0") repo.set("https://github.com/SasanLabs/owasp-zap-fileupload-addon/") } } dependencies { + implementation("org.zaproxy:zap:2.11.0-SNAPSHOT") } diff --git a/docs/fileupload-options-panel.png b/docs/images/fileupload-options-panel.png similarity index 100% rename from docs/fileupload-options-panel.png rename to docs/images/fileupload-options-panel.png From b3ef6ccc16427acc5f6b96ed13d71a1e374d432a Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Sun, 8 Aug 2021 15:49:45 +0530 Subject: [PATCH 49/53] Incorporating review comments --- README.md | 4 +- build.gradle.kts | 5 +- docs/images/fileupload-options-panel.png | Bin 202986 -> 215451 bytes .../fileupload/FileUploadScanRule.java | 20 ++-- .../fileupload/attacks/AttackVector.java | 4 +- .../fileupload/ui/FileUploadOptionsPanel.java | 91 +++++++++++------- .../resources/help/contents/fileupload.html | 56 +++++++++++ .../fileupload/resources/help/helpset.hs | 41 ++++++++ .../fileupload/resources/help/index.xml | 9 ++ .../fileupload/resources/help/map.jhm | 8 ++ .../fileupload/resources/help/toc.xml | 12 +++ .../fileupload/i18n/Messages.properties | 7 +- 12 files changed, 201 insertions(+), 56 deletions(-) create mode 100644 src/main/javahelp/org/sasanlabs/fileupload/resources/help/contents/fileupload.html create mode 100644 src/main/javahelp/org/sasanlabs/fileupload/resources/help/helpset.hs create mode 100644 src/main/javahelp/org/sasanlabs/fileupload/resources/help/index.xml create mode 100644 src/main/javahelp/org/sasanlabs/fileupload/resources/help/map.jhm create mode 100644 src/main/javahelp/org/sasanlabs/fileupload/resources/help/toc.xml diff --git a/README.md b/README.md index 42591f5..905f081 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,8 @@ Under ZAP's Options dialog you will find a File Upload section as shown below: For finding the URL to retrieve/view the uploaded file, here are some options: 1. In some applications the URL to retrieve the uploaded file is static and doesn't change or only the file name is changed. For handling this type of configuration, options panel has `Static Location Configuration` where static URL is added into `URI Regex` field. `URI Regex` field also supports the dynamic file name by `${fileName}`. parameter, for e.g. `http:///${fileName}` -2. In some applications the URL to retrieve the uploaded file is present in the file upload request's response. For handling this type of configuration, options panel has `Dynamic Location Configuration` which has 2 parameters `Start Identifier` and `End Identifier`. These identifiers are used to locate the URL within the response. -3. In some applications the URL to retrieve the uploaded file is present in the response of a different URL which is called a preflight request. E.g. Profile picture URL is part of profile page and hence we need to parse the response of the profile page to find the URL of the profile picture. For handling this type of configuration, the options panel has `Dynamic Location Configuration` which has a `URI Regex`, `Start Identifier`, and `End Identifier`. So the File Upload add-on will invoke the URI mentioned in `URI Regex` and then parse the response using `Start Identifier` and `End Identifier`. `URI Regex` field also supports the dynamic file name by `${fileName}` +2. In some applications the URL to retrieve the uploaded file is present in the file upload request's response. For handling this type of configuration, options panel has `Parse Http Response Configuration` which has 2 parameters `Start Identifier` and `End Identifier`. These identifiers are used to locate the URL within the response. +3. In some applications the URL to retrieve the uploaded file is present in the response of a different URL which is called a preflight request. E.g. Profile picture URL is part of profile page and hence we need to parse the response of the profile page to find the URL of the profile picture. For handling this type of configuration, the options panel has `Dynamic Location Configuration` which has a `URI Regex` and `Parse Http Response Configuration` which has `Start Identifier`, and `End Identifier`. So the File Upload add-on will invoke the URI mentioned in `URI Regex` and then parse the response using `Start Identifier` and `End Identifier`. `URI Regex` field also supports the dynamic file name by `${fileName}` ### Note: This addon fires a lot of requests to the target application hence can impact the performance of the targeted application. So please run this addon in non-prod environment only. diff --git a/build.gradle.kts b/build.gradle.kts index 902d227..ec2c966 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -36,14 +36,13 @@ description = "Detect File upload requests and scan them to find related vulnera zapAddOn { addOnName.set("File upload Scan Rule") addOnStatus.set(AddOnStatus.ALPHA) - + zapVersion.set("2.11.0-SNAPSHOT") manifest { author.set("KSASAN preetkaran20@gmail.com") - notBeforeVersion.set("2.11.0") repo.set("https://github.com/SasanLabs/owasp-zap-fileupload-addon/") } } dependencies { - implementation("org.zaproxy:zap:2.11.0-SNAPSHOT") + compileOnly("org.zaproxy:zap:2.11.0-SNAPSHOT") } diff --git a/docs/images/fileupload-options-panel.png b/docs/images/fileupload-options-panel.png index 7fc48f886c88665b11935174820dacc2130eda29..758139a695f86af1b0b903d7468b71f95c4d6ea7 100644 GIT binary patch literal 215451 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
srzXG!NUcCCDU(0l!2Aj73^I*rH2C3 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 z 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 literal 202986 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ξB9? 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 diff --git a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java index 53220c2..211182e 100644 --- a/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java +++ b/src/main/java/org/sasanlabs/fileupload/FileUploadScanRule.java @@ -15,7 +15,6 @@ import java.io.IOException; import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.parosproxy.paros.core.scanner.AbstractAppParamPlugin; @@ -48,36 +47,36 @@ public class FileUploadScanRule extends AbstractAppParamPlugin { private static final String REFERENCE = FileUploadI18n.getMessage("fileupload.scanrule.refs"); private static final Logger LOGGER = LogManager.getLogger(FileUploadScanRule.class); - private AtomicInteger maxRequestCount; + private int maxRequestCount; @Override public void init() { switch (this.getAttackStrength()) { case LOW: - maxRequestCount = new AtomicInteger(30); + maxRequestCount = 30; break; case MEDIUM: - maxRequestCount = new AtomicInteger(60); + maxRequestCount = 60; break; case HIGH: - maxRequestCount = new AtomicInteger(90); + maxRequestCount = 90; break; case INSANE: - maxRequestCount = new AtomicInteger(150); + maxRequestCount = 150; break; default: - maxRequestCount = new AtomicInteger(60); + maxRequestCount = 60; break; } } @Override public boolean isStop() { - return super.isStop() || (this.maxRequestCount.get() <= 0); + return super.isStop() || (this.maxRequestCount <= 0); } public void decreaseRequestCount() { - this.maxRequestCount.getAndDecrement(); + this.maxRequestCount--; } @Override @@ -146,7 +145,8 @@ public void raiseAlert( .raise(); } - public void sendAndRecieve(HttpMessage msg) throws IOException { + @Override + public void sendAndReceive(HttpMessage msg) throws IOException { super.sendAndReceive(msg); } diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java index 45da368..dfdad2a 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java @@ -165,7 +165,7 @@ private HttpMessage uploadFile( } fileUploadScanRule.setParameters(uploadFileMsg, inputVectorBuilder.build()); try { - fileUploadScanRule.sendAndRecieve(uploadFileMsg); + fileUploadScanRule.sendAndReceive(uploadFileMsg); } catch (IOException ex) { throw new FileUploadException("Exception occurred while sending modified message", ex); } @@ -197,7 +197,7 @@ private boolean genericAttackExecutor( this.getUploadedFileHttpMessage( uploadFileMsg, fileUploadAttackExecutor.getOriginalFileName(), - fileUploadAttackExecutor.getFileUploadScanRule()::sendAndRecieve); + fileUploadAttackExecutor.getFileUploadScanRule()::sendAndReceive); if (Objects.nonNull(retrieveUploadedFile) && contentMatcher.match(retrieveUploadedFile)) { raiseAlert( diff --git a/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java b/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java index b091225..d4b8858 100644 --- a/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java +++ b/src/main/java/org/sasanlabs/fileupload/ui/FileUploadOptionsPanel.java @@ -49,8 +49,8 @@ public class FileUploadOptionsPanel extends AbstractParamPanel { // UI components private JTextField staticLocationConfigurationURIRegex; private JTextField dynamicLocationConfigurationURIRegex; - private JTextField dynamicLocationConfigurationStartIdentifier; - private JTextField dynamicLocationConfigurationEndIdentifier; + private JTextField parseResponseStartIdentifier; + private JTextField parseResponseEndIdentifier; public FileUploadOptionsPanel() { super(); @@ -139,39 +139,50 @@ private JPanel dynamicURILocatorConfiguration() { dynamicLocationConfigurationGridBagConstriants); dynamicLocationConfigurationGridBagConstriants.gridy++; dynamicLocationConfigurationGridBagConstriants.gridx = 0; + return dynamicLocationConfigurationPanel; + } - JLabel dynamicLocationConfigurationStartIdentifierLabel = + private JPanel parseResponseConfiguration() { + TitledBorder parseResponseConfigurationPanelBorder = + new TitledBorder( + FileUploadI18n.getMessage( + "fileupload.settings.urilocator.parseresponseconfiguration.title")); + JPanel parseResponseConfigurationPanel = new JPanel(); + GridBagLayout gridBagLayout = new GridBagLayout(); + parseResponseConfigurationPanel.setLayout(gridBagLayout); + parseResponseConfigurationPanel.setBorder(parseResponseConfigurationPanelBorder); + GridBagConstraints parseResponseConfigurationGridBagConstriants = getGridBagConstraints(); + + JLabel parseResponseConfigurationStartIdentifierLabel = new JLabel( FileUploadI18n.getMessage( - "fileupload.settings.urilocator.dynamiclocation.startidentifer")); - dynamicLocationConfigurationPanel.add( - dynamicLocationConfigurationStartIdentifierLabel, - dynamicLocationConfigurationGridBagConstriants); - dynamicLocationConfigurationGridBagConstriants.gridx++; - dynamicLocationConfigurationStartIdentifier = new JTextField(); + "fileupload.settings.urilocator.parseresponseconfiguration.startidentifer")); + parseResponseConfigurationPanel.add( + parseResponseConfigurationStartIdentifierLabel, + parseResponseConfigurationGridBagConstriants); + parseResponseConfigurationGridBagConstriants.gridx++; + parseResponseStartIdentifier = new JTextField(); dynamicLocationConfigurationURIRegex.setColumns(15); - dynamicLocationConfigurationPanel.add( - dynamicLocationConfigurationStartIdentifier, - dynamicLocationConfigurationGridBagConstriants); - dynamicLocationConfigurationGridBagConstriants.gridy++; - dynamicLocationConfigurationGridBagConstriants.gridx = 0; + parseResponseConfigurationPanel.add( + parseResponseStartIdentifier, parseResponseConfigurationGridBagConstriants); + parseResponseConfigurationGridBagConstriants.gridy++; + parseResponseConfigurationGridBagConstriants.gridx = 0; - JLabel dynamicLocationConfigurationEndIdentifierLabel = + JLabel parseResponseConfigurationEndIdentifierLabel = new JLabel( FileUploadI18n.getMessage( - "fileupload.settings.urilocator.dynamiclocation.endidentifer")); - dynamicLocationConfigurationPanel.add( - dynamicLocationConfigurationEndIdentifierLabel, - dynamicLocationConfigurationGridBagConstriants); - dynamicLocationConfigurationGridBagConstriants.gridx++; - dynamicLocationConfigurationEndIdentifier = new JTextField(); + "fileupload.settings.urilocator.parseresponseconfiguration.endidentifer")); + parseResponseConfigurationPanel.add( + parseResponseConfigurationEndIdentifierLabel, + parseResponseConfigurationGridBagConstriants); + parseResponseConfigurationGridBagConstriants.gridx++; + parseResponseEndIdentifier = new JTextField(); dynamicLocationConfigurationURIRegex.setColumns(15); - dynamicLocationConfigurationPanel.add( - dynamicLocationConfigurationEndIdentifier, - dynamicLocationConfigurationGridBagConstriants); - dynamicLocationConfigurationGridBagConstriants.gridy++; - dynamicLocationConfigurationGridBagConstriants.gridx = 0; - return dynamicLocationConfigurationPanel; + parseResponseConfigurationPanel.add( + parseResponseEndIdentifier, parseResponseConfigurationGridBagConstriants); + parseResponseConfigurationGridBagConstriants.gridy++; + parseResponseConfigurationGridBagConstriants.gridx = 0; + return parseResponseConfigurationPanel; } private JPanel uriLocatorConfiguration() { @@ -191,6 +202,9 @@ private JPanel uriLocatorConfiguration() { // Dynamic Configuration uriLocatorConfigurationPanel.add(this.dynamicURILocatorConfiguration(), gridBagConstraints); gridBagConstraints.gridy++; + // Parse Response Configuration + uriLocatorConfigurationPanel.add(this.parseResponseConfiguration(), gridBagConstraints); + gridBagConstraints.gridy++; return uriLocatorConfigurationPanel; } @@ -209,8 +223,8 @@ public static GridBagConstraints getGridBagConstraints() { private void resetOptionsPanel() { staticLocationConfigurationURIRegex.setText(""); dynamicLocationConfigurationURIRegex.setText(""); - dynamicLocationConfigurationStartIdentifier.setText(""); - dynamicLocationConfigurationEndIdentifier.setText(""); + parseResponseStartIdentifier.setText(""); + parseResponseEndIdentifier.setText(""); } @Override @@ -222,9 +236,9 @@ public void initParam(Object optionParams) { fileUploadConfiguration.getStaticLocationURIRegex()); dynamicLocationConfigurationURIRegex.setText( fileUploadConfiguration.getDynamicLocationURIRegex()); - dynamicLocationConfigurationStartIdentifier.setText( + parseResponseStartIdentifier.setText( fileUploadConfiguration.getDynamicLocationStartIdentifier()); - dynamicLocationConfigurationEndIdentifier.setText( + parseResponseEndIdentifier.setText( fileUploadConfiguration.getDynamicLocationEndIdentifier()); } @@ -235,9 +249,9 @@ public void validateParam(Object optionParams) throws Exception { boolean isDynamicUrlPresent = StringUtils.isNotEmpty(dynamicLocationConfigurationURIRegex.getText()); boolean isStartIdentifierPresent = - StringUtils.isNotEmpty(dynamicLocationConfigurationStartIdentifier.getText()); + StringUtils.isNotEmpty(parseResponseStartIdentifier.getText()); boolean isEndIdentifierPresent = - StringUtils.isNotEmpty(dynamicLocationConfigurationEndIdentifier.getText()); + StringUtils.isNotEmpty(parseResponseEndIdentifier.getText()); if (isStaticUrlPresent && (isDynamicUrlPresent || isStartIdentifierPresent || isEndIdentifierPresent)) { @@ -248,10 +262,15 @@ public void validateParam(Object optionParams) throws Exception { || (!isStartIdentifierPresent && isEndIdentifierPresent)) { throw new IllegalArgumentException( FileUploadI18n.getMessage( - "fileupload.settings.alert.invalid.dynamicconfigutation")); + "fileupload.settings.alert.invalid.httpresponseparseconfiguration")); } } + @Override + public String getHelpIndex() { + return "ui.dialog.options.fileupload"; + } + @Override public void saveParam(Object optionParams) throws Exception { FileUploadConfiguration fileUploadConfiguration = @@ -261,8 +280,8 @@ public void saveParam(Object optionParams) throws Exception { fileUploadConfiguration.setDynamicLocationURIRegex( this.dynamicLocationConfigurationURIRegex.getText()); fileUploadConfiguration.setDynamicLocationStartIdentifier( - this.dynamicLocationConfigurationStartIdentifier.getText()); + this.parseResponseStartIdentifier.getText()); fileUploadConfiguration.setDynamicLocationEndIdentifier( - this.dynamicLocationConfigurationEndIdentifier.getText()); + this.parseResponseEndIdentifier.getText()); } } diff --git a/src/main/javahelp/org/sasanlabs/fileupload/resources/help/contents/fileupload.html b/src/main/javahelp/org/sasanlabs/fileupload/resources/help/contents/fileupload.html new file mode 100644 index 0000000..b756f34 --- /dev/null +++ b/src/main/javahelp/org/sasanlabs/fileupload/resources/help/contents/fileupload.html @@ -0,0 +1,56 @@ + + + + +FileUpload addon + + + +

FileUpload

+This is a File Upload addon which is used to find the vulnerabilities in File Upload functionality. +

+

Why this addon is needed

+File upload is becoming a more and more essential part of any application, +where the user is able to upload their photo, their CV, or a video showcasing a +project they are working on. The application should be able to fend off bogus and +malicious files in a way to keep the application and the users safe. +Generally file upload functionality is quite complex to automate and has huge +attack surface hence there is a need to automate the process and also secure it. + +

Configuration

+File upload functionality generally has 2 endpoints, one from where file is uploaded and one +from where file is retrieved. It is necessary to know both these endpoints. +While Active Scanning an application, file upload endpoint is already known but retrieval +endpoint is not known to the scan rule hence there are configuration details specific +to the retrieval endpoint. + +

Explanation about Options Panel

+For finding the URL to retrieve/view the uploaded file, here are following options: +
    +
  1. +In some applications the URL to retrieve the uploaded file is static and doesn't change or +only the file name is changed. For handling this type of configuration, +options panel has Static Location Configuration where +static URL is added into URI Regex field. URI Regex field also supports the dynamic file name +by ${fileName}. parameter, for e.g. http:///${fileName} +
  2. +
  3. +In some applications the URL to retrieve the uploaded file is present in the file upload request's response. +For handling this type of configuration, options panel has Parse Http Response Configuration +which has 2 parameters Start Identifier and End Identifier. +These identifiers are used to locate the URL within the response. +
  4. +
  5. +In some applications the URL to retrieve the uploaded file is present in the response of a different URL which is called a +preflight request. E.g. Profile picture URL is part of profile page and +hence we need to parse the response of the profile page to find the URL of the profile picture. +For handling this type of configuration, the options panel has Dynamic Location Configuration +which has a URI Regex and Parse Http Response Configuration which has Start Identifier and End Identifier. +So the File Upload add-on will invoke the URI mentioned in URI Regex and +then parse the response using Start Identifier and End Identifier. URI Regex field also +supports the dynamic file name by ${fileName} +
  6. +
+ + + diff --git a/src/main/javahelp/org/sasanlabs/fileupload/resources/help/helpset.hs b/src/main/javahelp/org/sasanlabs/fileupload/resources/help/helpset.hs new file mode 100644 index 0000000..a8ed0e7 --- /dev/null +++ b/src/main/javahelp/org/sasanlabs/fileupload/resources/help/helpset.hs @@ -0,0 +1,41 @@ + + + + Simple Example Add-On + + + top + + + + + TOC + + org.zaproxy.zap.extension.help.ZapTocView + toc.xml + + + + Index + + javax.help.IndexView + index.xml + + + + Search + + javax.help.SearchView + + JavaHelpSearch + + + + + Favorites + + javax.help.FavoritesView + + diff --git a/src/main/javahelp/org/sasanlabs/fileupload/resources/help/index.xml b/src/main/javahelp/org/sasanlabs/fileupload/resources/help/index.xml new file mode 100644 index 0000000..09b7959 --- /dev/null +++ b/src/main/javahelp/org/sasanlabs/fileupload/resources/help/index.xml @@ -0,0 +1,9 @@ + + + + + + + diff --git a/src/main/javahelp/org/sasanlabs/fileupload/resources/help/map.jhm b/src/main/javahelp/org/sasanlabs/fileupload/resources/help/map.jhm new file mode 100644 index 0000000..b0aa20c --- /dev/null +++ b/src/main/javahelp/org/sasanlabs/fileupload/resources/help/map.jhm @@ -0,0 +1,8 @@ + + + + + + diff --git a/src/main/javahelp/org/sasanlabs/fileupload/resources/help/toc.xml b/src/main/javahelp/org/sasanlabs/fileupload/resources/help/toc.xml new file mode 100644 index 0000000..afafeea --- /dev/null +++ b/src/main/javahelp/org/sasanlabs/fileupload/resources/help/toc.xml @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties b/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties index 1b5adf9..4d1224f 100755 --- a/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties +++ b/src/main/resources/org/sasanlabs/fileupload/i18n/Messages.properties @@ -7,10 +7,11 @@ 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.dynamiclocation.startidentifer=Start Identifier -fileupload.settings.urilocator.dynamiclocation.endidentifer=End Identifier +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.dynamicconfigutation=Both dynamic start and end identifier should be present. +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. # Alert details From 9ebedbc105688c81183fd9c10886fb8d49b807db Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Wed, 11 Aug 2021 19:29:31 +0530 Subject: [PATCH 50/53] Adding URI --- build.gradle.kts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index ec2c966..4b30da8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -14,6 +14,9 @@ plugins { repositories { mavenCentral() mavenLocal() + maven { + url = uri("https://oss.sonatype.org/content/repositories/snapshots/") + } } java { @@ -36,7 +39,7 @@ description = "Detect File upload requests and scan them to find related vulnera zapAddOn { addOnName.set("File upload Scan Rule") addOnStatus.set(AddOnStatus.ALPHA) - zapVersion.set("2.11.0-SNAPSHOT") + zapVersion.set("2.11.0-SNAPSHOT") manifest { author.set("KSASAN preetkaran20@gmail.com") repo.set("https://github.com/SasanLabs/owasp-zap-fileupload-addon/") From db1bcdfe3d1e416824a1e08a08a5cafd8496c0d8 Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Wed, 11 Aug 2021 20:00:40 +0530 Subject: [PATCH 51/53] Small Fix --- build.gradle.kts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 4b30da8..f577274 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -31,7 +31,11 @@ spotless { } } -tasks.withType().configureEach { options.encoding = "utf-8" } +tasks.compileJava { + dependsOn("spotlessApply") +} + +tasks.withType().configureEach { options.encoding = "utf-8"} version = "1.0.0" description = "Detect File upload requests and scan them to find related vulnerabilities" From 640127541279e3d6f2eeca1807e09d7c260b906f Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Wed, 11 Aug 2021 20:07:35 +0530 Subject: [PATCH 52/53] Incorporating review comments --- build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index f577274..13a92b6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -43,7 +43,7 @@ description = "Detect File upload requests and scan them to find related vulnera zapAddOn { addOnName.set("File upload Scan Rule") addOnStatus.set(AddOnStatus.ALPHA) - zapVersion.set("2.11.0-SNAPSHOT") + zapVersion.set("2.11.0") manifest { author.set("KSASAN preetkaran20@gmail.com") repo.set("https://github.com/SasanLabs/owasp-zap-fileupload-addon/") @@ -51,5 +51,5 @@ zapAddOn { } dependencies { - compileOnly("org.zaproxy:zap:2.11.0-SNAPSHOT") + zap("org.zaproxy:zap:2.11.0-SNAPSHOT") } From dc31a88bb2eab892026b6189405f00dee0ad9d8f Mon Sep 17 00:00:00 2001 From: Karan Preet Singh Sasan Date: Thu, 12 Aug 2021 21:22:20 +0530 Subject: [PATCH 53/53] Small Fix --- src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java index dfdad2a..f505a02 100644 --- a/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java +++ b/src/main/java/org/sasanlabs/fileupload/attacks/AttackVector.java @@ -81,6 +81,7 @@ private HttpMessage getUploadedFileHttpMessage( uploadedFileRetrievalMsg .getRequestHeader() .setCookies(httpMsg.getRequestHeader().getHttpCookies()); + uploadedFileRetrievalMsg.setRequestBody(""); sendAndRecieveHttpMsg.accept(uploadedFileRetrievalMsg); } catch (IOException e) { throw new FileUploadException(