diff --git a/pom.xml b/pom.xml index 3718d9be3..02f8f6df3 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 org.owasp.webgoat WebGoat-Container - jar + war 6.1.0 @@ -38,15 +38,17 @@ org.apache.maven.plugins maven-compiler-plugin - 1.6 - 1.6 + 1.7 + 1.7 ISO-8859-1 org.apache.maven.plugins maven-war-plugin + + true true @@ -59,10 +61,28 @@ + + org.apache.maven.plugins + maven-jar-plugin + + + create-jar + compile + + jar + + + + org.apache.tomcat.maven tomcat7-maven-plugin 2.1 + + http://localhost:8080/manager + /WebGoat + exec + tomcat-run @@ -70,11 +90,6 @@ exec-war-only package - - http://localhost:8080/manager - /WebGoat - exec - diff --git a/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java b/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java index e689f7d1f..8f3ed38e6 100644 --- a/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java +++ b/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java @@ -385,7 +385,7 @@ public abstract class AbstractLesson extends Screen implements Comparable" diff --git a/src/main/java/org/owasp/webgoat/plugins/Plugin.java b/src/main/java/org/owasp/webgoat/plugins/Plugin.java new file mode 100644 index 000000000..77827910f --- /dev/null +++ b/src/main/java/org/owasp/webgoat/plugins/Plugin.java @@ -0,0 +1,146 @@ +package org.owasp.webgoat.plugins; + +import org.owasp.webgoat.lessons.AbstractLesson; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.StringUtils; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.owasp.webgoat.plugins.PluginFileUtils.fileEndsWith; +import static org.owasp.webgoat.plugins.PluginFileUtils.hasParentDirectoryWithName; + +public class Plugin { + + private static final String NAME_LESSON_SOLUTION_DIRECTORY = "lessonSolutions"; + private static final String NAME_LESSON_PLANS_DIRECTORY = "lessonPlans"; + private static final String NAME_LESSON_I18N_DIRECTORY = "i18n"; + private final Logger logger = LoggerFactory.getLogger(Plugin.class); + private final Path pluginDirectory; + + private Class lesson; + private Map solutionLanguageFiles = new HashMap<>(); + private Map lessonPlansLanguageFiles = new HashMap<>(); + private File lessonSourceFile; + + public static class PluginLoadingFailure extends RuntimeException { + + public PluginLoadingFailure(String message) { + super(message); + } + + public PluginLoadingFailure(String message, Exception e) { + super(message, e); + } + } + + public Plugin(Path pluginDirectory) { + this.pluginDirectory = pluginDirectory; + } + + public void loadClasses(Map classes) { + for (Map.Entry clazz : classes.entrySet()) { + loadClass(clazz.getKey(), clazz.getValue()); + } + if (lesson == null) { + throw new PluginLoadingFailure(String + .format("Lesson class not found, following classes were detected in the plugin: %s", + StringUtils.collectionToCommaDelimitedString(classes.keySet()))); + } + } + + private void loadClass(String name, byte[] classFile) { + ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); + PluginClassLoader pluginClassLoader = new PluginClassLoader(contextClassLoader, classFile); + try { + String realClassName = name.replaceFirst("/", "").replaceAll("/", ".").replaceAll(".class", ""); + Class clazz = pluginClassLoader.loadClass(realClassName); + if (AbstractLesson.class.isAssignableFrom(clazz)) { + this.lesson = clazz; + } + } catch (ClassNotFoundException e) { + logger.error("Unable to load class {}", name); + } + } + + public void loadFiles(List files, boolean reload) { + for (Path file : files) { + if (fileEndsWith(file, ".html") && hasParentDirectoryWithName(file, NAME_LESSON_SOLUTION_DIRECTORY)) { + solutionLanguageFiles.put(file.getParent().getFileName().toString(), file.toFile()); + } + if (fileEndsWith(file, ".html") && hasParentDirectoryWithName(file, NAME_LESSON_PLANS_DIRECTORY)) { + lessonPlansLanguageFiles.put(file.getParent().getFileName().toString(), file.toFile()); + } + if (fileEndsWith(file, ".java")) { + lessonSourceFile = file.toFile(); + } + if (fileEndsWith(file, ".properties") && hasParentDirectoryWithName(file, NAME_LESSON_I18N_DIRECTORY)) { + copyProperties(reload, file); + } + } + } + + private void copyProperties(boolean reload, Path file) { + try { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + Files.copy(file, bos); + Path propertiesPath = createPropertiesDirectory(); + ResourceBundleClassLoader.setPropertiesPath(propertiesPath); + if ( reload ) { + Files.write(propertiesPath.resolve(file.getFileName()), bos.toByteArray(), StandardOpenOption.CREATE, StandardOpenOption.APPEND); + } else { + Files.write(propertiesPath.resolve(file.getFileName()), bos.toByteArray(), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); + } + } catch (IOException io) { + throw new PluginLoadingFailure("Property file detected, but unable to copy the properties", io); + } + } + + private Path createPropertiesDirectory() throws IOException { + if (Files.exists(pluginDirectory.resolve(NAME_LESSON_I18N_DIRECTORY))) { + return pluginDirectory.resolve(NAME_LESSON_I18N_DIRECTORY); + } else { + return Files.createDirectory(pluginDirectory.resolve(NAME_LESSON_I18N_DIRECTORY)); + } + } + + public void rewritePaths(Path pluginTarget) { + try { + for (Map.Entry html : solutionLanguageFiles.entrySet()) { + byte[] htmlFileAsBytes = Files.readAllBytes(Paths.get(html.getValue().toURI())); + String htmlFile = new String(htmlFileAsBytes); + htmlFile = htmlFile.replaceAll(this.lesson.getSimpleName() + "_files", pluginTarget.getFileName().toString() + "/lessons/plugin/SqlStringInjection/lessonSolutions/en/" + this.lesson.getSimpleName() + "_files"); + Files.write(Paths.get(html.getValue().toURI()), htmlFile.getBytes(), StandardOpenOption.CREATE, + StandardOpenOption.TRUNCATE_EXISTING); + } + } catch (IOException e) { + throw new PluginLoadingFailure("Unable to rewrite the paths in the solutions", e); + } + } + + + public Class getLesson() { + return lesson; + } + + public Map getLessonSolutions() { + return this.solutionLanguageFiles; + } + + public File getLessonSource() { + return lessonSourceFile; + } + + public Map getLessonPlans() { + return this.lessonPlansLanguageFiles; + } +} diff --git a/src/main/java/org/owasp/webgoat/plugins/PluginBackgroundLoader.java b/src/main/java/org/owasp/webgoat/plugins/PluginBackgroundLoader.java new file mode 100644 index 000000000..e2d59002f --- /dev/null +++ b/src/main/java/org/owasp/webgoat/plugins/PluginBackgroundLoader.java @@ -0,0 +1,28 @@ +package org.owasp.webgoat.plugins; + +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.annotation.WebListener; +import java.nio.file.Paths; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +@WebListener +public class PluginBackgroundLoader implements ServletContextListener { + + private ScheduledExecutorService scheduler; + + @Override + public void contextInitialized(ServletContextEvent event) { + String pluginPath = event.getServletContext().getRealPath("plugin_lessons"); + String targetPath = event.getServletContext().getRealPath("plugin_extracted"); + scheduler = Executors.newSingleThreadScheduledExecutor(); + scheduler.scheduleAtFixedRate(new PluginsLoader(Paths.get(pluginPath), Paths.get(targetPath)), 0, 5, TimeUnit.MINUTES); + } + + @Override + public void contextDestroyed(ServletContextEvent event) { + scheduler.shutdownNow(); + } +} diff --git a/src/main/java/org/owasp/webgoat/plugins/PluginClassLoader.java b/src/main/java/org/owasp/webgoat/plugins/PluginClassLoader.java new file mode 100644 index 000000000..98b101b8b --- /dev/null +++ b/src/main/java/org/owasp/webgoat/plugins/PluginClassLoader.java @@ -0,0 +1,17 @@ +package org.owasp.webgoat.plugins; + +public class PluginClassLoader extends ClassLoader { + + private final byte[] classFile; + + public PluginClassLoader(ClassLoader parent, byte[] classFile) { + super(parent); + this.classFile = classFile; + } + + public Class findClass(String name) { + return defineClass(name, classFile, 0, classFile.length); + } + +} + diff --git a/src/main/java/org/owasp/webgoat/plugins/PluginExtractor.java b/src/main/java/org/owasp/webgoat/plugins/PluginExtractor.java new file mode 100644 index 000000000..a9a2f1043 --- /dev/null +++ b/src/main/java/org/owasp/webgoat/plugins/PluginExtractor.java @@ -0,0 +1,71 @@ +package org.owasp.webgoat.plugins; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.net.URI; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static java.lang.String.format; +import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; +import static org.owasp.webgoat.plugins.PluginFileUtils.createDirsIfNotExists; + +/** + * Extract the wpf file and place them in the system temp directory in the folder webgoat and collect the files + * and classes. + */ +public class PluginExtractor { + + private final Path pluginArchive; + private final Map classes = new HashMap<>(); + private final List files = new ArrayList<>(); + + public PluginExtractor(Path pluginArchive) { + this.pluginArchive = pluginArchive; + } + + public void extract(final Path target) { + try (FileSystem zip = createZipFileSystem()) { + final Path root = zip.getPath("/"); + Files.walkFileTree(root, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + if (file.toString().endsWith(".class")) { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + Files.copy(file, bos); + classes.put(file.toString(), bos.toByteArray()); + } + files.add(Files.copy(file, createDirsIfNotExists(Paths.get(target.toString(), file.toString())), REPLACE_EXISTING)); + return FileVisitResult.CONTINUE; + } + }); + } catch (IOException io) { + new Plugin.PluginLoadingFailure(format("Unable to extract: %s", pluginArchive.getFileName()), io); + } + } + + public Map getClasses() { + return this.classes; + } + + public List getFiles() { + return this.files; + } + + private FileSystem createZipFileSystem() throws IOException { + final URI uri = URI.create("jar:file:" + pluginArchive.toUri().getPath()); + return FileSystems.newFileSystem(uri, new HashMap()); + } + + +} diff --git a/src/main/java/org/owasp/webgoat/plugins/PluginFileUtils.java b/src/main/java/org/owasp/webgoat/plugins/PluginFileUtils.java new file mode 100644 index 000000000..c0390539c --- /dev/null +++ b/src/main/java/org/owasp/webgoat/plugins/PluginFileUtils.java @@ -0,0 +1,31 @@ +package org.owasp.webgoat.plugins; + + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +public class PluginFileUtils { + + public static boolean fileEndsWith(Path p, String s) { + return p.getFileName().toString().endsWith(s); + } + + public static boolean hasParentDirectoryWithName(Path p, String s) { + if (p == null || p.getParent() == null || p.getRoot().equals(p.getParent())) { + return false; + } + if (p.getParent().getFileName().toString().equals(s)) { + return true; + } + return hasParentDirectoryWithName(p.getParent(), s); + } + + public static Path createDirsIfNotExists(Path p) throws IOException { + if ( Files.notExists(p)) { + Files.createDirectories(p); + } + return p; + } + +} diff --git a/src/main/java/org/owasp/webgoat/plugins/PluginsLoader.java b/src/main/java/org/owasp/webgoat/plugins/PluginsLoader.java new file mode 100644 index 000000000..87ffc3669 --- /dev/null +++ b/src/main/java/org/owasp/webgoat/plugins/PluginsLoader.java @@ -0,0 +1,60 @@ +package org.owasp.webgoat.plugins; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.List; + +public class PluginsLoader implements Runnable { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + private final Path pluginSource; + private Path pluginTarget; + + public PluginsLoader(Path pluginSource, Path pluginTarget) { + this.pluginSource = pluginSource; + this.pluginTarget = pluginTarget; + } + + public List loadPlugins(final boolean reload) { + final List plugins = new ArrayList(); + try { + Files.walkFileTree(pluginSource, new SimpleFileVisitor() { + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + try { + PluginFileUtils.createDirsIfNotExists(pluginTarget); + PluginExtractor extractor = new PluginExtractor(file); + extractor.extract(pluginTarget); + Plugin plugin = new Plugin(pluginTarget); + plugin.loadClasses(extractor.getClasses()); + plugin.loadFiles(extractor.getFiles(), reload); + plugin.rewritePaths(pluginTarget); + plugins.add(plugin); + } catch (Plugin.PluginLoadingFailure e) { + logger.error("Unable to load plugin, continue loading others..."); + } + return FileVisitResult.CONTINUE; + } + + }); + } catch (IOException e) { + logger.error("Loading plugins failed", e); + } + return plugins; + } + + + @Override + public void run() { + loadPlugins(true); + } +} diff --git a/src/main/java/org/owasp/webgoat/plugins/ResourceBundleClassLoader.java b/src/main/java/org/owasp/webgoat/plugins/ResourceBundleClassLoader.java new file mode 100644 index 000000000..6f69f7ce1 --- /dev/null +++ b/src/main/java/org/owasp/webgoat/plugins/ResourceBundleClassLoader.java @@ -0,0 +1,33 @@ +package org.owasp.webgoat.plugins; + +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +public class ResourceBundleClassLoader { + + private final static ResourceBundleClassLoader classLoader = new ResourceBundleClassLoader(); + private Path propertiesPath; + + private ResourceBundleClassLoader() { + } + + public static void setPropertiesPath(Path path) { + classLoader.propertiesPath = path; + } + + public static ClassLoader createPropertyFilesClassLoader(ClassLoader parentClassLoader) { + final List urls = new ArrayList<>(); + + try { + urls.add(classLoader.propertiesPath.toUri().toURL()); + } catch (IOException e) { + throw new Plugin.PluginLoadingFailure("Unable to load the properties for the classloader", e); + } + return new URLClassLoader(urls.toArray(new URL[urls.size()]), Thread.currentThread().getContextClassLoader()); + } + +} \ No newline at end of file diff --git a/src/main/java/org/owasp/webgoat/session/Course.java b/src/main/java/org/owasp/webgoat/session/Course.java index 9245db83c..6f4abd4e5 100644 --- a/src/main/java/org/owasp/webgoat/session/Course.java +++ b/src/main/java/org/owasp/webgoat/session/Course.java @@ -1,49 +1,54 @@ package org.owasp.webgoat.session; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Set; -import java.util.LinkedList; -import javax.servlet.ServletContext; import org.owasp.webgoat.HammerHead; import org.owasp.webgoat.lessons.AbstractLesson; import org.owasp.webgoat.lessons.Category; -import org.owasp.webgoat.util.WebGoatI18N; +import org.owasp.webgoat.plugins.Plugin; +import org.owasp.webgoat.plugins.PluginsLoader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.servlet.ServletContext; +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + /** * ************************************************************************************************* - * - * + *

+ *

* 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. - * + *

* For details, please see http://webgoat.github.io * * @author Bruce Mayhew WebGoat @@ -73,7 +78,7 @@ public class Course { /** * Take an absolute file and return the filename. - * + *

* Ex. /etc/password becomes password * * @param s @@ -95,7 +100,7 @@ public class Course { /** * Take a class name and return the equivalent file name - * + *

* Ex. org.owasp.webgoat becomes org/owasp/webgoat.java * * @param className @@ -114,7 +119,7 @@ public class Course { * Takes a file name and builds the class file name * * @param fileName Description of the Parameter - * @param path Description of the Parameter + * @param path Description of the Parameter * @return Description of the Return Value */ private static String getClassFile(String fileName, String path) { @@ -237,7 +242,7 @@ public class Course { * Gets the lessons attribute of the Course object * * @param category Description of the Parameter - * @param role Description of the Parameter + * @param role Description of the Parameter * @return The lessons value */ private List getLessons(Category category, List roles) { @@ -276,106 +281,37 @@ public class Course { return null; } - /** - * Load all of the filenames into a temporary cache - * - * @param context - * @param path - */ - private void loadFiles(ServletContext context, String path) { - logger.debug("Loading files into cache, path: " + path); - Set resourcePaths = context.getResourcePaths(path); - if (resourcePaths == null) { - logger.error("Unable to load file cache for courses, this is probably a bug or configuration issue"); + private void loadLessionFromPlugin(ServletContext context) { + context.getContextPath(); + logger.debug("Loading plugins into cache"); + String pluginPath = context.getRealPath("plugin_lessons"); + String targetPath = context.getRealPath("plugin_extracted"); + if (pluginPath == null) { + logger.error("Plugins directory {} not found", pluginPath); return; } - Iterator itr = resourcePaths.iterator(); + Path pluginDirectory = Paths.get(pluginPath); + List plugins = new PluginsLoader(Paths.get(pluginPath), Paths.get(targetPath)).loadPlugins(false); + for (Plugin plugin : plugins) { + try { + Class c = plugin.getLesson(); + Object o = c.newInstance(); - while (itr.hasNext()) { - String file = (String) itr.next(); + AbstractLesson lesson = (AbstractLesson) o; + lesson.setWebgoatContext(webgoatContext); - if (file.length() != 1 && file.endsWith("/")) { - loadFiles(context, file); - } else { - files.add(file); - } - } - } + lesson.update(properties); - /** - * Instantiate all the lesson objects into a cache - * - * @param path - */ - private void loadLessons(String path) { - for (String file : files) { - String className = getClassFile(file, path); - - if (className != null && !className.endsWith("_i")) { - try { - Class c = Class.forName(className); - Object o = c.newInstance(); - - if (o instanceof AbstractLesson) { - AbstractLesson lesson = (AbstractLesson) o; - lesson.setWebgoatContext(webgoatContext); - - lesson.update(properties); - - if (lesson.getHidden() == false) { - lessons.add(lesson); - } - } - } catch (Exception e) { - logger.error("Error in loadLessons: ", e); + if (lesson.getHidden() == false) { + lessons.add(lesson); } - } - } - } - - private String getLanguageFromFileName(String first, String absoluteFile) { - int p1 = absoluteFile.indexOf("/", absoluteFile.indexOf(first) + 1); - int p2 = absoluteFile.indexOf("/", p1 + 1); - String langStr = absoluteFile.substring(p1 + 1, p2); - - return langStr; - } - - /** - * For each lesson, set the source file and lesson file - */ - private void loadResources() { - for (AbstractLesson lesson : lessons) { - logger.info("Loading resources for lesson -> " + lesson.getName()); - String className = lesson.getClass().getName(); - String classFile = getSourceFile(className); - logger.info("Lesson classname: " + className); - logger.info("Lesson java file: " + classFile); - - for (String absoluteFile : files) { - String fileName = getFileName(absoluteFile); - //logger.debug("Course: looking at file: " + absoluteFile); - - if (absoluteFile.endsWith(classFile)) { - logger.info("Set source file for " + classFile); - lesson.setSourceFileName(absoluteFile); - } - - if (absoluteFile.startsWith("/lesson_plans") && absoluteFile.endsWith(".html") - && className.endsWith(fileName)) { - logger.info("setting lesson plan file " + absoluteFile + " for lesson " - + lesson.getClass().getName()); - logger.info("fileName: " + fileName + " == className: " + className); - String language = getLanguageFromFileName("/lesson_plans", absoluteFile); - lesson.setLessonPlanFileName(language, absoluteFile); - } - if (absoluteFile.startsWith("/lesson_solutions") && absoluteFile.endsWith(".html") - && className.endsWith(fileName)) { - logger.info("setting lesson solution file " + absoluteFile + " for lesson " - + lesson.getClass().getName()); - logger.info("fileName: " + fileName + " == className: " + className); - lesson.setLessonSolutionFileName(absoluteFile); + for(Map.Entry lessonPlan : plugin.getLessonPlans().entrySet()) { + lesson.setLessonPlanFileName(lessonPlan.getKey(), lessonPlan.getValue().toString()); } + lesson.setLessonSolutionFileName(plugin.getLessonSolutions().get("en").toString()); + lesson.setSourceFileName(plugin.getLessonSource().toString()); + } catch (Exception e) { + logger.error("Error in loadLessons: ", e); } } } @@ -384,14 +320,13 @@ public class Course { * Description of the Method * * @param webgoatContext - * @param path Description of the Parameter - * @param context Description of the Parameter + * @param path Description of the Parameter + * @param context Description of the Parameter */ public void loadCourses(WebgoatContext webgoatContext, ServletContext context, String path) { logger.info("Loading courses: " + path); this.webgoatContext = webgoatContext; - loadFiles(context, path); - loadLessons(path); - loadResources(); + loadLessionFromPlugin(context); } + } diff --git a/src/main/java/org/owasp/webgoat/session/WebgoatContext.java b/src/main/java/org/owasp/webgoat/session/WebgoatContext.java index 1d3fb8266..8c9ce4549 100644 --- a/src/main/java/org/owasp/webgoat/session/WebgoatContext.java +++ b/src/main/java/org/owasp/webgoat/session/WebgoatContext.java @@ -1,9 +1,10 @@ package org.owasp.webgoat.session; -import javax.servlet.http.HttpServlet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.servlet.http.HttpServlet; + public class WebgoatContext { final Logger logger = LoggerFactory.getLogger(WebgoatContext.class); @@ -80,6 +81,8 @@ public class WebgoatContext { private String defaultLanguage; + private java.nio.file.Path pluginDirectory; + public WebgoatContext(HttpServlet servlet) { this.servlet = servlet; databaseConnectionString = getParameter(servlet, DATABASE_CONNECTION_STRING); @@ -212,5 +215,4 @@ public class WebgoatContext { public String getDefaultLanguage() { return defaultLanguage; } - } diff --git a/src/main/java/org/owasp/webgoat/util/LabelProvider.java b/src/main/java/org/owasp/webgoat/util/LabelProvider.java index ad6ffe4ff..e2861096d 100644 --- a/src/main/java/org/owasp/webgoat/util/LabelProvider.java +++ b/src/main/java/org/owasp/webgoat/util/LabelProvider.java @@ -1,10 +1,12 @@ package org.owasp.webgoat.util; +import org.owasp.webgoat.plugins.ResourceBundleClassLoader; +import org.springframework.stereotype.Component; + import java.util.HashMap; import java.util.Locale; import java.util.ResourceBundle; -import org.springframework.stereotype.Component; /*************************************************************************************************** @@ -37,7 +39,7 @@ import org.springframework.stereotype.Component; @Component public class LabelProvider { - public final static String DEFAULT_LANGUAGE = "en"; + public final static String DEFAULT_LANGUAGE = Locale.ENGLISH.getLanguage(); private final HashMap labels = new HashMap(); private final WebGoatResourceBundleController localeController = new WebGoatResourceBundleController(); @@ -46,7 +48,8 @@ public class LabelProvider { if (!labels.containsKey(locale)) { - ResourceBundle resBundle = ResourceBundle.getBundle("WebGoatLabels", locale, localeController); + ClassLoader classLoader = ResourceBundleClassLoader.createPropertyFilesClassLoader(ResourceBundle.class.getClassLoader()); + ResourceBundle resBundle = ResourceBundle.getBundle("WebGoatLabels", locale, classLoader, localeController); labels.put(locale, resBundle); } return labels.get(locale).getString(strName); diff --git a/src/main/resources/WebGoatLabels.properties b/src/main/resources/WebGoatLabels.properties deleted file mode 100644 index 21e1a6125..000000000 --- a/src/main/resources/WebGoatLabels.properties +++ /dev/null @@ -1,7 +0,0 @@ -#General -LessonCompleted=Congratulations. You have successfully completed this lesson. -RestartLesson=Restart this Lesson -SolutionVideos=Solution Videos -ErrorGenerating=Error generating -InvalidData=Invalid Data - diff --git a/src/main/resources/WebGoatLabels_de.properties b/src/main/resources/WebGoatLabels_de.properties deleted file mode 100644 index d6edeef94..000000000 --- a/src/main/resources/WebGoatLabels_de.properties +++ /dev/null @@ -1,8 +0,0 @@ -#General -LessonCompleted=Herzlichen Gl\u00fcckwunsch! Sie haben diese Lektion erfolgreich abgeschlossen. -RestartLesson=Lektion neu beginnen -SolutionVideos=L\u00f6sungsvideos -ErrorGenerating=Fehler beim Generieren von -InvalidData=Ung\u00fcltige Daten - - \ No newline at end of file diff --git a/src/main/resources/WebGoatLabels_fr.properties b/src/main/resources/WebGoatLabels_fr.properties deleted file mode 100644 index 24b7f4f39..000000000 --- a/src/main/resources/WebGoatLabels_fr.properties +++ /dev/null @@ -1,7 +0,0 @@ -#General -LessonCompleted=F\u00e9licitations. Vous avez termin\u00e9 cette le\u00e7on avec succ\u00e9s. -RestartLesson=Recommencer cette le\u00e7on -SolutionVideos=Solution vid\u00e9os -ErrorGenerating=Error generating -InvalidData=Donn\u00e9e invalide - diff --git a/src/main/resources/WebGoatLabels_ru.properties b/src/main/resources/WebGoatLabels_ru.properties deleted file mode 100644 index 8b7a4132d..000000000 --- a/src/main/resources/WebGoatLabels_ru.properties +++ /dev/null @@ -1,7 +0,0 @@ -#General -LessonCompleted=\u041f\u043e\u0437\u0434\u0440\u0430\u0432\u043b\u044f\u044e. \u0412\u044b \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043f\u0440\u043e\u0448\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0439 \u0443\u0440\u043e\u043a. -RestartLesson=\u041d\u0430\u0447\u0430\u043b\u044c \u0441\u043d\u0430\u0447\u0430\u043b\u0430 -SolutionVideos=\u0412\u0438\u0434\u0435\u043e \u0441 \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c -ErrorGenerating=\u041f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430 -InvalidData=\u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 - diff --git a/src/main/resources/log4j.properties b/src/main/resources/log4j.properties index 734eb76c8..7dee72c2e 100644 --- a/src/main/resources/log4j.properties +++ b/src/main/resources/log4j.properties @@ -1,4 +1,4 @@ -log4j.rootLogger=DEBUG, MAIN_LOG +log4j.rootLogger=DEBUG, MAIN_LOG,CONSOLE #log4j.rootLogger=DEBUG, MAIN_LOG, ERROR_LOG # MAIN - everything gets logged here @@ -10,9 +10,20 @@ log4j.appender.MAIN_LOG.MaxFileSize=10MB log4j.appender.MAIN_LOG.MaxBackupIndex=5 log4j.appender.MAIN_LOG.append=true +log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender +log4j.appender.CONSOLE.Target=System.out +log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout +log4j.appender.CONSOLE.layout.conversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p - %m%n + + # a little less spring output log4j.category.org.springframework = INFO +log4j.appender.default.out=org.apache.log4j.ConsoleAppender +log4j.appender.default.out.threeshold=DEBUG +log4j.appender.default.out.layout=org.apache.log4j.PatternLayout +log4j.appender.default.out.layout.ConversionPattern=%-5p %c: %m%n + # ERROR log4j.appender.ERROR_LOG=org.apache.log4j.RollingFileAppender log4j.appender.ERROR_LOG.File=${catalina.home}/logs/webgoat_error.log diff --git a/src/main/webapp/js/ace/mode-praat.js b/src/main/webapp/js/ace/mode-praat.js index bbd5618ac..d47e332f4 100644 --- a/src/main/webapp/js/ace/mode-praat.js +++ b/src/main/webapp/js/ace/mode-praat.js @@ -1 +1 @@ -ace.define("ace/mode/praat_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){var e="if|then|else|elsif|elif|endif|fi|endfor|endproc|while|endwhile|repeat|until|select|plus|minus|assert",t="macintosh|windows|unix|praatVersion|praatVersion\\$pi|undefined|newline\\$|tab\\$|shellDirectory\\$|homeDirectory\\$|preferencesDirectory\\$|temporaryDirectory\\$|defaultDirectory\\$",n="clearinfo|endSendPraat",r="writeInfo|writeInfoLine|appendInfo|appendInfoLine|writeFile|writeFileLine|appendFile|appendFileLine|abs|round|floor|ceiling|min|max|imin|imax|sqrt|sin|cos|tan|arcsin|arccos|arctan|arctan2|sinc|sincpi|exp|ln|log10|log2|sinh|cosh|tanh|arcsinh|arccosh|actanh|sigmoid|invSigmoid|erf|erfc|randomUniform|randomInteger|randomGauss|randomPoisson|lnGamma|gaussP|gaussQ|invGaussQ|chiSquareP|chiSquareQ|invChiSquareQ|studentP|studentQ|invStudentQ|fisherP|fisherQ|invFisherQ|binomialP|binomialQ|invBinomialP|invBinomialQ|hertzToBark|barkToHerz|hertzToMel|melToHertz|hertzToSemitones|semitonesToHerz|erb|hertzToErb|erbToHertz|phonToDifferenceLimens|differenceLimensToPhon|beta|besselI|besselK|selected|selected\\$|numberOfSelected|variableExists|index|rindex|startsWith|endsWith|index_regex|rindex_regex|replace_regex\\$|length|extractWord\\$|extractLine\\$|extractNumber|left\\$|right\\$|mid\\$|replace\\$|beginPause|endPause|demoShow|demoWindowTitle|demoInput|demoWaitForInput|demoClicked|demoClickedIn|demoX|demoY|demoKeyPressed|demoKey\\$|demoExtraControlKeyPressed|demoShiftKeyPressed|demoCommandKeyPressed|demoOptionKeyPressed|environment\\$|chooseReadFile\\$|chooseDirectory\\$|createDirectory|fileReadable|deleteFile|selectObject|removeObject|plusObject|minusObject|runScript|exitScript|beginSendPraat|endSendPraat",i="Activation|AffineTransform|AmplitudeTier|Art|Artword|Autosegment|BarkFilter|CCA|Categories|Cepstrum|Cepstrumc|ChebyshevSeries|ClassificationTable|Cochleagram|Collection|Configuration|Confusion|ContingencyTable|Corpus|Correlation|Covariance|CrossCorrelationTable|CrossCorrelationTables|DTW|Diagonalizer|Discriminant|Dissimilarity|Distance|Distributions|DurationTier|EEG|ERP|ERPTier|Eigen|Excitation|Excitations|ExperimentMFC|FFNet|FeatureWeights|Formant|FormantFilter|FormantGrid|FormantPoint|FormantTier|GaussianMixture|HMM|HMM_Observation|HMM_ObservationSequence|HMM_State|HMM_StateSequence|Harmonicity|ISpline|Index|Intensity|IntensityTier|IntervalTier|KNN|KlattGrid|KlattTable|LFCC|LPC|Label|LegendreSeries|LinearRegression|LogisticRegression|LongSound|Ltas|MFCC|MSpline|ManPages|Manipulation|Matrix|MelFilter|MixingMatrix|Movie|Network|OTGrammar|OTHistory|OTMulti|PCA|PairDistribution|ParamCurve|Pattern|Permutation|Pitch|PitchTier|PointProcess|Polygon|Polynomial|Procrustes|RealPoint|RealTier|ResultsMFC|Roots|SPINET|SSCP|SVD|Salience|ScalarProduct|Similarity|SimpleString|SortedSetOfString|Sound|Speaker|Spectrogram|Spectrum|SpectrumTier|SpeechSynthesizer|SpellingChecker|Strings|StringsIndex|Table|TableOfReal|TextGrid|TextInterval|TextPoint|TextTier|Tier|Transition|VocalTract|Weight|WordList";this.$rules={start:[{token:"string.interpolated",regex:/'((?:[a-z][a-zA-Z0-9_]*)(?:\$|#|:[0-9]+)?)'/},{token:["text","text","keyword.operator","text","keyword"],regex:/(^\s*)(?:([a-z][a-zA-Z0-9_]*\$?\s+)(=)(\s+))?(stopwatch)/},{token:["text","keyword","text","string"],regex:/(^\s*)(print(?:line)?|echo|exit|pause|sendpraat|include|execute)(\s+)(.*)/},{token:["text","keyword"],regex:"(^\\s*)("+n+")$"},{token:["text","keyword.operator","text"],regex:/(\s+)((?:\+|-|\/|\*|<|>)=?|==?|!=|%|\^|\||and|or|not)(\s+)/},{token:["text","text","keyword.operator","text","keyword","text","keyword"],regex:/(^\s*)(?:([a-z][a-zA-Z0-9_]*\$?\s+)(=)(\s+))?(?:((?:no)?warn|nocheck|noprogress)(\s+))?((?:[A-Z][^.:"]+)(?:$|(?:\.{3}|:)))/},{token:["text","keyword","text","keyword"],regex:/(^\s*)(?:(demo)?(\s+))((?:[A-Z][^.:"]+)(?:$|(?:\.{3}|:)))/},{token:["text","keyword","text","keyword"],regex:/^(\s*)(?:(demo)(\s+))?(10|12|14|16|24)$/},{token:["text","support.function","text"],regex:/(\s*)(do\$?)(\s*:\s*|\s*\(\s*)/},{token:"entity.name.type",regex:"("+i+")"},{token:"variable.language",regex:"("+t+")"},{token:["support.function","text"],regex:"((?:"+r+")\\$?)(\\s*(?::|\\())"},{token:"keyword",regex:/(\bfor\b)/,next:"for"},{token:"keyword",regex:"(\\b(?:"+e+")\\b)"},{token:"string",regex:/"[^"]*"/},{token:"string",regex:/"[^"]*$/,next:"brokenstring"},{token:["text","keyword","text","entity.name.section"],regex:/(^\s*)(\bform\b)(\s+)(.*)/,next:"form"},{token:"constant.numeric",regex:/\b[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/},{token:["keyword","text","entity.name.function"],regex:/(procedure)(\s+)(\S+)/},{token:["entity.name.function","text"],regex:/(@\S+)(:|\s*\()/},{token:["text","keyword","text","entity.name.function"],regex:/(^\s*)(call)(\s+)(\S+)/},{token:"comment",regex:/(^\s*#|;).*$/},{token:"text",regex:/\s+/}],form:[{token:["keyword","text","constant.numeric"],regex:/((?:optionmenu|choice)\s+)(\S+:\s+)([0-9]+)/},{token:["keyword","constant.numeric"],regex:/((?:option|button)\s+)([+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b)/},{token:["keyword","string"],regex:/((?:option|button)\s+)(.*)/},{token:["keyword","text","string"],regex:/((?:sentence|text)\s+)(\S+\s*)(.*)/},{token:["keyword","text","string","invalid.illegal"],regex:/(word\s+)(\S+\s*)(\S+)?(\s.*)?/},{token:["keyword","text","constant.language"],regex:/(boolean\s+)(\S+\s*)(0|1|"?(?:yes|no)"?)/},{token:["keyword","text","constant.numeric"],regex:/((?:real|natural|positive|integer)\s+)(\S+\s*)([+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b)/},{token:["keyword","string"],regex:/(comment\s+)(.*)/},{token:"keyword",regex:"endform",next:"start"}],"for":[{token:["keyword","text","constant.numeric","text"],regex:/(from|to)(\s+)([+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?)(\s*)/},{token:["keyword","text"],regex:/(from|to)(\s+\S+\s*)/},{token:"text",regex:/$/,next:"start"}],brokenstring:[{token:["text","string"],regex:/(\s*\.{3})([^"]*)/},{token:"string",regex:/"/,next:"start"}]}};r.inherits(s,i),t.PraatHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){"use strict";var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){return e.match(/^\s*/)[0]}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){"use strict";var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(e){e&&(this.foldingStartMarker=new RegExp(this.foldingStartMarker.source.replace(/\|[^|]*?$/,"|"+e.start)),this.foldingStopMarker=new RegExp(this.foldingStopMarker.source.replace(/\|[^|]*?$/,"|"+e.end)))};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n,r){var i=e.getLine(n),s=i.match(this.foldingStartMarker);if(s){var o=s.index;if(s[1])return this.openingBracketBlock(e,s[1],n,o);var u=e.getCommentFoldRange(n,o+s[0].length,1);return u&&!u.isMultiLine()&&(r?u=this.getSectionRange(e,n):t!="all"&&(u=null)),u}if(t==="markbegin")return;var s=i.match(this.foldingStopMarker);if(s){var o=s.index+s[0].length;return s[1]?this.closingBracketBlock(e,s[1],n,o):e.getCommentFoldRange(n,o,-1)}},this.getSectionRange=function(e,t){var n=e.getLine(t),r=n.search(/\S/),s=t,o=n.length;t+=1;var u=t,a=e.getLength();while(++tf)break;var l=this.getFoldWidgetRange(e,"all",t);if(l){if(l.start.row<=s)break;if(l.isMultiLine())t=l.end.row;else if(r==f)break}u=t}return new i(s,o,u,e.getLine(u).length)}}.call(o.prototype)}),ace.define("ace/mode/praat",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/praat_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/mode/folding/cstyle"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text").Mode,s=e("./praat_highlight_rules").PraatHighlightRules,o=e("./matching_brace_outdent").MatchingBraceOutdent,u=e("../range").Range,a=e("./folding/cstyle").FoldMode,f=function(){this.HighlightRules=s,this.$outdent=new o};r.inherits(f,i),function(){this.lineCommentStart="#",this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.getTokenizer().getLineTokens(t,e),s=i.tokens;if(s.length&&s[s.length-1].type=="comment")return r;if(e=="start"){var o=t.match(/^.*[\{\(\[\:]\s*$/);o&&(r+=n)}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.$id="ace/mode/praat"}.call(f.prototype),t.Mode=f}) \ No newline at end of file +ace.define("ace/mode/praat_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){var e="if|then|else|elsif|elif|endif|fi|endfor|endproc|while|endwhile|repeat|until|select|plus|minus|assert",t="macintosh|windows|unix|praatVersion|praatVersion\\$pi|undefined|newline\\$|tab\\$|shellDirectory\\$|homeDirectory\\$|preferencesDirectory\\$|temporaryDirectory\\$|defaultDirectory\\$",n="clearinfo|endSendPraat",r="writeInfo|writeInfoLine|appendInfo|appendInfoLine|writeFile|writeFileLine|appendFile|appendFileLine|abs|round|floor|ceiling|min|max|imin|imax|sqrt|sin|cos|tan|arcsin|arccos|arctan|arctan2|sinc|sincpi|exp|ln|log10|log2|sinh|cosh|tanh|arcsinh|arccosh|actanh|sigmoid|invSigmoid|erf|erfc|randomUniform|randomInteger|randomGauss|randomPoisson|lnGamma|gaussP|gaussQ|invGaussQ|chiSquareP|chiSquareQ|invChiSquareQ|studentP|studentQ|invStudentQ|fisherP|fisherQ|invFisherQ|binomialP|binomialQ|invBinomialP|invBinomialQ|hertzToBark|barkToHerz|hertzToMel|melToHertz|hertzToSemitones|semitonesToHerz|erb|hertzToErb|erbToHertz|phonToDifferenceLimens|differenceLimensToPhon|beta|besselI|besselK|selected|selected\\$|numberOfSelected|variableExists|index|rindex|startsWith|fileEndsWith|index_regex|rindex_regex|replace_regex\\$|length|extractWord\\$|extractLine\\$|extractNumber|left\\$|right\\$|mid\\$|replace\\$|beginPause|endPause|demoShow|demoWindowTitle|demoInput|demoWaitForInput|demoClicked|demoClickedIn|demoX|demoY|demoKeyPressed|demoKey\\$|demoExtraControlKeyPressed|demoShiftKeyPressed|demoCommandKeyPressed|demoOptionKeyPressed|environment\\$|chooseReadFile\\$|chooseDirectory\\$|createDirectory|fileReadable|deleteFile|selectObject|removeObject|plusObject|minusObject|runScript|exitScript|beginSendPraat|endSendPraat",i="Activation|AffineTransform|AmplitudeTier|Art|Artword|Autosegment|BarkFilter|CCA|Categories|Cepstrum|Cepstrumc|ChebyshevSeries|ClassificationTable|Cochleagram|Collection|Configuration|Confusion|ContingencyTable|Corpus|Correlation|Covariance|CrossCorrelationTable|CrossCorrelationTables|DTW|Diagonalizer|Discriminant|Dissimilarity|Distance|Distributions|DurationTier|EEG|ERP|ERPTier|Eigen|Excitation|Excitations|ExperimentMFC|FFNet|FeatureWeights|Formant|FormantFilter|FormantGrid|FormantPoint|FormantTier|GaussianMixture|HMM|HMM_Observation|HMM_ObservationSequence|HMM_State|HMM_StateSequence|Harmonicity|ISpline|Index|Intensity|IntensityTier|IntervalTier|KNN|KlattGrid|KlattTable|LFCC|LPC|Label|LegendreSeries|LinearRegression|LogisticRegression|LongSound|Ltas|MFCC|MSpline|ManPages|Manipulation|Matrix|MelFilter|MixingMatrix|Movie|Network|OTGrammar|OTHistory|OTMulti|PCA|PairDistribution|ParamCurve|Pattern|Permutation|Pitch|PitchTier|PointProcess|Polygon|Polynomial|Procrustes|RealPoint|RealTier|ResultsMFC|Roots|SPINET|SSCP|SVD|Salience|ScalarProduct|Similarity|SimpleString|SortedSetOfString|Sound|Speaker|Spectrogram|Spectrum|SpectrumTier|SpeechSynthesizer|SpellingChecker|Strings|StringsIndex|Table|TableOfReal|TextGrid|TextInterval|TextPoint|TextTier|Tier|Transition|VocalTract|Weight|WordList";this.$rules={start:[{token:"string.interpolated",regex:/'((?:[a-z][a-zA-Z0-9_]*)(?:\$|#|:[0-9]+)?)'/},{token:["text","text","keyword.operator","text","keyword"],regex:/(^\s*)(?:([a-z][a-zA-Z0-9_]*\$?\s+)(=)(\s+))?(stopwatch)/},{token:["text","keyword","text","string"],regex:/(^\s*)(print(?:line)?|echo|exit|pause|sendpraat|include|execute)(\s+)(.*)/},{token:["text","keyword"],regex:"(^\\s*)("+n+")$"},{token:["text","keyword.operator","text"],regex:/(\s+)((?:\+|-|\/|\*|<|>)=?|==?|!=|%|\^|\||and|or|not)(\s+)/},{token:["text","text","keyword.operator","text","keyword","text","keyword"],regex:/(^\s*)(?:([a-z][a-zA-Z0-9_]*\$?\s+)(=)(\s+))?(?:((?:no)?warn|nocheck|noprogress)(\s+))?((?:[A-Z][^.:"]+)(?:$|(?:\.{3}|:)))/},{token:["text","keyword","text","keyword"],regex:/(^\s*)(?:(demo)?(\s+))((?:[A-Z][^.:"]+)(?:$|(?:\.{3}|:)))/},{token:["text","keyword","text","keyword"],regex:/^(\s*)(?:(demo)(\s+))?(10|12|14|16|24)$/},{token:["text","support.function","text"],regex:/(\s*)(do\$?)(\s*:\s*|\s*\(\s*)/},{token:"entity.name.type",regex:"("+i+")"},{token:"variable.language",regex:"("+t+")"},{token:["support.function","text"],regex:"((?:"+r+")\\$?)(\\s*(?::|\\())"},{token:"keyword",regex:/(\bfor\b)/,next:"for"},{token:"keyword",regex:"(\\b(?:"+e+")\\b)"},{token:"string",regex:/"[^"]*"/},{token:"string",regex:/"[^"]*$/,next:"brokenstring"},{token:["text","keyword","text","entity.name.section"],regex:/(^\s*)(\bform\b)(\s+)(.*)/,next:"form"},{token:"constant.numeric",regex:/\b[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/},{token:["keyword","text","entity.name.function"],regex:/(procedure)(\s+)(\S+)/},{token:["entity.name.function","text"],regex:/(@\S+)(:|\s*\()/},{token:["text","keyword","text","entity.name.function"],regex:/(^\s*)(call)(\s+)(\S+)/},{token:"comment",regex:/(^\s*#|;).*$/},{token:"text",regex:/\s+/}],form:[{token:["keyword","text","constant.numeric"],regex:/((?:optionmenu|choice)\s+)(\S+:\s+)([0-9]+)/},{token:["keyword","constant.numeric"],regex:/((?:option|button)\s+)([+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b)/},{token:["keyword","string"],regex:/((?:option|button)\s+)(.*)/},{token:["keyword","text","string"],regex:/((?:sentence|text)\s+)(\S+\s*)(.*)/},{token:["keyword","text","string","invalid.illegal"],regex:/(word\s+)(\S+\s*)(\S+)?(\s.*)?/},{token:["keyword","text","constant.language"],regex:/(boolean\s+)(\S+\s*)(0|1|"?(?:yes|no)"?)/},{token:["keyword","text","constant.numeric"],regex:/((?:real|natural|positive|integer)\s+)(\S+\s*)([+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b)/},{token:["keyword","string"],regex:/(comment\s+)(.*)/},{token:"keyword",regex:"endform",next:"start"}],"for":[{token:["keyword","text","constant.numeric","text"],regex:/(from|to)(\s+)([+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?)(\s*)/},{token:["keyword","text"],regex:/(from|to)(\s+\S+\s*)/},{token:"text",regex:/$/,next:"start"}],brokenstring:[{token:["text","string"],regex:/(\s*\.{3})([^"]*)/},{token:"string",regex:/"/,next:"start"}]}};r.inherits(s,i),t.PraatHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){"use strict";var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){return e.match(/^\s*/)[0]}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){"use strict";var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(e){e&&(this.foldingStartMarker=new RegExp(this.foldingStartMarker.source.replace(/\|[^|]*?$/,"|"+e.start)),this.foldingStopMarker=new RegExp(this.foldingStopMarker.source.replace(/\|[^|]*?$/,"|"+e.end)))};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n,r){var i=e.getLine(n),s=i.match(this.foldingStartMarker);if(s){var o=s.index;if(s[1])return this.openingBracketBlock(e,s[1],n,o);var u=e.getCommentFoldRange(n,o+s[0].length,1);return u&&!u.isMultiLine()&&(r?u=this.getSectionRange(e,n):t!="all"&&(u=null)),u}if(t==="markbegin")return;var s=i.match(this.foldingStopMarker);if(s){var o=s.index+s[0].length;return s[1]?this.closingBracketBlock(e,s[1],n,o):e.getCommentFoldRange(n,o,-1)}},this.getSectionRange=function(e,t){var n=e.getLine(t),r=n.search(/\S/),s=t,o=n.length;t+=1;var u=t,a=e.getLength();while(++tf)break;var l=this.getFoldWidgetRange(e,"all",t);if(l){if(l.start.row<=s)break;if(l.isMultiLine())t=l.end.row;else if(r==f)break}u=t}return new i(s,o,u,e.getLine(u).length)}}.call(o.prototype)}),ace.define("ace/mode/praat",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/praat_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/mode/folding/cstyle"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text").Mode,s=e("./praat_highlight_rules").PraatHighlightRules,o=e("./matching_brace_outdent").MatchingBraceOutdent,u=e("../range").Range,a=e("./folding/cstyle").FoldMode,f=function(){this.HighlightRules=s,this.$outdent=new o};r.inherits(f,i),function(){this.lineCommentStart="#",this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.getTokenizer().getLineTokens(t,e),s=i.tokens;if(s.length&&s[s.length-1].type=="comment")return r;if(e=="start"){var o=t.match(/^.*[\{\(\[\:]\s*$/);o&&(r+=n)}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.$id="ace/mode/praat"}.call(f.prototype),t.Mode=f}) \ No newline at end of file diff --git a/src/main/webapp/js/ace/snippets/jsp.js b/src/main/webapp/js/ace/snippets/jsp.js index fcbace719..c39e6c084 100644 --- a/src/main/webapp/js/ace/snippets/jsp.js +++ b/src/main/webapp/js/ace/snippets/jsp.js @@ -1 +1 @@ -ace.define("ace/snippets/jsp",["require","exports","module"],function(e,t,n){"use strict";t.snippetText='snippet @page\n <%@page contentType="text/html" pageEncoding="UTF-8"%>\nsnippet jstl\n <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>\n <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>\nsnippet jstl:c\n <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>\nsnippet jstl:fn\n <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>\nsnippet cpath\n ${pageContext.request.contextPath}\nsnippet cout\n \nsnippet cset\n \nsnippet cremove\n \nsnippet ccatch\n \nsnippet cif\n \n ${2}\n \nsnippet cchoose\n \n ${1}\n \nsnippet cwhen\n \n ${2}\n \nsnippet cother\n \n ${1}\n \nsnippet cfore\n \n ${4:}\n \nsnippet cfort\n ${2:item1,item2,item3}\n \n ${5:}\n \nsnippet cparam\n \nsnippet cparam+\n \n cparam+${3}\nsnippet cimport\n \nsnippet cimport+\n \n \n cparam+${4}\n \nsnippet curl\n \n ${3}\nsnippet curl+\n \n \n cparam+${6}\n \n ${3}\nsnippet credirect\n \nsnippet contains\n ${fn:contains(${1:string}, ${2:substr})}\nsnippet contains:i\n ${fn:containsIgnoreCase(${1:string}, ${2:substr})}\nsnippet endswith\n ${fn:endsWith(${1:string}, ${2:suffix})}\nsnippet escape\n ${fn:escapeXml(${1:string})}\nsnippet indexof\n ${fn:indexOf(${1:string}, ${2:substr})}\nsnippet join\n ${fn:join(${1:collection}, ${2:delims})}\nsnippet length\n ${fn:length(${1:collection_or_string})}\nsnippet replace\n ${fn:replace(${1:string}, ${2:substr}, ${3:replace})}\nsnippet split\n ${fn:split(${1:string}, ${2:delims})}\nsnippet startswith\n ${fn:startsWith(${1:string}, ${2:prefix})}\nsnippet substr\n ${fn:substring(${1:string}, ${2:begin}, ${3:end})}\nsnippet substr:a\n ${fn:substringAfter(${1:string}, ${2:substr})}\nsnippet substr:b\n ${fn:substringBefore(${1:string}, ${2:substr})}\nsnippet lc\n ${fn:toLowerCase(${1:string})}\nsnippet uc\n ${fn:toUpperCase(${1:string})}\nsnippet trim\n ${fn:trim(${1:string})}\n',t.scope="jsp"}) \ No newline at end of file +ace.define("ace/snippets/jsp",["require","exports","module"],function(e,t,n){"use strict";t.snippetText='snippet @page\n <%@page contentType="text/html" pageEncoding="UTF-8"%>\nsnippet jstl\n <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>\n <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>\nsnippet jstl:c\n <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>\nsnippet jstl:fn\n <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>\nsnippet cpath\n ${pageContext.request.contextPath}\nsnippet cout\n \nsnippet cset\n \nsnippet cremove\n \nsnippet ccatch\n \nsnippet cif\n \n ${2}\n \nsnippet cchoose\n \n ${1}\n \nsnippet cwhen\n \n ${2}\n \nsnippet cother\n \n ${1}\n \nsnippet cfore\n \n ${4:}\n \nsnippet cfort\n ${2:item1,item2,item3}\n \n ${5:}\n \nsnippet cparam\n \nsnippet cparam+\n \n cparam+${3}\nsnippet cimport\n \nsnippet cimport+\n \n \n cparam+${4}\n \nsnippet curl\n \n ${3}\nsnippet curl+\n \n \n cparam+${6}\n \n ${3}\nsnippet credirect\n \nsnippet contains\n ${fn:contains(${1:string}, ${2:substr})}\nsnippet contains:i\n ${fn:containsIgnoreCase(${1:string}, ${2:substr})}\nsnippet endswith\n ${fn:fileEndsWith(${1:string}, ${2:suffix})}\nsnippet escape\n ${fn:escapeXml(${1:string})}\nsnippet indexof\n ${fn:indexOf(${1:string}, ${2:substr})}\nsnippet join\n ${fn:join(${1:collection}, ${2:delims})}\nsnippet length\n ${fn:length(${1:collection_or_string})}\nsnippet replace\n ${fn:replace(${1:string}, ${2:substr}, ${3:replace})}\nsnippet split\n ${fn:split(${1:string}, ${2:delims})}\nsnippet startswith\n ${fn:startsWith(${1:string}, ${2:prefix})}\nsnippet substr\n ${fn:substring(${1:string}, ${2:begin}, ${3:end})}\nsnippet substr:a\n ${fn:substringAfter(${1:string}, ${2:substr})}\nsnippet substr:b\n ${fn:substringBefore(${1:string}, ${2:substr})}\nsnippet lc\n ${fn:toLowerCase(${1:string})}\nsnippet uc\n ${fn:toUpperCase(${1:string})}\nsnippet trim\n ${fn:trim(${1:string})}\n',t.scope="jsp"}) \ No newline at end of file diff --git a/src/main/webapp/lessons/ConfManagement/config.jsp b/src/main/webapp/lessons/ConfManagement/config.jsp new file mode 100644 index 000000000..31b51e2f1 --- /dev/null +++ b/src/main/webapp/lessons/ConfManagement/config.jsp @@ -0,0 +1,19 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> +<%@page import="org.owasp.webgoat.session.WebSession"%> +<% +WebSession webSession = ((WebSession)session.getAttribute("websession")); +%> + + + + +Configuration Page + + +<% response.sendRedirect(webSession.getCurrentLesson().getLink() + + "&succeeded=yes"); +%> + + + \ No newline at end of file diff --git a/src/main/webapp/plugin_lessons/SqlStringInjection-1.0.jar b/src/main/webapp/plugin_lessons/SqlStringInjection-1.0.jar new file mode 100644 index 000000000..d032bb12c Binary files /dev/null and b/src/main/webapp/plugin_lessons/SqlStringInjection-1.0.jar differ