diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..412eeda --- /dev/null +++ b/.gitattributes @@ -0,0 +1,22 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp +*.sln merge=union +*.csproj merge=union +*.vbproj merge=union +*.fsproj merge=union +*.dbproj merge=union + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..dd84ea7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,38 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Smartphone (please complete the following information):** + - Device: [e.g. iPhone6] + - OS: [e.g. iOS8.1] + - Browser [e.g. stock browser, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..bbcbbe7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.gitignore b/.gitignore index 1ceb81e..55805d4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,49 @@ -__pycache__ -env -.vscode \ No newline at end of file +## Directory-based project format: +.idea/ +!.idea/copyright +!.idea/dataSources.xml + +## File-based project format: +*.ipr +*.iws +*.iml + +# Output directories +target/ +/build/ +/dist/ +bin/ +*.class + +# Eclipse metadata +.metadata +.project +.recommenders +.settings +.classpath +.loadpath + +# NetBeans specific +nbproject/private/ +build/ +nbbuild/ +dist/ +nbdist/ +nbactions.xml +nb-configuration.xml + +# SonarGraph metadata +*.sonargraph + +# Overlays +*overlays/ + +# MacOS files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db +_site/ diff --git a/Gemfile b/Gemfile index 89dbd97..829a2c9 100644 --- a/Gemfile +++ b/Gemfile @@ -1,4 +1,4 @@ source 'https://rubygems.org' group :jekyll_plugins do gem "github-pages" -end \ No newline at end of file +end diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8dfa293 --- /dev/null +++ b/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2011, Eric Sheridan +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/_config.yml b/_config.yml index 5dd48ce..eb4d87f 100644 --- a/_config.yml +++ b/_config.yml @@ -1,3 +1,3 @@ -remote_theme: "owasp/www--site-theme" +remote_theme: "owasp/www--site-theme@main" plugins: - - jekyll-include-cache-0.2.0 \ No newline at end of file + - jekyll-include-cache-0.2.0 diff --git a/csrfguard-extensions/csrfguard-extension-session/pom.xml b/csrfguard-extensions/csrfguard-extension-session/pom.xml new file mode 100644 index 0000000..ae8287f --- /dev/null +++ b/csrfguard-extensions/csrfguard-extension-session/pom.xml @@ -0,0 +1,53 @@ + + + + + 4.0.0 + + + org.owasp + csrfguard-extensions + 4.0.2-SNAPSHOT + + + csrfguard-extension-session + + + + ${project.groupId} + csrfguard + + + + javax.servlet + servlet-api + + + \ No newline at end of file diff --git a/csrfguard-extensions/csrfguard-extension-session/src/main/java/org/owasp/csrfguard/CsrfGuardHttpSessionListener.java b/csrfguard-extensions/csrfguard-extension-session/src/main/java/org/owasp/csrfguard/CsrfGuardHttpSessionListener.java new file mode 100644 index 0000000..b4b1ccd --- /dev/null +++ b/csrfguard-extensions/csrfguard-extension-session/src/main/java/org/owasp/csrfguard/CsrfGuardHttpSessionListener.java @@ -0,0 +1,54 @@ +/* + * The OWASP CSRFGuard Project, BSD License + * Copyright (c) 2011, Eric Sheridan (eric@infraredsecurity.com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of OWASP nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.owasp.csrfguard; + +import org.owasp.csrfguard.session.ContainerSession; +import org.owasp.csrfguard.session.LogicalSession; + +import javax.servlet.http.HttpSession; +import javax.servlet.http.HttpSessionEvent; +import javax.servlet.http.HttpSessionListener; + +public class CsrfGuardHttpSessionListener implements HttpSessionListener { + + @Override + public void sessionCreated(final HttpSessionEvent event) { + final HttpSession session = event.getSession(); + final LogicalSession logicalSession = new ContainerSession(session); + CsrfGuard.getInstance().onSessionCreated(logicalSession); + } + + @Override + public void sessionDestroyed(final HttpSessionEvent event) { + final HttpSession session = event.getSession(); + final LogicalSession logicalSession = new ContainerSession(session); + CsrfGuard.getInstance().onSessionDestroyed(logicalSession); + } +} diff --git a/csrfguard-extensions/csrfguard-extension-session/src/main/java/org/owasp/csrfguard/action/SessionAttribute.java b/csrfguard-extensions/csrfguard-extension-session/src/main/java/org/owasp/csrfguard/action/SessionAttribute.java new file mode 100644 index 0000000..505ea60 --- /dev/null +++ b/csrfguard-extensions/csrfguard-extension-session/src/main/java/org/owasp/csrfguard/action/SessionAttribute.java @@ -0,0 +1,58 @@ +/* + * The OWASP CSRFGuard Project, BSD License + * Copyright (c) 2011, Eric Sheridan (eric@infraredsecurity.com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of OWASP nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.owasp.csrfguard.action; + +import org.owasp.csrfguard.CsrfGuard; +import org.owasp.csrfguard.CsrfGuardException; +import org.owasp.csrfguard.config.properties.ConfigParameters; +import org.owasp.csrfguard.session.LogicalSession; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Objects; + +/** + * Saves the thrown CsrfGuardException object after a token validation to the session, bound to the attribute name extracted from the properties file. + */ +public final class SessionAttribute extends AbstractAction { + + private static final long serialVersionUID = 1367492926060283228L; + + @Override + public void execute(final HttpServletRequest request, final HttpServletResponse response, final CsrfGuardException csrfe, final CsrfGuard csrfGuard) throws CsrfGuardException { + final String attributeName = getParameter(ConfigParameters.ACTION_ATTRIBUTE_NAME); + + final LogicalSession logicalSession = CsrfGuard.getInstance().getLogicalSessionExtractor().extract(request); + + if (Objects.nonNull(logicalSession)) { + logicalSession.setAttribute(attributeName, csrfe); + } + } +} diff --git a/csrfguard-extensions/csrfguard-extension-session/src/main/java/org/owasp/csrfguard/session/ContainerSession.java b/csrfguard-extensions/csrfguard-extension-session/src/main/java/org/owasp/csrfguard/session/ContainerSession.java new file mode 100644 index 0000000..9a2c9c1 --- /dev/null +++ b/csrfguard-extensions/csrfguard-extension-session/src/main/java/org/owasp/csrfguard/session/ContainerSession.java @@ -0,0 +1,79 @@ +/* + * The OWASP CSRFGuard Project, BSD License + * Copyright (c) 2011, Eric Sheridan (eric@infraredsecurity.com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of OWASP nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.owasp.csrfguard.session; + +import javax.servlet.http.HttpSession; +import java.util.Objects; + +public class ContainerSession implements LogicalSession { + + private final HttpSession httpSession; + private boolean areTokensGenerated; + + public ContainerSession(final HttpSession httpSession) { + this.httpSession = httpSession; + } + + @Override + public String getKey() { + return this.httpSession.getId(); + } + + @Override + public boolean isNew() { + return Objects.nonNull(this.httpSession) && this.httpSession.isNew(); + } + + @Override + public void invalidate() { + if (Objects.nonNull(this.httpSession)) { + this.httpSession.invalidate(); + } + } + + @Override + public boolean areTokensGenerated() { + return this.areTokensGenerated; + } + + @Override + public void setTokensGenerated(final boolean areTokensGenerated) { + this.areTokensGenerated = areTokensGenerated; + } + + @Override + public void setAttribute(final String name, final Object value) { + this.httpSession.setAttribute(name, value); + } + + @Override + public Object getAttribute(final String attributeName) { + return this.httpSession.getAttribute(attributeName); + } +} diff --git a/csrfguard-extensions/csrfguard-extension-session/src/main/java/org/owasp/csrfguard/session/SessionTokenKeyExtractor.java b/csrfguard-extensions/csrfguard-extension-session/src/main/java/org/owasp/csrfguard/session/SessionTokenKeyExtractor.java new file mode 100644 index 0000000..cb0406c --- /dev/null +++ b/csrfguard-extensions/csrfguard-extension-session/src/main/java/org/owasp/csrfguard/session/SessionTokenKeyExtractor.java @@ -0,0 +1,58 @@ +/* + * The OWASP CSRFGuard Project, BSD License + * Copyright (c) 2011, Eric Sheridan (eric@infraredsecurity.com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of OWASP nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.owasp.csrfguard.session; + +import org.owasp.csrfguard.token.storage.LogicalSessionExtractor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; +import java.util.Objects; + +public class SessionTokenKeyExtractor implements LogicalSessionExtractor { + + /** + * @param httpServletRequest the current HTTP servlet request + * @return a wrapped container session implementation if a session exists, null otherwise + */ + @Override + public LogicalSession extract(final HttpServletRequest httpServletRequest) { + return extractOrCreate(httpServletRequest, false); + } + + @Override + public LogicalSession extractOrCreate(final HttpServletRequest httpServletRequest) { + return extractOrCreate(httpServletRequest, true); + } + + private LogicalSession extractOrCreate(final HttpServletRequest httpServletRequest, final boolean create) { + final HttpSession session = httpServletRequest.getSession(create); + + return Objects.isNull(session) ? null : new ContainerSession(session); + } +} diff --git a/csrfguard-extensions/csrfguard-jsp-tags/pom.xml b/csrfguard-extensions/csrfguard-jsp-tags/pom.xml new file mode 100644 index 0000000..a008379 --- /dev/null +++ b/csrfguard-extensions/csrfguard-jsp-tags/pom.xml @@ -0,0 +1,73 @@ + + + + + 4.0.0 + + + org.owasp + csrfguard-extensions + 4.0.2-SNAPSHOT + + + csrfguard-jsp-tags + + + + + src/main/resources + + **/*.tld + + true + + + + + + + ${project.groupId} + csrfguard + + + + javax.servlet + servlet-api + + + javax.servlet.jsp + jsp-api + + + javax.servlet + jstl + + + \ No newline at end of file diff --git a/csrfguard-extensions/csrfguard-jsp-tags/src/main/java/org/owasp/csrfguard/tag/ATag.java b/csrfguard-extensions/csrfguard-jsp-tags/src/main/java/org/owasp/csrfguard/tag/ATag.java new file mode 100644 index 0000000..5aff662 --- /dev/null +++ b/csrfguard-extensions/csrfguard-jsp-tags/src/main/java/org/owasp/csrfguard/tag/ATag.java @@ -0,0 +1,115 @@ +/* + * The OWASP CSRFGuard Project, BSD License + * Copyright (c) 2011, Eric Sheridan (eric@infraredsecurity.com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of OWASP nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.owasp.csrfguard.tag; + +import org.owasp.csrfguard.CsrfGuard; +import org.owasp.csrfguard.session.LogicalSession; +import org.owasp.csrfguard.util.BrowserEncoder; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.jsp.tagext.DynamicAttributes; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +public final class ATag extends AbstractUriTag implements DynamicAttributes { + + private final static long serialVersionUID = 0x00202937; + + private final Map attributes = new HashMap<>(); + + @Override + public int doStartTag() { + final CsrfGuard csrfGuard = CsrfGuard.getInstance(); + final String tokenName = csrfGuard.getTokenName(); + + final LogicalSession logicalSession = csrfGuard.getLogicalSessionExtractor().extract((HttpServletRequest) this.pageContext.getRequest()); + final String tokenValue = Objects.nonNull(logicalSession) ? csrfGuard.getTokenService().getTokenValue(logicalSession.getKey(), buildUri(this.attributes.get("href"))) : null; + + try { + this.pageContext.getOut().write(buildStartHtml(tokenName, tokenValue)); + } catch (final IOException e) { + this.pageContext.getServletContext().log(e.getLocalizedMessage(), e); + } + + return EVAL_BODY_INCLUDE; + } + + @Override + public int doEndTag() { + try { + this.pageContext.getOut().write(""); + } catch (final IOException e) { + this.pageContext.getServletContext().log(e.getLocalizedMessage(), e); + } + + return EVAL_PAGE; + } + + @Override + public void setDynamicAttribute(final String arg0, final String arg1, final Object arg2) { + this.attributes.put(arg1.toLowerCase(), String.valueOf(arg2)); + } + + private String buildStartHtml(final String tokenName, final String tokenValue) { + final StringBuilder sb = new StringBuilder(); + + sb.append("'); + + return sb.toString(); + } +} diff --git a/csrfguard-extensions/csrfguard-jsp-tags/src/main/java/org/owasp/csrfguard/tag/AbstractTag.java b/csrfguard-extensions/csrfguard-jsp-tags/src/main/java/org/owasp/csrfguard/tag/AbstractTag.java new file mode 100644 index 0000000..223649f --- /dev/null +++ b/csrfguard-extensions/csrfguard-jsp-tags/src/main/java/org/owasp/csrfguard/tag/AbstractTag.java @@ -0,0 +1,61 @@ +/* + * The OWASP CSRFGuard Project, BSD License + * Copyright (c) 2011, Eric Sheridan (eric@infraredsecurity.com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of OWASP nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.owasp.csrfguard.tag; + +import org.owasp.csrfguard.CsrfValidator; +import org.owasp.csrfguard.ProtectionResult; + +import javax.servlet.jsp.tagext.TagSupport; + +public abstract class AbstractTag extends TagSupport { + + private final static long serialVersionUID = 0xadede854; + + public String buildUri(final String uri) { + return calculateExtendedPageDescriptorUri(normalizeUri(uri)); + } + + /** + * @param normalizedUri the current normalizedUri + * @return if the protected/un-protected page descriptors were defined using wildcards or regexes, this method + * will return the extended page descriptor definition of the normalizedUri, otherwise returns itself + */ + private String calculateExtendedPageDescriptorUri(final String normalizedUri) { + final ProtectionResult protectionResult = new CsrfValidator().isProtectedPage(normalizedUri); + + return protectionResult.isProtected() ? protectionResult.getResourceIdentifier() + : normalizedUri; + } + + private String normalizeUri(final String uri) { + return uri.startsWith("/") ? uri + : this.pageContext.getServletContext().getContextPath() + '/' + uri; + } +} diff --git a/csrfguard/src/main/java/org/owasp/csrfguard/tag/AbstractUriTag.java b/csrfguard-extensions/csrfguard-jsp-tags/src/main/java/org/owasp/csrfguard/tag/AbstractUriTag.java similarity index 63% rename from csrfguard/src/main/java/org/owasp/csrfguard/tag/AbstractUriTag.java rename to csrfguard-extensions/csrfguard-jsp-tags/src/main/java/org/owasp/csrfguard/tag/AbstractUriTag.java index 6c9feb2..296e06c 100644 --- a/csrfguard/src/main/java/org/owasp/csrfguard/tag/AbstractUriTag.java +++ b/csrfguard-extensions/csrfguard-jsp-tags/src/main/java/org/owasp/csrfguard/tag/AbstractUriTag.java @@ -1,19 +1,19 @@ -/** +/* * The OWASP CSRFGuard Project, BSD License - * Eric Sheridan (eric@infraredsecurity.com), Copyright (c) 2011 + * Copyright (c) 2011, Eric Sheridan (eric@infraredsecurity.com) * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of OWASP nor the names of its contributors may be used - * to endorse or promote products derived from this software without specific - * prior written permission. + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of OWASP nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -26,6 +26,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + package org.owasp.csrfguard.tag; public abstract class AbstractUriTag extends AbstractTag { @@ -35,11 +36,10 @@ public abstract class AbstractUriTag extends AbstractTag { private String uri = null; public String getUri() { - return uri; + return this.uri; } - public void setUri(String uri) { + public void setUri(final String uri) { this.uri = buildUri(uri); } - } diff --git a/csrfguard-extensions/csrfguard-jsp-tags/src/main/java/org/owasp/csrfguard/tag/FormTag.java b/csrfguard-extensions/csrfguard-jsp-tags/src/main/java/org/owasp/csrfguard/tag/FormTag.java new file mode 100644 index 0000000..99aa781 --- /dev/null +++ b/csrfguard-extensions/csrfguard-jsp-tags/src/main/java/org/owasp/csrfguard/tag/FormTag.java @@ -0,0 +1,110 @@ +/* + * The OWASP CSRFGuard Project, BSD License + * Copyright (c) 2011, Eric Sheridan (eric@infraredsecurity.com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of OWASP nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.owasp.csrfguard.tag; + +import org.owasp.csrfguard.CsrfGuard; +import org.owasp.csrfguard.session.LogicalSession; +import org.owasp.csrfguard.util.BrowserEncoder; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.DynamicAttributes; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +public final class FormTag extends AbstractUriTag implements DynamicAttributes { + + private final static long serialVersionUID = 0xbefee742; + + private final Map attributes = new HashMap<>(); + + @Override + public int doStartTag() { + final CsrfGuard csrfGuard = CsrfGuard.getInstance(); + final String tokenName = csrfGuard.getTokenName(); + + final LogicalSession logicalSession = csrfGuard.getLogicalSessionExtractor().extract((HttpServletRequest) this.pageContext.getRequest()); + final String tokenValue = Objects.nonNull(logicalSession) ? csrfGuard.getTokenService().getTokenValue(logicalSession.getKey(), buildUri(this.attributes.get("action"))) : null; + + try { + this.pageContext.getOut().write(buildStartHtml(tokenName, tokenValue)); + } catch (final IOException e) { + this.pageContext.getServletContext().log(e.getLocalizedMessage(), e); + } + + return EVAL_BODY_INCLUDE; + } + + @Override + public int doEndTag() { + try { + this.pageContext.getOut().write(""); + } catch (final IOException e) { + this.pageContext.getServletContext().log(e.getLocalizedMessage(), e); + } + + return EVAL_PAGE; + } + + @Override + public void setDynamicAttribute(final String arg0, final String arg1, final Object arg2) throws JspException { + this.attributes.put(arg1.toLowerCase(), String.valueOf(arg2)); + } + + private String buildStartHtml(final String tokenName, final String tokenValue) { + final StringBuilder sb = new StringBuilder(); + + sb.append("
'); + sb.append(""); + + return sb.toString(); + } +} diff --git a/csrfguard/src/main/java/org/owasp/csrfguard/tag/TokenNameTag.java b/csrfguard-extensions/csrfguard-jsp-tags/src/main/java/org/owasp/csrfguard/tag/TokenNameTag.java similarity index 53% rename from csrfguard/src/main/java/org/owasp/csrfguard/tag/TokenNameTag.java rename to csrfguard-extensions/csrfguard-jsp-tags/src/main/java/org/owasp/csrfguard/tag/TokenNameTag.java index 2fbae53..53519a8 100644 --- a/csrfguard/src/main/java/org/owasp/csrfguard/tag/TokenNameTag.java +++ b/csrfguard-extensions/csrfguard-jsp-tags/src/main/java/org/owasp/csrfguard/tag/TokenNameTag.java @@ -1,19 +1,19 @@ -/** +/* * The OWASP CSRFGuard Project, BSD License - * Eric Sheridan (eric@infraredsecurity.com), Copyright (c) 2011 + * Copyright (c) 2011, Eric Sheridan (eric@infraredsecurity.com) * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of OWASP nor the names of its contributors may be used - * to endorse or promote products derived from this software without specific - * prior written permission. + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of OWASP nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -26,12 +26,13 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + package org.owasp.csrfguard.tag; -import java.io.*; -import javax.servlet.jsp.tagext.*; +import org.owasp.csrfguard.CsrfGuard; -import org.owasp.csrfguard.*; +import javax.servlet.jsp.tagext.TagSupport; +import java.io.IOException; public final class TokenNameTag extends TagSupport { @@ -39,15 +40,16 @@ public final class TokenNameTag extends TagSupport { @Override public int doStartTag() { - String tokenName = CsrfGuard.getInstance().getTokenName(); + final CsrfGuard csrfGuard = CsrfGuard.getInstance(); - try { - pageContext.getOut().write(tokenName); - } catch (IOException e) { - pageContext.getServletContext().log(e.getLocalizedMessage(), e); + if (csrfGuard.isEnabled()) { + try { + final String tokenName = csrfGuard.getTokenName(); + this.pageContext.getOut().write(tokenName); + } catch (final IOException e) { + this.pageContext.getServletContext().log(e.getLocalizedMessage(), e); + } } - return SKIP_BODY; } - } diff --git a/csrfguard-extensions/csrfguard-jsp-tags/src/main/java/org/owasp/csrfguard/tag/TokenTag.java b/csrfguard-extensions/csrfguard-jsp-tags/src/main/java/org/owasp/csrfguard/tag/TokenTag.java new file mode 100644 index 0000000..b74fe0a --- /dev/null +++ b/csrfguard-extensions/csrfguard-jsp-tags/src/main/java/org/owasp/csrfguard/tag/TokenTag.java @@ -0,0 +1,65 @@ +/* + * The OWASP CSRFGuard Project, BSD License + * Copyright (c) 2011, Eric Sheridan (eric@infraredsecurity.com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of OWASP nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.owasp.csrfguard.tag; + +import org.owasp.csrfguard.CsrfGuard; +import org.owasp.csrfguard.session.LogicalSession; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.util.Objects; + +public final class TokenTag extends AbstractUriTag { + + private final static long serialVersionUID = 0x12164baa; + + @Override + public int doStartTag() { + final CsrfGuard csrfGuard = CsrfGuard.getInstance(); + + if (csrfGuard.isEnabled()) { + if (csrfGuard.isTokenPerPageEnabled() && Objects.isNull(getUri())) { + throw new IllegalStateException("Must define 'uri' attribute when token per page is enabled"); + } + + final LogicalSession logicalSession = csrfGuard.getLogicalSessionExtractor().extract((HttpServletRequest) this.pageContext.getRequest()); + final String tokenValue = Objects.nonNull(logicalSession) ? csrfGuard.getTokenService().getTokenValue(logicalSession.getKey(), getUri()) : null; + final String tokenName = csrfGuard.getTokenName(); + + try { + this.pageContext.getOut().write(tokenName + '=' + tokenValue); + } catch (final IOException e) { + this.pageContext.getServletContext().log(e.getLocalizedMessage(), e); + } + } + + return SKIP_BODY; + } +} diff --git a/csrfguard-extensions/csrfguard-jsp-tags/src/main/java/org/owasp/csrfguard/tag/TokenValueTag.java b/csrfguard-extensions/csrfguard-jsp-tags/src/main/java/org/owasp/csrfguard/tag/TokenValueTag.java new file mode 100644 index 0000000..dd1e9bf --- /dev/null +++ b/csrfguard-extensions/csrfguard-jsp-tags/src/main/java/org/owasp/csrfguard/tag/TokenValueTag.java @@ -0,0 +1,64 @@ +/* + * The OWASP CSRFGuard Project, BSD License + * Copyright (c) 2011, Eric Sheridan (eric@infraredsecurity.com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of OWASP nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.owasp.csrfguard.tag; + +import org.owasp.csrfguard.CsrfGuard; +import org.owasp.csrfguard.session.LogicalSession; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.util.Objects; + +public final class TokenValueTag extends AbstractUriTag { + + private final static long serialVersionUID = 0xaaca46d3; + + @Override + public int doStartTag() { + final CsrfGuard csrfGuard = CsrfGuard.getInstance(); + + if (csrfGuard.isEnabled()) { + if (csrfGuard.isTokenPerPageEnabled() && Objects.isNull(getUri())) { + throw new IllegalStateException("Must define 'uri' attribute when token per page is enabled"); + } + + final LogicalSession logicalSession = csrfGuard.getLogicalSessionExtractor().extract((HttpServletRequest) this.pageContext.getRequest()); + final String tokenValue = Objects.nonNull(logicalSession) ? csrfGuard.getTokenService().getTokenValue(logicalSession.getKey(), getUri()) : null; + + try { + this.pageContext.getOut().write(tokenValue); + } catch (final IOException e) { + this.pageContext.getServletContext().log(e.getLocalizedMessage(), e); + } + } + + return SKIP_BODY; + } +} diff --git a/csrfguard-extensions/csrfguard-jsp-tags/src/main/resources/META-INF/tags/csrfguard.tld b/csrfguard-extensions/csrfguard-jsp-tags/src/main/resources/META-INF/tags/csrfguard.tld new file mode 100644 index 0000000..42b9420 --- /dev/null +++ b/csrfguard-extensions/csrfguard-jsp-tags/src/main/resources/META-INF/tags/csrfguard.tld @@ -0,0 +1,70 @@ + + + + ${jstl.version} + ${jsp-api.version} + Owasp CsrfGuard Tag Library + http://www.owasp.org/index.php/Category:OWASP_CSRFGuard_Project/Owasp.CsrfGuard.tld + + token + org.owasp.csrfguard.tag.TokenTag + empty + + uri + false + true + + + + tokenname + org.owasp.csrfguard.tag.TokenNameTag + empty + + + tokenvalue + org.owasp.csrfguard.tag.TokenValueTag + empty + + uri + false + true + + + + a + org.owasp.csrfguard.tag.ATag + true + + + form + org.owasp.csrfguard.tag.FormTag + true + + diff --git a/csrfguard-extensions/pom.xml b/csrfguard-extensions/pom.xml new file mode 100644 index 0000000..203c2b7 --- /dev/null +++ b/csrfguard-extensions/pom.xml @@ -0,0 +1,70 @@ + + + + + 4.0.0 + + + org.owasp + csrfguard-parent + 4.0.2-SNAPSHOT + + + csrfguard-extensions + pom + + + csrfguard-extension-session + csrfguard-jsp-tags + + + + + + ${project.groupId} + csrfguard + ${project.version} + + + + + + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-javadoc-plugin + + + + diff --git a/csrfguard-test/csrfguard-test-jsp/pom.xml b/csrfguard-test/csrfguard-test-jsp/pom.xml new file mode 100644 index 0000000..1b8b14f --- /dev/null +++ b/csrfguard-test/csrfguard-test-jsp/pom.xml @@ -0,0 +1,137 @@ + + + + + 4.0.0 + + + org.owasp + csrfguard-test + 4.0.2-SNAPSHOT + + + csrfguard-test-jsp + war + + OWASP CSRFGuard JSP Test WebApp + + + 2.1 + true + true + + + + + deploy-jsp-webapp + + false + + + + + + + ${project.groupId} + csrfguard + + + + ${project.groupId} + csrfguard-extension-session + + + + ${project.groupId} + csrfguard-jsp-tags + ${project.version} + + + + javax.servlet + servlet-api + + + javax.servlet.jsp + jsp-api + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + org.apache.tomcat.maven + tomcat7-maven-plugin + ${tomcat7-maven-plugin.version} + + / + 8080 + ${skip.run.webapp} + + + + create-executable-jar + + exec-war-only + + package + + false + ${project.artifactId}-${project.version}-executable.jar + ${skip.create.executable.jar} + utf-8 + + + + deploy-jsp-war + pre-integration-test + + run-war + + + + shutdown-tomcat + post-integration-test + + shutdown + + + + + + + diff --git a/csrfguard/src/main/java/org/owasp/csrfguard/tag/TokenValueTag.java b/csrfguard-test/csrfguard-test-jsp/src/main/java/org/owasp/csrfguard/test/CORSFilter.java similarity index 52% rename from csrfguard/src/main/java/org/owasp/csrfguard/tag/TokenValueTag.java rename to csrfguard-test/csrfguard-test-jsp/src/main/java/org/owasp/csrfguard/test/CORSFilter.java index 89a42d1..fd49c2c 100644 --- a/csrfguard/src/main/java/org/owasp/csrfguard/tag/TokenValueTag.java +++ b/csrfguard-test/csrfguard-test-jsp/src/main/java/org/owasp/csrfguard/test/CORSFilter.java @@ -1,8 +1,8 @@ -/** +/* * The OWASP CSRFGuard Project, BSD License - * Eric Sheridan (eric@infraredsecurity.com), Copyright (c) 2011 + * Eric Sheridan (eric@infraredsecurity.com), Copyright (c) 2011 * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * @@ -26,35 +26,43 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.owasp.csrfguard.tag; - -import java.io.*; +package org.owasp.csrfguard.test; -import javax.servlet.http.*; +import org.owasp.csrfguard.CsrfGuard; -import org.owasp.csrfguard.*; +import javax.servlet.*; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; -public final class TokenValueTag extends AbstractUriTag { +/** + * Enables Cross-Origin Resource Sharing + * Only for testing purposes. + * Disabled by default through the web.xml + */ +public class CORSFilter implements Filter { - private final static long serialVersionUID = 0xaaca46d3; + @Override + public void init(FilterConfig filterConfig) {} - @Override - public int doStartTag() { - CsrfGuard csrfGuard = CsrfGuard.getInstance(); + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + { + HttpServletResponse httpResponse = (HttpServletResponse) servletResponse; + httpResponse.addHeader("Access-Control-Allow-Origin", "*"); - if (csrfGuard.isTokenPerPageEnabled() && getUri() == null) { - throw new IllegalStateException("must define 'uri' attribute when token per page is enabled"); - } +// httpResponse.addHeader("Access-Control-Allow-Headers", "*"); + httpResponse.addHeader("Access-Control-Allow-Headers", String.join(",", CsrfGuard.getInstance().getTokenName(), + "X-Requested-With")); + } - String tokenValue = csrfGuard.getTokenValue((HttpServletRequest) pageContext.getRequest(), getUri()); + { // Access-Control-Allow-Credentials cannot be set to true if the Access-Control-Allow-Origin is "*" +// httpResponse.addHeader("Access-Control-Allow-Origin", "http://attacker.local:8080"); // sudo echo "127.0.0.1 attacker.local" >> /etc/hosts +// httpResponse.addHeader("Access-Control-Allow-Credentials", Boolean.toString(true)); + } - try { - pageContext.getOut().write(tokenValue); - } catch (IOException e) { - pageContext.getServletContext().log(e.getLocalizedMessage(), e); - } + filterChain.doFilter(servletRequest, servletResponse); + } - return SKIP_BODY; - } - + @Override + public void destroy() {} } diff --git a/csrfguard-test/csrfguard-test-jsp/src/main/java/org/owasp/csrfguard/test/CounterServlet.java b/csrfguard-test/csrfguard-test-jsp/src/main/java/org/owasp/csrfguard/test/CounterServlet.java new file mode 100644 index 0000000..ffe14e3 --- /dev/null +++ b/csrfguard-test/csrfguard-test-jsp/src/main/java/org/owasp/csrfguard/test/CounterServlet.java @@ -0,0 +1,98 @@ +/* + * The OWASP CSRFGuard Project, BSD License + * Eric Sheridan (eric@infraredsecurity.com), Copyright (c) 2011 + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of OWASP nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.owasp.csrfguard.test; + +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Objects; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * Servlet implementation class HelloServlet + */ +public class CounterServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + + private static final ConcurrentMap COUNTER = new ConcurrentHashMap<>(); + + private static final String COUNTER_VALUE_MESSAGE = "Counter value: "; + public static final String INPUT_PARAMETER_NAME = "value"; + public static final String NO_SESSION_MESSAGE = "The request did not contain an associated session!"; + + /** + * Default constructor. + */ + public CounterServlet() {} + + /** + * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) + */ + @Override + protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws IOException { + final HttpSession session = request.getSession(false); + if (Objects.nonNull(session)) { + respond(response, COUNTER.compute(session.getId(), (k, v) -> Optional.ofNullable(v).orElse(0))); + } else { + System.err.println(NO_SESSION_MESSAGE); + response.setStatus(HttpServletResponse.SC_FORBIDDEN); + } + } + + /** + * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) + */ + @Override + protected void doPost(final HttpServletRequest request, final HttpServletResponse response) { + final HttpSession session = request.getSession(false); + if (Objects.nonNull(session)) { + final String inputValue = request.getParameter(INPUT_PARAMETER_NAME); + + try { + final int valueToIncreaseBy = Integer.parseInt(inputValue); + respond(response, COUNTER.compute(session.getId(), (k, v) -> Objects.isNull(v) ? valueToIncreaseBy : v + valueToIncreaseBy)); + } catch (Exception ignored) {} + } else { + System.err.println(NO_SESSION_MESSAGE); + response.setStatus(HttpServletResponse.SC_FORBIDDEN); + } + } + + private void respond(HttpServletResponse response, int value) throws IOException { + response.setContentType("text/plain"); + final PrintWriter writer = new PrintWriter(response.getOutputStream()); + writer.println(COUNTER_VALUE_MESSAGE + value); + writer.close(); + } +} diff --git a/csrfguard-test/csrfguard-test-jsp/src/main/webapp/WEB-INF/classes/Owasp.CsrfGuard.overlay.properties b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/WEB-INF/classes/Owasp.CsrfGuard.overlay.properties new file mode 100644 index 0000000..65a9439 --- /dev/null +++ b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/WEB-INF/classes/Owasp.CsrfGuard.overlay.properties @@ -0,0 +1,75 @@ +###################################################################################### +# The OWASP CSRFGuard Project, BSD License +# Copyright (c) 2011, Eric Sheridan (eric@infraredsecurity.com) +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of OWASP nor the names of its contributors may be used +# to endorse or promote products derived from this software without specific +# prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +###################################################################################### + +org.owasp.csrfguard.configuration.provider.factory=org.owasp.csrfguard.config.overlay.ConfigurationOverlayProviderFactory + +org.owasp.csrfguard.JavascriptServlet.refererPattern = http://localhost:80.* + +org.owasp.csrfguard.TokenPerPagePrecreate = true + +org.owasp.csrfguard.Rotate = true +org.owasp.csrfguard.Ajax = true +org.owasp.csrfguard.TokenPerPage = true +org.owasp.csrfguard.JavascriptServlet.injectIntoDynamicNodes = true + +# Note: it is only enabled for the demo application, for testing purposes. +org.owasp.csrfguard.forceSynchronousAjax = true + +################################################################################ +#### Scenario: everything is protected, except the resources enlisted below #### +################################################################################ +# org.owasp.csrfguard.Protect = false + +org.owasp.csrfguard.unprotected.Default=%servletContext%/ +org.owasp.csrfguard.unprotected.Upload=%servletContext%/upload.html +org.owasp.csrfguard.unprotected.JavaScriptServlet=%servletContext%/JavaScriptServlet +org.owasp.csrfguard.unprotected.Ajax=%servletContext%/ajax.html +org.owasp.csrfguard.unprotected.Error=%servletContext%/error.html +org.owasp.csrfguard.unprotected.Index=%servletContext%/index.html +org.owasp.csrfguard.unprotected.JavaScript=%servletContext%/javascript.html +org.owasp.csrfguard.unprotected.Tag=%servletContext%/tag.jsp +org.owasp.csrfguard.unprotected.Redirect=%servletContext%/redirect.jsp +org.owasp.csrfguard.unprotected.Forward=%servletContext%/forward.jsp +org.owasp.csrfguard.unprotected.Session=%servletContext%/session.jsp +org.owasp.csrfguard.unprotected.Favicon=%servletContext%/favicon.ico +org.owasp.csrfguard.unprotected.ExtensionTest=*.txt +org.owasp.csrfguard.unprotected.WildcardTest=%servletContext%/wildcardtest/* +org.owasp.csrfguard.unprotected.InDepthTxt=^%servletContext%/regextest/.*/.*\\.txt$ +org.owasp.csrfguard.unprotected.Unprotected=^%servletContext%/.*unprotected\\..*$ + +################################################################################## +#### Scenario: everything is unprotected, except the resources enlisted below #### +################################################################################## +org.owasp.csrfguard.Protect = true +org.owasp.csrfguard.protected.Protect=^.*/protect\\..*$ +org.owasp.csrfguard.protected.Protected=^.*/protected\\..*$ +org.owasp.csrfguard.protected.WildcardTest=%servletContext%/wildcardtest/* +org.owasp.csrfguard.protected.CounterServlet=%servletContext%/counter/* +org.owasp.csrfguard.protected.OwaspLogo=owasp_logo.png +################################################################################ \ No newline at end of file diff --git a/csrfguard-test/src/main/webapp/WEB-INF/classes/Owasp.CsrfGuard.properties b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/WEB-INF/classes/Owasp.CsrfGuard.properties similarity index 55% rename from csrfguard-test/src/main/webapp/WEB-INF/classes/Owasp.CsrfGuard.properties rename to csrfguard-test/csrfguard-test-jsp/src/main/webapp/WEB-INF/classes/Owasp.CsrfGuard.properties index 9cf4957..d5849ec 100644 --- a/csrfguard-test/src/main/webapp/WEB-INF/classes/Owasp.CsrfGuard.properties +++ b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/WEB-INF/classes/Owasp.CsrfGuard.properties @@ -1,18 +1,19 @@ +###################################################################################### # The OWASP CSRFGuard Project, BSD License -# Eric Sheridan (eric@infraredsecurity.com), Copyright (c) 2011 +# Copyright (c) 2011, Eric Sheridan (eric@infraredsecurity.com) # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # -# 1. Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of OWASP nor the names of its contributors may be used -# to endorse or promote products derived from this software without specific -# prior written permission. +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of OWASP nor the names of its contributors may be used +# to endorse or promote products derived from this software without specific +# prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -24,17 +25,19 @@ # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# From: https://github.com/esheri3/OWASP-CSRFGuard/blob/master/csrfguard-test/src/main/webapp/WEB-INF/csrfguard.properties - -# Common substitutions -# %servletContext% is the servlet context (e.g. the configured app prefix or war file name, or blank. -# e.g. if you deploy a default warfile as someApp.war, then %servletContext% will be /someApp -# if there isnt a context it will be the empty string. So to use this in the configuration, use e.g. %servletContext%/something.html +###################################################################################### + +########################## +## Common substitutions ## +########################## +# %servletContext% is the servlet context (e.g. the configured app prefix or war file name, or blank. +# e.g. if you deploy a default war file as someApp.war, then %servletContext% will be /someApp +# if there isn't a context it will be the empty string. So to use this in the configuration, use e.g. %servletContext%/something.html # which will translate to e.g. /someApp/something.html -# Logger -# +############ +## Logger ## +############ # The logger property (org.owasp.csrfguard.Logger) defines the qualified class name of # the object responsible for processing all log messages produced by CSRFGuard. The default # CSRFGuard logger is org.owasp.csrfguard.log.ConsoleLogger. This class logs all messages @@ -44,28 +47,28 @@ # logger's qualified class name. The following configuration snippet instructs OWASP CSRFGuard # to capture all log messages to the console: # -# org.owasp.csrfguard.Logger=org.owasp.csrfguard.log.ConsoleLogger -org.owasp.csrfguard.Logger=org.owasp.csrfguard.log.JavaLogger +# org.owasp.csrfguard.Logger = org.owasp.csrfguard.log.ConsoleLogger +org.owasp.csrfguard.Logger = org.owasp.csrfguard.log.JavaLogger -# Which configuration provider factory you want to use. The default is org.owasp.csrfguard.config.PropertiesConfigurationProviderFactory +# Which configuration provider factory you want to use. The default is org.owasp.csrfguard.config.PropertiesConfigurationProviderFactory # Another configuration provider has more features including config overlays: org.owasp.csrfguard.config.overlay.ConfigurationOverlayProviderFactory # The default configuration provider is: org.owasp.csrfguard.config.overlay.ConfigurationAutodetectProviderFactory # which will look for an overlay file, it is there, and the factory inside that file is set it will use it, otherwise will be PropertiesConfigurationProviderFactory # it needs to implement org.owasp.csrfguard.config.ConfigurationProviderFactory org.owasp.csrfguard.configuration.provider.factory = org.owasp.csrfguard.config.overlay.ConfigurationAutodetectProviderFactory - -# If csrfguard filter is enabled +# If CSRFGuard filter is enabled org.owasp.csrfguard.Enabled = true # If csrf guard filter should check even if there is no session for the user # Note: this changed around 2014/04, the default behavior used to be to -# not check if there is no session. If you want the legacy behavior (if your app +# not check if there is no session. If you want the legacy behavior (if your app # is not susceptible to CSRF if the user has no session), set this to false org.owasp.csrfguard.ValidateWhenNoSessionExists = true -# New Token Landing Page -# +############################ +## New Token Landing Page ## +############################ # The new token landing page property (org.owasp.csrfguard.NewTokenLandingPage) defines where # to send a user if the token is being generated for the first time, and the use new token landing # page boolean property (org.owasp.csrfguard.UseNewTokenLandingPage) determines if any redirect happens. @@ -78,11 +81,11 @@ org.owasp.csrfguard.ValidateWhenNoSessionExists = true # redirect the user to %servletContext%/index.html when the user visits a protected resource # without having a corresponding CSRF token present in the HttpSession object: # -# org.owasp.csrfguard.NewTokenLandingPage=%servletContext%/index.html - +# org.owasp.csrfguard.NewTokenLandingPage = %servletContext%/index.html -# Protected Methods -# +####################### +## Protected Methods ## +####################### # The protected methods property (org.owasp.csrfguard.ProtectedMethods) defines a comma # separated list of HTTP request methods that should be protected by CSRFGuard. The default # list is an empty list which will cause all HTTP methods to be protected, thus preserving @@ -97,14 +100,15 @@ org.owasp.csrfguard.ValidateWhenNoSessionExists = true # The following configuration snippet instructs OWASP CSRFGuard to protect only the POST, # PUT, and DELETE HTTP methods. # -# org.owasp.csrfguard.ProtectedMethods=POST,PUT,DELETE - -# or you can configure all to be protected, and specify which is unprotected. This is the preferred approach - -# org.owasp.csrfguard.UnprotectedMethods=GET - -# Unique Per-Page Tokens +# org.owasp.csrfguard.ProtectedMethods = POST,PUT,DELETE # +# or you can configure all to be protected, and specify which is unprotected. This is the preferred approach +# +# org.owasp.csrfguard.UnprotectedMethods = GET + +############################ +## Unique Per-Page Tokens ## +############################ # The unique token per-page property (org.owasp.csrfguard.TokenPerPage) is a boolean value that # determines if CSRFGuard should make use of unique per-page (i.e. URI) prevention tokens as # opposed to unique per-session prevention tokens. When a user requests a protected resource, @@ -116,10 +120,17 @@ org.owasp.csrfguard.ValidateWhenNoSessionExists = true # the first time. All subsequent requests must have the per-page token intact or the request will # be treated as a CSRF attack. This behavior can be changed with the org.owasp.csrfguard.TokenPerPagePrecreate # property. Enabling this property will make CSRFGuard calculate the per page token prior to a first -# visit. This option only works with JSTL token injection and is useful for preserving the validity of -# links if the user pushes the back button. There may be a performance impact when enabling this option -# if the .jsp has a large number of proctected links that need tokens to be calculated. -# Use of the unique token per page property is currently experimental +# visit. +# +# This option ONLY WORKS WITH JSTL token injection and is useful for preserving the validity of +# links if the user pushes the BACK button. There may be a performance impact when enabling this option +# if the JSP has a large number of protected links that need tokens to be calculated. +# +# Note: Pre-creating tokens is only available with the session bound token holder implementation, +# because in case for stateless or custom state implementations, client could would need +# to signal when it's ok to pre-create the tokens and this would affect the modularity/pluggability of the solution. +# +# Use of the unique token per page property is currently EXPERIMENTAL, # but provides a significant amount of improved security. Consider the exposure of a CSRF token using # the legacy unique per-session model. Exposure of this token facilitates the attacker's ability to # carry out a CSRF attack against the victim's active session for any resource exposed by the web @@ -129,14 +140,12 @@ org.owasp.csrfguard.ValidateWhenNoSessionExists = true # unique token per-page property is a strong defense in depth strategy significantly reducing the # impact of exposed CSRF prevention tokens. The following configuration snippet instructs OWASP # CSRFGuard to utilize the unique token per-page model: -# -# org.owasp.csrfguard.TokenPerPage=true -# org.owasp.csrfguard.TokenPerPagePrecreate=false -org.owasp.csrfguard.TokenPerPage=true -org.owasp.csrfguard.TokenPerPagePrecreate=true +org.owasp.csrfguard.TokenPerPage = true +org.owasp.csrfguard.TokenPerPagePrecreate = false -# Token Rotation -# +#################### +## Token Rotation ## +#################### # The rotate token property (org.owasp.csrfguard.Rotate) is a boolean value that determines if # CSRFGuard should generate and utilize a new token after verifying the previous token. Rotation # helps minimize the window of opportunity an attacker has to leverage the victim's stolen token @@ -146,13 +155,20 @@ org.owasp.csrfguard.TokenPerPagePrecreate=true # an old token causing CSRFGuard to incorrectly believe this request is a CSRF attack in progress # (i.e. a 'false positive'). Users can prevent this scenario by preventing the caching of HTML pages # containing FORM submissions using the cache-control header. However, this may also introduce -# performance problems as the browser will have to request HTML on a more frequent basis. The following -# configuration snippet enables token rotation: +# performance problems as the browser will have to request HTML on a more frequent basis. # -# org.owasp.csrfguard.Rotate=true - -# Ajax and XMLHttpRequest Support +# Note: Rotation in case of AJAX requests is not supported currently because of possible race conditions. +# A Single Page Application can fire multiple simultaneous requests. If rotation is enabled for AJAX requests, +# the first request could trigger a token change before the validation of the same token within the second request, +# causing false-positive CSRF intrusion exceptions. +# +# The following configuration snippet enables token rotation: # +# org.owasp.csrfguard.Rotate = true + +##################################### +## Ajax and XMLHttpRequest Support ## +##################################### # The Ajax property (org.owasp.csrfguard.Ajax) is a boolean value that indicates whether or not OWASP # CSRFGuard should support the injection and verification of unique per-session prevention tokens for # XMLHttpRequests. To leverage Ajax support, the user must not only set this property to true but must @@ -169,22 +185,27 @@ org.owasp.csrfguard.TokenPerPagePrecreate=true # the corresponding X-Requested-With and custom headers are embedded within the request. The following # configuration snippet instructs OWASP CSRFGuard to support Ajax requests by verifying the presence and # correctness of the X-Requested-With and custom headers: -# -# org.owasp.csrfguard.Ajax=true -org.owasp.csrfguard.Ajax=true +org.owasp.csrfguard.Ajax = true +####################### +## Protecting Pages ## +####################### # The default behavior of CSRFGuard is to protect all pages. Pages marked as unprotected will not be protected. # If the Protect property is enabled, this behavior is reversed. Pages must be marked as protected to be protected. # All other pages will not be protected. This is useful when the CsrfGuardFilter is aggressively mapped (ex: /*), # but you only want to protect a few pages. # -# org.owasp.csrfguard.Protect=false -org.owasp.csrfguard.protected.Protected=/protect.html -org.owasp.csrfguard.protected.Test=/test.html -org.owasp.csrfguard.protected.Forward=/forward.jsp - -# Unprotected Pages: +# org.owasp.csrfguard.Protect = true # +# Defining pages to protect explicitly: +# +# org.owasp.csrfguard.protected.Protected = /protect.html +# org.owasp.csrfguard.protected.Test = /test.html +# org.owasp.csrfguard.protected.Forward = /forward.jsp + +####################### +## Unprotected Pages ## +####################### # The unprotected pages property (org.owasp.csrfguard.unprotected.*) defines a series of pages that # should not be protected by CSRFGuard. Such configurations are useful when the CsrfGuardFilter is # aggressively mapped (ex: /*). The syntax of the property name is org.owasp.csrfguard.unprotected.[PageName], @@ -196,8 +217,8 @@ org.owasp.csrfguard.protected.Forward=/forward.jsp # Case 1: exact match between request uri and unprotected page # Case 2: longest path prefix match, beginning / and ending /* # Case 3: extension match, beginning *. -# Case 4: if the value starts with ^ and ends with $, it will be evaulated as a regex. Note that before the -# regex is compiled, any common variables will be substituted (e.g. %servletContext%) +# Case 4: if the value starts with ^ and ends with $, it will be evaluated as a regex. +# Note that before the regex is compiled, any common variables will be substituted (e.g. %servletContext%) # Default: requested resource must be validated by CSRFGuard # # The following code snippet illustrates the four use cases over four examples. The first two examples @@ -205,27 +226,29 @@ org.owasp.csrfguard.protected.Forward=/forward.jsp # ending in a .html extension. The next example (Public) looks for all resources prefixed with the URI path /MySite/Public/*. # The last example looks for resources that end in Public.do # -# org.owasp.csrfguard.unprotected.Tag=%servletContext%/tag.jsp -# org.owasp.csrfguard.unprotected.JavaScriptServlet=%servletContext%/JavaScriptServlet -# org.owasp.csrfguard.unprotected.Html=*.html -# org.owasp.csrfguard.unprotected.Public=%servletContext%/Public/* -# regex example starts with ^ and ends with $, and the %servletContext% is evaluated before the regex -# org.owasp.csrfguard.unprotected.PublicServlet=^%servletContext%/.*Public\.do$ - -#org.owasp.csrfguard.unprotected.Default=%servletContext%/ -#org.owasp.csrfguard.unprotected.Upload=%servletContext%/upload.html -#org.owasp.csrfguard.unprotected.JavaScriptServlet=%servletContext%/JavaScriptServlet -#org.owasp.csrfguard.unprotected.Ajax=%servletContext%/ajax.html -#org.owasp.csrfguard.unprotected.Error=%servletContext%/error.html -#org.owasp.csrfguard.unprotected.Index=%servletContext%/index.html -#org.owasp.csrfguard.unprotected.JavaScript=%servletContext%/javascript.html -#org.owasp.csrfguard.unprotected.Tag=%servletContext%/tag.jsp -#org.owasp.csrfguard.unprotected.Redirect=%servletContext%/redirect.jsp -#org.owasp.csrfguard.unprotected.Forward=%servletContext%/forward.jsp -#org.owasp.csrfguard.unprotected.Session=%servletContext%/session.jsp - -# Actions: Responding to Attacks -# +# org.owasp.csrfguard.unprotected.Tag = %servletContext%/tag.jsp +# org.owasp.csrfguard.unprotected.JavaScriptServlet = %servletContext%/JavaScriptServlet +# org.owasp.csrfguard.unprotected.Html = *.html +# org.owasp.csrfguard.unprotected.Public = %servletContext%/Public/* +# +# Regex example starts with ^ and ends with $, and the %servletContext% is evaluated before the regex: +# org.owasp.csrfguard.unprotected.PublicServlet = ^%servletContext%/.*Public\.do$ + +# org.owasp.csrfguard.unprotected.Default = %servletContext%/ +# org.owasp.csrfguard.unprotected.Upload = %servletContext%/upload.html +# org.owasp.csrfguard.unprotected.JavaScriptServlet = %servletContext%/JavaScriptServlet +# org.owasp.csrfguard.unprotected.Ajax = %servletContext%/ajax.html +# org.owasp.csrfguard.unprotected.Error = %servletContext%/error.html +# org.owasp.csrfguard.unprotected.Index = %servletContext%/index.html +# org.owasp.csrfguard.unprotected.JavaScript = %servletContext%/javascript.html +# org.owasp.csrfguard.unprotected.Tag = %servletContext%/tag.jsp +# org.owasp.csrfguard.unprotected.Redirect = %servletContext%/redirect.jsp +# org.owasp.csrfguard.unprotected.Forward = %servletContext%/forward.jsp +# org.owasp.csrfguard.unprotected.Session = %servletContext%/session.jsp + +#################################### +## Actions: Responding to Attacks ## +#################################### # The actions directive (org.owasp.csrfguard.action.*) gives the user the ability to specify one or more # actions that should be invoked when a CSRF attack is detected. Every action must implement the # org.owasp.csrfguard.action.IAction interface either directly or indirectly through the @@ -238,8 +261,8 @@ org.owasp.csrfguard.protected.Forward=/forward.jsp # the CSRFGuard bundle and is available via the class name org.owasp.csrfguard.actions.Redirect. In order to enable # this action, we capture the following declaration in the Owasp.CsrfGuard.properties file: # -# syntax: org.owasp.csrfguard.action.[actionName]=[className] -# example: org.owasp.csrfguard.action.class.Redirect=org.owasp.csrfguard.actions.Redirect +# syntax: org.owasp.csrfguard.action.[actionName] = [className] +# example: org.owasp.csrfguard.action.class.Redirect = org.owasp.csrfguard.actions.Redirect # # The aforementioned directive declares an action called "Redirect" (i.e. [actionName]) referencing the Java class # "org.owasp.csrfguard.actions.Redirect" (i.e. [className]). Anytime a CSRF attack is detected, the Redirect action @@ -247,95 +270,89 @@ org.owasp.csrfguard.protected.Forward=/forward.jsp # action parameters come into play. In order to specify the redirect location, we capture the following declaration # in the Owasp.CsrfGuard.properties file: # -# syntax: org.owasp.csrfguard.action.[actionName].[parameterName]=[parameterValue] -# example: org.owasp.csrfguard.action.Redirect.ErrorPage=%servletContext%/error.html +# syntax: org.owasp.csrfguard.action.[actionName].[parameterName] = [parameterValue] +# example: org.owasp.csrfguard.action.Redirect.ErrorPage = %servletContext%/error.html # # The aforementioned directive declares an action parameter called "ErrorPage" (i.e. [parameterName]) with the value # of "%servletContext%/error.html" (i.e. [parameterValue]) for the action "Redirect" (i.e. [actionName]). The # Redirect action expects the "ErrorPage" parameter to be defined and will redirect the user to this location when # an attack is detected. +# org.owasp.csrfguard.action.Empty = org.owasp.csrfguard.action.Empty # -#org.owasp.csrfguard.action.Empty=org.owasp.csrfguard.action.Empty -org.owasp.csrfguard.action.Log=org.owasp.csrfguard.action.Log -org.owasp.csrfguard.action.Log.Message=potential cross-site request forgery (CSRF) attack thwarted (user:%user%, ip:%remote_ip%, method:%request_method%, uri:%request_uri%, error:%exception_message%) -#org.owasp.csrfguard.action.Invalidate=org.owasp.csrfguard.action.Invalidate -org.owasp.csrfguard.action.Redirect=org.owasp.csrfguard.action.Redirect -org.owasp.csrfguard.action.Redirect.Page=%servletContext%/error.html -#org.owasp.csrfguard.action.RequestAttribute=org.owasp.csrfguard.action.RequestAttribute -#org.owasp.csrfguard.action.RequestAttribute.AttributeName=Owasp_CsrfGuard_Exception_Key -org.owasp.csrfguard.action.Rotate=org.owasp.csrfguard.action.Rotate -#org.owasp.csrfguard.action.SessionAttribute=org.owasp.csrfguard.action.SessionAttribute -#org.owasp.csrfguard.action.SessionAttribute.AttributeName=Owasp_CsrfGuard_Exception_Key -#org.owasp.csrfguard.action.Error=org.owasp.csrfguard.action.Error -#org.owasp.csrfguard.action.Error.Code=403 -#org.owasp.csrfguard.action.Error.Message=Security violation. - -# Token Name +# org.owasp.csrfguard.action.Invalidate = org.owasp.csrfguard.action.Invalidate # +# org.owasp.csrfguard.action.RequestAttribute = org.owasp.csrfguard.action.RequestAttribute +# org.owasp.csrfguard.action.RequestAttribute.AttributeName = Owasp_CsrfGuard_Exception_Key +# +# org.owasp.csrfguard.action.Error = org.owasp.csrfguard.action.Error +# org.owasp.csrfguard.action.Error.Code = 403 +# org.owasp.csrfguard.action.Error.Message = Security violation. + +org.owasp.csrfguard.action.Log = org.owasp.csrfguard.action.Log +org.owasp.csrfguard.action.Log.Message = potential cross-site request forgery (CSRF) attack thwarted (user:%user%, ip:%remote_ip%, method:%request_method%, uri:%request_uri%, error:%exception_message%) + +org.owasp.csrfguard.action.Redirect = org.owasp.csrfguard.action.Redirect +org.owasp.csrfguard.action.Redirect.Page = %servletContext%/error.html + +org.owasp.csrfguard.action.Rotate = org.owasp.csrfguard.action.Rotate + +# Extension modules can add their own actions. Please refer to their documentation to see what actions can be added. +# Extension provided actions should be added through a configuration overlay. +# org.owasp.csrfguard.action.SessionAttribute = org.owasp.csrfguard.action.SessionAttribute +# org.owasp.csrfguard.action.SessionAttribute.AttributeName = Owasp_CsrfGuard_Exception_Key + +################ +## Token Name ## +################ # The token name property (org.owasp.csrfguard.TokenName) defines the name of the HTTP parameter # to contain the value of the OWASP CSRFGuard token for each request. The following configuration # snippet sets the CSRFGuard token parameter name to the value OWASP-CSRFTOKEN: -# -# org.owasp.csrfguard.TokenName=OWASP-CSRFTOKEN -org.owasp.csrfguard.TokenName=OWASP-CSRFTOKEN - -# Session Key -# -# The session key property (org.owasp.csrfguard.SessionKey) defines the string literal used to save -# and lookup the CSRFGuard token from the session. This value is used by the filter and the tag -# libraries to retrieve and set the token value in the session. Developers can use this key to -# programmatically lookup the token within their own code. The following configuration snippet sets -# the session key to the value OWASP_CSRFTOKEN: -# -# org.owasp.csrfguard.SessionKey=OWASP_CSRFTOKEN -org.owasp.csrfguard.SessionKey=OWASP_CSRFTOKEN +org.owasp.csrfguard.TokenName = OWASP-CSRFTOKEN -# Token Length -# +################## +## Token Length ## +################## # The token length property (org.owasp.csrfguard.TokenLength) defines the number of characters that # should be found within the CSRFGuard token. Note that characters are delimited by dashes (-) in groups # of four. For cosmetic reasons, users are encourage to ensure the token length is divisible by four. # The following configuration snippet sets the token length property to 32 characters: -# -# org.owasp.csrfguard.TokenLength=32 -org.owasp.csrfguard.TokenLength=32 +org.owasp.csrfguard.TokenLength = 32 -# Pseudo-random Number Generator -# +#################################### +## Pseudo-random Number Generator ## +#################################### # The pseudo-random number generator property (org.owasp.csrfguard.PRNG) defines what PRNG should be used # to generate the OWASP CSRFGuard token. Always ensure this value references a cryptographically strong # pseudo-random number generator algorithm. The following configuration snippet sets the pseudo-random number # generator to SHA1PRNG: -# -# org.owasp.csrfguard.PRNG=SHA1PRNG -org.owasp.csrfguard.PRNG=SHA1PRNG - -# Pseudo-random Number Generator Provider +org.owasp.csrfguard.PRNG = SHA1PRNG +############################################# +## Pseudo-random Number Generator Provider ## +############################################# # The pseudo-random number generator provider property (org.owasp.csrfguard.PRNG.Provider) defines which # provider's implementation of org.owasp.csrfguard.PRNG we should utilize. The following configuration # snippet instructs the JVM to leverage SUN's implementation of the algorithm denoted by the # org.owasp.csrfguard.PRNG property: -# org.owasp.csrfguard.PRNG.Provider=SUN -org.owasp.csrfguard.PRNG.Provider=SUN +org.owasp.csrfguard.PRNG.Provider = SUN # If not specifying the print config option in the web.xml, you can specify it here, to print the config # on startup org.owasp.csrfguard.Config.Print = true -########################### -## Javascript servlet settings if not set in web.xml -## https://www.owasp.org/index.php/CSRFGuard_3_Token_Injection -########################### +################################################################# +## Javascript servlet settings if not set in web.xml ## +## https://www.owasp.org/index.php/CSRFGuard_3_Token_Injection ## +################################################################# -# leave this blank and blank in web.xml and it will read from META-INF/csrfguard.js from the jarfile +# leave this blank and blank in web.xml and it will read from META-INF/csrfguard.js from the jar file # Denotes the location of the JavaScript template file that should be consumed and dynamically # augmented by the JavaScriptServlet class. The default value is WEB-INF/Owasp.CsrfGuard.js. # Use of this property and the existence of the specified template file is required. -org.owasp.csrfguard.JavascriptServlet.sourceFile = /script/csrfguard.js +org.owasp.csrfguard.JavascriptServlet.sourceFile = -# Boolean value that determines whether or not the dynamic JavaScript code should be strict +# Boolean value that determines whether or not the dynamic JavaScript code should be strict # with regards to what links it should inject the CSRF prevention token. With a value of true, # the JavaScript code will only place the token in links that point to the same exact domain # from which the HTML originated. With a value of false, the JavaScript code will place the @@ -344,11 +361,11 @@ org.owasp.csrfguard.JavascriptServlet.sourceFile = /script/csrfguard.js org.owasp.csrfguard.JavascriptServlet.domainStrict = true # Allows the developer to specify the value of the Cache-Control header in the HTTP response -# when serving the dynamic JavaScript file. The default value is private, maxage=28800. +# when serving the dynamic JavaScript file. The default value is private, max-age=28800. # Caching of the dynamic JavaScript file is intended to minimize traffic and improve performance. # Note that the Cache-Control header is always set to "no-store" when either the "Rotate" # "TokenPerPage" options is set to true in Owasp.CsrfGuard.properties. -org.owasp.csrfguard.JavascriptServlet.cacheControl = private, maxage=28800 +org.owasp.csrfguard.JavascriptServlet.cacheControl = private, max-age=28800 # Allows the developer to specify a regular expression describing the required value of the # Referer header. Any attempts to access the servlet with a Referer header that does not @@ -359,9 +376,14 @@ org.owasp.csrfguard.JavascriptServlet.cacheControl = private, maxage=28800 # checking is implemented to achieve defense in depth. org.owasp.csrfguard.JavascriptServlet.refererPattern = .* -# Similar to javascript servlet referer pattern, but this will make sure the referer of the -# javascript servlet matches the domain of the request. If there is no referer (proxy strips it?) -# then it will not fail. Generally this is a good idea to be true. +# Used in conjunction with javascript servlet referer Match Domain, but this will make sure the referer of the +# javascript servlet matches the protocol of the request. If the referer Match Domain property is disabled, +# this property is not used +org.owasp.csrfguard.JavascriptServlet.refererMatchProtocol = true + +# Similar to javascript servlet referer pattern, but this will make sure the referer of the +# javascript servlet matches the domain of the request. If there is no referer (proxy strips it?) +# then it will not fail. Generally this is a good idea to be true. org.owasp.csrfguard.JavascriptServlet.refererMatchDomain = true # Boolean value that determines whether or not the dynamic JavaScript code should @@ -370,16 +392,16 @@ org.owasp.csrfguard.JavascriptServlet.refererMatchDomain = true # as most server-side state changing actions are triggered via a POST request. org.owasp.csrfguard.JavascriptServlet.injectIntoForms = true -# if the token should be injected in GET forms (which will be on the URL) -# if the HTTP method GET is unprotected, then this should likely be false +# If the token should be injected in GET forms (which will be on the URL). +# If this property is set to true, it will enable tokens injection into forms with GET method, +# even if the method was previously configured as unprotected. org.owasp.csrfguard.JavascriptServlet.injectGetForms = true # if the token should be injected in the action in forms # note, if injectIntoForms is true, then this might not need to be true org.owasp.csrfguard.JavascriptServlet.injectFormAttributes = true - -# Boolean value that determines whether or not the dynamic JavaScript code should +# Boolean value that determines whether or not the dynamic JavaScript code should # inject the CSRF prevention token in the query string of src and href attributes. # Injecting the CSRF prevention token in a URL resource increases its general risk # of exposure to unauthorized parties. However, most JavaEE web applications respond @@ -391,17 +413,43 @@ org.owasp.csrfguard.JavascriptServlet.injectFormAttributes = true # POST requests (i.e. discarding GET requests) are strongly encouraged to disable this property. org.owasp.csrfguard.JavascriptServlet.injectIntoAttributes = true +# Some applications might dynamically create new DOM elements (e.g. forms). +# This property enables an asynchronous MutationObserver or a DOMNodeInserted event listener if MutationObservers are not supported +# that is called when new elements are added to the DOM, then injects the CSRF tokens to it. +# Note: using event listeners can have a significant impact on performance, hence it defaults to false. +org.owasp.csrfguard.JavascriptServlet.injectIntoDynamicNodes = false + +# This property defines the custom event name that will be fired manually by the client when a DOM element +# that requires CSRF tokens to be injected is modified or (e.g. form action changed) a new one is created. +# Since the default MutationObserver implementation is asynchronous, there might be corner-case race conditions +# between dynamically created and submitted forms and the time the MutationObserver is being invoked by the browser. +# These special cases are intended to be handled with this approach, because JavaScript events are executed synchronously. +# After a dynamic DOM element creation which requires token injection the integrator client has to manually fire an event +# with the same name provided below. +# +# Example client code, where 'updatedInjectableElement' is the dynamically created element added to the DOM: +# const injectableNodeChangedEvent = new CustomEvent('InjectableNodeChanged', {detail: updatedInjectableElement}); +# window.dispatchEvent(injectableNodeChangedEvent); +# +# Note: this property does not default to a pre-defined value and is only considered, +# if 'org.owasp.csrfguard.JavascriptServlet.injectIntoDynamicNodes' is true. +# org.owasp.csrfguard.JavascriptServlet.dynamicNodeCreationEventName = InjectableNodeChanged org.owasp.csrfguard.JavascriptServlet.xRequestedWith = OWASP CSRFGuard Project -########################### -## Config overlay settings if you have the provider above set to ConfigurationOverlayProvider -## This CSRF config provider uses Internet2 Configuration Overlays (documented on Internet2 wiki) -## By default the configuration is read from the Owasp.CsrfGuard.properties -## (which should not be edited), and the Owasp.CsrfGuard.overlay.properties overlays -## the base settings. See the Owasp.CsrfGuard.properties for the possible -## settings that can be applied to the Owasp.CsrfGuard.overlay.properties -########################### +# A comma separated list of file extensions can be added here to prevent the token from +# being appended to them after pageload (which often causes a second copy of those static +# resources to be downloaded). ex: "js,css,gif,png,ico,jpg" +# org.owasp.csrfguard.JavascriptServlet.UnprotectedExtensions = js,css,gif,png,ico,jpg + +#################################################################################################### +## Config overlay settings if you have the provider above set to ConfigurationOverlayProvider ## +## This CSRF config provider uses Internet2 Configuration Overlays (documented on Internet2 wiki) ## +## By default the configuration is read from the Owasp.CsrfGuard.properties ## +## (which should not be edited), and the Owasp.CsrfGuard.overlay.properties overlays ## +## the base settings. See the Owasp.CsrfGuard.properties for the possible ## +## settings that can be applied to the Owasp.CsrfGuard.overlay.properties ## +#################################################################################################### # comma separated config files that override each other (files on the right override the left) # each should start with file: or classpath: @@ -411,6 +459,52 @@ org.owasp.csrfguard.configOverlay.hierarchy = classpath:Owasp.CsrfGuard.properti # seconds between checking to see if the config files are updated org.owasp.csrfguard.configOverlay.secondsBetweenUpdateChecks = 60 - -########################### - +########################## +## Custom Token storage ## +########################## +# This parameter enables custom Token Holder implementations. It can be used when the backend has a stateless architecture. +# The implementation has to implement the org.owasp.csrfguard.token.storage.TokenHolder interface. +# The logic uses SPI to discover the implementation, so in the client module there should be a file called 'org.owasp.csrfguard.token.storage.TokenHolder' under the 'META-INF/services' directory that would contain +# the fully qualified class name of the custom implementation. +# +# Depends on the 'org.owasp.csrfguard.token.storage.LogicalSessionExtractor' property. If the dependency is not fulfilled, then this property will be disregarded. +# Defaults to 'org.owasp.csrfguard.token.storage.impl.InMemoryTokenHolder', which uses a ConcurrentHashMap to store the tokens. +# TODO review +# org.owasp.csrfguard.TokenHolder = org.owasp.csrfguard.token.storage.impl.InMemoryTokenHolder + +# This parameter enables defining a custom logical session extractor. The logic must implement the 'org.owasp.csrfguard.token.storage.LogicalSessionExtractor' interface. +# TODO +# Defaults to 'org.owasp.csrfguard.session.ContainerSession', which uses the container's HttpSession in the background. The extensions module containing this logic has to be added as a Maven dependency to the project. +# If a custom implementation is required (e.g. stateless sessions with JWTs), the integration code should invoke the 'org.owasp.csrfguard.CsrfGuard.onSessionCreated' and 'org.owasp.csrfguard.CsrfGuard.onSessionDestroyed' +# The 'org.owasp.csrfguard.token.storage.LogicalSessionExtractor#getKey' method should return a unique identifier for a specific request (e.g. username from JWT token) +org.owasp.csrfguard.LogicalSessionExtractor = org.owasp.csrfguard.session.SessionTokenKeyExtractor + +################# +## Concurrency ## +################# +# Defines for how many milliseconds the application should accept the master token instead of a newly generated page token. +# +# This parameter is aimed to solve the race condition when the 'org.owasp.csrfguard.TokenPerPage' option is enabled without 'org.owasp.csrfguard.TokenPerPagePrecreate' +# when multiple simultaneous AJAX ('org.owasp.csrfguard.Ajax') requests are fired by a Single Page Applications (SPA) +# before the initialization of the desired endpoint URIs. The first request against a specific endpoint URI is validated using the master token, +# then a new page token is generated for future calls, but in case of multiple simultaneously requests, the logic might not have time to assign +# the newly generated page token to the resource on the client side causing false positive intrusion exceptions. +# +# Note: This configuration does not (yet) enable the AJAX and Token Rotation combination. See the documentation for 'org.owasp.csrfguard.Rotate' +# +# Defaults to 2000 milliseconds (= 2 seconds). +org.owasp.csrfguard.PageTokenSynchronizationTolerance = 2000 + +# The current approach of the OWASP CSRFGuard relies on JavaScript logic for injecting CSRF tokens into HTML elements or XHR requests. +# Forcing synchronous loading of the AJAX requests has been disabled by default, since they were deprecated +# (see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Synchronous_and_Asynchronous_Requests#synchronous_request) +# due to their negative impact on the user experience. For this reason, protecting resources that would load +# before or in parallel with the JavaScript logic (e.g. references IFrames or IMG tags) is not possible anymore. +# In most cases this should not be a problem, because usually GET requests should not facilitate state-changing operations. +# If case this last condition cannot be fulfilled (e.g. for legacy applications), backwards compatibility can be achieved by enabling the +# "forceSynchronousAjax" property below, until there is browser support for it. +# +# Defaults to False. +# Note: it is only enabled for the demo application, for testing purposes. +# +org.owasp.csrfguard.forceSynchronousAjax = false diff --git a/csrfguard-test/src/main/webapp/WEB-INF/web.xml b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/WEB-INF/web.xml similarity index 63% rename from csrfguard-test/src/main/webapp/WEB-INF/web.xml rename to csrfguard-test/csrfguard-test-jsp/src/main/webapp/WEB-INF/web.xml index 0596336..8c40702 100644 --- a/csrfguard-test/src/main/webapp/WEB-INF/web.xml +++ b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/WEB-INF/web.xml @@ -1,5 +1,9 @@ - + OWASP CSRFGuard Test @@ -17,7 +21,7 @@ org.owasp.csrfguard.CsrfGuardHttpSessionListener - + CSRFGuard org.owasp.csrfguard.CsrfGuardFilter @@ -43,14 +47,22 @@ - - HelloServlet - HelloServlet - org.owasp.csrfguard.test.HelloServlet + CounterServlet + CounterServlet + org.owasp.csrfguard.test.CounterServlet - HelloServlet - /HelloServlet + CounterServlet + /counter + + diff --git a/csrfguard-test/csrfguard-test-jsp/src/main/webapp/ajax.html b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/ajax.html new file mode 100644 index 0000000..b039adb --- /dev/null +++ b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/ajax.html @@ -0,0 +1,78 @@ + + + + + + Ajax Header Verification + + + +

Test Link(s)

+
+
+

Test Form(s)

+ + + +
+

Dom Test

+
+ + \ No newline at end of file diff --git a/csrfguard-test/csrfguard-test-jsp/src/main/webapp/attack1.html b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/attack1.html new file mode 100644 index 0000000..7bd7b9f --- /dev/null +++ b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/attack1.html @@ -0,0 +1,28 @@ + + + + + + +
+ +
+ \ No newline at end of file diff --git a/csrfguard-test/csrfguard-test-jsp/src/main/webapp/attack2.html b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/attack2.html new file mode 100644 index 0000000..a18becf --- /dev/null +++ b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/attack2.html @@ -0,0 +1,24 @@ + + + + + + \ No newline at end of file diff --git a/csrfguard-test/csrfguard-test-jsp/src/main/webapp/counter.html b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/counter.html new file mode 100644 index 0000000..dfc0cc2 --- /dev/null +++ b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/counter.html @@ -0,0 +1,51 @@ + + + + + + Counter test + + + +

Get or increment the counter:

+

If the counter can be externally incremented, it signals that there is a vulnerability in the solution.

+ + +
+ + +
+

+
+ + diff --git a/csrfguard-test/src/main/webapp/error.html b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/error.html similarity index 56% rename from csrfguard-test/src/main/webapp/error.html rename to csrfguard-test/csrfguard-test-jsp/src/main/webapp/error.html index 97acd83..94a5f2a 100644 --- a/csrfguard-test/src/main/webapp/error.html +++ b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/error.html @@ -1,10 +1,10 @@ - + - -CSRF Attack Detected + + CSRF Attack Detected CSRF Attack Detected - Home - \ No newline at end of file + diff --git a/csrfguard-test/csrfguard-test-jsp/src/main/webapp/favicon.ico b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/favicon.ico new file mode 100644 index 0000000..ab0a666 Binary files /dev/null and b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/favicon.ico differ diff --git a/csrfguard-test/src/main/webapp/forward.jsp b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/forward.jsp similarity index 61% rename from csrfguard-test/src/main/webapp/forward.jsp rename to csrfguard-test/csrfguard-test-jsp/src/main/webapp/forward.jsp index 4b656ef..53e63ab 100644 --- a/csrfguard-test/src/main/webapp/forward.jsp +++ b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/forward.jsp @@ -1,12 +1,11 @@ -<%@ page language="java" contentType="text/html; charset=ISO-8859-1" - pageEncoding="ISO-8859-1"%> +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1" %> - -Forward Test + + Forward Test - \ No newline at end of file + diff --git a/csrfguard-test/csrfguard-test-jsp/src/main/webapp/index.html b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/index.html new file mode 100644 index 0000000..58e725a --- /dev/null +++ b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/index.html @@ -0,0 +1,37 @@ + + + + + CSRFGuard Test Application + + +Welcome to the OWASP CSRFGuard Test Application! Where would you like to go? +
+Tests: + +
+ +Attempt CSRF attacks against the /counter endpoint:
+

Mimic hosting the exploits on a different domain:

+ +
+ +Utilities: + + + diff --git a/csrfguard-test/csrfguard-test-jsp/src/main/webapp/javascript.html b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/javascript.html new file mode 100644 index 0000000..b11f044 --- /dev/null +++ b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/javascript.html @@ -0,0 +1,53 @@ + + + + + + JavaScript Token Injection + + + +

Test Link(s)

+ +
+ +

Test Form(s)

+
+ + +
+

+ +

"Evil" Form(s)

+

Tokens should not be injected into links referencing different domains if the domainStrict property is set to true.

+
+ + +
+

+ + diff --git a/csrfguard-test/csrfguard-test-jsp/src/main/webapp/legacySyncAjaxTest.html b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/legacySyncAjaxTest.html new file mode 100644 index 0000000..ed41600 --- /dev/null +++ b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/legacySyncAjaxTest.html @@ -0,0 +1,29 @@ + + + + + Page for testing legacy synchronous AJAX requests + + + +

Important note:

+

+ The current approach of the OWASP CSRFGuard relies on JavaScript logic for injecting CSRF tokens into HTML elements or XHR requests. + Forcing synchronous loading of the AJAX requests has been disabled, since they were + deprecated + due to their negative impact on the user experience. For this reason, protecting resources that would load + before or in parallel with the JavaScript logic (e.g. references IFrames or IMG tags) is not possible. + In most cases this should not be a problem, because usually GET requests should not facilitate state-changing operations. + If this last condition cannot be fulfilled (e.g. for legacy applications), backwards compatibility can be achieved by enabling the + "forceSynchronousAjax" property within the configurations, until there is browser support for it. +

+

IFrame

+

Aims to test token injection for referenced protected pages that are loaded before user interaction.

+ +

+ +

Image Tag

+

Aims to test token injection for referenced protected pages that are loaded before user interaction.

+ OWASP logo + + diff --git a/csrfguard-test/csrfguard-test-jsp/src/main/webapp/owasp_logo.png b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/owasp_logo.png new file mode 100644 index 0000000..b0af38b Binary files /dev/null and b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/owasp_logo.png differ diff --git a/csrfguard-test/src/main/webapp/protect.html b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/protect.html similarity index 60% rename from csrfguard-test/src/main/webapp/protect.html rename to csrfguard-test/csrfguard-test-jsp/src/main/webapp/protect.html index 447606d..6fa151c 100644 --- a/csrfguard-test/src/main/webapp/protect.html +++ b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/protect.html @@ -1,10 +1,10 @@ - + - -Protect + + Protect This is a resource that should be protected from CSRF attacks. - \ No newline at end of file + diff --git a/csrfguard-test/src/main/webapp/redirect.jsp b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/redirect.jsp similarity index 51% rename from csrfguard-test/src/main/webapp/redirect.jsp rename to csrfguard-test/csrfguard-test-jsp/src/main/webapp/redirect.jsp index 604f1f7..9994054 100644 --- a/csrfguard-test/src/main/webapp/redirect.jsp +++ b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/redirect.jsp @@ -1,14 +1,13 @@ -<%@ page language="java" contentType="text/html; charset=ISO-8859-1" - pageEncoding="ISO-8859-1"%> +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1" %> - -Redirect Test + + Redirect Test <% -response.sendRedirect("protect.html"); + response.sendRedirect("protect.html"); %> - \ No newline at end of file + diff --git a/csrfguard-test/csrfguard-test-jsp/src/main/webapp/regextest/protected.html b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/regextest/protected.html new file mode 100644 index 0000000..3b892d0 --- /dev/null +++ b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/regextest/protected.html @@ -0,0 +1,10 @@ + + + + + This page is meant to test protected page setup with regular expressions. + + +This page is meant to test protected page setup with regular expressions. + + \ No newline at end of file diff --git a/csrfguard-test/csrfguard-test-jsp/src/main/webapp/regextest/protected.txt b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/regextest/protected.txt new file mode 100644 index 0000000..39dd5e9 --- /dev/null +++ b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/regextest/protected.txt @@ -0,0 +1,11 @@ +Everything under /regextest/ that starts with protected should be protected unless it's .txt + +see: isProtectEnabled() + +protected: +^/regextest/protected\..*$ +^/regextest/.*/protected\.html$ + +unprotected: +^/regextest/.*\.txt$ +^/regextest/.*/.*\.txt$ diff --git a/csrfguard-test/csrfguard-test-jsp/src/main/webapp/regextest/resources/protected.html b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/regextest/resources/protected.html new file mode 100644 index 0000000..3b892d0 --- /dev/null +++ b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/regextest/resources/protected.html @@ -0,0 +1,10 @@ + + + + + This page is meant to test protected page setup with regular expressions. + + +This page is meant to test protected page setup with regular expressions. + + \ No newline at end of file diff --git a/csrfguard-test/csrfguard-test-jsp/src/main/webapp/regextest/resources/protected.txt b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/regextest/resources/protected.txt new file mode 100644 index 0000000..e69de29 diff --git a/csrfguard-test/csrfguard-test-jsp/src/main/webapp/regextest/resources/unprotected.html b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/regextest/resources/unprotected.html new file mode 100644 index 0000000..4375aa5 --- /dev/null +++ b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/regextest/resources/unprotected.html @@ -0,0 +1,10 @@ + + + + + This page is meant to test un-protected page setup with regular expressions. + + +This page is meant to test un-protected page setup with regular expressions. + + \ No newline at end of file diff --git a/csrfguard-test/csrfguard-test-jsp/src/main/webapp/regextest/unprotected.html b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/regextest/unprotected.html new file mode 100644 index 0000000..4375aa5 --- /dev/null +++ b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/regextest/unprotected.html @@ -0,0 +1,10 @@ + + + + + This page is meant to test un-protected page setup with regular expressions. + + +This page is meant to test un-protected page setup with regular expressions. + + \ No newline at end of file diff --git a/csrfguard-test/csrfguard-test-jsp/src/main/webapp/session.jsp b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/session.jsp new file mode 100644 index 0000000..2712e30 --- /dev/null +++ b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/session.jsp @@ -0,0 +1,19 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1" %> + + + + + Session Utilities + + +<% + final String action = request.getParameter("action"); + + if ("invalidate".equals(action)) { + session.invalidate(); + request.getSession(true); +%>Session Invalidated!<% + } +%> + + diff --git a/csrfguard-test/src/main/webapp/tag.jsp b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/tag.jsp similarity index 95% rename from csrfguard-test/src/main/webapp/tag.jsp rename to csrfguard-test/csrfguard-test-jsp/src/main/webapp/tag.jsp index cda799a..db66265 100644 --- a/csrfguard-test/src/main/webapp/tag.jsp +++ b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/tag.jsp @@ -20,6 +20,7 @@

Test Form(s)

+Used token rotation is not supported with JSPs.
@@ -30,4 +31,4 @@ - \ No newline at end of file + diff --git a/csrfguard-test/csrfguard-test-jsp/src/main/webapp/upload.html b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/upload.html new file mode 100644 index 0000000..843c88d --- /dev/null +++ b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/upload.html @@ -0,0 +1,15 @@ + + + + + File Upload Example + + + +
+ +
+ + + + diff --git a/csrfguard-test/csrfguard-test-jsp/src/main/webapp/wildcardtest/test.html b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/wildcardtest/test.html new file mode 100644 index 0000000..bcdee64 --- /dev/null +++ b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/wildcardtest/test.html @@ -0,0 +1,10 @@ + + + + + This page is meant to test protected page setup using wildcards. + + +This page is meant to test protected page setup using wildcards. + + \ No newline at end of file diff --git a/csrfguard-test/csrfguard-test-jsp/src/main/webapp/wildcardtest/test.txt b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/wildcardtest/test.txt new file mode 100644 index 0000000..ae2d16c --- /dev/null +++ b/csrfguard-test/csrfguard-test-jsp/src/main/webapp/wildcardtest/test.txt @@ -0,0 +1,11 @@ +everything under /regextest/ that starts with protected should be protected unless it's .txt + +see: isProtectEnabled() + +protected: +^/regextest/protected\..*$ +^/regextest/.*/protected\.html$ + +unprotected: +^/regextest/.*\.txt$ +^/regextest/.*/.*\.txt$ diff --git a/csrfguard-test/misc/eclipse/README.txt b/csrfguard-test/misc/eclipse/README.txt deleted file mode 100644 index e5384b5..0000000 --- a/csrfguard-test/misc/eclipse/README.txt +++ /dev/null @@ -1 +0,0 @@ -These files put in the csrfguard-test dir work for eclipse kepler and m2e maven plugin \ No newline at end of file diff --git a/csrfguard-test/pom.xml b/csrfguard-test/pom.xml index 37a3d55..10c88c4 100644 --- a/csrfguard-test/pom.xml +++ b/csrfguard-test/pom.xml @@ -1,148 +1,63 @@ + + + - 4.0.0 - org.owasp - csrfguard-test - 3.1.0-SNAPSHOT - war - OWASP CSRFGuard Test Application - OWASP CSRFGuard is a library that implements a variant of the synchronizer token pattern to mitigate the risk of Cross-Site Request Forgery (CSRF) attacks. - https://www.owasp.org/index.php/Category:OWASP_CSRFGuard_Project - - OWASP - http://www.owasp.org - - - - BSD License - http://www.opensource.org/licenses/bsd-license.php - - - - https://github.com/esheri3/OWASP-CSRFGuard - https://github.com/esheri3/OWASP-CSRFGuard.git - - - - esheri3 - Eric Sheridan - eric@infraredsecurity.com - - - - UTF-8 - - - - javax.servlet - servlet-api - 2.5 - provided - - - javax.servlet.jsp - jsp-api - 2.1 - provided - - - org.owasp - csrfguard - ${project.version} - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.1 - - true - true - true - 1.6 - 1.6 - true - - - - org.apache.maven.plugins - maven-jar-plugin - 2.2 - - - - true - false - - - Eric Sheridan (eric@infraredsecurity.com) - ${project.url} - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.9 - - - - - javadoc-jar - package - - jar - - - - - - org.apache.maven.plugins - maven-source-plugin - 2.2.1 - - UTF-8 - UTF-8 - - - true - false - - - Eric Sheridan (eric@infraredsecurity.com) - ${project.url} - - - - - - attach-sources - package - - jar-no-fork - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.12.4 - - true - - - - org.apache.tomcat.maven - tomcat7-maven-plugin - 2.1 - - / - 8000 - - - - + 4.0.0 + + + org.owasp + csrfguard-parent + 4.0.2-SNAPSHOT + + + csrfguard-test + OWASP CSRFGuard Test Parent POM + pom + + + csrfguard-test-jsp + + + + + + ${project.groupId} + csrfguard + ${project.version} + + + + ${project.groupId} + csrfguard-extension-session + ${project.version} + + + diff --git a/csrfguard-test/src/main/java/org/owasp/csrfguard/test/HelloServlet.java b/csrfguard-test/src/main/java/org/owasp/csrfguard/test/HelloServlet.java deleted file mode 100644 index ac3e9b6..0000000 --- a/csrfguard-test/src/main/java/org/owasp/csrfguard/test/HelloServlet.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.owasp.csrfguard.test; - -import java.io.IOException; -import java.io.PrintWriter; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -/** - * Servlet implementation class HelloServlet - */ -public class HelloServlet extends HttpServlet { - private static final long serialVersionUID = 1L; - - /** - * Default constructor. - */ - public HelloServlet() { - // TODO Auto-generated constructor stub - } - - /** - * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) - */ - @Override - protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - doPost(request, response); - } - - /** - * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) - */ - @Override - protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - response.setContentType("text/plain"); - - PrintWriter writer = new PrintWriter(response.getOutputStream()); - writer.println("Hello World!"); - writer.close(); - } - -} diff --git a/csrfguard-test/src/main/webapp/WEB-INF/classes/Owasp.CsrfGuard.overlay.properties b/csrfguard-test/src/main/webapp/WEB-INF/classes/Owasp.CsrfGuard.overlay.properties deleted file mode 100644 index 104a423..0000000 --- a/csrfguard-test/src/main/webapp/WEB-INF/classes/Owasp.CsrfGuard.overlay.properties +++ /dev/null @@ -1,17 +0,0 @@ - -org.owasp.csrfguard.configuration.provider.factory=org.owasp.csrfguard.config.overlay.ConfigurationOverlayProviderFactory - -org.owasp.csrfguard.JavascriptServlet.refererPattern = http://localhost:80.* - -org.owasp.csrfguard.unprotected.Default=%servletContext%/ -org.owasp.csrfguard.unprotected.Upload=%servletContext%/upload.html -org.owasp.csrfguard.unprotected.JavaScriptServlet=%servletContext%/JavaScriptServlet -org.owasp.csrfguard.unprotected.Ajax=%servletContext%/ajax.html -org.owasp.csrfguard.unprotected.Error=%servletContext%/error.html -org.owasp.csrfguard.unprotected.Index=%servletContext%/index.html -org.owasp.csrfguard.unprotected.JavaScript=%servletContext%/javascript.html -org.owasp.csrfguard.unprotected.Tag=%servletContext%/tag.jsp -org.owasp.csrfguard.unprotected.Redirect=%servletContext%/redirect.jsp -org.owasp.csrfguard.unprotected.Forward=%servletContext%/forward.jsp -org.owasp.csrfguard.unprotected.Session=%servletContext%/session.jsp -org.owasp.csrfguard.unprotected.Favicon=%servletContext%/favicon.ico diff --git a/csrfguard-test/src/main/webapp/ajax.html b/csrfguard-test/src/main/webapp/ajax.html deleted file mode 100644 index 867298d..0000000 --- a/csrfguard-test/src/main/webapp/ajax.html +++ /dev/null @@ -1,75 +0,0 @@ - - - - -Ajax Header Verification - - - -

Test Link(s)

- -
-

Test Form(s)

-
- - -
-

Dom Test

-
- - - - \ No newline at end of file diff --git a/csrfguard-test/src/main/webapp/index.html b/csrfguard-test/src/main/webapp/index.html deleted file mode 100644 index a098fd4..0000000 --- a/csrfguard-test/src/main/webapp/index.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - -CSRFGuard Test Application - - -Welcome to the OWASP CSRFGuard Test Application! Where would you like to go? -
-Tests: - -
-Utilities: - - - \ No newline at end of file diff --git a/csrfguard-test/src/main/webapp/javascript.html b/csrfguard-test/src/main/webapp/javascript.html deleted file mode 100644 index fc4bdd0..0000000 --- a/csrfguard-test/src/main/webapp/javascript.html +++ /dev/null @@ -1,41 +0,0 @@ - - - - -JavaScript Token Injection - - -

Test Link(s)

- -
-

Test Form(s)

-
- - -
- -
-
-

Evil Form(s)

-
- - -
-
-
-

IFrame

- -
-
-

Image Tag

- - - - - - \ No newline at end of file diff --git a/csrfguard-test/src/main/webapp/script/csrfguard.js b/csrfguard-test/src/main/webapp/script/csrfguard.js deleted file mode 100644 index 78c57f5..0000000 --- a/csrfguard-test/src/main/webapp/script/csrfguard.js +++ /dev/null @@ -1,450 +0,0 @@ -/** - * The OWASP CSRFGuard Project, BSD License - * Eric Sheridan (eric@infraredsecurity.com), Copyright (c) 2011 - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of OWASP nor the names of its contributors may be used - * to endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -(function() { - /** - * Code to ensure our event always gets triggered when the DOM is updated. - * @param obj - * @param type - * @param fn - * @source http://www.dustindiaz.com/rock-solid-addevent/ - */ - function addEvent( obj, type, fn ) { - if (obj.addEventListener) { - obj.addEventListener( type, fn, false ); - EventCache.add(obj, type, fn); - } - else if (obj.attachEvent) { - obj["e"+type+fn] = fn; - obj[type+fn] = function() { obj["e"+type+fn]( window.event ); } - obj.attachEvent( "on"+type, obj[type+fn] ); - EventCache.add(obj, type, fn); - } - else { - obj["on"+type] = obj["e"+type+fn]; - } - } - - var EventCache = function(){ - var listEvents = []; - return { - listEvents : listEvents, - add : function(node, sEventName, fHandler){ - listEvents.push(arguments); - }, - flush : function(){ - var i, item; - for(i = listEvents.length - 1; i >= 0; i = i - 1){ - item = listEvents[i]; - if(item[0].removeEventListener){ - item[0].removeEventListener(item[1], item[2], item[3]); - }; - if(item[1].substring(0, 2) != "on"){ - item[1] = "on" + item[1]; - }; - if(item[0].detachEvent){ - item[0].detachEvent(item[1], item[2]); - }; - }; - } - }; - }(); - - /** string utility functions **/ - function startsWith(s, prefix) { - return s.indexOf(prefix) === 0; - } - - function endsWith(s, suffix) { - return s.substring(s.length - suffix.length) === suffix; - } - - /** hook using standards based prototype **/ - function hijackStandard() { - XMLHttpRequest.prototype._open = XMLHttpRequest.prototype.open; - XMLHttpRequest.prototype.open = function(method, url, async, user, pass) { - this.url = url; - - this._open.apply(this, arguments); - }; - - XMLHttpRequest.prototype._send = XMLHttpRequest.prototype.send; - XMLHttpRequest.prototype.send = function(data) { - if(this.onsend != null) { - this.onsend.apply(this, arguments); - } - - this._send.apply(this, arguments); - }; - } - - /** ie does not properly support prototype - wrap completely **/ - function hijackExplorer() { - var _XMLHttpRequest = window.XMLHttpRequest; - - function alloc_XMLHttpRequest() { - this.base = _XMLHttpRequest ? new _XMLHttpRequest : new window.ActiveXObject("Microsoft.XMLHTTP"); - } - - function init_XMLHttpRequest() { - return new alloc_XMLHttpRequest; - } - - init_XMLHttpRequest.prototype = alloc_XMLHttpRequest.prototype; - - /** constants **/ - init_XMLHttpRequest.UNSENT = 0; - init_XMLHttpRequest.OPENED = 1; - init_XMLHttpRequest.HEADERS_RECEIVED = 2; - init_XMLHttpRequest.LOADING = 3; - init_XMLHttpRequest.DONE = 4; - - /** properties **/ - init_XMLHttpRequest.prototype.status = 0; - init_XMLHttpRequest.prototype.statusText = ""; - init_XMLHttpRequest.prototype.readyState = init_XMLHttpRequest.UNSENT; - init_XMLHttpRequest.prototype.responseText = ""; - init_XMLHttpRequest.prototype.responseXML = null; - init_XMLHttpRequest.prototype.onsend = null; - - init_XMLHttpRequest.url = null; - init_XMLHttpRequest.onreadystatechange = null; - - /** methods **/ - init_XMLHttpRequest.prototype.open = function(method, url, async, user, pass) { - var self = this; - this.url = url; - - this.base.onreadystatechange = function() { - try { self.status = self.base.status; } catch (e) { } - try { self.statusText = self.base.statusText; } catch (e) { } - try { self.readyState = self.base.readyState; } catch (e) { } - try { self.responseText = self.base.responseText; } catch(e) { } - try { self.responseXML = self.base.responseXML; } catch(e) { } - - if(self.onreadystatechange != null) { - self.onreadystatechange.apply(this, arguments); - } - } - - this.base.open(method, url, async, user, pass); - }; - - init_XMLHttpRequest.prototype.send = function(data) { - if(this.onsend != null) { - this.onsend.apply(this, arguments); - } - - this.base.send(data); - }; - - init_XMLHttpRequest.prototype.abort = function() { - this.base.abort(); - }; - - init_XMLHttpRequest.prototype.getAllResponseHeaders = function() { - return this.base.getAllResponseHeaders(); - }; - - init_XMLHttpRequest.prototype.getResponseHeader = function(name) { - return this.base.getResponseHeader(name); - }; - - init_XMLHttpRequest.prototype.setRequestHeader = function(name, value) { - return this.base.setRequestHeader(name, value); - }; - - /** hook **/ - window.XMLHttpRequest = init_XMLHttpRequest; - } - - /** check if valid domain based on domainStrict **/ - function isValidDomain(current, target) { - var result = false; - - /** check exact or subdomain match **/ - if(current == target) { - result = true; - } else if(%DOMAIN_STRICT% == false) { - if(target.charAt(0) == '.') { - result = endsWith(current, target); - } else { - result = endsWith(current, '.' + target); - } - } - - return result; - } - - /** determine if uri/url points to valid domain **/ - function isValidUrl(src) { - var result = false; - - /** parse out domain to make sure it points to our own **/ - if(src.substring(0, 7) == "http://" || src.substring(0, 8) == "https://") { - var token = "://"; - var index = src.indexOf(token); - var part = src.substring(index + token.length); - var domain = ""; - - /** parse up to end, first slash, or anchor **/ - for(var i=0; i 0) { - part = url.substring(index + token.length); - } else if(url.charAt(0) != '/') { - part = "%CONTEXT_PATH%/" + url; - } else { - part = url; - } - - /** parse up to end or query string **/ - var uriContext = (index == -1); - - for(var i=0; i