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>.
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.
================================================
FILE: Ch04_OutputEscapingJSF/pom.xml
================================================
4.0.0de.dominikschadow.javawebsecurityjavawebsecurity1.0.0Ch04_OutputEscapingJSFwarChapter 04 - JSF Output Escapinghttps://github.com/dschadow/Java-Web-SecurityChapter 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_OutputEscapingJSFcom.sun.facesjsf-apicom.sun.facesjsf-implCh04_OutputEscapingJSFtomcat7:run-warorg.apache.maven.pluginsmaven-compiler-pluginorg.apache.tomcat.maventomcat7-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_OutputEscapingJSFjavax.faces.PROJECT_STAGEDevelopmentFaces Servletjavax.faces.webapp.FacesServlet1Faces Servlet*.xhtmlindex.xhtml
================================================
FILE: Ch04_OutputEscapingJSF/src/main/webapp/contact.xhtml
================================================
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.0de.dominikschadow.javawebsecurityjavawebsecurity1.0.0Ch04_OutputEscapingJSPwarChapter 04 - JSP Output Escapinghttps://github.com/dschadow/Java-Web-SecurityChapter 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_OutputEscapingJSPorg.springframeworkspring-webmvcjavax.servletjavax.servlet-apijavax.servlet.jspjavax.servlet.jsp-apijavax.servletjstlch.qos.logbacklogback-classicorg.springframeworkspring-testorg.junit.jupiterjunit-jupiter-engineorg.hamcresthamcrest-libraryCh04_OutputEscapingJSPtomcat7:run-warorg.apache.maven.pluginsmaven-compiler-pluginorg.apache.maven.pluginsmaven-war-pluginfalseorg.apache.tomcat.maventomcat7-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
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>.
================================================
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.0de.dominikschadow.javawebsecurityjavawebsecurity1.0.0Ch05_AccessReferenceMapswarChapter 05 - Access Reference Mapshttps://github.com/dschadow/Java-Web-SecurityChapter 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_AccessReferenceMapscom.sun.facesjsf-apicom.sun.facesjsf-implorg.owasp.esapiesapicom.h2databaseh2org.hibernatehibernate-corech.qos.logbacklogback-classicCh05_AccessReferenceMapstomcat7:run-warorg.apache.maven.pluginsmaven-compiler-pluginorg.apache.tomcat.maventomcat7-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.H2Dialectjava:comp/env/mapDScreate-dropfalse
================================================
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_AccessReferenceMapsjavax.faces.PROJECT_STAGEDevelopmentFaces Servletjavax.faces.webapp.FacesServlet1Faces Servlet*.xhtmlindex.xhtml
================================================
FILE: Ch05_AccessReferenceMaps/src/main/webapp/account.xhtml
================================================
Chapter 05 - Access Reference Maps
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.0javawebsecurityde.dominikschadow.javawebsecurity1.0.0Ch05_HSTSwarChapter 05 - HSTShttps://github.com/dschadow/Java-Web-SecurityChapter 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_HSTSjavax.servletjavax.servlet-apich.qos.logbacklogback-classicCh05_HSTStomcat7:run-warorg.apache.maven.pluginsmaven-compiler-pluginorg.apache.tomcat.maventomcat7-maven-pluginorg.apache.maven.pluginsmaven-war-pluginfalse
================================================
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("
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.0de.dominikschadow.javawebsecurityjavawebsecurity1.0.0Ch05_SessionFixationwarChapter 05 - Session Fixationhttps://github.com/dschadow/Java-Web-SecurityChapter 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_SessionFixationjavax.servletjavax.servlet-apich.qos.logbacklogback-classicCh05_SessionFixationtomcat7:run-warorg.apache.maven.pluginsmaven-compiler-pluginorg.apache.tomcat.maventomcat7-maven-plugin${project.basedir}/src/main/resources/context.xmlorg.apache.maven.pluginsmaven-war-pluginfalse
================================================
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("
================================================
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.0de.dominikschadow.javawebsecurityjavawebsecurity1.0.0Ch05_SessionHandlingwarChapter 05 - Session Handlinghttps://github.com/dschadow/Java-Web-SecurityChapter 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_SessionHandlingcom.sun.facesjsf-apicom.sun.facesjsf-implCh05_SessionHandlingtomcat7:run-warorg.apache.maven.pluginsmaven-compiler-pluginorg.apache.tomcat.maventomcat7-maven-plugin
================================================
FILE: Ch05_SessionHandling/src/main/webapp/WEB-INF/faces-config.xml
================================================
================================================
FILE: Ch05_SessionHandling/src/main/webapp/WEB-INF/web.xml
================================================
Ch05_SessionHandlingjavax.faces.PROJECT_STAGEDevelopmentindex.xhtmlFaces Servletjavax.faces.webapp.FacesServlet1Faces Servlet*.xhtml30trueCOOKIE
================================================
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.0de.dominikschadow.javawebsecurityjavawebsecurity1.0.0Ch06_SQLInjectionwarChapter 06 - SQL Injectionhttps://github.com/dschadow/Java-Web-SecurityChapter 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_SQLInjectionjavax.servletjavax.servlet-apicom.h2databaseh2org.owasp.esapiesapiorg.hibernatehibernate-corech.qos.logbacklogback-classicCh06_SQLInjectiontomcat7:run-warorg.apache.maven.pluginsmaven-compiler-pluginorg.apache.tomcat.maventomcat7-maven-plugin${project.basedir}/src/main/resources/context.xmlorg.apache.maven.pluginsmaven-war-pluginfalse
================================================
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("
ID
");
out.println("
Name
");
out.println("
Status
");
out.println("
Order Limit
");
out.println("
");
for (Customer customer : customers) {
out.println("
");
out.println("
" + customer.getCustId() + "
");
out.println("
" + customer.getName() + "
");
out.println("
" + customer.getStatus() + "
");
out.println("
" + customer.getOrderLimit() + "
");
out.println("
");
}
out.println("
");
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.H2Dialectjava:comp/env/sqliDScreate-dropfalse
================================================
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.0de.dominikschadow.javawebsecurityjavawebsecurity1.0.0Ch06_XPathInjectionwarChapter 06 - XPath Injectionhttps://github.com/dschadow/Java-Web-SecurityChapter 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_XPathInjectionjavax.servletjavax.servlet-apiorg.owasp.esapiesapich.qos.logbacklogback-classicCh06_XPathInjectiontomcat7:run-warorg.apache.maven.pluginsmaven-compiler-pluginorg.apache.tomcat.maventomcat7-maven-pluginorg.apache.maven.pluginsmaven-war-pluginfalse
================================================
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("
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.0de.dominikschadow.javawebsecurityjavawebsecurity1.0.0Ch07_CSPwarChapter 07 - CSPhttps://github.com/dschadow/Java-Web-SecurityChapter 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_CSPjavax.servletjavax.servlet-apich.qos.logbacklogback-classicCh07_CSPtomcat7:run-warorg.apache.maven.pluginsmaven-compiler-pluginorg.apache.tomcat.maventomcat7-maven-pluginorg.apache.maven.pluginsmaven-war-pluginfalse
================================================
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("
================================================
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.0de.dominikschadow.javawebsecurityjavawebsecurity1.0.0Ch07_XSSwarChapter 07 - XSShttps://github.com/dschadow/Java-Web-SecurityChapter 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_XSScom.sun.facesjsf-apicom.sun.facesjsf-implorg.hibernatehibernate-corecom.h2databaseh2ch.qos.logbacklogback-classicorg.apache.commonscommons-lang3Ch07_XSStomcat7:run-warorg.apache.maven.pluginsmaven-compiler-pluginorg.apache.tomcat.maventomcat7-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.H2Dialectjava:comp/env/xssDScreate-dropfalse
================================================
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_XSSjavax.faces.PROJECT_STAGEDevelopmentindex.xhtmlFaces Servletjavax.faces.webapp.FacesServlet1Faces Servlet*.xhtmlfalseCOOKIE
================================================
FILE: Ch07_XSS/src/main/webapp/createCustomer.xhtml
================================================
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.
These are all customers currently available in the database:
IDNameStatusOrder LimitHint
================================================
FILE: Ch07_XSSFilter/pom.xml
================================================
4.0.0de.dominikschadow.javawebsecurityjavawebsecurity1.0.0Ch07_XSSFilterwarChapter 07 - XSS Filterhttps://github.com/dschadow/Java-Web-SecurityChapter 7 XSS Filter sample project. Requires a server like Apache Tomcat. Open the web application in your browser at http://localhost:8080/Ch07_XSSFilterorg.owasp.esapiesapijavax.servletjavax.servlet-apijavax.servlet.jspjavax.servlet.jsp-apijavax.servletjstlCh07_XSSFilterorg.apache.maven.pluginsmaven-compiler-pluginorg.apache.tomcat.maventomcat7-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_XSSJSFjavax.faces.PROJECT_STAGEDevelopmentFaces Servletjavax.faces.webapp.FacesServlet1Faces Servlet*.xhtmlindex.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.
================================================
FILE: Ch08_CSRF/pom.xml
================================================
4.0.0de.dominikschadow.javawebsecurityjavawebsecurity1.0.0Ch08_CSRFwarChapter 08 - CSRFhttps://github.com/dschadow/Java-Web-SecurityChapter 8 CSRF sample project. Requires a server like Apache Tomcat. Open the web application in your browser at http://localhost:8080/Ch08_CSRFjavax.servletjavax.servlet-apiorg.owasp.esapiesapich.qos.logbacklogback-classicCh08_CSRForg.apache.maven.pluginsmaven-compiler-pluginorg.apache.maven.pluginsmaven-war-pluginfalseorg.apache.tomcat.maventomcat7-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("");
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("");
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
================================================
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
 [](https://opensource.org/licenses/Apache-2.0)
================================================
FILE: pom.xml
================================================
4.0.0javawebsecurityde.dominikschadow.javawebsecurity1.0.0pomJava-Web-Securityhttps://github.com/dschadow/Java-Web-SecurityThis 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 Schadowhttps://blog.dominikschadow.deGitHubhttps://github.com/dschadow/Java-Web-Security/issuesscm:git:git@github.com:dschadow/Java-Web-Security.gitscm:git:git@github.com:dschadow/Java-Web-Security.githttps://github.com/dschadow/Java-Web-SecurityApache License 2.0https://www.apache.org/licenses/LICENSE-2.0UTF-85.3.291.7.332.2.205.6.15.Final6.0.33.017javax.servletjavax.servlet-api4.0.1providedjavax.servlet.jspjavax.servlet.jsp-api2.3.3providedjavax.servletjstl1.2compileorg.owasp.esapiesapi2.7.0.0javax.servletservlet-apiantisamyorg.owasp.antisamyorg.springframeworkspring-test${spring.version}testorg.springframeworkspring-webmvc${spring.version}com.h2databaseh22.4.240runtimeorg.hibernatehibernate-core${hibernate.version}com.sun.facesjsf-api${jsf.version}com.sun.facesjsf-impl${jsf.version}ch.qos.logbacklogback-classic1.5.32org.apache.commonscommons-lang33.20.0org.junit.jupiterjunit-jupiter-engine${junit.jupiter.version}testorg.hamcresthamcrest-library${hamcrest.version}testcom.github.spotbugsspotbugs-maven-plugin4.9.8.3MaxLowcom.h3xstream.findsecbugsfindsecbugs-plugin1.14.0org.apache.maven.pluginsmaven-compiler-plugin3.15.0${java.version}${java.version}org.apache.tomcat.maventomcat7-maven-plugin2.2org.apache.maven.pluginsmaven-war-plugin3.5.1org.apache.maven.pluginsmaven-site-plugin3.21.0org.apache.maven.pluginsmaven-project-info-reports-plugin3.9.0org.owaspdependency-check-maven12.2.1truetrueaggregateCh04_OutputEscapingCh04_OutputEscapingJSFCh04_OutputEscapingJSPCh05_AccessReferenceMapsCh05_HSTSCh05_SessionFixationCh05_SessionHandlingCh06_SQLInjectionCh06_XPathInjectionCh07_CSPCh07_XSSCh07_XSSFilterCh07_XSSJSFCh08_CSRF