├── .codeclimate.yml ├── .csslintrc ├── .gitignore ├── .travis.yml ├── Duke Encounters.tm7 ├── Jenkinsfile ├── LICENSE ├── README.md ├── duke-encounters ├── pom.xml └── src │ ├── main │ ├── docker │ │ └── Dockerfile │ ├── java │ │ └── de │ │ │ └── dominikschadow │ │ │ └── dukeencounters │ │ │ ├── Constants.java │ │ │ ├── DukeEncountersApplication.java │ │ │ ├── account │ │ │ ├── AccountController.java │ │ │ ├── PasswordChange.java │ │ │ ├── PasswordChangeValidator.java │ │ │ └── PasswordController.java │ │ │ ├── config │ │ │ ├── DukeEncountersProperties.java │ │ │ ├── SessionTimeoutListener.java │ │ │ ├── WebConfig.java │ │ │ └── WebSecurityConfig.java │ │ │ ├── confirmation │ │ │ ├── Confirmation.java │ │ │ ├── ConfirmationController.java │ │ │ ├── ConfirmationRepository.java │ │ │ └── ConfirmationService.java │ │ │ ├── encounter │ │ │ ├── Authority.java │ │ │ ├── BaseEncounterValidator.java │ │ │ ├── DukeEncountersUser.java │ │ │ ├── Encounter.java │ │ │ ├── EncounterController.java │ │ │ ├── EncounterRepository.java │ │ │ ├── EncounterService.java │ │ │ ├── EncounterSpecification.java │ │ │ ├── EncounterValidator.java │ │ │ └── Likelihood.java │ │ │ ├── home │ │ │ └── HomeController.java │ │ │ ├── login │ │ │ └── LoginController.java │ │ │ ├── search │ │ │ ├── SearchController.java │ │ │ ├── SearchFilter.java │ │ │ └── SearchFilterValidator.java │ │ │ ├── security │ │ │ └── SecurityValidationService.java │ │ │ └── user │ │ │ ├── AuthorityRepository.java │ │ │ ├── DukeEncountersUserValidator.java │ │ │ ├── Level.java │ │ │ ├── UserController.java │ │ │ ├── UserRepository.java │ │ │ └── UserService.java │ └── resources │ │ ├── META-INF │ │ └── additional-spring-configuration-metadata.json │ │ ├── application-boxfuse.yml │ │ ├── application-development.yml │ │ ├── application.yml │ │ ├── appsensor-client-config.xml │ │ ├── appsensor-server-config.xml │ │ ├── data.sql │ │ ├── messages.properties │ │ ├── static │ │ ├── css │ │ │ └── custom.css │ │ ├── favicon.ico │ │ └── img │ │ │ ├── duke-guitar.png │ │ │ └── duke-small.png │ │ └── templates │ │ ├── encounters.html │ │ ├── error.html │ │ ├── index.html │ │ ├── login.html │ │ ├── partials.html │ │ ├── register.html │ │ ├── search.html │ │ └── user │ │ ├── account.html │ │ ├── changePassword.html │ │ ├── confirmations.html │ │ ├── createEncounter.html │ │ ├── editAccount.html │ │ └── encounterDetails.html │ └── test │ └── java │ └── de │ └── dominikschadow │ └── dukeencounters │ ├── DukeEncountersApplicationTest.java │ ├── TestData.java │ ├── account │ └── AccountControllerTest.java │ ├── confirmation │ └── ConfirmationServiceTest.java │ ├── encounter │ ├── EncounterControllerTest.java │ └── EncounterServiceTest.java │ ├── home │ └── HomeControllerTest.java │ ├── search │ └── SearchControllerTest.java │ └── services │ └── UserServiceTest.java ├── findbugs-security-exclude.xml ├── findbugs-security-include.xml └── pom.xml /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | --- 2 | engines: 3 | csslint: 4 | enabled: true 5 | fixme: 6 | enabled: true 7 | ratings: 8 | paths: 9 | - "**.css" 10 | exclude_paths: [] 11 | -------------------------------------------------------------------------------- /.csslintrc: -------------------------------------------------------------------------------- 1 | --exclude-exts=.min.css 2 | --ignore=adjoining-classes,box-model,ids,order-alphabetical,unqualified-attributes 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | *.log 3 | *.lck 4 | .idea 5 | */target* 6 | .settings* 7 | .metadata* 8 | .classpath 9 | .project 10 | 11 | # Elastic Beanstalk Files 12 | .elasticbeanstalk/* 13 | !.elasticbeanstalk/*.cfg.yml 14 | !.elasticbeanstalk/*.global.yml -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: java 3 | jdk: oraclejdk8 4 | branches: 5 | only: 6 | - develop 7 | before_install: 8 | - echo "MAVEN_OPTS='-Xmx2048m'" > ~/.mavenrc 9 | - mvn versions:set -DnewVersion=$TRAVIS_BUILD_NUMBER 10 | script: mvn deploy cobertura:cobertura 11 | after_success: 12 | - curl --data build=true -X POST https://registry.hub.docker.com/u/dschadow/applicationintrusiondetection/trigger/21839a64-31aa-48fc-bcd6-1020e15b4ec3/ 13 | - bash <(curl -s https://codecov.io/bash) -------------------------------------------------------------------------------- /Jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline { 2 | agent any 3 | 4 | tools { 5 | maven 'Maven 3.5.0' 6 | jdk 'Java 8' 7 | } 8 | 9 | options { 10 | buildDiscarder(logRotator(numToKeepStr: '5')) 11 | } 12 | 13 | triggers { 14 | pollSCM '@daily' 15 | } 16 | 17 | stages { 18 | stage('Checkout') { 19 | steps { 20 | git 'https://github.com/dschadow/ApplicationIntrusionDetection' 21 | } 22 | } 23 | 24 | stage('Version') { 25 | steps { 26 | sh "mvn versions:set -DnewVersion=${env.BUILD_NUMBER}" 27 | } 28 | } 29 | 30 | stage('Build') { 31 | steps { 32 | sh 'mvn -B clean package' 33 | } 34 | } 35 | 36 | stage('Archive') { 37 | steps { 38 | archiveArtifacts(artifacts: '**/target/*.jar', fingerprint: true) 39 | junit(testResults: '**/target/**TEST*.xml', allowEmptyResults: true) 40 | } 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Application Intrusion Detection 2 | ============ 3 | This repository is all about Application Intrusion Detection. Have a look at my 4 | [presentations](https://blog.dominikschadow.de/events) I've given on this topic or watch the recordings at 5 | [W-JAX 2015](https://jaxenter.de/web-app-security-43952) (German) or [JavaZone 2016](https://vimeo.com/181788148) 6 | (English). 7 | 8 | # duke-encounters 9 | **Duke Encounters** is a complete web application utilizing Application Intrusion Detection based on 10 | [OWASP AppSensor](http://appsensor.org). This web application is using 11 | [Spring Boot](http://projects.spring.io/spring-boot) with a [h2](http://www.h2database.com) in-memory database and 12 | a [Thymeleaf](http://www.thymeleaf.org) UI. Keep in mind that all entered information is only stored temporarily and will be 13 | lost when restarting. Run this application with **mvn spring-boot:run**. After launching, open the web application in 14 | your browser at **http://localhost:8080**. 15 | 16 | As an alternative, you can use [Boxfuse](https://boxfuse.com) to fuse, launch the app within an immutable image and open 17 | the web application in your browser at **http://localhost:8080**. 18 | 19 | And of course you can use [Docker](https://www.docker.com) to create an image via `mvn clean package docker:build`, 20 | launch the container via `docker run -d -p 8080:8080 -t dschadow/duke-encounters` and open the web application in your 21 | browser at **http://localhost:8080**. 22 | 23 | Available users are listed in the [src/main/resources/data.sql](https://github.com/dschadow/ApplicationIntrusionDetection/blob/master/duke-encounters/src/main/resources/data.sql) 24 | file. Username and password are always identical. 25 | 26 | ## Meta 27 | [![Build Status](https://travis-ci.org/dschadow/ApplicationIntrusionDetection.svg)](https://travis-ci.org/dschadow/ApplicationIntrusionDetection) 28 | [![Code Climate](https://codeclimate.com/github/dschadow/ApplicationIntrusionDetection/badges/gpa.svg)](https://codeclimate.com/github/dschadow/ApplicationIntrusionDetection) 29 | [![codecov](https://codecov.io/gh/dschadow/ApplicationIntrusionDetection/branch/develop/graph/badge.svg)](https://codecov.io/gh/dschadow/ApplicationIntrusionDetection) 30 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) 31 | -------------------------------------------------------------------------------- /duke-encounters/src/main/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jre-alpine 2 | MAINTAINER Dominik Schadow 3 | 4 | VOLUME /tmp 5 | 6 | ADD duke-encounters.jar app.jar 7 | 8 | RUN bash -c 'touch app.jar' 9 | 10 | ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"] -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/Constants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters; 19 | 20 | /** 21 | * Project wide constants. Utility class with hidden constructor to avoid instantiation. 22 | * 23 | * @author Dominik Schadow 24 | */ 25 | public final class Constants { 26 | /** 27 | * XSS error code, value is {@value}. 28 | */ 29 | public static final String XSS_ERROR_CODE = "xss.attempt"; 30 | /** 31 | * SQL injection error code, value is {@value}. 32 | */ 33 | public static final String SQLI_ERROR_CODE = "sqli.attempt"; 34 | /** 35 | * Invalid value error code, value is {@value}. 36 | */ 37 | public static final String ATTACK_ERROR_CODE = "invalid.value"; 38 | /** 39 | * Invalid year error code, value is {@value}. 40 | */ 41 | public static final String INVALID_YEAR_ERROR_CODE = "invalid.year"; 42 | /** 43 | * Passwords don't match error code, value is {@value}. 44 | */ 45 | public static final String NOT_MATCHING_PASSWORDS_ERROR_CODE = "password.nomatch"; 46 | /** 47 | * The new password is not safe, value is {@value}. 48 | */ 49 | public static final String UNSAFE_PASSWORD_ERROR_CODE = "password.unsafe"; 50 | /** 51 | * The current password is not correct, value is {@value}. 52 | */ 53 | public static final String CURRENT_PASSWORD_NOT_CORRECT_ERROR_CODE = "password.incorrect"; 54 | /** 55 | * The entered username already exists, value is {@value}. 56 | */ 57 | public static final String USERNAME_ALREADY_EXISTS = "username.exists"; 58 | /** 59 | * Like for SQL queries, value is {@value}. 60 | */ 61 | public static final String LIKE = "%"; 62 | /** 63 | * Year of Java creation, any Duke encounter before this year is impossible, value is {@value}. 64 | */ 65 | public static final int YEAR_OF_JAVA_CREATION = 1995; 66 | 67 | private Constants() { 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/DukeEncountersApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters; 19 | 20 | import org.springframework.boot.SpringApplication; 21 | import org.springframework.boot.autoconfigure.SpringBootApplication; 22 | 23 | /** 24 | * Main class to start the embedded web server and the Duke Encounters application. 25 | * 26 | * @author Dominik Schadow 27 | */ 28 | @SpringBootApplication 29 | public class DukeEncountersApplication { 30 | public static void main(String[] args) { 31 | SpringApplication.run(DukeEncountersApplication.class, args); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/account/AccountController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.account; 19 | 20 | import de.dominikschadow.dukeencounters.confirmation.Confirmation; 21 | import de.dominikschadow.dukeencounters.confirmation.ConfirmationService; 22 | import de.dominikschadow.dukeencounters.encounter.DukeEncountersUser; 23 | import de.dominikschadow.dukeencounters.encounter.Encounter; 24 | import de.dominikschadow.dukeencounters.encounter.EncounterService; 25 | import de.dominikschadow.dukeencounters.user.DukeEncountersUserValidator; 26 | import de.dominikschadow.dukeencounters.user.Level; 27 | import de.dominikschadow.dukeencounters.user.UserService; 28 | import lombok.AllArgsConstructor; 29 | import lombok.extern.slf4j.Slf4j; 30 | import org.owasp.security.logging.SecurityMarkers; 31 | import org.springframework.security.access.prepost.PreAuthorize; 32 | import org.springframework.stereotype.Controller; 33 | import org.springframework.ui.Model; 34 | import org.springframework.web.bind.WebDataBinder; 35 | import org.springframework.web.bind.annotation.GetMapping; 36 | import org.springframework.web.bind.annotation.InitBinder; 37 | import org.springframework.web.bind.annotation.ModelAttribute; 38 | import org.springframework.web.bind.annotation.PostMapping; 39 | import org.springframework.web.servlet.ModelAndView; 40 | import org.springframework.web.servlet.mvc.support.RedirectAttributes; 41 | 42 | import java.util.List; 43 | 44 | /** 45 | * Controller to handle all account related requests. 46 | * 47 | * @author Dominik Schadow 48 | */ 49 | @Controller 50 | @Slf4j 51 | @AllArgsConstructor 52 | public class AccountController { 53 | private final EncounterService encounterService; 54 | private final ConfirmationService confirmationService; 55 | private final UserService userService; 56 | private final DukeEncountersUserValidator validator; 57 | 58 | @GetMapping("/account") 59 | @PreAuthorize("hasAnyRole('USER','ADMIN')") 60 | public String showMyAccount(final Model model) { 61 | String username = userService.getUsername(); 62 | 63 | log.warn(SecurityMarkers.SECURITY_AUDIT, "User {} is accessing his account", username); 64 | 65 | List encounters = encounterService.getEncountersByUsername(username); 66 | model.addAttribute("encounters", encounters); 67 | 68 | List confirmations = confirmationService.getConfirmationsByUsername(username); 69 | model.addAttribute("confirmations", confirmations); 70 | 71 | String userLevel = Level.ROOKIE.getName(); 72 | 73 | DukeEncountersUser dukeEncountersUser = userService.getDukeEncountersUser(username); 74 | if (dukeEncountersUser != null && dukeEncountersUser.getLevel() != null) { 75 | userLevel = dukeEncountersUser.getLevel().getName(); 76 | } 77 | 78 | model.addAttribute("userlevel", userLevel); 79 | 80 | return "user/account"; 81 | } 82 | 83 | @GetMapping("/account/userdata") 84 | @PreAuthorize("hasAnyRole('USER','ADMIN')") 85 | public ModelAndView editMyAccount() { 86 | String username = userService.getUsername(); 87 | 88 | log.warn(SecurityMarkers.SECURITY_AUDIT, "User {} is editing his account", username); 89 | 90 | ModelAndView modelAndView = new ModelAndView("user/editAccount"); 91 | 92 | DukeEncountersUser user = userService.getDukeEncountersUser(); 93 | modelAndView.addObject("user", user); 94 | modelAndView.addObject("userlevel", user.getLevel().getName()); 95 | 96 | return modelAndView; 97 | } 98 | 99 | /** 100 | * Updates the users first name and last name and stores it in the database. 101 | * 102 | * @param updatedUser The updated user 103 | * @param redirectAttributes Attributes available after the redirect 104 | * @return Account page 105 | */ 106 | @PostMapping("/account/userdata") 107 | @PreAuthorize("hasAnyRole('USER','ADMIN')") 108 | public ModelAndView updateUser(@ModelAttribute final DukeEncountersUser updatedUser, 109 | final RedirectAttributes redirectAttributes) { 110 | DukeEncountersUser user = userService.getDukeEncountersUser(); 111 | user.setFirstname(updatedUser.getFirstname()); 112 | user.setLastname(updatedUser.getLastname()); 113 | 114 | DukeEncountersUser storedUser = userService.updateUser(user); 115 | 116 | log.warn(SecurityMarkers.SECURITY_AUDIT, "User {} updated his userdata", storedUser); 117 | 118 | redirectAttributes.addFlashAttribute("dataUpdated", true); 119 | 120 | return new ModelAndView("redirect:/account"); 121 | } 122 | 123 | /** 124 | * Updates the users email and stores it in the database. 125 | * 126 | * @param updatedUser The updated user 127 | * @param redirectAttributes Attributes available after the redirect 128 | * @return Account page 129 | */ 130 | @PostMapping("/account/accountdata") 131 | @PreAuthorize("hasAnyRole('USER','ADMIN')") 132 | public ModelAndView updateAccount(@ModelAttribute final DukeEncountersUser updatedUser, 133 | final RedirectAttributes redirectAttributes) { 134 | if (userService.confirmPassword(updatedUser.getPassword())) { 135 | DukeEncountersUser user = userService.getDukeEncountersUser(); 136 | user.setEmail(updatedUser.getEmail()); 137 | 138 | DukeEncountersUser storedUser = userService.updateUser(user); 139 | 140 | log.warn(SecurityMarkers.SECURITY_AUDIT, "User {} updated his account", storedUser); 141 | 142 | redirectAttributes.addFlashAttribute("dataUpdated", true); 143 | } else { 144 | redirectAttributes.addFlashAttribute("dataNotUpdated", true); 145 | } 146 | 147 | return new ModelAndView("redirect:/account"); 148 | } 149 | 150 | @InitBinder 151 | protected void initBinder(final WebDataBinder binder) { 152 | binder.setValidator(validator); 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/account/PasswordChange.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.account; 19 | 20 | import lombok.Data; 21 | 22 | /** 23 | * Updates the password of the selected user. 24 | * 25 | * @author Dominik Schadow 26 | */ 27 | @Data 28 | public class PasswordChange { 29 | private String currentPassword; 30 | private String newPassword; 31 | private String newPasswordConfirmation; 32 | } 33 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/account/PasswordChangeValidator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.account; 19 | 20 | import de.dominikschadow.dukeencounters.Constants; 21 | import de.dominikschadow.dukeencounters.user.UserService; 22 | import lombok.AllArgsConstructor; 23 | import org.apache.commons.lang3.StringUtils; 24 | import org.springframework.stereotype.Component; 25 | import org.springframework.validation.Errors; 26 | import org.springframework.validation.Validator; 27 | import org.springframework.validation.beanvalidation.SpringValidatorAdapter; 28 | 29 | /** 30 | * Validates a request to change the users password. Makes sure that the current password is correct and that the new 31 | * password matches its confirmation. 32 | * 33 | * @author Dominik Schadow 34 | */ 35 | @Component 36 | @AllArgsConstructor 37 | public class PasswordChangeValidator implements Validator { 38 | private final SpringValidatorAdapter validator; 39 | private final UserService userService; 40 | 41 | @Override 42 | public boolean supports(final Class clazz) { 43 | return PasswordChange.class.equals(clazz); 44 | } 45 | 46 | @Override 47 | public void validate(final Object target, final Errors errors) { 48 | validator.validate(target, errors); 49 | 50 | PasswordChange passwordChange = (PasswordChange) target; 51 | 52 | if (!userService.confirmPassword(passwordChange.getCurrentPassword())) { 53 | errors.rejectValue("currentPassword", Constants.CURRENT_PASSWORD_NOT_CORRECT_ERROR_CODE); 54 | } 55 | 56 | if (StringUtils.length(passwordChange.getNewPassword()) < 10) { 57 | errors.rejectValue("newPassword", Constants.UNSAFE_PASSWORD_ERROR_CODE); 58 | } 59 | 60 | if (!passwordChange.getNewPassword().equals(passwordChange.getNewPasswordConfirmation())) { 61 | errors.rejectValue("newPassword", Constants.NOT_MATCHING_PASSWORDS_ERROR_CODE); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/account/PasswordController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.account; 19 | 20 | import de.dominikschadow.dukeencounters.encounter.DukeEncountersUser; 21 | import de.dominikschadow.dukeencounters.user.UserService; 22 | import lombok.AllArgsConstructor; 23 | import lombok.extern.slf4j.Slf4j; 24 | import org.owasp.security.logging.SecurityMarkers; 25 | import org.springframework.security.access.prepost.PreAuthorize; 26 | import org.springframework.stereotype.Controller; 27 | import org.springframework.validation.BindingResult; 28 | import org.springframework.web.bind.WebDataBinder; 29 | import org.springframework.web.bind.annotation.GetMapping; 30 | import org.springframework.web.bind.annotation.InitBinder; 31 | import org.springframework.web.bind.annotation.ModelAttribute; 32 | import org.springframework.web.bind.annotation.PostMapping; 33 | import org.springframework.web.servlet.ModelAndView; 34 | import org.springframework.web.servlet.mvc.support.RedirectAttributes; 35 | 36 | import javax.validation.Valid; 37 | 38 | /** 39 | * Controller to handle a password change request. 40 | * 41 | * @author Dominik Schadow 42 | */ 43 | @Controller 44 | @Slf4j 45 | @AllArgsConstructor 46 | public class PasswordController { 47 | private final UserService userService; 48 | private final PasswordChangeValidator validator; 49 | 50 | /** 51 | * Loads the change password page. 52 | * 53 | * @param passwordChange The PasswordChange model attribute 54 | * @return The page to navigate to, including user level information 55 | */ 56 | @GetMapping("/account/password") 57 | @PreAuthorize("hasAnyRole('USER','ADMIN')") 58 | public ModelAndView changePassword(@ModelAttribute final PasswordChange passwordChange) { 59 | String username = userService.getUsername(); 60 | 61 | log.warn(SecurityMarkers.SECURITY_AUDIT, "User {} is changing his password", username); 62 | 63 | ModelAndView modelAndView = new ModelAndView("user/changePassword"); 64 | 65 | DukeEncountersUser user = userService.getDukeEncountersUser(); 66 | modelAndView.addObject("userlevel", user.getLevel().getName()); 67 | 68 | return modelAndView; 69 | } 70 | 71 | /** 72 | * Updates the users password and stores it in the database. 73 | * 74 | * @param update The new password 75 | * @return Account page 76 | */ 77 | @PostMapping("/account/password") 78 | @PreAuthorize("hasAnyRole('USER','ADMIN')") 79 | public ModelAndView updatePassword(@Valid final PasswordChange update, final BindingResult result, 80 | final RedirectAttributes redirectAttributes) { 81 | if (result.hasErrors()) { 82 | return new ModelAndView("user/changePassword", "formErrors", result.getAllErrors()); 83 | } 84 | 85 | DukeEncountersUser user = userService.getDukeEncountersUser(); 86 | user.setPassword(userService.hashPassword(update.getNewPassword())); 87 | 88 | DukeEncountersUser storedUser = userService.updateUser(user); 89 | 90 | log.warn(SecurityMarkers.SECURITY_AUDIT, "User {} changed his password", storedUser.getUsername()); 91 | 92 | redirectAttributes.addFlashAttribute("dataUpdated", true); 93 | 94 | return new ModelAndView("redirect:/account"); 95 | } 96 | 97 | @InitBinder 98 | protected void initBinder(final WebDataBinder binder) { 99 | binder.setValidator(validator); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/config/DukeEncountersProperties.java: -------------------------------------------------------------------------------- 1 | package de.dominikschadow.dukeencounters.config; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | 6 | /** 7 | * Configuration properties holder for all {@code Duke Encounter} properties. 8 | * 9 | * @author Dominik Schadow 10 | */ 11 | @ConfigurationProperties(prefix = "duke.encounters") 12 | @Data 13 | public class DukeEncountersProperties { 14 | /** 15 | * The number of encounters to be shown in the latest encounters list. 16 | */ 17 | private int latestAmount; 18 | private int passwordStrength; 19 | } 20 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/config/SessionTimeoutListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.config; 19 | 20 | import javax.servlet.http.HttpSessionEvent; 21 | import javax.servlet.http.HttpSessionListener; 22 | 23 | /** 24 | * Adds a session timeout to the created user session. 25 | * 26 | * @author Dominik Schadow 27 | */ 28 | public class SessionTimeoutListener implements HttpSessionListener { 29 | @Override 30 | public void sessionCreated(HttpSessionEvent event) { 31 | event.getSession().setMaxInactiveInterval(10 * 60); 32 | } 33 | 34 | @Override 35 | public void sessionDestroyed(HttpSessionEvent event) { 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/config/WebConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.config; 19 | 20 | import org.owasp.appsensor.core.AppSensorClient; 21 | import org.owasp.appsensor.core.DetectionSystem; 22 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 23 | import org.springframework.context.annotation.Bean; 24 | import org.springframework.context.annotation.ComponentScan; 25 | import org.springframework.context.annotation.Configuration; 26 | import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; 27 | 28 | import javax.validation.Validator; 29 | 30 | /** 31 | * Spring configuration file. 32 | * 33 | * @author Dominik Schadow 34 | */ 35 | @Configuration 36 | @EnableConfigurationProperties(DukeEncountersProperties.class) 37 | @ComponentScan(basePackages = "org.owasp.appsensor") 38 | public class WebConfig { 39 | @Bean 40 | public DetectionSystem detectionSystem(final AppSensorClient appSensorClient) { 41 | return new DetectionSystem(appSensorClient.getConfiguration().getServerConnection() 42 | .getClientApplicationIdentificationHeaderValue()); 43 | } 44 | 45 | @Bean 46 | public Validator localValidatorFactoryBean() { 47 | return new LocalValidatorFactoryBean(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/config/WebSecurityConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.config; 19 | 20 | import org.owasp.appsensor.integration.springsecurity.context.AppSensorSecurityContextRepository; 21 | import org.springframework.beans.factory.annotation.Autowired; 22 | import org.springframework.context.annotation.Bean; 23 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 24 | import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 25 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 26 | import org.springframework.security.config.annotation.web.builders.WebSecurity; 27 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 28 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 29 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 30 | import org.springframework.security.crypto.password.PasswordEncoder; 31 | import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; 32 | import org.springframework.security.web.context.SecurityContextRepository; 33 | 34 | import javax.servlet.http.HttpSessionListener; 35 | import javax.sql.DataSource; 36 | 37 | /** 38 | * Spring Security configuration. 39 | * 40 | * @author Dominik Schadow 41 | */ 42 | @EnableWebSecurity 43 | @EnableGlobalMethodSecurity(prePostEnabled = true) 44 | public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 45 | @Autowired 46 | private DataSource dataSource; 47 | @Autowired 48 | private DukeEncountersProperties properties; 49 | 50 | @Override 51 | protected void configure(final HttpSecurity http) throws Exception { 52 | // @formatter:off 53 | http 54 | .authorizeRequests() 55 | .mvcMatchers("/admin/**").hasRole("ADMIN") 56 | .mvcMatchers("/", "/register", "/encounters", "/search", "/error").permitAll() 57 | .mvcMatchers().authenticated() 58 | .and() 59 | .csrf() 60 | .ignoringAntMatchers("/admin/h2-console/*") 61 | .and() 62 | .formLogin() 63 | .loginPage("/login") 64 | .defaultSuccessUrl("/account") 65 | .permitAll() 66 | .and() 67 | .exceptionHandling() 68 | .authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login")) 69 | .and() 70 | .logout() 71 | .logoutSuccessUrl("/") 72 | .permitAll() 73 | .and() 74 | .rememberMe().rememberMeParameter("remember-me") 75 | .and() 76 | .securityContext().securityContextRepository(securityContextRepository()) 77 | .and() 78 | .headers() 79 | .contentSecurityPolicy("default-src 'self'; img-src 'self' https://camo.githubusercontent.com") 80 | .and() 81 | .frameOptions().sameOrigin(); 82 | // @formatter:on 83 | } 84 | 85 | /** 86 | * BCryptPasswordEncoder constructor takes a work factor as argument. The default is 10, the valid range is 4 to 31. 87 | * The amount of work increases exponentially. 88 | * 89 | * @return The PasswordEncoder to use for all dukeEncountersUser passwords 90 | */ 91 | @Bean 92 | public PasswordEncoder passwordEncoder() { 93 | return new BCryptPasswordEncoder(properties.getPasswordStrength()); 94 | } 95 | 96 | @Override 97 | public void configure(final WebSecurity web) { 98 | // @formatter:off 99 | web 100 | .ignoring() 101 | .antMatchers("/css/**", "/img/**", "/webjars/**"); 102 | // @formatter:on 103 | } 104 | 105 | /** 106 | * Enables JDBC authentication and sets the configured BCryptPasswordEncoder. 107 | * 108 | * @param auth The AuthenticationManagerBuilder 109 | * @throws Exception during configuration 110 | */ 111 | @Autowired 112 | public void configureGlobal(final AuthenticationManagerBuilder auth) throws Exception { 113 | // @formatter:off 114 | auth 115 | .jdbcAuthentication() 116 | .dataSource(dataSource) 117 | .passwordEncoder(passwordEncoder()); 118 | // @formatter:on 119 | } 120 | 121 | /** 122 | * Sets the AppSensorSecurityContextRepository as the SecurityContextRepository. 123 | * 124 | * @return The SecurityContextRepository to use 125 | */ 126 | @Bean 127 | public SecurityContextRepository securityContextRepository() { 128 | return new AppSensorSecurityContextRepository(); 129 | } 130 | 131 | /** 132 | * Adds the {@link SessionTimeoutListener} to invalidate a user session after the configured timeout. 133 | * 134 | * @return The SessionTimeoutListener 135 | */ 136 | @Bean 137 | public HttpSessionListener httpSessionTimeoutListener() { 138 | return new SessionTimeoutListener(); 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/confirmation/Confirmation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.confirmation; 19 | 20 | import de.dominikschadow.dukeencounters.encounter.DukeEncountersUser; 21 | import de.dominikschadow.dukeencounters.encounter.Encounter; 22 | import lombok.Data; 23 | import org.apache.commons.lang3.builder.ToStringBuilder; 24 | import org.springframework.format.annotation.DateTimeFormat; 25 | 26 | import javax.persistence.*; 27 | import java.util.Date; 28 | 29 | /** 30 | * Represents a single confirmation of a single encounter. 31 | * 32 | * @author Dominik Schadow 33 | */ 34 | @Entity 35 | @Table(name = "confirmations") 36 | @Data 37 | public class Confirmation { 38 | @Id 39 | @GeneratedValue 40 | private long id; 41 | @ManyToOne 42 | @JoinColumn(name = "user_id", nullable = false) 43 | private DukeEncountersUser user; 44 | @ManyToOne(fetch = FetchType.LAZY) 45 | @JoinColumn(name = "encounter_id", nullable = false) 46 | private Encounter encounter; 47 | @DateTimeFormat(pattern = "MM/dd/yyyy") 48 | private Date date; 49 | 50 | @Override 51 | public String toString() { 52 | return new ToStringBuilder(this). 53 | append("id", getId()). 54 | append("user", getUser()). 55 | append("encounter", getEncounter()). 56 | append("date", getDate()). 57 | toString(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/confirmation/ConfirmationController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.confirmation; 19 | 20 | import de.dominikschadow.dukeencounters.encounter.EncounterService; 21 | import de.dominikschadow.dukeencounters.user.UserService; 22 | import lombok.AllArgsConstructor; 23 | import lombok.extern.slf4j.Slf4j; 24 | import org.owasp.appsensor.core.DetectionPoint; 25 | import org.owasp.appsensor.core.DetectionSystem; 26 | import org.owasp.appsensor.core.Event; 27 | import org.owasp.appsensor.core.event.EventManager; 28 | import org.owasp.security.logging.SecurityMarkers; 29 | import org.springframework.security.access.prepost.PreAuthorize; 30 | import org.springframework.stereotype.Controller; 31 | import org.springframework.ui.Model; 32 | import org.springframework.web.bind.annotation.GetMapping; 33 | import org.springframework.web.bind.annotation.PostMapping; 34 | import org.springframework.web.bind.annotation.RequestParam; 35 | import org.springframework.web.servlet.ModelAndView; 36 | import org.springframework.web.servlet.mvc.support.RedirectAttributes; 37 | 38 | import java.util.List; 39 | 40 | import static org.owasp.appsensor.core.DetectionPoint.Category.INPUT_VALIDATION; 41 | 42 | /** 43 | * Controller to handle all encounter confirmation related requests. 44 | * 45 | * @author Dominik Schadow 46 | */ 47 | @Controller 48 | @Slf4j 49 | @AllArgsConstructor 50 | public class ConfirmationController { 51 | private final ConfirmationService confirmationService; 52 | private final EncounterService encounterService; 53 | private final UserService userService; 54 | private final DetectionSystem detectionSystem; 55 | private final EventManager ids; 56 | 57 | @GetMapping("/confirmations") 58 | @PreAuthorize("hasAnyRole('USER','ADMIN')") 59 | public String getConfirmations(final Model model, 60 | @RequestParam(name = "type", required = false) final String type) { 61 | List confirmations = confirmationService.getConfirmations(type); 62 | model.addAttribute("confirmations", confirmations); 63 | 64 | return "user/confirmations"; 65 | } 66 | 67 | @PostMapping("/confirmation/add") 68 | @PreAuthorize("hasAnyRole('USER','ADMIN')") 69 | public ModelAndView addConfirmation(final long encounterId, final RedirectAttributes redirectAttributes) { 70 | String username = userService.getUsername(); 71 | 72 | if (encounterService.isOwnEncounter(encounterId, username)) { 73 | log.info(SecurityMarkers.SECURITY_FAILURE, "User {} is owner of encounter {} and tried to confirm it", 74 | username, encounterId); 75 | 76 | fireConfirmationErrorEvent(); 77 | redirectAttributes.addFlashAttribute("ownEncounter", true); 78 | } else if (confirmationService.hasConfirmedEncounter(username, encounterId)) { 79 | log.info(SecurityMarkers.SECURITY_FAILURE, "User {} has already confirmed encounter {} and tried to " 80 | + "confirm it again", username, encounterId); 81 | 82 | fireConfirmationErrorEvent(); 83 | redirectAttributes.addFlashAttribute("secondConfirm", true); 84 | } else { 85 | confirmationService.addConfirmation(username, encounterId); 86 | 87 | log.info(SecurityMarkers.SECURITY_SUCCESS, "User {} confirmed encounter {}", username, encounterId); 88 | } 89 | 90 | return new ModelAndView("redirect:/account"); 91 | } 92 | 93 | @PostMapping("/confirmation/revoke") 94 | @PreAuthorize("hasAnyRole('USER','ADMIN')") 95 | public ModelAndView revokeConfirmation(final long confirmationId) { 96 | String username = userService.getUsername(); 97 | 98 | confirmationService.deleteConfirmation(username, confirmationId); 99 | 100 | log.info(SecurityMarkers.SECURITY_SUCCESS, "User {} revoked confirmation {}", username, confirmationId); 101 | 102 | return new ModelAndView("redirect:/account"); 103 | } 104 | 105 | private void fireConfirmationErrorEvent() { 106 | DetectionPoint detectionPoint = new DetectionPoint(INPUT_VALIDATION, "IE5-001"); 107 | ids.addEvent(new Event(userService.getUser(), detectionPoint, detectionSystem)); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/confirmation/ConfirmationRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.confirmation; 19 | 20 | import org.springframework.data.jpa.repository.JpaRepository; 21 | import org.springframework.data.jpa.repository.JpaSpecificationExecutor; 22 | import org.springframework.data.jpa.repository.Query; 23 | import org.springframework.data.repository.query.Param; 24 | 25 | import java.util.List; 26 | 27 | /** 28 | * JPA repository class to access {@link Confirmation}s. 29 | * 30 | * @author Dominik Schadow 31 | */ 32 | public interface ConfirmationRepository extends JpaRepository, JpaSpecificationExecutor { 33 | @Query(value = "select c from Confirmation c, DukeEncountersUser u where c.user = u.id and u.username = :username" 34 | + " order by c.date desc") 35 | List findAllByUsername(@Param("username") String username); 36 | 37 | @Query(value = "select c from Confirmation c, DukeEncountersUser u where c.user = u.id and u.username = :username" 38 | + " and c.encounter.id = :encounterId") 39 | Confirmation findByUsernameAndEncounterId(@Param("username") String username, @Param("encounterId") long 40 | encounterId); 41 | } 42 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/confirmation/ConfirmationService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.confirmation; 19 | 20 | import de.dominikschadow.dukeencounters.encounter.EncounterService; 21 | import de.dominikschadow.dukeencounters.user.UserService; 22 | import lombok.AllArgsConstructor; 23 | import lombok.NonNull; 24 | import lombok.extern.slf4j.Slf4j; 25 | import org.owasp.security.logging.SecurityMarkers; 26 | import org.springframework.stereotype.Service; 27 | 28 | import javax.validation.constraints.NotNull; 29 | import java.util.Date; 30 | import java.util.List; 31 | import java.util.Objects; 32 | 33 | /** 34 | * CRUD service for all confirmation related operations. 35 | * 36 | * @author Dominik Schadow 37 | */ 38 | @Service 39 | @Slf4j 40 | @AllArgsConstructor 41 | public class ConfirmationService { 42 | private final ConfirmationRepository repository; 43 | private final UserService userService; 44 | private final EncounterService encounterService; 45 | 46 | public List getConfirmationsByUsername(@NonNull final String username) { 47 | List confirmations = repository.findAllByUsername(username); 48 | 49 | log.info("Query for user {} confirmations returned {} confirmations", username, confirmations.size()); 50 | 51 | return confirmations; 52 | } 53 | 54 | public Confirmation getConfirmationByUsernameAndEncounterId(@NonNull final String username, 55 | final long encounterId) { 56 | Confirmation confirmation = repository.findByUsernameAndEncounterId(username, encounterId); 57 | 58 | log.info("Query for user {} confirmations returned {}", username, confirmation); 59 | 60 | return confirmation; 61 | } 62 | 63 | public Confirmation addConfirmation(@NotNull final String username, final long encounterId) { 64 | Confirmation newConfirmation = new Confirmation(); 65 | newConfirmation.setUser(userService.getDukeEncountersUser(username)); 66 | newConfirmation.setDate(new Date()); 67 | newConfirmation.setEncounter(encounterService.getEncounterById(encounterId)); 68 | 69 | Confirmation confirmation = repository.save(newConfirmation); 70 | 71 | log.info("Created new confirmation {}", confirmation); 72 | 73 | return confirmation; 74 | } 75 | 76 | public void deleteConfirmation(@NonNull final String username, final long confirmationId) { 77 | repository.delete(confirmationId); 78 | 79 | log.warn(SecurityMarkers.SECURITY_AUDIT, "User {} deleted confirmation {}", username, confirmationId); 80 | } 81 | 82 | public boolean hasConfirmedEncounter(@NonNull final String username, final long encounterId) { 83 | return getConfirmationByUsernameAndEncounterId(username, encounterId) != null; 84 | } 85 | 86 | public List getConfirmations(final String type) { 87 | List confirmations; 88 | 89 | if (Objects.equals("own", type)) { 90 | String username = userService.getUsername(); 91 | 92 | log.warn(SecurityMarkers.SECURITY_AUDIT, "Querying confirmations for user {}", username); 93 | 94 | confirmations = repository.findAllByUsername(username); 95 | } else { 96 | confirmations = repository.findAll(); 97 | } 98 | 99 | log.info("Query returned {} confirmations", confirmations.size()); 100 | 101 | return confirmations; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/encounter/Authority.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.encounter; 19 | 20 | import lombok.Data; 21 | import lombok.NoArgsConstructor; 22 | import org.hibernate.validator.constraints.NotBlank; 23 | 24 | import javax.persistence.*; 25 | 26 | /** 27 | * Holds a role in the application. 28 | * 29 | * @author Dominik Schadow 30 | */ 31 | @Entity 32 | @Table(name = "authorities", uniqueConstraints = @UniqueConstraint(columnNames = {"username"})) 33 | @Data 34 | @NoArgsConstructor 35 | public class Authority { 36 | @Id 37 | @GeneratedValue 38 | private long id; 39 | @NotBlank(message = "Username may not be null") 40 | private String username; 41 | @NotBlank(message = "Authority may not be null") 42 | private String authority; 43 | 44 | public Authority(final String username, final String authority) { 45 | this.username = username; 46 | this.authority = authority; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/encounter/BaseEncounterValidator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.encounter; 19 | 20 | import de.dominikschadow.dukeencounters.Constants; 21 | import de.dominikschadow.dukeencounters.security.SecurityValidationService; 22 | import de.dominikschadow.dukeencounters.user.UserService; 23 | import lombok.AllArgsConstructor; 24 | import org.owasp.appsensor.core.DetectionPoint; 25 | import org.owasp.appsensor.core.DetectionSystem; 26 | import org.owasp.appsensor.core.Event; 27 | import org.owasp.appsensor.core.event.EventManager; 28 | import org.springframework.validation.Errors; 29 | import org.springframework.validation.Validator; 30 | import org.springframework.validation.beanvalidation.SpringValidatorAdapter; 31 | 32 | import static org.owasp.appsensor.core.DetectionPoint.Category.*; 33 | 34 | /** 35 | * Base validator class for encounter common properties like event, location and country. 36 | * 37 | * @author Dominik Schadow 38 | */ 39 | @AllArgsConstructor 40 | public abstract class BaseEncounterValidator implements Validator { 41 | protected final SpringValidatorAdapter validator; 42 | protected final SecurityValidationService securityValidationService; 43 | private final EventManager ids; 44 | private final UserService userService; 45 | private final DetectionSystem detectionSystem; 46 | 47 | /** 48 | * Validates the base data of an encounter: event, location and country. 49 | * 50 | * @param event The event the encounter took place 51 | * @param location The location the encounter took place 52 | * @param country The country the encounter took place 53 | * @param errors Validation errors will be added to this object 54 | */ 55 | protected void validateBaseData(final String event, final String location, final String country, 56 | final Errors errors) { 57 | if (securityValidationService.hasXssPayload(event)) { 58 | fireXssEvent(); 59 | errors.rejectValue("event", Constants.XSS_ERROR_CODE); 60 | } else if (securityValidationService.hasSqlIPayload(event)) { 61 | fireSqlIEvent(); 62 | errors.rejectValue("event", Constants.SQLI_ERROR_CODE); 63 | } 64 | 65 | if (securityValidationService.hasXssPayload(location)) { 66 | fireXssEvent(); 67 | errors.rejectValue("location", Constants.XSS_ERROR_CODE); 68 | } else if (securityValidationService.hasSqlIPayload(location)) { 69 | fireSqlIEvent(); 70 | errors.rejectValue("location", Constants.SQLI_ERROR_CODE); 71 | } 72 | 73 | if (securityValidationService.hasXssPayload(country)) { 74 | fireXssEvent(); 75 | errors.rejectValue("country", Constants.XSS_ERROR_CODE); 76 | } else if (securityValidationService.hasSqlIPayload(country)) { 77 | fireSqlIEvent(); 78 | errors.rejectValue("country", Constants.SQLI_ERROR_CODE); 79 | } 80 | } 81 | 82 | /** 83 | * Fires a new XSS event with the label {@code IE1-001}. 84 | */ 85 | protected final void fireXssEvent() { 86 | DetectionPoint detectionPoint = new DetectionPoint(INPUT_VALIDATION, "IE1-001"); 87 | ids.addEvent(new Event(userService.getUser(), detectionPoint, detectionSystem)); 88 | } 89 | 90 | /** 91 | * Fires a new SQL injection event with the label {@code CIE1-001}. 92 | */ 93 | protected final void fireSqlIEvent() { 94 | DetectionPoint detectionPoint = new DetectionPoint(COMMAND_INJECTION, "CIE1-001"); 95 | ids.addEvent(new Event(userService.getUser(), detectionPoint, detectionSystem)); 96 | } 97 | 98 | /** 99 | * Fires a new invalid value event with the label {@code ACE2-001}. 100 | */ 101 | protected final void fireInvalidValueEvent() { 102 | DetectionPoint detectionPoint = new DetectionPoint(ACCESS_CONTROL, "ACE2-001"); 103 | ids.addEvent(new Event(userService.getUser(), detectionPoint, detectionSystem)); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/encounter/DukeEncountersUser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.encounter; 19 | 20 | import com.google.common.base.CharMatcher; 21 | import com.google.common.base.Strings; 22 | import de.dominikschadow.dukeencounters.user.Level; 23 | import lombok.Data; 24 | import org.hibernate.validator.constraints.Email; 25 | import org.hibernate.validator.constraints.Length; 26 | import org.hibernate.validator.constraints.NotBlank; 27 | 28 | import javax.persistence.*; 29 | import java.util.Date; 30 | 31 | /** 32 | * Holds a user of the application. 33 | * 34 | * @author Dominik Schadow 35 | */ 36 | @Entity 37 | @Table(name = "users", uniqueConstraints = @UniqueConstraint(columnNames = {"username"})) 38 | @Data 39 | public class DukeEncountersUser { 40 | @Id 41 | @GeneratedValue 42 | private long id; 43 | @NotBlank(message = "Your firstname is required") 44 | private String firstname; 45 | @NotBlank(message = "Your lastname is required") 46 | private String lastname; 47 | @NotBlank(message = "Your username is required") 48 | @Column(nullable = false) 49 | private String username; 50 | @NotBlank(message = "Your email address is required") 51 | @Email 52 | @Column(nullable = false) 53 | private String email; 54 | @Length(min = 10, max = 1024, message = "A password is required and must contain between 10 and 60 characters") 55 | @Column(nullable = false, length = 60) 56 | private String password; 57 | @Transient 58 | private String confirmPassword; 59 | private Date registrationDate; 60 | @Enumerated(EnumType.STRING) 61 | private Level level; 62 | private boolean enabled; 63 | @OneToOne 64 | private Authority authority; 65 | 66 | @Override 67 | public String toString() { 68 | String name = Strings.nullToEmpty(getFirstname()) + " " + Strings.nullToEmpty(getLastname()); 69 | name = CharMatcher.WHITESPACE.trimTrailingFrom(name); 70 | 71 | return name; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/encounter/Encounter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.encounter; 19 | 20 | import de.dominikschadow.dukeencounters.confirmation.Confirmation; 21 | import lombok.Data; 22 | import org.hibernate.validator.constraints.NotBlank; 23 | import org.springframework.format.annotation.DateTimeFormat; 24 | 25 | import javax.persistence.*; 26 | import javax.validation.constraints.NotNull; 27 | import java.util.Date; 28 | import java.util.List; 29 | 30 | /** 31 | * Represents a single encounter. 32 | * 33 | * @author Dominik Schadow 34 | */ 35 | @Entity 36 | @Table(name = "encounters") 37 | @Data 38 | public class Encounter { 39 | @Id 40 | @GeneratedValue 41 | private long id; 42 | @NotBlank(message = "An event is required for each encounter") 43 | @Column(nullable = false) 44 | private String event; 45 | @NotBlank(message = "A location is required for each encounter") 46 | @Column(nullable = false) 47 | private String location; 48 | @NotBlank(message = "A country is required for each encounter") 49 | @Column(nullable = false) 50 | private String country; 51 | private String comment; 52 | @NotNull(message = "A date in the format MM/dd/yyyy is required for each encounter") 53 | @Column(nullable = false) 54 | @DateTimeFormat(pattern = "MM/dd/yyyy") 55 | private Date date; 56 | @ManyToOne 57 | @JoinColumn(name = "user_id", nullable = false) 58 | private DukeEncountersUser user; 59 | @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "encounter") 60 | private List confirmations; 61 | 62 | public String getLikelihood() { 63 | return Likelihood.getLikelihood(getConfirmations()).getName(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/encounter/EncounterController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.encounter; 19 | 20 | import de.dominikschadow.dukeencounters.user.UserService; 21 | import lombok.AllArgsConstructor; 22 | import org.apache.commons.lang3.StringUtils; 23 | import org.owasp.appsensor.core.DetectionPoint; 24 | import org.owasp.appsensor.core.DetectionSystem; 25 | import org.owasp.appsensor.core.Event; 26 | import org.owasp.appsensor.core.event.EventManager; 27 | import org.springframework.security.access.prepost.PreAuthorize; 28 | import org.springframework.stereotype.Controller; 29 | import org.springframework.ui.Model; 30 | import org.springframework.validation.BindingResult; 31 | import org.springframework.web.bind.WebDataBinder; 32 | import org.springframework.web.bind.annotation.*; 33 | import org.springframework.web.servlet.ModelAndView; 34 | import org.springframework.web.servlet.mvc.support.RedirectAttributes; 35 | 36 | import javax.validation.Valid; 37 | import java.util.List; 38 | 39 | import static org.owasp.appsensor.core.DetectionPoint.Category.REQUEST; 40 | 41 | /** 42 | * Controller to handle all encounter related requests. 43 | * 44 | * @author Dominik Schadow 45 | */ 46 | @Controller 47 | @AllArgsConstructor 48 | public class EncounterController { 49 | private final EncounterService encounterService; 50 | private final EncounterValidator validator; 51 | private final UserService userService; 52 | private final DetectionSystem detectionSystem; 53 | private final EventManager ids; 54 | 55 | @GetMapping("/encounters") 56 | public String getEncounters(final Model model, @RequestParam(name = "type", required = false) final String type) { 57 | boolean confirmable = !StringUtils.equals(userService.getUser().getUsername(), "anonymousUser") 58 | && !StringUtils.equals("own", type); 59 | 60 | List encounters = encounterService.getEncounters(type); 61 | model.addAttribute("encounters", encounters); 62 | model.addAttribute("confirmable", confirmable); 63 | 64 | return "encounters"; 65 | } 66 | 67 | @GetMapping("/encounter/create") 68 | @PreAuthorize("hasAnyRole('USER','ADMIN')") 69 | public String createEncounter(@ModelAttribute final Encounter encounter) { 70 | return "user/createEncounter"; 71 | } 72 | 73 | @PostMapping("/encounter/create") 74 | @PreAuthorize("hasAnyRole('USER','ADMIN')") 75 | public String saveEncounter(@Valid final Encounter encounter, final Model model, final BindingResult result) { 76 | if (result.hasErrors()) { 77 | model.addAttribute("formErrors", result.getAllErrors()); 78 | return "user/createEncounter"; 79 | } 80 | 81 | encounterService.createEncounter(encounter); 82 | model.addAttribute("confirmable", true); 83 | 84 | return "redirect:/encounters"; 85 | } 86 | 87 | @PostMapping("/encounter/delete") 88 | @PreAuthorize("hasAnyRole('USER','ADMIN')") 89 | public ModelAndView deleteEncounter(final long encounterId) { 90 | encounterService.deleteEncounter(encounterId); 91 | 92 | return new ModelAndView("redirect:/account"); 93 | } 94 | 95 | @GetMapping("/encounter/{id}") 96 | @PreAuthorize("hasAnyRole('USER','ADMIN')") 97 | public String encounterById(@PathVariable("id") final long encounterId, final Model model, 98 | final RedirectAttributes redirectAttributes) { 99 | Encounter encounter = encounterService.getEncounterById(encounterId); 100 | 101 | if (encounter == null) { 102 | fireInvalidUrlParameterEvent(); 103 | redirectAttributes.addFlashAttribute("encounterFailure", true); 104 | redirectAttributes.addFlashAttribute("confirmable", true); 105 | 106 | return "redirect:/encounters"; 107 | } 108 | 109 | model.addAttribute("encounter", encounter); 110 | 111 | return "user/encounterDetails"; 112 | } 113 | 114 | private void fireInvalidUrlParameterEvent() { 115 | DetectionPoint detectionPoint = new DetectionPoint(REQUEST, "RE8-001"); 116 | ids.addEvent(new Event(userService.getUser(), detectionPoint, detectionSystem)); 117 | } 118 | 119 | @InitBinder 120 | protected void initBinder(final WebDataBinder binder) { 121 | binder.setValidator(validator); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/encounter/EncounterRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.encounter; 19 | 20 | import org.springframework.data.domain.Pageable; 21 | import org.springframework.data.jpa.repository.JpaRepository; 22 | import org.springframework.data.jpa.repository.JpaSpecificationExecutor; 23 | import org.springframework.data.jpa.repository.Query; 24 | import org.springframework.data.repository.query.Param; 25 | 26 | import java.util.List; 27 | 28 | /** 29 | * JPA repository class to access {@link Encounter}s. 30 | * 31 | * @author Dominik Schadow 32 | */ 33 | public interface EncounterRepository extends JpaRepository, JpaSpecificationExecutor { 34 | @Query(value = "select e from Encounter e") 35 | List findWithPageable(Pageable latestTen); 36 | 37 | @Query(value = "select e from Encounter e, DukeEncountersUser u where e.user = u.id and u.username = :username " 38 | + "order by e.date desc ") 39 | List findAllByUsername(@Param("username") String username); 40 | 41 | @Query(value = "select e from Encounter e, DukeEncountersUser u where e.user = u.id and u.username = :username " 42 | + "and e.id = :encounterId") 43 | Encounter findByIdAndUsername(@Param("encounterId") long encounterId, @Param("username") String username); 44 | 45 | List findByEventContaining(String event); 46 | } 47 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/encounter/EncounterSpecification.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.encounter; 19 | 20 | import org.springframework.data.jpa.domain.Specification; 21 | 22 | import java.util.Calendar; 23 | import java.util.Date; 24 | 25 | /** 26 | * Specification to filter encounters based on the entered search filter. 27 | * 28 | * @author Dominik Schadow 29 | */ 30 | public class EncounterSpecification { 31 | /** 32 | * Utility class, hidden constructor. 33 | */ 34 | private EncounterSpecification() { 35 | } 36 | 37 | public static Specification encounterAfterYear(final int year) { 38 | Calendar calendar = Calendar.getInstance(); 39 | calendar.set(Calendar.YEAR, year); 40 | return (root, query, cb) -> cb.greaterThanOrEqualTo(root.get("date"), calendar.getTime()); 41 | } 42 | 43 | public static Specification encounterByConfirmations(final int confirmations) { 44 | // TODO count confirmations 45 | return (root, query, cb) -> cb.greaterThanOrEqualTo(root.get(""), confirmations); 46 | } 47 | 48 | public static Specification encounterByEvent(final String event) { 49 | return (root, query, cb) -> cb.like(root.get("event"), event); 50 | } 51 | 52 | public static Specification encounterByLocation(final String location) { 53 | return (root, query, cb) -> cb.like(root.get("location"), location); 54 | } 55 | 56 | public static Specification encounterByCountry(final String country) { 57 | return (root, query, cb) -> cb.like(root.get("country"), country); 58 | } 59 | 60 | public static Specification encounterByLikelihood(final Likelihood likelihood) { 61 | return (root, query, cb) -> cb.equal(root.get("likelihood"), likelihood.getName()); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/encounter/EncounterValidator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.encounter; 19 | 20 | import de.dominikschadow.dukeencounters.Constants; 21 | import de.dominikschadow.dukeencounters.security.SecurityValidationService; 22 | import de.dominikschadow.dukeencounters.user.UserService; 23 | import org.owasp.appsensor.core.DetectionSystem; 24 | import org.owasp.appsensor.core.event.EventManager; 25 | import org.springframework.stereotype.Component; 26 | import org.springframework.validation.Errors; 27 | import org.springframework.validation.beanvalidation.SpringValidatorAdapter; 28 | 29 | /** 30 | * Validates an encounter: checks required fields and scans for basic Cross-Site Scripting and SQL Injection payload. 31 | * 32 | * @author Dominik Schadow 33 | */ 34 | @Component 35 | public class EncounterValidator extends BaseEncounterValidator { 36 | public EncounterValidator(EventManager ids, DetectionSystem detectionSystem, SpringValidatorAdapter validator, 37 | UserService userService, SecurityValidationService securityValidationService) { 38 | super(validator, securityValidationService, ids, userService, detectionSystem); 39 | } 40 | 41 | @Override 42 | public boolean supports(final Class clazz) { 43 | return Encounter.class.equals(clazz); 44 | } 45 | 46 | @Override 47 | public void validate(final Object target, final Errors errors) { 48 | validator.validate(target, errors); 49 | 50 | Encounter encounter = (Encounter) target; 51 | 52 | validateBaseData(encounter.getEvent(), encounter.getLocation(), encounter.getCountry(), errors); 53 | 54 | if (securityValidationService.hasXssPayload(encounter.getComment())) { 55 | fireXssEvent(); 56 | errors.rejectValue("comment", Constants.XSS_ERROR_CODE); 57 | } else if (securityValidationService.hasSqlIPayload(encounter.getComment())) { 58 | fireSqlIEvent(); 59 | errors.rejectValue("comment", Constants.SQLI_ERROR_CODE); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/encounter/Likelihood.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.encounter; 19 | 20 | import com.google.common.base.Strings; 21 | import de.dominikschadow.dukeencounters.confirmation.Confirmation; 22 | 23 | import java.util.List; 24 | import java.util.Objects; 25 | 26 | /** 27 | * Encounter likelihood enum. 28 | * 29 | * @author Dominik Schadow 30 | */ 31 | public enum Likelihood { 32 | ANY("*"), NOT_CONFIRMED("not confirmed"), PLAUSIBLE("plausible"), CONFIRMED("confirmed"); 33 | 34 | private final String name; 35 | 36 | Likelihood(String name) { 37 | this.name = name; 38 | } 39 | 40 | public String getName() { 41 | return name; 42 | } 43 | 44 | public static Likelihood fromString(String value) { 45 | if (!Strings.isNullOrEmpty(value)) { 46 | for (Likelihood l : Likelihood.values()) { 47 | if (value.equals(l.toString())) { 48 | return l; 49 | } 50 | } 51 | } 52 | 53 | throw new IllegalArgumentException("No enum found for " + value); 54 | } 55 | 56 | public static Likelihood getLikelihood(List confirmations) { 57 | if (Objects.isNull(confirmations) || confirmations.isEmpty()) { 58 | return Likelihood.NOT_CONFIRMED; 59 | } 60 | 61 | return confirmations.size() < 3 ? Likelihood.PLAUSIBLE : Likelihood.CONFIRMED; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/home/HomeController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.home; 19 | 20 | import de.dominikschadow.dukeencounters.encounter.Encounter; 21 | import de.dominikschadow.dukeencounters.encounter.EncounterService; 22 | import lombok.AllArgsConstructor; 23 | import org.springframework.stereotype.Controller; 24 | import org.springframework.ui.Model; 25 | import org.springframework.web.bind.annotation.GetMapping; 26 | 27 | import java.util.List; 28 | 29 | /** 30 | * Controller for the main page. 31 | * 32 | * @author Dominik Schadow 33 | */ 34 | @Controller 35 | @AllArgsConstructor 36 | public class HomeController { 37 | private final EncounterService encounterService; 38 | 39 | /** 40 | * Queries for the latest encounters, adds them to the model and returns the index page. 41 | * 42 | * @param model The model attribute container 43 | * @return Index URL 44 | */ 45 | @GetMapping("/") 46 | public String home(final Model model) { 47 | List encounters = encounterService.getLatestEncounters(); 48 | model.addAttribute("encounters", encounters); 49 | 50 | return "index"; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/login/LoginController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.login; 19 | 20 | import org.springframework.stereotype.Controller; 21 | import org.springframework.web.bind.annotation.GetMapping; 22 | import org.springframework.web.bind.annotation.RequestParam; 23 | import org.springframework.web.servlet.ModelAndView; 24 | 25 | /** 26 | * Controller for login related requests. 27 | * 28 | * @author Dominik Schadow 29 | */ 30 | @Controller 31 | public class LoginController { 32 | /** 33 | * Shows the login page. 34 | * 35 | * @param error An optional error message to show (e.g. login failed) 36 | * @return Login URL 37 | */ 38 | @GetMapping("/login") 39 | public ModelAndView login(@RequestParam(value = "error", required = false) final String error) { 40 | ModelAndView model = new ModelAndView("login"); 41 | 42 | if (error != null) { 43 | model.addObject("loginError", true); 44 | } 45 | 46 | return model; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/search/SearchController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.search; 19 | 20 | import de.dominikschadow.dukeencounters.encounter.Encounter; 21 | import de.dominikschadow.dukeencounters.encounter.EncounterService; 22 | import lombok.AllArgsConstructor; 23 | import org.springframework.stereotype.Controller; 24 | import org.springframework.validation.BindingResult; 25 | import org.springframework.web.bind.WebDataBinder; 26 | import org.springframework.web.bind.annotation.*; 27 | import org.springframework.web.servlet.ModelAndView; 28 | 29 | import javax.validation.Valid; 30 | import java.util.LinkedHashMap; 31 | import java.util.List; 32 | import java.util.Map; 33 | 34 | /** 35 | * Controller for all search related requests. 36 | * 37 | * @author Dominik Schadow 38 | */ 39 | @Controller 40 | @AllArgsConstructor 41 | public class SearchController { 42 | private final EncounterService encounterService; 43 | private final SearchFilterValidator validator; 44 | 45 | /** 46 | * Shows the search form. 47 | * 48 | * @param searchFilter The new SearchFilter 49 | * @return Search URL 50 | */ 51 | @GetMapping("/search") 52 | public String searchEncounters(@ModelAttribute final SearchFilter searchFilter) { 53 | return "search"; 54 | } 55 | 56 | /** 57 | * Uses the input text to search for the encounter event. 58 | * 59 | * @param event The events name 60 | * @return ModelAndView with encounters URL and a model map 61 | */ 62 | @PostMapping("/search") 63 | public ModelAndView searchEncounterByEvent(@RequestParam("quickSearch") final String event) { 64 | List encounters = encounterService.getEncountersByEvent(event); 65 | 66 | Map modelMap = new LinkedHashMap<>(); 67 | modelMap.put("encounters", encounters); 68 | 69 | return new ModelAndView("encounters", modelMap); 70 | } 71 | 72 | /** 73 | * Search the encounters based on the given search filter. 74 | * 75 | * @param searchFilter The search filter identifying encounters 76 | * @param result BindingResult 77 | * @return ModelAndView with encounters URL and a model map 78 | */ 79 | @PostMapping("/encounters") 80 | public ModelAndView searchEncounters(@Valid final SearchFilter searchFilter, final BindingResult result) { 81 | if (result.hasErrors()) { 82 | return new ModelAndView("search", "formErrors", result.getAllErrors()); 83 | } 84 | 85 | List encounters = encounterService.getEncounters(searchFilter); 86 | 87 | Map modelMap = new LinkedHashMap<>(); 88 | modelMap.put("encounters", encounters); 89 | modelMap.put("searchFilter", searchFilter); 90 | 91 | return new ModelAndView("encounters", modelMap); 92 | } 93 | 94 | @InitBinder 95 | protected void initBinder(final WebDataBinder binder) { 96 | binder.setValidator(validator); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/search/SearchFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.search; 19 | 20 | import com.google.common.base.Strings; 21 | import lombok.Data; 22 | 23 | /** 24 | * SearchFilter to search for Duke encounters based on various fields. 25 | * 26 | * @author Dominik Schadow 27 | */ 28 | @Data 29 | public class SearchFilter { 30 | private String event; 31 | private String location; 32 | private String country; 33 | private String year; 34 | private String likelihood; 35 | private int confirmations; 36 | 37 | @Override 38 | public String toString() { 39 | StringBuilder searchFilterString = new StringBuilder(); 40 | if (!Strings.isNullOrEmpty(getEvent())) { 41 | searchFilterString.append("Event: "); 42 | searchFilterString.append(getEvent()); 43 | searchFilterString.append(", "); 44 | } 45 | if (!Strings.isNullOrEmpty(getLocation())) { 46 | searchFilterString.append("Location: "); 47 | searchFilterString.append(getLocation()); 48 | searchFilterString.append(", "); 49 | } 50 | if (!Strings.isNullOrEmpty(getCountry())) { 51 | searchFilterString.append("Country: "); 52 | searchFilterString.append(getCountry()); 53 | searchFilterString.append(", "); 54 | } 55 | if (!Strings.isNullOrEmpty(getYear())) { 56 | searchFilterString.append("Year: "); 57 | searchFilterString.append(getYear()); 58 | searchFilterString.append(", "); 59 | } 60 | if (!Strings.isNullOrEmpty(getLikelihood())) { 61 | searchFilterString.append("Likelihood: "); 62 | searchFilterString.append(getLikelihood()); 63 | searchFilterString.append(", "); 64 | } 65 | if (getConfirmations() > 0) { 66 | searchFilterString.append("Confirmations: "); 67 | searchFilterString.append(getConfirmations()); 68 | } 69 | 70 | if (searchFilterString.toString().endsWith(", ")) { 71 | return searchFilterString.substring(0, searchFilterString.length() - 2); 72 | } 73 | 74 | return searchFilterString.toString(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/search/SearchFilterValidator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.search; 19 | 20 | import de.dominikschadow.dukeencounters.Constants; 21 | import de.dominikschadow.dukeencounters.encounter.BaseEncounterValidator; 22 | import de.dominikschadow.dukeencounters.encounter.Likelihood; 23 | import de.dominikschadow.dukeencounters.security.SecurityValidationService; 24 | import de.dominikschadow.dukeencounters.user.UserService; 25 | import lombok.extern.slf4j.Slf4j; 26 | import org.apache.commons.lang3.StringUtils; 27 | import org.owasp.appsensor.core.DetectionSystem; 28 | import org.owasp.appsensor.core.event.EventManager; 29 | import org.owasp.security.logging.SecurityMarkers; 30 | import org.springframework.stereotype.Component; 31 | import org.springframework.validation.Errors; 32 | import org.springframework.validation.beanvalidation.SpringValidatorAdapter; 33 | 34 | /** 35 | * Validates a search filter: scans for basic Cross-Site Scripting and SQL Injection payload. 36 | * 37 | * @author Dominik Schadow 38 | */ 39 | @Component 40 | @Slf4j 41 | public class SearchFilterValidator extends BaseEncounterValidator { 42 | public SearchFilterValidator(EventManager ids, DetectionSystem detectionSystem, SpringValidatorAdapter validator, 43 | UserService userService, SecurityValidationService securityValidationService) { 44 | super(validator, securityValidationService, ids, userService, detectionSystem); 45 | } 46 | 47 | @Override 48 | public boolean supports(final Class clazz) { 49 | return SearchFilter.class.equals(clazz); 50 | } 51 | 52 | @Override 53 | public void validate(final Object target, final Errors errors) { 54 | validator.validate(target, errors); 55 | 56 | SearchFilter filter = (SearchFilter) target; 57 | 58 | validateBaseData(filter.getEvent(), filter.getLocation(), filter.getCountry(), errors); 59 | 60 | if (securityValidationService.hasXssPayload(filter.getYear())) { 61 | fireXssEvent(); 62 | errors.rejectValue("year", Constants.XSS_ERROR_CODE); 63 | } else if (securityValidationService.hasSqlIPayload(filter.getYear())) { 64 | fireSqlIEvent(); 65 | errors.rejectValue("year", Constants.SQLI_ERROR_CODE); 66 | } else if (StringUtils.isNotEmpty(filter.getYear())) { 67 | if (StringUtils.isNumeric(filter.getYear())) { 68 | int year = Integer.parseInt(filter.getYear()); 69 | 70 | if (year < Constants.YEAR_OF_JAVA_CREATION) { 71 | log.info(SecurityMarkers.SECURITY_FAILURE, "Requested {} as event year - possible typo", 72 | filter.getYear()); 73 | errors.rejectValue("year", Constants.INVALID_YEAR_ERROR_CODE); 74 | } 75 | } else { 76 | errors.rejectValue("year", Constants.INVALID_YEAR_ERROR_CODE); 77 | } 78 | } 79 | 80 | try { 81 | Likelihood.fromString(filter.getLikelihood()); 82 | } catch (IllegalArgumentException ex) { 83 | log.error(ex.getMessage(), ex); 84 | log.info(SecurityMarkers.SECURITY_FAILURE, "Requested {} as likelihood - out of configured range", 85 | filter.getLikelihood()); 86 | fireInvalidValueEvent(); 87 | errors.rejectValue("likelihood", Constants.ATTACK_ERROR_CODE); 88 | } 89 | 90 | if (filter.getConfirmations() < 0 || filter.getConfirmations() > 10) { 91 | log.info(SecurityMarkers.SECURITY_FAILURE, "Requested {} confirmations - out of configured range", 92 | filter.getConfirmations()); 93 | fireInvalidValueEvent(); 94 | errors.rejectValue("confirmations", Constants.ATTACK_ERROR_CODE); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/security/SecurityValidationService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.security; 19 | 20 | import org.apache.commons.lang3.StringUtils; 21 | import org.springframework.stereotype.Service; 22 | 23 | import javax.validation.constraints.NotNull; 24 | 25 | /** 26 | * Searches for different attack strings with incomplete (and simple!) blacklists. Detects some Cross-Site Scripting 27 | * (XSS) and SQL Injection attacks. 28 | * 29 | * @author Dominik Schadow 30 | */ 31 | @Service 32 | public class SecurityValidationService { 33 | public final boolean hasXssPayload(@NotNull final String payload) { 34 | return containsAnyIgnoreCase(payload, "<", "script", "onload", "eval", "document.cookie"); 35 | } 36 | 37 | public final boolean hasSqlIPayload(@NotNull final String payload) { 38 | return containsAnyIgnoreCase(payload, "drop", "insert", "update", "delete", "union", "select", "exec", "fetch", 39 | "' or '1'='1", "' or 1=1"); 40 | } 41 | 42 | private boolean containsAnyIgnoreCase(final String payload, final String... searchStrings) { 43 | for (String searchString : searchStrings) { 44 | if (StringUtils.containsIgnoreCase(payload, searchString)) { 45 | return true; 46 | } 47 | } 48 | 49 | return false; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/user/AuthorityRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.user; 19 | 20 | import de.dominikschadow.dukeencounters.encounter.Authority; 21 | import org.springframework.data.jpa.repository.JpaRepository; 22 | 23 | /** 24 | * JPA repository class to access {@link Authority}s. 25 | * 26 | * @author Dominik Schadow 27 | */ 28 | public interface AuthorityRepository extends JpaRepository { 29 | } 30 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/user/DukeEncountersUserValidator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.user; 19 | 20 | import de.dominikschadow.dukeencounters.Constants; 21 | import de.dominikschadow.dukeencounters.encounter.DukeEncountersUser; 22 | import de.dominikschadow.dukeencounters.security.SecurityValidationService; 23 | import lombok.AllArgsConstructor; 24 | import org.owasp.appsensor.core.DetectionPoint; 25 | import org.owasp.appsensor.core.DetectionSystem; 26 | import org.owasp.appsensor.core.Event; 27 | import org.owasp.appsensor.core.event.EventManager; 28 | import org.springframework.stereotype.Component; 29 | import org.springframework.validation.Errors; 30 | import org.springframework.validation.Validator; 31 | import org.springframework.validation.beanvalidation.SpringValidatorAdapter; 32 | 33 | import static org.owasp.appsensor.core.DetectionPoint.Category.COMMAND_INJECTION; 34 | import static org.owasp.appsensor.core.DetectionPoint.Category.INPUT_VALIDATION; 35 | 36 | /** 37 | * Validates an user: checks required fields and scans for basic Cross-Site Scripting and SQL Injection payload. 38 | * 39 | * @author Dominik Schadow 40 | */ 41 | @Component 42 | @AllArgsConstructor 43 | public class DukeEncountersUserValidator implements Validator { 44 | private final SpringValidatorAdapter validator; 45 | private final EventManager ids; 46 | private final UserService userService; 47 | private final SecurityValidationService securityValidationService; 48 | private final DetectionSystem detectionSystem; 49 | 50 | @Override 51 | public boolean supports(final Class clazz) { 52 | return DukeEncountersUser.class.equals(clazz); 53 | } 54 | 55 | @Override 56 | public void validate(final Object target, final Errors errors) { 57 | validator.validate(target, errors); 58 | 59 | DukeEncountersUser user = (DukeEncountersUser) target; 60 | 61 | if (securityValidationService.hasXssPayload(user.getFirstname())) { 62 | fireXssEvent(); 63 | errors.rejectValue("firstname", Constants.XSS_ERROR_CODE); 64 | } else if (securityValidationService.hasSqlIPayload(user.getFirstname())) { 65 | fireSqlIEvent(); 66 | errors.rejectValue("firstname", Constants.SQLI_ERROR_CODE); 67 | } 68 | 69 | if (securityValidationService.hasXssPayload(user.getLastname())) { 70 | fireXssEvent(); 71 | errors.rejectValue("lastname", Constants.XSS_ERROR_CODE); 72 | } else if (securityValidationService.hasSqlIPayload(user.getLastname())) { 73 | fireSqlIEvent(); 74 | errors.rejectValue("lastname", Constants.SQLI_ERROR_CODE); 75 | } 76 | 77 | if (securityValidationService.hasXssPayload(user.getUsername())) { 78 | fireXssEvent(); 79 | errors.rejectValue("username", Constants.XSS_ERROR_CODE); 80 | } else if (securityValidationService.hasSqlIPayload(user.getUsername())) { 81 | fireSqlIEvent(); 82 | errors.rejectValue("username", Constants.SQLI_ERROR_CODE); 83 | } 84 | 85 | if (securityValidationService.hasXssPayload(user.getEmail())) { 86 | fireXssEvent(); 87 | errors.rejectValue("email", Constants.XSS_ERROR_CODE); 88 | } else if (securityValidationService.hasSqlIPayload(user.getEmail())) { 89 | fireSqlIEvent(); 90 | errors.rejectValue("email", Constants.SQLI_ERROR_CODE); 91 | } 92 | 93 | if (!user.getPassword().equals(user.getConfirmPassword())) { 94 | errors.rejectValue("password", Constants.NOT_MATCHING_PASSWORDS_ERROR_CODE); 95 | } 96 | 97 | if (userService.findUser(user.getUsername()) != null) { 98 | errors.rejectValue("username", Constants.USERNAME_ALREADY_EXISTS); 99 | } 100 | } 101 | 102 | private void fireXssEvent() { 103 | DetectionPoint detectionPoint = new DetectionPoint(INPUT_VALIDATION, "IE1-001"); 104 | ids.addEvent(new Event(userService.getUser(), detectionPoint, detectionSystem)); 105 | } 106 | 107 | private void fireSqlIEvent() { 108 | DetectionPoint detectionPoint = new DetectionPoint(COMMAND_INJECTION, "CIE1-001"); 109 | ids.addEvent(new Event(userService.getUser(), detectionPoint, detectionSystem)); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/user/Level.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.user; 19 | 20 | import org.apache.commons.lang3.builder.ToStringBuilder; 21 | 22 | /** 23 | * Enum for the level of a user. 24 | * 25 | * @author Dominik Schadow 26 | */ 27 | public enum Level { 28 | NEWBIE("Newbie"), ROOKIE("Rookie"), PRO("Pro"), ADMIN("Admin"); 29 | 30 | private final String name; 31 | 32 | Level(String name) { 33 | this.name = name; 34 | } 35 | 36 | public String getName() { 37 | return name; 38 | } 39 | 40 | @Override 41 | public String toString() { 42 | return new ToStringBuilder(this).append("name", getName()).toString(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/user/UserController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.user; 19 | 20 | import de.dominikschadow.dukeencounters.encounter.DukeEncountersUser; 21 | import lombok.AllArgsConstructor; 22 | import lombok.extern.slf4j.Slf4j; 23 | import org.owasp.security.logging.SecurityMarkers; 24 | import org.springframework.stereotype.Controller; 25 | import org.springframework.validation.BindingResult; 26 | import org.springframework.web.bind.WebDataBinder; 27 | import org.springframework.web.bind.annotation.GetMapping; 28 | import org.springframework.web.bind.annotation.InitBinder; 29 | import org.springframework.web.bind.annotation.ModelAttribute; 30 | import org.springframework.web.bind.annotation.PostMapping; 31 | import org.springframework.web.servlet.ModelAndView; 32 | 33 | import javax.validation.Valid; 34 | 35 | /** 36 | * Controller to handle all user related requests. 37 | * 38 | * @author Dominik Schadow 39 | */ 40 | @Controller 41 | @Slf4j 42 | @AllArgsConstructor 43 | public class UserController { 44 | private final UserService userService; 45 | private final DukeEncountersUserValidator validator; 46 | 47 | /** 48 | * Shows the registration page. 49 | * 50 | * @param dukeEncountersUser The new DukeEncountersUser 51 | * @return Register URL 52 | */ 53 | @GetMapping("/register") 54 | public String register(@ModelAttribute final DukeEncountersUser dukeEncountersUser) { 55 | return "register"; 56 | } 57 | 58 | /** 59 | * Creates the new user and stores it in the database. 60 | * 61 | * @param dukeEncountersUser The new user to register 62 | * @param result The binding result 63 | * @return Login URL 64 | */ 65 | @PostMapping("/register") 66 | public ModelAndView createUser(@Valid final DukeEncountersUser dukeEncountersUser, final BindingResult result) { 67 | if (result.hasErrors()) { 68 | return new ModelAndView("register", "formErrors", result.getAllErrors()); 69 | } 70 | 71 | DukeEncountersUser newUser = userService.createUser(dukeEncountersUser); 72 | 73 | log.warn(SecurityMarkers.SECURITY_AUDIT, "User {} created", newUser); 74 | 75 | ModelAndView modelAndView = new ModelAndView("login"); 76 | modelAndView.addObject("userCreated", newUser.getUsername()); 77 | 78 | return modelAndView; 79 | } 80 | 81 | @InitBinder 82 | protected void initBinder(final WebDataBinder binder) { 83 | binder.setValidator(validator); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/user/UserRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.user; 19 | 20 | import de.dominikschadow.dukeencounters.encounter.DukeEncountersUser; 21 | import org.springframework.data.jpa.repository.JpaRepository; 22 | 23 | /** 24 | * JPA repository class to access {@link DukeEncountersUser}s. 25 | * 26 | * @author Dominik Schadow 27 | */ 28 | public interface UserRepository extends JpaRepository { 29 | DukeEncountersUser findByUsername(String username); 30 | } 31 | -------------------------------------------------------------------------------- /duke-encounters/src/main/java/de/dominikschadow/dukeencounters/user/UserService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.user; 19 | 20 | import de.dominikschadow.dukeencounters.encounter.Authority; 21 | import de.dominikschadow.dukeencounters.encounter.DukeEncountersUser; 22 | import lombok.AllArgsConstructor; 23 | import lombok.extern.slf4j.Slf4j; 24 | import org.owasp.appsensor.core.User; 25 | import org.owasp.security.logging.SecurityMarkers; 26 | import org.springframework.security.core.Authentication; 27 | import org.springframework.security.core.context.SecurityContextHolder; 28 | import org.springframework.security.core.userdetails.UserDetails; 29 | import org.springframework.security.crypto.password.PasswordEncoder; 30 | import org.springframework.stereotype.Service; 31 | import org.springframework.transaction.annotation.Transactional; 32 | 33 | import javax.validation.constraints.NotNull; 34 | import java.util.Date; 35 | 36 | /** 37 | * CRUD services for users. 38 | * 39 | * @author Dominik Schadow 40 | */ 41 | @Service 42 | @Slf4j 43 | @AllArgsConstructor 44 | public class UserService { 45 | private final UserRepository userRepository; 46 | private final AuthorityRepository authorityRepository; 47 | private final PasswordEncoder passwordEncoder; 48 | 49 | /** 50 | * Creates a new user. This user receives the normal user role, is enabled and has the {@link Level} NEWBIE. 51 | * 52 | * @param newUser The user to create 53 | * @return The created user with all fields filled 54 | */ 55 | @Transactional 56 | public DukeEncountersUser createUser(@NotNull final DukeEncountersUser newUser) { 57 | log.info("Creating user with username {}", newUser.getEmail()); 58 | Authority authority = authorityRepository.save(new Authority(newUser.getUsername(), "ROLE_USER")); 59 | 60 | newUser.setEnabled(true); 61 | newUser.setLevel(Level.NEWBIE); 62 | newUser.setRegistrationDate(new Date()); 63 | newUser.setAuthority(authority); 64 | newUser.setPassword(hashPassword(newUser.getPassword())); 65 | 66 | DukeEncountersUser user = userRepository.save(newUser); 67 | 68 | log.warn(SecurityMarkers.SECURITY_AUDIT, "Created a new user with username {} and id {} with role {}", 69 | user.getUsername(), user.getId(), user.getAuthority().getAuthority()); 70 | 71 | return user; 72 | } 73 | 74 | @Transactional 75 | public DukeEncountersUser updateUser(@NotNull final DukeEncountersUser dukeEncountersUser) { 76 | return userRepository.save(dukeEncountersUser); 77 | } 78 | 79 | public boolean confirmPassword(@NotNull final String password) { 80 | return passwordEncoder.matches(password, getDukeEncountersUser().getPassword()); 81 | } 82 | 83 | public DukeEncountersUser findUser(final String username) { 84 | return userRepository.findByUsername(username); 85 | } 86 | 87 | public String getUsername() { 88 | Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); 89 | 90 | String username = authentication.getName(); 91 | 92 | if (authentication instanceof UserDetails) { 93 | UserDetails userDetails = (UserDetails) authentication; 94 | 95 | username = userDetails.getUsername(); 96 | } 97 | 98 | return username; 99 | } 100 | 101 | public User getUser() { 102 | return new User(getUsername()); 103 | } 104 | 105 | public DukeEncountersUser getDukeEncountersUser() { 106 | return getDukeEncountersUser(getUsername()); 107 | } 108 | 109 | public DukeEncountersUser getDukeEncountersUser(@NotNull final String username) { 110 | return userRepository.findByUsername(username); 111 | } 112 | 113 | public String hashPassword(String password) { 114 | return passwordEncoder.encode(password); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /duke-encounters/src/main/resources/META-INF/additional-spring-configuration-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "properties": [ 3 | { 4 | "name": "encounters.latest.amount", 5 | "type": "java.lang.Integer", 6 | "description": "Number of encounters the latest encounters list should show." 7 | } 8 | ] 9 | } -------------------------------------------------------------------------------- /duke-encounters/src/main/resources/application-boxfuse.yml: -------------------------------------------------------------------------------- 1 | info: 2 | application: 3 | env: Boxfuse -------------------------------------------------------------------------------- /duke-encounters/src/main/resources/application-development.yml: -------------------------------------------------------------------------------- 1 | # Session 2 | server: 3 | session: 4 | timeout: 3600 5 | cookie: 6 | http-only: true 7 | 8 | # Actuator 9 | management: 10 | context-path: /admin 11 | security: 12 | enabled: false 13 | 14 | security: 15 | basic: 16 | enabled: false 17 | 18 | info: 19 | application: 20 | env: Development 21 | 22 | # Logging 23 | logging: 24 | level: 25 | root: INFO 26 | org.springframework: WARN 27 | org.springframework.security: INFO 28 | org.hibernate: WARN 29 | org.thymeleaf: WARN -------------------------------------------------------------------------------- /duke-encounters/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # Duke Encounters 2 | duke: 3 | encounters: 4 | latest-amount: 10 5 | password-strength: 10 6 | 7 | # Session 8 | server: 9 | session: 10 | timeout: 1800 11 | cookie: 12 | http-only: true 13 | 14 | spring: 15 | h2: 16 | console: 17 | path: /admin/h2-console 18 | resources: 19 | chain: 20 | enabled: true 21 | mvc: 22 | favicon: 23 | enabled: false 24 | 25 | # Actuator 26 | management: 27 | context-path: /admin 28 | security: 29 | enabled: true 30 | 31 | security: 32 | basic: 33 | enabled: true 34 | user: 35 | name: admin 36 | password: admin 37 | 38 | info: 39 | application: 40 | env: Production 41 | 42 | # Logging 43 | logging: 44 | file: /var/logs/duke-encounters.log 45 | pattern: 46 | console: "%d %-5level %marker %logger : %msg%n" 47 | file: "%d %-5level %marker [%thread] %logger : %msg%n" 48 | level: 49 | root: WARN 50 | org.springframework: ERROR 51 | org.hibernate: ERROR 52 | org.thymeleaf: ERROR -------------------------------------------------------------------------------- /duke-encounters/src/main/resources/appsensor-client-config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | http://localhost:8080 6 | duke-encounters 7 | 8 | 9 | -------------------------------------------------------------------------------- /duke-encounters/src/main/resources/appsensor-server-config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | X-Appsensor-Client-Application-Name 4 | 5 | 6 | 7 | 8 | Access Control 9 | ACE2-001 10 | 11 | 1 12 | 24 13 | 14 | 15 | 16 | disableUser 17 | 18 | 19 | 20 | 21 | Command Injection 22 | CIE1-001 23 | 24 | 2 25 | 5 26 | 27 | 28 | 29 | log 30 | 31 | 32 | logout 33 | 34 | 35 | disableUser 36 | 37 | 38 | 39 | 40 | Command Injection 41 | CIE1-002 42 | 43 | 1 44 | 24 45 | 46 | 47 | 48 | disableUser 49 | 50 | 51 | 52 | 53 | Input Validation 54 | IE1-001 55 | 56 | 2 57 | 5 58 | 59 | 60 | 61 | log 62 | 63 | 64 | logout 65 | 66 | 67 | disableUser 68 | 69 | 70 | 71 | 72 | Input Validation 73 | IE5-001 74 | 75 | 1 76 | 5 77 | 78 | 79 | 80 | log 81 | 82 | 83 | disableUser 84 | 85 | 86 | 87 | 88 | Request 89 | RE8-001 90 | 91 | 5 92 | 5 93 | 94 | 95 | 96 | log 97 | 98 | 99 | logout 100 | 101 | 102 | 103 | 104 | System Trend 105 | STE1 106 | 107 | 10 108 | 5 109 | 110 | 111 | 112 | log 113 | 114 | 115 | logout 116 | 117 | 118 | disableUser 119 | 120 | 121 | disableComponentForSpecificUser 122 | 30 123 | 124 | 125 | disableComponentForAllUsers 126 | 10 127 | 128 | 129 | 130 | 131 | System Trend 132 | STE2 133 | 134 | 12 135 | 5 136 | 137 | 138 | 139 | log 140 | 141 | 142 | logout 143 | 144 | 145 | disableUser 146 | 147 | 148 | disableComponentForSpecificUser 149 | 30 150 | 151 | 152 | disableComponentForAllUsers 153 | 10 154 | 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /duke-encounters/src/main/resources/data.sql: -------------------------------------------------------------------------------- 1 | -- AUTHORITIES 2 | INSERT INTO authorities(id, username, authority) VALUES (1, 'arthur@dent.com', 'ROLE_USER'); 3 | INSERT INTO authorities(id, username, authority) VALUES (2, 'ford@prefect.com', 'ROLE_USER'); 4 | INSERT INTO authorities(id, username, authority) VALUES (3, 'zaphod@beeblebrox.com', 'ROLE_USER'); 5 | INSERT INTO authorities(id, username, authority) VALUES (4, 'marvin@marvin.com', 'ROLE_USER'); 6 | INSERT INTO authorities(id, username, authority) VALUES (5, 'humma@kavula.com', 'ROLE_USER'); 7 | INSERT INTO authorities(id, username, authority) VALUES (6, 'questular@rontok.com', 'ROLE_USER'); 8 | INSERT INTO authorities(id, username, authority) VALUES (7, 'deep@thought.com', 'ROLE_USER'); 9 | INSERT INTO authorities(id, username, authority) VALUES (8, 'tricia@mcmillan.com', 'ROLE_USER'); 10 | INSERT INTO authorities(id, username, authority) VALUES (9, 'slartibartfast@slartibartfast.com', 'ROLE_USER'); 11 | INSERT INTO authorities(id, username, authority) VALUES (10, 'jin@jenz.com', 'ROLE_USER'); 12 | INSERT INTO authorities(id, username, authority) VALUES (11, 'gag@halfrunt.com', 'ROLE_USER'); 13 | INSERT INTO authorities(id, username, authority) VALUES (12, 'duke@encounters.com', 'ROLE_ADMIN'); 14 | 15 | -- USERS (username and password are always identical) 16 | INSERT INTO users (id, firstname, lastname, email, username, password, registration_date, level, enabled) VALUES (1, 'Arthur', 'Dent', 'arthur@dent.com', 'arthur@dent.com', '$2a$10$UYOseFWgR87PwL2j8VmycO.IjuH2uGht3lGFGBn2ShUUS9B4zclIe', '2010-05-05 10:45:33', 'ROOKIE', TRUE); 17 | INSERT INTO users (id, firstname, lastname, email, username, password, registration_date, level, enabled) VALUES (2, 'Ford', 'Prefect', 'ford@prefect.com', 'ford@prefect.com', '$2a$10$8yg/hBDXP0bpQuuKJneYbucl0/NsjfT1zQjMsEcnFrjt.6tVnrAEW', '2012-10-01 11:02:29', 'PRO', TRUE); 18 | INSERT INTO users (id, firstname, lastname, email, username, password, registration_date, level, enabled) VALUES (3, 'Zaphod', 'Beeblebrox', 'zaphod@beeblebrox.com', 'zaphod@beeblebrox.com', '$2a$10$fBUuTN5MQafWRqWULmC8DuN30CTWOphJZlUOJnO/woK2uPM.5e4vC', '2015-09-23 08:52:11', 'NEWBIE', TRUE); 19 | INSERT INTO users (id, firstname, lastname, email, username, password, registration_date, level, enabled) VALUES (4, 'Marvin', '', 'marvin@marvin.com', 'marvin@marvin.com', '$2a$10$PL7R5GjZX2xJJDaGK9PSsuq4nUWM4v9XaBC0lsIRYhv8OpHFEMl8u', '2010-01-01 08:52:11', 'NEWBIE', TRUE); 20 | INSERT INTO users (id, firstname, lastname, email, username, password, registration_date, level, enabled) VALUES (5, 'Humma', 'Kavula', 'humma@kavula.com', 'humma@kavula.com', '$2a$10$wRQ2YUJI8TTK0jWLRidwbu0HJxAdOGWUdLV8gHjT9KkUtc/w7TdcW', '2011-02-02 08:52:11', 'PRO', TRUE); 21 | INSERT INTO users (id, firstname, lastname, email, username, password, registration_date, level, enabled) VALUES (6, 'Questular', 'Rontok', 'questular@rontok.com', 'questular@rontok.com', '$2a$10$OcYDMMBCzkOTLEn5AilcYupDNhHyZA2yowCjo9gXOtL1b0Fr0EGF2', '2012-03-03 08:52:11', 'NEWBIE', TRUE); 22 | INSERT INTO users (id, firstname, lastname, email, username, password, registration_date, level, enabled) VALUES (7, 'Deep', 'Thought', 'deep@thought.com', 'deep@thought.com', '$2a$10$8q2YjsU1axyOwC6Vjsr8VOvwpjqh84ZlAzTgUO/NV38BjsuuVoBTe', '2013-04-04 08:52:11', 'NEWBIE', TRUE); 23 | INSERT INTO users (id, firstname, lastname, email, username, password, registration_date, level, enabled) VALUES (8, 'Tricia', 'McMillan', 'tricia@mcmillan.com', 'tricia@mcmillan.com', '$2a$10$ubWNmc1TD8gDpBTR2Tfl9eE0lvYEZmB4dyvd47KLCLnTAnjNCA0e2', '2014-05-05 08:52:11', 'PRO', TRUE); 24 | INSERT INTO users (id, firstname, lastname, email, username, password, registration_date, level, enabled) VALUES (9, 'Slartibartfast', '', 'slartibartfast@slartibartfast.com', 'slartibartfast@slartibartfast.com', '$2a$10$8lFXL0sPVQERcfJIG.UaIuPjoo9xeSRRdk8.Z20FdujLqohdvy8WO', '2015-06-06 08:52:11', 'NEWBIE', TRUE); 25 | INSERT INTO users (id, firstname, lastname, email, username, password, registration_date, level, enabled) VALUES (10, 'Jin', 'Jenz', 'jin@jenz.com', 'jin@jenz.com', '$2a$10$EaOdJoUZKay5RXLwR552h.QdTjYroGIU0WKT5BAWetOPSDBEA2BY2', '2010-07-07 08:52:11', 'NEWBIE', TRUE); 26 | INSERT INTO users (id, firstname, lastname, email, username, password, registration_date, level, enabled) VALUES (11, 'Gag', 'Halfrunt', 'gag@halfrunt.com', 'gag@halfrunt.com', '$2a$10$W7Ik5kkje5NGJQpKBV10TuKXGjZ2So2Oq8w9UMDuFj88ziwrONwQ6', '2011-08-08 08:52:11', 'NEWBIE', TRUE); 27 | INSERT INTO users (id, firstname, lastname, email, username, password, registration_date, level, enabled) VALUES (12, 'Duke', 'Encounters', 'duke@encounters.com', 'duke@encounters.com', '$2a$10$f23RDQjcGwaS91cjKSXdKupUbCxTRmPzgaOhF2.nJNz.dj6lZa9O.', '2000-01-01 08:08:08', 'ADMIN', TRUE); 28 | 29 | -- ENCOUNTERS 30 | INSERT INTO encounters (id, event, location, country, comment, date, user_id) VALUES (1, 'JavaOne 1996', 'San Francisco', 'USA', 'The first JavaOne!', '1996-05-31', 5); 31 | INSERT INTO encounters (id, event, location, country, comment, date, user_id) VALUES (2, 'JavaOne 1997', 'San Francisco', 'USA', '', '1997-04-04', 5); 32 | INSERT INTO encounters (id, event, location, country, comment, date, user_id) VALUES (3, 'JavaOne 1998', 'San Francisco', 'USA', '', '1998-03-01', 5); 33 | INSERT INTO encounters (id, event, location, country, comment, date, user_id) VALUES (4, 'JavaOne 1999', 'San Francisco', 'USA', '', '1999-10-01', 5); 34 | INSERT INTO encounters (id, event, location, country, comment, date, user_id) VALUES (5, 'JavaOne 2000', 'San Francisco', 'USA', '', '2000-10-01', 5); 35 | INSERT INTO encounters (id, event, location, country, comment, date, user_id) VALUES (6, 'JavaOne 2001', 'San Francisco', 'USA', '', '2001-10-01', 5); 36 | INSERT INTO encounters (id, event, location, country, comment, date, user_id) VALUES (7, 'JavaOne 2002', 'San Francisco', 'USA', '', '2002-10-01', 5); 37 | INSERT INTO encounters (id, event, location, country, comment, date, user_id) VALUES (8, 'JavaOne 2003', 'San Francisco', 'USA', '', '2003-10-01', 8); 38 | INSERT INTO encounters (id, event, location, country, comment, date, user_id) VALUES (9, 'JavaOne 2004', 'San Francisco', 'USA', '', '2004-10-01', 8); 39 | INSERT INTO encounters (id, event, location, country, comment, date, user_id) VALUES (10, 'JavaOne 2005', 'San Francisco', 'USA', '', '2005-10-01', 8); 40 | INSERT INTO encounters (id, event, location, country, comment, date, user_id) VALUES (11, 'JavaOne 2006', 'San Francisco', 'USA', '', '2006-10-01', 5); 41 | INSERT INTO encounters (id, event, location, country, comment, date, user_id) VALUES (12, 'JavaOne 2007', 'San Francisco', 'USA', '', '2007-10-01', 5); 42 | INSERT INTO encounters (id, event, location, country, comment, date, user_id) VALUES (13, 'JavaOne 2008', 'San Francisco', 'USA', '', '2008-10-01', 5); 43 | INSERT INTO encounters (id, event, location, country, comment, date, user_id) VALUES (14, 'JavaOne 2009', 'San Francisco', 'USA', '', '2009-10-01', 5); 44 | INSERT INTO encounters (id, event, location, country, comment, date, user_id) VALUES (15, 'JavaOne 2010', 'San Francisco', 'USA', '', '2010-09-22', 5); 45 | INSERT INTO encounters (id, event, location, country, comment, date, user_id) VALUES (16, 'JavaOne 2011', 'San Francisco', 'USA', '', '2011-10-01', 5); 46 | INSERT INTO encounters (id, event, location, country, comment, date, user_id) VALUES (17, 'JavaOne 2012', 'San Francisco', 'USA', '', '2012-10-01', 1); 47 | INSERT INTO encounters (id, event, location, country, comment, date, user_id) VALUES (18, 'JavaOne 2013', 'San Francisco', 'USA', '', '2013-09-22', 2); 48 | INSERT INTO encounters (id, event, location, country, comment, date, user_id) VALUES (19, 'JavaOne 2014', 'San Francisco', 'USA', '', '2014-09-30', 1); 49 | INSERT INTO encounters (id, event, location, country, comment, date, user_id) VALUES (20, 'JavaOne 2015', 'San Francisco', 'USA', '20 years of Java!', '2015-10-26', 11); 50 | INSERT INTO encounters (id, event, location, country, comment, date, user_id) VALUES (21, 'JavaOne 2016', 'San Francisco', 'USA', '', '2016-09-18', 3); 51 | 52 | -- CONFIRMATIONS 53 | INSERT INTO confirmations (id, user_id, encounter_id, date) VALUES (1, 2, 19, '2014-09-30'); 54 | INSERT INTO confirmations (id, user_id, encounter_id, date) VALUES (2, 3, 19, '2014-09-30'); 55 | INSERT INTO confirmations (id, user_id, encounter_id, date) VALUES (3, 4, 19, '2014-10-01'); 56 | INSERT INTO confirmations (id, user_id, encounter_id, date) VALUES (4, 7, 19, '2014-10-02'); 57 | INSERT INTO confirmations (id, user_id, encounter_id, date) VALUES (5, 8, 19, '2014-10-30'); 58 | INSERT INTO confirmations (id, user_id, encounter_id, date) VALUES (6, 2, 1, '1996-12-12'); 59 | INSERT INTO confirmations (id, user_id, encounter_id, date) VALUES (7, 3, 2, '1998-02-15'); 60 | INSERT INTO confirmations (id, user_id, encounter_id, date) VALUES (8, 2, 2, '1997-10-01'); 61 | INSERT INTO confirmations (id, user_id, encounter_id, date) VALUES (9, 7, 1, '1996-10-02'); 62 | INSERT INTO confirmations (id, user_id, encounter_id, date) VALUES (10, 11, 18, '2013-10-30'); 63 | INSERT INTO confirmations (id, user_id, encounter_id, date) VALUES (11, 10, 18, '2013-10-30'); 64 | INSERT INTO confirmations (id, user_id, encounter_id, date) VALUES (12, 1, 10, '2005-10-10'); 65 | INSERT INTO confirmations (id, user_id, encounter_id, date) VALUES (13, 2, 9, '2004-12-12'); 66 | INSERT INTO confirmations (id, user_id, encounter_id, date) VALUES (14, 3, 9, '2005-02-15'); 67 | INSERT INTO confirmations (id, user_id, encounter_id, date) VALUES (15, 4, 9, '2004-10-01'); 68 | INSERT INTO confirmations (id, user_id, encounter_id, date) VALUES (16, 4, 13, '2008-10-02'); 69 | INSERT INTO confirmations (id, user_id, encounter_id, date) VALUES (17, 11, 11, '2006-10-30'); 70 | INSERT INTO confirmations (id, user_id, encounter_id, date) VALUES (18, 10, 12, '2007-10-30'); 71 | INSERT INTO confirmations (id, user_id, encounter_id, date) VALUES (19, 1, 13, '2012-10-10'); -------------------------------------------------------------------------------- /duke-encounters/src/main/resources/messages.properties: -------------------------------------------------------------------------------- 1 | xss.attempt=This application is XSS bulletproof! 2 | sqli.attempt=This application is SQL Injection bulletproof! 3 | password.nomatch=The entered passwords don't match 4 | password.unsafe=The entered password is not safe, it must contain at least 10 characters 5 | password.incorrect=Your current password is not correct 6 | invalid.value=This is not a valid value 7 | invalid.year=The entered year is not valid - Java did not exist before 1995 8 | username.exists=The entered username already exists, please enter another one -------------------------------------------------------------------------------- /duke-encounters/src/main/resources/static/css/custom.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 70px; 3 | } 4 | 5 | .btn-dropdown-logout { 6 | margin-top: 8px; 7 | margin-left: 20px; 8 | } 9 | 10 | .well .page-header { 11 | margin-top: 0; 12 | margin-bottom: 0; 13 | } 14 | 15 | h1 { 16 | margin-top: 2px; 17 | } 18 | 19 | .well .page-header p { 20 | margin-bottom: 5px; 21 | } 22 | 23 | .duke { 24 | padding-top: 50px; 25 | text-align: center; 26 | } 27 | 28 | input[type='checkbox'] { 29 | margin-top: 0; 30 | } 31 | 32 | footer { 33 | background: #333; 34 | color: #eee; 35 | font-size: 11px; 36 | padding: 20px; 37 | } 38 | 39 | .unstyled { 40 | list-style: none; 41 | padding: 0; 42 | } 43 | 44 | #encountersAndConfirmations { 45 | margin-top: 25px; 46 | margin-bottom: 25px; 47 | } 48 | 49 | .panel-text { 50 | margin-top: 25px; 51 | } 52 | 53 | .btn-success, .btn-success.active, .btn-success:active, .btn-success:hover, .btn-success.focus, .btn-success:focus, .btn-success:active:hover, 54 | .btn-success.active:hover, .btn-success:active:focus, .btn-success.active:focus, .btn-success:active.focus, .btn-success.active.focus, 55 | .btn-success.disabled:hover, .btn-success[disabled]:hover, .btn-success.disabled:focus, .btn-success[disabled]:focus, 56 | .btn-success.disabled.focus, .btn-success[disabled].focus { 57 | background-color: #337ab7; 58 | } 59 | 60 | #actions { 61 | margin-bottom: 20px; 62 | } 63 | 64 | #github { 65 | position: absolute; 66 | top: 0; 67 | right: 0; 68 | border: 0; 69 | z-index: 9999; 70 | } -------------------------------------------------------------------------------- /duke-encounters/src/main/resources/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dschadow/ApplicationIntrusionDetection/ab72f4470e4a6ab031482d8c3c440e1178eda681/duke-encounters/src/main/resources/static/favicon.ico -------------------------------------------------------------------------------- /duke-encounters/src/main/resources/static/img/duke-guitar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dschadow/ApplicationIntrusionDetection/ab72f4470e4a6ab031482d8c3c440e1178eda681/duke-encounters/src/main/resources/static/img/duke-guitar.png -------------------------------------------------------------------------------- /duke-encounters/src/main/resources/static/img/duke-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dschadow/ApplicationIntrusionDetection/ab72f4470e4a6ab031482d8c3c440e1178eda681/duke-encounters/src/main/resources/static/img/duke-small.png -------------------------------------------------------------------------------- /duke-encounters/src/main/resources/templates/encounters.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 | 23 | 24 |
25 |
26 |

Encounters

27 | 28 |

Encounter not listed yet? Create a new one.

30 | 31 |

Event and confirmation details are only 32 | visible after login.

33 |
34 |
35 | 36 |
37 |
38 |

The requested encounter does not exist

39 |
40 |
41 | 42 |
43 |
44 |

Your search for 45 | returned the following results:

46 | 47 |
48 |
49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 64 | 65 | 66 | 67 | 73 | 74 | 82 | 83 | 84 |
EventLocationDateConfirmed byLikelihoodConfirm
68 | 69 | 70 | 71 | 72 | 75 |
76 | 77 | 80 |
81 |
85 |
86 |
87 |
88 |
89 |
90 | 91 |
92 | 93 |
94 | 95 | 96 | -------------------------------------------------------------------------------- /duke-encounters/src/main/resources/templates/error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 |
8 |
9 |

Something horrible just happened...

10 | 11 |

There seems to be a problem with the page you requested ( at 12 | ). 13 |

14 |
15 |
16 | 17 |
18 |
19 | Return home 20 |
21 |
22 |
23 | 24 | 25 | -------------------------------------------------------------------------------- /duke-encounters/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 |
8 | Fork me on GitHub 11 |
12 | 13 | 29 | 30 |
31 |
32 |
33 | 47 |
48 |
49 |
50 | 51 |
52 |
53 |

Latest Encounters

54 | 55 |

View all encounters or search 56 | for the ones 57 | you 58 | are interested in. You have to register or login to contribute. 60 |

61 |
62 |
63 | 64 |
65 |
66 |
    67 |
  • 68 | 69 |

    70 | 71 |

    72 |

    73 | 74 |

    75 |
  • 76 |
77 | 89 |
90 |
Duke by Wikimedia Commons - https://commons.wikimedia.org/wiki/File:Duke-Guitar.png 94 |
95 |
96 |
97 | 98 |
99 | 100 |
101 | 102 | 103 | -------------------------------------------------------------------------------- /duke-encounters/src/main/resources/templates/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 | 23 | 24 |
25 |
26 |

Login

27 | 28 |

Use your credentials to log in. Need to register first?

29 |
30 |
31 | 32 |
33 |
34 |

User 35 | successfully created, you can now use it to log in.

36 |
37 |
38 | 39 |
40 |
41 |
42 | 45 |
46 | 47 |
48 | 50 |
51 |
52 |
53 | 54 |
55 | 57 |
58 |
59 |
60 | 61 |
62 | 63 |
64 |
65 |
66 |
67 | 68 |
69 |
70 |
71 |
72 |
73 |
74 | 75 |
76 | 77 |
78 | 79 | -------------------------------------------------------------------------------- /duke-encounters/src/main/resources/templates/partials.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Duke Encounters 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 24 | 25 | 26 | 33 | 34 | 35 | 68 | 69 | 70 |
71 |
72 |
73 |
74 |
Duke Encounters
75 |

The leading online platform for Java Duke spotting.

76 |
77 |
78 |
About
79 |

This demo web application is developed by Dominik Schadow, 81 | source code is available on GitHub.

84 |
85 |
86 |
Navigation
87 | 93 |
94 |
95 |
Follow me
96 | 101 |
102 |
103 |
104 |
105 | 106 | 107 |
108 | 109 | 110 |
111 | 112 | -------------------------------------------------------------------------------- /duke-encounters/src/main/resources/templates/register.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 | 23 | 24 |
25 |
26 |

Register

27 | 28 |

Already have a user? Please login directly.

29 |
30 |
31 | 32 |
33 |
34 |
36 |
37 |

38 | Validation error 39 |

40 |
41 | 42 |
43 | 44 |
45 | 47 |
48 |
49 |
50 | 51 |
52 | 53 |
54 |
55 |
56 | 57 |
58 | 59 |
60 |
61 |
62 | 63 |
64 | 65 |
66 |
67 |
68 | 69 |
70 | 72 |
73 |
74 |
75 | 76 |
77 | 79 |
80 |
81 |
82 |
83 | 84 |
85 |
86 |
87 |
88 |
89 |
90 | 91 |
92 | 93 |
94 | 95 | -------------------------------------------------------------------------------- /duke-encounters/src/main/resources/templates/search.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 | 23 | 24 |
25 |
26 |

Search

27 | 28 |

Search for encounters that have been reported in the past.

29 |
30 |
31 | 32 |
33 |
34 |
36 |
37 |

38 | Validation error 39 |

40 |
41 |
42 | 43 |
44 | 46 |
47 |
48 |
49 | 50 |
51 | 53 |
54 |
55 |
56 | 57 |
58 | 60 |
61 |
62 |
63 | 64 |
65 | 67 |
68 |
69 |
70 |
71 | 72 |
73 | 79 |
80 |
81 |
82 |
83 | 84 |
85 | 90 |
91 |
92 |
93 |
94 |
95 | 96 |
97 |
98 |
99 |
100 |
101 |
102 | 103 |
104 | 105 |
106 | 107 | 108 | -------------------------------------------------------------------------------- /duke-encounters/src/main/resources/templates/user/account.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 | 23 | 24 |
25 |
26 |

My Profile 27 | 28 |

29 |
30 |
31 | 32 |
33 |
34 |

You can't confirm your own encounter!

35 |

You have already confirmed this encounter and cannot 36 | confirm it again!

37 |

Data successfully updated

38 |

Data update failed

39 |
40 |
41 | 42 |
43 | 47 |
48 | 49 |
50 |
51 |
52 |
53 |

My Encounters

54 |
55 | 56 | 68 | 69 |
70 | Add Encounter 71 |
72 |
73 |
74 |
75 |
76 |
77 |

My Confirmations

78 |
79 | 80 | 91 | 92 |
93 | Add Confirmation 94 |
95 |
96 |
97 |
98 |
99 | 100 |
101 | 102 |
103 | 104 | 105 | -------------------------------------------------------------------------------- /duke-encounters/src/main/resources/templates/user/changePassword.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 | 23 | 24 |
25 |
26 |

My Password 27 | 28 |

29 |
30 |
31 | 32 |
33 |
34 | Account 35 | Edit Userdata 36 |
37 |
38 | 39 |
40 |
41 | 43 |
44 |
45 | 46 |
47 |
48 |

Password

49 | 50 |
52 |
53 |

54 | Validation error 55 |

56 |
57 | 58 |
59 | 60 |
61 | 63 |
64 |
65 |
66 | 67 |
68 | 70 |
71 |
72 |
73 | 74 |
75 | 78 |
79 |
80 |
81 |
82 | 83 |
84 |
85 |
86 |
87 |
88 |
89 | 90 |
91 | 92 |
93 | 94 | -------------------------------------------------------------------------------- /duke-encounters/src/main/resources/templates/user/confirmations.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 | 23 | 24 |
25 |
26 |

Confirmations

27 | 28 |

Confirmation not listed yet? Confirm an encounter.

29 |
30 |
31 | 32 |
33 |
34 |

The requested confirmation does not exist

35 |
36 |
37 | 38 |
39 |
40 |
41 |
42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 56 | 57 | 58 | 59 | 68 | 69 | 70 |
EventLocationDateConfirmation DateRevoke
60 |
61 | 62 | 66 |
67 |
71 |
72 |
73 |
74 |
75 |
76 | 77 |
78 | 79 |
80 | 81 | 82 | -------------------------------------------------------------------------------- /duke-encounters/src/main/resources/templates/user/createEncounter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 | 23 | 24 |
25 |
26 |

Create Encounter

27 | 28 |

Had an encounter that is missing in our database? Create it right away!

29 |
30 |
31 | 32 |
33 |
34 |
36 |
37 |

38 | Validation error 39 |

40 |
41 | 42 |
43 | 44 |
45 | 47 |
48 |
49 |
50 | 51 |
52 | 53 |
54 |
55 |
56 | 57 |
58 | 59 |
60 |
61 |
62 | 63 |
64 | 65 |
66 |
67 |
68 |
69 | 70 |
71 | 72 |
73 |
74 |
75 |
76 | 77 |
78 |
79 |
80 |
81 |
82 |
83 | 84 |
85 | 86 |
87 | 88 | 89 | -------------------------------------------------------------------------------- /duke-encounters/src/main/resources/templates/user/editAccount.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 | 23 | 24 |
25 |
26 |

My Data 27 | 28 |

29 |
30 |
31 | 32 |
33 |
34 | Account 35 | Change Password 36 |
37 |
38 | 39 |
40 |
41 |

User Data

42 | 43 | 45 | 46 |
48 |
49 |

50 | Validation error 51 |

52 |
53 | 54 |
55 | 56 |
57 | 59 |
60 |
61 |
62 | 63 |
64 | 66 |
67 |
68 |
69 |
70 | 71 |
72 |
73 |
74 |
75 |
76 | 77 |
78 |
79 |

Account Data

80 | 81 | 83 | 84 |
86 |
87 |

88 | Validation error 89 |

90 |
91 | 92 |
93 | 94 |
95 | 97 |
98 |
99 |
100 | 101 |
102 | 104 |
105 |
106 |
107 |
108 | 109 |
110 |
111 |
112 |
113 |
114 |
115 | 116 |
117 | 118 |
119 | 120 | 121 | -------------------------------------------------------------------------------- /duke-encounters/src/main/resources/templates/user/encounterDetails.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 | 23 | 24 |
25 |
26 |

27 |
28 |
29 | 30 |
31 |
32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 58 | 59 | 60 |
CityCountryDateLikelihood
61 | 62 |
63 |

Comment

64 | 65 |

66 |
67 |
68 |
69 | 70 |
71 |
72 |

Confirmations

73 | 74 |

75 |
76 |

77 | 78 |

Encounter not confirmed

79 | 80 | 89 |
90 |
91 | 92 |
93 |
94 | Encounters 95 |
96 |
97 |
98 | 99 |
100 | 101 |
102 | 103 | 104 | -------------------------------------------------------------------------------- /duke-encounters/src/test/java/de/dominikschadow/dukeencounters/DukeEncountersApplicationTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters; 19 | 20 | import org.junit.Test; 21 | import org.junit.runner.RunWith; 22 | import org.springframework.boot.test.context.SpringBootTest; 23 | import org.springframework.test.context.junit4.SpringRunner; 24 | import org.springframework.test.context.web.WebAppConfiguration; 25 | 26 | /** 27 | * Tests the application itself and tries to startup the application context. 28 | */ 29 | @RunWith(SpringRunner.class) 30 | @SpringBootTest(classes = DukeEncountersApplication.class) 31 | @WebAppConfiguration 32 | public class DukeEncountersApplicationTest { 33 | @Test 34 | public void contextLoads() { 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /duke-encounters/src/test/java/de/dominikschadow/dukeencounters/TestData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters; 19 | 20 | import de.dominikschadow.dukeencounters.confirmation.Confirmation; 21 | import de.dominikschadow.dukeencounters.encounter.DukeEncountersUser; 22 | import de.dominikschadow.dukeencounters.encounter.Encounter; 23 | 24 | import java.util.ArrayList; 25 | import java.util.List; 26 | 27 | /** 28 | * Sets up different test data. 29 | * 30 | * @author Dominik Schadow 31 | */ 32 | public class TestData { 33 | public static Confirmation testConfirmation() { 34 | Confirmation testConfirmation = new Confirmation(); 35 | testConfirmation.setId(1); 36 | testConfirmation.setEncounter(testEncounter(1)); 37 | testConfirmation.setUser(testUser()); 38 | 39 | return testConfirmation; 40 | } 41 | 42 | public static DukeEncountersUser testUser() { 43 | DukeEncountersUser testUser = new DukeEncountersUser(); 44 | testUser.setUsername("test"); 45 | 46 | return testUser; 47 | } 48 | 49 | public static Encounter testEncounter(long id) { 50 | Encounter testEncounter = new Encounter(); 51 | testEncounter.setId(id); 52 | 53 | return testEncounter; 54 | } 55 | 56 | public static List twoTestEncounters() { 57 | List encounters = new ArrayList<>(); 58 | encounters.add(testEncounter(1)); 59 | encounters.add(testEncounter(2)); 60 | 61 | return encounters; 62 | } 63 | 64 | public static List threeTestEncounters() { 65 | List encounters = new ArrayList<>(); 66 | encounters.add(testEncounter(1)); 67 | encounters.add(testEncounter(2)); 68 | encounters.add(testEncounter(3)); 69 | 70 | return encounters; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /duke-encounters/src/test/java/de/dominikschadow/dukeencounters/account/AccountControllerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.account; 19 | 20 | import de.dominikschadow.dukeencounters.confirmation.ConfirmationService; 21 | import de.dominikschadow.dukeencounters.encounter.EncounterService; 22 | import de.dominikschadow.dukeencounters.user.UserService; 23 | import de.dominikschadow.dukeencounters.user.DukeEncountersUserValidator; 24 | import org.junit.Test; 25 | import org.junit.runner.RunWith; 26 | import org.springframework.beans.factory.annotation.Autowired; 27 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; 28 | import org.springframework.boot.test.mock.mockito.MockBean; 29 | import org.springframework.security.test.context.support.WithMockUser; 30 | import org.springframework.test.context.junit4.SpringRunner; 31 | import org.springframework.test.web.servlet.MockMvc; 32 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; 33 | import org.springframework.test.web.servlet.result.MockMvcResultMatchers; 34 | 35 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 36 | 37 | /** 38 | * Tests the [@link AccountController} class. 39 | * 40 | * @author Dominik Schadow 41 | */ 42 | @RunWith(SpringRunner.class) 43 | @WebMvcTest(AccountController.class) 44 | public class AccountControllerTest { 45 | @MockBean 46 | private EncounterService encounterService; 47 | @MockBean 48 | private UserService userService; 49 | @MockBean 50 | private ConfirmationService confirmationService; 51 | @MockBean 52 | private DukeEncountersUserValidator dukeEncountersUserValidator; 53 | 54 | @Autowired 55 | private MockMvc mvc; 56 | 57 | @Test 58 | @WithMockUser(username = "arthur@dent.com", password = "arthur@dent.com", roles = "USER") 59 | public void verifyAccountAuthorizeOK() throws Exception { 60 | mvc.perform(MockMvcRequestBuilders.get("/account")).andExpect(MockMvcResultMatchers.status().isOk()); 61 | } 62 | 63 | @Test 64 | @WithMockUser(username = "arthur@dent.com", password = "arthur@dent.com", roles = "DUMMY") 65 | public void verifyAccountAuthorizeNOK() throws Exception { 66 | mvc.perform(MockMvcRequestBuilders.get("/account")).andExpect(MockMvcResultMatchers.status().isForbidden()); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /duke-encounters/src/test/java/de/dominikschadow/dukeencounters/confirmation/ConfirmationServiceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.confirmation; 19 | 20 | import com.google.common.collect.Lists; 21 | import de.dominikschadow.dukeencounters.encounter.EncounterService; 22 | import de.dominikschadow.dukeencounters.user.UserService; 23 | import org.junit.Before; 24 | import org.junit.Rule; 25 | import org.junit.Test; 26 | import org.junit.rules.ExpectedException; 27 | import org.mockito.Mock; 28 | import org.mockito.MockitoAnnotations; 29 | 30 | import java.util.List; 31 | 32 | import static de.dominikschadow.dukeencounters.TestData.*; 33 | import static org.assertj.core.api.Assertions.assertThat; 34 | import static org.mockito.BDDMockito.given; 35 | import static org.mockito.Matchers.*; 36 | import static org.mockito.Mockito.doNothing; 37 | 38 | /** 39 | * Tests the [@link ConfirmationService} class. 40 | * 41 | * @author Dominik Schadow 42 | */ 43 | public class ConfirmationServiceTest { 44 | @Rule 45 | public ExpectedException thrown = ExpectedException.none(); 46 | 47 | @Mock 48 | private ConfirmationRepository repository; 49 | @Mock 50 | private UserService userService; 51 | @Mock 52 | private EncounterService encounterService; 53 | 54 | private ConfirmationService service; 55 | 56 | @Before 57 | public void setup() { 58 | MockitoAnnotations.initMocks(this); 59 | service = new ConfirmationService(repository, userService, encounterService); 60 | } 61 | 62 | @Test 63 | public void getConfirmationsByUsernameWhenUsernameIsNullShouldThrowException() throws Exception { 64 | thrown.expect(NullPointerException.class); 65 | thrown.expectMessage("username"); 66 | service.getConfirmationsByUsername(null); 67 | } 68 | 69 | @Test 70 | public void getConfirmationsByUsernameWhenUsernameIsValidShouldReturnConfirmations() throws Exception { 71 | given(repository.findAllByUsername(anyString())).willReturn(Lists.newArrayList(testConfirmation())); 72 | List confirmations = service.getConfirmationsByUsername("test"); 73 | 74 | assertThat(confirmations.size()).isEqualTo(1); 75 | } 76 | 77 | @Test 78 | public void getConfirmationByUsernameAndEncounterIdWhenUsernameAndIdAreValidShouldReturnConfirmation() throws Exception { 79 | given(repository.findByUsernameAndEncounterId(anyString(), anyLong())).willReturn(testConfirmation()); 80 | Confirmation confirmation = service.getConfirmationByUsernameAndEncounterId("test", 1); 81 | 82 | assertThat(confirmation.getId()).isEqualTo(1); 83 | } 84 | 85 | @Test 86 | public void getOwnConfirmationsShouldReturnConfirmations() throws Exception { 87 | given(repository.findAllByUsername(anyString())).willReturn(Lists.newArrayList(testConfirmation())); 88 | List confirmations = service.getConfirmations("own"); 89 | 90 | assertThat(confirmations.size()).isEqualTo(1); 91 | } 92 | 93 | @Test 94 | public void getConfirmationsWithTypeNullShouldReturnAllConfirmations() throws Exception { 95 | given(repository.findAll()).willReturn(Lists.newArrayList(testConfirmation())); 96 | List confirmations = service.getConfirmations(null); 97 | 98 | assertThat(confirmations.size()).isEqualTo(1); 99 | } 100 | 101 | @Test 102 | public void hasConfirmedEncounterForAlreadyConfirmedEncounterShouldReturnTrue() throws Exception { 103 | given(repository.findByUsernameAndEncounterId(anyString(), anyLong())).willReturn(testConfirmation()); 104 | boolean hasConfirmedEncounter = service.hasConfirmedEncounter("test", 1); 105 | 106 | assertThat(hasConfirmedEncounter).isTrue(); 107 | } 108 | 109 | @Test 110 | public void hasConfirmedEncounterForUnconfirmedEncounterShouldReturnFalse() throws Exception { 111 | given(repository.findByUsernameAndEncounterId(anyString(), anyLong())).willReturn(null); 112 | boolean hasConfirmedEncounter = service.hasConfirmedEncounter("test", 1); 113 | 114 | assertThat(hasConfirmedEncounter).isFalse(); 115 | } 116 | 117 | @Test 118 | public void deleteEncounterForOwnEncounterShouldSucceed() throws Exception { 119 | doNothing().when(repository).delete(1l); 120 | service.deleteConfirmation("test", 1); 121 | } 122 | 123 | @Test 124 | public void addConfirmationWithValidDataShouldSucceed() throws Exception { 125 | given(userService.getDukeEncountersUser(anyString())).willReturn(testUser()); 126 | given(encounterService.getEncounterById(anyLong())).willReturn(testEncounter(1)); 127 | given(repository.save(any(Confirmation.class))).willReturn(testConfirmation()); 128 | Confirmation confirmation = service.addConfirmation("test", 1); 129 | 130 | assertThat(confirmation.getEncounter().getId()).isEqualTo(1); 131 | assertThat(confirmation.getUser().getUsername()).isEqualTo("test"); 132 | } 133 | } -------------------------------------------------------------------------------- /duke-encounters/src/test/java/de/dominikschadow/dukeencounters/encounter/EncounterControllerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.encounter; 19 | 20 | import de.dominikschadow.dukeencounters.DukeEncountersApplication; 21 | import org.junit.Before; 22 | import org.junit.Test; 23 | import org.junit.runner.RunWith; 24 | import org.springframework.beans.factory.annotation.Autowired; 25 | import org.springframework.boot.test.context.SpringBootTest; 26 | import org.springframework.http.MediaType; 27 | import org.springframework.test.context.junit4.SpringRunner; 28 | import org.springframework.test.context.web.WebAppConfiguration; 29 | import org.springframework.test.web.servlet.MockMvc; 30 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; 31 | import org.springframework.web.context.WebApplicationContext; 32 | 33 | import static org.hamcrest.Matchers.hasSize; 34 | import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; 35 | import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; 36 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 37 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; 38 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; 39 | 40 | /** 41 | * Tests the [@link EncounterController} class. 42 | * 43 | * @author Dominik Schadow 44 | */ 45 | @RunWith(SpringRunner.class) 46 | @SpringBootTest(classes = DukeEncountersApplication.class) 47 | @WebAppConfiguration 48 | public class EncounterControllerTest { 49 | @Autowired 50 | private WebApplicationContext context; 51 | 52 | private MockMvc mvc; 53 | 54 | @Before 55 | public void setup() { 56 | mvc = MockMvcBuilders.webAppContextSetup(context).apply(springSecurity()).build(); 57 | } 58 | 59 | @Test 60 | public void listEncounters() throws Exception { 61 | mvc.perform(get("/encounters")) 62 | .andExpect(status().isOk()) 63 | .andExpect(view().name("encounters")) 64 | .andExpect(model().attributeExists("encounters")) 65 | .andExpect(model().attribute("encounters", hasSize(21))); 66 | } 67 | 68 | @Test 69 | public void searchEncounterWithCompleteSearchFilterShouldReturnResult() throws Exception { 70 | mvc.perform(post("/encounters").with(csrf()) 71 | .contentType(MediaType.APPLICATION_FORM_URLENCODED) 72 | .param("event", "JavaOne 2015") 73 | .param("location", "San Francisco") 74 | .param("likelihood", "ANY") 75 | .param("country", "USA") 76 | .param("year", "2015") 77 | .param("confirmations", "1")) 78 | .andExpect(status().isOk()) 79 | .andExpect(view().name("encounters")) 80 | .andExpect(model().attribute("encounters", hasSize(1))); 81 | } 82 | 83 | @Test 84 | public void searchEncounterWithMinimalisticSearchFilterShouldReturnResult() throws Exception { 85 | mvc.perform(post("/encounters").with(csrf()) 86 | .contentType(MediaType.APPLICATION_FORM_URLENCODED) 87 | .param("event", "JavaOne") 88 | .param("location", "San Francisco") 89 | .param("likelihood", "ANY")) 90 | .andExpect(status().isOk()) 91 | .andExpect(view().name("encounters")) 92 | .andExpect(model().attribute("encounters", hasSize(21))); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /duke-encounters/src/test/java/de/dominikschadow/dukeencounters/encounter/EncounterServiceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.encounter; 19 | 20 | import de.dominikschadow.dukeencounters.config.DukeEncountersProperties; 21 | import de.dominikschadow.dukeencounters.user.UserService; 22 | import org.junit.Before; 23 | import org.junit.Test; 24 | import org.mockito.Mock; 25 | import org.mockito.MockitoAnnotations; 26 | import org.owasp.appsensor.core.DetectionSystem; 27 | import org.owasp.appsensor.core.event.EventManager; 28 | 29 | import java.util.List; 30 | 31 | import static de.dominikschadow.dukeencounters.TestData.testEncounter; 32 | import static de.dominikschadow.dukeencounters.TestData.threeTestEncounters; 33 | import static de.dominikschadow.dukeencounters.TestData.twoTestEncounters; 34 | import static org.assertj.core.api.Java6Assertions.assertThat; 35 | import static org.mockito.BDDMockito.given; 36 | import static org.mockito.Matchers.anyLong; 37 | import static org.mockito.Matchers.anyObject; 38 | import static org.mockito.Matchers.anyString; 39 | 40 | /** 41 | * Tests the [@link EncounterService} class. 42 | * 43 | * @author Dominik Schadow 44 | */ 45 | public class EncounterServiceTest { 46 | @Mock 47 | private EncounterRepository repository; 48 | @Mock 49 | private UserService userService; 50 | @Mock 51 | private EventManager ids; 52 | @Mock 53 | private DetectionSystem detectionSystem; 54 | @Mock 55 | private DukeEncountersProperties properties; 56 | 57 | private EncounterService service; 58 | 59 | @Before 60 | public void setUp() throws Exception { 61 | MockitoAnnotations.initMocks(this); 62 | service = new EncounterService(repository, userService, ids, detectionSystem, properties); 63 | } 64 | 65 | @Test 66 | public void getLatestEncountersInsideLimitsShouldReturnList() throws Exception { 67 | given(properties.getLatestAmount()).willReturn(2); 68 | given(repository.findWithPageable(anyObject())).willReturn(twoTestEncounters()); 69 | List latestEncounters = service.getLatestEncounters(); 70 | 71 | assertThat(latestEncounters.size()).isEqualTo(2); 72 | } 73 | 74 | @Test 75 | public void getLatestEncountersOutsideLimitsFiresSqlIEvent() throws Exception { 76 | given(properties.getLatestAmount()).willReturn(2); 77 | given(repository.findWithPageable(anyObject())).willReturn(threeTestEncounters()); 78 | List latestEncounters = service.getLatestEncounters(); 79 | 80 | assertThat(latestEncounters.size()).isEqualTo(3); 81 | } 82 | 83 | @Test 84 | public void getEncountersByUsernameShouldReturnList() throws Exception { 85 | given(repository.findAllByUsername(anyString())).willReturn(threeTestEncounters()); 86 | List encounters = service.getEncountersByUsername("test"); 87 | 88 | assertThat(encounters.size()).isEqualTo(3); 89 | } 90 | 91 | @Test 92 | public void getEncountersByEventShouldReturnList() throws Exception { 93 | given(repository.findByEventContaining(anyString())).willReturn(threeTestEncounters()); 94 | List encounters = service.getEncountersByEvent("test"); 95 | 96 | assertThat(encounters.size()).isEqualTo(3); 97 | } 98 | 99 | @Test 100 | public void isOwnEncountersForOwnEncounterShouldReturnTrue() throws Exception { 101 | given(repository.findByIdAndUsername(anyLong(), anyString())).willReturn(testEncounter(1)); 102 | boolean ownEncounter = service.isOwnEncounter(1, "test"); 103 | 104 | assertThat(ownEncounter).isTrue(); 105 | } 106 | 107 | @Test 108 | public void isOwnEncountersForOtherEncounterShouldReturnFalse() throws Exception { 109 | given(repository.findByIdAndUsername(anyLong(), anyString())).willReturn(null); 110 | boolean ownEncounter = service.isOwnEncounter(1, "test"); 111 | 112 | assertThat(ownEncounter).isFalse(); 113 | } 114 | } -------------------------------------------------------------------------------- /duke-encounters/src/test/java/de/dominikschadow/dukeencounters/home/HomeControllerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.home; 19 | 20 | import de.dominikschadow.dukeencounters.DukeEncountersApplication; 21 | import org.junit.Before; 22 | import org.junit.Test; 23 | import org.junit.runner.RunWith; 24 | import org.springframework.beans.factory.annotation.Autowired; 25 | import org.springframework.boot.test.context.SpringBootTest; 26 | import org.springframework.test.context.junit4.SpringRunner; 27 | import org.springframework.test.context.web.WebAppConfiguration; 28 | import org.springframework.test.web.servlet.MockMvc; 29 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; 30 | import org.springframework.web.context.WebApplicationContext; 31 | 32 | import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; 33 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 34 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 35 | 36 | /** 37 | * Tests the [@link HomeController} class. 38 | * 39 | * @author Dominik Schadow 40 | */ 41 | @RunWith(SpringRunner.class) 42 | @SpringBootTest(classes = DukeEncountersApplication.class) 43 | @WebAppConfiguration 44 | public class HomeControllerTest { 45 | @Autowired 46 | private WebApplicationContext context; 47 | 48 | private MockMvc mvc; 49 | 50 | @Before 51 | public void setup() { 52 | mvc = MockMvcBuilders.webAppContextSetup(context).apply(springSecurity()).build(); 53 | } 54 | 55 | @Test 56 | public void verifyHomepage() throws Exception { 57 | mvc.perform(get("/")).andExpect(status().isOk()); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /duke-encounters/src/test/java/de/dominikschadow/dukeencounters/search/SearchControllerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.search; 19 | 20 | import de.dominikschadow.dukeencounters.DukeEncountersApplication; 21 | import org.junit.Before; 22 | import org.junit.Test; 23 | import org.junit.runner.RunWith; 24 | import org.springframework.beans.factory.annotation.Autowired; 25 | import org.springframework.boot.test.context.SpringBootTest; 26 | import org.springframework.http.MediaType; 27 | import org.springframework.test.context.junit4.SpringRunner; 28 | import org.springframework.test.context.web.WebAppConfiguration; 29 | import org.springframework.test.web.servlet.MockMvc; 30 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; 31 | import org.springframework.web.context.WebApplicationContext; 32 | 33 | import static org.hamcrest.Matchers.hasSize; 34 | import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; 35 | import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; 36 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 37 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; 38 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; 39 | 40 | /** 41 | * Tests the [@link SearchController} class. 42 | * 43 | * @author Dominik Schadow 44 | */ 45 | @RunWith(SpringRunner.class) 46 | @SpringBootTest(classes = DukeEncountersApplication.class) 47 | @WebAppConfiguration 48 | public class SearchControllerTest { 49 | @Autowired 50 | private WebApplicationContext context; 51 | 52 | private MockMvc mvc; 53 | 54 | @Before 55 | public void setup() { 56 | mvc = MockMvcBuilders.webAppContextSetup(context).apply(springSecurity()).build(); 57 | } 58 | 59 | @Test 60 | public void searchEncounter() throws Exception { 61 | mvc.perform(get("/search")) 62 | .andExpect(status().isOk()) 63 | .andExpect(view().name("search")); 64 | } 65 | 66 | @Test 67 | public void quickSearchEncounter() throws Exception { 68 | mvc.perform(post("/search").with(csrf()) 69 | .contentType(MediaType.APPLICATION_FORM_URLENCODED) 70 | .param("quickSearch", "JavaOne 2015")) 71 | .andExpect(status().isOk()) 72 | .andExpect(view().name("encounters")) 73 | .andExpect(model().attribute("encounters", hasSize(1))); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /duke-encounters/src/test/java/de/dominikschadow/dukeencounters/services/UserServiceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com 3 | * 4 | * This file is part of the Application Intrusion Detection project. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package de.dominikschadow.dukeencounters.services; 19 | 20 | import de.dominikschadow.dukeencounters.DukeEncountersApplication; 21 | import de.dominikschadow.dukeencounters.user.UserService; 22 | import org.junit.Test; 23 | import org.junit.runner.RunWith; 24 | import org.springframework.beans.factory.annotation.Autowired; 25 | import org.springframework.boot.test.context.SpringBootTest; 26 | import org.springframework.test.context.junit4.SpringRunner; 27 | 28 | import java.util.Arrays; 29 | import java.util.List; 30 | 31 | import static org.junit.Assert.assertNotEquals; 32 | 33 | /** 34 | * Tests the [@link UserService} class. 35 | * 36 | * @author Dominik Schadow 37 | */ 38 | @RunWith(SpringRunner.class) 39 | @SpringBootTest(classes = DukeEncountersApplication.class) 40 | public class UserServiceTest { 41 | @Autowired 42 | private UserService userService; 43 | private List passwords = Arrays.asList("arthur@dent.com", "ford@prefect.com", "zaphod@beeblebrox.com", 44 | "marvin@marvin.com", "humma@kavula.com", "questular@rontok.com", "deep@thought.com", "tricia@mcmillan.com", 45 | "slartibartfast@slartibartfast.com", "jin@jenz.com", "gag@halfrunt.com", "duke@encounters.com"); 46 | 47 | @Test 48 | public void hashPassword() { 49 | for (String password : passwords) { 50 | String hashedPassword = userService.hashPassword(password); 51 | 52 | assertNotEquals(hashedPassword, password); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /findbugs-security-exclude.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /findbugs-security-include.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | --------------------------------------------------------------------------------