Repository: dschadow/Java-Web-Security Branch: main Commit: b34e8f6a4758 Files: 158 Total size: 226.7 KB Directory structure: gitextract_58dy3jvz/ ├── .github/ │ ├── dependabot.yml │ └── workflows/ │ └── maven.yml ├── .gitignore ├── Ch04_OutputEscaping/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── resources/ │ │ └── ESAPI.properties │ └── webapp/ │ ├── index.jsp │ ├── resources/ │ │ └── css/ │ │ └── styles.css │ ├── withOutputEscaping.jsp │ └── withoutOutputEscaping.jsp ├── Ch04_OutputEscapingJSF/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── de/ │ │ └── dominikschadow/ │ │ └── webappsecurity/ │ │ └── ContactController.java │ └── webapp/ │ ├── WEB-INF/ │ │ ├── faces-config.xml │ │ └── web.xml │ ├── contact.xhtml │ ├── index.xhtml │ └── resources/ │ └── css/ │ └── styles.css ├── Ch04_OutputEscapingJSP/ │ ├── pom.xml │ └── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── de/ │ │ │ └── dominikschadow/ │ │ │ └── webappsecurity/ │ │ │ ├── OutputEscapingWebAppInitializer.java │ │ │ ├── WebConfig.java │ │ │ ├── controller/ │ │ │ │ ├── ContactController.java │ │ │ │ └── IndexController.java │ │ │ └── domain/ │ │ │ └── Contact.java │ │ ├── resources/ │ │ │ └── logback.xml │ │ └── webapp/ │ │ ├── WEB-INF/ │ │ │ └── views/ │ │ │ ├── contact.jsp │ │ │ └── index.jsp │ │ └── resources/ │ │ └── styles.css │ └── test/ │ └── java/ │ └── de/ │ └── dominikschadow/ │ └── webappsecurity/ │ └── controller/ │ ├── ContactControllerTest.java │ └── IndexControllerTest.java ├── Ch05_AccessReferenceMaps/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── de/ │ │ └── dominikschadow/ │ │ └── webappsecurity/ │ │ ├── AccountController.java │ │ ├── AccountIntegerController.java │ │ ├── AccountRandomController.java │ │ ├── AccountsDAO.java │ │ ├── AccountsIntegerDAO.java │ │ ├── AccountsRandomDAO.java │ │ ├── HibernateUtil.java │ │ └── domain/ │ │ ├── Account.java │ │ └── User.java │ ├── resources/ │ │ ├── ESAPI.properties │ │ ├── context.xml │ │ ├── hibernate.cfg.xml │ │ ├── import.sql │ │ └── logback.xml │ └── webapp/ │ ├── WEB-INF/ │ │ ├── faces-config.xml │ │ └── web.xml │ ├── account.xhtml │ ├── accountInteger.xhtml │ ├── accountRandom.xhtml │ ├── index.xhtml │ └── resources/ │ └── css/ │ └── styles.css ├── Ch05_HSTS/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── de/ │ │ └── dominikschadow/ │ │ └── webappsecurity/ │ │ ├── filter/ │ │ │ └── HSTSFilter.java │ │ └── servlets/ │ │ └── LoginServlet.java │ ├── resources/ │ │ └── logback.xml │ └── webapp/ │ ├── WEB-INF/ │ │ └── web.xml │ ├── index.jsp │ └── styles.css ├── Ch05_SessionFixation/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── de/ │ │ └── dominikschadow/ │ │ └── webappsecurity/ │ │ └── servlets/ │ │ └── LoginServlet.java │ ├── resources/ │ │ ├── context.xml │ │ └── logback.xml │ └── webapp/ │ ├── index.jsp │ └── styles.css ├── Ch05_SessionHandling/ │ ├── pom.xml │ └── src/ │ └── main/ │ └── webapp/ │ ├── WEB-INF/ │ │ ├── faces-config.xml │ │ └── web.xml │ ├── index.xhtml │ └── resources/ │ └── css/ │ └── styles.css ├── Ch06_SQLInjection/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── de/ │ │ └── dominikschadow/ │ │ └── webappsecurity/ │ │ ├── domain/ │ │ │ └── Customer.java │ │ └── servlets/ │ │ ├── CustomerTable.java │ │ ├── HQLServlet.java │ │ ├── HibernateUtil.java │ │ ├── InitDbServlet.java │ │ ├── PreparedStatementServlet.java │ │ ├── StatementEscapingServlet.java │ │ └── StatementServlet.java │ ├── resources/ │ │ ├── ESAPI.properties │ │ ├── context.xml │ │ ├── hibernate.cfg.xml │ │ ├── import.sql │ │ └── logback.xml │ └── webapp/ │ ├── index.jsp │ └── styles.css ├── Ch06_XPathInjection/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── de/ │ │ └── dominikschadow/ │ │ └── webappsecurity/ │ │ └── servlets/ │ │ ├── XPathEscapingServlet.java │ │ └── XPathServlet.java │ ├── resources/ │ │ ├── ESAPI.properties │ │ ├── customer.xml │ │ └── logback.xml │ └── webapp/ │ ├── index.jsp │ └── styles.css ├── Ch07_CSP/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── de/ │ │ └── dominikschadow/ │ │ └── webappsecurity/ │ │ ├── CSPReporting.java │ │ ├── WithCSPReportingServlet.java │ │ ├── WithCSPServlet.java │ │ └── WithoutCSPServlet.java │ ├── resources/ │ │ └── logback.xml │ └── webapp/ │ ├── index.jsp │ └── styles.css ├── Ch07_XSS/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── de/ │ │ └── dominikschadow/ │ │ └── webappsecurity/ │ │ ├── beans/ │ │ │ ├── CustomerController.java │ │ │ └── SearchController.java │ │ ├── daos/ │ │ │ ├── CustomerDAO.java │ │ │ └── HibernateUtil.java │ │ └── domain/ │ │ └── Customer.java │ ├── resources/ │ │ ├── context.xml │ │ ├── hibernate.cfg.xml │ │ ├── import.sql │ │ └── logback.xml │ └── webapp/ │ ├── WEB-INF/ │ │ ├── faces-config.xml │ │ └── web.xml │ ├── createCustomer.xhtml │ ├── index.xhtml │ ├── resources/ │ │ └── css/ │ │ └── styles.css │ ├── search.xhtml │ ├── searchCustomer.xhtml │ └── showCustomers.xhtml ├── Ch07_XSSFilter/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── de/ │ │ └── dominikschadow/ │ │ └── webappsecurity/ │ │ └── filter/ │ │ ├── BlacklistFilter.java │ │ ├── BlacklistRequestWrapper.java │ │ ├── ESAPIFilter.java │ │ └── ESAPIRequestWrapper.java │ ├── resources/ │ │ └── ESAPI.properties │ └── webapp/ │ ├── WEB-INF/ │ │ └── web.xml │ ├── index.jsp │ ├── outputBlacklist.jsp │ ├── outputEsapi.jsp │ └── resources/ │ └── css/ │ └── styles.css ├── Ch07_XSSJSF/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── de/ │ │ └── dominikschadow/ │ │ └── webappsecurity/ │ │ ├── MaximumController.java │ │ ├── StandardController.java │ │ └── Status.java │ └── webapp/ │ ├── WEB-INF/ │ │ ├── faces-config.xml │ │ └── web.xml │ ├── index.xhtml │ ├── maximum.xhtml │ ├── resources/ │ │ └── css/ │ │ └── styles.css │ └── standard.xhtml ├── Ch08_CSRF/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── de/ │ │ └── dominikschadow/ │ │ └── webappsecurity/ │ │ ├── servlets/ │ │ │ ├── ProtectedServlet.java │ │ │ └── UnprotectedServlet.java │ │ └── token/ │ │ └── CSRFTokenHandler.java │ ├── resources/ │ │ └── logback.xml │ └── webapp/ │ ├── form-protected.html │ ├── form-unprotected.html │ ├── form-working.jsp │ ├── image-protected.html │ ├── image-unprotected.html │ ├── index.jsp │ ├── requests-protected.html │ ├── requests-unprotected.html │ ├── resources/ │ │ └── css/ │ │ └── styles.css │ ├── xmlhttprequest-protected.html │ └── xmlhttprequest-unprotected.html ├── LICENSE ├── README.md └── pom.xml ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/dependabot.yml ================================================ # To get started with Dependabot version updates, you'll need to specify which # package ecosystems to update and where the package manifests are located. # Please see the documentation for all configuration options: # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates version: 2 updates: - package-ecosystem: "maven" # See documentation for possible values directory: "/" # Location of package manifests schedule: interval: "daily" ================================================ FILE: .github/workflows/maven.yml ================================================ name: Build on: push: pull_request: branches: [ main ] jobs: build: runs-on: ubuntu-latest name: JavaWebSecurity Build steps: - name: Checkout uses: actions/checkout@v5 - name: Configure Java for Build uses: actions/setup-java@v5 with: distribution: 'temurin' java-version: '17' cache: 'maven' - name: Build with Maven run: mvn -B package --file pom.xml ================================================ FILE: .gitignore ================================================ *.class .idea .classpath .project .DS_Store */target* target/ .settings* # Package Files # *.jar *.war *.ear *.iml *.log *.lck .pmd .forge_settings accountsDB.properties customerDB.properties ================================================ FILE: Ch04_OutputEscaping/pom.xml ================================================ 4.0.0 de.dominikschadow.javawebsecurity javawebsecurity 1.0.0 Ch04_OutputEscaping war Chapter 04 - Output Escaping https://github.com/dschadow/Java-Web-Security Chapter 4 Output Escaping sample project. Requires a server like Apache Tomcat or the Maven Tomcat plugin. After starting, open the web application in your browser at http://localhost:8080/Ch04_OutputEscaping javax.servlet javax.servlet-api org.owasp.esapi esapi Ch04_OutputEscaping tomcat7:run-war org.apache.maven.plugins maven-compiler-plugin org.apache.tomcat.maven tomcat7-maven-plugin org.apache.maven.plugins maven-war-plugin false ================================================ FILE: Ch04_OutputEscaping/src/main/resources/ESAPI.properties ================================================ # Logging Logger.ApplicationName=Ch04_OutputEscaping ================================================ FILE: Ch04_OutputEscaping/src/main/webapp/index.jsp ================================================ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> Chapter 04 - Output Escaping

Chapter 04 - Output Escaping

This demo application shows how JavaServer Pages (JSP) can be extended with safe output escaping provided by the OWASP Enterprise Security API (ESAPI). Feel free to enter any attack data like <script>alert('XSS')</script>.

Without Output Escaping
With Output Escaping
================================================ FILE: Ch04_OutputEscaping/src/main/webapp/resources/css/styles.css ================================================ h1 { font-size: 1.5em; } h2 { font-size: 1.2em; } fieldset { width: 450px; font-size: 1.2em; margin-top: 20px; } input { display: inline-block; vertical-align: middle; width: 250px; } input[type=submit] { width: 75px; height: 20px; margin-left: 10px; } label { margin-right: 10px; } ================================================ FILE: Ch04_OutputEscaping/src/main/webapp/withOutputEscaping.jsp ================================================ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="org.owasp.esapi.ESAPI" %> Chapter 04 - Output Escaping

Chapter 04 - Output Escaping

The provided input is printed output escaped. Output escaping is done by the Enterprise Security API (ESAPI) for different contexts. Only HTML is the correct context here, the others are provided for reference only. The input is printed into [] to show its position.

CSS

[<%= ESAPI.encoder().encodeForCSS(request.getParameter("protected")) %>]

HTML

[<%= ESAPI.encoder().encodeForHTML(request.getParameter("protected")) %>]

HTML Attribute

[<%= ESAPI.encoder().encodeForHTMLAttribute(request.getParameter("protected")) %>]

JavaScript

[<%= ESAPI.encoder().encodeForJavaScript(request.getParameter("protected")) %>]

URL

[<%= ESAPI.encoder().encodeForURL(request.getParameter("protected")) %>]

XML

[<%= ESAPI.encoder().encodeForXML(request.getParameter("protected")) %>]

XML Attribute

[<%= ESAPI.encoder().encodeForXMLAttribute(request.getParameter("protected")) %>]

XPath

[<%= ESAPI.encoder().encodeForXPath(request.getParameter("protected")) %>]

Back

================================================ FILE: Ch04_OutputEscaping/src/main/webapp/withoutOutputEscaping.jsp ================================================ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> Chapter 04 - Output Escaping

Chapter 04 - Output Escaping

This is your input without any output escaping at all. The input is printed into [] to show its position.

[<%= request.getParameter("unprotected") %>]

Back

================================================ FILE: Ch04_OutputEscapingJSF/pom.xml ================================================ 4.0.0 de.dominikschadow.javawebsecurity javawebsecurity 1.0.0 Ch04_OutputEscapingJSF war Chapter 04 - JSF Output Escaping https://github.com/dschadow/Java-Web-Security Chapter 4 JSF Output Escaping sample project. Requires a server like Apache Tomcat or the Maven Tomcat plugin. After starting, open the web application in your browser at http://localhost:8080/Ch04_OutputEscapingJSF com.sun.faces jsf-api com.sun.faces jsf-impl Ch04_OutputEscapingJSF tomcat7:run-war org.apache.maven.plugins maven-compiler-plugin org.apache.tomcat.maven tomcat7-maven-plugin ================================================ FILE: Ch04_OutputEscapingJSF/src/main/java/de/dominikschadow/webappsecurity/ContactController.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity; import javax.faces.bean.ManagedBean; import javax.faces.bean.SessionScoped; import java.io.Serial; import java.io.Serializable; /** * Bean representing user input (no additional security related attributes). * * @author Dominik Schadow */ @ManagedBean(name = "contact") @SessionScoped public class ContactController implements Serializable { @Serial private static final long serialVersionUID = 4083596061570021965L; private String firstname; private String lastname; public String getFirstname() { return firstname; } public void setFirstname(String firstname) { this.firstname = firstname; } public String getLastname() { return lastname; } public void setLastname(String lastname) { this.lastname = lastname; } } ================================================ FILE: Ch04_OutputEscapingJSF/src/main/webapp/WEB-INF/faces-config.xml ================================================ ================================================ FILE: Ch04_OutputEscapingJSF/src/main/webapp/WEB-INF/web.xml ================================================ Ch04_OutputEscapingJSF javax.faces.PROJECT_STAGE Development Faces Servlet javax.faces.webapp.FacesServlet 1 Faces Servlet *.xhtml index.xhtml ================================================ FILE: Ch04_OutputEscapingJSF/src/main/webapp/contact.xhtml ================================================ Chapter 04 - JSF Output Escaping

Chapter 04 - JSF Output Escaping

Input displayed with direct value expression

#{contact.firstname} #{contact.lastname}

Input displayed with <h:outputText /> element

Back
================================================ FILE: Ch04_OutputEscapingJSF/src/main/webapp/index.xhtml ================================================ Chapter 04 - JSF Output Escaping

Chapter 04 - JSF Output Escaping

This demo application shows how JavaServer Faces (JSF) handle output escaping with direct value expressions and normal elements/ attributes. Feel free to enter any attack data like <script>alert('XSS')</script>.

================================================ FILE: Ch04_OutputEscapingJSF/src/main/webapp/resources/css/styles.css ================================================ h1 { font-size: 1.5em; } h2 { font-size: 1.2em; } ================================================ FILE: Ch04_OutputEscapingJSP/pom.xml ================================================ 4.0.0 de.dominikschadow.javawebsecurity javawebsecurity 1.0.0 Ch04_OutputEscapingJSP war Chapter 04 - JSP Output Escaping https://github.com/dschadow/Java-Web-Security Chapter 4 JSP Output Escaping sample project. Requires a server like Apache Tomcat or the Maven Tomcat plugin. After starting, open the web application in your browser at http://localhost:8080/Ch04_OutputEscapingJSP org.springframework spring-webmvc javax.servlet javax.servlet-api javax.servlet.jsp javax.servlet.jsp-api javax.servlet jstl ch.qos.logback logback-classic org.springframework spring-test org.junit.jupiter junit-jupiter-engine org.hamcrest hamcrest-library Ch04_OutputEscapingJSP tomcat7:run-war org.apache.maven.plugins maven-compiler-plugin org.apache.maven.plugins maven-war-plugin false org.apache.tomcat.maven tomcat7-maven-plugin ================================================ FILE: Ch04_OutputEscapingJSP/src/main/java/de/dominikschadow/webappsecurity/OutputEscapingWebAppInitializer.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; /** * * @author Dominik Schadow */ public class OutputEscapingWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class[] getRootConfigClasses() { return null; } @Override protected Class[] getServletConfigClasses() { return new Class[]{WebConfig.class}; } @Override protected String[] getServletMappings() { return new String[]{"/"}; } } ================================================ FILE: Ch04_OutputEscapingJSP/src/main/java/de/dominikschadow/webappsecurity/WebConfig.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.view.InternalResourceViewResolver; /** * @author Dominik Schadow */ @Configuration @EnableWebMvc @ComponentScan("de.dominikschadow.webappsecurity.controller") public class WebConfig implements WebMvcConfigurer { @Bean public ViewResolver viewResolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setPrefix("/WEB-INF/views/"); resolver.setSuffix(".jsp"); resolver.setExposeContextBeansAsAttributes(true); return resolver; } @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } } ================================================ FILE: Ch04_OutputEscapingJSP/src/main/java/de/dominikschadow/webappsecurity/controller/ContactController.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity.controller; import de.dominikschadow.webappsecurity.domain.Contact; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.SessionAttributes; /** * * @author Dominik Schadow */ @Controller @SessionAttributes public class ContactController { private static final Logger LOGGER = LoggerFactory.getLogger(ContactController.class); @RequestMapping(value = "/addContact", method = RequestMethod.POST) public String addContact(@ModelAttribute Contact contact, Model model) { LOGGER.info("Contact first name: {}, last name: {}", contact.getFirstname(), contact.getLastname()); model.addAttribute("contact", contact); return "contact"; } } ================================================ FILE: Ch04_OutputEscapingJSP/src/main/java/de/dominikschadow/webappsecurity/controller/IndexController.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import static org.springframework.web.bind.annotation.RequestMethod.GET; /** * Controller to handle GET requests for the home page. * * @author Dominik Schadow */ @Controller @RequestMapping(value = "/") public class IndexController { @RequestMapping(method = GET) public String index() { return "index"; } } ================================================ FILE: Ch04_OutputEscapingJSP/src/main/java/de/dominikschadow/webappsecurity/domain/Contact.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity.domain; /** * * @author Dominik Schadow */ public class Contact { private String firstname; private String lastname; public String getFirstname() { return firstname; } public void setFirstname(String firstname) { this.firstname = firstname; } public String getLastname() { return lastname; } public void setLastname(String lastname) { this.lastname = lastname; } } ================================================ FILE: Ch04_OutputEscapingJSP/src/main/resources/logback.xml ================================================ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n ================================================ FILE: Ch04_OutputEscapingJSP/src/main/webapp/WEB-INF/views/contact.jsp ================================================ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="s" uri="http://www.springframework.org/tags" %> " > Chapter 04 - JSP Output Escaping

Chapter 04 - JSP Output Escaping

Input displayed as direct value expression

${contact.firstname} ${contact.lastname}

Input displayed as out element

Input displayed inside Spring escapeBody element as direct value expression

${contact.firstname} ${contact.lastname}

">Back ================================================ FILE: Ch04_OutputEscapingJSP/src/main/webapp/WEB-INF/views/index.jsp ================================================ <%@ page session="false" %> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> " > Chapter 04 - JSP Output Escaping

Chapter 04 - JSP Output Escaping

This demo application shows how JavaServer Pages (JSP) handle output escaping with direct value expressions and normal elements/ attributes. Feel free to enter any attack data like <script>alert('XSS')</script>.

Add new contact
================================================ FILE: Ch04_OutputEscapingJSP/src/main/webapp/resources/styles.css ================================================ h1 { font-size: 1.5em; } h2 { font-size: 1.2em; } fieldset { width: 600px; font-size: 1.2em; margin-top: 20px; } input { display: inline-block; vertical-align: middle; width: 150px; } input[type=submit] { width: 75px; height: 20px; margin-left: 10px; } label { margin-right: 10px; } ================================================ FILE: Ch04_OutputEscapingJSP/src/test/java/de/dominikschadow/webappsecurity/controller/ContactControllerTest.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity.controller; import org.junit.jupiter.api.Test; import org.springframework.test.web.servlet.MockMvc; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup; /** * * @author Dominik Schadow */ public class ContactControllerTest { @Test public void testContactPage() throws Exception { ContactController controller = new ContactController(); MockMvc mockMvc = standaloneSetup(controller).build(); mockMvc.perform(post("/addContact")).andExpect(view().name("contact")); } } ================================================ FILE: Ch04_OutputEscapingJSP/src/test/java/de/dominikschadow/webappsecurity/controller/IndexControllerTest.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity.controller; import org.junit.jupiter.api.Test; import org.springframework.test.web.servlet.MockMvc; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup; /** * * @author Dominik Schadow */ public class IndexControllerTest { @Test public void testIndexPage() throws Exception { IndexController controller = new IndexController(); MockMvc mockMvc = standaloneSetup(controller).build(); mockMvc.perform(get("/")).andExpect(view().name("index")); } } ================================================ FILE: Ch05_AccessReferenceMaps/pom.xml ================================================ 4.0.0 de.dominikschadow.javawebsecurity javawebsecurity 1.0.0 Ch05_AccessReferenceMaps war Chapter 05 - Access Reference Maps https://github.com/dschadow/Java-Web-Security Chapter 5 Access Reference sample project. Requires a server like Apache Tomcat or the Maven Tomcat plugin. After starting, open the web application in your browser at http://localhost:8080/Ch05_AccessReferenceMaps com.sun.faces jsf-api com.sun.faces jsf-impl org.owasp.esapi esapi com.h2database h2 org.hibernate hibernate-core ch.qos.logback logback-classic Ch05_AccessReferenceMaps tomcat7:run-war org.apache.maven.plugins maven-compiler-plugin org.apache.tomcat.maven tomcat7-maven-plugin ${project.basedir}/src/main/resources/context.xml ================================================ FILE: Ch05_AccessReferenceMaps/src/main/java/de/dominikschadow/webappsecurity/AccountController.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity; import de.dominikschadow.webappsecurity.domain.Account; import javax.faces.bean.ManagedBean; import javax.faces.bean.SessionScoped; import java.io.Serializable; import java.util.ArrayList; import java.util.List; /** * Managed bean to access an account by account id. Does not verify the given account id and therefore does not * provide any protection. * * @author Dominik Schadow */ @ManagedBean(name = "account") @SessionScoped public class AccountController implements Serializable { private Account account; private int userId = 42; private int accountId = 1; private transient AccountsDAO dao; private List accountReferences = new ArrayList<>(); public int getAccountId() { return accountId; } public void setAccountId(int accountId) { this.accountId = accountId; } public int getUserId() { return userId; } public Account getAccount() { return account; } public List getAccountReferences() { return accountReferences; } public AccountController() { dao = new AccountsDAO(); accountReferences = dao.getAccountsForUser(userId); } public String show() { account = dao.loadAccount(accountId); return "account"; } } ================================================ FILE: Ch05_AccessReferenceMaps/src/main/java/de/dominikschadow/webappsecurity/AccountIntegerController.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity; import de.dominikschadow.webappsecurity.domain.Account; import de.dominikschadow.webappsecurity.domain.User; import javax.faces.bean.ManagedBean; import javax.faces.bean.SessionScoped; import java.io.Serializable; import java.util.ArrayList; import java.util.List; /** * Managed bean to access an account by account reference (IntegerAccessReferenceMap). Only accounts belonging to the * current user are contained in this map. * * @author Dominik Schadow */ @ManagedBean(name = "accountInteger") @SessionScoped public class AccountIntegerController implements Serializable { private List accountReferences = new ArrayList<>(); private int iaAccountId = 1; private int userId = 42; private transient AccountsIntegerDAO dao; public int getIaAccountId() { return iaAccountId; } public void setIaAccountId(int iaAccountId) { this.iaAccountId = iaAccountId; } public int getUserId() { return userId; } public Account getAccount() { return dao.retrieveAccount(iaAccountId); } public List getAccountReferences() { return accountReferences; } public AccountIntegerController() { User currentUser = new User(); currentUser.setUserId(userId); dao = new AccountsIntegerDAO(); accountReferences = dao.loadAccountsForUser(currentUser); } public String show() { return "accountInteger"; } } ================================================ FILE: Ch05_AccessReferenceMaps/src/main/java/de/dominikschadow/webappsecurity/AccountRandomController.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity; import de.dominikschadow.webappsecurity.domain.Account; import de.dominikschadow.webappsecurity.domain.User; import javax.faces.bean.ManagedBean; import javax.faces.bean.SessionScoped; import java.io.Serializable; import java.util.ArrayList; import java.util.List; /** * Managed bean to access an account by account reference (RandomAccessReferenceMap). Only accounts belonging to the * current user are contained in this map. * * @author Dominik Schadow */ @ManagedBean(name = "accountRandom") @SessionScoped public class AccountRandomController implements Serializable { private List accountReferences = new ArrayList<>(); private String raAccountId = ""; private int userId = 42; private transient AccountsRandomDAO dao; public String getRaAccountId() { return raAccountId; } public void setRaAccountId(String raAccountId) { this.raAccountId = raAccountId; } public int getUserId() { return userId; } public Account getAccount() { return dao.retrieveAccount(raAccountId); } public List getAccountReferences() { return accountReferences; } public AccountRandomController() { User currentUser = new User(); currentUser.setUserId(userId); dao = new AccountsRandomDAO(); accountReferences = dao.loadAccountsForUser(currentUser); } public String show() { return "accountRandom"; } } ================================================ FILE: Ch05_AccessReferenceMaps/src/main/java/de/dominikschadow/webappsecurity/AccountsDAO.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity; import de.dominikschadow.webappsecurity.domain.Account; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.query.Query; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.List; import static de.dominikschadow.webappsecurity.HibernateUtil.getSessionFactory; /** * Loads accounts from the in-memory-database for the unprotected managed bean. * * @author Dominik Schadow * @see AccountController */ public class AccountsDAO { private static final Logger LOGGER = LoggerFactory.getLogger(AccountsDAO.class); public List getAccountsForUser(int userId) { return queryAccounts(userId); } public Account loadAccount(int id) { return queryAccount(id); } private Account queryAccount(int id) { try (Session session = getSessionFactory().openSession()) { Query query = session.createQuery("FROM Account WHERE accountId = :id"); query.setParameter("id", id); return (Account) query.uniqueResult(); } catch (HibernateException ex) { LOGGER.error(ex.getMessage(), ex); } return null; } private List queryAccounts(int userId) { List accountReferences = new ArrayList<>(); try (Session session = getSessionFactory().openSession()) { Query query = session.createNativeQuery("SELECT accountId FROM account WHERE ownerId = :id"); query.setParameter("id", userId); accountReferences = query.list(); LOGGER.info("Found {} account references", accountReferences.size()); } catch (HibernateException ex) { LOGGER.error(ex.getMessage(), ex); } return accountReferences; } } ================================================ FILE: Ch05_AccessReferenceMaps/src/main/java/de/dominikschadow/webappsecurity/AccountsIntegerDAO.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity; import de.dominikschadow.webappsecurity.domain.Account; import de.dominikschadow.webappsecurity.domain.User; import org.owasp.esapi.errors.AccessControlException; import org.owasp.esapi.reference.IntegerAccessReferenceMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.List; import static de.dominikschadow.webappsecurity.HibernateUtil.queryUserAccounts; /** * Loads accounts from the in-memory-database for the protected managed bean. * * @author Dominik Schadow * @see AccountIntegerController */ public class AccountsIntegerDAO { private IntegerAccessReferenceMap accounts = new IntegerAccessReferenceMap(); private static final Logger LOGGER = LoggerFactory.getLogger(AccountsIntegerDAO.class); public Account retrieveAccount(int accountId) { String accountReference = String.valueOf(accountId); try { return accounts.getDirectReference(accountReference); } catch (AccessControlException ex) { LOGGER.error("Access to " + accountReference + " denied", ex); return null; } } public List loadAccountsForUser(User user) { return queryAccounts(user); } private List queryAccounts(User user) { List ownAccounts = queryUserAccounts(user); LOGGER.info("Found {} account references", ownAccounts.size()); List accountReferences = new ArrayList<>(); for (Account account : ownAccounts) { accounts.addDirectReference(account); accountReferences.add(accounts.getIndirectReference(account)); } return accountReferences; } } ================================================ FILE: Ch05_AccessReferenceMaps/src/main/java/de/dominikschadow/webappsecurity/AccountsRandomDAO.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity; import de.dominikschadow.webappsecurity.domain.Account; import de.dominikschadow.webappsecurity.domain.User; import org.owasp.esapi.errors.AccessControlException; import org.owasp.esapi.reference.RandomAccessReferenceMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.List; import static de.dominikschadow.webappsecurity.HibernateUtil.queryUserAccounts; /** * Loads accounts from the in-memory-database for the protected managed bean. * * @author Dominik Schadow * @see AccountRandomController */ public class AccountsRandomDAO { private RandomAccessReferenceMap accounts = new RandomAccessReferenceMap(); private static final Logger LOGGER = LoggerFactory.getLogger(AccountsRandomDAO.class); public Account retrieveAccount(String accountReference) { try { return accounts.getDirectReference(accountReference); } catch (AccessControlException ex) { LOGGER.error("Access to " + accountReference + " denied", ex); return null; } } public List loadAccountsForUser(User user) { return queryAccounts(user); } private List queryAccounts(User user) { List ownAccounts = queryUserAccounts(user); LOGGER.info("Found {} account references", ownAccounts.size()); List accountReferences = new ArrayList<>(); for (Account account : ownAccounts) { accounts.addDirectReference(account); accountReferences.add(accounts.getIndirectReference(account)); } return accountReferences; } } ================================================ FILE: Ch05_AccessReferenceMaps/src/main/java/de/dominikschadow/webappsecurity/HibernateUtil.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity; import de.dominikschadow.webappsecurity.domain.Account; import de.dominikschadow.webappsecurity.domain.User; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import org.hibernate.query.Query; import java.util.List; /** * @author Dominik Schadow */ public class HibernateUtil { static SessionFactory sessionFactory; /** * Util class, no constructor required. */ private HibernateUtil() { } public static SessionFactory getSessionFactory() { if (sessionFactory == null) { sessionFactory = new Configuration().configure().buildSessionFactory(); } return sessionFactory; } public static List queryUserAccounts(User user) { Session session = getSessionFactory().openSession(); Query query = session.createQuery("FROM Account WHERE ownerId = :id"); query.setParameter("id", user.getUserId()); List accounts = query.list(); session.close(); return accounts; } } ================================================ FILE: Ch05_AccessReferenceMaps/src/main/java/de/dominikschadow/webappsecurity/domain/Account.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity.domain; import javax.persistence.Entity; import javax.persistence.Id; import java.io.Serializable; /** * Simple account object representing one user account. * * @author Dominik Schadow */ @Entity public class Account implements Serializable { @Id private int accountId; private String name; private String type; private int ownerId; public int getAccountId() { return accountId; } public void setAccountId(int accountId) { this.accountId = accountId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getType() { return type; } public void setType(String type) { this.type = type; } public int getOwnerId() { return ownerId; } public void setOwnerId(int ownerId) { this.ownerId = ownerId; } } ================================================ FILE: Ch05_AccessReferenceMaps/src/main/java/de/dominikschadow/webappsecurity/domain/User.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity.domain; import javax.persistence.Entity; import javax.persistence.Id; import java.io.Serializable; /** * Represents a simple user. * * @author Dominik Schadow */ @Entity public class User implements Serializable { @Id private int userId; private String name; public int getUserId() { return userId; } public void setUserId(int userId) { this.userId = userId; } public String getName() { return name; } public void setName(String name) { this.name = name; } } ================================================ FILE: Ch05_AccessReferenceMaps/src/main/resources/ESAPI.properties ================================================ # Logging Logger.ApplicationName=Ch05_AccessReferenceMaps ================================================ FILE: Ch05_AccessReferenceMaps/src/main/resources/context.xml ================================================ ================================================ FILE: Ch05_AccessReferenceMaps/src/main/resources/hibernate.cfg.xml ================================================ org.hibernate.dialect.H2Dialect java:comp/env/mapDS create-drop false ================================================ FILE: Ch05_AccessReferenceMaps/src/main/resources/import.sql ================================================ INSERT INTO ACCOUNT (accountid, name, type, ownerid) VALUES (1, 'Marvin Savings', 'Savings', 42); INSERT INTO ACCOUNT (accountid, name, type, ownerid) VALUES (2, 'Marvin Credit Card',' Credit Card', 42); INSERT INTO ACCOUNT (accountid, name, type, ownerid) VALUES (3, 'Zaphod Savings',' Savings', 55); INSERT INTO ACCOUNT (accountid, name, type, ownerid) VALUES (4, 'Ford Prefect Credit Card', 'Credit Card', 10); INSERT INTO ACCOUNT (accountid, name, type, ownerid) VALUES (5, 'Ford Prefect Savings', 'Savings', 10); ================================================ FILE: Ch05_AccessReferenceMaps/src/main/resources/logback.xml ================================================ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n ================================================ FILE: Ch05_AccessReferenceMaps/src/main/webapp/WEB-INF/faces-config.xml ================================================ ================================================ FILE: Ch05_AccessReferenceMaps/src/main/webapp/WEB-INF/web.xml ================================================ Ch05_AccessReferenceMaps javax.faces.PROJECT_STAGE Development Faces Servlet javax.faces.webapp.FacesServlet 1 Faces Servlet *.xhtml index.xhtml ================================================ FILE: Ch05_AccessReferenceMaps/src/main/webapp/account.xhtml ================================================ Chapter 05 - Access Reference Maps

Chapter 05 - Access Reference Maps

Account details (user id #{account.userId}).

Account name Account type Account id Account owner

No account found

Back

================================================ FILE: Ch05_AccessReferenceMaps/src/main/webapp/accountInteger.xhtml ================================================ Chapter 05 - Access Reference Maps

Chapter 05 - Access Reference Maps

Account details (user id #{accountInteger.userId}).

Account name Account type Account id Account owner

No account found

Back

================================================ FILE: Ch05_AccessReferenceMaps/src/main/webapp/accountRandom.xhtml ================================================ Chapter 05 - Access Reference Maps

Chapter 05 - Access Reference Maps

Account details (user id #{accountRandom.userId}).

Account name Account type Account id Account owner

No account found

Back

================================================ FILE: Ch05_AccessReferenceMaps/src/main/webapp/index.xhtml ================================================ Chapter 05 - Access Reference Maps

Chapter 05 - Access Reference Maps

Your user id is #{account.userId}.

Unprotected

Valid account references for user id #{account.userId} are . All accounts between 1 and 5 are accessible.

Protected by IntegerAccessReferenceMap

Valid account references for user id #{accountInteger.userId} are . Only these accounts are accessible.

Protected by RandomAccessReferenceMap

Valid account references for user id #{accountRandom.userId} are . Only these accounts are accessible.

================================================ FILE: Ch05_AccessReferenceMaps/src/main/webapp/resources/css/styles.css ================================================ .send-button { margin-left: 25px; } h1 { font-size: 1.5em; } h2 { font-size: 1.2em; } ================================================ FILE: Ch05_HSTS/pom.xml ================================================ 4.0.0 javawebsecurity de.dominikschadow.javawebsecurity 1.0.0 Ch05_HSTS war Chapter 05 - HSTS https://github.com/dschadow/Java-Web-Security Chapter 5 HTTP Strict Transport Security (HSTS sample project. Requires a server like Apache Tomcat or the Maven Tomcat plugin. After starting, open the web application in your browser at http://localhost:8080/Ch05_HSTS javax.servlet javax.servlet-api ch.qos.logback logback-classic Ch05_HSTS tomcat7:run-war org.apache.maven.plugins maven-compiler-plugin org.apache.tomcat.maven tomcat7-maven-plugin org.apache.maven.plugins maven-war-plugin false ================================================ FILE: Ch05_HSTS/src/main/java/de/dominikschadow/webappsecurity/filter/HSTSFilter.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity.filter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.*; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * Filter to add the Strict-Transport-Security header to every response. * * @author Dominik Schadow */ public class HSTSFilter implements Filter { private static final Logger LOGGER = LoggerFactory.getLogger(HSTSFilter.class); @Override public void init(FilterConfig filterConfig) { LOGGER.info("HSTSFilter init"); } @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { ((HttpServletResponse) res).setHeader("Strict-Transport-Security", "max-age=12960000; includeSubdomains"); LOGGER.info("Added Strict-Transport-Security header to response"); chain.doFilter(req, res); } @Override public void destroy() { } } ================================================ FILE: Ch05_HSTS/src/main/java/de/dominikschadow/webappsecurity/servlets/LoginServlet.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity.servlets; import java.io.IOException; import java.io.PrintWriter; import java.io.Serial; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Servlet faking a user login. Invalidates the current session (and its session id) and creates a new one afterwards. * * @author Dominik Schadow */ @WebServlet(name = "LoginServlet", urlPatterns = {"/LoginServlet"}) public class LoginServlet extends HttpServlet { private static final Logger LOGGER = LoggerFactory.getLogger(LoginServlet.class); @Serial private static final long serialVersionUID = 1L; @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { String name = request.getParameter("name"); LOGGER.info("Received {} as POST parameter", name); // invalidate the current session request.getSession().invalidate(); // create a new one and continue in the "login" process request.getSession(true); response.setContentType("text/html"); try (PrintWriter out = response.getWriter()) { out.println(""); out.println(""); out.println(""); out.println("

Ch05_HSTS

"); out.println(""); out.println(""); out.println(""); } catch (IOException ex) { LOGGER.error(ex.getMessage(), ex); } } } ================================================ FILE: Ch05_HSTS/src/main/resources/logback.xml ================================================ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n ================================================ FILE: Ch05_HSTS/src/main/webapp/WEB-INF/web.xml ================================================ HSTS HSTSFilter de.dominikschadow.webappsecurity.filter.HSTSFilter HSTSFilter /* index.jsp ================================================ FILE: Ch05_HSTS/src/main/webapp/index.jsp ================================================ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> Chapter 05 - HTTP Strict Transport Security (HSTS)

Chapter 05 - HTTP Strict Transport Security (HSTS)

================================================ FILE: Ch05_HSTS/src/main/webapp/styles.css ================================================ .text-input { width: 250px; } h1 { font-size: 150%; } h2 { font-size: 125%; } td { font-size: 115%; } th { background-color: darkgrey; padding: 2pt; font-weight: bold; font-size: 125%; } ================================================ FILE: Ch05_SessionFixation/pom.xml ================================================ 4.0.0 de.dominikschadow.javawebsecurity javawebsecurity 1.0.0 Ch05_SessionFixation war Chapter 05 - Session Fixation https://github.com/dschadow/Java-Web-Security Chapter 5 Session Fixation sample project. Requires a server like Apache Tomcat or the Maven Tomcat plugin. After starting, open the web application in your browser at http://localhost:8080/Ch05_SessionFixation javax.servlet javax.servlet-api ch.qos.logback logback-classic Ch05_SessionFixation tomcat7:run-war org.apache.maven.plugins maven-compiler-plugin org.apache.tomcat.maven tomcat7-maven-plugin ${project.basedir}/src/main/resources/context.xml org.apache.maven.plugins maven-war-plugin false ================================================ FILE: Ch05_SessionFixation/src/main/java/de/dominikschadow/webappsecurity/servlets/LoginServlet.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity.servlets; import java.io.IOException; import java.io.PrintWriter; import java.io.Serial; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Servlet faking a user login. Invalidates the current session (and its session id) and creates a new one afterwards. * * @author Dominik Schadow */ @WebServlet(name = "LoginServlet", urlPatterns = {"/LoginServlet"}) public class LoginServlet extends HttpServlet { private static final Logger LOGGER = LoggerFactory.getLogger(LoginServlet.class); @Serial private static final long serialVersionUID = 1L; @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { String name = request.getParameter("name"); LOGGER.info("Received {} as POST parameter", name); // invalidate the current session request.getSession().invalidate(); // create a new one and continue in the "login" process request.getSession(true); response.setContentType("text/html"); try (PrintWriter out = response.getWriter()) { out.println(""); out.println(""); out.println(""); out.println("

Ch05_SessionFixation

"); out.println(""); out.println(""); out.println(""); } catch (IOException ex) { LOGGER.error(ex.getMessage(), ex); } } } ================================================ FILE: Ch05_SessionFixation/src/main/resources/context.xml ================================================ ================================================ FILE: Ch05_SessionFixation/src/main/resources/logback.xml ================================================ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n ================================================ FILE: Ch05_SessionFixation/src/main/webapp/index.jsp ================================================ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> Chapter 05 - Session Fixation

Chapter 05 - Session Fixation

================================================ FILE: Ch05_SessionFixation/src/main/webapp/styles.css ================================================ .text-input { width: 250px; } h1 { font-size: 150%; } h2 { font-size: 125%; } td { font-size: 115%; } th { background-color: darkgrey; padding: 2pt; font-weight: bold; font-size: 125%; } ================================================ FILE: Ch05_SessionHandling/pom.xml ================================================ 4.0.0 de.dominikschadow.javawebsecurity javawebsecurity 1.0.0 Ch05_SessionHandling war Chapter 05 - Session Handling https://github.com/dschadow/Java-Web-Security Chapter 5 Session Handling sample project. Requires a server like Apache Tomcat or the Maven Tomcat plugin. After starting, open the web application in your browser at http://localhost:8080/Ch05_SessionHandling com.sun.faces jsf-api com.sun.faces jsf-impl Ch05_SessionHandling tomcat7:run-war org.apache.maven.plugins maven-compiler-plugin org.apache.tomcat.maven tomcat7-maven-plugin ================================================ FILE: Ch05_SessionHandling/src/main/webapp/WEB-INF/faces-config.xml ================================================ ================================================ FILE: Ch05_SessionHandling/src/main/webapp/WEB-INF/web.xml ================================================ Ch05_SessionHandling javax.faces.PROJECT_STAGE Development index.xhtml Faces Servlet javax.faces.webapp.FacesServlet 1 Faces Servlet *.xhtml 30 true COOKIE ================================================ FILE: Ch05_SessionHandling/src/main/webapp/index.xhtml ================================================ Chapter 05 - Session Handling

Chapter 05 - Session Handling

Cookie information in popup is empty because of web.xml protection.

================================================ FILE: Ch05_SessionHandling/src/main/webapp/resources/css/styles.css ================================================ h1 { font-size: 125%; } ================================================ FILE: Ch06_SQLInjection/pom.xml ================================================ 4.0.0 de.dominikschadow.javawebsecurity javawebsecurity 1.0.0 Ch06_SQLInjection war Chapter 06 - SQL Injection https://github.com/dschadow/Java-Web-Security Chapter 6 SQL Injection sample project. Requires a server like Apache Tomcat or the Maven Tomcat plugin. After starting, open the web application in your browser at http://localhost:8080/Ch06_SQLInjection javax.servlet javax.servlet-api com.h2database h2 org.owasp.esapi esapi org.hibernate hibernate-core ch.qos.logback logback-classic Ch06_SQLInjection tomcat7:run-war org.apache.maven.plugins maven-compiler-plugin org.apache.tomcat.maven tomcat7-maven-plugin ${project.basedir}/src/main/resources/context.xml org.apache.maven.plugins maven-war-plugin false ================================================ FILE: Ch06_SQLInjection/src/main/java/de/dominikschadow/webappsecurity/domain/Customer.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity.domain; import javax.persistence.*; /** * @author Dominik Schadow */ @Entity public class Customer { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "cust_id") private int custId; private String name; private String status; @Column(name = "order_limit") private int orderLimit; private String hint; public int getCustId() { return custId; } public void setCustId(int custId) { this.custId = custId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public int getOrderLimit() { return orderLimit; } public void setOrderLimit(int orderLimit) { this.orderLimit = orderLimit; } public String getHint() { return hint; } public void setHint(String hint) { this.hint = hint; } @Override public String toString() { return "ID " + custId + ", Name " + name + ", Status " + status + ", Order Limit " + orderLimit + ", Hint " + hint; } } ================================================ FILE: Ch06_SQLInjection/src/main/java/de/dominikschadow/webappsecurity/servlets/CustomerTable.java ================================================ package de.dominikschadow.webappsecurity.servlets; import de.dominikschadow.webappsecurity.domain.Customer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; /** * Util class to create the customers list and to create the HTML table with all queried customers. * * @author Dominik Schadow */ public class CustomerTable { private static final Logger LOGGER = LoggerFactory.getLogger(CustomerTable.class); public static List extractCustomers(ResultSet rs) throws SQLException { List customers = new ArrayList<>(); while (rs.next()) { Customer customer = new Customer(); customer.setCustId(rs.getInt(1)); customer.setName(rs.getString(2)); customer.setStatus(rs.getString(3)); customer.setOrderLimit(rs.getInt(4)); customers.add(customer); } return customers; } public static void writeCustomers(HttpServletResponse response, String name, List customers) { response.setContentType("text/html"); try (PrintWriter out = response.getWriter()) { out.println(""); out.println(""); out.println(""); out.println("

Chapter 06 - SQL Injection

"); out.println("

Input " + name + "

"); out.println("

Customer Data

"); out.println(""); out.println(""); out.println(""); out.println(""); out.println(""); out.println(""); out.println(""); for (Customer customer : customers) { out.println(""); out.println(""); out.println(""); out.println(""); out.println(""); out.println(""); } out.println("
IDNameStatusOrder Limit
" + customer.getCustId() + "" + customer.getName() + "" + customer.getStatus() + "" + customer.getOrderLimit() + "
"); out.println(""); out.println(""); } catch (IOException ex) { LOGGER.error(ex.getMessage(), ex); } } } ================================================ FILE: Ch06_SQLInjection/src/main/java/de/dominikschadow/webappsecurity/servlets/HQLServlet.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity.servlets; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.query.Query; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import static de.dominikschadow.webappsecurity.servlets.CustomerTable.writeCustomers; import static de.dominikschadow.webappsecurity.servlets.HibernateUtil.getSessionFactory; /** * Servlet using Hibernate Query Language (HQL) to query the in-memory-database. * User input is not modified and used directly in the HQL query. * * @author Dominik Schadow */ @WebServlet(name = "HQLServlet", urlPatterns = {"/HQLServlet"}) public class HQLServlet extends HttpServlet { private static final Logger LOGGER = LoggerFactory.getLogger(HQLServlet.class); @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { String name = request.getParameter("name"); LOGGER.info("Received {} as POST parameter", name); try (Session session = getSessionFactory().openSession()) { Query query = session.createQuery("FROM Customer WHERE name = :name ORDER BY custId"); query.setParameter("name", name); writeCustomers(response, name, query.list()); } catch (HibernateException ex) { LOGGER.error(ex.getMessage(), ex); } } } ================================================ FILE: Ch06_SQLInjection/src/main/java/de/dominikschadow/webappsecurity/servlets/HibernateUtil.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity.servlets; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; /** * @author Dominik Schadow */ public class HibernateUtil { static SessionFactory sessionFactory; /** * Util class, no constructor required. */ private HibernateUtil() { } public static SessionFactory getSessionFactory() { if (sessionFactory == null) { sessionFactory = new Configuration().configure().buildSessionFactory(); } return sessionFactory; } } ================================================ FILE: Ch06_SQLInjection/src/main/java/de/dominikschadow/webappsecurity/servlets/InitDbServlet.java ================================================ package de.dominikschadow.webappsecurity.servlets; import org.hibernate.Session; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import static de.dominikschadow.webappsecurity.servlets.HibernateUtil.getSessionFactory; /** * Servlet to initialize the database with some sample data. * * @author Dominik Schadow */ @WebServlet(name = "InitDbServlet", urlPatterns = {"/"}) public class InitDbServlet extends HttpServlet { @Override public void init() { Session session = getSessionFactory().openSession(); session.close(); } } ================================================ FILE: Ch06_SQLInjection/src/main/java/de/dominikschadow/webappsecurity/servlets/PreparedStatementServlet.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity.servlets; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.sql.*; import static de.dominikschadow.webappsecurity.servlets.CustomerTable.extractCustomers; import static de.dominikschadow.webappsecurity.servlets.CustomerTable.writeCustomers; /** * Servlet using a Prepared Statement to query the in-memory-database. * User input is not modified and used directly in the SQL query. * * @author Dominik Schadow */ @WebServlet(name = "PreparedStatementServlet", urlPatterns = {"/PreparedStatementServlet"}) public class PreparedStatementServlet extends HttpServlet { private static final Logger LOGGER = LoggerFactory.getLogger(PreparedStatementServlet.class); @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { String name = request.getParameter("name"); LOGGER.info("Received {} as POST parameter", name); String query = "SELECT * FROM customer WHERE name = ? ORDER BY CUST_ID"; ResultSet rs = null; try (Connection con = DriverManager.getConnection("jdbc:h2:mem:sqli", "sa", "sa"); PreparedStatement stmt = con.prepareStatement(query)) { stmt.setString(1, name); rs = stmt.executeQuery(); writeCustomers(response, name, extractCustomers(rs)); } catch (SQLException ex) { LOGGER.error(ex.getMessage(), ex); } finally { try { if (rs != null) { rs.close(); } } catch (SQLException ex) { LOGGER.error(ex.getMessage(), ex); } } } } ================================================ FILE: Ch06_SQLInjection/src/main/java/de/dominikschadow/webappsecurity/servlets/StatementEscapingServlet.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity.servlets; import org.owasp.esapi.ESAPI; import org.owasp.esapi.codecs.OracleCodec; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.sql.*; import static de.dominikschadow.webappsecurity.servlets.CustomerTable.extractCustomers; import static de.dominikschadow.webappsecurity.servlets.CustomerTable.writeCustomers; /** * Servlet using a normal Statement to query the in-memory-database. * User input is escaped with ESAPI and used in the SQL query afterwards. * * @author Dominik Schadow */ @WebServlet(name = "StatementEscapingServlet", urlPatterns = {"/StatementEscapingServlet"}) public class StatementEscapingServlet extends HttpServlet { private static final Logger LOGGER = LoggerFactory.getLogger(StatementEscapingServlet.class); @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { String name = request.getParameter("name"); LOGGER.info("Received {} as POST parameter", name); String safeName = ESAPI.encoder().encodeForSQL(new OracleCodec(), name); LOGGER.info("Escaped name is {}", safeName); String query = "SELECT * FROM customer WHERE name = '" + safeName + "' ORDER BY CUST_ID"; LOGGER.info("Final SQL query {}", query); ResultSet rs = null; try (Connection con = DriverManager.getConnection("jdbc:h2:mem:sqli", "sa", "sa"); Statement stmt = con.createStatement()) { rs = stmt.executeQuery(query); writeCustomers(response, name, extractCustomers(rs)); } catch (SQLException ex) { LOGGER.error(ex.getMessage(), ex); } finally { try { if (rs != null) { rs.close(); } } catch (SQLException ex) { LOGGER.error(ex.getMessage(), ex); } } } } ================================================ FILE: Ch06_SQLInjection/src/main/java/de/dominikschadow/webappsecurity/servlets/StatementServlet.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity.servlets; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.sql.*; import static de.dominikschadow.webappsecurity.servlets.CustomerTable.extractCustomers; import static de.dominikschadow.webappsecurity.servlets.CustomerTable.writeCustomers; /** * Servlet using a normal Statement to query the in-memory-database. * User input is not modified and used directly in the SQL query. * * @author Dominik Schadow */ @WebServlet(name = "StatementServlet", urlPatterns = {"/StatementServlet"}) public class StatementServlet extends HttpServlet { private static final Logger LOGGER = LoggerFactory.getLogger(StatementServlet.class); @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { String name = request.getParameter("name"); LOGGER.info("Received {} as POST parameter", name); String query = "SELECT * FROM customer WHERE name = '" + name + "' ORDER BY CUST_ID"; LOGGER.info("Final SQL query {}", query); ResultSet rs = null; try (Connection con = DriverManager.getConnection("jdbc:h2:mem:sqli", "sa", "sa"); Statement stmt = con.createStatement()) { rs = stmt.executeQuery(query); writeCustomers(response, name, extractCustomers(rs)); } catch (SQLException ex) { LOGGER.error(ex.getMessage(), ex); } finally { try { if (rs != null) { rs.close(); } } catch (SQLException ex) { LOGGER.error(ex.getMessage(), ex); } } } } ================================================ FILE: Ch06_SQLInjection/src/main/resources/ESAPI.properties ================================================ # Logging Logger.ApplicationName=Ch06_SQLInjection ================================================ FILE: Ch06_SQLInjection/src/main/resources/context.xml ================================================ ================================================ FILE: Ch06_SQLInjection/src/main/resources/hibernate.cfg.xml ================================================ org.hibernate.dialect.H2Dialect java:comp/env/sqliDS create-drop false ================================================ FILE: Ch06_SQLInjection/src/main/resources/import.sql ================================================ INSERT INTO CUSTOMER (CUST_ID, NAME, STATUS, ORDER_LIMIT, HINT) VALUES (1001, 'Arthur Dent', 'A', 10000, ''); INSERT INTO CUSTOMER (CUST_ID, NAME, STATUS, ORDER_LIMIT, HINT) VALUES (1002, 'Ford Prefect', 'B', 5000, ''); INSERT INTO CUSTOMER (CUST_ID, NAME, STATUS, ORDER_LIMIT, HINT) VALUES (1003, 'Tricia Trillian McMillan', 'C', 1000, ''); INSERT INTO CUSTOMER (CUST_ID, NAME, STATUS, ORDER_LIMIT, HINT) VALUES (1004, 'Zaphod Beeblebrox', 'D', 500, 'President of the Galaxy'); INSERT INTO CUSTOMER (CUST_ID, NAME, STATUS, ORDER_LIMIT, HINT) VALUES (1005, 'Marvin', 'A', 100000, 'Depressive'); INSERT INTO CUSTOMER (CUST_ID, NAME, STATUS, ORDER_LIMIT, HINT) VALUES (1006, 'Slartibartfast', 'D', 100, '42'); ================================================ FILE: Ch06_SQLInjection/src/main/resources/logback.xml ================================================ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n ================================================ FILE: Ch06_SQLInjection/src/main/webapp/index.jsp ================================================ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> Chapter 06 - SQL Injection

Chapter 06 - SQL Injection

You can use different options to access the database. Not every field is attackable by SQL Injection. Valid customers are: Arthur Dent, Ford Prefect, Tricia Trillian McMillan, Zaphod Beeblebrox, Marvin, Slartibartfast

Using Statement

Using Statement with Escaping

Using Prepared Statement

Using Hibernate Query Language (HQL)

================================================ FILE: Ch06_SQLInjection/src/main/webapp/styles.css ================================================ .text-input { width: 250px; } h1 { font-size: 1.5em; } h2 { font-size: 1.2em; } th { background-color: darkgrey; padding: 2pt; font-weight: bold; font-size: 1.1em; } ================================================ FILE: Ch06_XPathInjection/pom.xml ================================================ 4.0.0 de.dominikschadow.javawebsecurity javawebsecurity 1.0.0 Ch06_XPathInjection war Chapter 06 - XPath Injection https://github.com/dschadow/Java-Web-Security Chapter 6 XPath Injection sample project. Requires a server like Apache Tomcat or the Maven Tomcat plugin. After starting, open the web application in your browser at http://localhost:8080/Ch06_XPathInjection javax.servlet javax.servlet-api org.owasp.esapi esapi ch.qos.logback logback-classic Ch06_XPathInjection tomcat7:run-war org.apache.maven.plugins maven-compiler-plugin org.apache.tomcat.maven tomcat7-maven-plugin org.apache.maven.plugins maven-war-plugin false ================================================ FILE: Ch06_XPathInjection/src/main/java/de/dominikschadow/webappsecurity/servlets/XPathEscapingServlet.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity.servlets; import org.owasp.esapi.ESAPI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; /** * Servlet using an XPath expression to query the customer XML document. * User input is escaped before being used in the XPath expression. *

* Use ' or '1' = '1 or '] | /* | /foo[bar=' as password. * * @author Dominik Schadow */ @WebServlet(name = "XPathEscapingServlet", urlPatterns = {"/XPathEscapingServlet"}) public class XPathEscapingServlet extends HttpServlet { private static final Logger LOGGER = LoggerFactory.getLogger(XPathEscapingServlet.class); private static Document doc; @Override public void init() { try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("/customer.xml")) { DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); doc = dBuilder.parse(inputStream); } catch (SAXException | IOException | ParserConfigurationException ex) { LOGGER.error(ex.getMessage(), ex); } } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { String name = request.getParameter("name"); String password = request.getParameter("password"); LOGGER.info("Received {} and {} as parameter", name, password); String safeName = ESAPI.encoder().encodeForXPath(name); String safePassword = ESAPI.encoder().encodeForXPath(password); LOGGER.info("Using safe name {} and {}", safeName, safePassword); String xpathExpression = "/customers/customer[name='" + safeName + "' and @password='" + safePassword + "']/orderLimit"; printOrderLimit(xpathExpression, name, response); } private void printOrderLimit(String xpath, String name, HttpServletResponse response) { LOGGER.info("XPath expression is {}", xpath); try (PrintWriter out = response.getWriter()) { XPathExpression expression = XPathFactory.newInstance().newXPath().compile(xpath); Object result = expression.evaluate(doc, XPathConstants.NODESET); response.setContentType("text/html"); out.println(""); out.println(""); out.println(""); out.println("

Ch06_XPathInjection

"); out.println("

Order limit for " + name + "

"); NodeList nodes = (NodeList) result; for (int i = 0; i < nodes.getLength(); i++) { out.println("

" + nodes.item(i).getTextContent() + "

"); } out.println(""); out.println(""); } catch (XPathExpressionException | IOException ex) { LOGGER.error(ex.getMessage(), ex); } } } ================================================ FILE: Ch06_XPathInjection/src/main/java/de/dominikschadow/webappsecurity/servlets/XPathServlet.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity.servlets; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; /** * Servlet using an XPath expression to query the customer XML document. * User input is not modified and used directly in the XPath expression. *

* Use ' or '1' = '1 or '] | /* | /foo[bar=' as password. * * @author Dominik Schadow */ @WebServlet(name = "XPathServlet", urlPatterns = {"/XPathServlet"}) public class XPathServlet extends HttpServlet { private static final Logger LOGGER = LoggerFactory.getLogger(XPathServlet.class); private static Document doc; @Override public void init() { try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("/customer.xml")) { DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); doc = dBuilder.parse(inputStream); } catch (SAXException | IOException | ParserConfigurationException ex) { LOGGER.error(ex.getMessage(), ex); } } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { String name = request.getParameter("name"); String password = request.getParameter("password"); LOGGER.info("Received {} and {} as parameter", name, password); String xpathExpression = "/customers/customer[name='" + name + "' and @password='" + password + "']/orderLimit"; printOrderLimit(xpathExpression, name, response); } private void printOrderLimit(String xpath, String name, HttpServletResponse response) { LOGGER.info("XPath expression is {}", xpath); try (PrintWriter out = response.getWriter()) { XPathExpression expression = XPathFactory.newInstance().newXPath().compile(xpath); Object result = expression.evaluate(doc, XPathConstants.NODESET); response.setContentType("text/html"); out.println(""); out.println(""); out.println(""); out.println("

Ch06_XPathInjection

"); out.println("

Order limit for " + name + "

"); NodeList nodes = (NodeList) result; for (int i = 0; i < nodes.getLength(); i++) { out.println("

" + nodes.item(i).getTextContent() + "

"); } out.println(""); out.println(""); } catch (XPathExpressionException | IOException ex) { LOGGER.error(ex.getMessage(), ex); } } } ================================================ FILE: Ch06_XPathInjection/src/main/resources/ESAPI.properties ================================================ # Logging Logger.ApplicationName=Ch06_XPathInjection ================================================ FILE: Ch06_XPathInjection/src/main/resources/customer.xml ================================================ Arthur Dent A 10000 Ford Prefect B 5000 Tricia Trillian McMillan C 1000 Zaphod Beeblebrox D 500 Marvin A 100000 Slartibartfast D 100 ================================================ FILE: Ch06_XPathInjection/src/main/resources/logback.xml ================================================ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n ================================================ FILE: Ch06_XPathInjection/src/main/webapp/index.jsp ================================================ Chapter 06 - XPath Injection

Chapter 06 - XPath Injection

Valid customers are: Arthur Dent, Ford Prefect, Tricia Trillian McMillan, Zaphod Beeblebrox, Marvin, Slartibartfast
Password is always their first name.

Without Escaping

 

With Escaping

 
================================================ FILE: Ch06_XPathInjection/src/main/webapp/styles.css ================================================ .text-input { width: 250px; } h1 { font-size: 150%; } h2 { font-size: 125%; } td { font-size: 115%; } th { background-color: darkgrey; padding: 2pt; font-weight: bold; font-size: 125%; } ================================================ FILE: Ch07_CSP/pom.xml ================================================ 4.0.0 de.dominikschadow.javawebsecurity javawebsecurity 1.0.0 Ch07_CSP war Chapter 07 - CSP https://github.com/dschadow/Java-Web-Security Chapter 7 Content Security Policy (CSP) sample project. Requires a server like Apache Tomcat or the Maven Tomcat7 plugin. After starting, open the web application in your browser at http://localhost:8080/Ch07_CSP javax.servlet javax.servlet-api ch.qos.logback logback-classic Ch07_CSP tomcat7:run-war org.apache.maven.plugins maven-compiler-plugin org.apache.tomcat.maven tomcat7-maven-plugin org.apache.maven.plugins maven-war-plugin false ================================================ FILE: Ch07_CSP/src/main/java/de/dominikschadow/webappsecurity/CSPReporting.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.Serial; import java.nio.charset.Charset; /** * Simple CSP-Reporting servlet to receive and print out any JSON style CSP report with violations. * * @author Dominik Schadow */ @WebServlet(name = "CSPReporting", urlPatterns = {"/CSPReporting"}) public class CSPReporting extends HttpServlet { @Serial private static final long serialVersionUID = 1L; private static final Logger LOGGER = LoggerFactory.getLogger(CSPReporting.class); @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { try (BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream(), Charset.defaultCharset()))) { StringBuilder responseBuilder = new StringBuilder(); String inputStr; while ((inputStr = reader.readLine()) != null) { responseBuilder.append(inputStr); } LOGGER.info("\n{}", responseBuilder.toString()); } catch (IOException ex) { LOGGER.error(ex.getMessage(), ex); } } } ================================================ FILE: Ch07_CSP/src/main/java/de/dominikschadow/webappsecurity/WithCSPReportingServlet.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.io.Serial; /** * Servlet which sets the Content-Security-Policy-Report-Only response header and reports * any JavaScript code that would have been stopped by the policy. * * @author Dominik Schadow */ @WebServlet(name = "WithCSPReportingServlet", urlPatterns = {"/WithCSPReportingServlet"}) public class WithCSPReportingServlet extends HttpServlet { @Serial private static final long serialVersionUID = 1L; private static final Logger LOGGER = LoggerFactory.getLogger(WithCSPReportingServlet.class); @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { LOGGER.info("Processing POST request with Content Security Policy Reporting"); String name = request.getParameter("reporting"); LOGGER.info("Received {} as POST parameter", name); response.setContentType("text/html"); // the following line only reports violations and does not block anything response.setHeader("Content-Security-Policy-Report-Only", "default-src 'self'; report-uri CSPReporting"); // use the following line to activate the policy and still report all violations //response.setHeader("Content-Security-Policy", "default-src 'self'; report-uri CSPReporting"); try (PrintWriter out = response.getWriter()) { out.println(""); out.println(""); out.println(""); out.println("

Ch07_CSP

"); out.println("

With Content Security Policy Reporting

"); out.println("

Hello " + name + "

"); out.println(""); out.println(""); } catch (IOException ex) { LOGGER.error(ex.getMessage(), ex); } } } ================================================ FILE: Ch07_CSP/src/main/java/de/dominikschadow/webappsecurity/WithCSPServlet.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.io.Serial; /** * Servlet which sets the Content-Security-Policy response header and stops any JavaScript code entered * in the textfield. * Any entered script-tag will not be rendered any more in the result page. * * @author Dominik Schadow */ @WebServlet(name = "WithCSPServlet", urlPatterns = {"/WithCSPServlet"}) public class WithCSPServlet extends HttpServlet { @Serial private static final long serialVersionUID = 1L; private static final Logger LOGGER = LoggerFactory.getLogger(WithCSPServlet.class); @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { LOGGER.info("Processing POST request with Content Security Policy"); String name = request.getParameter("protected"); LOGGER.info("Received {} as POST parameter", name); response.setContentType("text/html"); response.setHeader("Content-Security-Policy", "default-src 'self'"); // following line enables unsafe inline JavaScript // response.setHeader("Content-Security-Policy", "default-src 'self' 'unsafe-inline'"); try (PrintWriter out = response.getWriter()) { out.println(""); out.println(""); out.println(""); out.println("

Ch07_CSP

"); out.println("

With Content Security Policy

"); out.println("

Hello " + name + "

"); out.println(""); out.println(""); } catch (IOException ex) { LOGGER.error(ex.getMessage(), ex); } } } ================================================ FILE: Ch07_CSP/src/main/java/de/dominikschadow/webappsecurity/WithoutCSPServlet.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.io.Serial; /** * Default servlet without any additional protection. Any entered script-tag will be executed on the result page. * * @author Dominik Schadow */ @WebServlet(name = "WithoutCSPServlet", urlPatterns = {"/WithoutCSPServlet"}) public class WithoutCSPServlet extends HttpServlet { @Serial private static final long serialVersionUID = 1L; private static final Logger LOGGER = LoggerFactory.getLogger(WithoutCSPServlet.class); @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { LOGGER.info("Processing POST request without Content Security Policy"); String name = request.getParameter("unprotected"); LOGGER.info("Received {} as POST parameter", name); response.setContentType("text/html"); try (PrintWriter out = response.getWriter()) { out.println(""); out.println(""); out.println(""); out.println("

Ch07_CSP

"); out.println("

Without Content Security Policy

"); out.println("

Hello " + name + "

"); out.println(""); out.println(""); } catch (IOException ex) { LOGGER.error(ex.getMessage(), ex); } } } ================================================ FILE: Ch07_CSP/src/main/resources/logback.xml ================================================ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n ================================================ FILE: Ch07_CSP/src/main/webapp/index.jsp ================================================ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> Chapter 07 - Content Security Policy (CSP)

Chapter 07 - Content Security Policy (CSP)

Without Content Security Policy

With Content Security Policy

With Content Security Policy Reporting

================================================ FILE: Ch07_CSP/src/main/webapp/styles.css ================================================ .text-input { width: 250px; } h1 { font-size: 150%; } h2 { font-size: 125%; } td { font-size: 115%; } ================================================ FILE: Ch07_XSS/pom.xml ================================================ 4.0.0 de.dominikschadow.javawebsecurity javawebsecurity 1.0.0 Ch07_XSS war Chapter 07 - XSS https://github.com/dschadow/Java-Web-Security Chapter 7 XSS sample project. Requires a server like Apache Tomcat or the Maven Tomcat plugin. After starting, open the web application in your browser at http://localhost:8080/Ch07_XSS com.sun.faces jsf-api com.sun.faces jsf-impl org.hibernate hibernate-core com.h2database h2 ch.qos.logback logback-classic org.apache.commons commons-lang3 Ch07_XSS tomcat7:run-war org.apache.maven.plugins maven-compiler-plugin org.apache.tomcat.maven tomcat7-maven-plugin ${project.basedir}/src/main/resources/context.xml ================================================ FILE: Ch07_XSS/src/main/java/de/dominikschadow/webappsecurity/beans/CustomerController.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity.beans; import de.dominikschadow.webappsecurity.daos.CustomerDAO; import de.dominikschadow.webappsecurity.domain.Customer; import javax.faces.bean.ManagedBean; import javax.faces.bean.RequestScoped; import java.util.List; /** * * @author Dominik Schadow */ @ManagedBean(name = "customer") @RequestScoped public class CustomerController { private Customer customer; private CustomerDAO customerDAO; public CustomerController() { customer = new Customer(); customerDAO = new CustomerDAO(); } public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } public List getCustomers() { return customerDAO.getAllCustomers(); } public String save() { customerDAO.createCustomer(customer); return "showCustomers"; } } ================================================ FILE: Ch07_XSS/src/main/java/de/dominikschadow/webappsecurity/beans/SearchController.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity.beans; import de.dominikschadow.webappsecurity.daos.CustomerDAO; import de.dominikschadow.webappsecurity.domain.Customer; import org.apache.commons.lang3.StringUtils; import javax.faces.bean.ManagedBean; import javax.faces.bean.RequestScoped; import javax.faces.context.FacesContext; import java.util.List; import java.util.Map; /** * Searches customers by the given customer name. The search string can be passed via * customerName setter method or as a customerName parameter. * * @author Dominik Schadow */ @ManagedBean(name = "search") @RequestScoped public class SearchController { private String customerName; private CustomerDAO customerDAO; private List customers; public SearchController() { customerDAO = new CustomerDAO(); } public String getCustomerName() { return customerName; } public void setCustomerName(String customerName) { this.customerName = customerName; } public List getCustomers() { return customers; } public String search() { if (StringUtils.isEmpty(customerName)) { Map requestMap = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap(); customerName = requestMap.get("customerName"); } Customer search = new Customer(); search.setName(customerName); customers = customerDAO.findCustomers(search); return "searchCustomer"; } } ================================================ FILE: Ch07_XSS/src/main/java/de/dominikschadow/webappsecurity/daos/CustomerDAO.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity.daos; import de.dominikschadow.webappsecurity.domain.Customer; import org.hibernate.Criteria; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.criterion.Restrictions; import org.hibernate.query.Query; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.List; import static de.dominikschadow.webappsecurity.daos.HibernateUtil.getSessionFactory; /** * Loads customers from the in-memory-database for the managed beans. * * @author Dominik Schadow * @see de.dominikschadow.webappsecurity.beans.CustomerController */ public class CustomerDAO { private static final Logger LOGGER = LoggerFactory.getLogger(CustomerDAO.class); public List getAllCustomers() { List customers = new ArrayList<>(); try (Session session = getSessionFactory().openSession()) { Query query = session.createQuery("FROM Customer"); customers = query.list(); LOGGER.info("Found {} customers", customers.size()); } catch (HibernateException ex) { LOGGER.error(ex.getMessage(), ex); } return customers; } public void createCustomer(Customer customer) { try (Session session = getSessionFactory().openSession()) { Transaction tx = session.beginTransaction(); session.persist(customer); tx.commit(); } catch (HibernateException ex) { LOGGER.error(ex.getMessage(), ex); } } public List findCustomers(Customer customer) { List customers = new ArrayList<>(); try (Session session = getSessionFactory().openSession()) { Criteria criteria = session.createCriteria(Customer.class); criteria.add(Restrictions.like("name", "%" + customer.getName() + "%")); customers = criteria.list(); LOGGER.info("Found {} customers", customers.size()); } catch (HibernateException ex) { LOGGER.error(ex.getMessage(), ex); } return customers; } } ================================================ FILE: Ch07_XSS/src/main/java/de/dominikschadow/webappsecurity/daos/HibernateUtil.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity.daos; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; /** * @author Dominik Schadow */ public class HibernateUtil { private static SessionFactory sessionFactory; /** * Util class, no constructor required. */ private HibernateUtil() { } public static SessionFactory getSessionFactory() { if (sessionFactory == null) { sessionFactory = new Configuration().configure().buildSessionFactory(); } return sessionFactory; } } ================================================ FILE: Ch07_XSS/src/main/java/de/dominikschadow/webappsecurity/domain/Customer.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity.domain; import javax.persistence.*; /** * @author Dominik Schadow */ @Entity public class Customer { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "cust_id") private int custId; private String name; private String status; @Column(name = "order_limit") private int orderLimit; private String hint; public int getCustId() { return custId; } public void setCustId(int custId) { this.custId = custId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public int getOrderLimit() { return orderLimit; } public void setOrderLimit(int orderLimit) { this.orderLimit = orderLimit; } public String getHint() { return hint; } public void setHint(String hint) { this.hint = hint; } @Override public String toString() { return "ID " + custId + ", Name " + name + ", Status " + status + ", Order Limit " + orderLimit + ", Hint " + hint; } } ================================================ FILE: Ch07_XSS/src/main/resources/context.xml ================================================ ================================================ FILE: Ch07_XSS/src/main/resources/hibernate.cfg.xml ================================================ org.hibernate.dialect.H2Dialect java:comp/env/xssDS create-drop false ================================================ FILE: Ch07_XSS/src/main/resources/import.sql ================================================ INSERT INTO CUSTOMER (CUST_ID, NAME, STATUS, ORDER_LIMIT, HINT) VALUES (1001, 'Arthur Dent', 'A', 10000, ''); INSERT INTO CUSTOMER (CUST_ID, NAME, STATUS, ORDER_LIMIT, HINT) VALUES (1002, 'Ford Prefect', 'B', 5000, ''); INSERT INTO CUSTOMER (CUST_ID, NAME, STATUS, ORDER_LIMIT, HINT) VALUES (1003, 'Tricia Trillian McMillan', 'C', 1000, ''); INSERT INTO CUSTOMER (CUST_ID, NAME, STATUS, ORDER_LIMIT, HINT) VALUES (1004, 'Zaphod Beeblebrox', 'D', 500, 'President of the Galaxy'); INSERT INTO CUSTOMER (CUST_ID, NAME, STATUS, ORDER_LIMIT, HINT) VALUES (1005, 'Marvin', 'A', 100000, 'Depressive'); INSERT INTO CUSTOMER (CUST_ID, NAME, STATUS, ORDER_LIMIT, HINT) VALUES (1006, 'Slartibartfast', 'D', 100, '42'); INSERT INTO CUSTOMER (CUST_ID, NAME, STATUS, ORDER_LIMIT, HINT) VALUES (1007, 'Stored XSS', 'X', 9999, ''); ================================================ FILE: Ch07_XSS/src/main/resources/logback.xml ================================================ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n ================================================ FILE: Ch07_XSS/src/main/webapp/WEB-INF/faces-config.xml ================================================ ================================================ FILE: Ch07_XSS/src/main/webapp/WEB-INF/web.xml ================================================ Ch07_XSS javax.faces.PROJECT_STAGE Development index.xhtml Faces Servlet javax.faces.webapp.FacesServlet 1 Faces Servlet *.xhtml false COOKIE ================================================ FILE: Ch07_XSS/src/main/webapp/createCustomer.xhtml ================================================ Chapter 07 - XSS

Chapter 07 - XSS

| |

Enter all information to create a new customer:

================================================ FILE: Ch07_XSS/src/main/webapp/index.xhtml ================================================ Chapter 07 - XSS

Chapter 07 - XSS

This demo application shows Cross-Site Scripting (XSS) with JavaServer Faces (JSF). The first block of links enables normal usage of the demo application (like a normal user). The second block contains attack possibilities with XSS.

Normal Usage

Attacks

================================================ FILE: Ch07_XSS/src/main/webapp/resources/css/styles.css ================================================ th { font-size: 1.1em; font-weight: bold; padding: 5px; } td { padding: 5px; } h1 { font-size: 1.5em; } h2 { font-size: 1.2em; } ================================================ FILE: Ch07_XSS/src/main/webapp/search.xhtml ================================================ Chapter 07 - XSS

Chapter 07 - XSS

| |
================================================ FILE: Ch07_XSS/src/main/webapp/searchCustomer.xhtml ================================================ Chapter 07 - XSS

Chapter 07 - XSS

| | |

Your search for [] returned the following results:

ID Name Status Order Limit Hint
================================================ FILE: Ch07_XSS/src/main/webapp/showCustomers.xhtml ================================================ Chapter 07 - XSS

Chapter 07 - XSS

| |

These are all customers currently available in the database:

ID Name Status Order Limit Hint
================================================ FILE: Ch07_XSSFilter/pom.xml ================================================ 4.0.0 de.dominikschadow.javawebsecurity javawebsecurity 1.0.0 Ch07_XSSFilter war Chapter 07 - XSS Filter https://github.com/dschadow/Java-Web-Security Chapter 7 XSS Filter sample project. Requires a server like Apache Tomcat. Open the web application in your browser at http://localhost:8080/Ch07_XSSFilter org.owasp.esapi esapi javax.servlet javax.servlet-api javax.servlet.jsp javax.servlet.jsp-api javax.servlet jstl Ch07_XSSFilter org.apache.maven.plugins maven-compiler-plugin org.apache.tomcat.maven tomcat7-maven-plugin ================================================ FILE: Ch07_XSSFilter/src/main/java/de/dominikschadow/webappsecurity/filter/BlacklistFilter.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity.filter; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import java.io.IOException; /** * Request filter calling the BlacklistRequestWrapper for filtering. * * @see de.dominikschadow.webappsecurity.filter.BlacklistRequestWrapper * * @author Dominik Schadow */ public class BlacklistFilter implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { filterChain.doFilter(new BlacklistRequestWrapper((HttpServletRequest) servletRequest), servletResponse); } @Override public void init(FilterConfig filterConfig) { } @Override public void destroy() { } } ================================================ FILE: Ch07_XSSFilter/src/main/java/de/dominikschadow/webappsecurity/filter/BlacklistRequestWrapper.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity.filter; import org.owasp.esapi.ESAPI; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import java.util.regex.Pattern; /** * Filter HTML tags which can be used for a XSS attack with a blacklist.
*

* Originally based on Ricardo Zuasti. * * @author Dominik Schadow */ public class BlacklistRequestWrapper extends HttpServletRequestWrapper { public BlacklistRequestWrapper(HttpServletRequest servletRequest) { super(servletRequest); } @Override public String[] getParameterValues(String parameter) { String[] values = super.getParameterValues(parameter); if (values == null) { return null; } int count = values.length; String[] encodedValues = new String[count]; for (int i = 0; i < count; i++) { encodedValues[i] = stripXSS(values[i]); } return encodedValues; } @Override public String getParameter(String parameter) { String value = super.getParameter(parameter); return stripXSS(value); } @Override public String getHeader(String name) { String value = super.getHeader(name); return stripXSS(value); } private static String stripXSS(String value) { if (value != null) { value = ESAPI.encoder().canonicalize(value); // Avoid null characters value = value.replaceAll("", ""); // Avoid anything between script tags Pattern scriptPattern = Pattern.compile("", Pattern.CASE_INSENSITIVE); value = scriptPattern.matcher(value).replaceAll(""); // Avoid anything in a src='...' type of expression scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\'(.*?)\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); value = scriptPattern.matcher(value).replaceAll(""); scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); value = scriptPattern.matcher(value).replaceAll(""); // Remove any lonesome tag scriptPattern = Pattern.compile("", Pattern.CASE_INSENSITIVE); value = scriptPattern.matcher(value).replaceAll(""); // Remove any lonesome "; private Map maximumMap = null; private Status[] maximumArray = null; public Map getMaximumMap() { return maximumMap; } public Status[] getMaximumArray() { return maximumArray; } public String getInput() { return input; } public void setInput(String input) { this.input = input; maximumMap = new LinkedHashMap<>(); maximumMap.put(input, input); maximumArray = new Status[1]; maximumArray[0] = new Status(input); } } ================================================ FILE: Ch07_XSSJSF/src/main/java/de/dominikschadow/webappsecurity/StandardController.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity; import javax.faces.bean.ManagedBean; import javax.faces.bean.SessionScoped; import java.io.Serial; import java.io.Serializable; import java.util.LinkedHashMap; import java.util.Map; /** * Bean representing user input into the standard protected output page * (no additional security related attributes). * * @author Dominik Schadow */ @ManagedBean(name = "standard") @SessionScoped public class StandardController implements Serializable { @Serial private static final long serialVersionUID = 4083596061570021965L; private String input = ""; private Map standardMap = null; private Status[] standardArray = null; public Map getStandardMap() { return standardMap; } public Status[] getStandardArray() { return standardArray; } public String getInput() { return input; } public void setInput(String input) { this.input = input; standardMap = new LinkedHashMap<>(); standardMap.put(input, input); standardArray = new Status[1]; standardArray[0] = new Status(input); } } ================================================ FILE: Ch07_XSSJSF/src/main/java/de/dominikschadow/webappsecurity/Status.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity; import java.io.Serial; import java.io.Serializable; /** * Represents one Status array entry. * * @author Dominik Schadow */ public class Status implements Serializable { @Serial private static final long serialVersionUID = -5176873476153674154L; private String label; private String value; public Status(String text) { this.label = text; this.value = text; } public String getLabel() { return label; } public String getValue() { return value; } } ================================================ FILE: Ch07_XSSJSF/src/main/webapp/WEB-INF/faces-config.xml ================================================ ================================================ FILE: Ch07_XSSJSF/src/main/webapp/WEB-INF/web.xml ================================================ Ch07_XSSJSF javax.faces.PROJECT_STAGE Development Faces Servlet javax.faces.webapp.FacesServlet 1 Faces Servlet *.xhtml index.xhtml ================================================ FILE: Ch07_XSSJSF/src/main/webapp/index.xhtml ================================================ Chapter 07 - XSS with JSF

Chapter 07 - XSS with JSF

The first form posts to a page processing the input in elements with default attributes. The second form posts to a page which is configured as secure as possible using all available attributes to escape the output.

Default Attributes

Secure Attributes

================================================ FILE: Ch07_XSSJSF/src/main/webapp/maximum.xhtml ================================================ Chapter 07 - XSS with JSF

Chapter 07 - XSS with JSF

All available security attributes are set for all elements on this page.

selectOneMenu with Map

selectOneMenu with Array

selectOneMenu with selectItem

outputText element

outputText direct value expression

#{maximum.input}

Back

================================================ FILE: Ch07_XSSJSF/src/main/webapp/resources/css/styles.css ================================================ .text-input { width: 250px; } .send-button { margin-left: 25px; } h1 { font-size: 1.5em; } h2 { font-size: 1.2em; } ================================================ FILE: Ch07_XSSJSF/src/main/webapp/standard.xhtml ================================================ Chapter 07 - XSS with JSF

Chapter 07 - XSS with JSF

Only the default attributes are active for all elements on this page.

selectOneMenu with Map

selectOneMenu with Array

selectOneMenu with selectItem

outputText element

outputText direct value expression

#{standard.input}

Back

================================================ FILE: Ch08_CSRF/pom.xml ================================================ 4.0.0 de.dominikschadow.javawebsecurity javawebsecurity 1.0.0 Ch08_CSRF war Chapter 08 - CSRF https://github.com/dschadow/Java-Web-Security Chapter 8 CSRF sample project. Requires a server like Apache Tomcat. Open the web application in your browser at http://localhost:8080/Ch08_CSRF javax.servlet javax.servlet-api org.owasp.esapi esapi ch.qos.logback logback-classic Ch08_CSRF org.apache.maven.plugins maven-compiler-plugin org.apache.maven.plugins maven-war-plugin false org.apache.tomcat.maven tomcat7-maven-plugin ================================================ FILE: Ch08_CSRF/src/main/java/de/dominikschadow/webappsecurity/servlets/ProtectedServlet.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity.servlets; import de.dominikschadow.webappsecurity.token.CSRFTokenHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.io.Serial; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; /** * Basic protected servlet for GET and POST requests. Checks the CSRF-Token value to identify * CSRF attacks. Prints out all information to standard out and returns the received parameter * as response. * * @author Dominik Schadow */ @WebServlet(name = "ProtectedServlet", urlPatterns = {"/ProtectedServlet"}) public class ProtectedServlet extends HttpServlet { @Serial private static final long serialVersionUID = 1L; private static final Logger LOGGER = LoggerFactory.getLogger(ProtectedServlet.class); @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException { LOGGER.info("Processing protected GET request"); response.setContentType("text/html"); try { if (!CSRFTokenHandler.isValid(request)) { LOGGER.warn("CSRF token is invalid"); response.setStatus(401); try (PrintWriter out = response.getWriter()) { out.println("CSRF token is invalid"); } catch (IOException ex) { LOGGER.error(ex.getMessage(), ex); } return; } } catch (NoSuchAlgorithmException | NoSuchProviderException ex) { LOGGER.error(ex.getMessage(), ex); } LOGGER.info("CSRF token is valid"); String newPassword = request.getParameter("newPassword"); String confirmPassword = request.getParameter("confirmPassword"); LOGGER.info("Received {} and {} as GET parameter.", newPassword, confirmPassword); try (PrintWriter out = response.getWriter()) { out.println(""); out.println(""); out.println("Chapter 08 - CSRF"); out.println(""); out.println(""); out.println(""); out.println("

Chapter 08 - CSRF

"); out.println("

Received " + newPassword + " and " + confirmPassword + " as GET parameter.

"); out.println("

Back

"); out.println(""); out.println(""); } catch (IOException ex) { LOGGER.error(ex.getMessage(), ex); } } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException { LOGGER.info("Processing protected POST request"); response.setContentType("text/html"); try { if (!CSRFTokenHandler.isValid(request)) { LOGGER.warn("CSRF token is invalid"); response.setStatus(401); return; } } catch (NoSuchAlgorithmException | NoSuchProviderException ex) { LOGGER.error(ex.getMessage(), ex); } LOGGER.info("CSRF token is valid"); String newPassword = request.getParameter("newPassword"); String confirmPassword = request.getParameter("confirmPassword"); LOGGER.info("Received {} and {} as POST parameter.", newPassword, confirmPassword); try (PrintWriter out = response.getWriter()) { out.println(""); out.println(""); out.println("Chapter 08 - CSRF"); out.println(""); out.println(""); out.println(""); out.println("

Chapter 08 - CSRF

"); out.println("

Received " + newPassword + " and " + confirmPassword + " as POST parameter.

"); out.println("

Back

"); out.println(""); out.println(""); } catch (IOException ex) { LOGGER.error(ex.getMessage(), ex); } } } ================================================ FILE: Ch08_CSRF/src/main/java/de/dominikschadow/webappsecurity/servlets/UnprotectedServlet.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of the Java-Web-Security project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity.servlets; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.io.Serial; /** * Basic unprotected servlet for GET and POST requests. Prints out all information to standard out * and returns the received parameter as response. * * @author Dominik Schadow */ @WebServlet(name = "UnprotectedServlet", urlPatterns = {"/UnprotectedServlet"}) public class UnprotectedServlet extends HttpServlet { @Serial private static final long serialVersionUID = 1L; private static final Logger LOGGER = LoggerFactory.getLogger(UnprotectedServlet.class); @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) { String newPassword = request.getParameter("newPassword"); String confirmPassword = request.getParameter("confirmPassword"); LOGGER.info("Processing unprotected GET request: Received {} and {} as parameter.", newPassword, confirmPassword); response.setContentType("text/html"); try (PrintWriter out = response.getWriter()) { out.println(""); out.println(""); out.println("Chapter 08 - CSRF"); out.println(""); out.println(""); out.println(""); out.println("

Chapter 08 - CSRF

"); out.println("

Received " + newPassword + " and " + confirmPassword + " as GET parameter.

"); out.println("

Back

"); out.println(""); out.println(""); } catch (IOException ex) { LOGGER.error(ex.getMessage(), ex); } } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { String newPassword = request.getParameter("newPassword"); String confirmPassword = request.getParameter("confirmPassword"); LOGGER.info("Processing unprotected POST request: Received {} and {} as parameter.", newPassword, confirmPassword); response.setContentType("text/html"); try (PrintWriter out = response.getWriter()) { out.println(""); out.println(""); out.println("Chapter 08 - CSRF"); out.println(""); out.println(""); out.println(""); out.println("

Chapter 08 - CSRF

"); out.println("

Received " + newPassword + " and " + confirmPassword + " as POST parameter.

"); out.println("

Back

"); out.println(""); out.println(""); } catch (IOException ex) { LOGGER.error(ex.getMessage(), ex); } } } ================================================ FILE: Ch08_CSRF/src/main/java/de/dominikschadow/webappsecurity/token/CSRFTokenHandler.java ================================================ /* * Copyright (C) 2015 Dominik Schadow, info@dominikschadow.de * * This file is part of Java-Web-Security . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.webappsecurity.token; import org.apache.commons.lang.StringUtils; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.SecureRandom; /** * Calculates a new token and adds it to the session. Compares the session toke value with the * token value included in the request. * * @author Dominik Schadow */ public final class CSRFTokenHandler { public static final String CSRF_TOKEN = "CSRF_TOKEN"; private static final String MISSING_SESSION = "No session available"; /** * Private constructor to prevent initialization. */ private CSRFTokenHandler() { } private static String getToken() throws NoSuchAlgorithmException, NoSuchProviderException { SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "SUN"); sr.nextBytes(new byte[20]); return String.valueOf(sr.nextLong()); } public static String getToken(HttpSession session) throws ServletException, NoSuchAlgorithmException, NoSuchProviderException { if (session == null) { throw new ServletException(MISSING_SESSION); } String token = (String) session.getAttribute(CSRF_TOKEN); if (StringUtils.isEmpty(token)) { token = getToken(); session.setAttribute(CSRF_TOKEN, token); } return token; } public static boolean isValid(HttpServletRequest request) throws ServletException, NoSuchAlgorithmException, NoSuchProviderException { if (request.getSession(false) == null) { throw new ServletException(MISSING_SESSION); } return StringUtils.equals(getToken(request.getSession(false)), request.getParameter(CSRF_TOKEN)); } } ================================================ FILE: Ch08_CSRF/src/main/resources/logback.xml ================================================ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n ================================================ FILE: Ch08_CSRF/src/main/webapp/form-protected.html ================================================ Chapter 08 - CSRF

Chapter 08 - CSRF: Hidden Form

Back

================================================ FILE: Ch08_CSRF/src/main/webapp/form-unprotected.html ================================================ Chapter 08 - CSRF

Chapter 08 - CSRF: Hidden Form

Back

================================================ FILE: Ch08_CSRF/src/main/webapp/form-working.jsp ================================================ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="de.dominikschadow.webappsecurity.token.CSRFTokenHandler" %> Chapter 08 - CSRF

Chapter 08 - CSRF: Working Form

 
================================================ FILE: Ch08_CSRF/src/main/webapp/image-protected.html ================================================ Chapter 08 - CSRF

Chapter 08 - CSRF: Hidden Image

Back

================================================ FILE: Ch08_CSRF/src/main/webapp/image-unprotected.html ================================================ Chapter 08 - CSRF

Chapter 08 - CSRF: Hidden Image

Back

================================================ FILE: Ch08_CSRF/src/main/webapp/index.jsp ================================================ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="de.dominikschadow.webappsecurity.token.CSRFTokenHandler" %> Chapter 08 - CSRF

Chapter 08 - CSRF

The generated CSRF token for this session is: <%=CSRFTokenHandler.getToken(request.getSession(false))%>

================================================ FILE: Ch08_CSRF/src/main/webapp/requests-protected.html ================================================ Chapter 08 - CSRF

Chapter 08 - CSRF: Protected Requests

The following links show different ways to trigger a GET or POST request with CSRF protection in the backend.

GET Requests

GET requests are easy to trigger and only require some HTML.

POST Requests

POST requests are a little bit harder to trigger and require JavaScript.

Back

================================================ FILE: Ch08_CSRF/src/main/webapp/requests-unprotected.html ================================================ Chapter 08 - CSRF

Chapter 08 - CSRF: Unprotected Requests

The following links show different ways to trigger a GET or POST request without any CSRF protection in the backend.

GET Requests

GET requests are easy to trigger and only require some HTML.

POST Requests

POST requests are a little bit harder to trigger and require JavaScript.

Back

================================================ FILE: Ch08_CSRF/src/main/webapp/resources/css/styles.css ================================================ .text-input { width: 250px; } h1 { font-size: 1.5em; } h2 { font-size: 1.2em; } ================================================ FILE: Ch08_CSRF/src/main/webapp/xmlhttprequest-protected.html ================================================ Chapter 08 - CSRF

Chapter 08 - CSRF

Back

================================================ FILE: Ch08_CSRF/src/main/webapp/xmlhttprequest-unprotected.html ================================================ Chapter 08 - CSRF

Chapter 08 - CSRF: XMLHttpRequest

Back

================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: README.md ================================================ Java-Web-Security ============== This repository contains the complete code samples from my book **Java-Web-Security - Sichere Webanwendungen mit Java entwickeln** (dpunkt.verlag, ISBN 978-3-86490-146-1), available as [Print](http://www.dpunkt.de/buecher/4198/java-web-security.html), as [PDF/EPub](http://www.dpunkt.de/buecher/4825/java-web-security.html) and for [Kindle](http://www.amazon.de/gp/product/B00IUJM3J4/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1638&creative=6742&creativeASIN=B00IUJM3J4&linkCode=as2&tag=dominikswelt). All Java projects are created as **Maven** projects and require [Java 17](https://adoptium.net/temurin/) and [Apache Maven 3](http://maven.apache.org) or newer. In **Eclipse** you therefore need to install the Maven integration via the Eclipse update manager. After that, you can either use the **git m2e connector (m2e-egit)** to import the new projects directly from the repository. Alternatively, you can clone the repository and use **Import Maven Projects** instead (no connector required here). **IntelliJ IDEA** supports this out of the box. **Mozilla Firefox** is the recommended and up until today working browser for all vulnerable web applications in this repository. Keep in mind that browsers or some add-ons may block or filter certain attacks already. Deactivate all blocking or intercepting add-ons or try a different browser if a sample application is not working. The easiest way to start a web application is to use the **Maven-Tomcat7-Plug-in** in each project: **mvn tomcat7:run-war** (or simply **mvn** in the console, since this is the default goal). Open your browser and point it to **http://localhost:8080/PROJECT_NAME**, e.g. **http://localhost:8080/Ch04_OutputEscaping**. The project name is always the final part of the URL. See the following subsections for a short description and the requirements to execute the sample code and launch the web application. ## Ch04_OutputEscaping Web application using JavaServer Pages (JSP) to show the difference between output escaping via Enterprise Security API (ESAPI) and no output escaping at all. Use an input like *<script>alert('XSS')</script>* to examine the difference. **Requirements:** Apache Tomcat, Webbrowser ## Ch04_OutputEscapingJSF Web application using JavaServer Faces (JSF) to demonstrate the two different possibilities to show user input in a web page with *#{contact.firstname}* and *<h:outputText value="#{contact.firstname}" />*. Use an input like *<script>alert('XSS')</script>* to examine the difference. **Requirements:** Apache Tomcat, Webbrowser ## Ch04_OutputEscapingJSP Spring based web application using JavaServer Pages (JSP) to demonstrate the two different possibilities to show user input in a web page with *${contact.firstname}* and *<c:out value="${contact.firstname}" />*. Use an input like *<script>alert('XSS')</script>* to examine the difference. **Requirements:** Apache Tomcat, Webbrowser ## Ch05_AccessReferenceMaps Web application using JavaServer Faces (JSF) to show the difference between using unprotected and protected Maps (with *IntegerAccessReferenceMaps* and *RandomAccessReferenceMaps*) with user data. **Requirements:** Apache Tomcat, Webbrowser ## Ch05_HSTS Web application using a Servlet filter to add the *Strict-Transport-Security* header to each response. **Requirements:** Apache Tomcat, Webbrowser ## Ch05_SessionFixation Web application invalidating an existing session and its session id before continuing the login process. This web application requires the included special *context.xml* configuration for Tomcat in order to display the current session id via JavaScript. **Requirements:** Apache Tomcat, Webbrowser ## Ch05_SessionHandling Web application containing a complete *web.xml* configuration showing how to protect cookies and other session data. Contains only a start page which fails trying to show the session cookie in a JavaScript popup. **Requirements:** Apache Tomcat, Webbrowser ## Ch06_SQLInjection Web application using user input to query a in-memory-database. The entered data is used as part of a normal *Statement*, an *escaped Statement*, a *Prepared Statement* and as input for a *Hibernate Query Language*. **Requirements:** Apache Tomcat, Webbrowser ## Ch06_XPathInjection Web application using user input to query a simple XML document. The entered data (name and password) is used as part of a normal *XPath expression* without any escaping and escaped as part of another *XPath expression*. The unescaped version is prune to XPath Injection, which makes it possible to retrieve more data of the XML document as the intended order limit. **Requirements:** Apache Tomcat, Webbrowser ## Ch07_CSP Web application with three input processing servlets. One is unprotected and processes any input without input validation or output escaping and is prone to Cross-Site Scripting. The second servlet adds a minimal *Content-Security-Policy* header to the response and allows to use any source from the same page (URL). This already protects the response page from Cross-Site Scripting in supported browsers. The third form adds a *Content-Security-Policy-Report-Only* header and shows how easy the reported data can be processed. **Requirements:** Apache Tomcat, Webbrowser ## Ch07_XSS Web application to test the three XSS types *stored*, *reflected* and *DOM based*. The input textfield is vulnerable to XSS and can be easily protected by enabling output escaping. Cookie could be protected by removing the special *context.xml* and by setting the corresponding *web.xml* parameter. This web application requires the included special *context.xml* configuration for Tomcat in order to display the current session id via JavaScript. **Requirements:** Apache Tomcat, Webbrowser ## Ch07_XSSFilter Web application showing the differences between a blacklist and an ESAPI based request filtering. Use an input like *<script>alert('XSS')</script>* to see the different output on the output pages. **Requirements:** Apache Tomcat, Webbrowser ## Ch07_XSSJSF JavaServer Faces (JSF) based web application accepting user input in two forms. The first form results into an output page showing the user input in drop down boxes and output text fields with all default attributes active. The second form results into an output page using the same output fields with any additional security related attribute set to the maximum. Use an input like *<script>alert('XSS')</script>* to challenge the JSF XSS protection. **Requirements:** Apache Tomcat, Webbrowser ## Ch08_CSRF Web application showing Cross-Site Request Forgery (CSRF) with GET and POST requests and how to protect forms with an anti CSRF token. All requests on the **Unprotected Requests** page are successful and reach the backend as a normal request. The **Protected Requests** page contains successful (with token) and unsuccessful (without token) requests; only the valid requests are processed in the backend. **Requirements:** Apache Tomcat, Webbrowser ## Meta ![Build](https://github.com/dschadow/Java-Web-Security/workflows/Build/badge.svg) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) ================================================ FILE: pom.xml ================================================ 4.0.0 javawebsecurity de.dominikschadow.javawebsecurity 1.0.0 pom Java-Web-Security https://github.com/dschadow/Java-Web-Security This repository contains the complete code samples from my book 'Java-Web-Security - Sichere Webanwendungen mit Java entwickeln' (dpunkt.verlag, ISBN 978-3-86490-146-1). Dominik Schadow https://blog.dominikschadow.de GitHub https://github.com/dschadow/Java-Web-Security/issues scm:git:git@github.com:dschadow/Java-Web-Security.git scm:git:git@github.com:dschadow/Java-Web-Security.git https://github.com/dschadow/Java-Web-Security Apache License 2.0 https://www.apache.org/licenses/LICENSE-2.0 UTF-8 5.3.29 1.7.33 2.2.20 5.6.15.Final 6.0.3 3.0 17 javax.servlet javax.servlet-api 4.0.1 provided javax.servlet.jsp javax.servlet.jsp-api 2.3.3 provided javax.servlet jstl 1.2 compile org.owasp.esapi esapi 2.7.0.0 javax.servlet servlet-api antisamy org.owasp.antisamy org.springframework spring-test ${spring.version} test org.springframework spring-webmvc ${spring.version} com.h2database h2 2.4.240 runtime org.hibernate hibernate-core ${hibernate.version} com.sun.faces jsf-api ${jsf.version} com.sun.faces jsf-impl ${jsf.version} ch.qos.logback logback-classic 1.5.32 org.apache.commons commons-lang3 3.20.0 org.junit.jupiter junit-jupiter-engine ${junit.jupiter.version} test org.hamcrest hamcrest-library ${hamcrest.version} test com.github.spotbugs spotbugs-maven-plugin 4.9.8.3 Max Low com.h3xstream.findsecbugs findsecbugs-plugin 1.14.0 org.apache.maven.plugins maven-compiler-plugin 3.15.0 ${java.version} ${java.version} org.apache.tomcat.maven tomcat7-maven-plugin 2.2 org.apache.maven.plugins maven-war-plugin 3.5.1 org.apache.maven.plugins maven-site-plugin 3.21.0 org.apache.maven.plugins maven-project-info-reports-plugin 3.9.0 org.owasp dependency-check-maven 12.2.1 true true aggregate Ch04_OutputEscaping Ch04_OutputEscapingJSF Ch04_OutputEscapingJSP Ch05_AccessReferenceMaps Ch05_HSTS Ch05_SessionFixation Ch05_SessionHandling Ch06_SQLInjection Ch06_XPathInjection Ch07_CSP Ch07_XSS Ch07_XSSFilter Ch07_XSSJSF Ch08_CSRF