First attempt at moving to Spring Boot 2

This commit is contained in:
Nanne Baars 2019-09-12 17:22:03 +02:00
parent a56f41e0ea
commit 361249c666
33 changed files with 271 additions and 398 deletions

View File

@ -21,7 +21,7 @@
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.21.RELEASE</version> <version>2.1.8.RELEASE</version>
</parent> </parent>
<licenses> <licenses>

View File

@ -121,8 +121,7 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.thymeleaf.extras</groupId> <groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId> <artifactId>thymeleaf-extras-springsecurity5</artifactId>
<version>2.1.2.RELEASE</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.hsqldb</groupId> <groupId>org.hsqldb</groupId>

View File

@ -39,12 +39,15 @@ import org.owasp.webgoat.asciidoc.WebGoatVersionMacro;
import org.owasp.webgoat.asciidoc.WebWolfMacro; import org.owasp.webgoat.asciidoc.WebWolfMacro;
import org.owasp.webgoat.asciidoc.WebWolfRootMacro; import org.owasp.webgoat.asciidoc.WebWolfRootMacro;
import org.owasp.webgoat.i18n.Language; import org.owasp.webgoat.i18n.Language;
import org.thymeleaf.TemplateProcessingParameters; import org.thymeleaf.IEngineConfiguration;
import org.thymeleaf.resourceresolver.IResourceResolver; import org.thymeleaf.templateresolver.FileTemplateResolver;
import org.thymeleaf.templateresolver.TemplateResolver; import org.thymeleaf.templateresource.ITemplateResource;
import org.thymeleaf.templateresource.StringTemplateResource;
import java.io.*; import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.util.Map; import java.util.Map;
import static org.asciidoctor.Asciidoctor.Factory.create; import static org.asciidoctor.Asciidoctor.Factory.create;
@ -57,7 +60,7 @@ import static org.asciidoctor.Asciidoctor.Factory.create;
* </code> * </code>
*/ */
@Slf4j @Slf4j
public class AsciiDoctorTemplateResolver extends TemplateResolver { public class AsciiDoctorTemplateResolver extends FileTemplateResolver {
private static final Asciidoctor asciidoctor = create(); private static final Asciidoctor asciidoctor = create();
private static final String PREFIX = "doc:"; private static final String PREFIX = "doc:";
@ -65,72 +68,56 @@ public class AsciiDoctorTemplateResolver extends TemplateResolver {
public AsciiDoctorTemplateResolver(Language language) { public AsciiDoctorTemplateResolver(Language language) {
this.language = language; this.language = language;
setResourceResolver(new AdocResourceResolver());
setResolvablePatterns(Sets.newHashSet(PREFIX + "*")); setResolvablePatterns(Sets.newHashSet(PREFIX + "*"));
} }
@Override @Override
protected String computeResourceName(TemplateProcessingParameters params) { protected ITemplateResource computeTemplateResource(IEngineConfiguration configuration, String ownerTemplate, String template, String resourceName, String characterEncoding, Map<String, Object> templateResolutionAttributes) {
String templateName = params.getTemplateName(); var templateName = resourceName.substring(PREFIX.length());
return templateName.substring(PREFIX.length()); try (InputStream is = readInputStreamOrFallbackToEnglish(templateName, language)) {
}
private class AdocResourceResolver implements IResourceResolver {
@Override
public InputStream getResourceAsStream(TemplateProcessingParameters params, String resourceName) {
try (InputStream is = readInputStreamOrFallbackToEnglish(resourceName, language)) {
if (is == null) {
log.warn("Resource name: {} not found, did you add the adoc file?", resourceName);
return new ByteArrayInputStream(new byte[0]);
} else {
StringWriter writer = new StringWriter();
JavaExtensionRegistry extensionRegistry = asciidoctor.javaExtensionRegistry();
extensionRegistry.inlineMacro("webWolfLink", WebWolfMacro.class);
extensionRegistry.inlineMacro("webWolfRootLink", WebWolfRootMacro.class);
extensionRegistry.inlineMacro("webGoatVersion", WebGoatVersionMacro.class);
asciidoctor.convert(new InputStreamReader(is), writer, createAttributes());
return new ByteArrayInputStream(writer.getBuffer().toString().getBytes(StandardCharsets.UTF_8));
}
} catch (IOException e) {
//no html yet
return new ByteArrayInputStream(new byte[0]);
}
}
/**
* The resource name is for example HttpBasics_content1.adoc. This is always located in the following directory:
* <code>plugin/HttpBasics/lessonPlans/en/HttpBasics_content1.adoc</code>
*/
private String computeResourceName(String resourceName, String language) {
return String.format("lessonPlans/%s/%s", language, resourceName);
}
private InputStream readInputStreamOrFallbackToEnglish(String resourceName, Language language) {
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(computeResourceName(resourceName, language.getLocale().getLanguage()));
if (is == null) { if (is == null) {
is = Thread.currentThread().getContextClassLoader().getResourceAsStream(computeResourceName(resourceName, "en")); log.warn("Resource name: {} not found, did you add the adoc file?", templateName);
return new StringTemplateResource("");
} else {
StringWriter writer = new StringWriter();
JavaExtensionRegistry extensionRegistry = asciidoctor.javaExtensionRegistry();
extensionRegistry.inlineMacro("webWolfLink", WebWolfMacro.class);
extensionRegistry.inlineMacro("webWolfRootLink", WebWolfRootMacro.class);
extensionRegistry.inlineMacro("webGoatVersion", WebGoatVersionMacro.class);
asciidoctor.convert(new InputStreamReader(is), writer, createAttributes());
return new StringTemplateResource(writer.getBuffer().toString());
} }
return is; } catch (IOException e) {
} //no html yet
return new StringTemplateResource("");
private Map<String, Object> createAttributes() {
Map<String, Object> attributes = Maps.newHashMap();
attributes.put("source-highlighter", "coderay");
attributes.put("backend", "xhtml");
Map<String, Object> options = Maps.newHashMap();
options.put("attributes", attributes);
return options;
}
@Override
public String getName() {
return "adocResourceResolver";
} }
} }
/**
* The resource name is for example HttpBasics_content1.adoc. This is always located in the following directory:
* <code>plugin/HttpBasics/lessonPlans/en/HttpBasics_content1.adoc</code>
*/
private String computeResourceName(String resourceName, String language) {
return String.format("lessonPlans/%s/%s", language, resourceName);
}
private InputStream readInputStreamOrFallbackToEnglish(String resourceName, Language language) {
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(computeResourceName(resourceName, language.getLocale().getLanguage()));
if (is == null) {
is = Thread.currentThread().getContextClassLoader().getResourceAsStream(computeResourceName(resourceName, "en"));
}
return is;
}
private Map<String, Object> createAttributes() {
Map<String, Object> attributes = Maps.newHashMap();
attributes.put("source-highlighter", "coderay");
attributes.put("backend", "xhtml");
Map<String, Object> options = Maps.newHashMap();
options.put("attributes", attributes);
return options;
}
} }

View File

@ -1,47 +1,46 @@
/** /**
************************************************************************************************* * ************************************************************************************************
* * <p>
* * <p>
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/ * please see http://www.owasp.org/
* * <p>
* Copyright (c) 2002 - 20014 Bruce Mayhew * Copyright (c) 2002 - 20014 Bruce Mayhew
* * <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the * 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 * GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version. * 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 * 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 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* * <p>
* You should have received a copy of the GNU General Public License along with this program; if * 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 * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA. * 02111-1307, USA.
* * <p>
* Getting Source ============== * Getting Source ==============
* * <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects. * projects.
* *
* @author WebGoat * @author WebGoat
* @since October 28, 2003
* @version $Id: $Id * @version $Id: $Id
* @since October 28, 2003
*/ */
package org.owasp.webgoat; package org.owasp.webgoat;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
import lombok.SneakyThrows;
import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.ResourceLoader;
import org.thymeleaf.TemplateProcessingParameters; import org.thymeleaf.IEngineConfiguration;
import org.thymeleaf.resourceresolver.IResourceResolver; import org.thymeleaf.templateresolver.FileTemplateResolver;
import org.thymeleaf.templateresolver.TemplateResolver; import org.thymeleaf.templateresource.ITemplateResource;
import org.thymeleaf.templateresource.StringTemplateResource;
import java.io.ByteArrayInputStream; import java.io.IOException;
import java.io.File; import java.nio.charset.StandardCharsets;
import java.io.InputStream;
import java.util.Map; import java.util.Map;
/** /**
@ -53,42 +52,29 @@ import java.util.Map;
* *
* Thymeleaf will invoke this resolver based on the prefix and this implementation will resolve the html in the plugins directory * Thymeleaf will invoke this resolver based on the prefix and this implementation will resolve the html in the plugins directory
*/ */
public class LessonTemplateResolver extends TemplateResolver { public class LessonTemplateResolver extends FileTemplateResolver {
private final static String PREFIX = "lesson:"; private final static String PREFIX = "lesson:";
private final File pluginTargetDirectory;
private ResourceLoader resourceLoader; private ResourceLoader resourceLoader;
private Map<String, byte[]> resources = Maps.newHashMap(); private Map<String, byte[]> resources = Maps.newHashMap();
public LessonTemplateResolver(File pluginTargetDirectory, ResourceLoader resourceLoader) { public LessonTemplateResolver(ResourceLoader resourceLoader) {
this.pluginTargetDirectory = pluginTargetDirectory;
this.resourceLoader = resourceLoader; this.resourceLoader = resourceLoader;
setResourceResolver(new LessonResourceResolver());
setResolvablePatterns(Sets.newHashSet(PREFIX + "*")); setResolvablePatterns(Sets.newHashSet(PREFIX + "*"));
} }
@Override @Override
protected String computeResourceName(TemplateProcessingParameters params) { protected ITemplateResource computeTemplateResource(IEngineConfiguration configuration, String ownerTemplate, String template, String resourceName, String characterEncoding, Map<String, Object> templateResolutionAttributes) {
String templateName = params.getTemplateName(); var templateName = resourceName.substring(PREFIX.length());;
return templateName.substring(PREFIX.length()); byte[] resource = resources.get(templateName);
} if (resource == null) {
try {
private class LessonResourceResolver implements IResourceResolver { resource = ByteStreams.toByteArray(resourceLoader.getResource("classpath:/html/" + templateName + ".html").getInputStream());
} catch (IOException e) {
@Override e.printStackTrace();
@SneakyThrows
public InputStream getResourceAsStream(TemplateProcessingParameters params, String resourceName) {
byte[] resource = resources.get(resourceName);
if (resource == null) {
resource = ByteStreams.toByteArray(resourceLoader.getResource("classpath:/html/" + resourceName + ".html").getInputStream());
resources.put(resourceName, resource);
} }
return new ByteArrayInputStream(resource); resources.put(resourceName, resource);
}
@Override
public String getName() {
return "lessonResourceResolver";
} }
return new StringTemplateResource(new String(resource, StandardCharsets.UTF_8));
} }
} }

View File

@ -30,41 +30,38 @@
*/ */
package org.owasp.webgoat; package org.owasp.webgoat;
import com.google.common.collect.Sets;
import org.owasp.webgoat.i18n.Language; import org.owasp.webgoat.i18n.Language;
import org.owasp.webgoat.i18n.Messages; import org.owasp.webgoat.i18n.Messages;
import org.owasp.webgoat.i18n.PluginMessages; import org.owasp.webgoat.i18n.PluginMessages;
import org.owasp.webgoat.session.LabelDebugger; import org.owasp.webgoat.session.LabelDebugger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.ResourceLoader;
import org.springframework.web.servlet.LocaleResolver; import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.SessionLocaleResolver; import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import org.thymeleaf.extras.springsecurity4.dialect.SpringSecurityDialect; import org.thymeleaf.TemplateEngine;
import org.thymeleaf.spring4.SpringTemplateEngine; import org.thymeleaf.extras.springsecurity5.dialect.SpringSecurityDialect;
import org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver; import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.templateresolver.TemplateResolver; import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ITemplateResolver;
import java.io.File; import java.util.Set;
/** /**
* Configuration for Spring MVC * Configuration for Spring MVC
*/ */
@Configuration @Configuration
public class MvcConfiguration extends WebMvcConfigurerAdapter { public class MvcConfiguration implements WebMvcConfigurer {
private static final String UTF8 = "UTF-8"; private static final String UTF8 = "UTF-8";
@Autowired
@Qualifier("pluginTargetDirectory")
private File pluginTargetDirectory;
@Override @Override
public void addViewControllers(ViewControllerRegistry registry) { public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login"); registry.addViewController("/login").setViewName("login");
@ -74,13 +71,21 @@ public class MvcConfiguration extends WebMvcConfigurerAdapter {
//registry.addViewController("/list_users").setViewName("list_users"); //registry.addViewController("/list_users").setViewName("list_users");
} }
@Bean
public ViewResolver viewResolver(SpringTemplateEngine thymeleafTemplateEngine) {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(thymeleafTemplateEngine);
resolver.setCharacterEncoding("UTF-8");
return resolver;
}
@Bean @Bean
public TemplateResolver springThymeleafTemplateResolver(ApplicationContext applicationContext) { public ITemplateResolver springThymeleafTemplateResolver(ApplicationContext applicationContext) {
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver(); SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setPrefix("classpath:/templates/"); resolver.setPrefix("classpath:/templates/");
resolver.setSuffix(".html"); resolver.setSuffix(".html");
resolver.setOrder(1); resolver.setTemplateMode(TemplateMode.HTML);
resolver.setOrder(2);
resolver.setCacheable(false); resolver.setCacheable(false);
resolver.setCharacterEncoding(UTF8); resolver.setCharacterEncoding(UTF8);
resolver.setApplicationContext(applicationContext); resolver.setApplicationContext(applicationContext);
@ -89,8 +94,8 @@ public class MvcConfiguration extends WebMvcConfigurerAdapter {
@Bean @Bean
public LessonTemplateResolver lessonTemplateResolver(ResourceLoader resourceLoader) { public LessonTemplateResolver lessonTemplateResolver(ResourceLoader resourceLoader) {
LessonTemplateResolver resolver = new LessonTemplateResolver(pluginTargetDirectory, resourceLoader); LessonTemplateResolver resolver = new LessonTemplateResolver(resourceLoader);
resolver.setOrder(2); resolver.setOrder(0);
resolver.setCacheable(false); resolver.setCacheable(false);
resolver.setCharacterEncoding(UTF8); resolver.setCharacterEncoding(UTF8);
return resolver; return resolver;
@ -100,19 +105,20 @@ public class MvcConfiguration extends WebMvcConfigurerAdapter {
public AsciiDoctorTemplateResolver asciiDoctorTemplateResolver(Language language) { public AsciiDoctorTemplateResolver asciiDoctorTemplateResolver(Language language) {
AsciiDoctorTemplateResolver resolver = new AsciiDoctorTemplateResolver(language); AsciiDoctorTemplateResolver resolver = new AsciiDoctorTemplateResolver(language);
resolver.setCacheable(false); resolver.setCacheable(false);
resolver.setOrder(3); resolver.setOrder(1);
resolver.setCharacterEncoding(UTF8); resolver.setCharacterEncoding(UTF8);
return resolver; return resolver;
} }
@Bean @Bean
public SpringTemplateEngine thymeleafTemplateEngine(TemplateResolver springThymeleafTemplateResolver, public SpringTemplateEngine thymeleafTemplateEngine(ITemplateResolver springThymeleafTemplateResolver,
LessonTemplateResolver lessonTemplateResolver, LessonTemplateResolver lessonTemplateResolver,
AsciiDoctorTemplateResolver asciiDoctorTemplateResolver) { AsciiDoctorTemplateResolver asciiDoctorTemplateResolver) {
SpringTemplateEngine engine = new SpringTemplateEngine(); SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setEnableSpringELCompiler(true);
engine.addDialect(new SpringSecurityDialect()); engine.addDialect(new SpringSecurityDialect());
engine.setTemplateResolvers( engine.setTemplateResolvers(
Sets.newHashSet(springThymeleafTemplateResolver, lessonTemplateResolver, asciiDoctorTemplateResolver)); Set.of(lessonTemplateResolver, asciiDoctorTemplateResolver, springThymeleafTemplateResolver));
return engine; return engine;
} }
@ -123,12 +129,10 @@ public class MvcConfiguration extends WebMvcConfigurerAdapter {
*/ */
@Override @Override
public void addResourceHandlers(ResourceHandlerRegistry registry) { public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/plugin_lessons/**").addResourceLocations("file:///" + pluginTargetDirectory.toString() + "/");
registry.addResourceHandler("/images/**").addResourceLocations("classpath:/images/"); registry.addResourceHandler("/images/**").addResourceLocations("classpath:/images/");
registry.addResourceHandler("/lesson_js/**").addResourceLocations("classpath:/js/"); registry.addResourceHandler("/lesson_js/**").addResourceLocations("classpath:/js/");
registry.addResourceHandler("/lesson_css/**").addResourceLocations("classpath:/css/"); registry.addResourceHandler("/lesson_css/**").addResourceLocations("classpath:/css/");
registry.addResourceHandler("/video/**").addResourceLocations("classpath:/video/"); registry.addResourceHandler("/video/**").addResourceLocations("classpath:/video/");
super.addResourceHandlers(registry);
} }
@Bean @Bean

View File

@ -30,15 +30,11 @@
*/ */
package org.owasp.webgoat; package org.owasp.webgoat;
import org.owasp.webgoat.plugins.PluginEndpointPublisher;
import org.owasp.webgoat.plugins.PluginsLoader;
import org.owasp.webgoat.session.Course;
import org.owasp.webgoat.session.UserSessionData; import org.owasp.webgoat.session.UserSessionData;
import org.owasp.webgoat.session.WebSession; import org.owasp.webgoat.session.WebSession;
import org.owasp.webgoat.session.WebgoatContext; import org.owasp.webgoat.session.WebgoatContext;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode; import org.springframework.context.annotation.ScopedProxyMode;
@ -66,16 +62,6 @@ public class WebGoat {
return new UserSessionData("test", "data"); return new UserSessionData("test", "data");
} }
@Bean
public PluginEndpointPublisher pluginEndpointPublisher(ApplicationContext applicationContext) {
return new PluginEndpointPublisher(applicationContext);
}
@Bean
public Course course(PluginEndpointPublisher pluginEndpointPublisher) {
return new PluginsLoader(pluginEndpointPublisher).loadPlugins();
}
@Bean @Bean
public RestTemplate restTemplate() { public RestTemplate restTemplate() {
return new RestTemplate(); return new RestTemplate();

View File

@ -35,6 +35,7 @@ import org.owasp.webgoat.users.UserService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; 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.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity;
@ -42,6 +43,7 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
/** /**
* Security configuration for WebGoat. * Security configuration for WebGoat.
@ -90,4 +92,16 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
public UserDetailsService userDetailsServiceBean() throws Exception { public UserDetailsService userDetailsServiceBean() throws Exception {
return userDetailsService; return userDetailsService;
} }
@Override
@Bean
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
@SuppressWarnings("deprecation")
@Bean
public NoOpPasswordEncoder passwordEncoder() {
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
}
} }

View File

@ -41,7 +41,8 @@ import org.springframework.beans.factory.annotation.Autowired;
* </p> * </p>
* Note: each subclass should declare this annotation otherwise the WebGoat framework cannot find your endpoint. * Note: each subclass should declare this annotation otherwise the WebGoat framework cannot find your endpoint.
*/ */
public abstract class AssignmentEndpoint extends Endpoint { //TODO: rename to assignment
public abstract class AssignmentEndpoint {
@Autowired @Autowired
private UserTrackerRepository userTrackerRepository; private UserTrackerRepository userTrackerRepository;
@ -76,11 +77,6 @@ public abstract class AssignmentEndpoint extends Endpoint {
return userSessionData; return userSessionData;
} }
@Override
public final String getPath() {
return this.getClass().getAnnotationsByType(AssignmentPath.class)[0].value();
}
/** /**
* Convenience method for create a successful result: * Convenience method for create a successful result:
* *

View File

@ -1,5 +1,9 @@
package org.owasp.webgoat.assignments; package org.owasp.webgoat.assignments;
import org.springframework.core.annotation.AliasFor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
@ -10,7 +14,15 @@ import java.lang.annotation.Target;
*/ */
@Target(ElementType.TYPE) @Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
//@RequestMapping
public @interface AssignmentPath { public @interface AssignmentPath {
String value(); // @AliasFor(annotation = RequestMapping.class)
String[] path() default {};
// @AliasFor(annotation = RequestMapping.class)
RequestMethod[] method() default {};
// @AliasFor("path")
String value() default "";
} }

View File

@ -1,41 +0,0 @@
/*
* 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 - 2017 Bruce Mayhew
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
* <p>
* Getting Source ==============
* <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
* <p>
*/
package org.owasp.webgoat.assignments;
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
public abstract class Endpoint implements MvcEndpoint {
@Override
public final boolean isSensitive() {
return false;
}
@Override
public final Class<? extends org.springframework.boot.actuate.endpoint.Endpoint> getEndpointType() {
return null;
}
}

View File

@ -52,8 +52,8 @@ public class Assignment {
//Hibernate //Hibernate
} }
public Assignment(String name, String path) { public Assignment(String name) {
this(name, path, Lists.newArrayList()); this(name, name, Lists.newArrayList());
} }
public Assignment(String name, String path, List<String> hints) { public Assignment(String name, String path, List<String> hints) {

View File

@ -1,66 +0,0 @@
package org.owasp.webgoat.plugins;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.assignments.Endpoint;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import java.util.List;
/**
* ************************************************************************************************
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
* <p>
* Copyright (c) 2002 - 20014 Bruce Mayhew
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
* <p>
* Getting Source ==============
* <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
* <p>
*
* @author nbaars
* @version $Id: $Id
* @since October 16, 2016
*/
@Slf4j
public class PluginEndpointPublisher {
private AbstractApplicationContext applicationContext;
public PluginEndpointPublisher(ApplicationContext applicationContext) {
this.applicationContext = (AbstractApplicationContext) applicationContext;
}
public void publish(List<Class<Endpoint>> endpoints) {
endpoints.forEach(e -> publishEndpoint(e));
}
private void publishEndpoint(Class<? extends MvcEndpoint> e) {
try {
BeanDefinition beanDefinition = new RootBeanDefinition(e, Autowire.BY_TYPE.value(), true);
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getBeanFactory();
beanFactory.registerBeanDefinition(beanDefinition.getBeanClassName(), beanDefinition);
} catch (Exception ex) {
log.error("Failed to register " + e.getSimpleName() + " as endpoint with Spring, skipping...");
}
}
}

View File

@ -3,19 +3,12 @@ package org.owasp.webgoat.plugins;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import org.owasp.webgoat.assignments.AssignmentEndpoint; import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.Endpoint;
import org.owasp.webgoat.lessons.NewLesson; import org.owasp.webgoat.lessons.NewLesson;
import java.net.URL; import java.net.URL;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/**
* Plugin resource
*
* @author nbaars
* @since 3/4/17.
*/
@AllArgsConstructor @AllArgsConstructor
@Getter @Getter
public class PluginResource { public class PluginResource {
@ -27,13 +20,6 @@ public class PluginResource {
return classes.stream().filter(c -> c.getSuperclass() == NewLesson.class).collect(Collectors.toList()); return classes.stream().filter(c -> c.getSuperclass() == NewLesson.class).collect(Collectors.toList());
} }
public List<Class<Endpoint>> getEndpoints() {
return classes.stream().
filter(c -> c.getSuperclass() == AssignmentEndpoint.class || c.getSuperclass() == Endpoint.class).
map(c -> (Class<Endpoint>) c).
collect(Collectors.toList());
}
public List<Class<AssignmentEndpoint>> getAssignments(Class lesson) { public List<Class<AssignmentEndpoint>> getAssignments(Class lesson) {
return classes.stream(). return classes.stream().
filter(c -> c.getSuperclass() == AssignmentEndpoint.class). filter(c -> c.getSuperclass() == AssignmentEndpoint.class).

View File

@ -8,14 +8,22 @@ import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.assignments.AssignmentEndpoint; import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentHints; import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AssignmentPath; import org.owasp.webgoat.assignments.AssignmentPath;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.lessons.AbstractLesson; import org.owasp.webgoat.lessons.AbstractLesson;
import org.owasp.webgoat.lessons.Assignment; import org.owasp.webgoat.lessons.Assignment;
import org.owasp.webgoat.lessons.NewLesson; import org.owasp.webgoat.lessons.NewLesson;
import org.owasp.webgoat.session.Course; import org.owasp.webgoat.session.Course;
import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.type.filter.RegexPatternTypeFilter; import org.springframework.core.type.filter.RegexPatternTypeFilter;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.net.URL; import java.net.URL;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -56,13 +64,12 @@ import static java.util.stream.Collectors.toList;
*/ */
@AllArgsConstructor @AllArgsConstructor
@Slf4j @Slf4j
@Configuration
public class PluginsLoader { public class PluginsLoader {
private final PluginEndpointPublisher pluginEndpointPublisher;
/** /**
* <p>createLessonsFromPlugins.</p> * <p>createLessonsFromPlugins.</p>
*/ */
@Bean
public Course loadPlugins() { public Course loadPlugins() {
List<AbstractLesson> lessons = Lists.newArrayList(); List<AbstractLesson> lessons = Lists.newArrayList();
for (PluginResource plugin : findPluginResources()) { for (PluginResource plugin : findPluginResources()) {
@ -70,7 +77,7 @@ public class PluginsLoader {
plugin.getLessons().forEach(c -> { plugin.getLessons().forEach(c -> {
NewLesson lesson = null; NewLesson lesson = null;
try { try {
lesson = (NewLesson) c.newInstance(); lesson = (NewLesson) c.getConstructor().newInstance();
log.trace("Lesson loaded: {}", lesson.getId()); log.trace("Lesson loaded: {}", lesson.getId());
} catch (Exception e) { } catch (Exception e) {
log.error("Error while loading:" + c, e); log.error("Error while loading:" + c, e);
@ -78,7 +85,6 @@ public class PluginsLoader {
List<Class<AssignmentEndpoint>> assignments = plugin.getAssignments(c); List<Class<AssignmentEndpoint>> assignments = plugin.getAssignments(c);
lesson.setAssignments(createAssignment(assignments)); lesson.setAssignments(createAssignment(assignments));
lessons.add(lesson); lessons.add(lesson);
pluginEndpointPublisher.publish(plugin.getEndpoints());
}); });
} catch (Exception e) { } catch (Exception e) {
log.error("Error in loadLessons: ", e); log.error("Error in loadLessons: ", e);
@ -97,7 +103,29 @@ public class PluginsLoader {
} }
private String getPath(Class<AssignmentEndpoint> e) { private String getPath(Class<AssignmentEndpoint> e) {
return e.getAnnotationsByType(AssignmentPath.class)[0].value(); for (Method m : e.getMethods()) {
if (m.getReturnType() == AttackResult.class) {
var mapping = m.getAnnotation(RequestMapping.class);
if (mapping == null) {
log.error("AttackResult method found without mapping in: {}", e.getSimpleName());
} else {
return getMapping(m);
}
}
}
return "";
}
private String getMapping(Method m) {
String[] path = null;
if (m.getAnnotation(RequestMapping.class) != null) {
path = m.getAnnotation(RequestMapping.class).path();
} else if (m.getAnnotation(PostMapping.class) != null) {
path = m.getAnnotation(PostMapping.class).path();
} else if (m.getAnnotation(GetMapping.class) != null) {
path = m.getAnnotation(GetMapping.class).value();
}
return path != null && path.length > 0 ? path[0] : "";
} }
private List<String> getHints(Class<AssignmentEndpoint> e) { private List<String> getHints(Class<AssignmentEndpoint> e) {
@ -107,8 +135,6 @@ public class PluginsLoader {
return Lists.newArrayList(); return Lists.newArrayList();
} }
@SneakyThrows @SneakyThrows
public List<PluginResource> findPluginResources() { public List<PluginResource> findPluginResources() {
final ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false); final ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);

View File

@ -76,7 +76,7 @@ public class LessonProgressService {
} }
private List<LessonOverview> toJson(Map<Assignment, Boolean> map) { private List<LessonOverview> toJson(Map<Assignment, Boolean> map) {
ArrayList<LessonOverview> result = Lists.newArrayList(); List<LessonOverview> result = new ArrayList();
for (Map.Entry<Assignment, Boolean> entry : map.entrySet()) { for (Map.Entry<Assignment, Boolean> entry : map.entrySet()) {
result.add(new LessonOverview(entry.getKey(), entry.getValue())); result.add(new LessonOverview(entry.getKey(), entry.getValue()));
} }

View File

@ -1,7 +1,7 @@
server.error.include-stacktrace=always server.error.include-stacktrace=always
server.error.path=/error.html server.error.path=/error.html
server.session.timeout=600 server.session.timeout=600
server.contextPath=/WebGoat server.servlet.context-path=/WebGoat
server.port=${WEBGOAT_PORT:8080} server.port=${WEBGOAT_PORT:8080}
server.address=${WEBGOAT_HOST:127.0.0.1} server.address=${WEBGOAT_HOST:127.0.0.1}
@ -17,6 +17,11 @@ spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.HSQLDialect spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.HSQLDialect
spring.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver spring.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver
logging.level.org.thymeleaf=DEBUG
logging.level.org.thymeleaf.TemplateEngine.CONFIG=TRACE
logging.level.org.thymeleaf.TemplateEngine.TIMER=TRACE
logging.level.org.thymeleaf.TemplateEngine.cache.TEMPLATE_CACHE=TRACE
logging.level.org.springframework.web=TRACE
logging.level.org.springframework=INFO logging.level.org.springframework=INFO
logging.level.org.springframework.boot.devtools=INFO logging.level.org.springframework.boot.devtools=INFO
logging.level.org.owasp=DEBUG logging.level.org.owasp=DEBUG
@ -25,7 +30,6 @@ logging.level.org.owasp.webgoat=TRACE
# Needed for creating a vulnerable web application # Needed for creating a vulnerable web application
security.enable-csrf=false security.enable-csrf=false
spring.resources.cache-period=0
spring.thymeleaf.cache=false spring.thymeleaf.cache=false
webgoat.start.hsqldb=true webgoat.start.hsqldb=true

View File

@ -28,15 +28,15 @@
<!-- JS --> <!-- JS -->
<script src="js/modernizr-2.6.2.min.js"/> <script src="js/modernizr-2.6.2.min.js"></script>
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries --> <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]> <!--[if lt IE 9]>
<script src="js/html5shiv.js"/> <script src="js/html5shiv.js"></script>
<script src="js/respond.min.js"/> <script src="js/respond.min.js"></script>
<![endif]--> <![endif]-->
<!-- Require.js used to load js asynchronously --> <!-- Require.js used to load js asynchronously -->
<script src="js/libs/require.min.js" data-main="js/main.js"/> <script src="js/libs/require.min.js" data-main="js/main.js"></script>
<meta http-equiv="Content-Type" content="text/id; charset=ISO-8859-1"/> <meta http-equiv="Content-Type" content="text/id; charset=ISO-8859-1"/>
<title>WebGoat</title> <title>WebGoat</title>
</head> </head>
@ -67,8 +67,7 @@
<li role="presentation"><a role="menuitem" tabindex="-1" th:href="@{/logout}" <li role="presentation"><a role="menuitem" tabindex="-1" th:href="@{/logout}"
th:text="#{logout}">Logout</a></li> th:text="#{logout}">Logout</a></li>
<li role="presentation" class="divider"></li> <li role="presentation" class="divider"></li>
<li role="presentation" class="disabled"><a role="menuitem" tabindex="-1" href="#">User: <span <li role="presentation" class="disabled"><a role="menuitem" tabindex="-1" href="#">User: <span sec:authentication="name"></span></a>
th:text="${#authentication.name}"></span></a>
</li> </li>
<li role="presentation" class="disabled"><a role="menuitem" tabindex="-1" href="#">Role: <li role="presentation" class="disabled"><a role="menuitem" tabindex="-1" href="#">Role:
<span sec:authorize="hasAuthority('WEBGOAT_USER')">User</span> <span sec:authorize="hasAuthority('WEBGOAT_USER')">User</span>
@ -134,14 +133,14 @@
<div id="lesson-content-wrapper" class="panel"> <div id="lesson-content-wrapper" class="panel">
<div class="" id="error-notification-container"> <div class="" id="error-notification-container">
<div class="" id="error-notification"> <div class="" id="error-notification">
<i class="fa fa-exclamation-circle"/> There was an unexpected error. Please try <i class="fa fa-exclamation-circle"> There was an unexpected error. Please try
again. again.</i>
</div> </div>
</div> </div>
<div class="" id="help-controls"> <div class="" id="help-controls">
<button class="btn btn-primary btn-xs btn-danger help-button" <button class="btn btn-primary btn-xs btn-danger help-button"
id="show-source-button"> id="show-source-button">
<i class="fa fa-code"/> <i class="fa fa-code"></i>
</button> </button>
<button class="btn btn-primary btn-xs btn-danger help-button" <button class="btn btn-primary btn-xs btn-danger help-button"
id="show-hints-button" th:text="#{show.hints}">Show hints id="show-hints-button" th:text="#{show.hints}">Show hints

View File

@ -6,9 +6,9 @@ import org.owasp.webgoat.i18n.PluginMessages;
import org.owasp.webgoat.session.WebSession; import org.owasp.webgoat.session.WebSession;
import org.owasp.webgoat.session.WebgoatContext; import org.owasp.webgoat.session.WebgoatContext;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.embedded.LocalServerPort;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.TestPropertySource;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.WebApplicationContext;

View File

@ -17,6 +17,8 @@ import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import java.util.List;
import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.is;
import static org.mockito.Matchers.any; import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.anyString;
@ -71,7 +73,7 @@ public class LessonProgressServiceTest {
@Before @Before
public void setup() { public void setup() {
Assignment assignment = new Assignment("test", "test"); Assignment assignment = new Assignment("test", "test", List.of());
when(userTrackerRepository.findByUser(anyString())).thenReturn(userTracker); when(userTrackerRepository.findByUser(anyString())).thenReturn(userTracker);
when(userTracker.getLessonTracker(any(AbstractLesson.class))).thenReturn(lessonTracker); when(userTracker.getLessonTracker(any(AbstractLesson.class))).thenReturn(lessonTracker);
when(websession.getCurrentLesson()).thenReturn(lesson); when(websession.getCurrentLesson()).thenReturn(lesson);

View File

@ -48,7 +48,7 @@ public class LessonTrackerTest {
@Test @Test
public void allAssignmentsSolvedShouldMarkLessonAsComplete() { public void allAssignmentsSolvedShouldMarkLessonAsComplete() {
AbstractLesson lesson = mock(AbstractLesson.class); AbstractLesson lesson = mock(AbstractLesson.class);
when(lesson.getAssignments()).thenReturn(Lists.newArrayList(new Assignment("assignment", ""))); when(lesson.getAssignments()).thenReturn(Lists.newArrayList(new Assignment("assignment", "assignment", List.of(""))));
LessonTracker lessonTracker = new LessonTracker(lesson); LessonTracker lessonTracker = new LessonTracker(lesson);
lessonTracker.assignmentSolved("assignment"); lessonTracker.assignmentSolved("assignment");
@ -58,8 +58,8 @@ public class LessonTrackerTest {
@Test @Test
public void noAssignmentsSolvedShouldMarkLessonAsInComplete() { public void noAssignmentsSolvedShouldMarkLessonAsInComplete() {
AbstractLesson lesson = mock(AbstractLesson.class); AbstractLesson lesson = mock(AbstractLesson.class);
Assignment a1 = new Assignment("a1", "a1"); Assignment a1 = new Assignment("a1");
Assignment a2 = new Assignment("a2", "a2"); Assignment a2 = new Assignment("a2");
List<Assignment> assignments = Lists.newArrayList(a1, a2); List<Assignment> assignments = Lists.newArrayList(a1, a2);
when(lesson.getAssignments()).thenReturn(assignments); when(lesson.getAssignments()).thenReturn(assignments);
LessonTracker lessonTracker = new LessonTracker(lesson); LessonTracker lessonTracker = new LessonTracker(lesson);
@ -73,7 +73,7 @@ public class LessonTrackerTest {
@Test @Test
public void solvingSameAssignmentShouldNotAddItTwice() { public void solvingSameAssignmentShouldNotAddItTwice() {
AbstractLesson lesson = mock(AbstractLesson.class); AbstractLesson lesson = mock(AbstractLesson.class);
Assignment a1 = new Assignment("a1", "a1"); Assignment a1 = new Assignment("a1");
List<Assignment> assignments = Lists.newArrayList(a1); List<Assignment> assignments = Lists.newArrayList(a1);
when(lesson.getAssignments()).thenReturn(assignments); when(lesson.getAssignments()).thenReturn(assignments);
LessonTracker lessonTracker = new LessonTracker(lesson); LessonTracker lessonTracker = new LessonTracker(lesson);

View File

@ -5,7 +5,6 @@ import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.assignments.AttackResult; import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.assignments.Endpoint;
import org.owasp.webgoat.i18n.PluginMessages; import org.owasp.webgoat.i18n.PluginMessages;
import org.owasp.webgoat.session.WebSession; import org.owasp.webgoat.session.WebSession;
import org.owasp.webgoat.users.UserTracker; import org.owasp.webgoat.users.UserTracker;
@ -27,7 +26,7 @@ import java.util.stream.IntStream;
* @since 3/23/17. * @since 3/23/17.
*/ */
@Slf4j @Slf4j
public class Flag extends Endpoint { public class Flag { //extends Endpoint {
public static final Map<Integer, String> FLAGS = Maps.newHashMap(); public static final Map<Integer, String> FLAGS = Maps.newHashMap();
@Autowired @Autowired
@ -48,10 +47,10 @@ public class Flag extends Endpoint {
IntStream.range(1, 10).forEach(i -> FLAGS.put(i, UUID.randomUUID().toString())); IntStream.range(1, 10).forEach(i -> FLAGS.put(i, UUID.randomUUID().toString()));
} }
@Override // @Override
public String getPath() { // public String getPath() {
return "challenge/flag"; // return "challenge/flag";
} // }
@RequestMapping(method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) @RequestMapping(method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody @ResponseBody

View File

@ -63,6 +63,5 @@ public class Assignment1 extends AssignmentEndpoint {
public static boolean containsHeader(HttpServletRequest request) { public static boolean containsHeader(HttpServletRequest request) {
return StringUtils.hasText(request.getHeader("X-Forwarded-For")); return StringUtils.hasText(request.getHeader("X-Forwarded-For"));
} }
} }

View File

@ -7,7 +7,6 @@ package org.owasp.webgoat.plugin;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import org.owasp.webgoat.assignments.Endpoint;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;
import org.springframework.util.FileCopyUtils; import org.springframework.util.FileCopyUtils;
@ -30,7 +29,7 @@ import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
public class Salaries extends Endpoint { public class Salaries { // {extends Endpoint {
@Value("${webgoat.user.directory}") @Value("${webgoat.user.directory}")
private String webGoatHomeDirectory; private String webGoatHomeDirectory;
@ -84,10 +83,10 @@ public class Salaries extends Endpoint {
return json; return json;
} }
@Override // @Override
public String getPath() { // public String getPath() {
return "/clientSideFiltering/salaries"; // return "/clientSideFiltering/salaries";
} // }
} }

View File

@ -1,6 +1,5 @@
package org.owasp.webgoat.plugin; package org.owasp.webgoat.plugin;
import org.owasp.webgoat.assignments.Endpoint;
import org.owasp.webgoat.i18n.PluginMessages; import org.owasp.webgoat.i18n.PluginMessages;
import org.owasp.webgoat.session.UserSessionData; import org.owasp.webgoat.session.UserSessionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -20,7 +19,7 @@ import java.util.Random;
* Created by jason on 9/30/17. * Created by jason on 9/30/17.
*/ */
public class CSRFGetFlag extends Endpoint { public class CSRFGetFlag {
@Autowired @Autowired
UserSessionData userSessionData; UserSessionData userSessionData;
@ -71,9 +70,9 @@ public class CSRFGetFlag extends Endpoint {
return response; return response;
} }
//
@Override // @Override
public String getPath() { // public String getPath() {
return "/csrf/basic-get-flag"; // return "/csrf/basic-get-flag";
} // }
} }

View File

@ -4,10 +4,7 @@ import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentHints; import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AssignmentPath; import org.owasp.webgoat.assignments.AssignmentPath;
import org.owasp.webgoat.assignments.AttackResult; import org.owasp.webgoat.assignments.AttackResult;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.io.IOException; import java.io.IOException;
@ -44,15 +41,14 @@ import java.io.IOException;
* @author Bruce Mayhew <a href="http://code.google.com/p/webgoat">WebGoat</a> * @author Bruce Mayhew <a href="http://code.google.com/p/webgoat">WebGoat</a>
* @created October 28, 2003 * @created October 28, 2003
*/ */
@AssignmentPath("/HttpBasics/attack1") @RestController
@AssignmentHints({"http-basics.hints.http_basics_lesson.1"}) @AssignmentHints({"http-basics.hints.http_basics_lesson.1"})
public class HttpBasicsLesson extends AssignmentEndpoint { public class HttpBasicsLesson extends AssignmentEndpoint {
@RequestMapping(method = RequestMethod.POST) @PostMapping("/HttpBasics/attack1")
public
@ResponseBody @ResponseBody
AttackResult completed(@RequestParam String person) throws IOException { public AttackResult completed(@RequestParam String person) {
if (!person.toString().equals("")) { if (!person.equals("")) {
return trackProgress(success() return trackProgress(success()
.feedback("http-basics.reversed") .feedback("http-basics.reversed")
.feedbackArgs(new StringBuffer(person).reverse().toString()) .feedbackArgs(new StringBuffer(person).reverse().toString())

View File

@ -4,10 +4,7 @@ import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentHints; import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AssignmentPath; import org.owasp.webgoat.assignments.AssignmentPath;
import org.owasp.webgoat.assignments.AttackResult; import org.owasp.webgoat.assignments.AttackResult;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.io.IOException; import java.io.IOException;
@ -15,49 +12,51 @@ import java.io.IOException;
/** /**
* This file is part of WebGoat, an Open Web Application Security Project * This file is part of WebGoat, an Open Web Application Security Project
* utility. For details, please see http://www.owasp.org/ * utility. For details, please see http://www.owasp.org/
* * <p>
* Copyright (c) 2002 - 20014 Bruce Mayhew * Copyright (c) 2002 - 20014 Bruce Mayhew
* * <p>
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software * the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later * Foundation; either version 2 of the License, or (at your option) any later
* version. * version.
* * <p>
* This program is distributed in the hope that it will be useful, but WITHOUT * This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details. * details.
* * <p>
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307, USA. * Place - Suite 330, Boston, MA 02111-1307, USA.
* * <p>
* Getting Source ============== * Getting Source ==============
* * <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
* for free software projects. * for free software projects.
* * <p>
* For details, please see http://webgoat.github.io * For details, please see http://webgoat.github.io
* *
* @author Bruce Mayhew <a href="http://code.google.com/p/webgoat">WebGoat</a> * @author Bruce Mayhew <a href="http://code.google.com/p/webgoat">WebGoat</a>
* @created October 28, 2003 * @created October 28, 2003
*/ */
@AssignmentPath("/HttpBasics/attack2") @RestController
@AssignmentHints({"http-basics.hints.http_basic_quiz.1", "http-basics.hints.http_basic_quiz.2"}) @AssignmentHints({"http-basics.hints.http_basic_quiz.1", "http-basics.hints.http_basic_quiz.2"})
@AssignmentPath("HttpBasics/attack2")
public class HttpBasicsQuiz extends AssignmentEndpoint { public class HttpBasicsQuiz extends AssignmentEndpoint {
@RequestMapping(method = RequestMethod.POST) @PostMapping("/HttpBasics/attack2")
public @ResponseBody AttackResult completed(@RequestParam String answer, @RequestParam String magic_answer, @RequestParam String magic_num, HttpServletRequest request) throws IOException { @ResponseBody
public AttackResult completed(@RequestParam String answer, @RequestParam String magic_answer, @RequestParam String magic_num, HttpServletRequest request) throws IOException {
if ("POST".equals(answer.toUpperCase()) && magic_answer.equals(magic_num)) { if ("POST".equals(answer.toUpperCase()) && magic_answer.equals(magic_num)) {
return trackProgress(success().build()); return trackProgress(success().build());
} else { } else {
if (!"POST".equals(answer.toUpperCase())) { if (!"POST".equals(answer.toUpperCase())) {
return trackProgress(failed().feedback("http-basics.incorrect").build()); return trackProgress(failed().feedback("http-basics.incorrect").build());
} }
if (!magic_answer.equals(magic_num)){ if (!magic_answer.equals(magic_num)) {
return trackProgress(failed().feedback("http-basics.magic").build()); return trackProgress(failed().feedback("http-basics.magic").build());
} }
} }
return trackProgress(failed().build()); return trackProgress(failed().build());
} }
} }

View File

@ -1,7 +1,6 @@
package org.owasp.webgoat.plugin; package org.owasp.webgoat.plugin;
import org.owasp.webgoat.assignments.Endpoint;
import org.owasp.webgoat.session.UserSessionData; import org.owasp.webgoat.session.UserSessionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
@ -12,7 +11,6 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -46,7 +44,7 @@ import java.util.Map;
* @since January 3, 2017 * @since January 3, 2017
*/ */
public class IDORViewOwnProfile extends Endpoint{ public class IDORViewOwnProfile {
@Autowired @Autowired
UserSessionData userSessionData; UserSessionData userSessionData;
@ -74,8 +72,8 @@ public class IDORViewOwnProfile extends Endpoint{
return details; return details;
} }
@Override // @Override
public String getPath() { // public String getPath() {
return "/IDOR/profile"; // return "/IDOR/profile";
} // }
} }

View File

@ -1,6 +1,5 @@
package org.owasp.webgoat.plugin; package org.owasp.webgoat.plugin;
import org.owasp.webgoat.assignments.Endpoint;
import org.owasp.webgoat.session.DatabaseUtilities; import org.owasp.webgoat.session.DatabaseUtilities;
import org.owasp.webgoat.session.UserSessionData; import org.owasp.webgoat.session.UserSessionData;
import org.owasp.webgoat.session.WebSession; import org.owasp.webgoat.session.WebSession;
@ -13,7 +12,7 @@ import javax.servlet.http.HttpServletRequest;
import java.sql.*; import java.sql.*;
import java.util.HashMap; import java.util.HashMap;
public class Users extends Endpoint{ public class Users {
@Autowired @Autowired
private WebSession webSession; private WebSession webSession;
@ -102,8 +101,8 @@ public class Users extends Endpoint{
return webSession; return webSession;
} }
@Override // @Override
public String getPath() { // public String getPath() {
return "/access-control/list-users"; // return "/access-control/list-users";
} // }
} }

View File

@ -1,7 +1,6 @@
package org.owasp.webgoat.plugin; package org.owasp.webgoat.plugin;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.assignments.Endpoint;
import org.owasp.webgoat.session.WebSession; import org.owasp.webgoat.session.WebSession;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
@ -41,17 +40,17 @@ import java.io.PrintWriter;
* @since November 17, 2016 * @since November 17, 2016
*/ */
@Slf4j @Slf4j
public class Ping extends Endpoint { public class Ping {
@Value("${webgoat.user.directory}") @Value("${webgoat.user.directory}")
private String webGoatHomeDirectory; private String webGoatHomeDirectory;
@Autowired @Autowired
private WebSession webSession; private WebSession webSession;
@Override // @Override
public String getPath() { // public String getPath() {
return "XXE/ping"; // return "XXE/ping";
} // }
@RequestMapping(method = RequestMethod.GET) @RequestMapping(method = RequestMethod.GET)
@ResponseBody @ResponseBody

View File

@ -147,12 +147,11 @@
<!--</dependency>--> <!--</dependency>-->
<!-- /lessons --> <!-- /lessons -->
<!-- devtools no longer working with Java 11 and Spring Boot version 1.* enable again once we move to 2.0--> <dependency>
<!--<dependency>--> <groupId>org.springframework.boot</groupId>
<!--<groupId>org.springframework.boot</groupId>--> <artifactId>spring-boot-devtools</artifactId>
<!--<artifactId>spring-boot-devtools</artifactId>--> <optional>true</optional>
<!--<optional>true</optional>--> </dependency>
<!--</dependency>-->
<dependency> <dependency>
<groupId>org.postgresql</groupId> <groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId> <artifactId>postgresql</artifactId>
@ -171,7 +170,7 @@
<requiresUnpack> <requiresUnpack>
<dependency> <dependency>
<groupId>org.thymeleaf.extra</groupId> <groupId>org.thymeleaf.extra</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId> <artifactId>thymeleaf-extras-springsecurity5++</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.asciidoctor</groupId> <groupId>org.asciidoctor</groupId>

View File

@ -4,7 +4,7 @@ import lombok.extern.slf4j.Slf4j;
import org.hsqldb.server.Server; import org.hsqldb.server.Server;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder; import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn; import org.springframework.context.annotation.DependsOn;

View File

@ -27,11 +27,7 @@ package org.owasp.webgoat;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Import;
import java.util.Map;
/** /**
* Main entry point, this project is here to get all the lesson jars included to the final jar file * Main entry point, this project is here to get all the lesson jars included to the final jar file
@ -39,7 +35,7 @@ import java.util.Map;
* @author nbaars * @author nbaars
* @date 2/21/17 * @date 2/21/17
*/ */
@SpringBootApplication @SpringBootApplication(scanBasePackages = "org.owasp.webgoat")
@Slf4j @Slf4j
public class StartWebGoat extends SpringBootServletInitializer { public class StartWebGoat extends SpringBootServletInitializer {

View File

@ -46,20 +46,17 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.thymeleaf.extras</groupId> <groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId> <artifactId>thymeleaf-extras-springsecurity5</artifactId>
<version>2.1.2.RELEASE</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId> <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency> </dependency>
<dependency>
<!-- devtools no longer working with Java 11 and Spring Boot version 1.* enable again once we move to 2.0--> <groupId>org.springframework.boot</groupId>
<!--<dependency>--> <artifactId>spring-boot-devtools</artifactId>
<!--<groupId>org.springframework.boot</groupId>--> <optional>true</optional>
<!--<artifactId>spring-boot-devtools</artifactId>--> </dependency>
<!--<optional>true</optional>-->
<!--</dependency>-->
<dependency> <dependency>
<groupId>org.webjars</groupId> <groupId>org.webjars</groupId>