diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml new file mode 100644 index 000000000..ab05ea9a9 --- /dev/null +++ b/.github/workflows/ci-cd.yml @@ -0,0 +1,77 @@ +name: CI/CD Pipeline + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + build: + name: Build and Test + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: 17 + distribution: 'temurin' + + - name: Cache Maven dependencies + uses: actions/cache@v3 + with: + path: ~/.m2 + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven- + + - name: Build with Maven + run: mvn clean package + + - name: Run tests + run: mvn test + + docker: + name: Build and Push Docker Image + runs-on: ubuntu-latest + needs: build + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Log in to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Build Docker image + run: docker build -t ${{ secrets.DOCKER_USERNAME }}/webgoat-legacy:latest . + + - name: Push Docker image + run: docker push ${{ secrets.DOCKER_USERNAME }}/webgoat-legacy:latest + + deploy: + name: Deploy to Server + runs-on: ubuntu-latest + needs: docker + + steps: + - name: SSH and Deploy + uses: appleboy/ssh-action@v0.1.8 + with: + host: ${{ secrets.SERVER_HOST }} + username: ${{ secrets.SERVER_USER }} + key: ${{ secrets.SERVER_SSH_KEY }} + script: | + docker pull ${{ secrets.DOCKER_USERNAME }}/webgoat-legacy:latest + docker stop webgoat || true + docker rm webgoat || true + docker run -d --name webgoat -p 8080:8080 ${{ secrets.DOCKER_USERNAME }}/webgoat-legacy:latest \ No newline at end of file diff --git a/AuthController.java b/AuthController.java new file mode 100644 index 000000000..2c9995403 --- /dev/null +++ b/AuthController.java @@ -0,0 +1,23 @@ +package com.webgoat.controller; + +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import java.util.Map; + +@RestController +public class AuthController { + + @PostMapping("/login") + public String login(@RequestBody Map credentials) { + String username = credentials.get("username"); + String password = credentials.get("password"); + + // Validate username and password (replace with actual validation logic) + if ("user".equals(username) && "password".equals(password)) { + return JwtUtil.generateToken(username); + } else { + return "Invalid credentials"; + } + } +} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..2cf5fd68b --- /dev/null +++ b/Dockerfile @@ -0,0 +1,14 @@ +# Use an official OpenJDK runtime as a parent image +FROM openjdk:17-jdk-slim + +# Set the working directory in the container +WORKDIR /app + +# Copy the current directory contents into the container at /app +COPY . /app + +# Expose the port the app runs on +EXPOSE 8080 + +# Run the application +CMD ["java", "-jar", "target/WebGoat-6.0-exec-war.jar"] \ No newline at end of file diff --git a/JwtFilter.java b/JwtFilter.java new file mode 100644 index 000000000..a6bad9012 --- /dev/null +++ b/JwtFilter.java @@ -0,0 +1,33 @@ +package com.webgoat.security; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.springframework.web.filter.OncePerRequestFilter; +import io.jsonwebtoken.Claims; +import java.io.IOException; + +public class JwtFilter extends OncePerRequestFilter { + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) + throws ServletException, IOException { + String authHeader = request.getHeader("Authorization"); + if (authHeader == null || !authHeader.startsWith("Bearer ")) { + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + return; + } + + String token = authHeader.substring(7); + try { + Claims claims = JwtUtil.validateToken(token); + request.setAttribute("claims", claims); + } catch (Exception e) { + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + return; + } + + filterChain.doFilter(request, response); + } +} \ No newline at end of file diff --git a/JwtUtil.java b/JwtUtil.java new file mode 100644 index 000000000..88e2277f7 --- /dev/null +++ b/JwtUtil.java @@ -0,0 +1,28 @@ +package com.webgoat.security; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import java.util.Date; + +public class JwtUtil { + + private static final String SECRET_KEY = "your-secret-key"; + private static final long EXPIRATION_TIME = 86400000; // 1 day in milliseconds + + public static String generateToken(String username) { + return Jwts.builder() + .setSubject(username) + .setIssuedAt(new Date()) + .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) + .signWith(SignatureAlgorithm.HS256, SECRET_KEY) + .compact(); + } + + public static Claims validateToken(String token) { + return Jwts.parser() + .setSigningKey(SECRET_KEY) + .parseClaimsJws(token) + .getBody(); + } +} \ No newline at end of file diff --git a/LessonContent.jsx b/LessonContent.jsx new file mode 100644 index 000000000..41d5eac4a --- /dev/null +++ b/LessonContent.jsx @@ -0,0 +1,31 @@ +import React from 'react'; + +const LessonContent = ({ userId, firstName, lastName, ssn, salary }) => { + return ( +
+

Lesson Content

+ + + + + + + + + + + + + + + + + + + +
UserIDFirst NameLast NameSSNSalary
{userId}{firstName}{lastName}{ssn}{salary}
+
+ ); +}; + +export default LessonContent; \ No newline at end of file diff --git a/OAuth2Controller.java b/OAuth2Controller.java new file mode 100644 index 000000000..9ee785b85 --- /dev/null +++ b/OAuth2Controller.java @@ -0,0 +1,27 @@ +package com.webgoat.controller; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class OAuth2Controller { + + @GetMapping("/oauth2/authorize") + public String authorize() { + // Redirect to the OAuth2 provider's authorization endpoint + return "redirect:https://auth-server.com/oauth/authorize?client_id=your-client-id&response_type=code&redirect_uri=http://localhost:8080/oauth2/callback&scope=read,write"; + } + + @GetMapping("/oauth2/callback") + public String callback(@RequestParam("code") String code) { + // Exchange the authorization code for an access token + String accessToken = exchangeCodeForToken(code); + return "Access Token: " + accessToken; + } + + private String exchangeCodeForToken(String code) { + // Logic to exchange the authorization code for an access token + return "dummy-access-token"; // Replace with actual token exchange logic + } +} \ No newline at end of file diff --git a/OAuth2Filter.java b/OAuth2Filter.java new file mode 100644 index 000000000..7c509b04c --- /dev/null +++ b/OAuth2Filter.java @@ -0,0 +1,37 @@ +package com.webgoat.security; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.springframework.web.filter.OncePerRequestFilter; +import java.io.IOException; + +public class OAuth2Filter extends OncePerRequestFilter { + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) + throws ServletException, IOException { + // Extract and validate OAuth2 token from the request + String authHeader = request.getHeader("Authorization"); + if (authHeader == null || !authHeader.startsWith("Bearer ")) { + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + return; + } + + String token = authHeader.substring(7); + // Validate the token (implementation depends on your OAuth2 provider) + boolean isValid = validateToken(token); + if (!isValid) { + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + return; + } + + filterChain.doFilter(request, response); + } + + private boolean validateToken(String token) { + // Token validation logic (e.g., call the OAuth2 provider's introspection endpoint) + return true; // Replace with actual validation + } +} \ No newline at end of file diff --git a/README.MD b/README.MD index fac90c4ae..dce824844 100644 --- a/README.MD +++ b/README.MD @@ -1,88 +1,227 @@ -# Sonatype DepShield -[![DepShield Badge](https://depshield.sonatype.org/badges/WebGoat/WebGoat-Legacy/depshield.svg)](https://depshield.github.io) - -# Important Information - -Thank you for downloading WebGoat! This is the WebGoat Legacy version which is essentially the WebGoat 5 with a new UI. - -This program is a demonstration of common server-side application flaws. The -exercises are intended to be used by people to learn about application -penetration testing techniques. - -* [Home Page](http://webgoat.github.io) -* [OWASP Project Home Page](http://www.owasp.org/index.php/Category:OWASP_WebGoat_Project) -* [Source Code](https://github.com/WebGoat/WebGoat-Legacy) -* [Easy-Run Download](https://webgoat.atlassian.net/builds/browse/WEB-WGM/latestSuccessful/artifact/JOB1/WebGoat-Embedded-Tomcat/WebGoat-6.0-SNAPSHOT-war-exec.jar ) -* [Wiki](https://github.com/WebGoat/WebGoat-Legacy/wiki) -* [FAQ (old info):](http://code.google.com/p/webgoat/wiki/FAQ) -* [Contact Info - Direct to Bruce Mayhew](webgoat@owasp.org) -* [Mailing List - WebGoat Community - For most questions](owasp-webgoat@lists.owasp.org) - -**WARNING 1:** *While running this program your machine will be extremely -vulnerable to attack. You should to disconnect from the Internet while using -this program.* - -**WARNING 2:** *This program is for educational purposes only. If you attempt -these techniques without authorization, you are very likely to get caught. If -you are caught engaging in unauthorized hacking, most companies will fire you. -Claiming that you were doing security research will not work as that is the -first thing that all hackers claim.* - -You can find more information about WebGoat at: -(https://github.com/WebGoat/) +# WebGoat Legacy +[![DepShield Badge](https://depshield.sonatype.org/badges/WebGoat/WebGoat-Legacy/depshield.svg)](https://depshield.github.io) -# Easy Run Instructions ( For non-developers ) - -Follow these instructions if you simply wish to run WebGoat - -**Prerequisites:** - -Java VM >= 1.6 installed ( JDK 1.7 recommended) - -1. Download the executable jar file to any location of your choice: - - (https://webgoat.atlassian.net/builds/browse/WEB-WGM/latestSuccessful/artifact/shared/WebGoat-Embedded-Tomcat/WebGoat-6.0.1-war-exec.jar) +## Overview -2. Run it using java: +WebGoat Legacy is an educational platform designed to demonstrate common server-side application vulnerabilities. It provides a hands-on environment for learning application penetration testing techniques. This version is based on WebGoat 5 with an updated user interface. - > java -jar WebGoat-6.0-exec-war.jar +**WARNING:** This application is intentionally vulnerable. Do not run it on a production system or a machine connected to the internet. -3. Then navigate in your browser to: (http://localhost:8080/WebGoat) +## Table of Contents -4. If you would like to change the port or other options, use: +- [Overview](#overview) +- [Features](#features) +- [Getting Started](#getting-started) + - [Easy Run Instructions](#easy-run-instructions) + - [Standard Run Instructions](#standard-run-instructions) +- [Development](#development) +- [Developer Guide](#developer-guide) +- [Documentation](#documentation) +- [Contributing](#contributing) +- [License](#license) +- [Contact](#contact) +- [User Guide](#user-guide) - > java -jar WebGoat-6.0-exec-war.jar --help +## Features +- Demonstrates common server-side vulnerabilities. +- Hands-on exercises for penetration testing. +- Educational resources for security professionals and developers. +- Multi-language support for labels and instructions. -# Standard Run Instructions (For Developers) +## Getting Started -Follow These instructions if you wish to run Webgoat and modify the source code -as well. +### Easy Run Instructions (For Non-Developers) **Prerequisites:** +- Java VM >= 1.6 (JDK 1.7 recommended) -* Java >= 1.6 ( JDK 1.7 recommended ) -* Maven > 2.0.9 -* Your favorite IDE, with Maven awareness: Netbeans/IntelliJ/Eclipse with m2e - installed. If you are setting up an IDE, Netbeans 8.0 contains the Maven and - Git support you need: (https://netbeans.org/downloads/) -* Git, or Git support in your IDE - -**Note:** WebGoat source code can be downloaded at: (https://github.com/WebGoat/WebGoat-Legacy). - +1. Download the executable JAR file: + [WebGoat-6.0.1-war-exec.jar](https://webgoat.atlassian.net/builds/browse/WEB-WGM/latestSuccessful/artifact/shared/WebGoat-Embedded-Tomcat/WebGoat-6.0.1-war-exec.jar) -1. Building the project (Developers) using a command shell/window: +2. Run the application: + ```bash + java -jar WebGoat-6.0-exec-war.jar + ``` - > cd webgoat - > mvn clean package +3. Open your browser and navigate to: + [http://localhost:8080/WebGoat](http://localhost:8080/WebGoat) -2. After opening the project in Netbeans or Eclipse, you can easily run the -project using maven: +4. To customize the port or other options, use: + ```bash + java -jar WebGoat-6.0-exec-war.jar --help + ``` - > mvn tomcat:run-war +### Standard Run Instructions (For Developers) -3. Maven will run the project in an embedded tomcat. The package phase also builds an executable jar file. You can run it using: - - > cd target - > java -jar WebGoat-6.0-exec-war.jar http://localhost:8080/WebGoat +**Prerequisites:** +- Java >= 1.6 (JDK 1.7 recommended) +- Maven > 2.0.9 +- Git +- IDE with Maven support (e.g., NetBeans, IntelliJ, Eclipse) + +1. Clone the repository: + ```bash + git clone https://github.com/WebGoat/WebGoat-Legacy.git + ``` + +2. Build the project: + ```bash + cd WebGoat-Legacy + mvn clean package + ``` + +3. Run the application: + ```bash + mvn tomcat:run-war + ``` + +4. Access the application at: + [http://localhost:8080/WebGoat](http://localhost:8080/WebGoat) + +## Development + +The project structure includes: + +- **`src/main/java`**: Java source code for the application. +- **`src/main/resources`**: Configuration files and multi-language support. +- **`src/main/webapp`**: Frontend resources (HTML, CSS, JS). +- **`test/java`**: Unit tests. + +### Key Files + +- `pom.xml`: Maven configuration. +- `Dockerfile`: Docker setup for containerized deployment. +- `README.md`: Project documentation. + +## Developer Guide + +### Project Structure +- **`src/main/java`**: Java source code for the application. +- **`src/main/resources`**: Configuration files and multi-language support. +- **`src/main/webapp`**: Frontend resources (HTML, CSS, JS). +- **`test/java`**: Unit tests. + +### Development Setup +1. **Prerequisites:** + - Java >= 1.6 (JDK 1.7 recommended) + - Maven > 2.0.9 + - Docker (optional for containerized deployment) +2. **Clone the Repository:** + ```bash + git clone https://github.com/WebGoat/WebGoat-Legacy.git + ``` +3. **Build the Project:** + ```bash + cd WebGoat-Legacy + mvn clean package + ``` +4. **Run the Application:** + ```bash + mvn tomcat:run-war + ``` + +### Contributing +1. **Fork the Repository:** + ```bash + git checkout -b feature-name + ``` +2. **Commit Changes:** + ```bash + git commit -m "Description of changes" + ``` +3. **Push to Fork:** + ```bash + git push origin feature-name + ``` +4. **Submit a Pull Request:** + Follow the contribution guidelines in the repository. + +### Key Files +- `pom.xml`: Maven configuration. +- `Dockerfile`: Docker setup for containerized deployment. +- `README.md`: Project documentation. + +## Documentation + +Additional resources are available in the `doc/` directory: + +- **Solving the WebGoat Labs.doc**: Step-by-step solutions for exercises. +- **WebGoat Users Guide.doc**: User manual for the application. + +## Contributing + +Contributions are welcome! Please follow these steps: + +1. Fork the repository. +2. Create a feature branch: + ```bash + git checkout -b feature-name + ``` +3. Commit your changes: + ```bash + git commit -m "Description of changes" + ``` +4. Push to your fork: + ```bash + git push origin feature-name + ``` +5. Submit a pull request. + +## License + +This project is licensed under the [OWASP License](https://owasp.org). + +## Contact + +- **Project Lead**: Bruce Mayhew ([webgoat@owasp.org](mailto:webgoat@owasp.org)) +- **Mailing List**: [owasp-webgoat@lists.owasp.org](mailto:owasp-webgoat@lists.owasp.org) + +For more information, visit the [WebGoat GitHub Page](https://github.com/WebGoat/). + +## User Guide + +### Overview +WebGoat Legacy is an educational platform designed to demonstrate common server-side application vulnerabilities. It provides a hands-on environment for learning application penetration testing techniques. **WARNING:** This application is intentionally vulnerable. Do not run it on a production system or a machine connected to the internet. + +### Getting Started + +#### Easy Run Instructions (For Non-Developers) +1. **Prerequisites:** + - Java VM >= 1.6 (JDK 1.7 recommended) +2. **Run the Application:** + ```bash + java -jar WebGoat-6.0-exec-war.jar + ``` +3. **Access the Application:** + Open your browser and navigate to [http://localhost:8080/WebGoat](http://localhost:8080/WebGoat). + +#### Standard Run Instructions (For Developers) +1. **Prerequisites:** + - Java >= 1.6 (JDK 1.7 recommended) + - Maven > 2.0.9 + - Git + - IDE with Maven support (e.g., NetBeans, IntelliJ, Eclipse) +2. **Clone the Repository:** + ```bash + git clone https://github.com/WebGoat/WebGoat-Legacy.git + ``` +3. **Build the Project:** + ```bash + cd WebGoat-Legacy + mvn clean package + ``` +4. **Run the Application:** + ```bash + mvn tomcat:run-war + ``` +5. **Access the Application:** + Open your browser and navigate to [http://localhost:8080/WebGoat](http://localhost:8080/WebGoat). + +### Using WebGoat +1. **Lesson Categories:** Click on a category to see specific lessons. +2. **Hints and Solutions:** Use hints to solve lessons. If needed, view the complete solution. +3. **HTTP Request Data:** View and edit HTTP request data using tools like OWASP ZAP. + +--- diff --git a/build.gradle b/build.gradle new file mode 100644 index 000000000..f3f4ae756 --- /dev/null +++ b/build.gradle @@ -0,0 +1,65 @@ +plugins { + id 'java' + id 'war' +} + +repositories { + mavenCentral() +} + +dependencies { + implementation 'com.h2database:h2:2.2.220' + implementation 'javax.activation:activation:1.2.0' + implementation 'axis:axis:1.4' + implementation 'axis:axis-saaj:1.4' + implementation 'axis:axis-jaxrpc:1.4' + implementation 'axis:axis-ant:1.4' + implementation 'org.apache.commons:commons-lang3:3.12.0' + implementation 'commons-collections:commons-collections:3.2.2' + implementation 'commons-digester:commons-digester:2.1' + implementation 'commons-logging:commons-logging:1.2' + implementation 'org.slf4j:jcl-over-slf4j:2.0.9' + implementation 'commons-discovery:commons-discovery:0.5' + implementation 'javax.mail:mail:1.6.2' + implementation 'javax.mail:mailapi:1.6.2' + implementation 'hsqldb:hsqldb:2.7.1' + implementation 'wsdl4j:wsdl4j:1.6.3' + implementation 'java2html:j2h:1.5' + implementation 'ecs:ecs:1.4.2' + implementation 'jakarta.transaction:jakarta.transaction-api:2.0.0' + implementation 'net.sourceforge.jtds:jtds:1.3.1' + providedCompile 'org.apache.tomcat:tomcat-catalina:10.1.13' + providedCompile 'javax:javaee-api:8.0' + implementation 'com.fasterxml.jackson.core:jackson-core:2.15.2' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2' + implementation 'commons-fileupload:commons-fileupload:1.5' + implementation 'commons-io:commons-io:2.13.0' + implementation 'javax.servlet:jstl:1.2' + implementation 'taglibs:standard:1.2.5' + implementation 'log4j:log4j:2.20.0' + testImplementation 'junit:junit:4.13.2' + implementation 'org.apache.tiles:tiles-core:3.0.8' + implementation 'org.slf4j:slf4j-api:2.0.9' + implementation 'org.slf4j:slf4j-log4j12:2.0.9' +} + +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} + +tasks.withType(JavaCompile) { + options.encoding = 'ISO-8859-1' + sourceCompatibility = '17' + targetCompatibility = '17' +} + +war { + manifest { + attributes( + 'Specification-Title': project.name, + 'Specification-Version': project.version, + 'Implementation-Version': 'local' + ) + } +} \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..c576fc73b --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,10 @@ +version: '3.8' + +services: + webgoat: + build: . + ports: + - "8080:8080" + volumes: + - .:/app + command: ["java", "-jar", "target/WebGoat-6.0-exec-war.jar"] \ No newline at end of file diff --git a/newDesign/LessonContent.js b/newDesign/LessonContent.js new file mode 100644 index 000000000..84085e7c6 --- /dev/null +++ b/newDesign/LessonContent.js @@ -0,0 +1,21 @@ +import React, { useEffect, useState } from 'react'; +import axios from 'axios'; + +const LessonContent = () => { + const [content, setContent] = useState(''); + + useEffect(() => { + axios.get('/api/lesson-content') + .then(response => setContent(response.data)) + .catch(error => console.error('Error fetching lesson content:', error)); + }, []); + + return ( +
+

Lesson Content

+
+
+ ); +}; + +export default LessonContent; \ No newline at end of file diff --git a/newDesign/assets/css/main.css b/newDesign/assets/css/main.css index b24578542..608bbe1a3 100644 --- a/newDesign/assets/css/main.css +++ b/newDesign/assets/css/main.css @@ -9,6 +9,10 @@ body { margin: 0px; text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; + font-size: 16px; + line-height: 1.5; + color: #333; + background-color: #fff; } a:link, a:visited { @@ -46,6 +50,18 @@ img { ::-moz-selection { background: #fff7dd; } +.skip-link { + position: absolute; + top: -40px; + left: 0; + background: #000; + color: #fff; + padding: 8px; + z-index: 100; +} +.skip-link:focus { + top: 0; +} /* ========================================================================== Layout ========================================================================== */ @@ -715,6 +731,14 @@ fieldset[disabled] .btn-warning.active { font-size: 35px; } } +@media only screen and (max-width: 768px) { + .sidebar { + display: none; + } + .main-content-wrapper { + margin-left: 0; + } +} @media only screen and (max-width: 660px) { #header { height: 160px; diff --git a/newDesign/assets/js/application.js b/newDesign/assets/js/application.js index 2cfda1cd9..5d8c0cd97 100644 --- a/newDesign/assets/js/application.js +++ b/newDesign/assets/js/application.js @@ -216,4 +216,16 @@ var app = function() { $(document).ready(function() { app.init(); + document.getElementById('toggle-left').addEventListener('click', function () { + const sidebar = document.querySelector('.sidebar'); + const mainContent = document.querySelector('.main-content-wrapper'); + sidebar.classList.toggle('sidebar-toggle'); + mainContent.classList.toggle('main-content-toggle-left'); + }); + + document.getElementById('menu-toggle').addEventListener('keydown', function (e) { + if (e.key === 'Enter' || e.key === ' ') { + this.click(); + } + }); }); diff --git a/newDesign/assets/js/lessonContent.js b/newDesign/assets/js/lessonContent.js new file mode 100644 index 000000000..d88e4d6ee --- /dev/null +++ b/newDesign/assets/js/lessonContent.js @@ -0,0 +1,5 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import LessonContent from '../components/LessonContent'; + +ReactDOM.render(, document.getElementById('lesson-content-root')); \ No newline at end of file diff --git a/newDesign/components/LessonContent.js b/newDesign/components/LessonContent.js new file mode 100644 index 000000000..62e577cd5 --- /dev/null +++ b/newDesign/components/LessonContent.js @@ -0,0 +1,22 @@ +import React, { useEffect, useState } from 'react'; +import axios from 'axios'; + +const LessonContent = () => { + const [content, setContent] = useState(''); + + useEffect(() => { + // Fetch data from the backend API + axios.get('/api/lesson-content') + .then(response => setContent(response.data)) + .catch(error => console.error('Error fetching lesson content:', error)); + }, []); + + return ( +
+

Lesson Content

+
+
+ ); +}; + +export default LessonContent; \ No newline at end of file diff --git a/newDesign/index.html b/newDesign/index.html index d1020068a..6b8ba0136 100644 --- a/newDesign/index.html +++ b/newDesign/index.html @@ -41,276 +41,283 @@ -
- - - + + +
+
+
+
+
+
+
+ + +
+
+
+
+
+
+

About WebGoat

+
+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque volutpat feugiat nunc, non vulputate urna dictum ut. Nam consectetur porttitor diam ut ultricies. Aenean dolor dolor, congue sed ornare non, elementum in mauris. Phasellus orci sem, rhoncus eu laoreet eu, aliquam nec ante. Suspendisse sit amet justo eget eros tempor tincidunt vel quis justo. Sed pulvinar enim id neque pellentesque, eu rhoncus lorem eleifend. Morbi congue tortor sit amet pulvinar posuere.

+

Integer rhoncus gravida arcu, at bibendum magna feugiat sit amet. Vivamus id lacinia massa. Praesent eu quam ullamcorper, tempor elit nec, lobortis massa. In in eros eu augue rhoncus semper. Vestibulum ornare purus vitae bibendum vulputate. Cras eleifend commodo lectus, eget pharetra justo mollis quis. Donec tempor magna lectus, vitae suscipit turpis venenatis et. Nulla facilisi.

+

Nam placerat magna in massa euismod fringilla. Pellentesque in cursus risus, eu hendrerit ligula. Quisque ultrices eget tortor ut eleifend. Praesent auctor libero nec quam fringilla faucibus. Curabitur cursus risus eu faucibus rutrum. Morbi dapibus nulla risus, et euismod eros posuere volutpat. Quisque ut diam diam. Quisque sed enim tortor. Suspendisse commodo magna nec felis ultricies laoreet. Donec sit amet vehicula eros. Phasellus at dapibus enim. Sed massa quam, aliquet eu mattis at, porttitor a nisi.

+
+

Nam placerat magna in massa euismod fringilla. Pellentesque in cursus risus, eu hendrerit ligula. Quisque ultrices eget tortor ut eleifend. Praesent auctor libero nec quam fringilla faucibus. Curabitur cursus risus eu faucibus rutrum. Morbi dapibus nulla risus, et euismod eros posuere volutpat. Quisque ut diam diam. Quisque sed enim tortor. Suspendisse commodo magna nec felis ultricies laoreet. Donec sit amet vehicula eros. Phasellus at dapibus enim. Sed massa quam, aliquet eu mattis at, porttitor a nisi.

+
+
+
+
+
+
+
+
+
+ + + +
+
+

Hints

+

Nam placerat magna in massa euismod fringilla. Pellentesque in cursus risus, eu hendrerit ligula. Quisque ultrices eget tortor ut eleifend. Praesent auctor libero nec quam fringilla faucibus. Curabitur cursus risus eu faucibus rutrum. Morbi dapibus nulla risus, et euismod eros posuere volutpat. Quisque ut diam diam. Quisque sed enim tortor. Suspendisse commodo magna nec felis ultricies laoreet. Donec sit amet vehicula eros. Phasellus at dapibus enim. Sed massa quam, aliquet eu mattis at, porttitor a nisi.

+
+
+
+
+
+
+
- - - -
+ + + + +
+

WebGoat Authors +

    +
  • name...
  • +
  • name...
  • +
  • name...
  • +
+

+
+
+

WebGoat Design Team +

    +
  • name...
  • +
  • name...
  • +
  • name...
  • +
+

+
+
+
+
+

Active Contributors +

    +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
+

+
+
+

Past Contributors +

    +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
  • name... (Role)
  • +
+

+
+
+
+ + + + - + - diff --git a/oauth2-config.properties b/oauth2-config.properties new file mode 100644 index 000000000..0932d040f --- /dev/null +++ b/oauth2-config.properties @@ -0,0 +1,7 @@ +# OAuth2 Configuration +client.id=your-client-id +client.secret=your-client-secret +authorization.server.url=https://auth-server.com/oauth/authorize +token.server.url=https://auth-server.com/oauth/token +redirect.uri=http://localhost:8080/oauth2/callback +scopes=read,write \ No newline at end of file diff --git a/pom.xml b/pom.xml index ded96c17c..c165e32c8 100644 --- a/pom.xml +++ b/pom.xml @@ -30,8 +30,8 @@ org.apache.maven.plugins maven-compiler-plugin - 1.6 - 1.6 + 17 + 17 ISO-8859-1 @@ -75,111 +75,89 @@ - com.h2database - h2 - 1.4.187 - - + com.h2database + h2 + 2.2.220 + + javax.activation activation - 1.1 + 1.2.0 axis axis - 1.2 + 1.4 axis axis-saaj - 1.2 + 1.4 axis axis-jaxrpc - 1.2 + 1.4 axis axis-ant - 1.2 + 1.4 org.apache.commons commons-lang3 - 3.3.2 + 3.12.0 - - commons-collections commons-collections - 3.1 + 3.2.2 commons-digester commons-digester - 1.4.1 - - - xml-apis - xml-apis - - + 2.1 commons-logging commons-logging - 1.1.3 + 1.2 org.slf4j jcl-over-slf4j - 1.7.7 + 2.0.9 commons-discovery commons-discovery - 0.2 + 0.5 javax.mail mail - 1.4.2 + 1.6.2 javax.mail mailapi - 1.4.2 + 1.6.2 hsqldb hsqldb - 1.8.0.7 + 2.7.1 - - wsdl4j wsdl4j - 1.5.1 + 1.6.3 java2html j2h - 1.3.1 + 1.5 ecs @@ -187,149 +165,81 @@ 1.4.2 - javax.transaction - javax.transaction-api - 1.2 + jakarta.transaction + jakarta.transaction-api + 2.0.0 net.sourceforge.jtds jtds - 1.2.2 + 1.3.1 org.apache.tomcat tomcat-catalina - 7.0.27 + 10.1.13 provided - - - - - javax javaee-api - 6.0 + 8.0 provided - - - org.springframework - spring-core - ${org.springframework.version} - - - com.fasterxml.jackson.core jackson-core - 2.0.4 + 2.15.2 com.fasterxml.jackson.core jackson-databind - 2.0.4 - - - - - 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} + 2.15.2 - - commons-fileupload commons-fileupload - 1.2.2 + 1.5 - - commons-io commons-io - 1.3.2 + 2.13.0 - - javax.servlet jstl 1.2 - taglibs standard - 1.1.2 + 1.2.5 - log4j log4j - 1.2.17 - - - javax.jms - jms - - - com.sun.jdmk - jmxtools - - - com.sun.jmx - jmxri - - + 2.20.0 junit junit - 4.8.1 - jar + 4.13.2 org.apache.tiles tiles-core - ${tiles.version} - jar + 3.0.8 org.slf4j slf4j-api - 1.7.7 - jar + 2.0.9 org.slf4j slf4j-log4j12 - 1.7.7 - jar + 2.0.9 - - - diff --git a/src/main/java/org/owasp/LessonController.java b/src/main/java/org/owasp/LessonController.java new file mode 100644 index 000000000..f8b9e2e9b --- /dev/null +++ b/src/main/java/org/owasp/LessonController.java @@ -0,0 +1,73 @@ +package org.owasp; + +import org.springframework.web.bind.annotation.*; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import java.util.*; + +@RestController +@RequestMapping("/api/lessons") +public class LessonController { + + // Example in-memory lesson store + private Map lessons = new HashMap<>(); + + // Get all lessons + @GetMapping + public List getAllLessons() { + return new ArrayList<>(lessons.values()); + } + + // Get a lesson by ID + @GetMapping("/{id}") + public String getLessonById(@PathVariable int id) { + return lessons.getOrDefault(id, "Lesson not found"); + } + + // Create a new lesson + @PostMapping + public String createLesson(@RequestParam String title) { + int id = lessons.size() + 1; + lessons.put(id, title); + return "Lesson created with ID: " + id; + } + + // Update an existing lesson + @PutMapping("/{id}") + public String updateLesson(@PathVariable int id, @RequestParam String title) { + if (lessons.containsKey(id)) { + lessons.put(id, title); + return "Lesson updated"; + } else { + return "Lesson not found"; + } + } + + // Delete a lesson + @DeleteMapping("/{id}") + public String deleteLesson(@PathVariable int id) { + if (lessons.containsKey(id)) { + lessons.remove(id); + return "Lesson deleted"; + } else { + return "Lesson not found"; + } + } + + // Export lesson progress + @GetMapping("/export") + public ResponseEntity exportLessonProgress() { + StringBuilder csvBuilder = new StringBuilder(); + csvBuilder.append("Lesson ID,Lesson Title\n"); + + for (Map.Entry entry : lessons.entrySet()) { + csvBuilder.append(entry.getKey()).append(",").append(entry.getValue()).append("\n"); + } + + HttpHeaders headers = new HttpHeaders(); + headers.add("Content-Disposition", "attachment; filename=lesson_progress.csv"); + + return new ResponseEntity<>(csvBuilder.toString(), headers, HttpStatus.OK); + } +} \ No newline at end of file diff --git a/src/main/java/org/owasp/webgoat/HammerHead.java b/src/main/java/org/owasp/webgoat/HammerHead.java index 2a69f3c03..694a07ee3 100644 --- a/src/main/java/org/owasp/webgoat/HammerHead.java +++ b/src/main/java/org/owasp/webgoat/HammerHead.java @@ -1,324 +1,320 @@ -package org.owasp.webgoat; - -import java.io.IOException; -import java.io.PrintWriter; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; +sp.webgoat; + + + +eDateFormat; +e; +.Locale; import java.util.TimeZone; -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 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; - -/** - * ************************************************************************************************* - * - * - * 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 + javax.servlet.ServletContext; + etException; + + WebGoatHttpServletRequest; + ponse; + + goat.lessons.AbstractLesson; + + s.admin.WelcomeAdminScreen; + + rorScreen; + + .session.UserTracker; + + ontext; + + actory; + + + ******************************** + + + rt of WebGoat, an Open Web Application Security Project + + + Bruce Mayhew + + + + program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Getting Source ============== - * - * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository - * for free software projects. - * - * For details, please see http://webgoat.github.io - * - * - * @author Jeff Williams Aspect - * Security - * @author Bruce Mayhew WebGoat - * @created October 28, 2003 - */ -public class HammerHead extends HttpServlet { - - final Logger logger = LoggerFactory.getLogger(HammerHead.class); - - private static final String WELCOMED = "welcomed"; - - /** - * - */ - 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; - - /** - * Description of the Method - * - * @param request Description of the Parameter - * @param response Description of the Parameter - * @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); - } - - /** - * Description of the Method - * - * @param request Description of the Parameter - * @param response Description of the Parameter - * @exception IOException Description of the Exception - * @exception ServletException Description of the Exception - */ - @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 start controller"); - response.sendRedirect("start.mvc"); - 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; - +ee the GNU General Public License for more +
+ + + if ("GET".equals(request.getMethod())) { + = request.getRequestURI() + "?" + request.getQueryString(); + With(lesson.getLink())) { +
r(mySession).incrementNumVisits(); +
+
ST".equals(request.getMethod()) +
.getPreviousScreen() == mySession.getCurrentScreen()) { +
on).incrementNumVisits(); +
+
+ + +
userTracker = UserTracker.instance(); +
r.update(mySession, screen); +
st, screen.getClass().getName() + " | " + mySession.getParser().toString()); +
+
our View servlet +
r-agent"); +

About WebGoat

wn!"; +
= null) { +

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque volutpat feugiat nunc, non vulputate urna dictum ut. Nam consectetur porttitor diam ut ultricies. Aenean dolor dolor, congue sed ornare non, elementum in mauris. Phasellus orci sem, rhoncus eu laoreet eu, aliquam nec ante. Suspendisse sit amet justo eget eros tempor tincidunt vel quis justo. Sed pulvinar enim id neque pellentesque, eu rhoncus lorem eleifend. Morbi congue tortor sit amet pulvinar posuere.

+

Integer rhoncus gravida arcu, at bibendum magna feugiat sit amet. Vivamus id lacinia massa. Praesent eu quam ullamcorper, tempor elit nec, lobortis massa. In in eros eu augue rhoncus semper. Vestibulum ornare purus vitae bibendum vulputate. Cras eleifend commodo lectus, eget pharetra justo mollis quis. Donec tempor magna lectus, vitae suscipit turpis venenatis et. Nulla facilisi.

+

Nam placerat magna in massa euismod fringilla. Pellentesque in cursus risus, eu hendrerit ligula. Quisque ultrices eget tortor ut eleifend. Praesent auctor libero nec quam fringilla faucibus. Curabitur cursus risus eu faucibus rutrum. Morbi dapibus nulla risus, et euismod eros posuere volutpat. Quisque ut diam diam. Quisque sed enim tortor. Suspendisse commodo magna nec felis ultricies laoreet. Donec sit amet vehicula eros. Phasellus at dapibus enim. Sed massa quam, aliquet eu mattis at, porttitor a nisi.

+
his is being done in updateSession call +

Nam placerat magna in massa euismod fringilla. Pellentesque in cursus risus, eu hendrerit ligula. Quisque ultrices eget tortor ut eleifend. Praesent auctor libero nec quam fringilla faucibus. Curabitur cursus risus eu faucibus rutrum. Morbi dapibus nulla risus, et euismod eros posuere volutpat. Quisque ut diam diam. Quisque sed enim tortor. Suspendisse commodo magna nec felis ultricies laoreet. Donec sit amet vehicula eros. Phasellus at dapibus enim. Sed massa quam, aliquet eu mattis at, porttitor a nisi.

+
y this is being set in the session? +
Session().setAttribute(WebSession.COURSE, mySession.getCourse()); +
age = getViewPage(mySession); +
ew: " + viewPage); +
+ screen); +
er(viewPage).forward(request, response); +
+
request", t); +
n(mySession, t); + + + +
s.writeScreen(mySession, screen, response); +
+

Hints

thr) { +

Nam placerat magna in massa euismod fringilla. Pellentesque in cursus risus, eu hendrerit ligula. Quisque ultrices eget tortor ut eleifend. Praesent auctor libero nec quam fringilla faucibus. Curabitur cursus risus eu faucibus rutrum. Morbi dapibus nulla risus, et euismod eros posuere volutpat. Quisque ut diam diam. Quisque sed enim tortor. Suspendisse commodo magna nec felis ultricies laoreet. Donec sit amet vehicula eros. Phasellus at dapibus enim. Sed massa quam, aliquet eu mattis at, porttitor a nisi.

+
+
n.returnConnection(mySession); +
bug("Leaving doPost: "); +
+
+
+ +
ng getViewPage(WebSession webSession) { +
x.html"; + + + + + } + if (s.isAdmin()) { +
== WebSession.WELCOME) { + + + + ist of roles. + on(s, scr, AbstractLesson.ADMIN_ROLE); + if (lesson == null) { + lesson = course.getLesson(s, scr, AbstractLesson.HACKED_ADMIN_ROLE); + } } if (lesson != null) { @@ -364,6 +360,19 @@ protected static void setCacheHeaders(HttpServletResponse response, int expiry) } } + /** + * This method sets the required security headers in the response. + * + * @param response The HttpServletResponse object + */ + protected static void setSecurityHeaders(HttpServletResponse response) { + response.setHeader("Strict-Transport-Security", "max-age=31536000; includeSubDomains"); + response.setHeader("X-Content-Type-Options", "nosniff"); + response.setHeader("X-Frame-Options", "DENY"); + response.setHeader("Content-Security-Policy", "default-src 'self'; script-src 'self'; object-src 'none';"); + response.setHeader("Referrer-Policy", "no-referrer"); + } + /** * Description of the Method * diff --git a/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java b/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java index e689f7d1f..33f526bd2 100644 --- a/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java +++ b/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java @@ -1,12 +1,12 @@ package org.owasp.webgoat.lessons; 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.Connection; +import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; @@ -35,8 +35,8 @@ import org.slf4j.LoggerFactory; /** - * ************************************************************************************************* - * + * AbstractLesson serves as a base class for all lessons in WebGoat. + * It provides common functionality such as handling lesson plans, solutions, and user roles. * * This file is part of WebGoat, an Open Web Application Security Project * utility. For details, please see http://www.owasp.org/ @@ -67,7 +67,7 @@ * @author Bruce Mayhew WebGoat * @created October 28, 2003 */ -public abstract class AbstractLesson extends Screen implements Comparable { +public sealed class AbstractLesson extends Screen implements Comparable permits BeginnerLesson, AdvancedLesson { private static final Logger logger = LoggerFactory.getLogger(AbstractLesson.class); @@ -201,70 +201,12 @@ public Category getCategory() { protected abstract boolean getDefaultHidden(); /** - * Gets the fileMethod attribute of the Lesson class + * Reads text from a file into a String. + * Each line in the file is represented in the String with a new-line character. * - * @param reader Description of the Parameter - * @param methodName Description of the Parameter - * @param numbers Description of the Parameter - * @return The fileMethod value - */ - public static String getFileMethod(BufferedReader reader, String methodName, boolean numbers) { - int count = 0; - StringBuffer sb = new StringBuffer(); - boolean echo = false; - boolean startCount = false; - int parenCount = 0; - - try { - String line; - - while ((line = reader.readLine()) != null) { - if ((line.indexOf(methodName) != -1) - && ((line.indexOf("public") != -1) || (line.indexOf("protected") != -1) || (line - .indexOf("private") != -1))) { - echo = true; - startCount = true; - } - - if (echo && startCount) { - if (numbers) { - sb.append(pad(++count) + " "); - } - - sb.append(line + "\n"); - } - - if (echo && (line.indexOf("{") != -1)) { - parenCount++; - } - - if (echo && (line.indexOf("}") != -1)) { - parenCount--; - - if (parenCount == 0) { - startCount = false; - echo = false; - } - } - } - - reader.close(); - } catch (Exception e) { - System.out.println(e); - e.printStackTrace(); - } - - return (sb.toString()); - } - - /** - * Reads text from a file into an ElementContainer. Each line in the file is - * represented in the ElementContainer by a StringElement. Each - * StringElement is appended with a new-line character. - * - * @param reader Description of the Parameter - * @param numbers Description of the Parameter - * @return Description of the Return Value + * @param reader BufferedReader to read the file. + * @param numbers Whether to include line numbers in the output. + * @return The content of the file as a String. */ public static String readFromFile(BufferedReader reader, boolean numbers) { return (getFileText(reader, numbers)); @@ -279,34 +221,21 @@ public static String readFromFile(BufferedReader reader, boolean numbers) { */ public static String getFileText(BufferedReader reader, boolean numbers) { int count = 0; - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); - try { + try (reader) { // Use try-with-resources to ensure the reader is closed String line; - while ((line = reader.readLine()) != null) { if (numbers) { - sb.append(pad(++count) + " "); + sb.append(pad(++count)).append(" "); } - sb.append(line + System.getProperty("line.separator")); + sb.append(line).append(System.lineSeparator()); } - - reader.close(); - } catch (Exception e) { - System.out.println(e); - e.printStackTrace(); + } catch (IOException e) { + logger.error("Error reading file: {}", e.getMessage(), e); // Log with meaningful message } - return (sb.toString()); - } - - /** - * Will this screen be included in an enterprise edition. - * - * @return The ranking value - */ - public boolean isEnterprise() { - return false; + return sb.toString(); } /** @@ -322,13 +251,6 @@ public int getHintCount(WebSession s) { protected abstract List getHints(WebSession s); - // @TODO we need to restrict access at the service layer - // rather than passing session object around - 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. @@ -353,46 +275,23 @@ public String getHint(WebSession s, int hintNumber) { * * @return The lessonPlan value */ - protected String getLessonName() { - int index = this.getClass().getName().indexOf("lessons."); - return this.getClass().getName().substring(index + "lessons.".length()); - } - - /** - * Gets the title attribute of the HelloScreen object - * - * @return The title value - */ - public abstract String getTitle(); - - /** - * Gets the content of lessonPlanURL - * - * @param s The user's WebSession - * - * @return The HTML content of the current lesson plan - */ public String getLessonPlan(WebSession s) { - StringBuffer src = new StringBuffer(); + StringBuilder src = new StringBuilder(); String lang = s.getCurrrentLanguage(); try { - // System.out.println("Loading lesson plan file: " + - // getLessonPlanFileName()); String filename = getLessonPlanFileName(lang); if (filename == null) { filename = getLessonPlanFileName(getDefaultLanguage()); - } - - src.append(readFromFile(new BufferedReader(new FileReader(s.getWebResource(filename))), false)); - - } catch (Exception e) { - // s.setMessage( "Could not find lesson plan for " + - // getLessonName()); - src = new StringBuffer("Could not find lesson plan for: " + getLessonName() + " and language " + lang); - + try (BufferedReader reader = new BufferedReader(new FileReader(s.getWebResource(filename)))) { + src.append(readFromFile(reader, false)); + } + } catch (IOException e) { + logger.error("Could not find lesson plan for lesson '{}' and language '{}': {}", getLessonName(), lang, e.getMessage(), e); + src.append("Could not find lesson plan for: ").append(getLessonName()).append(" and language ").append(lang); } + return src.toString(); } @@ -445,21 +344,6 @@ public int getScreenId() { return id.intValue(); } - public String getHtml_DELETE_ME(WebSession s) { - String html = null; - - // FIXME: This doesn't work for the labs since they do not implement - // createContent(). - String rawHtml = createContent(s).toString(); - // System.out.println("Getting raw html content: " + - // rawHtml.substring(0, Math.min(rawHtml.length(), 100))); - html = convertMetachars(AbstractLesson.readFromFile(new BufferedReader(new StringReader(rawHtml)), true)); - // System.out.println("Getting encoded html content: " + - // html.substring(0, Math.min(html.length(), 100))); - - return html; - } - public String getSource(WebSession s) { String source = null; String src = null; @@ -499,24 +383,6 @@ public String getSource(WebSession s) { return source; } - public String getRawSource(WebSession s) { - String src; - - try { - logger.debug("Loading source file: " + getSourceFileName()); - src = readFromFile(new BufferedReader(new FileReader(s.getWebResource(getSourceFileName()))), false); - - } catch (FileNotFoundException e) { - s.setMessage("Could not find source file"); - src = ("Could not find the source file or source file does not exist.
" - + "Send this message to: " + s.getWebgoatContext().getFeedbackAddress() + ""); - } - - return src; - } - public String getSolution(WebSession s) { String src = null; @@ -613,43 +479,36 @@ public boolean isAuthorized(WebSession s, int employeeId, String functionId) { * @return */ public boolean isAuthorized(WebSession s, String role, String functionId) { - logger.info("Checking if " + role + " authorized for: " + functionId); + logger.info("Checking if role '{}' is authorized for function '{}'", role, functionId); + String query = "SELECT * FROM auth WHERE role = ? AND functionid = ?"; boolean authorized = false; - try { - String query = "SELECT * FROM auth WHERE role = '" + role + "' and functionid = '" + functionId + "'"; - try { - Statement answer_statement = WebSession.getConnection(s) - .createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); - ResultSet answer_results = answer_statement.executeQuery(query); - authorized = answer_results.first(); - logger.info("authorized: "+ authorized); - } catch (SQLException sqle) { - s.setMessage("Error authorizing"); - logger.error("Error authorizing", sqle); + + try (Connection connection = WebSession.getConnection(s); + PreparedStatement statement = connection.prepareStatement(query)) { + statement.setString(1, role); + statement.setString(2, functionId); + try (ResultSet resultSet = statement.executeQuery()) { + authorized = resultSet.next(); } + } catch (SQLException e) { + logger.error("SQL error while authorizing role '{}' for function '{}': {}", role, functionId, e.getMessage(), e); + s.setMessage("Error authorizing"); } catch (Exception e) { + logger.error("Unexpected error while authorizing role '{}' for function '{}': {}", role, functionId, e.getMessage(), e); s.setMessage("Error authorizing"); - logger.error("Error authorizing", e); } - return authorized; - } - - public int getUserId(WebSession s) throws ParameterNotFoundException { - return -1; - } - public String getUserName(WebSession s) throws ParameterNotFoundException { - return null; + logger.info("Authorization result for role '{}' and function '{}': {}", role, functionId, authorized); + return authorized; } /** - * Description of the Method + * Generates a JavaScript function to open a new browser window. * - * @param windowName Description of the Parameter - * @return Description of the Return Value + * @param windowName The name of the window to be opened. + * @return A JavaScript function as a String. */ public static String makeWindowScript(String windowName) { - // FIXME: make this string static StringBuffer script = new StringBuffer(); script.append("