From 0779f7a3d03e83ca6e461b01e53701bb151ec712 Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Tue, 24 Jan 2017 15:34:06 +0100 Subject: [PATCH] Hints per lesson (#314) Squashing and merging ... * Each assigment should have the options to have its own set of hints #278 * Updating lessons due to changes from #278 * Enable i18n client side #312 * IDOR move hints to assignment and enable i18n #312 --- .gitignore | 1 + .../main/java/org/owasp/webgoat/WebGoat.java | 12 +++ .../webgoat/endpoints/AssignmentEndpoint.java | 8 +- .../webgoat/endpoints/AssignmentHints.java | 16 ++++ .../webgoat/endpoints/AssignmentPath.java | 18 +++++ .../org/owasp/webgoat/i18n/LabelManager.java | 46 ++++++++--- .../owasp/webgoat/i18n/LabelManagerImpl.java | 78 ------------------- .../org/owasp/webgoat/i18n/LabelProvider.java | 4 +- .../owasp/webgoat/lessons/AbstractLesson.java | 8 +- .../org/owasp/webgoat/lessons/Assignment.java | 7 ++ .../java/org/owasp/webgoat/lessons/Hint.java | 61 ++------------- .../webgoat/lessons/LessonInfoModel.java | 20 +---- .../org/owasp/webgoat/lessons/NewLesson.java | 1 - .../org/owasp/webgoat/plugins/Plugin.java | 13 +++- .../owasp/webgoat/service/HintService.java | 59 +++++++++----- .../webgoat/service/LessonInfoService.java | 13 +++- .../webgoat/service/LessonMenuService.java | 1 - .../js/goatApp/controller/LessonController.js | 25 +----- .../resources/static/js/goatApp/goatApp.js | 28 +++---- .../static/js/goatApp/model/HintCollection.js | 13 +++- .../static/js/goatApp/view/GoatRouter.js | 76 +++++++----------- .../js/goatApp/view/HelpControlsView.js | 29 ++++--- .../static/js/goatApp/view/HintView.js | 38 +++++++-- .../js/goatApp/view/LessonContentView.js | 13 +++- .../static/js/goatApp/view/MenuButtonView.js | 14 ++-- .../static/js/goatApp/view/MenuView.js | 2 +- .../resources/static/js/libs/polyglot.min.js | 17 ++++ .../src/main/resources/static/js/main.js | 1 + .../webgoat/service/HintServiceTest.java | 67 ++++++++++++++++ .../java/org/owasp/webgoat/plugin/Attack.java | 4 +- .../plugin/CrossSiteScriptingLesson1.java | 3 +- .../plugin/CrossSiteScriptingLesson5a.java | 3 +- .../plugin/CrossSiteScriptingLesson5b.java | 3 +- .../plugin/CrossSiteScriptingLesson6a.java | 3 +- .../plugin/CrossSiteScriptingLesson6b.java | 3 +- .../webgoat/plugin/DOMCrossSiteScripting.java | 3 +- .../org/owasp/webgoat/plugin/HttpBasics.java | 9 +-- .../webgoat/plugin/HttpBasicsLesson.java | 13 +++- .../owasp/webgoat/plugin/HttpBasicsQuiz.java | 13 +++- .../plugin/i18n/WebGoatLabels.properties | 17 +++- .../plugin/i18n/WebGoatLabels_nl.properties | 16 ++++ .../java/org/owasp/webgoat/plugin/IDOR.java | 6 +- .../webgoat/plugin/IDORDiffAttributes.java | 3 +- .../webgoat/plugin/IDOREditOtherProfiile.java | 3 +- .../org/owasp/webgoat/plugin/IDORLogin.java | 31 ++++---- .../webgoat/plugin/IDORViewOtherProfile.java | 3 +- .../plugin/IDORViewOwnProfileAltUrl.java | 3 +- .../webgoat/plugin/ViewOtherUserProfile.java | 3 +- .../plugin/i18n/WebGoatLabels.properties | 3 + .../webgoat/plugin/SqlInjectionLesson5a.java | 3 +- .../webgoat/plugin/SqlInjectionLesson5b.java | 3 +- .../webgoat/plugin/SqlInjectionLesson6a.java | 3 +- .../webgoat/plugin/SqlInjectionLesson6b.java | 3 +- .../plugin/BlindSendFileAssignment.java | 3 +- .../webgoat/plugin/ContentTypeAssignment.java | 3 +- .../org/owasp/webgoat/plugin/SimpleXXE.java | 3 +- 56 files changed, 488 insertions(+), 367 deletions(-) create mode 100644 webgoat-container/src/main/java/org/owasp/webgoat/endpoints/AssignmentHints.java create mode 100644 webgoat-container/src/main/java/org/owasp/webgoat/endpoints/AssignmentPath.java delete mode 100644 webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelManagerImpl.java create mode 100644 webgoat-container/src/main/resources/static/js/libs/polyglot.min.js create mode 100644 webgoat-container/src/test/java/org/owasp/webgoat/service/HintServiceTest.java create mode 100644 webgoat-lessons/http-basics/src/main/resources/plugin/i18n/WebGoatLabels_nl.properties create mode 100644 webgoat-lessons/idor/src/main/resources/plugin/i18n/WebGoatLabels.properties diff --git a/.gitignore b/.gitignore index 2a128be4e..2b12904c3 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,4 @@ UserDatabase.mv.db webgoat-container/src/main/webapp/users/guest.org.owasp.webgoat.plugin.*.props webgoat-container/src/main/webapp/plugin_lessons/dist-*.pom webgoat-lessons/**/target +**/*.jar diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java b/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java index bf4c9a990..f2ac1365c 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java @@ -30,6 +30,7 @@ */ package org.owasp.webgoat; +import com.fasterxml.jackson.annotation.JsonInclude; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.catalina.Context; @@ -49,8 +50,10 @@ import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletCon import org.springframework.boot.web.support.SpringBootServletInitializer; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.ScopedProxyMode; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import java.io.File; import java.util.Arrays; @@ -68,6 +71,15 @@ public class WebGoat extends SpringBootServletInitializer { SpringApplication.run(WebGoat.class, args); } + @Bean + @Primary + public Jackson2ObjectMapperBuilder jacksonBuilder() { + Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); + builder.indentOutput(true); + builder.serializationInclusion(JsonInclude.Include.NON_NULL); + return builder; + } + @Bean(name = "pluginTargetDirectory") public File pluginTargetDirectory(@Value("${webgoat.user.directory}") final String webgoatHome) { return new File(webgoatHome); diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/endpoints/AssignmentEndpoint.java b/webgoat-container/src/main/java/org/owasp/webgoat/endpoints/AssignmentEndpoint.java index d26b3a199..0d8f42b1c 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/endpoints/AssignmentEndpoint.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/endpoints/AssignmentEndpoint.java @@ -25,6 +25,9 @@ */ package org.owasp.webgoat.endpoints; +import lombok.Getter; +import org.owasp.webgoat.i18n.LabelManager; +import org.owasp.webgoat.i18n.LabelProvider; import org.owasp.webgoat.lessons.AttackResult; import org.owasp.webgoat.session.UserSessionData; import org.owasp.webgoat.session.UserTracker; @@ -50,6 +53,9 @@ public abstract class AssignmentEndpoint extends Endpoint { private WebSession webSession; @Autowired private UserSessionData userSessionData; + @Autowired + @Getter + private LabelManager labelProvider; //// TODO: 11/13/2016 events better fit? @@ -72,6 +78,6 @@ public abstract class AssignmentEndpoint extends Endpoint { @Override public final String getPath() { - return this.getClass().getAnnotationsByType(Path.class)[0].value(); + return this.getClass().getAnnotationsByType(AssignmentPath.class)[0].value(); } } diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/endpoints/AssignmentHints.java b/webgoat-container/src/main/java/org/owasp/webgoat/endpoints/AssignmentHints.java new file mode 100644 index 000000000..5b9829587 --- /dev/null +++ b/webgoat-container/src/main/java/org/owasp/webgoat/endpoints/AssignmentHints.java @@ -0,0 +1,16 @@ +package org.owasp.webgoat.endpoints; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Created by nbaars on 1/14/17. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface AssignmentHints { + + String[] value() default {}; +} diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/endpoints/AssignmentPath.java b/webgoat-container/src/main/java/org/owasp/webgoat/endpoints/AssignmentPath.java new file mode 100644 index 000000000..9212c47d5 --- /dev/null +++ b/webgoat-container/src/main/java/org/owasp/webgoat/endpoints/AssignmentPath.java @@ -0,0 +1,18 @@ +package org.owasp.webgoat.endpoints; + +import org.springframework.core.annotation.AliasFor; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Created by nbaars on 1/14/17. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface AssignmentPath { + + String value(); +} diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelManager.java b/webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelManager.java index 21990bf6e..5421e057a 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelManager.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelManager.java @@ -1,6 +1,10 @@ package org.owasp.webgoat.i18n; +import org.owasp.webgoat.session.LabelDebugger; +import org.springframework.stereotype.Component; + +import java.io.Serializable; import java.util.Locale; @@ -33,22 +37,42 @@ import java.util.Locale; * @version $Id: $Id * @author dm */ -public interface LabelManager +@Component +public class LabelManager { + private static final long serialVersionUID = 1L; + + private LabelProvider labelProvider; + private LabelDebugger labelDebugger; + private Locale locale = new Locale(LabelProvider.DEFAULT_LANGUAGE); /** - *

setLocale.

+ *

Constructor for LabelManagerImpl.

* - * @param locale a {@link java.util.Locale} object. + * @param labelProvider a {@link LabelProvider} object. */ - public void setLocale(Locale locale); + protected LabelManager(LabelProvider labelProvider, LabelDebugger labelDebugger) { + this.labelDebugger = labelDebugger; + this.labelProvider = labelProvider; + } - /** - *

get.

- * - * @param labelKey a {@link java.lang.String} object. - * @return a {@link java.lang.String} object. - */ - public String get(String labelKey); + /** {@inheritDoc} */ + public void setLocale(Locale locale) + { + if (locale != null) + { + this.locale = locale; + } + } + + /** {@inheritDoc} */ + public String get(String labelKey, Object... params) + { + String label = labelProvider.get(locale, labelKey, params); + if (labelDebugger.isEnabled()) { + label = "" + label + ""; + } + return label; + } } diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelManagerImpl.java b/webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelManagerImpl.java deleted file mode 100644 index 0e3ed00c4..000000000 --- a/webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelManagerImpl.java +++ /dev/null @@ -1,78 +0,0 @@ - -package org.owasp.webgoat.i18n; - -import org.owasp.webgoat.session.LabelDebugger; -import org.springframework.stereotype.Component; - -import java.io.Serializable; -import java.util.Locale; - - -/** - ************************************************************************************************* - * - * - * 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. - * - * @version $Id: $Id - * @author dm - */ -@Component -public class LabelManagerImpl implements LabelManager, Serializable -{ - private static final long serialVersionUID = 1L; - - private LabelProvider labelProvider; - private LabelDebugger labelDebugger; - private Locale locale = new Locale(LabelProvider.DEFAULT_LANGUAGE); - - /** - *

Constructor for LabelManagerImpl.

- * - * @param labelProvider a {@link LabelProvider} object. - */ - protected LabelManagerImpl(LabelProvider labelProvider, LabelDebugger labelDebugger) { - this.labelDebugger = labelDebugger; - this.labelProvider = labelProvider; - } - - /** {@inheritDoc} */ - public void setLocale(Locale locale) - { - if (locale != null) - { - this.locale = locale; - } - } - - /** {@inheritDoc} */ - public String get(String labelKey) - { - String label = labelProvider.get(locale, labelKey); - if (labelDebugger.isEnabled()) { - label = "" + label + ""; - } - return label; - } - -} diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelProvider.java b/webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelProvider.java index 79057df49..cdb50ee35 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelProvider.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelProvider.java @@ -97,8 +97,8 @@ public class LabelProvider { * @param strName a {@link java.lang.String} object. * @return a {@link java.lang.String} object. */ - public String get(Locale locale, String strName) { - return pluginLabels.getMessage(strName, null, useLocaleOrFallbackToEnglish(locale)); + public String get(Locale locale, String strName, Object... params) { + return pluginLabels.getMessage(strName, params, useLocaleOrFallbackToEnglish(locale)); } private Locale useLocaleOrFallbackToEnglish(Locale locale) { diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java index 728e23b22..eb200b354 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java @@ -124,13 +124,6 @@ public abstract class AbstractLesson extends Screen implements ComparablegetSubmitMethod

- * - * @return a {@link java.lang.String} object. - */ - public abstract String getSubmitMethod(); - /** * Gets the hintCount attribute of the Lesson object * @@ -219,4 +212,5 @@ public abstract class AbstractLesson extends Screen implements Comparable hints; } diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Hint.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Hint.java index 680be7f57..2f3363d9b 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Hint.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Hint.java @@ -26,70 +26,21 @@ */ package org.owasp.webgoat.lessons; +import lombok.Getter; +import lombok.Setter; + /** *

Hint class.

* * @author rlawson * @version $Id: $Id */ +@Getter +@Setter public class Hint { private String hint; private String lesson; + private String assignmentPath; private int number; - - /** - *

Getter for the field hint.

- * - * @return the hint - */ - public String getHint() { - return hint; - } - - /** - *

Setter for the field hint.

- * - * @param hint the hint to set - */ - public void setHint(String hint) { - this.hint = hint; - } - - /** - *

Getter for the field lesson.

- * - * @return the lesson - */ - public String getLesson() { - return lesson; - } - - /** - *

Setter for the field lesson.

- * - * @param lesson the lesson to set - */ - public void setLesson(String lesson) { - this.lesson = lesson; - } - - /** - *

Getter for the field number.

- * - * @return the number - */ - public int getNumber() { - return number; - } - - /** - *

Setter for the field number.

- * - * @param number the number to set - */ - public void setNumber(int number) { - this.number = number; - } - } diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/LessonInfoModel.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/LessonInfoModel.java index c889abc8f..3a3d0f9f7 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/LessonInfoModel.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/LessonInfoModel.java @@ -1,5 +1,6 @@ package org.owasp.webgoat.lessons; +import lombok.AllArgsConstructor; import lombok.Getter; import org.owasp.webgoat.session.WebSession; @@ -9,30 +10,13 @@ import org.owasp.webgoat.session.WebSession; * @author dm * @version $Id: $Id */ -//// TODO: 11/5/2016 this can be removed??? @Getter +@AllArgsConstructor public class LessonInfoModel { private String lessonTitle; - private int numberHints; private boolean hasSource; private boolean hasSolution; private boolean hasPlan; - private String submitMethod; - /** - *

Constructor for LessonInfoModel.

- * - * @param webSession a {@link org.owasp.webgoat.session.WebSession} object. - */ - public LessonInfoModel(WebSession webSession) { - AbstractLesson lesson = webSession.getCurrentLesson(); - //TODO make these first class citizens of the lesson itself; and stop passing the session all over ... and generally tighten the checks up - this.hasSource = false; - this.hasPlan = false; - this.hasSolution = false; - this.lessonTitle = lesson.getTitle(); - this.numberHints = lesson.getHintCount(); - this.submitMethod = lesson.getSubmitMethod(); - } } diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/NewLesson.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/NewLesson.java index c0a10e9d4..98c4638e7 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/NewLesson.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/NewLesson.java @@ -34,7 +34,6 @@ import java.util.List; public abstract class NewLesson extends LessonAdapter { - @Override public abstract Category getDefaultCategory(); diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/Plugin.java b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/Plugin.java index d86aecc6b..797994051 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/Plugin.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/Plugin.java @@ -4,6 +4,8 @@ import com.google.common.base.Optional; import com.google.common.collect.Lists; import lombok.Getter; import org.owasp.webgoat.endpoints.AssignmentEndpoint; +import org.owasp.webgoat.endpoints.AssignmentHints; +import org.owasp.webgoat.endpoints.AssignmentPath; import org.owasp.webgoat.endpoints.Endpoint; import org.owasp.webgoat.lessons.AbstractLesson; import org.owasp.webgoat.lessons.Assignment; @@ -114,12 +116,17 @@ public class Plugin { private List createAssignment(List> endpoints) { - return endpoints.stream().map(e -> new Assignment(e.getSimpleName(), getPath(e))).collect(toList()); + return endpoints.stream().map(e -> new Assignment(e.getSimpleName(), getPath(e), getHints(e))).collect(toList()); } private String getPath(Class e) { - return e.getAnnotationsByType(javax.ws.rs.Path.class)[0].value(); + return e.getAnnotationsByType(AssignmentPath.class)[0].value(); } - + private List getHints(Class e) { + if (e.isAnnotationPresent(AssignmentHints.class)) { + return Lists.newArrayList(e.getAnnotationsByType(AssignmentHints.class)[0].value()); + } + return Lists.newArrayList(); + } } diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/service/HintService.java b/webgoat-container/src/main/java/org/owasp/webgoat/service/HintService.java index 970bc4831..e2479c551 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/service/HintService.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/service/HintService.java @@ -5,14 +5,16 @@ */ package org.owasp.webgoat.service; +import com.google.common.collect.Lists; +import org.owasp.webgoat.i18n.LabelManager; import org.owasp.webgoat.lessons.AbstractLesson; +import org.owasp.webgoat.lessons.Assignment; import org.owasp.webgoat.lessons.Hint; import org.owasp.webgoat.session.WebSession; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; -import java.util.ArrayList; import java.util.List; import static java.util.stream.Collectors.toList; @@ -23,9 +25,10 @@ import static java.util.stream.Collectors.toList; * @author rlawson * @version $Id: $Id */ -@Controller +@RestController public class HintService { + public static final String URL_HINTS_MVC = "/service/hint.mvc"; private final WebSession webSession; public HintService(WebSession webSession) { @@ -37,30 +40,44 @@ public class HintService { * * @return a {@link java.util.List} object. */ - @RequestMapping(path = "/service/hint.mvc", produces = "application/json") - public + @GetMapping(path = URL_HINTS_MVC, produces = "application/json") @ResponseBody - List showHint() { - List listHints = new ArrayList(); + public List showHint() { AbstractLesson l = webSession.getCurrentLesson(); - if (l == null) { - return listHints; - } - List hints = l.getHints(); + List hints = createLessonHints(l); + hints.addAll(createAssignmentHints(l)); + return hints; - if (hints == null) { - return listHints; - } - - int idx = 0; - return hints.stream().map(h -> createHint(h, l.getName(), idx)).collect(toList()); } - private Hint createHint(String hintText, String lesson, int idx) { + private List createLessonHints(AbstractLesson l) { + if ( l != null ) { + return l.getHints().stream().map(h -> createHint(h, l.getName(), null)).collect(toList()); + } + return Lists.newArrayList(); + } + + private List createAssignmentHints(AbstractLesson l) { + List hints = Lists.newArrayList(); + if ( l != null) { + List assignments = l.getAssignments(); + assignments.stream().forEach(a -> { a.getHints(); createHints(a, hints);}); + } + return hints; + } + + private void createHints(Assignment a, List hints) { + hints.addAll(a.getHints().stream().map(h -> createHint(h, null, a.getPath())).collect(toList())); + } + + private Hint createHint(String hintText, String lesson, String assignmentName) { Hint hint = new Hint(); hint.setHint(hintText); - hint.setLesson(lesson); - hint.setNumber(idx); + if (lesson != null) { + hint.setLesson(lesson); + } else { + hint.setAssignmentPath(assignmentName); + } return hint; } } diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonInfoService.java b/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonInfoService.java index 78b9f43dc..eb1e00ca8 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonInfoService.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonInfoService.java @@ -1,24 +1,30 @@ package org.owasp.webgoat.service; +import org.owasp.webgoat.i18n.LabelManager; +import org.owasp.webgoat.lessons.AbstractLesson; import org.owasp.webgoat.lessons.LessonInfoModel; import org.owasp.webgoat.session.WebSession; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + -@Controller /** *

LessonInfoService class.

* * @author dm * @version $Id: $Id */ +@RestController public class LessonInfoService { private final WebSession webSession; + private final LabelManager labelManager; - public LessonInfoService(WebSession webSession) { + public LessonInfoService(WebSession webSession, LabelManager labelManager) { this.webSession = webSession; + this.labelManager = labelManager; } /** @@ -29,7 +35,8 @@ public class LessonInfoService { @RequestMapping(path = "/service/lessoninfo.mvc", produces = "application/json") public @ResponseBody LessonInfoModel getLessonInfo() { - return new LessonInfoModel(webSession); + AbstractLesson lesson = webSession.getCurrentLesson(); + return new LessonInfoModel(labelManager.get(lesson.getTitle()), false, false, false); } } diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonMenuService.java b/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonMenuService.java index 8f343d6d2..4a2e22077 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonMenuService.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonMenuService.java @@ -56,7 +56,6 @@ public class LessonMenuService { private final Course course; private UserTracker userTracker; - private final WebSession webSession; /** * Returns the lesson menu which is used to build the left nav diff --git a/webgoat-container/src/main/resources/static/js/goatApp/controller/LessonController.js b/webgoat-container/src/main/resources/static/js/goatApp/controller/LessonController.js index 45b8e5d31..6ce9932b1 100644 --- a/webgoat-container/src/main/resources/static/js/goatApp/controller/LessonController.js +++ b/webgoat-container/src/main/resources/static/js/goatApp/controller/LessonController.js @@ -72,6 +72,7 @@ define(['jquery', if (this.name === name) { this.lessonContentView.navToPage(pageNum); + this.lessonHintView.hideHints(); this.titleView.render(this.lessonInfoModel.get('lessonTitle')); return; } @@ -80,9 +81,7 @@ define(['jquery', if (typeof(name) === 'undefined' || name === null) { //TODO: implement lesson not found or return to welcome page? } - this.lessonContent.loadData({ - 'name':name - }); + this.lessonContent.loadData({'name':name}); this.planView = {}; this.solutionView = {}; this.sourceView = {}; @@ -94,23 +93,20 @@ define(['jquery', this.helpControlsView = new HelpControlsView({ hasPlan:this.lessonInfoModel.get('hasPlan'), hasSolution:this.lessonInfoModel.get('hasSolution'), - hasSource:this.lessonInfoModel.get('hasSource'), - hasHints:(this.lessonInfoModel.get('numberHints') > 0) - //hasAttack:this.lessonInfo.get('hasAttack') // TODO: add attack options + hasSource:this.lessonInfoModel.get('hasSource') }); this.listenTo(this.helpControlsView,'hints:show',this.showHints); this.listenTo(this.helpControlsView,'lessonOverview:show',this.showLessonOverview) - this.listenTo(this.helpControlsView,'attack:show',this.hideShowAttack); this.listenTo(this.helpControlsView,'solution:show',this.hideShowHelps); this.listenTo(this.helpControlsView,'source:show',this.hideShowHelps); this.listenTo(this.helpControlsView,'lesson:restart',this.restartLesson); this.listenTo(this.developerControlsView, 'dev:labels', this.restartLesson); - this.listenTo(this,'hints:show',this.onShowHints); this.helpControlsView.render(); this.lessonOverview.hideLessonOverview(); this.titleView.render(this.lessonInfoModel.get('lessonTitle')); + this.helpControlsView.showHideHintsButton({}); }; this.updateMenu = function() { @@ -191,19 +187,6 @@ define(['jquery', this.lessonOverviewModel.fetch().then(this.lessonOverview.render()); }; - this.hideShowAttack = function (options) { // will likely expand this to encompass - if (options.show) { - $('#attack-container').show(); - $('#attack-container div.modal-header button.close, #about-modal div.modal-footer button').unbind('click').on('click', function() { - $('#attack-container').hide(200); - }); - if (this.lessonInfoModel.get('numberHints') > 0) { - - this.lessonContentView.$el.find('#show-hints-button').unbind().on('click',_.bind(this.showHints,this)).show(); - } - } - }; - this.restartLesson = function() { var self=this; $.ajax({ diff --git a/webgoat-container/src/main/resources/static/js/goatApp/goatApp.js b/webgoat-container/src/main/resources/static/js/goatApp/goatApp.js index 56dbc31fd..cea94194e 100644 --- a/webgoat-container/src/main/resources/static/js/goatApp/goatApp.js +++ b/webgoat-container/src/main/resources/static/js/goatApp/goatApp.js @@ -1,13 +1,15 @@ -define(['jquery','underscore','backbone','goatApp/view/GoatRouter', 'goatApp/support/goatAsyncErrorHandler'], - function($,_,Backbone,Router, asyncErrorHandler){ - 'use strict' - //var goatRouter = new Router(); - return { - initApp: function() { - asyncErrorHandler.init(); - //TODO: add query/ability to load from where they left off - var goatRouter = new Router(); - goatRouter.init(); - } - }; -}); \ No newline at end of file +define(['jquery', 'underscore', 'backbone', 'polyglot', 'goatApp/view/GoatRouter', 'goatApp/support/goatAsyncErrorHandler'], + function ($, _, Backbone, Polyglot, Router, asyncErrorHandler) { + 'use strict' + return { + initApp: function () { + var locale = localStorage.getItem('locale') || 'en'; + $.getJSON('service/labels.mvc?lang=' + locale, function(data) { + window.polyglot = new Polyglot({phrases: data}); + asyncErrorHandler.init(); + var goatRouter = new Router(); + }); + + } + }; + }); \ No newline at end of file diff --git a/webgoat-container/src/main/resources/static/js/goatApp/model/HintCollection.js b/webgoat-container/src/main/resources/static/js/goatApp/model/HintCollection.js index 316645fa1..dc355441e 100644 --- a/webgoat-container/src/main/resources/static/js/goatApp/model/HintCollection.js +++ b/webgoat-container/src/main/resources/static/js/goatApp/model/HintCollection.js @@ -1,7 +1,7 @@ define(['jquery', 'underscore', 'backbone', - 'goatApp/model/HintModel'], + 'goatApp/model/HintModel'], function($, _, @@ -25,8 +25,17 @@ define(['jquery', checkNullModel:function() { if (this.models[0].indexOf('There are no hints defined.') > -1) { this.reset([]); - //return this.models; } + }, + + getHintsForAssignment: function(assignmentPath) { + var assignmentHints = new Array(); + this.models.forEach(function(hint) { + if (assignmentPath.includes(hint.get('assignmentPath'))) { + assignmentHints.push(hint); + } + }); + return assignmentHints; } }); }); \ No newline at end of file diff --git a/webgoat-container/src/main/resources/static/js/goatApp/view/GoatRouter.js b/webgoat-container/src/main/resources/static/js/goatApp/view/GoatRouter.js index b1a219667..52c8a1c30 100644 --- a/webgoat-container/src/main/resources/static/js/goatApp/view/GoatRouter.js +++ b/webgoat-container/src/main/resources/static/js/goatApp/view/GoatRouter.js @@ -17,11 +17,6 @@ define(['jquery', DeveloperControlsView, TitleView) { - var lessonContentView = new LessonContentView(); - var menuView = new MenuView(); - var developerControlsView = new DeveloperControlsView(); - var titleView = new TitleView(); - function getContentElement() { return $('#main-content'); }; @@ -38,7 +33,8 @@ define(['jquery', }; var GoatAppRouter = Backbone.Router.extend({ - routes: { + + routes: { 'welcome': 'welcomeRoute', 'lesson/:name': 'lessonRoute', 'lesson/:name/:pageNum': 'lessonPageRoute', @@ -46,14 +42,9 @@ define(['jquery', 'reportCard': 'reportCard' }, - lessonController: new LessonController({ - lessonContentView: lessonContentView, - titleView: titleView - }), - - menuController: new MenuController({ - menuView: menuView - }), + lessonController: null, + menuController : null, + titleView: null, setUpCustomJS: function () { webgoat.customjs.jquery = $; //passing jquery into custom js scope ... still klunky, but works for now @@ -75,54 +66,45 @@ define(['jquery', } }, - init: function () { - goatRouter = new GoatAppRouter(); + initialize: function () { + this.menuController = new MenuController({menuView: new MenuView()}); + this.titleView = new TitleView(); + this.lessonController = new LessonController({lessonContentView: new LessonContentView(), titleView: this.titleView}), this.lessonController.start(); - // this.menuController.initMenu(); webgoat = {}; webgoat.customjs = {}; this.setUpCustomJS(); - - goatRouter.on('route:lessonRoute', function (name) { - render(); - this.lessonController.loadLesson(name, 0); - //TODO - update menu code from below - this.menuController.updateMenu(name); - }); - - goatRouter.on('route:lessonPageRoute', function (name, pageNum) { - render(); - pageNum = (_.isNumber(parseInt(pageNum))) ? parseInt(pageNum) : 0; - this.lessonController.loadLesson(name, pageNum); - //TODO - update menu code from below - this.menuController.updateMenu(name); - }); - - goatRouter.on('route:welcomeRoute', function () { - render(); - this.lessonController.loadWelcome(); - }); - - goatRouter.on('route:testRoute', function (param) { - render(); - this.lessonController.testHandler(param); - }); - - goatRouter.on("route", function (route, params) { - }); - Backbone.history.start(); this.listenTo(this.lessonController, 'menu:reload', this.reloadMenu) }, + lessonRoute: function(name) { + render(); + this.lessonController.loadLesson(name, 0); + this.menuController.updateMenu(name); + }, + + lessonPageRoute: function (name, pageNum) { + render(); + pageNum = (_.isNumber(parseInt(pageNum))) ? parseInt(pageNum) : 0; + this.lessonController.loadLesson(name, pageNum); + this.menuController.updateMenu(name); + }, + + welcomeRoute: function () { + render(); + this.lessonController.loadWelcome(); + }, + reloadMenu: function (curLesson) { this.menuController.updateMenu(); }, reportCard : function () { + var self = this; require(['goatApp/view/ReportCardView'], function (ReportCardView) { - titleView.render('Report card'); + self.titleView.render('Report card'); render(new ReportCardView()); }); }, diff --git a/webgoat-container/src/main/resources/static/js/goatApp/view/HelpControlsView.js b/webgoat-container/src/main/resources/static/js/goatApp/view/HelpControlsView.js index 34798fda5..26f20f345 100644 --- a/webgoat-container/src/main/resources/static/js/goatApp/view/HelpControlsView.js +++ b/webgoat-container/src/main/resources/static/js/goatApp/view/HelpControlsView.js @@ -12,33 +12,34 @@ function($,_,Backbone) { this.hasPlan = options.hasPlan; this.hasSolution = options.hasSolution; this.hasSource = options.hasSource; - this.hasHints = options.hasHints; + var self = this; + Backbone.on('navigatedToPage', function(nav) { + self.showHideHintsButton(nav) + }); }, - + + showHideHintsButton: function(nav) { + if (typeof nav['assignmentPath'] !== 'undefined') { + this.$el.find('#show-hints-button').unbind().on('click',this.showHints.bind(this)).show(); + } else { + $('#show-hints-button').hide(); + } + }, + render:function(title) { - //this.$el.html(); - // if still showing, hide $('#show-source-button').hide(); $('#show-solution-button').hide(); $('#show-plan-button').hide(); - $('#show-hints-button').hide(); if (this.hasSource) { this.$el.find('#show-source-button').unbind().on('click',_.bind(this.showSource,this)).show(); } - if (this.hasHints) { - this.$el.find('#show-hints-button').unbind().on('click',this.showHints.bind(this)).show(); - } if (this.hasSolution) { this.$el.find('#show-solution-button').unbind().on('click',_.bind(this.showSolution,this)).show(); } - if (true) { //FIXME: change to this.hasAttack - this.$el.find('#show-attack-button').unbind().on('click',_.bind(this.showAttack,this)).show(); - } this.$el.find('#show-lesson-overview-button').unbind().on('click', _.bind(this.showLessonOverview, this)).show(); this.$el.find('#restart-lesson-button').unbind().on('click',_.bind(this.restartLesson,this)).show(); - //this.$el.append(this.helpButtons.restartLesson); }, showHints: function() { @@ -53,10 +54,6 @@ function($,_,Backbone) { this.trigger('solution:show','solution'); }, - showAttack: function() { - this.trigger('attack:show',{show:true}); - }, - restartLesson: function() { this.trigger('lesson:restart'); }, diff --git a/webgoat-container/src/main/resources/static/js/goatApp/view/HintView.js b/webgoat-container/src/main/resources/static/js/goatApp/view/HintView.js index 564acde68..06094592b 100644 --- a/webgoat-container/src/main/resources/static/js/goatApp/view/HintView.js +++ b/webgoat-container/src/main/resources/static/js/goatApp/view/HintView.js @@ -15,8 +15,13 @@ function($, initialize: function() { this.curHint=0; this.collection = new HintCollection(); + this.hintsToShow = new Array(); this.listenTo(this.collection,'loaded',this.onModelLoaded); this.hideHints(); + var self = this; + Backbone.on('navigatedToPage', function(nav){ + self.selectHints(nav) + }); }, isVisible: function() { @@ -34,19 +39,38 @@ function($, render:function() { if (this.isVisible()) { this.$el.hide(350); - } else { + } else if (this.hintsToShow.length > 0) { this.$el.show(350); } this.toggleLabel() - if (this.collection.length > 0) { + if (this.hintsToShow.length > 0) { this.hideShowPrevNextButtons(); } this.displayHint(this.curHint); }, + /** + * Select the hints, we get '/WebGoat/HttpBasics/attack1' in the json (nav) we need to select all the hints + * from the model where the assignment name is contained in the assignmentPath. We do this not to mess + * with contextRoots etc and try to select the name from the url. + * + * @todo we can of course try to add the assigment name to the html form as attribute. + * + * @param nav the json structure for navigating + */ + selectHints: function(nav) { + this.curHint = 0; + var assignmentPath = nav['assignmentPath']; + if (assignmentPath != null) { + this.hintsToShow = this.collection.getHintsForAssignment(assignmentPath); + } else { + this.hintsToShow = new Array(); + } + }, + onModelLoaded: function() { this.trigger('hints:loaded',{'helpElement':'hints','value':true}) }, @@ -58,7 +82,7 @@ function($, }, showNextHint: function() { - this.curHint = (this.curHint < this.collection.length -1) ? this.curHint+1 : this.curHint; + this.curHint = (this.curHint < this.hintsToShow.length -1) ? this.curHint+1 : this.curHint; this.hideShowPrevNextButtons(); this.displayHint(this.curHint); }, @@ -70,11 +94,15 @@ function($, }, displayHint: function(curHint) { - this.$el.find('#lesson-hint-content').html(this.collection.models[curHint].get('hint')); + if(this.hintsToShow.length == 0) { + this.hideHints(); + } else { + this.$el.find('#lesson-hint-content').html(polyglot.t(this.hintsToShow[curHint].get('hint'))); + } }, hideShowPrevNextButtons: function() { - if (this.curHint === this.collection.length -1) { + if (this.curHint === this.hintsToShow.length -1) { this.$el.find('#show-next-hint').css('visibility','hidden'); } else { this.$el.find('#show-next-hint').css('visibility','visible'); diff --git a/webgoat-container/src/main/resources/static/js/goatApp/view/LessonContentView.js b/webgoat-container/src/main/resources/static/js/goatApp/view/LessonContentView.js index 9e03341b7..7f0ce6794 100644 --- a/webgoat-container/src/main/resources/static/js/goatApp/view/LessonContentView.js +++ b/webgoat-container/src/main/resources/static/js/goatApp/view/LessonContentView.js @@ -189,7 +189,7 @@ define(['jquery', if (this.currentPage < this.numPages -1) { this.currentPage++; window.location.href = this.model.get('lessonUrl') + '/' + this.currentPage; - //this.showCurContentPage(true); + //this.showCurContentPage(true);Con } if (this.currentPage > 0) { @@ -225,10 +225,21 @@ define(['jquery', this.$el.find(this.$contentPages[this.currentPage]).show(); }, + findAssigmentEndpointOnPage: function(pageNumber) { + var contentPage = this.$contentPages[this.currentPage]; + var form = $('form.attack-form', contentPage); + var action = form.attr('action') + if (action !== undefined) { + return action; + } + }, + navToPage: function (pageNum) { this.setCurrentPage(pageNum);//provides validation this.showCurContentPage(this.currentPage); this.hideShowNavButtons(); + var assignmentPath = this.findAssigmentEndpointOnPage(pageNum); + Backbone.trigger('navigatedToPage',{'pageNumber':pageNum, 'assignmentPath' : assignmentPath}); }, hideShowNavButtons: function () { diff --git a/webgoat-container/src/main/resources/static/js/goatApp/view/MenuButtonView.js b/webgoat-container/src/main/resources/static/js/goatApp/view/MenuButtonView.js index b82e62b89..ee6df6ead 100644 --- a/webgoat-container/src/main/resources/static/js/goatApp/view/MenuButtonView.js +++ b/webgoat-container/src/main/resources/static/js/goatApp/view/MenuButtonView.js @@ -7,13 +7,13 @@ function($, _, Backbone) { return Backbone.View.extend({ - el:'#toggle-menu', //Check this, + el:'#toggle-menu', - initialize: function() { - this.$el.on('click',this.toggleMenu); - }, - - toggleMenu: function() { + events: { + "click": "toggleMenu" + }, + + toggleMenu: function(e) { //left if (!$('.sidebarRight').hasClass('.sidebar-toggle-right')) { $('.sidebarRight').removeClass('sidebar-toggle-right'); @@ -21,7 +21,7 @@ function($, } $('.sidebar').toggleClass('sidebar-toggle'); $('.main-content-wrapper').toggleClass('main-content-toggle-left'); - //e.stopPropagation(); + e.stopImmediatePropagation(); } }); }); \ No newline at end of file diff --git a/webgoat-container/src/main/resources/static/js/goatApp/view/MenuView.js b/webgoat-container/src/main/resources/static/js/goatApp/view/MenuView.js index 005402ab4..3dd2322e9 100644 --- a/webgoat-container/src/main/resources/static/js/goatApp/view/MenuView.js +++ b/webgoat-container/src/main/resources/static/js/goatApp/view/MenuView.js @@ -60,7 +60,7 @@ define(['jquery', var categoryLessonList = $('
    ',{class:'slideDown lessonsAndStages',id:catId}); //keepOpen for (var j=0; j < lessons.length;j++) { var lessonItem = $('
  • ',{class:'lesson'}); - var lessonName = lessons[j].name; + var lessonName = polyglot.t(lessons[j].name); var lessonId = catId + '-' + GoatUtils.makeId(lessonName); if (this.curLessonLinkId === lessonId) { lessonItem.addClass('selected'); diff --git a/webgoat-container/src/main/resources/static/js/libs/polyglot.min.js b/webgoat-container/src/main/resources/static/js/libs/polyglot.min.js new file mode 100644 index 000000000..30a393b63 --- /dev/null +++ b/webgoat-container/src/main/resources/static/js/libs/polyglot.min.js @@ -0,0 +1,17 @@ +// (c) 2012 Airbnb, Inc. +// +// polyglot.js may be freely distributed under the terms of the BSD +// license. For all licensing information, details, and documention: +// http://airbnb.github.com/polyglot.js +// +// +// Polyglot.js is an I18n helper library written in JavaScript, made to +// work both in the browser and in Node. It provides a simple solution for +// interpolation and pluralization, based off of Airbnb's +// experience adding I18n functionality to its Backbone.js and Node apps. +// +// Polylglot is agnostic to your translation backend. It doesn't perform any +// translation; it simply gives you a way to manage translated phrases from +// your client- or server-side JavaScript application. +// +(function(e,t){typeof define=="function"&&define.amd?define([],function(){return t(e)}):typeof exports=="object"?module.exports=t(e):e.Polyglot=t(e)})(this,function(e){"use strict";function t(e){e=e||{},this.phrases={},this.extend(e.phrases||{}),this.currentLocale=e.locale||"en",this.allowMissing=!!e.allowMissing,this.warn=e.warn||c}function s(e){var t,n,r,i={};for(t in e)if(e.hasOwnProperty(t)){n=e[t];for(r in n)i[n[r]]=t}return i}function o(e){var t=/^\s+|\s+$/g;return e.replace(t,"")}function u(e,t,r){var i,s,u;return r!=null&&e?(s=e.split(n),u=s[f(t,r)]||s[0],i=o(u)):i=e,i}function a(e){var t=s(i);return t[e]||t.en}function f(e,t){return r[a(e)](t)}function l(e,t){for(var n in t)n!=="_"&&t.hasOwnProperty(n)&&(e=e.replace(new RegExp("%\\{"+n+"\\}","g"),t[n]));return e}function c(t){e.console&&e.console.warn&&e.console.warn("WARNING: "+t)}function h(e){var t={};for(var n in e)t[n]=e[n];return t}t.VERSION="0.4.3",t.prototype.locale=function(e){return e&&(this.currentLocale=e),this.currentLocale},t.prototype.extend=function(e,t){var n;for(var r in e)e.hasOwnProperty(r)&&(n=e[r],t&&(r=t+"."+r),typeof n=="object"?this.extend(n,r):this.phrases[r]=n)},t.prototype.clear=function(){this.phrases={}},t.prototype.replace=function(e){this.clear(),this.extend(e)},t.prototype.t=function(e,t){var n,r;return t=t==null?{}:t,typeof t=="number"&&(t={smart_count:t}),typeof this.phrases[e]=="string"?n=this.phrases[e]:typeof t._=="string"?n=t._:this.allowMissing?n=e:(this.warn('Missing translation for key: "'+e+'"'),r=e),typeof n=="string"&&(t=h(t),r=u(n,this.currentLocale,t.smart_count),r=l(r,t)),r},t.prototype.has=function(e){return e in this.phrases};var n="||||",r={chinese:function(e){return 0},german:function(e){return e!==1?1:0},french:function(e){return e>1?1:0},russian:function(e){return e%10===1&&e%100!==11?0:e%10>=2&&e%10<=4&&(e%100<10||e%100>=20)?1:2},czech:function(e){return e===1?0:e>=2&&e<=4?1:2},polish:function(e){return e===1?0:e%10>=2&&e%10<=4&&(e%100<10||e%100>=20)?1:2},icelandic:function(e){return e%10!==1||e%100===11?1:0}},i={chinese:["fa","id","ja","ko","lo","ms","th","tr","zh"],german:["da","de","en","es","fi","el","he","hu","it","nl","no","pt","sv"],french:["fr","tl","pt-br"],russian:["hr","ru"],czech:["cs"],polish:["pl"],icelandic:["is"]};return t}); \ No newline at end of file diff --git a/webgoat-container/src/main/resources/static/js/main.js b/webgoat-container/src/main/resources/static/js/main.js index d1507f2a4..b64e0e0eb 100644 --- a/webgoat-container/src/main/resources/static/js/main.js +++ b/webgoat-container/src/main/resources/static/js/main.js @@ -18,6 +18,7 @@ require.config({ backbone: 'libs/backbone-min', text: 'libs/text', templates: 'goatApp/templates', + polyglot: 'libs/polyglot.min' }, shim: { underscore: { diff --git a/webgoat-container/src/test/java/org/owasp/webgoat/service/HintServiceTest.java b/webgoat-container/src/test/java/org/owasp/webgoat/service/HintServiceTest.java new file mode 100644 index 000000000..d57fa2a56 --- /dev/null +++ b/webgoat-container/src/test/java/org/owasp/webgoat/service/HintServiceTest.java @@ -0,0 +1,67 @@ +package org.owasp.webgoat.service; + +import com.beust.jcommander.internal.Lists; +import org.hamcrest.CoreMatchers; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; +import org.owasp.webgoat.i18n.LabelManager; +import org.owasp.webgoat.lessons.AbstractLesson; +import org.owasp.webgoat.lessons.Assignment; +import org.owasp.webgoat.session.WebSession; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; + +import static org.junit.Assert.*; +import static org.mockito.AdditionalAnswers.returnsFirstArg; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.when; +import static org.owasp.webgoat.service.HintService.URL_HINTS_MVC; +import static org.owasp.webgoat.service.LabelService.URL_LABELS_MVC; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup; + +@RunWith(MockitoJUnitRunner.class) +public class HintServiceTest { + + private MockMvc mockMvc; + @Mock + private WebSession websession; + @Mock + private AbstractLesson lesson; + + @Before + public void setup() { + this.mockMvc = standaloneSetup(new HintService(websession)).build(); + } + + @Test + public void onlyHintsOnLesson() throws Exception { + when(lesson.getName()).thenReturn("Test lesson"); + when(lesson.getHints()).thenReturn(Lists.newArrayList("hint 1", "hint 2")); + when(websession.getCurrentLesson()).thenReturn(lesson); + mockMvc.perform(MockMvcRequestBuilders.get(URL_HINTS_MVC)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$[0].hint", CoreMatchers.is("hint 1"))) + .andExpect(jsonPath("$[0].lesson", CoreMatchers.is("Test lesson"))); + } + + @Test + public void hintsPerAssignment() throws Exception { + when(lesson.getName()).thenReturn("Test lesson"); + Assignment assignment = Mockito.mock(Assignment.class); + when(assignment.getPath()).thenReturn("/HttpBasics/attack1"); + when(assignment.getHints()).thenReturn(Lists.newArrayList("hint 1", "hint 2")); + when(lesson.getAssignments()).thenReturn(Lists.newArrayList(assignment)); + when(websession.getCurrentLesson()).thenReturn(lesson); + mockMvc.perform(MockMvcRequestBuilders.get(URL_HINTS_MVC)) + .andExpect(status().isOk()).andDo(print()) + .andExpect(jsonPath("$[0].hint", CoreMatchers.is("hint 1"))) + .andExpect(jsonPath("$[0].assignmentPath", CoreMatchers.is("/HttpBasics/attack1"))); + } +} \ No newline at end of file diff --git a/webgoat-lessons/client-side-filtering/src/main/java/org/owasp/webgoat/plugin/Attack.java b/webgoat-lessons/client-side-filtering/src/main/java/org/owasp/webgoat/plugin/Attack.java index 9bebc7d7f..db0e73bb6 100644 --- a/webgoat-lessons/client-side-filtering/src/main/java/org/owasp/webgoat/plugin/Attack.java +++ b/webgoat-lessons/client-side-filtering/src/main/java/org/owasp/webgoat/plugin/Attack.java @@ -1,6 +1,8 @@ package org.owasp.webgoat.plugin; import org.owasp.webgoat.endpoints.AssignmentEndpoint; +import org.owasp.webgoat.endpoints.AssignmentHints; +import org.owasp.webgoat.endpoints.AssignmentPath; import org.owasp.webgoat.lessons.AttackResult; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -39,7 +41,7 @@ import java.io.IOException; * @version $Id: $Id * @since August 11, 2016 */ -@Path("/clientSideFiltering/attack1") +@AssignmentPath("/clientSideFiltering/attack1") public class Attack extends AssignmentEndpoint { @RequestMapping(method = RequestMethod.POST) diff --git a/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson1.java b/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson1.java index 47cbf78c3..5da607d10 100644 --- a/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson1.java +++ b/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson1.java @@ -7,6 +7,7 @@ import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Path; import org.owasp.webgoat.endpoints.AssignmentEndpoint; +import org.owasp.webgoat.endpoints.AssignmentPath; import org.owasp.webgoat.lessons.AttackResult; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -45,7 +46,7 @@ import org.springframework.web.bind.annotation.ResponseBody; * @author Bruce Mayhew WebGoat * @created October 28, 2003 */ -@Path("/CrossSiteScripting/attack1") +@AssignmentPath("/CrossSiteScripting/attack1") public class CrossSiteScriptingLesson1 extends AssignmentEndpoint { @RequestMapping(method = RequestMethod.POST) diff --git a/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson5a.java b/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson5a.java index 7ee473879..2d9e21f64 100644 --- a/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson5a.java +++ b/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson5a.java @@ -7,6 +7,7 @@ import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Path; import org.owasp.webgoat.endpoints.AssignmentEndpoint; +import org.owasp.webgoat.endpoints.AssignmentPath; import org.owasp.webgoat.lessons.AttackResult; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -45,7 +46,7 @@ import org.springframework.web.bind.annotation.ResponseBody; * @author Bruce Mayhew WebGoat * @created October 28, 2003 */ -@Path("/CrossSiteScripting/attack5a") +@AssignmentPath("/CrossSiteScripting/attack5a") public class CrossSiteScriptingLesson5a extends AssignmentEndpoint { @RequestMapping(method = RequestMethod.POST) diff --git a/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson5b.java b/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson5b.java index b2c42c261..63a763fb8 100644 --- a/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson5b.java +++ b/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson5b.java @@ -13,6 +13,7 @@ import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Path; import org.owasp.webgoat.endpoints.AssignmentEndpoint; +import org.owasp.webgoat.endpoints.AssignmentPath; import org.owasp.webgoat.lessons.AttackResult; import org.owasp.webgoat.session.DatabaseUtilities; import org.springframework.web.bind.annotation.RequestMapping; @@ -52,7 +53,7 @@ import org.springframework.web.bind.annotation.ResponseBody; * @author Bruce Mayhew WebGoat * @created October 28, 2003 */ -@Path("/CrossSiteScripting/attack5b") +@AssignmentPath("/CrossSiteScripting/attack5b") public class CrossSiteScriptingLesson5b extends AssignmentEndpoint { @RequestMapping(method = RequestMethod.POST) diff --git a/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson6a.java b/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson6a.java index 45e736d67..136495158 100644 --- a/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson6a.java +++ b/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson6a.java @@ -12,6 +12,7 @@ import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Path; import org.owasp.webgoat.endpoints.AssignmentEndpoint; +import org.owasp.webgoat.endpoints.AssignmentPath; import org.owasp.webgoat.lessons.AttackResult; import org.owasp.webgoat.session.DatabaseUtilities; import org.springframework.web.bind.annotation.RequestMapping; @@ -51,7 +52,7 @@ import org.springframework.web.bind.annotation.ResponseBody; * @author Bruce Mayhew WebGoat * @created October 28, 2003 */ -@Path("/CrossSiteScripting/attack6a") +@AssignmentPath("/CrossSiteScripting/attack6a") public class CrossSiteScriptingLesson6a extends AssignmentEndpoint { @RequestMapping(method = RequestMethod.POST) diff --git a/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson6b.java b/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson6b.java index f83921717..251eb8c4f 100644 --- a/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson6b.java +++ b/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/CrossSiteScriptingLesson6b.java @@ -11,6 +11,7 @@ import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Path; import org.owasp.webgoat.endpoints.AssignmentEndpoint; +import org.owasp.webgoat.endpoints.AssignmentPath; import org.owasp.webgoat.lessons.AttackResult; import org.owasp.webgoat.session.DatabaseUtilities; import org.springframework.web.bind.annotation.RequestMapping; @@ -50,7 +51,7 @@ import org.springframework.web.bind.annotation.ResponseBody; * @author Bruce Mayhew WebGoat * @created October 28, 2003 */ -@Path("/CrossSiteScripting/attack6b") +@AssignmentPath("/CrossSiteScripting/attack6b") public class CrossSiteScriptingLesson6b extends AssignmentEndpoint { @RequestMapping(method = RequestMethod.POST) diff --git a/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/DOMCrossSiteScripting.java b/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/DOMCrossSiteScripting.java index 8a6eab92d..6c030865b 100644 --- a/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/DOMCrossSiteScripting.java +++ b/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/DOMCrossSiteScripting.java @@ -1,6 +1,7 @@ package org.owasp.webgoat.plugin; import org.owasp.webgoat.endpoints.AssignmentEndpoint; +import org.owasp.webgoat.endpoints.AssignmentPath; import org.owasp.webgoat.lessons.AttackResult; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -14,7 +15,7 @@ import java.io.IOException; /** * Created by jason on 11/23/16. */ -@Path("/CrossSiteScripting/dom-xss") +@AssignmentPath("/CrossSiteScripting/dom-xss") public class DOMCrossSiteScripting extends AssignmentEndpoint { @RequestMapping(method = RequestMethod.POST) public @ResponseBody diff --git a/webgoat-lessons/http-basics/src/main/java/org/owasp/webgoat/plugin/HttpBasics.java b/webgoat-lessons/http-basics/src/main/java/org/owasp/webgoat/plugin/HttpBasics.java index 9e36727d1..b41e9d005 100644 --- a/webgoat-lessons/http-basics/src/main/java/org/owasp/webgoat/plugin/HttpBasics.java +++ b/webgoat-lessons/http-basics/src/main/java/org/owasp/webgoat/plugin/HttpBasics.java @@ -43,12 +43,7 @@ public class HttpBasics extends NewLesson { @Override public List getHints() { - return Lists.newArrayList("Type in your name and press 'go'", - "Turn on Show Parameters or other features", - "Try to intercept the request with OWASP ZAP", - "Press the Show Lesson Plan button to view a lesson summary", - "Press the Show Solution button to view a lesson solution", - "Use OWASP ZAP to intercept the request and see the type of HTTP command"); + return Lists.newArrayList(); } @Override @@ -58,7 +53,7 @@ public class HttpBasics extends NewLesson { @Override public String getTitle() { - return "HTTP Basics"; + return "http-basics.title"; } @Override diff --git a/webgoat-lessons/http-basics/src/main/java/org/owasp/webgoat/plugin/HttpBasicsLesson.java b/webgoat-lessons/http-basics/src/main/java/org/owasp/webgoat/plugin/HttpBasicsLesson.java index 5781b8745..2561fe4bd 100644 --- a/webgoat-lessons/http-basics/src/main/java/org/owasp/webgoat/plugin/HttpBasicsLesson.java +++ b/webgoat-lessons/http-basics/src/main/java/org/owasp/webgoat/plugin/HttpBasicsLesson.java @@ -1,6 +1,9 @@ package org.owasp.webgoat.plugin; +import com.beust.jcommander.internal.Lists; import org.owasp.webgoat.endpoints.AssignmentEndpoint; +import org.owasp.webgoat.endpoints.AssignmentHints; +import org.owasp.webgoat.endpoints.AssignmentPath; import org.owasp.webgoat.lessons.AttackResult; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -10,6 +13,7 @@ import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Path; import java.io.IOException; +import java.util.List; /** * ************************************************************************************************* @@ -44,15 +48,16 @@ import java.io.IOException; * @author Bruce Mayhew WebGoat * @created October 28, 2003 */ -@Path("/HttpBasics/attack1") +@AssignmentPath("/HttpBasics/attack1") +@AssignmentHints({"http-basics.hints.http_basics_lesson.1"}) public class HttpBasicsLesson extends AssignmentEndpoint { @RequestMapping(method = RequestMethod.POST) - public @ResponseBody AttackResult completed(@RequestParam String person, HttpServletRequest request) throws IOException { + public @ResponseBody AttackResult completed(@RequestParam String person) throws IOException { if (!person.toString().equals("")) { - return trackProgress(AttackResult.success("The server has reversed your name: " + new StringBuffer(person).reverse().toString())); + return trackProgress(AttackResult.success(getLabelProvider().get("http-basics.reversed", new StringBuffer(person).reverse().toString()))); } else { - return trackProgress(AttackResult.failed("You are close, try again")); + return trackProgress(AttackResult.failed(getLabelProvider().get("http-basics.close"))); } } } diff --git a/webgoat-lessons/http-basics/src/main/java/org/owasp/webgoat/plugin/HttpBasicsQuiz.java b/webgoat-lessons/http-basics/src/main/java/org/owasp/webgoat/plugin/HttpBasicsQuiz.java index 5c72286f8..ed1de9152 100644 --- a/webgoat-lessons/http-basics/src/main/java/org/owasp/webgoat/plugin/HttpBasicsQuiz.java +++ b/webgoat-lessons/http-basics/src/main/java/org/owasp/webgoat/plugin/HttpBasicsQuiz.java @@ -1,6 +1,9 @@ package org.owasp.webgoat.plugin; +import com.beust.jcommander.internal.Lists; import org.owasp.webgoat.endpoints.AssignmentEndpoint; +import org.owasp.webgoat.endpoints.AssignmentHints; +import org.owasp.webgoat.endpoints.AssignmentPath; import org.owasp.webgoat.lessons.AttackResult; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -10,6 +13,7 @@ import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Path; import java.io.IOException; +import java.util.List; /** * ************************************************************************************************* @@ -44,7 +48,8 @@ import java.io.IOException; * @author Bruce Mayhew WebGoat * @created October 28, 2003 */ -@Path("/HttpBasics/attack2") +@AssignmentPath("/HttpBasics/attack2") +@AssignmentHints({"http-basics.hints.http_basic_quiz.1", "http-basics.hints.http_basic_quiz.2"}) public class HttpBasicsQuiz extends AssignmentEndpoint { @RequestMapping(method = RequestMethod.POST) @@ -54,12 +59,12 @@ public class HttpBasicsQuiz extends AssignmentEndpoint { } else { StringBuffer message = new StringBuffer(); if (!"POST".equals(answer.toUpperCase())) { - message.append("The HTTP Command is incorrect. "); + message.append(getLabelProvider().get("http-basics.incorrect")); } if (!magic_answer.equals(magic_num)){ - message.append("The magic number is incorrect. "); + message.append(getLabelProvider().get("http-basics.magic")); } - return trackProgress(AttackResult.failed("You are close, try again. " + message.toString())); + return trackProgress(AttackResult.failed(getLabelProvider().get("http-basics.close", message.toString()))); } } } diff --git a/webgoat-lessons/http-basics/src/main/resources/plugin/i18n/WebGoatLabels.properties b/webgoat-lessons/http-basics/src/main/resources/plugin/i18n/WebGoatLabels.properties index 9d46e3d6e..673e9e318 100644 --- a/webgoat-lessons/http-basics/src/main/resources/plugin/i18n/WebGoatLabels.properties +++ b/webgoat-lessons/http-basics/src/main/resources/plugin/i18n/WebGoatLabels.properties @@ -1,2 +1,15 @@ -EnterYourName=Enter your Name -Go!=Go! +http-basics.EnterYourName=Enter your Name +http-basics.Go!=Go! +http-basics.title=HTTP Basics + + +http-basics.hints.http_basics_lesson.1=Type in your name and press 'go' +http-basics.hints.http_basic_quiz.1=Turn on Show Parameters or other features +http-basics.hints.http_basic_quiz.2=Try to intercept the request with OWASP ZAP + + +http-basics.reversed=The server has reversed your name: {0} + +http-basics.close=You are close, try again: {0} +http-basics.incorrect=the HTTP Command is incorrect. +http-basics.magic=the magic number is incorrect. \ No newline at end of file diff --git a/webgoat-lessons/http-basics/src/main/resources/plugin/i18n/WebGoatLabels_nl.properties b/webgoat-lessons/http-basics/src/main/resources/plugin/i18n/WebGoatLabels_nl.properties new file mode 100644 index 000000000..509aaaf7e --- /dev/null +++ b/webgoat-lessons/http-basics/src/main/resources/plugin/i18n/WebGoatLabels_nl.properties @@ -0,0 +1,16 @@ +http-basics.EnterYourName=Voer je naam in +http-basics.Go!=Go! +http-basics.title=HTTP Basics + + + +http-basics.hints.http_basics_lesson.1=Type je naam in en druk op 'Go' +http-basics.hints.http_basic_quiz.1=Schakel 'Toon paramaters of andere eigenschappen' in +http-basics.hints.http_basic_quiz.2=Probeer het verzoek te onderscheppen met OWASP ZAP + + +http-basics.reversed=De server heeft je naam omgedraaid: {0} + +http-basics.close=Je bent er bijna, probeer nog eens: {0} +http-basics.incorrect=het HTTP commando is niet correct. +http-basics.magic=het magische getal is niet correct. \ No newline at end of file diff --git a/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDOR.java b/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDOR.java index 339e4a083..6059ed54b 100644 --- a/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDOR.java +++ b/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDOR.java @@ -44,7 +44,7 @@ public class IDOR extends NewLesson { @Override public List getHints() { - return Lists.newArrayList("log in first"); + return Lists.newArrayList(); } @Override @@ -54,7 +54,7 @@ public class IDOR extends NewLesson { @Override public String getTitle() { - return "Insecure Direct Object References"; + return "idor.title"; } @Override @@ -62,6 +62,4 @@ public class IDOR extends NewLesson { return "IDOR"; } - - } diff --git a/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDORDiffAttributes.java b/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDORDiffAttributes.java index 0dbefd5c0..d925c90fb 100644 --- a/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDORDiffAttributes.java +++ b/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDORDiffAttributes.java @@ -1,6 +1,7 @@ package org.owasp.webgoat.plugin; import org.owasp.webgoat.endpoints.AssignmentEndpoint; +import org.owasp.webgoat.endpoints.AssignmentPath; import org.owasp.webgoat.lessons.AttackResult; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -41,7 +42,7 @@ import java.io.IOException; * @since January 3, 2017 */ -@Path("IDOR/diff-attributes") +@AssignmentPath("IDOR/diff-attributes") public class IDORDiffAttributes extends AssignmentEndpoint { @RequestMapping(method = RequestMethod.POST) diff --git a/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDOREditOtherProfiile.java b/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDOREditOtherProfiile.java index c2a509f45..9b48499f7 100644 --- a/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDOREditOtherProfiile.java +++ b/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDOREditOtherProfiile.java @@ -1,6 +1,7 @@ package org.owasp.webgoat.plugin; import org.owasp.webgoat.endpoints.AssignmentEndpoint; +import org.owasp.webgoat.endpoints.AssignmentPath; import org.owasp.webgoat.lessons.AttackResult; import org.owasp.webgoat.session.UserSessionData; import org.springframework.beans.factory.annotation.Autowired; @@ -42,7 +43,7 @@ import java.util.Map; * @since January 3, 2017 */ -@Path("IDOR/profile/{userId}") +@AssignmentPath("IDOR/profile/{userId}") public class IDOREditOtherProfiile extends AssignmentEndpoint { @Autowired diff --git a/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDORLogin.java b/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDORLogin.java index d0994ad8e..edb96fe5b 100644 --- a/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDORLogin.java +++ b/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDORLogin.java @@ -1,6 +1,8 @@ package org.owasp.webgoat.plugin; import org.owasp.webgoat.endpoints.AssignmentEndpoint; +import org.owasp.webgoat.endpoints.AssignmentHints; +import org.owasp.webgoat.endpoints.AssignmentPath; import org.owasp.webgoat.lessons.AttackResult; import org.owasp.webgoat.session.UserSessionData; @@ -42,29 +44,32 @@ import java.util.Map; * @since January 3, 2017 */ -@Path("/IDOR/login") +@AssignmentPath("/IDOR/login") +@AssignmentHints({"idor.hints.idor_login"}) public class IDORLogin extends AssignmentEndpoint { - private Map> idorUserInfo = new HashMap<>(); + private Map> idorUserInfo = new HashMap<>(); public void initIDORInfo() { - idorUserInfo.put("tom",new HashMap()); - idorUserInfo.get("tom").put("password","cat"); - idorUserInfo.get("tom").put("id","2342384"); - idorUserInfo.get("tom").put("color","yellow"); - idorUserInfo.get("tom").put("size","small"); + idorUserInfo.put("tom", new HashMap()); + idorUserInfo.get("tom").put("password", "cat"); + idorUserInfo.get("tom").put("id", "2342384"); + idorUserInfo.get("tom").put("color", "yellow"); + idorUserInfo.get("tom").put("size", "small"); - idorUserInfo.put("bill",new HashMap()); - idorUserInfo.get("bill").put("password","buffalo"); - idorUserInfo.get("bill").put("id","2342388"); - idorUserInfo.get("bill").put("color","brown"); - idorUserInfo.get("bill").put("size","large"); + idorUserInfo.put("bill", new HashMap()); + idorUserInfo.get("bill").put("password", "buffalo"); + idorUserInfo.get("bill").put("id", "2342388"); + idorUserInfo.get("bill").put("color", "brown"); + idorUserInfo.get("bill").put("size", "large"); } @PostMapping - public @ResponseBody AttackResult completed(@RequestParam String username, @RequestParam String password) { + public + @ResponseBody + AttackResult completed(@RequestParam String username, @RequestParam String password) { initIDORInfo(); UserSessionData userSessionData = getUserSessionData(); diff --git a/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDORViewOtherProfile.java b/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDORViewOtherProfile.java index 8e0f469e0..1ce215c5a 100644 --- a/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDORViewOtherProfile.java +++ b/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDORViewOtherProfile.java @@ -2,6 +2,7 @@ package org.owasp.webgoat.plugin; import org.owasp.webgoat.endpoints.AssignmentEndpoint; +import org.owasp.webgoat.endpoints.AssignmentPath; import org.owasp.webgoat.endpoints.Endpoint; import org.owasp.webgoat.lessons.AttackResult; import org.owasp.webgoat.session.UserSessionData; @@ -49,7 +50,7 @@ import java.util.Map; * @since January 3, 2017 */ -@Path("IDOR/profile/{userId}") +@AssignmentPath("IDOR/profile/{userId}") public class IDORViewOtherProfile extends AssignmentEndpoint{ @Autowired diff --git a/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDORViewOwnProfileAltUrl.java b/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDORViewOwnProfileAltUrl.java index 6edeca7c4..a13f47187 100644 --- a/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDORViewOwnProfileAltUrl.java +++ b/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/IDORViewOwnProfileAltUrl.java @@ -2,6 +2,7 @@ package org.owasp.webgoat.plugin; import org.owasp.webgoat.endpoints.AssignmentEndpoint; +import org.owasp.webgoat.endpoints.AssignmentPath; import org.owasp.webgoat.endpoints.Endpoint; import org.owasp.webgoat.lessons.AttackResult; import org.owasp.webgoat.session.UserSessionData; @@ -46,7 +47,7 @@ import java.util.Map; * @since January 3, 2017 */ -@Path("IDOR/profile/alt-path") +@AssignmentPath("IDOR/profile/alt-path") public class IDORViewOwnProfileAltUrl extends AssignmentEndpoint{ @Autowired diff --git a/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/ViewOtherUserProfile.java b/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/ViewOtherUserProfile.java index 447e885eb..7e35fc4f3 100644 --- a/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/ViewOtherUserProfile.java +++ b/webgoat-lessons/idor/src/main/java/org/owasp/webgoat/plugin/ViewOtherUserProfile.java @@ -2,6 +2,7 @@ package org.owasp.webgoat.plugin; import com.google.common.collect.Lists; import org.owasp.webgoat.endpoints.AssignmentEndpoint; +import org.owasp.webgoat.endpoints.AssignmentPath; import org.owasp.webgoat.lessons.AttackResult; import org.owasp.webgoat.session.UserSessionData; import org.springframework.beans.factory.annotation.Autowired; @@ -22,7 +23,7 @@ import java.util.Map; * Created by jason on 1/5/17. */ -@Path("/IDOR/viewprofile/{id}") +@AssignmentPath("/IDOR/viewprofile/{id}") public class ViewOtherUserProfile extends AssignmentEndpoint { private String color; diff --git a/webgoat-lessons/idor/src/main/resources/plugin/i18n/WebGoatLabels.properties b/webgoat-lessons/idor/src/main/resources/plugin/i18n/WebGoatLabels.properties new file mode 100644 index 000000000..24b49aea3 --- /dev/null +++ b/webgoat-lessons/idor/src/main/resources/plugin/i18n/WebGoatLabels.properties @@ -0,0 +1,3 @@ +idor.title=Insecure Direct Object References + +idor.hints.idor_login=Log in first diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson5a.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson5a.java index 8024548f0..b39c16567 100644 --- a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson5a.java +++ b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson5a.java @@ -12,6 +12,7 @@ import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Path; import org.owasp.webgoat.endpoints.AssignmentEndpoint; +import org.owasp.webgoat.endpoints.AssignmentPath; import org.owasp.webgoat.lessons.AttackResult; import org.owasp.webgoat.session.DatabaseUtilities; import org.springframework.web.bind.annotation.RequestMapping; @@ -51,7 +52,7 @@ import org.springframework.web.bind.annotation.ResponseBody; * @author Bruce Mayhew WebGoat * @created October 28, 2003 */ -@Path("/SqlInjection/attack5a") +@AssignmentPath("/SqlInjection/attack5a") public class SqlInjectionLesson5a extends AssignmentEndpoint { @RequestMapping(method = RequestMethod.POST) diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson5b.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson5b.java index 0101472fb..ecc5ae16e 100644 --- a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson5b.java +++ b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson5b.java @@ -13,6 +13,7 @@ import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Path; import org.owasp.webgoat.endpoints.AssignmentEndpoint; +import org.owasp.webgoat.endpoints.AssignmentPath; import org.owasp.webgoat.lessons.AttackResult; import org.owasp.webgoat.session.DatabaseUtilities; import org.springframework.web.bind.annotation.RequestMapping; @@ -52,7 +53,7 @@ import org.springframework.web.bind.annotation.ResponseBody; * @author Bruce Mayhew WebGoat * @created October 28, 2003 */ -@Path("/SqlInjection/attack5b") +@AssignmentPath("/SqlInjection/attack5b") public class SqlInjectionLesson5b extends AssignmentEndpoint { @RequestMapping(method = RequestMethod.POST) diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson6a.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson6a.java index d03285714..bacb96201 100644 --- a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson6a.java +++ b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson6a.java @@ -12,6 +12,7 @@ import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Path; import org.owasp.webgoat.endpoints.AssignmentEndpoint; +import org.owasp.webgoat.endpoints.AssignmentPath; import org.owasp.webgoat.lessons.AttackResult; import org.owasp.webgoat.session.DatabaseUtilities; import org.springframework.web.bind.annotation.RequestMapping; @@ -51,7 +52,7 @@ import org.springframework.web.bind.annotation.ResponseBody; * @author Bruce Mayhew WebGoat * @created October 28, 2003 */ -@Path("/SqlInjection/attack6a") +@AssignmentPath("/SqlInjection/attack6a") public class SqlInjectionLesson6a extends AssignmentEndpoint { @RequestMapping(method = RequestMethod.POST) diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson6b.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson6b.java index 1a731c7e4..bd5f7f607 100644 --- a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson6b.java +++ b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/SqlInjectionLesson6b.java @@ -11,6 +11,7 @@ import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Path; import org.owasp.webgoat.endpoints.AssignmentEndpoint; +import org.owasp.webgoat.endpoints.AssignmentPath; import org.owasp.webgoat.lessons.AttackResult; import org.owasp.webgoat.session.DatabaseUtilities; import org.springframework.web.bind.annotation.RequestMapping; @@ -50,7 +51,7 @@ import org.springframework.web.bind.annotation.ResponseBody; * @author Bruce Mayhew WebGoat * @created October 28, 2003 */ -@Path("/SqlInjection/attack6b") +@AssignmentPath("/SqlInjection/attack6b") public class SqlInjectionLesson6b extends AssignmentEndpoint { @RequestMapping(method = RequestMethod.POST) diff --git a/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/BlindSendFileAssignment.java b/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/BlindSendFileAssignment.java index 8de514d1b..45092502a 100644 --- a/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/BlindSendFileAssignment.java +++ b/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/BlindSendFileAssignment.java @@ -3,6 +3,7 @@ package org.owasp.webgoat.plugin; import com.google.common.base.Joiner; import org.apache.commons.lang.exception.ExceptionUtils; import org.owasp.webgoat.endpoints.AssignmentEndpoint; +import org.owasp.webgoat.endpoints.AssignmentPath; import org.owasp.webgoat.lessons.AttackResult; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.RequestBody; @@ -47,7 +48,7 @@ import static org.owasp.webgoat.plugin.SimpleXXE.parseXml; * @version $Id: $Id * @since November 18, 2016 */ -@Path("XXE/blind") +@AssignmentPath("XXE/blind") public class BlindSendFileAssignment extends AssignmentEndpoint { @RequestMapping(method = RequestMethod.POST, consumes = MediaType.ALL_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) diff --git a/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/ContentTypeAssignment.java b/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/ContentTypeAssignment.java index 45fcb6858..23bb4e6c0 100644 --- a/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/ContentTypeAssignment.java +++ b/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/ContentTypeAssignment.java @@ -2,6 +2,7 @@ package org.owasp.webgoat.plugin; import com.fasterxml.jackson.databind.ObjectMapper; import org.owasp.webgoat.endpoints.AssignmentEndpoint; +import org.owasp.webgoat.endpoints.AssignmentPath; import org.owasp.webgoat.lessons.AttackResult; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.RequestBody; @@ -45,7 +46,7 @@ import static org.owasp.webgoat.plugin.SimpleXXE.parseXml; * @version $Id: $Id * @since November 17, 2016 */ -@Path("XXE/content-type") +@AssignmentPath("XXE/content-type") public class ContentTypeAssignment extends AssignmentEndpoint { @RequestMapping(method = RequestMethod.POST, consumes = MediaType.ALL_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) diff --git a/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/SimpleXXE.java b/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/SimpleXXE.java index 06968eccf..908174412 100644 --- a/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/SimpleXXE.java +++ b/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/SimpleXXE.java @@ -2,6 +2,7 @@ package org.owasp.webgoat.plugin; import org.apache.commons.exec.OS; import org.owasp.webgoat.endpoints.AssignmentEndpoint; +import org.owasp.webgoat.endpoints.AssignmentPath; import org.owasp.webgoat.lessons.AttackResult; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.RequestBody; @@ -45,7 +46,7 @@ import java.io.StringReader; * @version $Id: $Id * @since November 17, 2016 */ -@Path("XXE/simple") +@AssignmentPath("XXE/simple") public class SimpleXXE extends AssignmentEndpoint { private final static String[] DEFAULT_LINUX_DIRECTORIES = {"usr", "opt", "var"};