Adjust lesson template (#704)
* Remove method `getId()` from all lessons as it defaults to the class name * remove clean up endpoint * remove unused class `RequestParameter` * remove unused class `PluginLoadingFailure` * Move `CourseConfiguration` to lesson package * Add more content around the lesson template lesson and make it visible as a lesson in WebGoat * Remove explicit invocation `trackProgress()` inside WebGoat framework so assignments only need to return an `AttackResult` * Put original solution back as well for SQL string injection * review comments * Add
This commit is contained in:
committed by
René Zubcevic
parent
f40b6ffd31
commit
5dd6b31905
@ -22,17 +22,13 @@ There are a number of moving parts and this sample lesson will help you navigate
|
||||
```
|
||||
1. The Base Class
|
||||
|
||||
* The name of the class (file and class name) to better match your lesson. (e.g. `sql-injection` >> `SqlInjection`)
|
||||
* The category in which you want your lesson to be in. You can create a new category if you want, or put in an issue to have one added.
|
||||
* The `defaultRanking` will move your lesson up or down in the categories list.
|
||||
* The name of the class (file and class name) to better match your lesson. (e.g. `sql-injection` >> `SqlInjection`)
|
||||
* The category in which you want your lesson to be in. You can create a new category if you want, or put in an issue to have one added.
|
||||
* Implement a new key name pair `lesson-template.title` (the key) and update the same key/value pair `your.key=your value` in src/main/resources/i18n/WebGoatLabels.properties.
|
||||
* Implement a new value for the `getId` method, which leads us to...
|
||||
|
||||
2. The HTML content framing
|
||||
|
||||
* Rename the provided file in src/main/resources/html using your value from the `getId` method in your lesson's base class:
|
||||
e.g.
|
||||
`public String getId() { return "your-lesson"; }` >> `your-lesson.html`
|
||||
* Rename the provided file in src/main/resources/html using the name of the lesson class.
|
||||
* Modify that file following the commented instructions in there.
|
||||
* In conjunction with this file you.
|
||||
|
||||
@ -41,7 +37,6 @@ There are a number of moving parts and this sample lesson will help you navigate
|
||||
* You can also create supporting (non-assignment) endpoints, that are not evaluated/graded.
|
||||
* See other lesson examples for creating unit/integration tests for your project as well.
|
||||
|
||||
|
||||
4. Getting your lesson to show up
|
||||
|
||||
* Modify the webgoat-lessons/pom.xml to include your project in the `<modules>` section:
|
||||
@ -63,8 +58,8 @@ There are a number of moving parts and this sample lesson will help you navigate
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<!-- .... >
|
||||
</dependencies>
|
||||
```
|
||||
</dependencies>
|
||||
```
|
||||
|
||||
|
||||
5. You should be ready to run and test your project. Please create issues at https://github.com/WebGoat/WebGoat if there errors or confusion with this documentation/template
|
||||
|
@ -1,38 +1,31 @@
|
||||
/*
|
||||
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
|
||||
*
|
||||
* Copyright (c) 2002 - 2019 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.
|
||||
*/
|
||||
|
||||
package org.owasp.webgoat.template;
|
||||
|
||||
import org.owasp.webgoat.lessons.Category;
|
||||
import org.owasp.webgoat.lessons.Lesson;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* ************************************************************************************************
|
||||
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
|
||||
* please see http://www.owasp.org/
|
||||
* <p>
|
||||
* Copyright (c) 2002 - 20014 Bruce Mayhew
|
||||
* <p>
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
* <p>
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||||
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
* <p>
|
||||
* You should have received a copy of the GNU General Public License along with this program; if
|
||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
* <p>
|
||||
* Getting Source ==============
|
||||
* <p>
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
|
||||
* projects.
|
||||
* <p>
|
||||
*
|
||||
* @author misfir3
|
||||
* @version $Id: $Id
|
||||
* @since January 3, 2017
|
||||
*/
|
||||
@Component
|
||||
public class LessonTemplate extends Lesson {
|
||||
|
||||
@ -45,10 +38,4 @@ public class LessonTemplate extends Lesson {
|
||||
public String getTitle() {
|
||||
return "lesson-template.title";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "LessonTemplate";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,24 +22,22 @@
|
||||
|
||||
package org.owasp.webgoat.template;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.owasp.webgoat.assignments.AssignmentEndpoint;
|
||||
import org.owasp.webgoat.assignments.AssignmentHints;
|
||||
import org.owasp.webgoat.assignments.AttackResult;
|
||||
import org.owasp.webgoat.session.UserSessionData;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by jason on 1/5/17.
|
||||
*/
|
||||
|
||||
@RestController
|
||||
@AssignmentHints({"lesson-template.hints.1", "lesson-template.hints.2", "lesson-template.hints.3"})
|
||||
public class SampleAttack extends AssignmentEndpoint {
|
||||
|
||||
String secretValue = "secr37Value";
|
||||
@ -48,28 +46,40 @@ public class SampleAttack extends AssignmentEndpoint {
|
||||
@Autowired
|
||||
UserSessionData userSessionData;
|
||||
|
||||
|
||||
@GetMapping(path = "/lesson-template/sample-attack", produces = {"application/json"})
|
||||
public @ResponseBody
|
||||
AttackResult completed(String param1, String param2, HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
@PostMapping("/lesson-template/sample-attack")
|
||||
@ResponseBody
|
||||
public AttackResult completed(@RequestParam("param1") String param1, @RequestParam("param2") String param2) {
|
||||
if (userSessionData.getValue("some-value") != null) {
|
||||
// do any session updating you want here ... or not, just comment/example here
|
||||
//return trackProgress(failed().feedback("lesson-template.sample-attack.failure-2").build());
|
||||
//return failed().feedback("lesson-template.sample-attack.failure-2").build());
|
||||
}
|
||||
|
||||
//overly simple example for success. See other existing lesssons for ways to detect 'success' or 'failure'
|
||||
if (secretValue.equals(param1)) {
|
||||
return trackProgress(success()
|
||||
return success(this)
|
||||
.output("Custom Output ...if you want, for success")
|
||||
.feedback("lesson-template.sample-attack.success")
|
||||
.build());
|
||||
.build();
|
||||
//lesson-template.sample-attack.success is defined in src/main/resources/i18n/WebGoatLabels.properties
|
||||
}
|
||||
|
||||
// else
|
||||
return trackProgress(failed()
|
||||
return failed(this)
|
||||
.feedback("lesson-template.sample-attack.failure-2")
|
||||
.output("Custom output for this failure scenario, usually html that will get rendered directly ... yes, you can self-xss if you want")
|
||||
.build());
|
||||
.build();
|
||||
}
|
||||
|
||||
@GetMapping("lesson-template/shop/{user}")
|
||||
@ResponseBody
|
||||
public List<Item> getItemsInBasket(@PathVariable("user") String user) {
|
||||
return List.of(new Item("WG-1", "WebGoat promo", 12.0), new Item("WG-2", "WebGoat sticker", 0.00));
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
private class Item {
|
||||
private String number;
|
||||
private String description;
|
||||
private double price;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,13 @@
|
||||
--CREATE TABLE servers(
|
||||
-- id varchar(10),
|
||||
-- hostname varchar(20),
|
||||
-- ip varchar(20),
|
||||
-- mac varchar(20),
|
||||
-- status varchar(20),
|
||||
-- description varchar(40)
|
||||
--);
|
||||
--INSERT INTO servers VALUES ('1', 'webgoat-dev', '192.168.4.0', 'AA:BB:11:22:CC:DD', 'online', 'Development server');
|
||||
--INSERT INTO servers VALUES ('2', 'webgoat-tst', '192.168.2.1', 'EE:FF:33:44:AB:CD', 'online', 'Test server');
|
||||
--INSERT INTO servers VALUES ('3', 'webgoat-acc', '192.168.3.3', 'EF:12:FE:34:AA:CC', 'offline', 'Acceptance server');
|
||||
--INSERT INTO servers VALUES ('4', 'webgoat-pre-prod', '192.168.6.4', 'EF:12:FE:34:AA:CC', 'offline', 'Pre-production server');
|
||||
--INSERT INTO servers VALUES ('4', 'webgoat-prd', '104.130.219.202', 'FA:91:EB:82:DC:73', 'out of order', 'Production server');
|
@ -7,12 +7,34 @@
|
||||
<div class="adoc-content" th:replace="doc:lesson-template-intro.adoc"></div>
|
||||
</div>
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
<!-- reuse the above lesson-page-wrapper block for each 'page' of content in your lesson -->
|
||||
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
|
||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
||||
<div class="adoc-content" th:replace="doc:lesson-template-content.adoc"></div>
|
||||
</div>
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
<!-- reuse the above lesson-page-wrapper block for each 'page' of content in your lesson -->
|
||||
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
|
||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
||||
<div class="adoc-content" th:replace="doc:lesson-template-video.adoc"></div>
|
||||
<!-- can use multiple adoc's in a page-wrapper if you want ... or not-->
|
||||
<div class="adoc-content" th:replace="doc:lesson-template-video-more.adoc"></div>
|
||||
</div>
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
<div class="adoc-content" th:replace="doc:lesson-template-lesson-class.adoc"></div>
|
||||
</div>
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
<div class="adoc-content" th:replace="doc:lesson-template-glue.adoc"></div>
|
||||
</div>
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
<!-- reuse the above lesson-page-wrapper block for each 'page' of content in your lesson -->
|
||||
<!-- include content here, or can be placed in another location. Content will be presented via asciidocs files,
|
||||
which you put in src/main/resources/plugin/lessonplans/{lang}/{fileName}.adoc -->
|
||||
<div class="adoc-content" th:replace="doc:lesson-template-attack.adoc"></div>
|
||||
|
||||
<!-- WebGoat will automatically style and scaffold some functionality by using the div.attack-container as below -->
|
||||
@ -23,10 +45,9 @@
|
||||
<!-- of course, you can write your own ajax submission /handling in your own javascript if you like -->
|
||||
|
||||
<!-- modify the action to point to the intended endpoint and set other attributes as desired -->
|
||||
<script th:src="@{/lesson_js/idor.js}" />
|
||||
<form class="attack-form" accept-charset="UNKNOWN"
|
||||
method="GET" name="form"
|
||||
action="/WebGoat/lesson-template/sample-attack"
|
||||
method="POST" name="form"
|
||||
action="/WebGoat/lesson-template/sample-attack"
|
||||
enctype="application/json;charset=UTF-8">
|
||||
<table>
|
||||
<tr>
|
||||
@ -34,8 +55,7 @@
|
||||
<td>parameter 1:<input name="param1" value="" type="TEXT" /></td>
|
||||
<td>parameter 2:<input name="param2" value="" type="TEXT" /></td>
|
||||
<td>
|
||||
<input
|
||||
name="submit" value="Submit" type="SUBMIT"/>
|
||||
<input name="submit" value="Submit" type="SUBMIT"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@ -51,4 +71,8 @@
|
||||
<!-- repeat and mix-and-match the lesson-page-wrappers with or wihtout the attack-containers as you like ...
|
||||
see other lessons for other more complex examples -->
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
<div class="adoc-content" th:replace="doc:lesson-template-database.adoc"></div>
|
||||
</div>
|
||||
|
||||
</html>
|
||||
|
@ -1,4 +1,8 @@
|
||||
lesson-template.title=Lesson Template
|
||||
lesson-template.title=Writing new lesson
|
||||
|
||||
lesson-template.hints.1=Hint 1
|
||||
lesson-template.hints.2=Hint 2
|
||||
lesson-template.hints.3=Hint 3
|
||||
|
||||
lesson-template.sample-attack.failure-1=Sample failure message
|
||||
lesson-template.sample-attack.failure-2=Sample failure message 2
|
||||
|
@ -1,83 +1,51 @@
|
||||
=== Attack Explanation
|
||||
=== Step 4: Add an assignment to your lesson
|
||||
|
||||
Each lesson can contain multiple assignments, first let's define a lesson class in Java
|
||||
With an assignment a user can practise within a lesson. A lesson can consist of multiple assignment, each assignment
|
||||
needs to extend the class `AssignmentEndpoint`, let's look at an example:
|
||||
|
||||
[source]
|
||||
[source,java]
|
||||
----
|
||||
@Component
|
||||
public class LessonTemplate extends AbstractLesson {
|
||||
@Override
|
||||
public Category getDefaultCategory() {
|
||||
return Category.GENERAL;
|
||||
}
|
||||
@RestController // <1>
|
||||
@AssignmentHints({"lesson-template.hints.1", "lesson-template.hints.2", "lesson-template.hints.3"}) // <2>
|
||||
public class SampleAttack extends AssignmentEndpoint { // <3>
|
||||
|
||||
@Override
|
||||
public List<String> getHints() {
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
private final String secretValue = "secr37Value";
|
||||
|
||||
@Override
|
||||
public Integer getDefaultRanking() {
|
||||
return 30;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return "lesson-template.title";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "LessonTemplate";
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
This implementation is quite straightforward. Now for an assignment you need to implement:
|
||||
|
||||
[source]
|
||||
----
|
||||
@RestController
|
||||
public class SampleAttack extends AssignmentEndpoint {
|
||||
|
||||
String secretValue = "secr37Value";
|
||||
|
||||
//UserSessionData is bound to session and can be used to persist data across multiple assignments
|
||||
@Autowired
|
||||
UserSessionData userSessionData;
|
||||
private UserSessionData userSessionData; // <4>
|
||||
|
||||
|
||||
@GetMapping(path = "/lesson-template/sample-attack", produces = {"application/json"})
|
||||
@PostMapping("/lesson-template/sample-attack") <5>
|
||||
@ResponseBody
|
||||
public AttackResult completed(String param1, String param2, HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
public AttackResult completed(@RequestParam("param1") String param1, @RequestParam("param2") String param2) { <6>
|
||||
if (userSessionData.getValue("some-value") != null) {
|
||||
// do any session updating you want here ... or not, just comment/example here
|
||||
//return trackProgress(failed().feedback("lesson-template.sample-attack.failure-2").build());
|
||||
//return failed(this).feedback("lesson-template.sample-attack.failure-2").build();
|
||||
}
|
||||
|
||||
//overly simple example for success. See other existing lesssons for ways to detect 'success' or 'failure'
|
||||
if (secretValue.equals(param1)) {
|
||||
return trackProgress(success()
|
||||
return success(this) // <7>
|
||||
.output("Custom Output ...if you want, for success")
|
||||
.feedback("lesson-template.sample-attack.success")
|
||||
.build());
|
||||
.build();
|
||||
//lesson-template.sample-attack.success is defined in src/main/resources/i18n/WebGoatLabels.properties
|
||||
}
|
||||
|
||||
// else
|
||||
return trackProgress(failed()
|
||||
return failed(this) // <8>
|
||||
.feedback("lesson-template.sample-attack.failure-2")
|
||||
.output("Custom output for this failure scenario, usually html that will get rendered directly ... yes, you can self-xss if you want")
|
||||
.build());
|
||||
.build();
|
||||
}
|
||||
|
||||
@GetMapping("lesson-template/shop/{user}")
|
||||
@ResponseBody
|
||||
public List<Items> getItemsInBasket(@PathVariable("user") String user) {
|
||||
....
|
||||
}
|
||||
}
|
||||
----
|
||||
<1> Every assignment is just a Spring RestController
|
||||
<2> Each assignment can have a list of hints, the actual text needs to be placed in `WebGoatLabels.properties`
|
||||
<3> Each assignment needs to extend the class `AssignmentEndpoint` giving you some helpful methods you need when you want to mark an assignment as complete
|
||||
<4> As the assignment is a Spring based class you can autowire every component managed by Spring necessary for the assignment
|
||||
<5> Each assignment should at least have one mapping with the method signature (see 6)
|
||||
<6> When the user tries to solve an assignment you need return an `AttackResult`
|
||||
<7> Returning a successful attack result when user solved the lesson
|
||||
<8> Returning a failed attack user did not solve the lesson
|
||||
|
||||
As you can see an assignment is a REST controller which need to at least have one method with the following signature:
|
||||
|
||||
@ -90,9 +58,20 @@ public AttackResult solve(String param) {
|
||||
}
|
||||
----
|
||||
|
||||
Other endpoints can be added in the assignment to support different cases for the assignment.
|
||||
=== Extra endpoints
|
||||
|
||||
### Glue between html and assignment
|
||||
Other endpoints can be added in the assignment to support different cases for the assignment, for example:
|
||||
|
||||
[source]
|
||||
----
|
||||
@GetMapping("lesson-template/shop/{user}")
|
||||
@ResponseBody
|
||||
public List<Item> getItemsInBasket(@PathVariable("user") String user) {
|
||||
return List.of(new Item("WG-1", "WebGoat promo", 12.0), new Item("WG-2", "WebGoat sticker", 0.00));
|
||||
}
|
||||
----
|
||||
|
||||
=== Adding an assignment to the html page
|
||||
|
||||
We mentioned a lesson can consist of multiple assignments, WebGoat picks them up automatically and the UI displays
|
||||
a navigation bar on top of every lesson. A page with an assignment will be red in the beginning and will become
|
||||
@ -100,19 +79,27 @@ green when the user solves the assignment. To make this work in the html we need
|
||||
|
||||
[source]
|
||||
----
|
||||
div class="attack-container">
|
||||
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
||||
<!-- using attack-form class on your form, will allow your request to be ajaxified and stay within the display framework for webgoat -->
|
||||
<!-- you can write your own custom forms, but standard form submission will take you to your endpoint and outside of the WebGoat framework -->
|
||||
<!-- of course, you can write your own ajax submission /handling in your own javascript if you like -->
|
||||
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
<div class="adoc-content" th:replace="doc:lesson-template-attack.adoc"></div>
|
||||
<div class="attack-container">
|
||||
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
|
||||
<form class="attack-form" accept-charset="UNKNOWN"
|
||||
method="GET" name="form"
|
||||
method="POST" name="form"
|
||||
action="/WebGoat/lesson-template/sample-attack"
|
||||
enctype="application/json;charset=UTF-8">
|
||||
....
|
||||
<table>
|
||||
<tr>
|
||||
<td>two random params</td>
|
||||
<td>parameter 1:<input name="param1" value="" type="TEXT" /></td>
|
||||
<td>parameter 2:<input name="param2" value="" type="TEXT" /></td>
|
||||
<td>
|
||||
<input name="submit" value="Submit" type="SUBMIT"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
<div class="attack-feedback"></div>
|
||||
<div class="attack-output"></div>
|
||||
</div>
|
||||
</div>
|
||||
----
|
||||
@ -120,4 +107,4 @@ div class="attack-container">
|
||||
So the `action` of the form should match the method which defines the check if the lesson has been solved or not
|
||||
see `public AttackResult solved()`
|
||||
|
||||
That's it you now successfully created your first WebGoat lesson.
|
||||
That's it you now successfully created your first WebGoat lesson including an assignment!
|
@ -0,0 +1,36 @@
|
||||
== Step 1: writing content
|
||||
|
||||
Each lesson can consist of multiple pages with content (text) to explain the vulnerability at hand. The content
|
||||
is written in AsciiDoc[https://asciidoctor.org/docs/asciidoc-writers-guide/] which makes it very easy to write content (if you know Markdown you know asciidoc).
|
||||
|
||||
You can find excellent tutorials online for the asciidoc syntax we are just showing a basic overview below.
|
||||
Below we will describe some of the constructs which are quite often used within WebGoat.
|
||||
|
||||
=== Sub-heading
|
||||
|
||||
Check asciidoc for syntax, but more = means smaller headings. You can *bold* text and other things.
|
||||
|
||||
=== Structuring files
|
||||
|
||||
You should set up all content so that it is these *.adoc files. The asciidoc files should be place in the
|
||||
directory `{lesson}/src/main/resources/lessonPlans/en` the last part depends on the locale.
|
||||
|
||||
=== Images
|
||||
|
||||
Images can be referenced as below including setting style (recommended to use lesson-image as the style). The root is `{lesson}/src/main/resources/images`
|
||||
|
||||
image::images/firefox-proxy-config.png[Firefox Proxy Config,510,634,style="lesson-image"]
|
||||
|
||||
=== Code block
|
||||
|
||||
Code blocks can be written as follows:
|
||||
|
||||
```
|
||||
[source]
|
||||
----
|
||||
public class A {
|
||||
|
||||
private String test;
|
||||
}
|
||||
----
|
||||
```
|
@ -0,0 +1,25 @@
|
||||
=== Database
|
||||
|
||||
If the new lesson needs to store or use a database you can add a create script in the directory `{lesson}/src/main/resources/db/migration` folder.
|
||||
The file name needs to follow a specific convention: `V2019_11_10_1__new-lesson.sql`, so the first part is just the current date.
|
||||
In this file you can for example create tables and insert some data, for example:
|
||||
|
||||
[source]
|
||||
----
|
||||
CREATE TABLE servers(
|
||||
id varchar(10),
|
||||
hostname varchar(20),
|
||||
ip varchar(20),
|
||||
mac varchar(20),
|
||||
status varchar(20),
|
||||
description varchar(40)
|
||||
);
|
||||
|
||||
INSERT INTO servers VALUES ('1', 'webgoat-dev', '192.168.4.0', 'AA:BB:11:22:CC:DD', 'online', 'Development server');
|
||||
INSERT INTO servers VALUES ('2', 'webgoat-tst', '192.168.2.1', 'EE:FF:33:44:AB:CD', 'online', 'Test server');
|
||||
INSERT INTO servers VALUES ('3', 'webgoat-acc', '192.168.3.3', 'EF:12:FE:34:AA:CC', 'offline', 'Acceptance server');
|
||||
INSERT INTO servers VALUES ('4', 'webgoat-pre-prod', '192.168.6.4', 'EF:12:FE:34:AA:CC', 'offline', 'Pre-production server');
|
||||
INSERT INTO servers VALUES ('4', 'webgoat-prd', '104.130.219.202', 'FA:91:EB:82:DC:73', 'out of order', 'Production server');
|
||||
----
|
||||
|
||||
Using this way to create a database will allow WebGoat to automatically reset the database to its original state.
|
@ -0,0 +1,59 @@
|
||||
=== Step 3: Write glue html page
|
||||
|
||||
We mentioned a lesson can consist of multiple assignments, WebGoat picks them up automatically and the UI displays
|
||||
a navigation bar on top of every lesson. A page with an assignment will be red in the beginning and will become
|
||||
green when the user solves the assignment. To make this work in the html we need to add:
|
||||
|
||||
[source]
|
||||
----
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
|
||||
<div class="lesson-page-wrapper">
|
||||
<div class="adoc-content" th:replace="doc:lesson-template-intro.adoc"></div>
|
||||
</div>
|
||||
<div class="lesson-page-wrapper">
|
||||
<div class="adoc-content" th:replace="doc:lesson-template-content.adoc"></div>
|
||||
</div>
|
||||
<div class="lesson-page-wrapper">
|
||||
<div class="adoc-content" th:replace="doc:lesson-template-lesson-class.adoc"></div>
|
||||
</div>
|
||||
</html>
|
||||
----
|
||||
|
||||
This file needs to be places in: `{lesson}/src/main/resources/html/`. The name of the file should be the same as
|
||||
the Java class we created in step 2.
|
||||
|
||||
This will create 3 separate pages (navigation bar) with the adoc pages we created to create this lesson.
|
||||
|
||||
That's it we create a basic lesson with only content. To make it all work you need to make the lesson available in
|
||||
WebGoat.
|
||||
|
||||
==== Create pom.xml
|
||||
|
||||
See the `pom.xml` of this project copy it to your new lesson and change the name.
|
||||
|
||||
==== Extend lesson project
|
||||
|
||||
Change the file in `webgoat-lesson/pom.xml` and add:
|
||||
|
||||
[source]
|
||||
----
|
||||
<module>new-lesson</module>
|
||||
----
|
||||
inside the existing `<modules>` tag.
|
||||
|
||||
==== Add project to WebGoat
|
||||
|
||||
Next step is to add a reference to the new project so WebGoat bundles it while building, open `pom.xml` in `webgoat-server/pom.xml`
|
||||
and add:
|
||||
|
||||
[source]
|
||||
----
|
||||
<dependency>
|
||||
<groupId>org.owasp.webgoat.lesson</groupId>
|
||||
<artifactId>new-lesson</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
That's it start WebGoat and your lesson will appear in the menu.
|
@ -1,19 +1,9 @@
|
||||
This lesson describes the steps needed to add a new lesson to WebGoat. In general there are three steps:
|
||||
|
||||
== Lesson Template Intro
|
||||
- Write the content, in WebGoat we use AsciiDoc as a format.
|
||||
- Create a lesson class
|
||||
- Write html glue page so WebGoat knows how the content should be displayed
|
||||
- Add one of more assignments within the lesson
|
||||
|
||||
This is the lesson template intro.
|
||||
|
||||
=== Sub-heading
|
||||
|
||||
Check asciidoc for syntax, but more = means smaller headings. You can *bold* text and other things.
|
||||
|
||||
=== Structuring files
|
||||
|
||||
You should set up all content so that it is these *.adoc files.
|
||||
|
||||
=== Images
|
||||
|
||||
Images can be referenced as below including setting style (recommended to use lesson-image as the style). The root is {lesson}/src/main/resources
|
||||
|
||||
image::images/firefox-proxy-config.png[Firefox Proxy Config,510,634,style="lesson-image"]
|
||||
Let's see how to create a new lesson.
|
||||
|
||||
|
@ -0,0 +1,20 @@
|
||||
=== Step 2: adding a new lesson class
|
||||
|
||||
Each lesson can contain multiple assignments, first let's define a lesson class in Java
|
||||
|
||||
[source]
|
||||
----
|
||||
@Component
|
||||
public class LessonTemplate extends Lesson {
|
||||
@Override
|
||||
public Category getDefaultCategory() {
|
||||
return Category.GENERAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return "lesson-template.title";
|
||||
}
|
||||
}
|
||||
----
|
||||
|
@ -0,0 +1,11 @@
|
||||
=== Even more content
|
||||
|
||||
You can include multiple adoc files in one page, by including them in the same `<div>`:
|
||||
|
||||
[source]
|
||||
----
|
||||
<div class="lesson-page-wrapper">
|
||||
<div class="adoc-content" th:replace="doc:lesson-template-video.adoc"></div>
|
||||
<div class="adoc-content" th:replace="doc:lesson-template-video-more.adoc"></div>
|
||||
</div>
|
||||
----
|
Reference in New Issue
Block a user