diff --git a/.travis.yml b/.travis.yml index d4c6df9f6..8559934a5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,27 +1,18 @@ language: java jdk: - - oraclejdk7 - oraclejdk8 install: "/bin/true" script: - - mvn clean install -q - - git clone -b develop https://github.com/WebGoat/WebGoat-Lessons.git - - mvn -file ./WebGoat-Lessons/pom.xml clean package -q - - cp -fa ./WebGoat-Lessons/target/plugins/*.jar ./webgoat-container/src/main/webapp/plugin_lessons/ - # Start the container this will make sure we do not see the debug logging of the Tomcat 7 Maven plugin - # which seems to always be set to DEBUG this will fail the build because we generate too much logging - - nohup bash -c "java -jar ./webgoat-standalone/target/webgoat-standalone-7.1-SNAPSHOT-exec.jar --port 8888 2>&1 &" - - if [[ $TRAVIS_PULL_REQUEST == "false" ]]; then mvn "-Dbuild.number=$TRAVIS_BUILD_NUMBER" -q clean install failsafe:integration-test; else mvn -q failsafe:integration-test; fi + - mvn clean install + - if [[ $TRAVIS_PULL_REQUEST == "false" ]]; then mvn "-Dbuild.number=$TRAVIS_BUILD_NUMBER" clean install; else mvn clean install; fi cache: directories: - $HOME/.m2 before_deploy: - export WEBGOAT_CONTAINTER_TARGET_DIR=$HOME/build/$TRAVIS_REPO_SLUG/webgoat-container/target - - export WEBGOAT_STANDALONE_TARGET_DIR=$HOME/build/$TRAVIS_REPO_SLUG/webgoat-standalone/target - export WEBGOAT_ARTIFACTS_FOLDER=$HOME/build/$TRAVIS_REPO_SLUG/Deployable_Artifacts/ - mkdir $WEBGOAT_ARTIFACTS_FOLDER - cp -fa $WEBGOAT_CONTAINTER_TARGET_DIR/* $WEBGOAT_ARTIFACTS_FOLDER/ - - cp -fa $WEBGOAT_STANDALONE_TARGET_DIR/* $WEBGOAT_ARTIFACTS_FOLDER/ - echo "Contents of artifcts folder:" - ls $WEBGOAT_ARTIFACTS_FOLDER deploy: @@ -35,11 +26,11 @@ deploy: local_dir: "$WEBGOAT_ARTIFACTS_FOLDER" on: repo: WebGoat/WebGoat - branch: develop + branch: master jdk: oraclejdk8 after_success: - - mvn versioneye:update -q - - mvn cobertura:cobertura coveralls:report -q + - mvn versioneye:update + - mvn cobertura:cobertura coveralls:report notifications: slack: secure: S9VFew5NSE8WDzYD1VDBUULKKT0fzgblQACznwQ85699b2yeX9TX58N3RZvRS1JVagVP1wu2xOrwN2g+AWx4Ro3UBZD5XG86uTJWpCLD4cRWHBoGMH2TfvI7/IzsWmgxH4MBxFRvZr/eEhlVAux+N9H4EoEdS4CKsJXEqV37PlA= @@ -47,7 +38,6 @@ env: global: - secure: "ZLZKz6lGt8YZ+NhkZPBAlI235+lEmu37Tcf+yTwh5yXuHAlnvvF6hPui7rANA/stbYGOIqIdhGOXbdrwyTU4Pvg78VwJOwsa9RtHJfou3pg4Ud9i0/dEeVl8aakmg2HDaWYGcFox8X1ViVc5UWjuBLztfJKQUEx0buJoWdMSf2E=" addons: - sauce_connect: true coverity_scan: project: name: "WebGoat/WebGoat" diff --git a/README.MD b/README.MD index 074a568c2..e018c1206 100644 --- a/README.MD +++ b/README.MD @@ -45,23 +45,35 @@ first thing that all hackers claim.* # Easy Run ( For non-developers ) Every successful build of the WebGoat Lessons Container and the WebGoat Lessons in our Continuous Integration Server -creates an "Easy Run" Executable JAR file, which contains the WebGoat Lessons Server, the lessons and a embedded Tomcat server. +creates an "Easy Run" Executable WAR file, which contains the WebGoat Lessons Server, the lessons and a embedded Tomcat server. -You can check for the "Last Modified" date of our "Easy Run" jar file [HERE](http://webgoat-war.s3-website-us-east-1.amazonaws.com/) +You can check for the "Last Modified" date of our "Easy Run" war file [HERE](http://webgoat-war.s3-website-us-east-1.amazonaws.com/) The "Easy Run" JAR file offers a no hassle approach to testing and running WebGoat. Follow these instructions if you wish to simply try/test/run the current development version of WebGoat ### Prerequisites: -* Java VM 1.8 +* Java VM 1.8 or Docker installed -## Standalone +## Easy Run Instructions: -#### 1. Download the easy run executable jar file which contains all the lessons and a embedded Tomcat server: +#### 1. Docker image + +The latest version of WebGoat is available at DockerHub, see [https://hub.docker.com/r/webgoat/webgoat-container/](https://hub.docker.com/r/webgoat/webgoat-container/). +First install Docker, then open a command shell/window and type: + +```Shell +docker pull webgoat/webgoat-container +docker run -p 8080:8080 webgoat/webgoat-container +``` + +Wait for the Docker container to start and go to step 3. + +#### 2. Download the easy run executable jar file which contains all the lessons and a embedded Tomcat server: https://s3.amazonaws.com/webgoat-war/webgoat-standalone-7.1-SNAPSHOT-exec.jar -#### 2. Run it using java: +#### 3. Run it using java: Open a command shell/window, browse to where you downloaded the easy run jar and type: @@ -106,8 +118,8 @@ Follow these instructions if you wish to run Webgoat and modify the source code ### Prerequisites: -* Java 1.8 -* Maven > 2.0.9 +* Java 8 +* Maven > 3.2.1 * Your favorite IDE, with Maven awareness: Netbeans/IntelliJ/Eclipse with m2e installed. * Git, or Git support in your IDE @@ -163,7 +175,7 @@ The __maven tomcat7:run-war__ goal runs the project in an embedded tomcat: ```Shell cd WebGoat -mvn -pl webgoat-container tomcat7:run-war +mvn -pl webgoat-container spring-boot:run ``` Browse to [http://localhost:8080/WebGoat](http://localhost:8080/WebGoat) and happy hacking ! @@ -195,18 +207,33 @@ Browse to [http://localhost:8080/WebGoat](http://localhost:8080/WebGoat) and hap ## Reloading plugins and lessons -If you want to __reload all the plugin and lessons__, open a new browser tab and visit the following url: - -[http://localhost:8080/WebGoat/service/reloadplugins.mvc](http://localhost:8080/WebGoat/service/reloadplugins.mvc) - -After the plugin reload is complete, _reloading a message_ will appear and you can refresh the __main WebGoat browser tab__. +If you want to __reload all the plugin and lessons__, open up the developer tools available from the info menu. This will +show an extra set of links below the cookie overview. ## Debugging label properties -To be able to see which labels are loaded through a property file, open a new browser tab and visit the following url: +To be able to see which labels are loaded through a property file, open up the developer tools avalailable from the info menu +After the reload is complete, all labels which are loaded from a property file will be __marked green__. -[http://localhost:8080/WebGoat/service/debug/labels.mvc](http://localhost:8080/WebGoat/service/debug/labels.mvc) -Switch back to the main WebGoat broswer tab and __reload the main WebGoat browser tab__. +## Building a new Docker image -After the reload is complete, all labels which where loaded from a property file will be __marked green__. +WebGoat now has Docker support you can build a container with the following commands: + +```Shell +cd WebGoat/ +mvn package +cd webgoat-container +mvn docker:build +docker login +docker push webgoat/webgoat-container +``` + +With the following command you are able to run the Docker container on your local machine: + +```Shell +docker run -p 8080:8080 -t webgoat/webgoat-container +docker ps +``` + +With the last command you are able to determine ip address to connect to. diff --git a/pom.xml b/pom.xml index 0b711b798..38400f79a 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.owasp.webgoat webgoat-parent pom - 7.2-SNAPSHOT + 7.1-SNAPSHOT WebGoat Parent Pom Parent Pom for the WebGoat Project. A deliberately insecure Web Application @@ -17,6 +17,12 @@ https://webgoat.github.io/ + + org.springframework.boot + spring-boot-starter-parent + 1.4.1.RELEASE + + GNU General Public License, version 2 @@ -100,6 +106,9 @@ + 1.8 + 1.8 + UTF-8 UTF-8 @@ -123,7 +132,6 @@ 3.4 1.2 4.0.0 - 1.4.2 18.0 1.4.190 1.8.0.10 @@ -146,9 +154,7 @@ 2.5.2 3.0.1 2.19 - 2.6 - 1.6.7 - 3.2.4.RELEASE + 1.6.6 2.1.20 2.48.2 1.7.12 @@ -164,7 +170,7 @@ webgoat-container - webgoat-standalone + webgoat-lessons @@ -285,6 +291,15 @@ + + + org.projectlombok + lombok + 1.16.10 + provided + + + diff --git a/webgoat-container/pom.xml b/webgoat-container/pom.xml index 740631278..61ee923b3 100644 --- a/webgoat-container/pom.xml +++ b/webgoat-container/pom.xml @@ -1,5 +1,6 @@ - + webgoat-container 4.0.0 @@ -9,111 +10,44 @@ org.owasp.webgoat webgoat-parent - 7.2-SNAPSHOT + 7.1-SNAPSHOT - - - run-integration-tests - - false - - run-integration - true - - - - - - org.apache.tomcat.maven - tomcat7-maven-plugin - 2.3-SNAPSHOT - - local_tomcat - http://localhost:8080/manager - /WebGoat - exec - true - true - ${project.basedir}/src/main/webapp/WEB-INF/context.xml - - - - org.owasp.webgoat - webgoat-container - ${project.version} - - - - - tomcat-run - - exec-war-only - - package - - - tomcat-startup - pre-integration-test - - run-war-only - - - 8888 - true - - - - - tomcat-shutdown - post-integration-test - - shutdown - - - - - - org.apache.maven.plugins - maven-failsafe-plugin - ${maven-failsafe-plugin.version} - - - file:${project.basedir}/src/test/resources/log4j-silent.properties - - - - - - integration-test - verify - - - - - - - - + + org.owasp.webgoat.WebGoat + - ${basedir}/src/main/java + src/main/java - ${basedir}/src/main/resources + src/main/resources + true + + **/application.properties + + + + src/main/resources - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin.version} + com.spotify + docker-maven-plugin + 0.4.10 - 1.7 - 1.7 - ISO-8859-1 + webgoat/${project.artifactId} + src/main/docker + + + / + ${project.build.directory} + ${project.build.finalName}.war + + @@ -130,26 +64,6 @@ - - org.apache.maven.plugins - maven-war-plugin - ${maven-war-plugin.version} - - - false - - - true - - - ${project.name} - ${project.version} - ${build.number} - - - - org.codehaus.mojo build-helper-maven-plugin @@ -172,34 +86,25 @@ - org.apache.tomcat.maven - tomcat7-maven-plugin - 2.3-SNAPSHOT + org.apache.maven.plugins + maven-resources-plugin + 2.6 - local_tomcat - http://localhost:8080/manager/text - /WebGoat - exec - true - true - ${project.basedir}/src/main/webapp/WEB-INF/context.xml + + @ + + false + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + ISO-8859-1 - - - org.owasp.webgoat - webgoat-container - ${project.version} - - - - - tomcat-run - - exec-war-only - - package - - org.apache.maven.plugins @@ -211,32 +116,102 @@ - - - - - - - - - - - - - - - - - - - - - - + + org.springframework.boot + spring-boot-maven-plugin + + + + + org.thymeleaf.extra + thymeleaf-extras-springsecurity4 + + + org.asciidoctor + asciidoctorj + + + org.jruby + jruby-complete + + + true + + + + + + + + + + + maven-clean-plugin + + + + ${project.basedir}/src/main/resources/plugin_lessons + + **/*.jar + **/*.pom + + + + ${user.home}/.webgoat/ + + **/*.jar + **/org/** + **/plugin/** + + + + + + + + org.projectlombok + lombok + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-yaml + + + org.asciidoctor + asciidoctorj + 1.5.4 + + + javax.servlet + jstl + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.thymeleaf.extras + thymeleaf-extras-springsecurity4 + 2.1.2.RELEASE + javax.activation activation @@ -267,52 +242,6 @@ axis-ant ${axis-ant.version} - - org.apache.commons - commons-lang3 - ${commons-lang3.version} - - - commons-io - commons-io - ${commons-io.version} - - - commons-collections - commons-collections - ${commons-collections.version} - - - commons-digester - commons-digester - ${commons-digester.version} - - - xml-apis - xml-apis - - - - - commons-logging - commons-logging - ${commons-logging.version} - - - org.slf4j - jcl-over-slf4j - ${jcl-over-slf4j.version} - - - commons-discovery - commons-discovery - ${commons-discovery.version} - - - javax.mail - javax.mail-api - ${mail-api.version} - hsqldb hsqldb @@ -323,92 +252,11 @@ wsdl4j ${wsdl4j.version} - - java2html - j2h - ${j2h.version} - - - ecs - ecs - ${ecs.version} - javax.transaction javax.transaction-api ${javax.transaction-api.version} - - net.sourceforge.jtds - jtds - ${jtds.version} - - - org.apache.tomcat - tomcat-catalina - ${tomcat-catalina.version} - provided - - - - - - - - javax - javaee-api - ${javaee-api.version} - provided - - - - org.springframework - spring-core - ${org.springframework.version} - - - org.springframework - spring-aop - ${org.springframework.version} - - - - - com.fasterxml.jackson.core - jackson-core - ${jackson-core.version} - - - com.fasterxml.jackson.core - jackson-databind - ${jackson-databind.version} - - - - - org.springframework - spring-webmvc - ${org.springframework.version} - jar - - - - org.springframework.security - spring-security-core - ${spring.security.version} - - - - org.springframework.security - spring-security-config - ${spring.security.version} - - - - org.springframework.security - spring-security-web - ${spring.security.version} - @@ -422,59 +270,19 @@ guava ${guava.version} - - - javax.servlet - jstl - ${jstl.version} + com.spotify + docker-maven-plugin + 0.4.10 - - taglibs - standard - ${standard.version} - - - - log4j - log4j - ${log4j.version} - - - javax.jms - jms - - - com.sun.jdmk - jmxtools - - - com.sun.jmx - jmxri - - - - - org.apache.tiles - tiles-core - ${tiles.version} - jar - - - org.slf4j - slf4j-api - ${slf4j-api.version} - jar - - - org.slf4j - slf4j-log4j12 - ${slf4j-log4j12.version} - jar - + + org.springframework.boot + spring-boot-starter-test + test + junit junit @@ -492,13 +300,9 @@ ${sauce_junit.version} test - - - - - + diff --git a/webgoat-container/src/main/docker/Dockerfile b/webgoat-container/src/main/docker/Dockerfile new file mode 100644 index 000000000..a33389017 --- /dev/null +++ b/webgoat-container/src/main/docker/Dockerfile @@ -0,0 +1,6 @@ +FROM frolvlad/alpine-oraclejdk8:slim +VOLUME /tmp +RUN cd /root; mkdir -p .webgoat +ADD webgoat-container-8.0-SNAPSHOT.war webgoat.jar +RUN sh -c 'touch /webgoat.jar' +ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/webgoat.jar"] \ No newline at end of file diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/AsciiDoctorTemplateResolver.java b/webgoat-container/src/main/java/org/owasp/webgoat/AsciiDoctorTemplateResolver.java new file mode 100644 index 000000000..1a2a8c38c --- /dev/null +++ b/webgoat-container/src/main/java/org/owasp/webgoat/AsciiDoctorTemplateResolver.java @@ -0,0 +1,108 @@ + +/** + ************************************************************************************************* + * 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. + *

+ * + * @author WebGoat + * @since December 12, 2015 + * @version $Id: $Id + */ +package org.owasp.webgoat; + +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import org.asciidoctor.Asciidoctor; +import org.thymeleaf.TemplateProcessingParameters; +import org.thymeleaf.resourceresolver.IResourceResolver; +import org.thymeleaf.templateresolver.TemplateResolver; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Optional; + +import static org.asciidoctor.Asciidoctor.Factory.create; + +/** + * Thymeleaf resolver for AsciiDoc used in the lesson, can be used as follows inside a lesson file: + * + * + *

+ * + */ +public class AsciiDoctorTemplateResolver extends TemplateResolver { + + private static final Asciidoctor asciidoctor = create(); + private static final String PREFIX = "doc:"; + private final File pluginTargetDirectory; + + public AsciiDoctorTemplateResolver(File pluginTargetDirectory) { + this.pluginTargetDirectory = pluginTargetDirectory; + setResourceResolver(new AdocResourceResolver()); + setResolvablePatterns(Sets.newHashSet(PREFIX + "*")); + } + + @Override + protected String computeResourceName(TemplateProcessingParameters params) { + String templateName = params.getTemplateName(); + return templateName.substring(PREFIX.length()); + } + + private class AdocResourceResolver implements IResourceResolver { + + @Override + public InputStream getResourceAsStream(TemplateProcessingParameters params, String resourceName) { + try { + Optional adocFile = find(pluginTargetDirectory.toPath(), resourceName); + if (adocFile.isPresent()) { + try (FileReader reader = new FileReader(adocFile.get().toFile())) { + StringWriter writer = new StringWriter(); + asciidoctor.convert(reader, writer, Maps.newHashMap()); + return new ByteArrayInputStream(writer.getBuffer().toString().getBytes()); + } + } + return new ByteArrayInputStream(new byte[0]); + } catch (IOException e) { + //no html yet + return new ByteArrayInputStream(new byte[0]); + } + } + + private Optional find(Path path, String resourceName) throws IOException { + return Files.walk(path) + .filter(Files::isRegularFile) + .filter(p -> p.toString().endsWith(resourceName)).findFirst(); + } + + @Override + public String getName() { + return "adocResourceResolver"; + } + } +} diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/Catcher.java b/webgoat-container/src/main/java/org/owasp/webgoat/Catcher.java deleted file mode 100644 index 074c61c91..000000000 --- a/webgoat-container/src/main/java/org/owasp/webgoat/Catcher.java +++ /dev/null @@ -1,120 +0,0 @@ - -package org.owasp.webgoat; - -import java.io.IOException; -import java.util.Enumeration; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.owasp.webgoat.lessons.AbstractLesson; -import org.owasp.webgoat.session.Course; -import org.owasp.webgoat.session.WebSession; - - -/** - ************************************************************************************************* - * - * - * 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. - * - * @author Bruce Mayhew WebGoat - * @since March 13, 2007 - * @version $Id: $Id - */ -public class Catcher extends HammerHead -{ - - /** - * - */ - private static final long serialVersionUID = 7441856110845727651L; - - /** - * Description of the Field - */ - public final static String START_SOURCE_SKIP = "START_OMIT_SOURCE"; - - /** Constant END_SOURCE_SKIP="END_OMIT_SOURCE" */ - public final static String END_SOURCE_SKIP = "END_OMIT_SOURCE"; - - /** Constant PROPERTY="PROPERTY" */ - public static final String PROPERTY = "PROPERTY"; - - /** Constant EMPTY_STRING="" */ - public static final String EMPTY_STRING = ""; - - /** - * {@inheritDoc} - * - * Description of the Method - * @exception IOException - * Description of the Exception - * @exception ServletException - * Description of the Exception - */ - public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException - { - try - { - // System.out.println( "Entering doPost: " ); - // System.out.println( " - request " + request); - // System.out.println( " - principle: " + request.getUserPrincipal() ); - // setCacheHeaders(response, 0); - WebSession session = (WebSession) request.getSession(true).getAttribute(WebSession.SESSION); - session.update(request, response, this.getServletName()); // FIXME: Too much in this - // call. - - int scr = session.getCurrentScreen(); - Course course = session.getCourse(); - AbstractLesson lesson = course.getLesson(session, scr, AbstractLesson.USER_ROLE); - - log(request, lesson.getClass().getName() + " | " + session.getParser().toString()); - - String property = new String(session.getParser().getStringParameter(PROPERTY, EMPTY_STRING)); - - // if the PROPERTY parameter is available - write all the parameters to the - // property file. No other control parameters are supported at this time. - if (!property.equals(EMPTY_STRING)) - { - Enumeration e = session.getParser().getParameterNames(); - - while (e.hasMoreElements()) - { - String name = (String) e.nextElement(); - String value = session.getParser().getParameterValues(name)[0]; - lesson.getLessonTracker(session).getLessonProperties().setProperty(name, value); - } - } - lesson.getLessonTracker(session).store(session, lesson); - - // BDM MC -// WEB-173 - removed for testing, as plugin architecture would not allow this -// if ( request.getParameter("Deleter") != null ){org.owasp.webgoat.lessons.BlindScript.StaticDeleter();} - - } catch (Throwable t) - { - t.printStackTrace(); - log("ERROR: " + t); - } - } -} diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/HammerHead.java b/webgoat-container/src/main/java/org/owasp/webgoat/HammerHead.java index d870a8a49..e2a09ab3a 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/HammerHead.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/HammerHead.java @@ -1,442 +1,59 @@ package org.owasp.webgoat; -import org.owasp.webgoat.lessons.AbstractLesson; -import org.owasp.webgoat.lessons.WelcomeScreen; -import org.owasp.webgoat.lessons.admin.WelcomeAdminScreen; import org.owasp.webgoat.session.Course; -import org.owasp.webgoat.session.ErrorScreen; -import org.owasp.webgoat.session.Screen; -import org.owasp.webgoat.session.UserTracker; -import org.owasp.webgoat.session.WebSession; -import org.owasp.webgoat.session.WebgoatContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import java.io.IOException; -import java.io.PrintWriter; -import java.net.URL; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; -import java.util.TimeZone; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.servlet.ModelAndView; /** * ************************************************************************************************* - * - * + *

+ *

* 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. * - * @author Jeff Williams Aspect - * Security - * @author Bruce Mayhew WebGoat - * @since October 28, 2003 + * @author Jeff Williams + * @author Bruce Mayhew + * @author Nanne Baars * @version $Id: $Id + * @since October 28, 2003 */ -public class HammerHead extends HttpServlet { +@Controller +public class HammerHead { - final Logger logger = LoggerFactory.getLogger(HammerHead.class); + private final Course course; - - /** - * - */ - private static final long serialVersionUID = 645640331343188020L; - - /** - * Description of the Field - */ - protected static SimpleDateFormat httpDateFormat; - - /** - * Set the session timeout to be 2 days - */ - private final static int sessionTimeoutSeconds = 60 * 60 * 24 * 2; - - // private final static int sessionTimeoutSeconds = 1; - /** - * Properties file path - */ - public static String propertiesPath = null; - - /** - * provides convenience methods for getting setup information from the - * ServletContext - */ - private WebgoatContext webgoatContext = null; - - /** - * {@inheritDoc} - * - * Description of the Method - * @exception IOException Description of the Exception - * @exception ServletException Description of the Exception - */ - @Override - public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { - doPost(request, response); + public HammerHead(Course course) { + this.course = course; } /** - * {@inheritDoc} - * - * Description of the Method - * @exception IOException Description of the Exception - * @exception ServletException Description of the Exception + * Entry point for WebGoat, redirects to the first lesson found within the course. */ - @Override - public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { - Screen screen = null; - - WebSession mySession = null; - try { - logger.debug("Entering doPost"); - logger.debug("request: " + request); - logger.debug("principle: " + request.getUserPrincipal()); - // setCacheHeaders(response, 0); - ServletContext context = getServletContext(); - - // FIXME: If a response is written by updateSession(), do not - // call makeScreen() and writeScreen() - mySession = updateSession(request, response, context); - - if (response.isCommitted()) { - logger.debug("Response already committed, exiting"); - return; - } - - if ("true".equals(request.getParameter("start")) || request.getQueryString() == null) { - logger.warn("Redirecting to first lesson"); - response.sendRedirect("start.mvc" + mySession.getCourse().getFirstLesson().getLink()); - return; - } - - // Note: For the lesson to track the status, we need to update - // the lesson tracker object - // from the screen.createContent() method. The create content is - // the only point - // where the lesson "knows" what has happened. To track it at a - // latter point would - // require the lesson to have memory. - screen = makeScreen(mySession); - // This calls the lesson's - // handleRequest() - if (response.isCommitted()) { - return; - } - - // perform lesson-specific tracking activities - if (screen instanceof AbstractLesson) { - AbstractLesson lesson = (AbstractLesson) screen; - - // we do not count the initial display of the lesson screen as a visit - if ("GET".equals(request.getMethod())) { - String uri = request.getRequestURI() + "?" + request.getQueryString(); - if (!uri.endsWith(lesson.getLink())) { - screen.getLessonTracker(mySession).incrementNumVisits(); - } - } else if ("POST".equals(request.getMethod()) - && mySession.getPreviousScreen() == mySession.getCurrentScreen()) { - screen.getLessonTracker(mySession).incrementNumVisits(); - } - } - - // log the access to this screen for this user - UserTracker userTracker = UserTracker.instance(); - userTracker.update(mySession, screen); - log(request, screen.getClass().getName() + " | " + mySession.getParser().toString()); - - // Redirect the request to our View servlet - String userAgent = request.getHeader("user-agent"); - String clientBrowser = "Not known!"; - if (userAgent != null) { - clientBrowser = userAgent; - } - request.setAttribute("client.browser", clientBrowser); - // removed - this is being done in updateSession call - //request.getSession().setAttribute(WebSession.SESSION, mySession); - // not sure why this is being set in the session? - //request.getSession().setAttribute(WebSession.COURSE, mySession.getCourse()); - String viewPage = getViewPage(mySession); - logger.debug("Forwarding to view: " + viewPage); - logger.debug("Screen: " + screen); - request.getRequestDispatcher(viewPage).forward(request, response); - } catch (Throwable t) { - logger.error("Error handling request", t); screen = new ErrorScreen(mySession, t); - } finally { - try { - if (screen instanceof ErrorScreen) { - this.writeScreen(mySession, screen, response); - } - } catch (Throwable thr) { - logger.error("Could not write error screen", thr); - } - WebSession.returnConnection(mySession); - logger.debug("Leaving doPost: "); - } - } - - private String getViewPage(WebSession webSession) { - // now always display the lesson content - String page = "/lesson_content.jsp"; - //page = "/main.jsp"; - return page; - } - - /** - * Description of the Method - * - * @param date Description of the Parameter - * @return RFC 1123 http date format - */ - protected static String formatHttpDate(Date date) { - synchronized (httpDateFormat) { - return httpDateFormat.format(date); - } - } - - /** - * {@inheritDoc} - * - * Return information about this servlet - */ - @Override - public String getServletInfo() { - return "WebGoat is sponsored by Aspect Security."; - } - - /** - * {@inheritDoc} - * - * Return properties path - */ - @Override - public void init() throws ServletException { - logger.info("Initializing main webgoat servlet"); - httpDateFormat = new SimpleDateFormat("EEE, dd MMM yyyyy HH:mm:ss z", Locale.US); - httpDateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); - propertiesPath = getServletContext().getRealPath("/WEB-INF/webgoat.properties"); - webgoatContext = new WebgoatContext(this); - URL runningStandalone = Thread.currentThread().getContextClassLoader().getResource("standalone.properties"); - if (runningStandalone == null) { - logger.info("Browse to http://localhost:8080/WebGoat and happy hacking!"); - } - } - - /** - * Description of the Method - * - * @param request Description of the Parameter - * @param message Description of the Parameter - */ - public void log(HttpServletRequest request, String message) { - String output = new Date() + " | " + request.getRemoteHost() + ":" + request.getRemoteAddr() + " | " + message; - log(output); - logger.debug(output); - } - - /* - * public List getLessons(Category category, String role) { Course course = - * mySession.getCourse(); // May need to clone the List before returning it. //return new - * ArrayList(course.getLessons(category, role)); return course.getLessons(category, role); } - */ - /** - * Description of the Method - * - * @param s Description of the Parameter - * @return Description of the Return Value - */ - protected Screen makeScreen(WebSession s) { - Screen screen = null; - int scr = s.getCurrentScreen(); - Course course = s.getCourse(); - - if (s.isUser() || s.isChallenge()) { - if (scr == WebSession.WELCOME) { - screen = new WelcomeScreen(s); - } else { - AbstractLesson lesson = course.getLesson(s, scr, AbstractLesson.USER_ROLE); - if (lesson == null && s.isHackedAdmin()) { - // If admin was hacked, let the user see some of the - // admin screens - lesson = course.getLesson(s, scr, AbstractLesson.HACKED_ADMIN_ROLE); - } - - if (lesson != null) { - screen = lesson; - - // We need to do some bookkeeping for the hackable admin - // interface. - // This is the only place we can tell if the user - // successfully hacked the hackable - // admin and has actually accessed an admin screen. You - // need BOTH pieces of information - // in order to satisfy the remote admin lesson. - s.setHasHackableAdmin(screen.getRole()); - - lesson.handleRequest(s); - s.setCurrentMenu(lesson.getCategory().getRanking()); - } else { - screen = new ErrorScreen(s, "Invalid screen requested. Try: http://localhost/WebGoat/attack"); - } - } - } else if (s.isAdmin()) { - if (scr == WebSession.WELCOME) { - screen = new WelcomeAdminScreen(s); - } else { - // Admin can see all roles. - // FIXME: should be able to pass a list of roles. - AbstractLesson lesson = course.getLesson(s, scr, AbstractLesson.ADMIN_ROLE); - if (lesson == null) { - lesson = course.getLesson(s, scr, AbstractLesson.HACKED_ADMIN_ROLE); - } - if (lesson == null) { - lesson = course.getLesson(s, scr, AbstractLesson.USER_ROLE); - } - - if (lesson != null) { - screen = lesson; - - // We need to do some bookkeeping for the hackable admin - // interface. - // This is the only place we can tell if the user - // successfully hacked the hackable - // admin and has actually accessed an admin screen. You - // need BOTH pieces of information - // in order to satisfy the remote admin lesson. - s.setHasHackableAdmin(screen.getRole()); - - lesson.handleRequest(s); - s.setCurrentMenu(lesson.getCategory().getRanking()); - } else { - screen = new ErrorScreen(s, - "Invalid screen requested. Try Setting Admin to false or Try: http://localhost/WebGoat/attack"); - } - } - } - - return (screen); - } - - /** - * This method sets the required expiration headers in the response for a - * given RunData object. This method attempts to set all relevant headers, - * both for HTTP 1.0 and HTTP 1.1. - * - * @param response The new cacheHeaders value - * @param expiry The new cacheHeaders value - */ - protected static void setCacheHeaders(HttpServletResponse response, int expiry) { - if (expiry == 0) { - response.setHeader("Pragma", "no-cache"); - response.setHeader("Cache-Control", "no-cache"); - response.setHeader("Expires", formatHttpDate(new Date())); - } else { - Date expiryDate = new Date(System.currentTimeMillis() + expiry); - response.setHeader("Expires", formatHttpDate(expiryDate)); - } - } - - /** - * Description of the Method - * - * @param request Description of the Parameter - * @param response Description of the Parameter - * @param context Description of the Parameter - * @return Description of the Return Value - * @throws java.io.IOException if any. - */ - protected WebSession updateSession(HttpServletRequest request, HttpServletResponse response, ServletContext context) - throws IOException { - HttpSession hs; - // session should already be created by spring security - hs = request.getSession(false); - - logger.debug("HH Entering Session_id: " + hs.getId()); - // dumpSession( hs ); - // Get our session object out of the HTTP session - WebSession session = null; - Object o = hs.getAttribute(WebSession.SESSION); - - if ((o != null) && o instanceof WebSession) { - session = (WebSession) o; - hs.setAttribute(WebSession.COURSE, session.getCourse()); - } else { - // Create new custom session and save it in the HTTP session - logger.warn("HH Creating new WebSession"); - session = new WebSession(webgoatContext, context); - // Ensure splash screen shows on any restart - // rlawson - removed this since we show splash screen at login now - //hs.removeAttribute(WELCOMED); - hs.setAttribute(WebSession.SESSION, session); - // reset timeout - hs.setMaxInactiveInterval(sessionTimeoutSeconds); - } - - session.update(request, response, this.getServletName()); - // update last attack request info (cookies, parms) - // this is so the REST services can have access to them via the session - session.updateLastAttackRequestInfo(request); - - // to authenticate - logger.debug("HH Leaving Session_id: " + hs.getId()); - //dumpSession( hs ); - return (session); - } - - /** - * Description of the Method - * - * @param s Description of the Parameter - * @param screen a {@link org.owasp.webgoat.session.Screen} object. - * @param screen a {@link org.owasp.webgoat.session.Screen} object. - * @param response Description of the Parameter - * @exception IOException Description of the Exception - * @throws java.io.IOException if any. - */ - protected void writeScreen(WebSession s, Screen screen, HttpServletResponse response) throws IOException { - response.setContentType("text/html"); - - PrintWriter out = response.getWriter(); - - if (s == null) { - screen = new ErrorScreen(s, "Page to display was null"); - } - - // set the content-length of the response. - // Trying to avoid chunked-encoding. (Aspect required) - response.setContentLength(screen.getContentLength()); - response.setHeader("Content-Length", screen.getContentLength() + ""); - - screen.output(out); - out.flush(); - out.close(); + @RequestMapping(path = "/attack", method = {RequestMethod.GET, RequestMethod.POST}) + public ModelAndView attack() { + return new ModelAndView("redirect:" + "start.mvc" + course.getFirstLesson().getLink()); } } diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/LessonSource.java b/webgoat-container/src/main/java/org/owasp/webgoat/LessonSource.java deleted file mode 100644 index 0b03e30ba..000000000 --- a/webgoat-container/src/main/java/org/owasp/webgoat/LessonSource.java +++ /dev/null @@ -1,191 +0,0 @@ -package org.owasp.webgoat; - -import java.io.IOException; -import java.io.PrintWriter; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.owasp.webgoat.lessons.AbstractLesson; -import org.owasp.webgoat.session.Course; -import org.owasp.webgoat.session.WebSession; - -/** - * ************************************************************************************************* - * - * - * 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. - * - * @author Bruce Mayhew WebGoat - * @since October 28, 2003 - * @version $Id: $Id - */ -public class LessonSource extends HammerHead { - - /** - * - */ - private static final long serialVersionUID = 2588430536196446145L; - - /** - * Description of the Field - */ - public final static String START_SOURCE_SKIP = "START_OMIT_SOURCE"; - - /** Constant END_SOURCE_SKIP="END_OMIT_SOURCE" */ - public final static String END_SOURCE_SKIP = "END_OMIT_SOURCE"; - - /** - * {@inheritDoc} - * - * Description of the Method - * @exception IOException Description of the Exception - * @exception ServletException Description of the Exception - */ - public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { - String source = null; - - try { - // System.out.println( "Entering doPost: " ); - // System.out.println( " - request " + request); - // System.out.println( " - principle: " + request.getUserPrincipal() - // ); - // setCacheHeaders(response, 0); - WebSession session = (WebSession) request.getSession(true).getAttribute(WebSession.SESSION); - // FIXME: Too much in this call. - session.update(request, response, this.getServletName()); - - boolean showSolution = session.getParser().getBooleanParameter("solution", false); - boolean showSource = session.getParser().getBooleanParameter("source", false); - if (showSolution) { - - // Get the Java solution of the lesson. - source = getSolution(session); - - int scr = session.getCurrentScreen(); - Course course = session.getCourse(); - AbstractLesson lesson = course.getLesson(session, scr, AbstractLesson.USER_ROLE); - lesson.getLessonTracker(session).setViewedSolution(true); - - } else if (showSource) { - - // Get the Java source of the lesson. FIXME: Not needed - source = getSource(session); - - int scr = session.getCurrentScreen(); - Course course = session.getCourse(); - AbstractLesson lesson = course.getLesson(session, scr, AbstractLesson.USER_ROLE); - lesson.getLessonTracker(session).setViewedSource(true); - } - } catch (Throwable t) { - t.printStackTrace(); - log("ERROR: " + t); - } finally { - try { - this.writeSource(source, response); - } catch (Throwable thr) { - thr.printStackTrace(); - log(request, "Could not write error screen: " + thr.getMessage()); - } - // System.out.println( "Leaving doPost: " ); - - } - } - - /** - * Description of the Method - * - * @param s Description of the Parameter - * @return Description of the Return Value - */ - protected String getSource(WebSession s) { - - String source = null; - int scr = s.getCurrentScreen(); - Course course = s.getCourse(); - - if (s.isUser() || s.isChallenge()) { - - AbstractLesson lesson = course.getLesson(s, scr, AbstractLesson.USER_ROLE); - - if (lesson != null) { - source = lesson.getSource(s); - } - } - if (source == null) { - return "Source code is not available. Contact " - + s.getWebgoatContext().getFeedbackAddressHTML(); - } - return (source.replaceAll("(?s)" + START_SOURCE_SKIP + ".*" + END_SOURCE_SKIP, - "Code Section Deliberately Omitted")); - } - - /** - *

getSolution.

- * - * @param s a {@link org.owasp.webgoat.session.WebSession} object. - * @return a {@link java.lang.String} object. - */ - protected String getSolution(WebSession s) { - - String source = null; - int scr = s.getCurrentScreen(); - Course course = s.getCourse(); - - if (s.isUser() || s.isChallenge()) { - - AbstractLesson lesson = course.getLesson(s, scr, AbstractLesson.USER_ROLE); - - if (lesson != null) { - source = lesson.getSolution(s); - } - } - if (source == null) { - return "Solution is not available. Contact " - + s.getWebgoatContext().getFeedbackAddressHTML(); - } - return (source); - } - - /** - * Description of the Method - * - * @param s Description of the Parameter - * @param response Description of the Parameter - * @exception IOException Description of the Exception - * @throws java.io.IOException if any. - */ - protected void writeSource(String s, HttpServletResponse response) throws IOException { - response.setContentType("text/html"); - - PrintWriter out = response.getWriter(); - - if (s == null) { - s = new String(); - } - - out.print(s); - out.close(); - } -} diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/LessonTemplateResolver.java b/webgoat-container/src/main/java/org/owasp/webgoat/LessonTemplateResolver.java new file mode 100644 index 000000000..dd23861fc --- /dev/null +++ b/webgoat-container/src/main/java/org/owasp/webgoat/LessonTemplateResolver.java @@ -0,0 +1,91 @@ +/** + ************************************************************************************************* + * + * + * 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. + * + * @author WebGoat + * @since October 28, 2003 + * @version $Id: $Id + */ +package org.owasp.webgoat; + +import com.google.common.collect.Sets; +import com.google.common.io.Files; +import org.thymeleaf.TemplateProcessingParameters; +import org.thymeleaf.resourceresolver.IResourceResolver; +import org.thymeleaf.templateresolver.TemplateResolver; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +/** + * Dynamically resolve a lesson. In the html file this can be invoked as: + * + * + *
+ *
+ * + * Thymeleaf will invoke this resolver based on the prefix and this implementqtion will resolve the html in the plugins directory + */ +public class LessonTemplateResolver extends TemplateResolver { + + private final static String PREFIX = "lesson:"; + private final File pluginTargetDirectory; + + public LessonTemplateResolver(File pluginTargetDirectory) { + this.pluginTargetDirectory = pluginTargetDirectory; + setResourceResolver(new LessonResourceResolver()); + setResolvablePatterns(Sets.newHashSet(PREFIX + "*")); + } + + @Override + protected String computeResourceName(TemplateProcessingParameters params) { + String templateName = params.getTemplateName(); + return templateName.substring(PREFIX.length()); + } + + private class LessonResourceResolver implements IResourceResolver { + + @Override + public InputStream getResourceAsStream(TemplateProcessingParameters params, String resourceName) { + File lesson = new File(pluginTargetDirectory, "/plugin/" + resourceName + "/html/" + resourceName + ".html"); + if (lesson != null) { + try { + return new ByteArrayInputStream(Files.toByteArray(lesson)); + } catch (IOException e) { + //no html yet + return new ByteArrayInputStream(new byte[0]); + } + } + return null; + } + + @Override + public String getName() { + return "lessonResourceResolver"; + } + } +} diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/MvcConfiguration.java b/webgoat-container/src/main/java/org/owasp/webgoat/MvcConfiguration.java new file mode 100644 index 000000000..02ab81b6d --- /dev/null +++ b/webgoat-container/src/main/java/org/owasp/webgoat/MvcConfiguration.java @@ -0,0 +1,124 @@ +/** + ************************************************************************************************* + * + * + * 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. + * + * @author WebGoat + * @since October 28, 2003 + * @version $Id: $Id + */ +package org.owasp.webgoat; + +import com.google.common.collect.Sets; +import org.owasp.webgoat.session.Course; +import org.owasp.webgoat.session.LabelDebugger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.thymeleaf.extras.springsecurity4.dialect.SpringSecurityDialect; +import org.thymeleaf.spring4.SpringTemplateEngine; +import org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver; +import org.thymeleaf.templateresolver.TemplateResolver; + +import java.io.File; + +/** + * Configuration for Spring MVC + */ +@Configuration +public class MvcConfiguration extends WebMvcConfigurerAdapter { + + @Autowired + @Qualifier("pluginTargetDirectory") + private File pluginTargetDirectory; + + @Override + public void addViewControllers(ViewControllerRegistry registry) { + registry.addViewController("/login").setViewName("login"); + registry.addViewController("/lesson_content").setViewName("lesson_content"); + registry.addViewController("/start.mvc").setViewName("main_new"); + } + + @Bean + public TemplateResolver springThymeleafTemplateResolver(ApplicationContext applicationContext) { + SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver(); + resolver.setPrefix("classpath:/templates/"); + resolver.setSuffix(".html"); + resolver.setOrder(1); + resolver.setApplicationContext(applicationContext); + return resolver; + } + + @Bean + public LessonTemplateResolver lessonTemplateResolver() { + LessonTemplateResolver resolver = new LessonTemplateResolver(pluginTargetDirectory); + resolver.setOrder(2); + resolver.setCacheable(false); + return resolver; + } + + @Bean + public AsciiDoctorTemplateResolver asciiDoctorTemplateResolver() { + AsciiDoctorTemplateResolver resolver = new AsciiDoctorTemplateResolver(pluginTargetDirectory); + resolver.setCacheable(true); + resolver.setOrder(3); + return resolver; + } + + @Bean + public SpringTemplateEngine thymeleafTemplateEngine(TemplateResolver springThymeleafTemplateResolver, + LessonTemplateResolver lessonTemplateResolver, + AsciiDoctorTemplateResolver asciiDoctorTemplateResolver) { + SpringTemplateEngine engine = new SpringTemplateEngine(); + engine.addDialect(new SpringSecurityDialect()); + engine.setTemplateResolvers( + Sets.newHashSet(springThymeleafTemplateResolver, lessonTemplateResolver, asciiDoctorTemplateResolver)); + return engine; + } + + /** + * This way we expose the plugins target directory as a resource within the web application. + * + * @param registry + */ + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/plugin_lessons/**").addResourceLocations("file:///" + pluginTargetDirectory.toString() + "/"); + } + + @Bean + public HammerHead hammerHead(Course course) { + return new HammerHead(course); + } + + @Bean + public LabelDebugger labelDebugger() { + return new LabelDebugger(); + } +} \ No newline at end of file diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java b/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java new file mode 100644 index 000000000..edaf68ce5 --- /dev/null +++ b/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java @@ -0,0 +1,116 @@ +/** + * ************************************************************************************************ + *

+ *

+ * 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. + * + * @author WebGoat + * @version $Id: $Id + * @since October 28, 2003 + */ +package org.owasp.webgoat; + +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.owasp.webgoat.plugins.Plugin; +import org.owasp.webgoat.plugins.PluginClassLoader; +import org.owasp.webgoat.plugins.PluginEndpointPublisher; +import org.owasp.webgoat.plugins.PluginsLoader; +import org.owasp.webgoat.session.Course; +import org.owasp.webgoat.session.UserTracker; +import org.owasp.webgoat.session.WebSession; +import org.owasp.webgoat.session.WebgoatContext; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.support.SpringBootServletInitializer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Scope; +import org.springframework.context.annotation.ScopedProxyMode; + +import java.io.File; +import java.util.List; + +@SpringBootApplication +@Slf4j +public class WebGoat extends SpringBootServletInitializer { + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(WebGoat.class); + } + + public static void main(String[] args) throws Exception { + SpringApplication.run(WebGoat.class, args); + } + + @Bean(name = "pluginTargetDirectory") + public File pluginTargetDirectory(@Value("${webgoat.user.directory}") final String webgoatHome) { + return new File(webgoatHome); + } + + @Bean + public PluginClassLoader pluginClassLoader() { + return new PluginClassLoader(PluginClassLoader.class.getClassLoader()); + } + + @Bean + public PluginsLoader pluginsLoader(@Qualifier("pluginTargetDirectory") File pluginTargetDirectory, PluginClassLoader classLoader) { + return new PluginsLoader(pluginTargetDirectory, classLoader); + } + + @Bean + @Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS) + public WebSession webSession(WebgoatContext webgoatContext) { + return new WebSession(webgoatContext); + } + + @Bean + public Course course(PluginsLoader pluginsLoader, PluginEndpointPublisher pluginEndpointPublisher) { + Course course = new Course(); + List plugins = pluginsLoader.loadPlugins(); + if (plugins.isEmpty()) { + log.error("No lessons found if you downloaded an official release of WebGoat please take the time to"); + log.error("create a new issue at https://github.com/WebGoat/WebGoat/issues/new"); + log.error("For developers run 'mvn package' first from the root directory."); + log.error("Stopping WebGoat..."); + System.exit(1); //we always run standalone + } + course.createLessonsFromPlugins(plugins); + plugins.forEach(p -> pluginEndpointPublisher.publish(p)); + + return course; + } + + @Bean + @Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS) + @SneakyThrows + public UserTracker userTracker(@Value("${webgoat.user.directory}") final String webgoatHome, WebSession webSession) { + UserTracker userTracker = new UserTracker(webgoatHome, webSession.getUserName()); + userTracker.load(); + return userTracker; + } + +} diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/WebSecurityConfig.java b/webgoat-container/src/main/java/org/owasp/webgoat/WebSecurityConfig.java new file mode 100644 index 000000000..51a9eecbf --- /dev/null +++ b/webgoat-container/src/main/java/org/owasp/webgoat/WebSecurityConfig.java @@ -0,0 +1,92 @@ + +/** + ************************************************************************************************* + * 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. + *

+ * + * @author WebGoat + * @since December 12, 2015 + * @version $Id: $Id + */ +package org.owasp.webgoat; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; +import org.springframework.security.core.userdetails.UserDetailsService; + +/** + * Security configuration for WebGoat. + */ +@Configuration +@EnableWebSecurity +public class WebSecurityConfig extends WebSecurityConfigurerAdapter { + @Override + protected void configure(HttpSecurity http) throws Exception { + ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry security = http + .authorizeRequests() + .antMatchers("/css/**", "/images/**", "/js/**", "fonts/**", "/plugins/**").permitAll() + .antMatchers("/servlet/AdminServlet/**").hasAnyRole("WEBGOAT_ADMIN", "SERVER_ADMIN") // + .antMatchers("/JavaSource/**").hasRole("SERVER_ADMIN") // + .anyRequest().hasAnyRole("WEBGOAT_USER", "WEBGOAT_ADMIN", "SERVER_ADMIN"); + security.and() + .formLogin() + .loginPage("/login") + .defaultSuccessUrl("/welcome.mvc", true) + .usernameParameter("username") + .passwordParameter("password") + .permitAll(); + security.and() + .logout() + .permitAll(); + security.and().csrf().disable(); + + http.headers().cacheControl().disable(); + } + + //// TODO: 11/18/2016 make this a little bit more configurabe last part at least + @Override + public void configure(WebSecurity web) throws Exception { + web.ignoring().antMatchers("/plugin_lessons/**", "/XXE/**"); + } + + @Autowired + public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication() + .withUser("guest").password("guest").roles("WEBGOAT_USER").and() // + .withUser("webgoat").password("webgoat").roles("WEBGOAT_ADMIN").and() // + .withUser("server").password("server").roles("SERVER_ADMIN"); + } + + @Bean + @Override + public UserDetailsService userDetailsServiceBean() throws Exception { + return super.userDetailsServiceBean(); + } +} \ No newline at end of file diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/application/Application.java b/webgoat-container/src/main/java/org/owasp/webgoat/application/Application.java deleted file mode 100644 index 7ad64dbb5..000000000 --- a/webgoat-container/src/main/java/org/owasp/webgoat/application/Application.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.owasp.webgoat.application; - -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.builder.ToStringBuilder; - -/** - * Singleton which is created on context startup - * - * @author rlawson - * @version $Id: $Id - */ -public class Application { - - private static final Application INSTANCE = new Application(); - - private Application() { - - } - - /** - *

getInstance.

- * - * @return a {@link org.owasp.webgoat.application.Application} object. - */ - public static final Application getInstance() { - return INSTANCE; - } - - private String version = "SNAPSHOT"; - private String build = "local"; - private String name = "WebGoat"; - - /** - *

Getter for the field version.

- * - * @return the version - */ - public String getVersion() { - return version; - } - - /** - *

Setter for the field version.

- * - * @param version the version to set - */ - public void setVersion(String version) { - if (StringUtils.isNotBlank(version)) { - this.version = version; - } - } - - /** - *

Getter for the field build.

- * - * @return the build - */ - public String getBuild() { - return build; - } - - /** - *

Setter for the field build.

- * - * @param build the build to set - */ - public void setBuild(String build) { - if (StringUtils.isNotBlank(build)) { - this.build = build; - } - } - - /** - *

Getter for the field name.

- * - * @return the name - */ - public String getName() { - return name; - } - - /** - *

Setter for the field name.

- * - * @param name the name to set - */ - public void setName(String name) { - if (StringUtils.isNotBlank(name)) { - this.name = name; - } - } - - /** {@inheritDoc} */ - @Override - public String toString() { - return new ToStringBuilder(this). - append("name", name). - append("version", version). - append("build", build). - toString(); - } -} diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/application/WebGoatServletListener.java b/webgoat-container/src/main/java/org/owasp/webgoat/application/WebGoatServletListener.java deleted file mode 100644 index 7999387e0..000000000 --- a/webgoat-container/src/main/java/org/owasp/webgoat/application/WebGoatServletListener.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.owasp.webgoat.application; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Paths; -import java.sql.Driver; -import java.sql.DriverManager; -import java.sql.SQLException; -import java.util.Enumeration; -import java.util.Set; -import java.util.jar.Attributes; -import java.util.jar.Manifest; - -import javax.servlet.ServletContext; -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; -import javax.servlet.ServletRegistration; - -import org.owasp.webgoat.HammerHead; -import org.owasp.webgoat.lessons.LessonServletMapping; -import org.owasp.webgoat.plugins.PluginsLoader; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; -import org.springframework.core.type.filter.AnnotationTypeFilter; - -/** - * Web application lifecycle listener. - * - * @author rlawson - * @version $Id: $Id - */ -public class WebGoatServletListener implements ServletContextListener { - - private static final Logger logger = LoggerFactory.getLogger(HammerHead.class); - - /** {@inheritDoc} */ - @Override - public void contextInitialized(ServletContextEvent sce) { - ServletContext context = sce.getServletContext(); - context.log("WebGoat is starting"); - setApplicationVariables(context); - context.log("Adding extra mappings for lessions"); - - loadPlugins(sce); - loadServlets(sce); - } - - private void loadServlets(ServletContextEvent sce) { - final ServletContext servletContext = sce.getServletContext(); - ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider( - false); - provider.addIncludeFilter(new AnnotationTypeFilter(LessonServletMapping.class)); - Set candidateComponents = provider.findCandidateComponents("org.owasp.webgoat"); - try { - for (BeanDefinition beanDefinition : candidateComponents) { - Class controllerClass = Class.forName(beanDefinition.getBeanClassName()); - LessonServletMapping pathAnnotation = (LessonServletMapping) controllerClass.getAnnotation(LessonServletMapping.class); - final ServletRegistration.Dynamic dynamic = servletContext.addServlet(controllerClass.getSimpleName(), controllerClass); - dynamic.addMapping(pathAnnotation.path()); - } - } catch (Exception e) { - logger.error("Error", e); - } - } - - private void loadPlugins(ServletContextEvent sce) { - String pluginPath = sce.getServletContext().getRealPath("plugin_lessons"); - String targetPath = sce.getServletContext().getRealPath("plugin_extracted"); - new PluginsLoader(Paths.get(pluginPath), Paths.get(targetPath)).loadPlugins(); - } - - /** {@inheritDoc} */ - @Override - public void contextDestroyed(ServletContextEvent sce) { - ServletContext context = sce.getServletContext(); - context.log("WebGoat is stopping"); - - // Unregister JDBC drivers in this context's ClassLoader: - // Get the webapp's ClassLoader - ClassLoader cl = Thread.currentThread().getContextClassLoader(); - // Loop through all drivers - Enumeration drivers = DriverManager.getDrivers(); - while (drivers.hasMoreElements()) { - java.sql.Driver driver = drivers.nextElement(); - if (driver.getClass().getClassLoader() == cl) { - // This driver was registered by the webapp's ClassLoader, so deregister it: - try { - context.log("Unregister JDBC driver {}"); - DriverManager.deregisterDriver(driver); - } catch (SQLException ex) { - context.log("Error unregistering JDBC driver {}"); - } - } else { - // driver was not registered by the webapp's ClassLoader and may be in use elsewhere - context.log("Not unregistering JDBC driver {} as it does not belong to this webapp's ClassLoader"); - } - } - } - - private void setApplicationVariables(ServletContext context) { - Application app = Application.getInstance(); - try { - InputStream inputStream = context.getResourceAsStream("/META-INF/MANIFEST.MF"); - Manifest manifest = new Manifest(inputStream); - Attributes attr = manifest.getMainAttributes(); - String name = attr.getValue("Specification-Title"); - String version = attr.getValue("Specification-Version"); - String build = attr.getValue("Implementation-Version"); - app.setName(name); - app.setVersion(version); - app.setBuild(build); - } catch (IOException ioe) { - context.log("Error setting application variables", ioe); - } - } -} diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/controller/About.java b/webgoat-container/src/main/java/org/owasp/webgoat/controller/About.java deleted file mode 100644 index 094d9285f..000000000 --- a/webgoat-container/src/main/java/org/owasp/webgoat/controller/About.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.owasp.webgoat.controller; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.servlet.ModelAndView; - -/** - *

About class.

- * - * @author rlawson - * @version $Id: $Id - */ -@Controller -public class About { - - final Logger logger = LoggerFactory.getLogger(About.class); - private static final String WELCOMED = "welcomed"; - - /** - *

welcome.

- * - * @param request a {@link javax.servlet.http.HttpServletRequest} object. - * @param error a {@link java.lang.String} object. - * @param logout a {@link java.lang.String} object. - * @return a {@link org.springframework.web.servlet.ModelAndView} object. - */ - @RequestMapping(value = "about.mvc", method = RequestMethod.GET) - public ModelAndView welcome(HttpServletRequest request, - @RequestParam(value = "error", required = false) String error, - @RequestParam(value = "logout", required = false) String logout) { - - // set the welcome attribute - // this is so the attack servlet does not also - // send them to the welcome page - HttpSession session = request.getSession(); - if (session.getAttribute(WELCOMED) == null) { - session.setAttribute(WELCOMED, "true"); - } - - //go ahead and send them to webgoat (skip the welcome page) - ModelAndView model = new ModelAndView(); - //model.setViewName("welcome"); - //model.setViewName("main_new"); - model.setViewName("about"); - return model; - } - -} diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/controller/Login.java b/webgoat-container/src/main/java/org/owasp/webgoat/controller/Login.java deleted file mode 100644 index 6f9021f19..000000000 --- a/webgoat-container/src/main/java/org/owasp/webgoat/controller/Login.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.owasp.webgoat.controller; - -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.servlet.ModelAndView; - -/** - *

Login class.

- * - * @author rlawson - * @version $Id: $Id - */ -@Controller -public class Login { - - /** - *

login.

- * - * @param error a {@link java.lang.String} object. - * @param logout a {@link java.lang.String} object. - * @return a {@link org.springframework.web.servlet.ModelAndView} object. - */ - @RequestMapping(value = "login.mvc", method = RequestMethod.GET) - public ModelAndView login( - @RequestParam(value = "error", required = false) String error, - @RequestParam(value = "logout", required = false) String logout) { - - ModelAndView model = new ModelAndView(); - if (error != null) { - model.addObject("error", "Invalid username and password!"); - } - - if (logout != null) { - model.addObject("msg", "You've been logged out successfully."); - } - model.setViewName("login"); - - return model; - - } -} diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/controller/Logout.java b/webgoat-container/src/main/java/org/owasp/webgoat/controller/Logout.java deleted file mode 100644 index 92e236a1c..000000000 --- a/webgoat-container/src/main/java/org/owasp/webgoat/controller/Logout.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.owasp.webgoat.controller; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.servlet.ModelAndView; - -/** - *

Logout class.

- * - * @author rlawson - * @version $Id: $Id - */ -@Controller -public class Logout { - - final Logger logger = LoggerFactory.getLogger(Logout.class); - - /** - *

logout.

- * - * @param error a {@link java.lang.String} object. - * @param logout a {@link java.lang.String} object. - * @return a {@link org.springframework.web.servlet.ModelAndView} object. - */ - @RequestMapping(value = "logout.mvc", method = RequestMethod.GET) - public ModelAndView logout( - @RequestParam(value = "error", required = false) String error, - @RequestParam(value = "logout", required = false) String logout) { - - logger.info("Logging user out"); - - ModelAndView model = new ModelAndView(); - if (error != null) { - model.addObject("error", "Invalid username and password!"); - } - - if (logout != null) { - model.addObject("msg", "You've been logged out successfully."); - } - model.setViewName("logout"); - - return model; - - } -} diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/controller/Start.java b/webgoat-container/src/main/java/org/owasp/webgoat/controller/Start.java deleted file mode 100644 index 300209a9d..000000000 --- a/webgoat-container/src/main/java/org/owasp/webgoat/controller/Start.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.owasp.webgoat.controller; - -import java.util.Collection; -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; -import org.apache.commons.lang3.StringUtils; -import org.owasp.webgoat.application.Application; -import org.owasp.webgoat.session.WebSession; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.servlet.ModelAndView; - -/** - *

Start class.

- * - * @author rlawson - * @version $Id: $Id - */ -@Controller -public class Start { - - final Logger logger = LoggerFactory.getLogger(Start.class); - - private static final String WELCOMED = "welcomed"; - - @Autowired - private ServletContext servletContext; - - /** - *

start.

- * - * @param request a {@link javax.servlet.http.HttpServletRequest} object. - * @param error a {@link java.lang.String} object. - * @param logout a {@link java.lang.String} object. - * @return a {@link org.springframework.web.servlet.ModelAndView} object. - */ - @RequestMapping(value = "start.mvc", method = {RequestMethod.GET, RequestMethod.POST}) - public ModelAndView start(HttpServletRequest request, - @RequestParam(value = "error", required = false) String error, - @RequestParam(value = "logout", required = false) String logout) { - - ModelAndView model = new ModelAndView(); - // make sure session is set up correctly - // if not redirect user to login - if (checkWebSession(request.getSession()) == false) { - model.setViewName("redirect:/login.mvc"); - return model; - } - String role = getRole(); - String user = request.getUserPrincipal().getName(); - model.addObject("role", role); - model.addObject("user", user); - - String contactEmail = servletContext.getInitParameter("email"); - model.addObject("contactEmail", contactEmail); - String emailList = servletContext.getInitParameter("emaillist"); - model.addObject("emailList", emailList); - - Application app = Application.getInstance(); - logger.info("Setting application properties: " + app); - model.addObject("version", app.getVersion()); - model.addObject("build", app.getBuild()); - - // if everything ok then go to webgoat UI - model.setViewName("main_new"); - return model; - } - - private String getRole() { - Collection authorities = (Collection) SecurityContextHolder.getContext().getAuthentication().getAuthorities(); - String role = "N/A"; - for (GrantedAuthority authority : authorities) { - authority.getAuthority(); - role = authority.getAuthority(); - role = StringUtils.lowerCase(role); - role = StringUtils.remove(role, "role_"); - break; - } - return role; - } - - /** - *

checkWebSession.

- * - * @param session a {@link javax.servlet.http.HttpSession} object. - * @return a boolean. - */ - public boolean checkWebSession(HttpSession session) { - Object o = session.getAttribute(WebSession.SESSION); - if (o == null) { - logger.error("No valid WebSession object found, has session timed out? [" + session.getId() + "]"); - return false; - } - if (!(o instanceof WebSession)) { - logger.error("Invalid WebSession object found, this is probably a bug! [" + o.getClass() + " | " + session.getId() + "]"); - return false; - } - return true; - } -} diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/controller/StartLesson.java b/webgoat-container/src/main/java/org/owasp/webgoat/controller/StartLesson.java new file mode 100644 index 000000000..6af1770f3 --- /dev/null +++ b/webgoat-container/src/main/java/org/owasp/webgoat/controller/StartLesson.java @@ -0,0 +1,93 @@ +/** + * ************************************************************************************************ + *

+ *

+ * 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. + * + * @author WebGoat + * @version $Id: $Id + * @since October 28, 2003 + */ +package org.owasp.webgoat.controller; + +import org.owasp.webgoat.lessons.AbstractLesson; +import org.owasp.webgoat.session.Course; +import org.owasp.webgoat.session.WebSession; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.servlet.ModelAndView; + +import javax.servlet.http.HttpServletRequest; +import java.util.List; +import java.util.Optional; + + +@Controller +public class StartLesson { + + private final WebSession ws; + private final Course course; + + public StartLesson(final WebSession ws, final Course course) { + this.ws = ws; + this.course = course; + } + + /** + *

start.

+ * + * @return a {@link ModelAndView} object. + */ + @RequestMapping(path = "startlesson.mvc", method = {RequestMethod.GET, RequestMethod.POST}) + public ModelAndView start() { + ModelAndView model = new ModelAndView(); + + model.addObject("course", course); + model.addObject("lesson", ws.getCurrentLesson()); + model.setViewName("lesson_content"); + return model; + } + + @RequestMapping(value = {"*.lesson"}, produces = "text/html") + public ModelAndView lessonPage(HttpServletRequest request) { + // I will set here the thymeleaf fragment location based on the resource requested. + ModelAndView model = new ModelAndView(); + SecurityContext context = SecurityContextHolder.getContext(); //TODO this should work with the security roles of Spring + GrantedAuthority authority = context.getAuthentication().getAuthorities().iterator().next(); + String path = request.getServletPath(); // we now got /a/b/c/AccessControlMatrix.lesson + String lessonName = path.substring(path.lastIndexOf('/') + 1, path.indexOf(".lesson")); + List lessons = course.getLessons(); + Optional lesson = lessons.stream() + .filter(l -> l.getId().equals(lessonName)) + .findFirst(); + ws.setCurrentLesson(lesson.get()); + model.setViewName("lesson_content"); + model.addObject("lesson", lesson.get()); + return model; + } + +} diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/controller/Welcome.java b/webgoat-container/src/main/java/org/owasp/webgoat/controller/Welcome.java index 050b0a79f..546b1f992 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/controller/Welcome.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/controller/Welcome.java @@ -1,20 +1,43 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. +/** + ************************************************************************************************* + * + * + * 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. + * + * @author WebGoat + * @since October 28, 2003 + * @version $Id: $Id */ package org.owasp.webgoat.controller; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.ModelAndView; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + /** *

Welcome class.

* @@ -23,22 +46,17 @@ import org.springframework.web.servlet.ModelAndView; */ @Controller public class Welcome { - - final Logger logger = LoggerFactory.getLogger(Welcome.class); + private static final String WELCOMED = "welcomed"; /** *

welcome.

* * @param request a {@link javax.servlet.http.HttpServletRequest} object. - * @param error a {@link java.lang.String} object. - * @param logout a {@link java.lang.String} object. * @return a {@link org.springframework.web.servlet.ModelAndView} object. */ - @RequestMapping(value = "welcome.mvc", method = RequestMethod.GET) - public ModelAndView welcome(HttpServletRequest request, - @RequestParam(value = "error", required = false) String error, - @RequestParam(value = "logout", required = false) String logout) { + @RequestMapping(path = "welcome.mvc", method = RequestMethod.GET) + public ModelAndView welcome(HttpServletRequest request) { // set the welcome attribute // this is so the attack servlet does not also diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/util/LabelManager.java b/webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelManager.java similarity index 98% rename from webgoat-container/src/main/java/org/owasp/webgoat/util/LabelManager.java rename to webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelManager.java index a0f42adc9..21990bf6e 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/util/LabelManager.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelManager.java @@ -1,5 +1,5 @@ -package org.owasp.webgoat.util; +package org.owasp.webgoat.i18n; import java.util.Locale; diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/util/LabelManagerImpl.java b/webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelManagerImpl.java similarity index 81% rename from webgoat-container/src/main/java/org/owasp/webgoat/util/LabelManagerImpl.java rename to webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelManagerImpl.java index f98b1a981..0e3ed00c4 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/util/LabelManagerImpl.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelManagerImpl.java @@ -1,8 +1,7 @@ -package org.owasp.webgoat.util; +package org.owasp.webgoat.i18n; import org.owasp.webgoat.session.LabelDebugger; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.io.Serializable; @@ -38,30 +37,22 @@ import java.util.Locale; * @version $Id: $Id * @author dm */ -@Component("labelManager") +@Component public class LabelManagerImpl implements LabelManager, Serializable { private static final long serialVersionUID = 1L; - @Autowired - private transient LabelProvider labelProvider; - @Autowired + private LabelProvider labelProvider; private LabelDebugger labelDebugger; - - /** Locale mapped with current session. */ private Locale locale = new Locale(LabelProvider.DEFAULT_LANGUAGE); - /** - *

Constructor for LabelManagerImpl.

- */ - protected LabelManagerImpl() {} - /** *

Constructor for LabelManagerImpl.

* - * @param labelProvider a {@link org.owasp.webgoat.util.LabelProvider} object. + * @param labelProvider a {@link LabelProvider} object. */ - protected LabelManagerImpl(LabelProvider labelProvider) { + protected LabelManagerImpl(LabelProvider labelProvider, LabelDebugger labelDebugger) { + this.labelDebugger = labelDebugger; this.labelProvider = labelProvider; } diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/util/LabelProvider.java b/webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelProvider.java similarity index 98% rename from webgoat-container/src/main/java/org/owasp/webgoat/util/LabelProvider.java rename to webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelProvider.java index 674699c01..c1fa62ae0 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/util/LabelProvider.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelProvider.java @@ -1,5 +1,5 @@ -package org.owasp.webgoat.util; +package org.owasp.webgoat.i18n; import org.springframework.context.support.ReloadableResourceBundleMessageSource; import org.springframework.core.io.Resource; @@ -7,7 +7,6 @@ import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.UrlResource; import org.springframework.stereotype.Component; -import javax.inject.Singleton; import java.net.MalformedURLException; import java.nio.file.Path; import java.util.Arrays; @@ -47,7 +46,6 @@ import java.util.Locale; * @author dm */ @Component -@Singleton public class LabelProvider { /** Constant DEFAULT_LANGUAGE="Locale.ENGLISH.getLanguage()" */ public final static String DEFAULT_LANGUAGE = Locale.ENGLISH.getLanguage(); diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java index b209a88cf..4648c0335 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java @@ -1,45 +1,15 @@ package org.owasp.webgoat.lessons; -import org.apache.ecs.Element; -import org.apache.ecs.ElementContainer; -import org.apache.ecs.StringElement; -import org.apache.ecs.html.Body; -import org.apache.ecs.html.Form; -import org.apache.ecs.html.Head; -import org.apache.ecs.html.Html; -import org.apache.ecs.html.IMG; -import org.apache.ecs.html.PRE; -import org.apache.ecs.html.Title; -import org.owasp.webgoat.session.ParameterNotFoundException; +import lombok.Getter; +import lombok.Setter; import org.owasp.webgoat.session.Screen; -import org.owasp.webgoat.session.WebSession; -import org.owasp.webgoat.session.WebgoatContext; -import org.owasp.webgoat.session.WebgoatProperties; -import org.owasp.webgoat.util.BeanProvider; -import org.owasp.webgoat.util.LabelManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import java.io.BufferedReader; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.InputStreamReader; -import java.io.StringReader; -import java.net.HttpURLConnection; -import java.net.URL; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.HashMap; -import java.util.LinkedList; import java.util.List; -import java.util.Map; - -import static java.lang.Math.abs; /** * ************************************************************************************************ *

+ *

* This file is part of WebGoat, an Open Web Application Security Project utility. For details, * please see http://www.owasp.org/ *

@@ -68,66 +38,24 @@ import static java.lang.Math.abs; */ public abstract class AbstractLesson extends Screen implements Comparable { - private static final Logger logger = LoggerFactory.getLogger(AbstractLesson.class); - - /** - * Description of the Field - */ - public final static String ADMIN_ROLE = "admin"; - - /** - * Constant CHALLENGE_ROLE="challenge" - */ - public final static String CHALLENGE_ROLE = "challenge"; - - /** - * Description of the Field - */ - public final static String HACKED_ADMIN_ROLE = "hacked_admin"; - - /** - * Description of the Field - */ - public final static String USER_ROLE = "user"; - private static int count = 1; private Integer id = null; - final static IMG nextGrey = new IMG("images/right16.gif").setAlt("Next").setBorder(0).setHspace(0).setVspace(0); - - final static IMG previousGrey = new IMG("images/left14.gif").setAlt("Previous").setBorder(0).setHspace(0) - .setVspace(0); - private Integer ranking; - private Category category; - - private boolean hidden; - - private String sourceFileName; - - private Map lessonPlanFileName = new HashMap(); - - private String lessonSolutionFileName; - - private WebgoatContext webgoatContext; - - private LinkedList availableLanguages = new LinkedList(); - - private String defaultLanguage = "en"; - - private LabelManager labelManager = null; + @Setter + @Getter + private List> assignments; /** * Constructor for the Lesson object */ public AbstractLesson() { - //based on the class name derive an id so the screenId is fixed, should not give clashes based on - //the fact we use the classname and the size is limited - id = abs(this.getClass().getSimpleName().hashCode()); + id = new Integer(++count); } + /** *

getName.

* @@ -147,46 +75,6 @@ public abstract class AbstractLesson extends Screen implements ComparableSetter for the field hidden.

- * - * @param hidden a boolean. - */ - public void setHidden(boolean hidden) { - this.hidden = hidden; - } - - /** - *

update.

- * - * @param properties a {@link org.owasp.webgoat.session.WebgoatProperties} object. - */ - public void update(WebgoatProperties properties) { - String className = getClass().getName(); - className = className.substring(className.lastIndexOf(".") + 1); - setRanking(new Integer(properties.getIntProperty("lesson." + className + ".ranking", getDefaultRanking() - .intValue()))); - String categoryRankingKey = "category." + getDefaultCategory().getName() + ".ranking"; - // System.out.println("Category ranking key: " + categoryRankingKey); - Category tempCategory = Category.getCategory(getDefaultCategory().getName()); - tempCategory.setRanking(new Integer(properties.getIntProperty(categoryRankingKey, getDefaultCategory() - .getRanking().intValue()))); - category = tempCategory; - setHidden(properties.getBooleanProperty("lesson." + className + ".hidden", getDefaultHidden())); - // System.out.println(className + " in " + tempCategory.getName() + " - // (Category Ranking: " + tempCategory.getRanking() + " Lesson ranking: - // " + getRanking() + ", hidden:" + hidden +")"); - } - - /** - *

isCompleted.

- * - * @param s a {@link org.owasp.webgoat.session.WebSession} object. - * @return a boolean. - */ - public boolean isCompleted(WebSession s) { - return getLessonTracker(s, this).getCompleted(); - } /** * {@inheritDoc} @@ -212,7 +100,7 @@ public abstract class AbstractLesson extends Screen implements ComparablegetHints.

* - * @param s a {@link org.owasp.webgoat.session.WebSession} object. * @return a {@link java.util.List} object. */ - protected abstract List getHints(WebSession s); - - // @TODO we need to restrict access at the service layer - // rather than passing session object around - - /** - *

getHintsPublic.

- * - * @param s a {@link org.owasp.webgoat.session.WebSession} object. - * @return a {@link java.util.List} object. - */ - public List getHintsPublic(WebSession s) { - List hints = getHints(s); - return hints; - } - - /** - * Fill in a minor hint that will help people who basically get it, but are - * stuck on somthing silly. - * - * @param s The users WebSession - * @param hintNumber a int. - * @return The hint1 value - */ - public String getHint(WebSession s, int hintNumber) { - return "Hint: " + getHints(s).get(hintNumber); - } - - /** - * Gets the instructions attribute of the AbstractLesson object - * - * @param s a {@link org.owasp.webgoat.session.WebSession} object. - * @return The instructions value - */ - public abstract String getInstructions(WebSession s); - - /** - * Gets the lessonPlan attribute of the Lesson object - * - * @return The lessonPlan value - */ - public String getLessonName() { - return this.getClass().getSimpleName(); - } + public abstract List getHints(); /** * Gets the title attribute of the HelloScreen object @@ -421,36 +154,6 @@ public abstract class AbstractLesson extends Screen implements Comparable