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