Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
d5f869c006 | |||
a9caaabb47 | |||
fb2ff01775 | |||
89ecf1d2ad | |||
1b66a742da | |||
a831da5886 | |||
fd5189c102 | |||
ae261f201a | |||
3d651526be | |||
c7c2a61f65 | |||
b7f657ad2c | |||
7fea42afe9 | |||
826887cc83 | |||
62db86246e |
2
.github/workflows/branchbuild.yml
vendored
2
.github/workflows/branchbuild.yml
vendored
@ -15,7 +15,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Set up JDK ${{ matrix.java-version }}
|
- name: Set up JDK ${{ matrix.java-version }}
|
||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
java-version: ${{ matrix.java-version }}
|
java-version: ${{ matrix.java-version }}
|
||||||
|
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@ -21,7 +21,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Set up JDK 17
|
- name: Set up JDK 17
|
||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
java-version: 17
|
java-version: 17
|
||||||
|
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@ -14,7 +14,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Set up JDK 17
|
- name: Set up JDK 17
|
||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
java-version: 17
|
java-version: 17
|
||||||
@ -121,7 +121,7 @@ jobs:
|
|||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set up JDK 17
|
- name: Set up JDK 17
|
||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
java-version: 17
|
java-version: 17
|
||||||
|
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@ -30,7 +30,7 @@ jobs:
|
|||||||
architecture: x64
|
architecture: x64
|
||||||
# Uses an action to add JDK 17 to the VM (and mvn?)
|
# Uses an action to add JDK 17 to the VM (and mvn?)
|
||||||
- name: set up JDK 17
|
- name: set up JDK 17
|
||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
java-version: 17
|
java-version: 17
|
||||||
|
2
.github/workflows/welcome.yml
vendored
2
.github/workflows/welcome.yml
vendored
@ -10,7 +10,7 @@ jobs:
|
|||||||
if: github.repository == 'WebGoat/WebGoat'
|
if: github.repository == 'WebGoat/WebGoat'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/first-interaction@v1.2.0
|
- uses: actions/first-interaction@v1.3.0
|
||||||
with:
|
with:
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
issue-message: 'Thanks for submitting your first issue, we will have a look as quickly as possible.'
|
issue-message: 'Thanks for submitting your first issue, we will have a look as quickly as possible.'
|
||||||
|
10
Dockerfile
10
Dockerfile
@ -1,4 +1,4 @@
|
|||||||
FROM docker.io/eclipse-temurin:19-jre-focal
|
FROM docker.io/eclipse-temurin:21.0.1_12-jre
|
||||||
LABEL NAME = "WebGoat: A deliberately insecure Web Application"
|
LABEL NAME = "WebGoat: A deliberately insecure Web Application"
|
||||||
MAINTAINER "WebGoat team"
|
MAINTAINER "WebGoat team"
|
||||||
|
|
||||||
@ -14,6 +14,8 @@ COPY --chown=webgoat target/webgoat-*.jar /home/webgoat/webgoat.jar
|
|||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
EXPOSE 9090
|
EXPOSE 9090
|
||||||
|
|
||||||
|
ENV TZ=Europe/Amsterdam
|
||||||
|
|
||||||
WORKDIR /home/webgoat
|
WORKDIR /home/webgoat
|
||||||
ENTRYPOINT [ "java", \
|
ENTRYPOINT [ "java", \
|
||||||
"-Duser.home=/home/webgoat", \
|
"-Duser.home=/home/webgoat", \
|
||||||
@ -30,8 +32,4 @@ ENTRYPOINT [ "java", \
|
|||||||
"--add-opens", "java.base/sun.nio.ch=ALL-UNNAMED", \
|
"--add-opens", "java.base/sun.nio.ch=ALL-UNNAMED", \
|
||||||
"--add-opens", "java.base/java.io=ALL-UNNAMED", \
|
"--add-opens", "java.base/java.io=ALL-UNNAMED", \
|
||||||
"-Drunning.in.docker=true", \
|
"-Drunning.in.docker=true", \
|
||||||
"-Dwebgoat.host=0.0.0.0", \
|
"-jar", "webgoat.jar", "--server.address", "0.0.0.0" ]
|
||||||
"-Dwebwolf.host=0.0.0.0", \
|
|
||||||
"-Dwebgoat.port=8080", \
|
|
||||||
"-Dwebwolf.port=9090", \
|
|
||||||
"-jar", "webgoat.jar" ]
|
|
||||||
|
26
README.md
26
README.md
@ -44,19 +44,27 @@ Every release is also published on [DockerHub](https://hub.docker.com/r/webgoat/
|
|||||||
docker run -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 webgoat/webgoat
|
docker run -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 webgoat/webgoat
|
||||||
```
|
```
|
||||||
|
|
||||||
If you want to reuse the container, give it a name:
|
For some lessons you need the container run in the same timezone. For this you can set the TZ environment variable.
|
||||||
|
E.g.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
docker run --name webgoat -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 webgoat/webgoat
|
docker run -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 -e TZ=America/Boise webgoat/webgoat
|
||||||
```
|
```
|
||||||
|
|
||||||
As long as you don't remove the container you can use:
|
If you want to use OWASP ZAP or another proxy, you can no longer use 127.0.0.1 or localhost. but
|
||||||
|
you can use custom host entries. For example:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
docker start webgoat
|
127.0.0.1 www.webgoat.local www.webwolf.local
|
||||||
```
|
```
|
||||||
|
|
||||||
This way, you can start where you left off. If you remove the container, you need to use `docker run` again.
|
Then you can run the container with:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
docker run -it -p 127.0.0.1:8080:8080 -p 127.0.0.1:9090:9090 -e WEBGOAT_HOST=www.webgoat.local -e WEBWOLF_HOST=www.webwolf.local -e TZ=America/Boise webgoat/webgoat
|
||||||
|
```
|
||||||
|
|
||||||
|
Then visit http://www.webgoat.local:8080/WebGoat/ and http://www.webwolf.local:9090/WebWolf/
|
||||||
|
|
||||||
## 2. Run using Docker with complete Linux Desktop
|
## 2. Run using Docker with complete Linux Desktop
|
||||||
|
|
||||||
@ -71,7 +79,8 @@ docker run -p 127.0.0.1:3000:3000 webgoat/webgoat-desktop
|
|||||||
Download the latest WebGoat release from [https://github.com/WebGoat/WebGoat/releases](https://github.com/WebGoat/WebGoat/releases)
|
Download the latest WebGoat release from [https://github.com/WebGoat/WebGoat/releases](https://github.com/WebGoat/WebGoat/releases)
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
java -Dfile.encoding=UTF-8 -Dwebgoat.port=8080 -Dwebwolf.port=9090 -jar webgoat-2023.4.jar
|
export TZ=Europe/Amsterdam # or your timezone
|
||||||
|
java -Dfile.encoding=UTF-8 -jar webgoat-2023.5.jar
|
||||||
```
|
```
|
||||||
|
|
||||||
Click the link in the log to start WebGoat.
|
Click the link in the log to start WebGoat.
|
||||||
@ -80,7 +89,7 @@ Click the link in the log to start WebGoat.
|
|||||||
|
|
||||||
### Prerequisites:
|
### Prerequisites:
|
||||||
|
|
||||||
* Java 17
|
* Java 17 or 21
|
||||||
* Your favorite IDE
|
* Your favorite IDE
|
||||||
* Git, or Git support in your IDE
|
* Git, or Git support in your IDE
|
||||||
|
|
||||||
@ -132,9 +141,10 @@ For specialist only. There is a way to set up WebGoat with a personalized menu.
|
|||||||
For instance running as a jar on a Linux/macOS it will look like this:
|
For instance running as a jar on a Linux/macOS it will look like this:
|
||||||
|
|
||||||
```Shell
|
```Shell
|
||||||
|
export TZ=Europe/Amsterdam # or your timezone
|
||||||
export EXCLUDE_CATEGORIES="CLIENT_SIDE,GENERAL,CHALLENGE"
|
export EXCLUDE_CATEGORIES="CLIENT_SIDE,GENERAL,CHALLENGE"
|
||||||
export EXCLUDE_LESSONS="SqlInjectionAdvanced,SqlInjectionMitigations"
|
export EXCLUDE_LESSONS="SqlInjectionAdvanced,SqlInjectionMitigations"
|
||||||
java -jar target/webgoat-2023.4-SNAPSHOT.jar
|
java -jar target/webgoat-2023.6-SNAPSHOT.jar
|
||||||
```
|
```
|
||||||
|
|
||||||
Or in a docker run it would (once this version is pushed into docker hub) look like this:
|
Or in a docker run it would (once this version is pushed into docker hub) look like this:
|
||||||
|
@ -1,5 +1,25 @@
|
|||||||
# WebGoat release notes
|
# WebGoat release notes
|
||||||
|
|
||||||
|
## Version 2023.7
|
||||||
|
|
||||||
|
### 🚀 New functionality
|
||||||
|
|
||||||
|
- Consistent environment values and url references (#1677)
|
||||||
|
- Show directly requested file in requests overview
|
||||||
|
- Show creating time in file upload overview
|
||||||
|
|
||||||
|
### 🐞 Bug fixes
|
||||||
|
|
||||||
|
- Fix startup message (#1687)
|
||||||
|
- Fix/state of software supply chain links (#1683)
|
||||||
|
- Fix WebWolf UI (#1686)
|
||||||
|
|
||||||
|
### 🔄 Technical tasks
|
||||||
|
|
||||||
|
- bump actions/setup-java from 3 to 4 (#1690)
|
||||||
|
- bump commons-io:commons-io from 2.14.0 to 2.15.1 (#1689)
|
||||||
|
- bump com.diffplug.spotless:spotless-maven-plugin (#1688)
|
||||||
|
|
||||||
## Version 2023.5
|
## Version 2023.5
|
||||||
|
|
||||||
### New functionality
|
### New functionality
|
||||||
|
44
pom.xml
44
pom.xml
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
<groupId>org.owasp.webgoat</groupId>
|
<groupId>org.owasp.webgoat</groupId>
|
||||||
<artifactId>webgoat</artifactId>
|
<artifactId>webgoat</artifactId>
|
||||||
<version>2023.5</version>
|
<version>2023.7</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>WebGoat</name>
|
<name>WebGoat</name>
|
||||||
@ -115,7 +115,7 @@
|
|||||||
<!-- do not update necessary for lesson -->
|
<!-- do not update necessary for lesson -->
|
||||||
<checkstyle.version>3.3.1</checkstyle.version>
|
<checkstyle.version>3.3.1</checkstyle.version>
|
||||||
<commons-collections.version>3.2.1</commons-collections.version>
|
<commons-collections.version>3.2.1</commons-collections.version>
|
||||||
<commons-io.version>2.14.0</commons-io.version>
|
<commons-io.version>2.15.1</commons-io.version>
|
||||||
<commons-lang3.version>3.12.0</commons-lang3.version>
|
<commons-lang3.version>3.12.0</commons-lang3.version>
|
||||||
<commons-text.version>1.10.0</commons-text.version>
|
<commons-text.version>1.10.0</commons-text.version>
|
||||||
<guava.version>32.1.3-jre</guava.version>
|
<guava.version>32.1.3-jre</guava.version>
|
||||||
@ -141,10 +141,9 @@
|
|||||||
<thymeleaf.version>3.1.1.RELEASE</thymeleaf.version>
|
<thymeleaf.version>3.1.1.RELEASE</thymeleaf.version>
|
||||||
<webdriver.version>5.3.3</webdriver.version>
|
<webdriver.version>5.3.3</webdriver.version>
|
||||||
<webgoat.context>/</webgoat.context>
|
<webgoat.context>/</webgoat.context>
|
||||||
<webgoat.port>8080</webgoat.port>
|
<webgoat.sslenabled>false</webgoat.sslenabled>
|
||||||
<webjars-locator-core.version>0.53</webjars-locator-core.version>
|
<webjars-locator-core.version>0.53</webjars-locator-core.version>
|
||||||
<webwolf.context>/</webwolf.context>
|
<webwolf.context>/</webwolf.context>
|
||||||
<webwolf.port>9090</webwolf.port>
|
|
||||||
<wiremock.version>2.27.2</wiremock.version>
|
<wiremock.version>2.27.2</wiremock.version>
|
||||||
<xml-resolver.version>1.2</xml-resolver.version>
|
<xml-resolver.version>1.2</xml-resolver.version>
|
||||||
<xstream.version>1.4.5</xstream.version>
|
<xstream.version>1.4.5</xstream.version>
|
||||||
@ -513,10 +512,19 @@
|
|||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-failsafe-plugin</artifactId>
|
<artifactId>maven-failsafe-plugin</artifactId>
|
||||||
<configuration>
|
<configuration>
|
||||||
|
<environmentVariables>
|
||||||
|
<WEBGOAT_SSLENABLED>${webgoat.sslenabled}</WEBGOAT_SSLENABLED>
|
||||||
|
<WEBGOAT_HOST>127.0.0.1</WEBGOAT_HOST>
|
||||||
|
<WEBGOAT_PORT>${webgoat.port}</WEBGOAT_PORT>
|
||||||
|
<WEBGOAT_CONTEXT>${webgoat.context}</WEBGOAT_CONTEXT>
|
||||||
|
<WEBWOLF_HOST>127.0.0.1</WEBWOLF_HOST>
|
||||||
|
<WEBWOLF_PORT>${webwolf.port}</WEBWOLF_PORT>
|
||||||
|
<WEBWOLF_CONTEXT>${webwolf.context}</WEBWOLF_CONTEXT>
|
||||||
|
</environmentVariables>
|
||||||
<systemPropertyVariables>
|
<systemPropertyVariables>
|
||||||
<logback.configurationFile>${basedir}/src/test/resources/logback-test.xml</logback.configurationFile>
|
<logback.configurationFile>${basedir}/src/test/resources/logback-test.xml</logback.configurationFile>
|
||||||
</systemPropertyVariables>
|
</systemPropertyVariables>
|
||||||
<argLine>-Xmx512m -Dwebgoatport=${webgoat.port} -Dwebwolfport=${webwolf.port} -Dwebwolfcontext=${webwolf.context} -Dwebgoatcontext=${webgoat.context}</argLine>
|
<argLine>-Xmx512m</argLine>
|
||||||
<includes>org/owasp/webgoat/*Test</includes>
|
<includes>org/owasp/webgoat/*Test</includes>
|
||||||
</configuration>
|
</configuration>
|
||||||
<executions>
|
<executions>
|
||||||
@ -557,7 +565,6 @@
|
|||||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||||
<version>${checkstyle.version}</version>
|
<version>${checkstyle.version}</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<encoding>UTF-8</encoding>
|
|
||||||
<consoleOutput>true</consoleOutput>
|
<consoleOutput>true</consoleOutput>
|
||||||
<failsOnError>true</failsOnError>
|
<failsOnError>true</failsOnError>
|
||||||
<configLocation>config/checkstyle/checkstyle.xml</configLocation>
|
<configLocation>config/checkstyle/checkstyle.xml</configLocation>
|
||||||
@ -568,7 +575,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>com.diffplug.spotless</groupId>
|
<groupId>com.diffplug.spotless</groupId>
|
||||||
<artifactId>spotless-maven-plugin</artifactId>
|
<artifactId>spotless-maven-plugin</artifactId>
|
||||||
<version>2.38.0</version>
|
<version>2.41.1</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<formats>
|
<formats>
|
||||||
<format>
|
<format>
|
||||||
@ -686,16 +693,15 @@
|
|||||||
<portNames>
|
<portNames>
|
||||||
<portName>webgoat.port</portName>
|
<portName>webgoat.port</portName>
|
||||||
<portName>webwolf.port</portName>
|
<portName>webwolf.port</portName>
|
||||||
<portName>jmxPort</portName>
|
|
||||||
</portNames>
|
</portNames>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>com.bazaarvoice.maven.plugins</groupId>
|
<groupId>org.honton.chas</groupId>
|
||||||
<artifactId>process-exec-maven-plugin</artifactId>
|
<artifactId>process-exec-maven-plugin</artifactId>
|
||||||
<version>0.9</version>
|
<version>0.9.2</version>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>start-jar</id>
|
<id>start-jar</id>
|
||||||
@ -703,8 +709,18 @@
|
|||||||
<goal>start</goal>
|
<goal>start</goal>
|
||||||
</goals>
|
</goals>
|
||||||
<phase>pre-integration-test</phase>
|
<phase>pre-integration-test</phase>
|
||||||
|
|
||||||
<configuration>
|
<configuration>
|
||||||
<workingDir>${project.build.directory}</workingDir>
|
<workingDir>${project.build.directory}</workingDir>
|
||||||
|
<environment>
|
||||||
|
<WEBGOAT_SSLENABLED>${webgoat.sslenabled}</WEBGOAT_SSLENABLED>
|
||||||
|
<WEBGOAT_HOST>127.0.0.1</WEBGOAT_HOST>
|
||||||
|
<WEBGOAT_PORT>${webgoat.port}</WEBGOAT_PORT>
|
||||||
|
<WEBGOAT_CONTEXT>${webgoat.context}</WEBGOAT_CONTEXT>
|
||||||
|
<WEBWOLF_HOST>127.0.0.1</WEBWOLF_HOST>
|
||||||
|
<WEBWOLF_PORT>${webwolf.port}</WEBWOLF_PORT>
|
||||||
|
<WEBWOLF_CONTEXT>${webwolf.context}</WEBWOLF_CONTEXT>
|
||||||
|
</environment>
|
||||||
<arguments>
|
<arguments>
|
||||||
<argument>java</argument>
|
<argument>java</argument>
|
||||||
<argument>-jar</argument>
|
<argument>-jar</argument>
|
||||||
@ -712,10 +728,6 @@
|
|||||||
<argument>-Dwebgoat.server.directory=${java.io.tmpdir}/webgoat_${webgoat.port}</argument>
|
<argument>-Dwebgoat.server.directory=${java.io.tmpdir}/webgoat_${webgoat.port}</argument>
|
||||||
<argument>-Dwebgoat.user.directory=${java.io.tmpdir}/webgoat_${webgoat.port}</argument>
|
<argument>-Dwebgoat.user.directory=${java.io.tmpdir}/webgoat_${webgoat.port}</argument>
|
||||||
<argument>-Dspring.main.banner-mode=off</argument>
|
<argument>-Dspring.main.banner-mode=off</argument>
|
||||||
<argument>-Dwebgoat.port=${webgoat.port}</argument>
|
|
||||||
<argument>-Dwebgoat.context=${webgoat.context}</argument>
|
|
||||||
<argument>-Dwebwolf.port=${webwolf.port}</argument>
|
|
||||||
<argument>-Dwebwolf.context=${webwolf.context}</argument>
|
|
||||||
<argument>--add-opens</argument>
|
<argument>--add-opens</argument>
|
||||||
<argument>java.base/java.lang=ALL-UNNAMED</argument>
|
<argument>java.base/java.lang=ALL-UNNAMED</argument>
|
||||||
<argument>--add-opens</argument>
|
<argument>--add-opens</argument>
|
||||||
@ -741,8 +753,6 @@
|
|||||||
<argument>${project.build.directory}/webgoat-${project.version}.jar</argument>
|
<argument>${project.build.directory}/webgoat-${project.version}.jar</argument>
|
||||||
</arguments>
|
</arguments>
|
||||||
<waitForInterrupt>false</waitForInterrupt>
|
<waitForInterrupt>false</waitForInterrupt>
|
||||||
<waitAfterLaunch>120</waitAfterLaunch>
|
|
||||||
<healthcheckUrl>http://localhost:${webgoat.port}/WebGoat/actuator/health</healthcheckUrl>
|
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
<execution>
|
<execution>
|
||||||
@ -767,7 +777,6 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.owasp</groupId>
|
<groupId>org.owasp</groupId>
|
||||||
<artifactId>dependency-check-maven</artifactId>
|
<artifactId>dependency-check-maven</artifactId>
|
||||||
<version>8.4.3</version>
|
|
||||||
<configuration>
|
<configuration>
|
||||||
<failBuildOnCVSS>7</failBuildOnCVSS>
|
<failBuildOnCVSS>7</failBuildOnCVSS>
|
||||||
<skipProvidedScope>false</skipProvidedScope>
|
<skipProvidedScope>false</skipProvidedScope>
|
||||||
@ -816,7 +825,6 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.jacoco</groupId>
|
<groupId>org.jacoco</groupId>
|
||||||
<artifactId>jacoco-maven-plugin</artifactId>
|
<artifactId>jacoco-maven-plugin</artifactId>
|
||||||
<version>${jacoco.version}</version>
|
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>before-unit-test</id>
|
<id>before-unit-test</id>
|
||||||
|
@ -253,6 +253,7 @@ public class CSRFIntegrationTest extends IntegrationTest {
|
|||||||
Overview[] assignments =
|
Overview[] assignments =
|
||||||
RestAssured.given()
|
RestAssured.given()
|
||||||
.cookie("JSESSIONID", getWebGoatCookie())
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
|
.relaxedHTTPSValidation()
|
||||||
.get(url("service/lessonoverview.mvc"))
|
.get(url("service/lessonoverview.mvc"))
|
||||||
.then()
|
.then()
|
||||||
.extract()
|
.extract()
|
||||||
|
@ -5,7 +5,6 @@ import static io.restassured.RestAssured.given;
|
|||||||
import io.restassured.RestAssured;
|
import io.restassured.RestAssured;
|
||||||
import io.restassured.http.ContentType;
|
import io.restassured.http.ContentType;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.hamcrest.CoreMatchers;
|
import org.hamcrest.CoreMatchers;
|
||||||
import org.hamcrest.MatcherAssert;
|
import org.hamcrest.MatcherAssert;
|
||||||
@ -15,23 +14,26 @@ import org.springframework.http.HttpStatus;
|
|||||||
|
|
||||||
public abstract class IntegrationTest {
|
public abstract class IntegrationTest {
|
||||||
|
|
||||||
private static String webGoatPort =
|
private static String webGoatPort = System.getenv().getOrDefault("WEBGOAT_PORT", "8080");
|
||||||
Objects.requireNonNull(System.getProperty("webgoatport", "8080"));
|
|
||||||
private static String webGoatContext =
|
private static String webGoatContext =
|
||||||
Objects.requireNonNull(System.getProperty("webgoatcontext", "/WebGoat/"));
|
System.getenv().getOrDefault("WEBGOAT_CONTEXT", "/WebGoat/");
|
||||||
|
|
||||||
|
@Getter private static String webWolfPort = System.getenv().getOrDefault("WEBWOLF_PORT", "9090");
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private static String webWolfPort =
|
private static String webWolfHost = System.getenv().getOrDefault("WEBWOLF_HOST", "127.0.0.1");
|
||||||
Objects.requireNonNull(System.getProperty("webwolfport", "9090"));
|
|
||||||
|
@Getter
|
||||||
|
private static String webGoatHost = System.getenv().getOrDefault("WEBGOAT_HOST", "127.0.0.1");
|
||||||
|
|
||||||
private static String webWolfContext =
|
private static String webWolfContext =
|
||||||
Objects.requireNonNull(System.getProperty("webwolfcontext", "/WebWolf/"));
|
System.getenv().getOrDefault("WEBWOLF_CONTEXT", "/WebWolf/");
|
||||||
|
|
||||||
private static boolean useSSL = false;
|
private static boolean useSSL =
|
||||||
|
Boolean.valueOf(System.getenv().getOrDefault("WEBGOAT_SSLENABLED", "false"));
|
||||||
private static String webgoatUrl =
|
private static String webgoatUrl =
|
||||||
(useSSL ? "https:" : "http:") + "//localhost:" + webGoatPort + webGoatContext;
|
(useSSL ? "https://" : "http://") + webGoatHost + ":" + webGoatPort + webGoatContext;
|
||||||
private static String webWolfUrl =
|
private static String webWolfUrl = "http://" + webWolfHost + ":" + webWolfPort + webWolfContext;
|
||||||
(useSSL ? "https:" : "http:") + "//localhost:" + webWolfPort + webWolfContext;
|
|
||||||
@Getter private String webGoatCookie;
|
@Getter private String webGoatCookie;
|
||||||
@Getter private String webWolfCookie;
|
@Getter private String webWolfCookie;
|
||||||
@Getter private final String user = "webgoat";
|
@Getter private final String user = "webgoat";
|
||||||
|
@ -69,7 +69,6 @@ public class PasswordResetLessonIntegrationTest extends IntegrationTest {
|
|||||||
|
|
||||||
// WebWolf
|
// WebWolf
|
||||||
var link = getPasswordResetLinkFromLandingPage();
|
var link = getPasswordResetLinkFromLandingPage();
|
||||||
|
|
||||||
// WebGoat
|
// WebGoat
|
||||||
changePassword(link);
|
changePassword(link);
|
||||||
checkAssignment(
|
checkAssignment(
|
||||||
@ -137,7 +136,7 @@ public class PasswordResetLessonIntegrationTest extends IntegrationTest {
|
|||||||
private void clickForgotEmailLink(String user) {
|
private void clickForgotEmailLink(String user) {
|
||||||
RestAssured.given()
|
RestAssured.given()
|
||||||
.when()
|
.when()
|
||||||
.header(HttpHeaders.HOST, String.format("%s:%s", "127.0.0.1", getWebWolfPort()))
|
.header(HttpHeaders.HOST, String.format("%s:%s", getWebWolfHost(), getWebWolfPort()))
|
||||||
.relaxedHTTPSValidation()
|
.relaxedHTTPSValidation()
|
||||||
.cookie("JSESSIONID", getWebGoatCookie())
|
.cookie("JSESSIONID", getWebGoatCookie())
|
||||||
.formParams("email", user)
|
.formParams("email", user)
|
||||||
|
@ -6,7 +6,6 @@ import javax.sql.DataSource;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.flywaydb.core.Flyway;
|
import org.flywaydb.core.Flyway;
|
||||||
import org.owasp.webgoat.container.lessons.LessonScanner;
|
|
||||||
import org.owasp.webgoat.container.service.RestartLessonService;
|
import org.owasp.webgoat.container.service.RestartLessonService;
|
||||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
|
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
@ -20,7 +19,6 @@ import org.springframework.jdbc.datasource.DriverManagerDataSource;
|
|||||||
public class DatabaseConfiguration {
|
public class DatabaseConfiguration {
|
||||||
|
|
||||||
private final DataSourceProperties properties;
|
private final DataSourceProperties properties;
|
||||||
private final LessonScanner lessonScanner;
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@Primary
|
@Primary
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
package org.owasp.webgoat.container.asciidoc;
|
package org.owasp.webgoat.container.asciidoc;
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.asciidoctor.ast.ContentNode;
|
import org.asciidoctor.ast.ContentNode;
|
||||||
import org.asciidoctor.extension.InlineMacroProcessor;
|
import org.asciidoctor.extension.InlineMacroProcessor;
|
||||||
import org.springframework.web.context.request.RequestContextHolder;
|
|
||||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Usage in asciidoc:
|
* Usage in asciidoc:
|
||||||
@ -26,7 +23,7 @@ public class WebWolfMacro extends InlineMacroProcessor {
|
|||||||
@Override
|
@Override
|
||||||
public Object process(ContentNode contentNode, String linkText, Map<String, Object> attributes) {
|
public Object process(ContentNode contentNode, String linkText, Map<String, Object> attributes) {
|
||||||
var env = EnvironmentExposure.getEnv();
|
var env = EnvironmentExposure.getEnv();
|
||||||
var hostname = determineHost(env.getProperty("webwolf.port"));
|
var hostname = env.getProperty("webwolf.url");
|
||||||
var target = (String) attributes.getOrDefault("target", "home");
|
var target = (String) attributes.getOrDefault("target", "home");
|
||||||
var href = hostname + "/" + target;
|
var href = hostname + "/" + target;
|
||||||
|
|
||||||
@ -45,29 +42,4 @@ public class WebWolfMacro extends InlineMacroProcessor {
|
|||||||
private boolean displayCompleteLinkNoFormatting(Map<String, Object> attributes) {
|
private boolean displayCompleteLinkNoFormatting(Map<String, Object> attributes) {
|
||||||
return attributes.values().stream().anyMatch(a -> a.equals("noLink"));
|
return attributes.values().stream().anyMatch(a -> a.equals("noLink"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine the host from the hostname and ports that were used. The purpose is to make it
|
|
||||||
* possible to use the application behind a reverse proxy. For instance in the docker
|
|
||||||
* compose/stack version with webgoat webwolf and nginx proxy. You do not have to use the
|
|
||||||
* indicated hostname, but if you do, you should define two hosts aliases 127.0.0.1
|
|
||||||
* www.webgoat.local www.webwolf.local
|
|
||||||
*/
|
|
||||||
private String determineHost(String port) {
|
|
||||||
HttpServletRequest request =
|
|
||||||
((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
|
|
||||||
String host = request.getHeader("Host");
|
|
||||||
int semicolonIndex = host.indexOf(":");
|
|
||||||
if (semicolonIndex == -1 || host.endsWith(":80")) {
|
|
||||||
host = host.replace(":80", "").replace("www.webgoat.local", "www.webwolf.local");
|
|
||||||
} else {
|
|
||||||
host = host.substring(0, semicolonIndex);
|
|
||||||
host = host.concat(":").concat(port);
|
|
||||||
}
|
|
||||||
return "http://" + host + (includeWebWolfContext() ? "/WebWolf" : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean includeWebWolfContext() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -17,9 +17,4 @@ public class WebWolfRootMacro extends WebWolfMacro {
|
|||||||
public WebWolfRootMacro(String macroName, Map<String, Object> config) {
|
public WebWolfRootMacro(String macroName, Map<String, Object> config) {
|
||||||
super(macroName, config);
|
super(macroName, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean includeWebWolfContext() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -25,24 +25,36 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.server;
|
package org.owasp.webgoat.server;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.owasp.webgoat.container.WebGoat;
|
import org.owasp.webgoat.container.WebGoat;
|
||||||
import org.owasp.webgoat.webwolf.WebWolf;
|
import org.owasp.webgoat.webwolf.WebWolf;
|
||||||
import org.springframework.boot.Banner;
|
import org.springframework.boot.Banner;
|
||||||
import org.springframework.boot.WebApplicationType;
|
import org.springframework.boot.WebApplicationType;
|
||||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class StartWebGoat {
|
public class StartWebGoat {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
var parentBuilder =
|
||||||
new SpringApplicationBuilder()
|
new SpringApplicationBuilder()
|
||||||
.parent(ParentConfig.class)
|
.parent(ParentConfig.class)
|
||||||
.web(WebApplicationType.NONE)
|
.web(WebApplicationType.NONE)
|
||||||
.bannerMode(Banner.Mode.OFF)
|
.bannerMode(Banner.Mode.OFF);
|
||||||
.child(WebGoat.class)
|
parentBuilder.child(WebWolf.class).web(WebApplicationType.SERVLET).run(args);
|
||||||
.web(WebApplicationType.SERVLET)
|
ApplicationContext webGoatContext =
|
||||||
.sibling(WebWolf.class)
|
parentBuilder.child(WebGoat.class).web(WebApplicationType.SERVLET).run(args);
|
||||||
.bannerMode(Banner.Mode.OFF)
|
|
||||||
.web(WebApplicationType.SERVLET)
|
printStartUpMessage(webGoatContext);
|
||||||
.run(args);
|
}
|
||||||
|
|
||||||
|
private static void printStartUpMessage(ApplicationContext webGoatContext) {
|
||||||
|
var url = webGoatContext.getEnvironment().getProperty("webgoat.url");
|
||||||
|
var sslEnabled =
|
||||||
|
webGoatContext.getEnvironment().getProperty("server.ssl.enabled", Boolean.class);
|
||||||
|
log.warn(
|
||||||
|
"Please browse to " + "{} to start using WebGoat...",
|
||||||
|
sslEnabled ? url.replace("http", "https") : url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
package org.owasp.webgoat.server;
|
|
||||||
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
|
||||||
import org.springframework.context.event.ContextStoppedEvent;
|
|
||||||
import org.springframework.context.event.EventListener;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
@Slf4j
|
|
||||||
@NoArgsConstructor
|
|
||||||
public class StartupMessage {
|
|
||||||
|
|
||||||
private String port;
|
|
||||||
private String address;
|
|
||||||
private String contextPath;
|
|
||||||
|
|
||||||
@EventListener
|
|
||||||
void onStartup(ApplicationReadyEvent event) {
|
|
||||||
|
|
||||||
port = event.getApplicationContext().getEnvironment().getProperty("server.port");
|
|
||||||
address = event.getApplicationContext().getEnvironment().getProperty("server.address");
|
|
||||||
contextPath =
|
|
||||||
event.getApplicationContext().getEnvironment().getProperty("server.servlet.context-path");
|
|
||||||
if (StringUtils.hasText(port)
|
|
||||||
&& !StringUtils.hasText(System.getProperty("running.in.docker"))) {
|
|
||||||
log.warn("Please browse to http://{}:{}{} to get started...", address, port, contextPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventListener
|
|
||||||
void onShutdown(ContextStoppedEvent event) {}
|
|
||||||
}
|
|
@ -22,14 +22,18 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.webwolf;
|
package org.owasp.webgoat.webwolf;
|
||||||
|
|
||||||
|
import static java.util.Comparator.comparing;
|
||||||
import static org.springframework.http.MediaType.ALL_VALUE;
|
import static org.springframework.http.MediaType.ALL_VALUE;
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.attribute.FileTime;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import lombok.AllArgsConstructor;
|
import java.util.TimeZone;
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
@ -51,6 +55,9 @@ import org.springframework.web.servlet.view.RedirectView;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class FileServer {
|
public class FileServer {
|
||||||
|
|
||||||
|
private static final DateTimeFormatter dateTimeFormatter =
|
||||||
|
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
@Value("${webwolf.fileserver.location}")
|
@Value("${webwolf.fileserver.location}")
|
||||||
private String fileLocation;
|
private String fileLocation;
|
||||||
|
|
||||||
@ -87,16 +94,9 @@ public class FileServer {
|
|||||||
new ModelMap().addAttribute("uploadSuccess", "File uploaded successful"));
|
new ModelMap().addAttribute("uploadSuccess", "File uploaded successful"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
@Getter
|
|
||||||
private class UploadedFile {
|
|
||||||
private final String name;
|
|
||||||
private final String size;
|
|
||||||
private final String link;
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping(value = "/files")
|
@GetMapping(value = "/files")
|
||||||
public ModelAndView getFiles(HttpServletRequest request, Authentication authentication) {
|
public ModelAndView getFiles(
|
||||||
|
HttpServletRequest request, Authentication authentication, TimeZone timezone) {
|
||||||
String username = (null != authentication) ? authentication.getName() : "anonymous";
|
String username = (null != authentication) ? authentication.getName() : "anonymous";
|
||||||
File destinationDir = new File(fileLocation, username);
|
File destinationDir = new File(fileLocation, username);
|
||||||
|
|
||||||
@ -108,18 +108,33 @@ public class FileServer {
|
|||||||
}
|
}
|
||||||
changeIndicatorFile.delete();
|
changeIndicatorFile.delete();
|
||||||
|
|
||||||
var uploadedFiles = new ArrayList<>();
|
record UploadedFile(String name, String size, String link, String creationTime) {}
|
||||||
|
|
||||||
|
var uploadedFiles = new ArrayList<UploadedFile>();
|
||||||
File[] files = destinationDir.listFiles(File::isFile);
|
File[] files = destinationDir.listFiles(File::isFile);
|
||||||
if (files != null) {
|
if (files != null) {
|
||||||
for (File file : files) {
|
for (File file : files) {
|
||||||
String size = FileUtils.byteCountToDisplaySize(file.length());
|
String size = FileUtils.byteCountToDisplaySize(file.length());
|
||||||
String link = String.format("files/%s/%s", username, file.getName());
|
String link = String.format("files/%s/%s", username, file.getName());
|
||||||
uploadedFiles.add(new UploadedFile(file.getName(), size, link));
|
uploadedFiles.add(
|
||||||
|
new UploadedFile(file.getName(), size, link, getCreationTime(timezone, file)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
modelAndView.addObject("files", uploadedFiles);
|
modelAndView.addObject(
|
||||||
|
"files",
|
||||||
|
uploadedFiles.stream().sorted(comparing(UploadedFile::creationTime).reversed()).toList());
|
||||||
modelAndView.addObject("webwolf_url", "http://" + server + ":" + port + contextPath);
|
modelAndView.addObject("webwolf_url", "http://" + server + ":" + port + contextPath);
|
||||||
return modelAndView;
|
return modelAndView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getCreationTime(TimeZone timezone, File file) {
|
||||||
|
try {
|
||||||
|
FileTime creationTime = (FileTime) Files.getAttribute(file.toPath(), "creationTime");
|
||||||
|
ZonedDateTime zonedDateTime = creationTime.toInstant().atZone(timezone.toZoneId());
|
||||||
|
return dateTimeFormatter.format(zonedDateTime);
|
||||||
|
} catch (IOException e) {
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,8 +22,6 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.webwolf.requests;
|
package org.owasp.webgoat.webwolf.requests;
|
||||||
|
|
||||||
import static java.util.stream.Collectors.toList;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
@ -67,10 +65,10 @@ public class Requests {
|
|||||||
var model = new ModelAndView("requests");
|
var model = new ModelAndView("requests");
|
||||||
String username = (null != authentication) ? authentication.getName() : "anonymous";
|
String username = (null != authentication) ? authentication.getName() : "anonymous";
|
||||||
var traces =
|
var traces =
|
||||||
traceRepository.findAllTraces().stream()
|
traceRepository.findAll().stream()
|
||||||
.filter(t -> allowedTrace(t, username))
|
.filter(t -> allowedTrace(t, username))
|
||||||
.map(t -> new Tracert(t.getTimestamp(), path(t), toJsonString(t)))
|
.map(t -> new Tracert(t.getTimestamp(), path(t), toJsonString(t)))
|
||||||
.collect(toList());
|
.toList();
|
||||||
model.addObject("traces", traces);
|
model.addObject("traces", traces);
|
||||||
|
|
||||||
return model;
|
return model;
|
||||||
@ -93,7 +91,7 @@ public class Requests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String path(HttpExchange t) {
|
private String path(HttpExchange t) {
|
||||||
return (String) t.getRequest().getUri().getPath();
|
return t.getRequest().getUri().getPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String toJsonString(HttpExchange t) {
|
private String toJsonString(HttpExchange t) {
|
||||||
|
@ -22,6 +22,9 @@
|
|||||||
|
|
||||||
package org.owasp.webgoat.webwolf.requests;
|
package org.owasp.webgoat.webwolf.requests;
|
||||||
|
|
||||||
|
import static org.owasp.webgoat.webwolf.requests.WebWolfTraceRepository.Exclusion.contains;
|
||||||
|
import static org.owasp.webgoat.webwolf.requests.WebWolfTraceRepository.Exclusion.endsWith;
|
||||||
|
|
||||||
import com.google.common.collect.EvictingQueue;
|
import com.google.common.collect.EvictingQueue;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -36,31 +39,50 @@ import org.springframework.boot.actuate.web.exchanges.HttpExchangeRepository;
|
|||||||
* @since 8/13/17.
|
* @since 8/13/17.
|
||||||
*/
|
*/
|
||||||
public class WebWolfTraceRepository implements HttpExchangeRepository {
|
public class WebWolfTraceRepository implements HttpExchangeRepository {
|
||||||
|
private enum MatchingMode {
|
||||||
|
CONTAINS,
|
||||||
|
ENDS_WITH,
|
||||||
|
EQUALS;
|
||||||
|
}
|
||||||
|
|
||||||
|
record Exclusion(String path, MatchingMode mode) {
|
||||||
|
public boolean matches(String path) {
|
||||||
|
return switch (mode) {
|
||||||
|
case CONTAINS -> path.contains(this.path);
|
||||||
|
case ENDS_WITH -> path.endsWith(this.path);
|
||||||
|
case EQUALS -> path.equals(this.path);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Exclusion contains(String exclusionPattern) {
|
||||||
|
return new Exclusion(exclusionPattern, MatchingMode.CONTAINS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Exclusion endsWith(String exclusionPattern) {
|
||||||
|
return new Exclusion(exclusionPattern, MatchingMode.ENDS_WITH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private final EvictingQueue<HttpExchange> traces = EvictingQueue.create(10000);
|
private final EvictingQueue<HttpExchange> traces = EvictingQueue.create(10000);
|
||||||
private final List<String> exclusionList =
|
private final List<Exclusion> exclusionList =
|
||||||
List.of(
|
List.of(
|
||||||
"/tmpdir",
|
contains("/tmpdir"),
|
||||||
"/home",
|
contains("/home"),
|
||||||
"/files",
|
endsWith("/files"),
|
||||||
"/images/",
|
contains("/images/"),
|
||||||
"/js/",
|
contains("/js/"),
|
||||||
"/webjars/",
|
contains("/webjars/"),
|
||||||
"/requests",
|
contains("/requests"),
|
||||||
"/css/",
|
contains("/css/"),
|
||||||
"/mail");
|
contains("/mail"));
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<HttpExchange> findAll() {
|
public List<HttpExchange> findAll() {
|
||||||
return List.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<HttpExchange> findAllTraces() {
|
|
||||||
return new ArrayList<>(traces);
|
return new ArrayList<>(traces);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isInExclusionList(String path) {
|
private boolean isInExclusionList(String path) {
|
||||||
return exclusionList.stream().anyMatch(e -> path.contains(e));
|
return exclusionList.stream().anyMatch(e -> e.matches(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
server.error.include-stacktrace=always
|
server.error.include-stacktrace=always
|
||||||
server.error.path=/error.html
|
server.error.path=/error.html
|
||||||
server.servlet.context-path=${webgoat.context}
|
server.servlet.context-path=${WEBGOAT_CONTEXT:/WebGoat}
|
||||||
server.servlet.session.persistent=false
|
server.servlet.session.persistent=false
|
||||||
server.port=${webgoat.port}
|
server.port=${WEBGOAT_PORT:8080}
|
||||||
server.address=${webgoat.host}
|
server.address=${WEBGOAT_HOST:127.0.0.1}
|
||||||
webgoat.host=${WEBGOAT_HOST:127.0.0.1}
|
webgoat.host=${WEBGOAT_HOST:127.0.0.1}
|
||||||
webgoat.port=${WEBGOAT_PORT:8080}
|
webgoat.port=${WEBGOAT_PORT:8080}
|
||||||
webgoat.context=${WEBGOAT_CONTEXT:/WebGoat}
|
webgoat.context=${WEBGOAT_CONTEXT:/WebGoat}
|
||||||
@ -43,11 +43,12 @@ webgoat.feedback.address=webgoat@owasp.org
|
|||||||
webgoat.feedback.address.html=<A HREF=mailto:webgoat@owasp.org>webgoat@owasp.org</A>
|
webgoat.feedback.address.html=<A HREF=mailto:webgoat@owasp.org>webgoat@owasp.org</A>
|
||||||
webgoat.database.connection.string=jdbc:hsqldb:mem:{USER}
|
webgoat.database.connection.string=jdbc:hsqldb:mem:{USER}
|
||||||
webgoat.default.language=en
|
webgoat.default.language=en
|
||||||
|
webgoat.url=http://${server.address}:${server.port}${server.servlet.context-path}
|
||||||
|
|
||||||
webwolf.host=${WEBWOLF_HOST:127.0.0.1}
|
webwolf.host=${WEBWOLF_HOST:127.0.0.1}
|
||||||
webwolf.port=${WEBWOLF_PORT:9090}
|
webwolf.port=${WEBWOLF_PORT:9090}
|
||||||
webwolf.context=${WEBWOLF_CONTEXT:/WebWolf}
|
webwolf.context=${WEBWOLF_CONTEXT:/WebWolf}
|
||||||
webwolf.url=http://${webwolf.host}:${webwolf.port}${webwolf.context}
|
webwolf.url=http://${WEBWOLF_HOST:127.0.0.1}:${WEBWOLF_PORT:9090}${WEBWOLF_CONTEXT:/WebWolf}
|
||||||
webwolf.landingpage.url=${webwolf.url}/landing
|
webwolf.landingpage.url=${webwolf.url}/landing
|
||||||
webwolf.mail.url=${webwolf.url}/mail
|
webwolf.mail.url=${webwolf.url}/mail
|
||||||
|
|
||||||
|
@ -2,12 +2,11 @@
|
|||||||
|
|
||||||
== Concept
|
== Concept
|
||||||
|
|
||||||
The way we build software has changed. The open source community is maturing and the availability of open source software has become prolific without regard to determining the provenance of the libraries used in our applications. Ref: https://www.sonatype.com/hubfs/SSC/Software_Supply_Chain_Inforgraphic.pdf?t=1485298506170[Software Supply Chain]
|
The way we build software has changed. The open source community is maturing and the availability of open source software has become prolific without regard to determining the provenance of the libraries used in our applications. Ref: https://www.sonatype.com/state-of-the-software-supply-chain/introduction[Software Supply Chain]
|
||||||
|
|
||||||
This lesson will walk through the difficulties with managing dependent libraries, the risk of not managing those dependencies, and the difficulty in determining if you are at risk.
|
This lesson will walk through the difficulties with managing dependent libraries, the risk of not managing those dependencies, and the difficulty in determining if you are at risk.
|
||||||
|
|
||||||
image::images/OpenSourceGrowing.png[caption="Figure: ", title="Software Supply Chain", alt="SSC", width="500", height="300", style="lesson-image" link="https://www.sonatype.com/hubfs/SSC/Software_Supply_Chain_Inforgraphic.pdf?t=1485298506170[Software Supply Chain"]
|
image::images/OpenSourceGrowing2023.png[caption="Figure: ", title="The continued growth of Open Source software.", alt="SSC", width="500", height="262", style="lesson-image" link=https://www.sonatype.com/state-of-the-software-supply-chain/introduction]
|
||||||
|
|
||||||
|
|
||||||
== Goals
|
== Goals
|
||||||
|
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 148 KiB |
Binary file not shown.
After Width: | Height: | Size: 220 KiB |
@ -75,7 +75,6 @@ textarea {
|
|||||||
/*Mailbox*/
|
/*Mailbox*/
|
||||||
body {
|
body {
|
||||||
margin: 0 0 10px;
|
margin: 0 0 10px;
|
||||||
font-family: 'Font Awesome 5 Free';
|
|
||||||
font-size: medium;
|
font-size: medium;
|
||||||
}
|
}
|
||||||
.nav-tabs .glyphicon:not(.no-margin) { margin-right:10px; }
|
.nav-tabs .glyphicon:not(.no-margin) { margin-right:10px; }
|
||||||
|
@ -9,8 +9,7 @@
|
|||||||
|
|
||||||
<script type="text/javascript" th:src="@{/js/fileUpload.js}"></script>
|
<script type="text/javascript" th:src="@{/js/fileUpload.js}"></script>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container mt-1">
|
||||||
|
|
||||||
<div class="alert alert-info alert-dismissible fade show" role="alert">
|
<div class="alert alert-info alert-dismissible fade show" role="alert">
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
@ -28,45 +27,42 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-heading"><strong>Upload a file</strong>
|
|
||||||
<small></small>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
<h5 class="card-title"><strong>Upload a file</strong></h5>
|
||||||
<!-- Standard Form -->
|
|
||||||
<form th:action="@{/fileupload}" method="post" enctype="multipart/form-data">
|
<form th:action="@{/fileupload}" method="post" enctype="multipart/form-data">
|
||||||
<div class="form-inline">
|
<fieldset>
|
||||||
<div class="form-group">
|
<div class="mb-3">
|
||||||
<input type="file" name="file"/>
|
<input type="file" class="form-control" name="file"/>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
<button type="submit" class="btn btn-md btn-primary">Upload files</button>
|
<button type="submit" class="btn btn-md btn-primary">Upload files</button>
|
||||||
</div>
|
</div>
|
||||||
|
</fieldset>
|
||||||
</form>
|
</form>
|
||||||
<div class="fileUploadAlert alert-success top10" role="alert">
|
|
||||||
<span th:text="${uploadSuccess}"></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="container mt-3">
|
||||||
|
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<thead class="thead-inverse">
|
<thead class="thead-inverse">
|
||||||
<tr>
|
<tr>
|
||||||
<th>Filename</th>
|
<th>Filename</th>
|
||||||
<th>Size</th>
|
<th>Size</th>
|
||||||
<th>Link</th>
|
<th>Creation time</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr th:each="f : ${files}">
|
<tr th:each="f : ${files}">
|
||||||
<td th:text="${f.name}">filename</td>
|
<td><a th:id="fileLink" th:href="@{'/' + ${f.link}}" th:text="${f.name}">link</a>
|
||||||
<td th:text="${f.size}">size</td>
|
|
||||||
<td><a th:id="fileLink" th:href="@{'/' + ${f.link}}">link</a>
|
|
||||||
<span class="fa fa-files-o" title="Click to copy to clipboard"></span>
|
|
||||||
</td>
|
</td>
|
||||||
|
<td th:text="${f.size}">size</td>
|
||||||
|
<td th:text="${f.creationTime}">creation time</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -13,10 +13,7 @@
|
|||||||
<body>
|
<body>
|
||||||
<div th:fragment="header">
|
<div th:fragment="header">
|
||||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||||
<div class="container-fluid">
|
|
||||||
<div class="navbar-item">
|
|
||||||
<a class="navbar-brand" th:href="@{/home}">WebWolf</a>
|
<a class="navbar-brand" th:href="@{/home}">WebWolf</a>
|
||||||
</div>
|
|
||||||
|
|
||||||
<ul class="nav navbar-nav">
|
<ul class="nav navbar-nav">
|
||||||
<li class="nav-item"><a class="nav-link" th:href="@{/home}">Home</a></li>
|
<li class="nav-item"><a class="nav-link" th:href="@{/home}">Home</a></li>
|
||||||
@ -25,8 +22,7 @@
|
|||||||
<li class="nav-item"><a class="nav-link" th:href="@{/requests}">Incoming requests</a></li>
|
<li class="nav-item"><a class="nav-link" th:href="@{/requests}">Incoming requests</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" th:href="@{/jwt}">JWT</a></li>
|
<li class="nav-item"><a class="nav-link" th:href="@{/jwt}">JWT</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul class="nav navbar-nav navbar-right">
|
<ul class="navbar-nav position-absolute end-0 mx-3">
|
||||||
|
|
||||||
<li class="nav-item"><a class="nav-link" href="#">
|
<li class="nav-item"><a class="nav-link" href="#">
|
||||||
<span sec:authorize="isAuthenticated()">
|
<span sec:authorize="isAuthenticated()">
|
||||||
<span class="glyphicon glyphicon-user"></span>
|
<span class="glyphicon glyphicon-user"></span>
|
||||||
@ -37,9 +33,9 @@
|
|||||||
Sign out</span></a>
|
Sign out</span></a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
<h1 class="h2">WebWolf</h1>
|
<h1 class="h2">WebWolf</h1>
|
||||||
<br/>
|
<br/>
|
||||||
<p>
|
<p>
|
||||||
Some challenges requires to have a local web server running. WebWolf is for you the attacker it
|
Some challenges require to have a local web server running. WebWolf is for you the attacker it
|
||||||
helps you while solving some assignments and challenges within
|
helps you while solving some assignments and challenges within
|
||||||
WebGoat. An assignment might for example require you to serve a file or connect back to your own
|
WebGoat. An assignment might for example require you to serve a file or connect back to your own
|
||||||
environment or to receive an e-mail.
|
environment or to receive an e-mail.
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
<script type="text/javascript" th:src="@{/js/jwt.js}"></script>
|
<script type="text/javascript" th:src="@{/js/jwt.js}"></script>
|
||||||
|
|
||||||
|
|
||||||
<div class="container">
|
<div class="container mt-3">
|
||||||
|
|
||||||
<div class="alert alert-info alert-dismissible fade show">
|
<div class="alert alert-info alert-dismissible fade show">
|
||||||
<div>
|
<div>
|
||||||
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
|
<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="token">Encoded</label>
|
<label for="token"><strong>Encoded</strong></label>
|
||||||
<form id="decodeForm">
|
<form id="decodeForm">
|
||||||
<textarea class="form-control" style="font-size: 14pt; font-family:monospace;" id="token" name="token"
|
<textarea class="form-control" style="font-size: 14pt; font-family:monospace;" id="token" name="token"
|
||||||
rows="4"
|
rows="4"
|
||||||
@ -31,8 +31,8 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<form id="encodeForm">
|
<form id="encodeForm">
|
||||||
<div class="form-group">
|
<div class="form-group mt-2">
|
||||||
<label>Decoded</label>
|
<label><strong>Decoded</strong></label>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-6 col-md-5">Header</div>
|
<div class="col-xs-6 col-md-5">Header</div>
|
||||||
<div class="col-xs-6 col-md-7">Payload</div>
|
<div class="col-xs-6 col-md-7">Payload</div>
|
||||||
@ -52,13 +52,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<br/>
|
<div class="input-group input-group-sm mb-3 mt-3">
|
||||||
<div class="input-group">
|
<span class="input-group-text" id="inputGroup-sizing-sm">Secret key</span>
|
||||||
<span class="input-group-addon">Secret key</span>
|
<input type="text" class="form-control" id="secretKey" placeholder="Enter your secret key" aria-describedby="inputGroup-sizing-sm">
|
||||||
<input type="text" placeholder="Enter your secret key" class="form-control" id="secretKey">
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="input-group">
|
<div class="input-group mt-2">
|
||||||
<h4 id="signatureValid">Invalid signature</h4>
|
<h4 id="signatureValid">Invalid signature</h4>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
|
|
||||||
|
|
||||||
<div class="alert alert-info alert-dismissible fade show">
|
<div class="alert alert-info alert-dismissible fade show mt-3">
|
||||||
<div>
|
<div>
|
||||||
<The mailbox of you as an attacker, all the mail send to <th:block th:text="${username}" />@webgoat.org will be send to this mailbox.
|
<The mailbox of you as an attacker, all the mail send to <th:block th:text="${username}" />@webgoat.org will be send to this mailbox.
|
||||||
</p>
|
</p>
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
|
|
||||||
|
|
||||||
<div class="alert alert-info alert-dismissible fade show">
|
<div class="alert alert-info alert-dismissible fade show mt-3">
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
Challenges in which you need to call your hacker machine WebWolf offers a simple httpd
|
Challenges in which you need to call your hacker machine WebWolf offers a simple httpd
|
||||||
@ -29,16 +29,16 @@
|
|||||||
|
|
||||||
|
|
||||||
<h3>Requests</h3>
|
<h3>Requests</h3>
|
||||||
<div th:each="trace,iter : ${traces}" class="card-group" id="accordion" role="tablist" aria-multiselectable="true">
|
<div th:each="trace,iter : ${traces}" class="card-group mt-1" id="accordion" role="tablist" aria-multiselectable="true">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-heading" role="tab" th:id="'heading' + ${iter.index}">
|
<div class="card-heading" role="tab" th:id="'heading' + ${iter.index}">
|
||||||
<h4 class="card-title">
|
<strong class="card-title">
|
||||||
<a class="collapsed" role="button" data-bs-toggle="collapse" data-bs-parent="#accordion"
|
<a class="collapsed" role="button" data-bs-toggle="collapse" data-bs-parent="#accordion"
|
||||||
th:href="'#collapse' + ${iter.index}" aria-expanded="false" th:aria-controls="'collapse' + ${iter.index}">
|
th:href="'#collapse' + ${iter.index}" aria-expanded="false" th:aria-controls="'collapse' + ${iter.index}">
|
||||||
<i class="bi bi-chevron-down"></i> <!-- FontAwesome icon -->
|
<i class="bi bi-chevron-down"></i> <!-- FontAwesome icon -->
|
||||||
<span th:utext="${trace.date}"/> | <span th:utext="${trace.path}"/>
|
<span th:utext="${trace.date}"/> | <span th:utext="${trace.path}"/>
|
||||||
</a>
|
</a>
|
||||||
</h4>
|
</strong>
|
||||||
</div>
|
</div>
|
||||||
<div th:id="'collapse' + ${iter.index}" class="card-collapse collapse" role="tabcard"
|
<div th:id="'collapse' + ${iter.index}" class="card-collapse collapse" role="tabcard"
|
||||||
th:aria-labelledby="'heading' + ${iter.index}">
|
th:aria-labelledby="'heading' + ${iter.index}">
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|
||||||
<div class="row" style="margin-top:20px">
|
<div class="row" style="margin-top:100px">
|
||||||
<div class="col-xs-12 col-sm-8 col-md-6 col-sm-offset-2 col-md-offset-3" th:style="'background:url(' + @{/images/wolf.png} + ') no-repeat right;'">
|
<div class="col-xs-12 col-sm-8 col-md-6 col-sm-offset-2 col-md-offset-3" th:style="'background:url(' + @{/images/wolf.png} + ') no-repeat right;'">
|
||||||
<form th:action="@{/login}" method="post">
|
<form th:action="@{/login}" method="post">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
@ -28,12 +28,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="input-group mb-3">
|
||||||
<input type="text" name="username" id="username" class="form-control input-lg"
|
<input type="text" name="username" id="username" class="form-control"
|
||||||
placeholder="Username WebGoat" required="true" autofocus="true"/>
|
placeholder="Username WebGoat" required="true" autofocus="true"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="input-group mb-3">
|
||||||
<input type="password" name="password" id="password" class="form-control input-lg"
|
<input type="password" name="password" id="password" class="form-control"
|
||||||
placeholder="Password WebGoat" required="true"/>
|
placeholder="Password WebGoat" required="true"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
package org.owasp.webgoat.webwolf.requests;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import org.assertj.core.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.boot.actuate.web.exchanges.HttpExchange;
|
||||||
|
|
||||||
|
class WebWolfTraceRepositoryTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("When a user hits a file upload it should be recorded")
|
||||||
|
void shouldAddFilesRequest() {
|
||||||
|
HttpExchange httpExchange = mock();
|
||||||
|
HttpExchange.Request request = mock();
|
||||||
|
when(httpExchange.getRequest()).thenReturn(request);
|
||||||
|
when(request.getUri()).thenReturn(URI.create("http://localhost:9090/files/test1234/test.jpg"));
|
||||||
|
WebWolfTraceRepository repository = new WebWolfTraceRepository();
|
||||||
|
|
||||||
|
repository.add(httpExchange);
|
||||||
|
|
||||||
|
Assertions.assertThat(repository.findAll()).hasSize(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("When a user hits file upload page ('/files') it should be recorded")
|
||||||
|
void shouldAddNotAddFilesRequestOverview() {
|
||||||
|
HttpExchange httpExchange = mock();
|
||||||
|
HttpExchange.Request request = mock();
|
||||||
|
when(httpExchange.getRequest()).thenReturn(request);
|
||||||
|
when(request.getUri()).thenReturn(URI.create("http://localhost:9090/files"));
|
||||||
|
WebWolfTraceRepository repository = new WebWolfTraceRepository();
|
||||||
|
|
||||||
|
repository.add(httpExchange);
|
||||||
|
|
||||||
|
Assertions.assertThat(repository.findAll()).hasSize(0);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user