Merge branch 'webgoat-container' of https://github.com/WebGoat/WebGoat into webgoat-container
This commit is contained in:
commit
cbc58dc4fa
31
pom.xml
31
pom.xml
@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.owasp.webgoat</groupId>
|
||||
<artifactId>WebGoat-Container</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<packaging>war</packaging>
|
||||
<version>6.1.0</version>
|
||||
|
||||
<repositories>
|
||||
@ -38,15 +38,17 @@
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
<source>1.7</source>
|
||||
<target>1.7</target>
|
||||
<encoding>ISO-8859-1</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
|
||||
<configuration>
|
||||
<archiveClasses>true</archiveClasses>
|
||||
<manifest>
|
||||
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
|
||||
</manifest>
|
||||
@ -59,10 +61,28 @@
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>create-jar</id>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.tomcat.maven</groupId>
|
||||
<artifactId>tomcat7-maven-plugin</artifactId>
|
||||
<version>2.1</version>
|
||||
<configuration>
|
||||
<url>http://localhost:8080/manager</url>
|
||||
<path>/WebGoat</path>
|
||||
<attachArtifactClassifier>exec</attachArtifactClassifier>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>tomcat-run</id>
|
||||
@ -70,11 +90,6 @@
|
||||
<goal>exec-war-only</goal>
|
||||
</goals>
|
||||
<phase>package</phase>
|
||||
<configuration>
|
||||
<url>http://localhost:8080/manager</url>
|
||||
<path>/WebGoat</path>
|
||||
<attachArtifactClassifier>exec</attachArtifactClassifier>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
@ -385,7 +385,7 @@ public abstract class AbstractLesson extends Screen implements Comparable<Object
|
||||
|
||||
}
|
||||
|
||||
src.append(readFromFile(new BufferedReader(new FileReader(s.getWebResource(filename))), false));
|
||||
src.append(readFromFile(new BufferedReader(new FileReader(filename)), false));
|
||||
|
||||
} catch (Exception e) {
|
||||
// s.setMessage( "Could not find lesson plan for " +
|
||||
@ -467,8 +467,7 @@ public abstract class AbstractLesson extends Screen implements Comparable<Object
|
||||
try {
|
||||
// System.out.println("Loading source file: " +
|
||||
// getSourceFileName());
|
||||
src = convertMetacharsJavaCode(readFromFile(new BufferedReader(new FileReader(s
|
||||
.getWebResource(getSourceFileName()))), true));
|
||||
src = convertMetacharsJavaCode(readFromFile(new BufferedReader(new FileReader(getSourceFileName())), true));
|
||||
|
||||
// TODO: For styled line numbers and better memory efficiency,
|
||||
// use a custom FilterReader
|
||||
@ -504,7 +503,7 @@ public abstract class AbstractLesson extends Screen implements Comparable<Object
|
||||
|
||||
try {
|
||||
logger.debug("Loading source file: " + getSourceFileName());
|
||||
src = readFromFile(new BufferedReader(new FileReader(s.getWebResource(getSourceFileName()))), false);
|
||||
src = readFromFile(new BufferedReader(new FileReader(getSourceFileName())), false);
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
s.setMessage("Could not find source file");
|
||||
@ -522,7 +521,7 @@ public abstract class AbstractLesson extends Screen implements Comparable<Object
|
||||
|
||||
try {
|
||||
// System.out.println("Solution: " + getLessonSolutionFileName());
|
||||
src = readFromFile(new BufferedReader(new FileReader(s.getWebResource(getLessonSolutionFileName()))), false);
|
||||
src = readFromFile(new BufferedReader(new FileReader(getLessonSolutionFileName())), false);
|
||||
} catch (Exception e) {
|
||||
s.setMessage("Could not find the solution file");
|
||||
src = ("Could not find the solution file or solution file does not exist.<br/>"
|
||||
|
146
src/main/java/org/owasp/webgoat/plugins/Plugin.java
Normal file
146
src/main/java/org/owasp/webgoat/plugins/Plugin.java
Normal file
@ -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<AbstractLesson> lesson;
|
||||
private Map<String, File> solutionLanguageFiles = new HashMap<>();
|
||||
private Map<String, File> 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<String, byte[]> classes) {
|
||||
for (Map.Entry<String, byte[]> 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<Path> 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<String, File> 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<AbstractLesson> getLesson() {
|
||||
return lesson;
|
||||
}
|
||||
|
||||
public Map<String, File> getLessonSolutions() {
|
||||
return this.solutionLanguageFiles;
|
||||
}
|
||||
|
||||
public File getLessonSource() {
|
||||
return lessonSourceFile;
|
||||
}
|
||||
|
||||
public Map<String, File> getLessonPlans() {
|
||||
return this.lessonPlansLanguageFiles;
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
71
src/main/java/org/owasp/webgoat/plugins/PluginExtractor.java
Normal file
71
src/main/java/org/owasp/webgoat/plugins/PluginExtractor.java
Normal file
@ -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<String, byte[]> classes = new HashMap<>();
|
||||
private final List<Path> 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<Path>() {
|
||||
@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<String, byte[]> getClasses() {
|
||||
return this.classes;
|
||||
}
|
||||
|
||||
public List<Path> 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<String, Object>());
|
||||
}
|
||||
|
||||
|
||||
}
|
31
src/main/java/org/owasp/webgoat/plugins/PluginFileUtils.java
Normal file
31
src/main/java/org/owasp/webgoat/plugins/PluginFileUtils.java
Normal file
@ -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;
|
||||
}
|
||||
|
||||
}
|
60
src/main/java/org/owasp/webgoat/plugins/PluginsLoader.java
Normal file
60
src/main/java/org/owasp/webgoat/plugins/PluginsLoader.java
Normal file
@ -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<Plugin> loadPlugins(final boolean reload) {
|
||||
final List<Plugin> plugins = new ArrayList<Plugin>();
|
||||
try {
|
||||
Files.walkFileTree(pluginSource, new SimpleFileVisitor<Path>() {
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
@ -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<URL> 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());
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
/**
|
||||
* *************************************************************************************************
|
||||
*
|
||||
*
|
||||
* <p/>
|
||||
* <p/>
|
||||
* This file is part of WebGoat, an Open Web Application Security Project
|
||||
* utility. For details, please see http://www.owasp.org/
|
||||
*
|
||||
* <p/>
|
||||
* Copyright (c) 2002 - 20014 Bruce Mayhew
|
||||
*
|
||||
* <p/>
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* <p/>
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* <p/>
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
* Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* <p/>
|
||||
* Getting Source ==============
|
||||
*
|
||||
* <p/>
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
|
||||
* for free software projects.
|
||||
*
|
||||
* <p/>
|
||||
* For details, please see http://webgoat.github.io
|
||||
*
|
||||
* @author Bruce Mayhew <a href="http://code.google.com/p/webgoat">WebGoat</a>
|
||||
@ -73,7 +78,7 @@ public class Course {
|
||||
|
||||
/**
|
||||
* Take an absolute file and return the filename.
|
||||
*
|
||||
* <p/>
|
||||
* Ex. /etc/password becomes password
|
||||
*
|
||||
* @param s
|
||||
@ -95,7 +100,7 @@ public class Course {
|
||||
|
||||
/**
|
||||
* Take a class name and return the equivalent file name
|
||||
*
|
||||
* <p/>
|
||||
* 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<AbstractLesson> 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<Plugin> plugins = new PluginsLoader(Paths.get(pluginPath), Paths.get(targetPath)).loadPlugins(false);
|
||||
for (Plugin plugin : plugins) {
|
||||
try {
|
||||
Class<AbstractLesson> 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<String, File> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<Locale, ResourceBundle> labels = new HashMap<Locale, ResourceBundle>();
|
||||
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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
File diff suppressed because one or more lines are too long
@ -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 <c:out value="${1}" default="${2}" />\nsnippet cset\n <c:set var="${1}" value="${2}" />\nsnippet cremove\n <c:remove var="${1}" scope="${2:page}" />\nsnippet ccatch\n <c:catch var="${1}" />\nsnippet cif\n <c:if test="${${1}}">\n ${2}\n </c:if>\nsnippet cchoose\n <c:choose>\n ${1}\n </c:choose>\nsnippet cwhen\n <c:when test="${${1}}">\n ${2}\n </c:when>\nsnippet cother\n <c:otherwise>\n ${1}\n </c:otherwise>\nsnippet cfore\n <c:forEach items="${${1}}" var="${2}" varStatus="${3}">\n ${4:<c:out value="$2" />}\n </c:forEach>\nsnippet cfort\n <c:set var="${1}">${2:item1,item2,item3}</c:set>\n <c:forTokens var="${3}" items="${$1}" delims="${4:,}">\n ${5:<c:out value="$3" />}\n </c:forTokens>\nsnippet cparam\n <c:param name="${1}" value="${2}" />\nsnippet cparam+\n <c:param name="${1}" value="${2}" />\n cparam+${3}\nsnippet cimport\n <c:import url="${1}" />\nsnippet cimport+\n <c:import url="${1}">\n <c:param name="${2}" value="${3}" />\n cparam+${4}\n </c:import>\nsnippet curl\n <c:url value="${1}" var="${2}" />\n <a href="${$2}">${3}</a>\nsnippet curl+\n <c:url value="${1}" var="${2}">\n <c:param name="${4}" value="${5}" />\n cparam+${6}\n </c:url>\n <a href="${$2}">${3}</a>\nsnippet credirect\n <c:redirect url="${1}" />\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"})
|
||||
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 <c:out value="${1}" default="${2}" />\nsnippet cset\n <c:set var="${1}" value="${2}" />\nsnippet cremove\n <c:remove var="${1}" scope="${2:page}" />\nsnippet ccatch\n <c:catch var="${1}" />\nsnippet cif\n <c:if test="${${1}}">\n ${2}\n </c:if>\nsnippet cchoose\n <c:choose>\n ${1}\n </c:choose>\nsnippet cwhen\n <c:when test="${${1}}">\n ${2}\n </c:when>\nsnippet cother\n <c:otherwise>\n ${1}\n </c:otherwise>\nsnippet cfore\n <c:forEach items="${${1}}" var="${2}" varStatus="${3}">\n ${4:<c:out value="$2" />}\n </c:forEach>\nsnippet cfort\n <c:set var="${1}">${2:item1,item2,item3}</c:set>\n <c:forTokens var="${3}" items="${$1}" delims="${4:,}">\n ${5:<c:out value="$3" />}\n </c:forTokens>\nsnippet cparam\n <c:param name="${1}" value="${2}" />\nsnippet cparam+\n <c:param name="${1}" value="${2}" />\n cparam+${3}\nsnippet cimport\n <c:import url="${1}" />\nsnippet cimport+\n <c:import url="${1}">\n <c:param name="${2}" value="${3}" />\n cparam+${4}\n </c:import>\nsnippet curl\n <c:url value="${1}" var="${2}" />\n <a href="${$2}">${3}</a>\nsnippet curl+\n <c:url value="${1}" var="${2}">\n <c:param name="${4}" value="${5}" />\n cparam+${6}\n </c:url>\n <a href="${$2}">${3}</a>\nsnippet credirect\n <c:redirect url="${1}" />\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"})
|
19
src/main/webapp/lessons/ConfManagement/config.jsp
Normal file
19
src/main/webapp/lessons/ConfManagement/config.jsp
Normal file
@ -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"));
|
||||
%>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Configuration Page</title>
|
||||
</head>
|
||||
<body>
|
||||
<% response.sendRedirect(webSession.getCurrentLesson().getLink() +
|
||||
"&succeeded=yes");
|
||||
%>
|
||||
|
||||
</body>
|
||||
</html>
|
BIN
src/main/webapp/plugin_lessons/SqlStringInjection-1.0.jar
Normal file
BIN
src/main/webapp/plugin_lessons/SqlStringInjection-1.0.jar
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user