diff --git a/README.md b/README.md index b37f350cb..71a0f1f98 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ Development for the "next generation" of ESAPI (starting with ESAPI 3.0), will b GitHub repository at [https://github.com/ESAPI/esapi-java](https://github.com/ESAPI/esapi-java). **IMPORTANT NOTES:** -* The default branch for ESAPI legacy is the 'develop' branch (rather than the 'main' (formerly 'master') branch), where future development, bug fixes, etc. are now being done. The 'main' branch is now marked as "protected"; it reflects the latest stable ESAPI release (2.5.3.0 as of this date). Note that this change of making the 'develop' branch the default may affect any pull requests that you were intending to make. +* The default branch for ESAPI legacy is the 'develop' branch (rather than the 'main' (formerly 'master') branch), where future development, bug fixes, etc. are now being done. The 'main' branch is now marked as "protected"; it reflects the latest stable ESAPI release (2.5.3.1 as of this date). Note that this change of making the 'develop' branch the default may affect any pull requests that you were intending to make. * Also, the *minimal* baseline Java version to use ESAPI is now Java 8. (This was changed from Java 7 during the 2.4.0.0 release.) * Support was dropped for Log4J 1 during ESAPI 2.5.0.0 release. If you need it, configure it via SLF4J. See the [2.5.0.0 release notes](https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/esapi4java-core-2.5.0.0-release-notes.txt) @@ -79,7 +79,7 @@ link to the specific release notes. Starting with release 2.4.0.0, Java 8 or later is required. # Locating ESAPI Jar files -The [latest ESAPI release](https://github.com/ESAPI/esapi-java-legacy/releases/latest) is 2.5.3.0. +The [latest ESAPI release](https://github.com/ESAPI/esapi-java-legacy/releases/latest) is 2.5.3.1. All the *regular* ESAPI jars, with the exception of the ESAPI configuration jar (i.e., esapi-2.#.#.#-configuration.jar) and its associated detached GPG signature, are available from Maven Central. The ESAPI configuration diff --git a/configuration/esapi/esapi-java-logging.properties b/configuration/esapi/esapi-java-logging.properties deleted file mode 100644 index 71011acc5..000000000 --- a/configuration/esapi/esapi-java-logging.properties +++ /dev/null @@ -1,6 +0,0 @@ -handlers= java.util.logging.ConsoleHandler -.level= INFO -java.util.logging.ConsoleHandler.level = INFO -java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter -java.util.logging.SimpleFormatter.format=[%1$tF %1$tT] [%3$-7s] %5$s %n -#https://www.logicbig.com/tutorials/core-java-tutorial/logging/customizing-default-format.html \ No newline at end of file diff --git a/documentation/ESAPI-release-steps.odt b/documentation/ESAPI-release-steps.odt index 838ca0df0..4bcf16361 100644 Binary files a/documentation/ESAPI-release-steps.odt and b/documentation/ESAPI-release-steps.odt differ diff --git a/documentation/ESAPI-release-steps.pdf b/documentation/ESAPI-release-steps.pdf index 53a30565c..239dba378 100644 Binary files a/documentation/ESAPI-release-steps.pdf and b/documentation/ESAPI-release-steps.pdf differ diff --git a/documentation/esapi4java-core-2.5.4.0-release-notes.txt b/documentation/esapi4java-core-2.5.4.0-release-notes.txt new file mode 100644 index 000000000..665c1d280 --- /dev/null +++ b/documentation/esapi4java-core-2.5.4.0-release-notes.txt @@ -0,0 +1,205 @@ +Release notes for ESAPI 2.5.4.0 + Release date: 2024-05-29 + Project leaders: + -Kevin W. Wall + -Matt Seil + +Previous release: ESAPI 2.5.3.1, 2023-12-01 + + +Executive Summary: Important Things to Note for this Release +------------------------------------------------------------ +This is a patch release with a few bug fixes and dependency updates. While the AntiSamy 1.7.5 update was intended to address an XSS vulnerability (CVE-2024-23635), the ESAPI team verified that this vulnerability did not affect the default configuration of ESAPI and its strict AntiSamy policy file, antisamy-esapi.xml. (Our AntiSamy policy file has the 'preserveComments' directive disabled.) + +There is one important issue that was patched (GitHub issue # 839) that has a side-effect. In particular, if you have ESAPI configured to use JUL (i.e., Java Util Logging) as your default logger (i.e., you have ESAPI.Logger set to 'org.owasp.esapi.logging.java.JavaLogFactory', then you MUST delete your 'esapi-java-logging.properties' to set some of the JUL properties. This file was conflicting with the other uses of JUL not used through ESAPI. If you start ESAPI 2.5.4.0 and this file is found as a resource, then a ConfigurationException will be thrown and the exception message will direct you to our GitHub wiki page, https://github.com/ESAPI/esapi-java-legacy/wiki/Configuring-the-JavaLogFactory + +Notes if you are not updating from the immediate previous release. release 2.5.3.1: + * You need to read through the series of release notes FIRST, going in order. + * For example, if you were updating from an older ESAPI release (say, 2.3.0.0), you should go back and FIRST read all the subsequent release notes in turn. For instance, if you are currently on release 2.3.0.0 and upgrading to (say) release 2.x.y.z, you should MINIMALLY read the sections "Changes Requiring Special Attention" in each of the subsequent release notes. So, going from release 2.3.0.0 to 2.x.y.z, you should in turn, read: + + esapi4java-core-2.4.0.0-release-notes.txt + esapi4java-core-2.5.0.0-release-notes.txt + esapi4java-core-2.5.1.0-release-notes.txt + esapi4java-core-2.5.2.0-release-notes.txt + ...etc., up through the current set of release notes... + esapi4java-core-2.x.y.z-release-notes.txt + +in that order. YOU HAVE BEEN WARNED!!! (These release notes are too large to put all this in a given document; very few read them thoroughly as it is.) + +If your SCA tool is reporting any CVE from a direct or transitive dependency in ESAPI, before reporting it as an GitHub issue, please make sure that you review the vulnerability analysis written up in https://github.com/ESAPI/esapi-java-legacy/blob/develop/Vulnerability-Summary.md. Please email us or contact us in our GitHub Discussions page if you have questions about this. See also the SECURITY.md file to report any security issues with ESAPI. + +You are encouraged to review the vulnerability analysis written up in https://github.com/ESAPI/esapi-java-legacy/blob/develop/Vulnerability-Summary.md and email us or contact us in our GitHub Discussions page if you have questions. + + +================================================================================================================= + +Basic ESAPI facts +----------------- + +ESAPI 2.5.3.1 release: + 207 Java source files + 4293 JUnit tests in 131 Java source files (0 failures, 0 errors, 0 tests skipped) + +ESAPI 2.5.4.0 release: + 207 Java source files + 4297 JUnit tests in 131 Java source files (0 failures, 0 errors, 0 tests skipped) + +8 GitHub Issues closed in this release, including those we've decided not to fix (marked 'wontfix' and 'falsepositive'). +(Reference: https://github.com/ESAPI/esapi-java-legacy/issues?q=is%3Aissue+state%3Aclosed+updated%3A%3E%3D2023-12-01) + +Issue # GitHub Issue Title +---------------------------------------------------------------------------------------------- +824 DefaultEncoder / getCanonicalizedURI returns mix encoding for HTML special characters +826 Fix Encoder.getCanonicalizedURI(URI) for the test case of a double-ampersand in the HTML Query +827 HTMLEntityCodec Mysteriously decodes &or +831 java.io.FileNotFoundException Error in Logs When ESAPI.properties and validation.properties are in resources. and the application is up ,features are not working. +832 easpi .properties and validation properties are present but still it is throwing error and the application is failing do you have any solution for this +835 Validator.isValidSafeHTML() is vulnerable as per CVE-2023-4780 +837 Validation does not work with esapi jakarta jar +839 ConcurrentModificationException + + +----------------------------------------------------------------------------- + + Changes Requiring Special Attention + +----------------------------------------------------------------------------- +Important Note affecting ESAPI 2.5.4.0 and later: +* If you are using JUL for ESAPI logging, you will need to delete esapi-java-logging.properties file so it is not found as a resource stream. Failure to do so will result in a ConfigurationException being thrown. For details, see our GitHub wiki page, https://github.com/ESAPI/esapi-java-legacy/wiki/Configuring-the-JavaLogFactory + +Important JDK Support Announcement +* ESAPI 2.3.0.0 was the last Java release to support Java 7. ESAPI 2.4.0 requires using Java 8 or later. See the ESAPI 2.4.0.0 release notes (https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/esapi4java-core-2.4.0.0-release-notes.txt) for details as to the reason. + - This means if your project requires Java 7, you must use ESAPI 2.3.0.0 or earlier. + +Important ESAPI Logging Changes + +* Since ESAPI 2.5.0.0, support for logging directly via Log4J 1 has been removed. (This was two years after it haveing first been deprecated.) Thus, you only choice of ESAPI logging are + - java.util.logging (JUL), which as been the default since ESAPI 2.2.1.0. + * Set ESAPI.Logger=org.owasp.esapi.logging.java.JavaLogFactory in your ESAPI.properties file. + - SLF4J (with your choice of supported SLF4J logging implemmentation) + * Set ESAPI.Logger=org.owasp.esapi.logging.slf4j.Slf4JLogFactory in your ESAPI.properties file. +* Logger configuration notes - If you are migrating from prior to ESAPI 2.2.1.1, you will need to update your ESAPI.properties file as logging-related configuration as per the ESAPI 2.2.1.1 release notes, which may be found at: + https://github.com/ESAPI/esapi-java-legacy/blob/develop/documentation/esapi4java-core-2.2.1.1-release-notes.txt#L39-L78 + +If you use ESAPI 2.5.0.0 or later, you will get an ClassNotFoundException as the root cause if you still have your ESAPI.Logger property set to use Log4J because the org.owasp.esapi.logger.log4j.Log4JFactory class has been completely removed from the ESAPI jar. If you are dead set on continuing to use Log4J 1, you ought to be able to do so via SLF4J. The set up for Log4J 1 (which has not be tested), should be similar to configure ESAPI to use SLF4J with Log4J 2 as described here: + https://github.com/ESAPI/esapi-java-legacy/wiki/Using-ESAPI-with-SLF4J#slf4j-using-log4j-2x + +----------------------------------------------------------------------------- + + Remaining Known Issues / Problems + +----------------------------------------------------------------------------- +None known, other than the remaining open issues on GitHub. + +----------------------------------------------------------------------------- + + Other changes in this release, some of which not tracked via GitHub issues + +----------------------------------------------------------------------------- + +* Minor updates to README.md file with respect to version information. + +----------------------------------------------------------------------------- + +Developer Activity Report (Changes between release 2.5.3.1 and 2.5.4.0, i.e., between 2023-12-01 and 2024-05-29) +Generated manually (this time) -- all errors are the fault of kwwall and his inability to do simple arithmetic. + +Developer Total Total Number # Merged +(GitHub ID) commits of Files Changed PRs +======================================================== +xeno6696 5 4 1 +jeremiahjstacey 2 4 1 +dependabot 1 1 1 +mpreziuso 1 2 1 +kwwall 11 6 0 (direct merge) +======================================================== + Total PRs: 4 + +----------------------------------------------------------------------------- + +CHANGELOG: Create your own. May I suggest: + + git log --stat --since=2023-12-01 --reverse --pretty=medium + + which will show all the commits since just after the previous (2.5.3.1) release. + + Alternately, you can download the most recent ESAPI source and run + + mvn site + + which will create a CHANGELOG file named 'target/site/changelog.html' + + +----------------------------------------------------------------------------- + +Direct and Transitive Runtime and Test Dependencies: + + $ mvn -B dependency:tree + ... + [INFO] --- maven-dependency-plugin:3.6.1:tree (default-cli) @ esapi --- + [INFO] org.owasp.esapi:esapi:jar:2.5.4.0 + [INFO] +- javax.servlet:javax.servlet-api:jar:3.1.0:provided + [INFO] +- javax.servlet.jsp:javax.servlet.jsp-api:jar:2.3.3:provided + [INFO] +- xom:xom:jar:1.3.9:compile + [INFO] +- commons-beanutils:commons-beanutils:jar:1.9.4:compile + [INFO] | +- commons-logging:commons-logging:jar:1.2:compile + [INFO] | \- commons-collections:commons-collections:jar:3.2.2:compile + [INFO] +- commons-configuration:commons-configuration:jar:1.10:compile + [INFO] +- commons-lang:commons-lang:jar:2.6:compile + [INFO] +- commons-fileupload:commons-fileupload:jar:1.5:compile + [INFO] +- org.apache.commons:commons-collections4:jar:4.5.0-M1:compile + [INFO] +- org.apache-extras.beanshell:bsh:jar:2.0b6:compile + [INFO] +- org.owasp.antisamy:antisamy:jar:1.7.5:compile + [INFO] | +- org.apache.httpcomponents.client5:httpclient5:jar:5.3.1:compile + [INFO] | | \- org.apache.httpcomponents.core5:httpcore5-h2:jar:5.2.4:compile + [INFO] | +- org.apache.httpcomponents.core5:httpcore5:jar:5.2.4:compile + [INFO] | +- org.apache.xmlgraphics:batik-css:jar:1.17:compile + [INFO] | | +- org.apache.xmlgraphics:batik-shared-resources:jar:1.17:compile + [INFO] | | +- org.apache.xmlgraphics:batik-util:jar:1.17:compile + [INFO] | | | +- org.apache.xmlgraphics:batik-constants:jar:1.17:compile + [INFO] | | | \- org.apache.xmlgraphics:batik-i18n:jar:1.17:compile + [INFO] | | \- org.apache.xmlgraphics:xmlgraphics-commons:jar:2.9:compile + [INFO] | +- org.htmlunit:neko-htmlunit:jar:3.11.1:compile + [INFO] | +- xerces:xercesImpl:jar:2.12.2:compile + [INFO] | \- xml-apis:xml-apis-ext:jar:1.3.04:compile + [INFO] +- org.slf4j:slf4j-api:jar:2.0.13:compile + [INFO] +- xml-apis:xml-apis:jar:1.4.01:compile + [INFO] +- commons-io:commons-io:jar:2.15.1:compile + [INFO] +- com.github.spotbugs:spotbugs-annotations:jar:4.8.5:compile + [INFO] | \- com.google.code.findbugs:jsr305:jar:3.0.2:compile + [INFO] +- commons-codec:commons-codec:jar:1.17.0:test + [INFO] +- junit:junit:jar:4.13.2:test + [INFO] +- org.bouncycastle:bcprov-jdk15on:jar:1.70:test + [INFO] +- org.hamcrest:hamcrest-core:jar:2.2:test + [INFO] | \- org.hamcrest:hamcrest:jar:2.2:test + [INFO] +- org.powermock:powermock-api-mockito2:jar:2.0.9:test + [INFO] | \- org.powermock:powermock-api-support:jar:2.0.9:test + [INFO] +- org.mockito:mockito-core:jar:3.12.4:test + [INFO] | +- net.bytebuddy:byte-buddy:jar:1.11.13:test + [INFO] | +- net.bytebuddy:byte-buddy-agent:jar:1.11.13:test + [INFO] | \- org.objenesis:objenesis:jar:3.2:test + [INFO] +- org.powermock:powermock-core:jar:2.0.9:test + [INFO] | \- org.javassist:javassist:jar:3.27.0-GA:test + [INFO] +- org.powermock:powermock-module-junit4:jar:2.0.9:test + [INFO] | \- org.powermock:powermock-module-junit4-common:jar:2.0.9:test + [INFO] +- org.powermock:powermock-reflect:jar:2.0.9:test + [INFO] \- org.openjdk.jmh:jmh-core:jar:1.37:test + [INFO] +- net.sf.jopt-simple:jopt-simple:jar:5.0.4:test + [INFO] \- org.apache.commons:commons-math3:jar:3.6.1:test + [INFO] ------------------------------------------------------------------------ + [INFO] BUILD SUCCESS + [INFO] ------------------------------------------------------------------------ + [INFO] Total time: 0.903 s + [INFO] Finished at: 2024-05-29T18:31:30-04:00 + [INFO] ------------------------------------------------------------------------ + +----------------------------------------------------------------------------- + +Acknowledgments: + A special hat tip to Arshan Dabirsiaghis, original creator of AntiSamy and the creator of the antisamy-esapi.xml file, the ultrastrict AntiSamy policy used by ESAPI. That avoided a vulnerability that affected AntiSamy itself, so kudos to that foresite. + A shutout to Michele Preziuso for the PR that updated AntiSamy, added a test, and avoided the convergence issue that resulted in me having to reject the Snyk and Dependabot PRs. I appreciate you saving me having to do the work. + And special kudos to Jerry Devis for one of the best bug reports (GitHub issue #839) that I've seen since I began working on ESAPI in 2009. I hope your bug report can be an example to all. Excellent work. + + Lastly, our usual special thanks to the ESAPI community from the ESAPI project co-leaders: + Kevin W. Wall (kwwall) <== The irresponsible party for these release notes! +Matt Seil (xeno6696) diff --git a/pom.xml b/pom.xml index 0ff01bd4e..49131449d 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.owasp.esapi esapi - 2.5.3.1 + 2.5.4.0 jar @@ -132,16 +132,16 @@ UTF-8 1.37 2.0.0-M3 - 2.0.0-M8 + 2.0.0-M9 2.0.9 - 4.8.2 - 4.8.2.0 - 3.2.2 + 4.8.5 + 4.8.5.0 + 3.2.5 1.8 - 2023-11-24 00:00:00 + 2023-12-01 00:00:00 @@ -233,7 +233,7 @@ org.apache.commons commons-collections4 - 4.4 + 4.5.0-M1 org.apache-extras.beanshell @@ -243,19 +243,24 @@ org.owasp.antisamy antisamy - 1.7.4 + 1.7.5 org.slf4j slf4j-api + + + commons-logging + commons-logging + org.slf4j slf4j-api - 2.0.6 + 2.0.13 xml-apis @@ -281,7 +286,7 @@ --> commons-io commons-io - 2.14.0 + 2.15.1 @@ -296,7 +301,7 @@ commons-codec commons-codec - 1.16.0 + 1.17.0 test @@ -413,7 +418,7 @@ org.apache.maven.plugins maven-assembly-plugin - 3.6.0 + 3.7.1 org.apache.maven.plugins @@ -441,7 +446,7 @@ org.cyclonedx cyclonedx-maven-plugin - 2.7.10 + 2.8.0 package @@ -489,7 +494,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.11.0 + 3.13.0 ${project.java.target} ${project.java.target} @@ -523,7 +528,7 @@ org.apache.maven.plugins maven-deploy-plugin - 3.1.1 + 3.1.2 @@ -543,7 +548,7 @@ org.codehaus.mojo extra-enforcer-rules - 1.7.0 + 1.8.0 org.codehaus.mojo @@ -559,8 +564,8 @@ - [3.3.9,) - Building ESAPI 2.x now requires Maven 3.3.9 or later. + [3.6.3,) + Building ESAPI 2.x now requires Maven 3.6.3 or later. @@ -612,7 +617,7 @@ org.apache.maven.plugins maven-gpg-plugin - 3.1.0 + 3.2.4 sign-artifacts @@ -625,13 +630,13 @@ org.apache.maven.plugins maven-install-plugin - 3.1.1 + 3.1.2 org.apache.maven.plugins maven-jar-plugin - 3.3.0 + 3.4.1 @@ -645,7 +650,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.6.2 + 3.6.3 8 none @@ -663,13 +668,13 @@ org.apache.maven.plugins maven-jxr-plugin - 3.3.1 + 3.3.2 org.apache.maven.plugins maven-pmd-plugin - 3.21.2 + 3.22.0 @@ -689,7 +694,7 @@ The skin is referenced in src/site/site.xml. --> org.apache.maven.plugins maven-site-plugin - 4.0.0-M12 + 4.0.0-M14 org.apache.maven.skins @@ -702,7 +707,7 @@ org.apache.maven.plugins maven-source-plugin - 3.3.0 + 3.3.1 attach-sources @@ -750,7 +755,7 @@ org.owasp dependency-check-maven - 9.0.0 + 9.2.0 ${env.NVD_API_KEY} 1.0 diff --git a/scripts/vars.2.5.4.0 b/scripts/vars.2.5.4.0 new file mode 100644 index 000000000..a5423489c --- /dev/null +++ b/scripts/vars.2.5.4.0 @@ -0,0 +1,14 @@ +# Do NOT edit this file directly. It will be created by the new createVarsFile.sh script, +# which should be run prior to the newReleaseNotes.sh script. + +# ESAPI (new / current) version +VERSION=2.5.4.0 + +# Previous ESAPI version +PREV_VERSION=2.5.3.1 + +# Release date of current version in yyyy-mm-dd format +YYYY_MM_DD_RELEASE_DATE=2024-05-29 + +# Previous ESAPI release date in same format +PREV_RELEASE_DATE=2023-12-01 diff --git a/src/main/java/org/owasp/esapi/codecs/LegacyHTMLEntityCodec.java b/src/main/java/org/owasp/esapi/codecs/LegacyHTMLEntityCodec.java index ce66ba256..240cc2ca7 100644 --- a/src/main/java/org/owasp/esapi/codecs/LegacyHTMLEntityCodec.java +++ b/src/main/java/org/owasp/esapi/codecs/LegacyHTMLEntityCodec.java @@ -1,5 +1,5 @@ /** - * OWASP Enterprise Security API (ESAPI) + * OWASP Enterprise Security API (ESAPI) * * This file is part of the Open Web Application Security Project (OWASP) * Enterprise Security API (ESAPI) project. For details, please see diff --git a/src/main/java/org/owasp/esapi/logging/java/JavaLogFactory.java b/src/main/java/org/owasp/esapi/logging/java/JavaLogFactory.java index 47502e16c..9ebd52d92 100644 --- a/src/main/java/org/owasp/esapi/logging/java/JavaLogFactory.java +++ b/src/main/java/org/owasp/esapi/logging/java/JavaLogFactory.java @@ -14,18 +14,23 @@ */ package org.owasp.esapi.logging.java; +import static org.owasp.esapi.PropNames.APPLICATION_NAME; +import static org.owasp.esapi.PropNames.LOG_APPLICATION_NAME; +import static org.owasp.esapi.PropNames.LOG_CLIENT_INFO; +import static org.owasp.esapi.PropNames.LOG_ENCODING_REQUIRED; +import static org.owasp.esapi.PropNames.LOG_SERVER_IP; +import static org.owasp.esapi.PropNames.LOG_USER_INFO; + import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.logging.LogManager; import org.owasp.esapi.ESAPI; import org.owasp.esapi.LogFactory; import org.owasp.esapi.Logger; -import org.owasp.esapi.PropNames; import org.owasp.esapi.codecs.HTMLEntityCodec; import org.owasp.esapi.errors.ConfigurationException; import org.owasp.esapi.logging.appender.LogAppender; @@ -35,13 +40,6 @@ import org.owasp.esapi.logging.cleaning.LogScrubber; import org.owasp.esapi.logging.cleaning.NewlineLogScrubber; -import static org.owasp.esapi.PropNames.LOG_ENCODING_REQUIRED; -import static org.owasp.esapi.PropNames.LOG_USER_INFO; -import static org.owasp.esapi.PropNames.LOG_CLIENT_INFO; -import static org.owasp.esapi.PropNames.LOG_APPLICATION_NAME; -import static org.owasp.esapi.PropNames.APPLICATION_NAME; -import static org.owasp.esapi.PropNames.LOG_SERVER_IP; - /** * LogFactory implementation which creates JAVA supporting Loggers. *

@@ -58,6 +56,8 @@ * */ public class JavaLogFactory implements LogFactory { + /**Consistent message offered as a part of the ConfigurationException which is thrown if esapi-java-logging.properties is found on the path. */ + private static final String PROPERTY_CONFIG_MSG = "esapi-java-logging.properties is no longer supported. See https://github.com/ESAPI/esapi-java-legacy/wiki/Configuring-the-JavaLogFactory for information on corrective actions."; /** Immune characters for the codec log scrubber for JAVA context.*/ private static final char[] IMMUNE_JAVA_HTML = {',', '.', '-', '_', ' ' }; /** Codec being used to clean messages for logging.*/ @@ -93,43 +93,24 @@ public class JavaLogFactory implements LogFactory { LOG_BRIDGE = new JavaLogBridgeImpl(JAVA_LOG_APPENDER, JAVA_LOG_SCRUBBER, levelLookup); - readLoggerConfiguration(LogManager.getLogManager()); - } - - /** - * Attempts to load the expected property file path into the provided LogManager reference. - * @param logManager LogManager which is being configured. - */ - /*package*/ static void readLoggerConfiguration(LogManager logManager) { - if (System.getProperties().keySet().stream().anyMatch(propKey -> - "java.util.logging.config.class".equals(propKey) || "java.util.logging.config.file".equals(propKey))) { - // LogManager has external configuration. Do not load ESAPI defaults. - // See javadoc for the LogManager class for more information on properties. - boolean isStartupSysoutDisabled = Boolean.valueOf(System.getProperty(PropNames.DISCARD_LOGSPECIAL, Boolean.FALSE.toString())); - if (!isStartupSysoutDisabled) { - String logManagerPreferredMsg = String.format("[ESAPI-STARTUP] ESAPI JavaLogFactory Configuration will not be applied. " - + "java.util.LogManager configuration Detected. " - + "{\"java.util.logging.config.class\":\"%s\",\"java.util.logging.config.file\":\"%s\"}", - System.getProperty("java.util.logging.config.class"), System.getProperty("java.util.logging.config.file")); - - System.out.println(logManagerPreferredMsg); - // ::SAMPLE OUTPUT:: - //[ESAPI-STARTUP] ESAPI JavaLogFactory Configuration will not be applied. java.util.LogManager configuration Detected.{"java.util.logging.config.class":"some.defined.value","java.util.logging.config.file":"null"} - } - - return; - } /* - * This will load the logging properties file to control the format of the output for Java logs. + * esapi-java-logging.properties file may lead to confusing logging behavior + * by overriding desired configurations provided through Java's LogManager class. + * + * Verify the file is not present and fail if found to enforce understanding of + * the configuration method. */ try (InputStream stream = JavaLogFactory.class.getClassLoader(). getResourceAsStream("esapi-java-logging.properties")) { - if (stream == null) { - throw new ConfigurationException("Unable to locate resource: esapi-java-logging.properties"); + if (stream != null) { + throw new ConfigurationException(PROPERTY_CONFIG_MSG); } - logManager.readConfiguration(stream); + } catch (IOException ioe) { - throw new ConfigurationException("Failed to load esapi-java-logging.properties.", ioe); + // This is a little strange, I know. + // If the IOException is thrown, then the file actually exists but is malformatted or has some other issue. + // The file should not exist at all, so use the same message as above but include the original exception in the log as well. + throw new ConfigurationException(PROPERTY_CONFIG_MSG, ioe); } } diff --git a/src/main/java/org/owasp/esapi/reference/DefaultEncoder.java b/src/main/java/org/owasp/esapi/reference/DefaultEncoder.java index a754064bc..348cb4a4d 100644 --- a/src/main/java/org/owasp/esapi/reference/DefaultEncoder.java +++ b/src/main/java/org/owasp/esapi/reference/DefaultEncoder.java @@ -520,6 +520,9 @@ public byte[] decodeFromBase64(String input) throws IOException { * This will extract each piece of a URI according to parse zone as specified in RFC-3986 section 3, * and it will construct a canonicalized String representing a version of the URI that is safe to * run regex against. + * + * NOTE: This method will obey the ESAPI.properties configurations for allowing + * Mixed and Multiple Encoding URLs. * * @param dirtyUri * @return Canonicalized URI string. @@ -548,7 +551,6 @@ public String getCanonicalizedURI(URI dirtyUri) throws IntrusionException{ parseMap.put(UriSegment.SCHEME, dirtyUri.getScheme()); //authority = [ userinfo "@" ] host [ ":" port ] parseMap.put(UriSegment.AUTHORITY, dirtyUri.getRawAuthority()); - parseMap.put(UriSegment.SCHEMSPECIFICPART, dirtyUri.getRawSchemeSpecificPart()); parseMap.put(UriSegment.HOST, dirtyUri.getHost()); //if port is undefined, it will return -1 Integer port = new Integer(dirtyUri.getPort()); @@ -557,9 +559,6 @@ public String getCanonicalizedURI(URI dirtyUri) throws IntrusionException{ parseMap.put(UriSegment.QUERY, dirtyUri.getRawQuery()); parseMap.put(UriSegment.FRAGMENT, dirtyUri.getRawFragment()); - //Now we canonicalize each part and build our string. - StringBuilder sb = new StringBuilder(); - //Replace all the items in the map with canonicalized versions. Set set = parseMap.keySet(); @@ -568,8 +567,7 @@ public String getCanonicalizedURI(URI dirtyUri) throws IntrusionException{ boolean allowMixed = sg.getBooleanProp("Encoder.AllowMixedEncoding"); boolean allowMultiple = sg.getBooleanProp("Encoder.AllowMultipleEncoding"); for(UriSegment seg: set){ - String value = canonicalize(parseMap.get(seg), allowMultiple, allowMixed); - value = value == null ? "" : value; + String value = ""; //In the case of a uri query, we need to break up and canonicalize the internal parts of the query. if(seg == UriSegment.QUERY && null != parseMap.get(seg)){ StringBuilder qBuilder = new StringBuilder(); @@ -597,6 +595,10 @@ public String getCanonicalizedURI(URI dirtyUri) throws IntrusionException{ } catch (UnsupportedEncodingException e) { logger.debug(Logger.EVENT_FAILURE, "decoding error when parsing [" + dirtyUri.toString() + "]"); } + } else { + String extractedInput = parseMap.get(seg); + value = canonicalize(extractedInput, allowMultiple, allowMixed); + value = value == null ? "" : value; } //Check if the port is -1, if it is, omit it from the output. if(seg == UriSegment.PORT){ @@ -618,11 +620,16 @@ public String getCanonicalizedURI(URI dirtyUri) throws IntrusionException{ */ protected String buildUrl(Map parseMap){ StringBuilder sb = new StringBuilder(); - sb.append(parseMap.get(UriSegment.SCHEME)) - .append("://") + boolean schemePresent = parseMap.get(UriSegment.SCHEME).equals("") ? false : true; + + if(schemePresent) { + sb.append(parseMap.get(UriSegment.SCHEME)) + .append("://"); + } + //can't use SCHEMESPECIFICPART for this, because we need to canonicalize all the parts of the query. //USERINFO is also deprecated. So we technically have more than we need. - .append(parseMap.get(UriSegment.AUTHORITY) == null || parseMap.get(UriSegment.AUTHORITY).equals("") ? "" : parseMap.get(UriSegment.AUTHORITY)) + sb.append(parseMap.get(UriSegment.AUTHORITY) == null || parseMap.get(UriSegment.AUTHORITY).equals("") ? "" : parseMap.get(UriSegment.AUTHORITY)) .append(parseMap.get(UriSegment.PATH) == null || parseMap.get(UriSegment.PATH).equals("") ? "" : parseMap.get(UriSegment.PATH)) .append(parseMap.get(UriSegment.QUERY) == null || parseMap.get(UriSegment.QUERY).equals("") ? "" : "?" + parseMap.get(UriSegment.QUERY)) diff --git a/src/test/java/org/owasp/esapi/codecs/HTMLEntityCodecTest.java b/src/test/java/org/owasp/esapi/codecs/HTMLEntityCodecTest.java index 070e28a26..869871c1c 100644 --- a/src/test/java/org/owasp/esapi/codecs/HTMLEntityCodecTest.java +++ b/src/test/java/org/owasp/esapi/codecs/HTMLEntityCodecTest.java @@ -2,6 +2,7 @@ import static org.junit.Assert.assertEquals; +import org.junit.Ignore; import org.junit.Test; public class HTMLEntityCodecTest { diff --git a/src/test/java/org/owasp/esapi/logging/java/JavaLogFactoryTest.java b/src/test/java/org/owasp/esapi/logging/java/JavaLogFactoryTest.java index 523660304..201a3c42a 100644 --- a/src/test/java/org/owasp/esapi/logging/java/JavaLogFactoryTest.java +++ b/src/test/java/org/owasp/esapi/logging/java/JavaLogFactoryTest.java @@ -14,12 +14,8 @@ */ package org.owasp.esapi.logging.java; -import java.io.IOException; -import java.io.InputStream; import java.util.List; -import java.util.logging.LogManager; -import org.hamcrest.CustomMatcher; import org.junit.Assert; import org.junit.Rule; import org.junit.Test; @@ -28,7 +24,6 @@ import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.owasp.esapi.Logger; -import org.owasp.esapi.errors.ConfigurationException; import org.owasp.esapi.logging.appender.LogAppender; import org.owasp.esapi.logging.appender.LogPrefixAppender; import org.owasp.esapi.logging.cleaning.CodecLogScrubber; @@ -48,83 +43,6 @@ public class JavaLogFactoryTest { @Rule public ExpectedException exEx = ExpectedException.none(); - @Test - public void testLogManagerConfigurationAsClass() throws Exception { - String propKey = "java.util.logging.config.class"; - //If defined, grab the value; otherwise, set to a known value to allow for prop to be cleared. - String sysDefault = System.getProperties().stringPropertyNames().contains(propKey) ? System.getProperty(propKey) : testName.getMethodName(); - - System.setProperty(propKey, "some.defined.value"); - LogManager testLogManager = new LogManager() { - @Override - public void readConfiguration(InputStream ins) throws IOException, SecurityException { - throw new IOException(testName.getMethodName()); - } - }; - - try { - // This would throw an IOException if the LogManager was not being respected since no esapi-java-logging file is specified - JavaLogFactory.readLoggerConfiguration(testLogManager); - } finally { - //Restore original prop values - if (testName.getMethodName().equals(sysDefault)) - System.clearProperty(propKey); - else { - System.setProperty(propKey, sysDefault); - } - } - } - - @Test - public void testLogManagerConfigurationAsFile() throws Exception { - String propKey = "java.util.logging.config.file"; - //If defined, grab the value; otherwise, set to a known value to allow for prop to be cleared. - String sysDefault = System.getProperties().stringPropertyNames().contains(propKey) ? System.getProperty(propKey) : testName.getMethodName(); - - System.setProperty(propKey, "some.defined.value"); - LogManager testLogManager = new LogManager() { - @Override - public void readConfiguration(InputStream ins) throws IOException, SecurityException { - throw new IOException(testName.getMethodName()); - } - }; - - try { - // This would throw an IOException if the LogManager was not being respected since no esapi-java-logging file is specified - JavaLogFactory.readLoggerConfiguration(testLogManager); - } finally { - //Restore original prop values - if (testName.getMethodName().equals(sysDefault)) { - System.clearProperty(propKey); - } else { - System.setProperty(propKey, sysDefault); - } - } - } - @Test - public void testConfigurationExceptionOnMissingConfiguration() throws Exception { - final IOException originException = new IOException(testName.getMethodName()); - - LogManager testLogManager = new LogManager() { - @Override - public void readConfiguration(InputStream ins) throws IOException, SecurityException { - throw originException; - } - }; - - exEx.expectMessage("Failed to load esapi-java-logging.properties"); - exEx.expect(ConfigurationException.class); - - exEx.expectCause(new CustomMatcher("Check for IOException") { - @Override - public boolean matches(Object item) { - return item instanceof IOException; - } - }); - - JavaLogFactory.readLoggerConfiguration(testLogManager); - } - @Test public void testCreateLoggerByString() { Logger logger = new JavaLogFactory().getLogger("test"); diff --git a/src/test/java/org/owasp/esapi/reference/EncoderTest.java b/src/test/java/org/owasp/esapi/reference/EncoderTest.java index 963939626..51f72d063 100644 --- a/src/test/java/org/owasp/esapi/reference/EncoderTest.java +++ b/src/test/java/org/owasp/esapi/reference/EncoderTest.java @@ -15,25 +15,21 @@ */ package org.owasp.esapi.reference; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URI; -import java.util.List; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import java.util.List; +import org.junit.Ignore; import org.owasp.esapi.ESAPI; import org.owasp.esapi.Encoder; import org.owasp.esapi.EncoderConstants; -import org.owasp.esapi.codecs.CSSCodec; +import org.owasp.esapi.SecurityConfiguration; +import org.owasp.esapi.SecurityConfigurationWrapper; import org.owasp.esapi.codecs.Codec; import org.owasp.esapi.codecs.HTMLEntityCodec; import org.owasp.esapi.codecs.MySQLCodec; @@ -45,8 +41,7 @@ import org.owasp.esapi.errors.EncodingException; import org.owasp.esapi.errors.IntrusionException; import org.owasp.esapi.Randomizer; -import org.owasp.esapi.SecurityConfiguration; -import org.owasp.esapi.SecurityConfigurationWrapper; + import junit.framework.Test; import junit.framework.TestCase; @@ -747,6 +742,7 @@ public void testDecodeFromURL() throws Exception { fail(); } try { + //FIXME: Rewrite this to use expected Exceptions. instance.decodeFromURL( "%3xridiculous" ); fail(); } catch( Exception e ) { @@ -985,6 +981,50 @@ public void testGetCanonicalizedUri() throws Exception { assertEquals(expectedUri, e.getCanonicalizedURI(uri)); } + + public void testGetCanonicalizedUriWithAnHTMLEntityCollision() throws Exception { + System.out.println("GetCanonicalizedUriWithAnHTMLEntityCollision"); + Encoder e = ESAPI.encoder(); + + String expectedUri = "http://palpatine@foobar.com/path_to/resource?foo=bar¶1=test"; + //Please note that section 3.2.1 of RFC-3986 explicitly states not to encode + //password information as in http://palpatine:password@foo.com, and this will + //not appear in the userinfo field. + String input = "http://palpatine@foobar.com/path_to/resource?foo=bar¶1=test"; + URI uri = new URI(input); + System.out.println(uri.toString()); + assertEquals(expectedUri, e.getCanonicalizedURI(uri)); + + } + + @org.junit.Ignore("Pre-check in unit test for issue #826") + public void Issue826GetCanonicalizedUriWithMultipleEncoding() throws Exception { + System.out.println("GetCanonicalizedUriWithAnHTMLEntityCollision"); + Encoder e = ESAPI.encoder(); + String expectedUri = "http://palpatine@foobar.com/path_to/resource?foo=bar¶1=&amp;amp;test"; + //Please note that section 3.2.1 of RFC-3986 explicitly states not to encode + //password information as in http://palpatine:password@foo.com, and this will + //not appear in the userinfo field. + String input = "http://palpatine@foobar.com/path_to/resource?foo=bar¶1=&amp;amp;test"; + URI uri = new URI(input); + System.out.println(uri.toString()); + assertEquals(expectedUri, e.getCanonicalizedURI(uri)); + + } + public void testGetCanonicalizedUriWithMultQueryParams() throws Exception { + System.out.println("getCanonicalizedUri"); + Encoder e = ESAPI.encoder(); + + String expectedUri = "http://palpatine@foo bar.com/path_to/resource?foo=bar&bar=foo#frag"; + //Please note that section 3.2.1 of RFC-3986 explicitly states not to encode + //password information as in http://palpatine:password@foo.com, and this will + //not appear in the userinfo field. + String input = "http://palpatine@foo%20bar.com/path_to/resource?foo=bar&bar=foo#frag"; + URI uri = new URI(input); + System.out.println(uri.toString()); + assertEquals(expectedUri, e.getCanonicalizedURI(uri)); + + } public void testGetCanonicalizedUriPiazza() throws Exception { System.out.println("getCanonicalizedUriPiazza"); @@ -1000,6 +1040,41 @@ public void testGetCanonicalizedUriPiazza() throws Exception { assertEquals(expectedUri, e.getCanonicalizedURI(uri)); } + + public void testIssue824() throws Exception { + System.out.println("getCanonicalizedUriPiazza"); + Encoder e = ESAPI.encoder(); + + String expectedUri = "/webapp/ux/home?d=1705914006565&status=login&ticket=1705914090394_HzJpTROVfhW-JhRW0OqDbHu7tWXXlgrKSUmOzIMsZNCcUIiYGMXX_Q==&newsess=false&roleid=DP010101/0007&origin=ourprogram"; + //Please note that section 3.2.1 of RFC-3986 explicitly states not to encode + //password information as in http://palpatine:password@foo.com, and this will + //not appear in the userinfo field. + String input = "/webapp/ux/home?d=1705914006565&status=login&ticket=1705914090394_HzJpTROVfhW-JhRW0OqDbHu7tWXXlgrKSUmOzIMsZNCcUIiYGMXX_Q%3D%3D&newsess=false&roleid=DP010101/0007&origin=ourprogram"; + URI uri = new URI(input); + System.out.println(uri.toString()); + assertEquals(expectedUri, e.getCanonicalizedURI(uri)); + + } + + @org.junit.Ignore("Pre-check in unit test for issue #826") + public void Issue826GetCanonicalizedDoubleAmpersand() throws Exception { + System.out.println("getCanonicalizedDoubleAmpersand"); + Encoder e = ESAPI.encoder(); + String expectedUri = "http://127.0.0.1:3000/campaigns?goal=all§ion=active&sort-by=-id&status=Draft%2C&html=&contentLaunched"; + //http://127.0.0.1:3000/campaigns?goal=all§ion=active&sort-by=-id&status=Draft,&html=null&=null&contentLaunched=null + /* + * In this case, the URI class should break up the HTML entity in the query so + */ + String input = "http://127.0.0.1:3000/campaigns?goal=all§ion=active&sort-by=-id&status=Draft%2C&html=&&contentLaunched"; + URI uri = new URI(input); + System.out.println(uri.toString()); + try { + assertEquals(expectedUri, e.getCanonicalizedURI(uri)); + fail(); + } catch (Exception ex) { + //Expected + } + } public void testGetCanonicalizedUriWithMailto() throws Exception { System.out.println("getCanonicalizedUriWithMailto"); diff --git a/src/test/java/org/owasp/esapi/reference/validation/HTMLValidationRuleCleanTest.java b/src/test/java/org/owasp/esapi/reference/validation/HTMLValidationRuleCleanTest.java index b5d516456..c28d24f9d 100644 --- a/src/test/java/org/owasp/esapi/reference/validation/HTMLValidationRuleCleanTest.java +++ b/src/test/java/org/owasp/esapi/reference/validation/HTMLValidationRuleCleanTest.java @@ -362,6 +362,10 @@ public void testAntiSamyRegressionCDATAWithJavascriptURL() throws Exception { // // See AntiSamy GitHub issue #380 (https://github.com/nahsra/antisamy/issues/389) for more details. // + // The output has changed again as of AntiSamy 1.7.5. The expected output is now: + // Walert(1) + // See AntiSamy Release notes for 1.7.5 (https://github.com/nahsra/antisamy/releases/tag/v1.7.5) + // // Also, this test, which originally used Validator.isValidSafeHTML(), has been // changed to use Validator.getValidSafeHTML() instead because Validator.isValidSafeHTML() // has been deprecated. See GitHub Security Advisory @@ -375,7 +379,8 @@ public void testScriptTagAfterStyleClosing() throws Exception { ValidationErrorList errors = new ValidationErrorList(); String input = "Walert(1)"; // String expected = "W<script>alert(1)</script>"; // Before AntiSamy 1.7.4 - String expected = "W<xmp<script>alert(1)</script>"; // AntiSamy 1.7.4 (and later?) + // String expected = "W<xmp<script>alert(1)</script>"; // AntiSamy 1.7.4 + String expected = "Walert(1)"; // AntiSamy 1.7.5 (and later?) String output = instance.getValidSafeHTML("escaping style tag attack with script tag", input, 250, false, errors); assertEquals(expected, output); assertTrue(errors.size() == 0); @@ -392,6 +397,10 @@ public void testScriptTagAfterStyleClosing() throws Exception { // // See AntiSamy GitHub issue #380 (https://github.com/nahsra/antisamy/issues/389) for more details. // + // The output has changed again as of AntiSamy 1.7.5. The expected output is now: + // kinput/onfocus=alert(1)> + // See AntiSamy Release notes for 1.7.5 (https://github.com/nahsra/antisamy/releases/tag/v1.7.5) + // // Also, this test, which originally used Validator.isValidSafeHTML(), has been // changed to use Validator.getValidSafeHTML() instead because Validator.isValidSafeHTML() // has been deprecated. See GitHub Security Advisory @@ -405,7 +414,8 @@ public void testOnfocusAfterStyleClosing() throws Exception { String input = "kinput/onfocus=alert(1)>"; // String expected = "k<input/onfocus=alert(1)>"; // Before AntiSamy 1.7.4 - String expected = "k<input<</>input/onfocus=alert(1)>"; // AntiSamy 1.7.4 (and later?) + // String expected = "k<input<</>input/onfocus=alert(1)>"; // AntiSamy 1.7.4 + String expected = "kinput/onfocus=alert(1)>"; // AntiSamy 1.7.5 (and later?) String output = instance.getValidSafeHTML("escaping style tag attack with onfocus attribute", input, 250, false, errors); assertEquals(expected, output); assertTrue(errors.size() == 0); diff --git a/src/test/resources/esapi-java-logging.properties b/src/test/resources/esapi-java-logging.properties deleted file mode 100644 index 71011acc5..000000000 --- a/src/test/resources/esapi-java-logging.properties +++ /dev/null @@ -1,6 +0,0 @@ -handlers= java.util.logging.ConsoleHandler -.level= INFO -java.util.logging.ConsoleHandler.level = INFO -java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter -java.util.logging.SimpleFormatter.format=[%1$tF %1$tT] [%3$-7s] %5$s %n -#https://www.logicbig.com/tutorials/core-java-tutorial/logging/customizing-default-format.html \ No newline at end of file