From 89037c3dfbf973bd7b157ee50b599a0819b830ba Mon Sep 17 00:00:00 2001 From: ronanclancy Date: Tue, 26 Mar 2019 10:01:07 +0000 Subject: [PATCH 001/119] Fim simple email assignment typo --- .../java/org/owasp/webgoat/plugin/SimpleMailAssignment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/plugin/SimpleMailAssignment.java b/webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/plugin/SimpleMailAssignment.java index a2c551687..e32815d66 100644 --- a/webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/plugin/SimpleMailAssignment.java +++ b/webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/plugin/SimpleMailAssignment.java @@ -63,7 +63,7 @@ public class SimpleMailAssignment extends AssignmentEndpoint { .recipient(username) .title("Simple e-mail assignment") .time(LocalDateTime.now()) - .contents("Thanks your resetting your password, your new password is: " + StringUtils.reverse(username)) + .contents("Thanks for resetting your password, your new password is: " + StringUtils.reverse(username)) .sender("webgoat@owasp.org") .build(); try { From a242347ee0bb0107ce8919768ba2967c56305ee8 Mon Sep 17 00:00:00 2001 From: rjclancy Date: Tue, 26 Mar 2019 12:05:42 +0000 Subject: [PATCH 002/119] add UserService unit test, modify UserService --- .../org/owasp/webwolf/user/UserService.java | 19 +++--- .../owasp/webwolf/user/UserServiceTest.java | 66 +++++++++++++++++++ 2 files changed, 76 insertions(+), 9 deletions(-) create mode 100644 webwolf/src/test/java/org/owasp/webwolf/user/UserServiceTest.java diff --git a/webwolf/src/main/java/org/owasp/webwolf/user/UserService.java b/webwolf/src/main/java/org/owasp/webwolf/user/UserService.java index 319a9a355..85c1576ff 100644 --- a/webwolf/src/main/java/org/owasp/webwolf/user/UserService.java +++ b/webwolf/src/main/java/org/owasp/webwolf/user/UserService.java @@ -1,6 +1,6 @@ package org.owasp.webwolf.user; -import lombok.AllArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; @@ -10,26 +10,27 @@ import org.springframework.stereotype.Service; * @since 3/19/17. */ @Service -@AllArgsConstructor public class UserService implements UserDetailsService { - private final UserRepository userRepository; + private UserRepository userRepository; + + @Autowired + public UserService(final UserRepository userRepository) { + this.userRepository = userRepository; + } @Override - public WebGoatUser loadUserByUsername(String username) throws UsernameNotFoundException { + public WebGoatUser loadUserByUsername(final String username) throws UsernameNotFoundException { WebGoatUser webGoatUser = userRepository.findByUsername(username); if (webGoatUser == null) { throw new UsernameNotFoundException("User not found"); - } else { - webGoatUser.createUser(); } + webGoatUser.createUser(); return webGoatUser; } - public void addUser(String username, String password) { + public void addUser(final String username, final String password) { userRepository.save(new WebGoatUser(username, password)); } - - } diff --git a/webwolf/src/test/java/org/owasp/webwolf/user/UserServiceTest.java b/webwolf/src/test/java/org/owasp/webwolf/user/UserServiceTest.java new file mode 100644 index 000000000..63da863bf --- /dev/null +++ b/webwolf/src/test/java/org/owasp/webwolf/user/UserServiceTest.java @@ -0,0 +1,66 @@ +package org.owasp.webwolf.user; + + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import static org.mockito.Mockito.*; + +@RunWith(SpringJUnit4ClassRunner.class) +public class UserServiceTest { + + @Mock + private UserRepository mockUserRepository; + + private UserService cut; + + @Before + public void setup(){ + cut = new UserService(mockUserRepository); + } + + @Test + public void testLoadUserByUsername(){ + // setup + final String username = "guest"; + final String password = "123"; + + WebGoatUser user = new WebGoatUser(username, password); + when(mockUserRepository.findByUsername(username)).thenReturn(user); + + // execute + final WebGoatUser webGoatUser = cut.loadUserByUsername(username); + + // verify + Assert.assertEquals(username, webGoatUser.getUsername()); + Assert.assertEquals(password, webGoatUser.getPassword()); + } + + @Test(expected = UsernameNotFoundException.class) + public void testLoadUserByUsername_NULL(){ + // setup + final String username = "guest"; + when(mockUserRepository.findByUsername(username)).thenReturn(null); + + // execute + cut.loadUserByUsername(username); + } + + @Test + public void testAddUser(){ + // setup + final String username = "guest"; + final String password = "guest"; + + // execute + cut.addUser(username, password); + + // verify + verify(mockUserRepository, times(1)).save(any(WebGoatUser.class)); + } +} From c6c0cc60f94712503e2eeb68217db1d1e07ce146 Mon Sep 17 00:00:00 2001 From: rjclancy Date: Tue, 26 Mar 2019 20:23:28 +0000 Subject: [PATCH 003/119] Add UserValidator tests + minor code clean up --- .../org/owasp/webwolf/user/UserService.java | 8 +- .../owasp/webwolf/user/UserServiceTest.java | 7 +- .../owasp/webwolf/user/UserValidatorTest.java | 85 +++++++++++++++++++ 3 files changed, 90 insertions(+), 10 deletions(-) create mode 100644 webwolf/src/test/java/org/owasp/webwolf/user/UserValidatorTest.java diff --git a/webwolf/src/main/java/org/owasp/webwolf/user/UserService.java b/webwolf/src/main/java/org/owasp/webwolf/user/UserService.java index 85c1576ff..90a430a1c 100644 --- a/webwolf/src/main/java/org/owasp/webwolf/user/UserService.java +++ b/webwolf/src/main/java/org/owasp/webwolf/user/UserService.java @@ -1,5 +1,6 @@ package org.owasp.webwolf.user; +import lombok.AllArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; @@ -10,14 +11,11 @@ import org.springframework.stereotype.Service; * @since 3/19/17. */ @Service +@AllArgsConstructor public class UserService implements UserDetailsService { - private UserRepository userRepository; - @Autowired - public UserService(final UserRepository userRepository) { - this.userRepository = userRepository; - } + private UserRepository userRepository; @Override public WebGoatUser loadUserByUsername(final String username) throws UsernameNotFoundException { diff --git a/webwolf/src/test/java/org/owasp/webwolf/user/UserServiceTest.java b/webwolf/src/test/java/org/owasp/webwolf/user/UserServiceTest.java index 63da863bf..ad53e36ec 100644 --- a/webwolf/src/test/java/org/owasp/webwolf/user/UserServiceTest.java +++ b/webwolf/src/test/java/org/owasp/webwolf/user/UserServiceTest.java @@ -5,6 +5,7 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.InjectMocks; import org.mockito.Mock; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -17,13 +18,9 @@ public class UserServiceTest { @Mock private UserRepository mockUserRepository; + @InjectMocks private UserService cut; - @Before - public void setup(){ - cut = new UserService(mockUserRepository); - } - @Test public void testLoadUserByUsername(){ // setup diff --git a/webwolf/src/test/java/org/owasp/webwolf/user/UserValidatorTest.java b/webwolf/src/test/java/org/owasp/webwolf/user/UserValidatorTest.java new file mode 100644 index 000000000..60e614a58 --- /dev/null +++ b/webwolf/src/test/java/org/owasp/webwolf/user/UserValidatorTest.java @@ -0,0 +1,85 @@ +package org.owasp.webwolf.user; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.validation.BindException; + +import static junit.framework.TestCase.assertTrue; +import static org.junit.Assert.assertFalse; +import static org.mockito.Mockito.when; + +/** + * @author rjclancy + * @since 3/26/19. + */ +@RunWith(SpringJUnit4ClassRunner.class) +public class UserValidatorTest { + + @Mock + private UserRepository mockUserRepository; + + @InjectMocks + private UserValidator userValidator; + + @Test + public void testValidUserForm() { + UserForm validUserForm = new UserForm(); + validUserForm.setUsername("guest"); + validUserForm.setMatchingPassword("123"); + validUserForm.setPassword("123"); + BindException errors = new BindException(validUserForm, "validUserForm"); + + userValidator.validate(validUserForm, errors); + + assertFalse(errors.hasErrors()); + } + + @Test + public void testValidUserForm_INVALID_PASSWORD() { + UserForm validUserForm = new UserForm(); + validUserForm.setUsername("guest"); + validUserForm.setMatchingPassword("123"); + validUserForm.setPassword("124"); + BindException errors = new BindException(validUserForm, "validUserForm"); + + userValidator.validate(validUserForm, errors); + + assertTrue(errors.hasErrors()); + } + + @Test + public void testValidUserForm_DUPLICATE_USER() { + // setup + final String username = "guest"; + final String password = "123"; + + UserForm validUserForm = new UserForm(); + validUserForm.setUsername(username); + validUserForm.setMatchingPassword(password); + validUserForm.setPassword("124"); + BindException errors = new BindException(validUserForm, "validUserForm"); + + WebGoatUser webGoatUser = new WebGoatUser(username, password); + when(mockUserRepository.findByUsername(validUserForm.getUsername())).thenReturn(webGoatUser); + + // execute + userValidator.validate(validUserForm, errors); + + // verify + assertTrue(errors.hasErrors()); + } + + @Test + public void testSupports(){ + Assert.assertTrue(userValidator.supports(UserForm.class)); + } + + @Test + public void testSupports_false(){ + Assert.assertFalse(userValidator.supports(UserService.class)); + } +} \ No newline at end of file From 331d9c8dd4b7f20563e456dc0e3cdc2c9373d59c Mon Sep 17 00:00:00 2001 From: rjclancy Date: Tue, 26 Mar 2019 20:33:11 +0000 Subject: [PATCH 004/119] add authur tag to test class --- .../src/test/java/org/owasp/webwolf/user/UserServiceTest.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/webwolf/src/test/java/org/owasp/webwolf/user/UserServiceTest.java b/webwolf/src/test/java/org/owasp/webwolf/user/UserServiceTest.java index ad53e36ec..3d611c30a 100644 --- a/webwolf/src/test/java/org/owasp/webwolf/user/UserServiceTest.java +++ b/webwolf/src/test/java/org/owasp/webwolf/user/UserServiceTest.java @@ -12,6 +12,10 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import static org.mockito.Mockito.*; +/** + * @author rjclancy + * @since 3/26/19. + */ @RunWith(SpringJUnit4ClassRunner.class) public class UserServiceTest { From 98537426f2b3c9855cdc44d00c6629b95da2265d Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Fri, 3 May 2019 11:15:11 +0200 Subject: [PATCH 005/119] SNAPSHOT version --- pom.xml | 2 +- webgoat-container/pom.xml | 2 +- webgoat-lessons/auth-bypass/pom.xml | 2 +- webgoat-lessons/bypass-restrictions/pom.xml | 2 +- webgoat-lessons/challenge/pom.xml | 2 +- webgoat-lessons/chrome-dev-tools/pom.xml | 2 +- webgoat-lessons/cia/pom.xml | 2 +- webgoat-lessons/client-side-filtering/pom.xml | 2 +- webgoat-lessons/cross-site-scripting/pom.xml | 2 +- webgoat-lessons/csrf/pom.xml | 2 +- webgoat-lessons/html-tampering/pom.xml | 2 +- webgoat-lessons/http-basics/pom.xml | 2 +- webgoat-lessons/http-proxies/pom.xml | 2 +- webgoat-lessons/idor/pom.xml | 2 +- webgoat-lessons/insecure-deserialization/pom.xml | 2 +- webgoat-lessons/insecure-login/pom.xml | 2 +- webgoat-lessons/jwt/pom.xml | 2 +- webgoat-lessons/missing-function-ac/pom.xml | 2 +- webgoat-lessons/password-reset/pom.xml | 2 +- webgoat-lessons/pom.xml | 4 ++-- webgoat-lessons/secure-passwords/pom.xml | 2 +- webgoat-lessons/sql-injection/pom.xml | 2 +- webgoat-lessons/ssrf/pom.xml | 2 +- webgoat-lessons/vulnerable-components/pom.xml | 2 +- webgoat-lessons/webgoat-introduction/pom.xml | 2 +- webgoat-lessons/webwolf-introduction/pom.xml | 2 +- webgoat-lessons/xxe/pom.xml | 2 +- webgoat-server/pom.xml | 2 +- webwolf/pom.xml | 2 +- 29 files changed, 30 insertions(+), 30 deletions(-) diff --git a/pom.xml b/pom.xml index 9e4fa1f03..bf6e77a90 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat webgoat-parent pom - v8.0.0.M25 + v8.0.0-SNAPSHOT WebGoat Parent Pom Parent Pom for the WebGoat Project. A deliberately insecure Web Application diff --git a/webgoat-container/pom.xml b/webgoat-container/pom.xml index a07fc905e..2f766037a 100644 --- a/webgoat-container/pom.xml +++ b/webgoat-container/pom.xml @@ -10,7 +10,7 @@ org.owasp.webgoat webgoat-parent - v8.0.0.M25 + v8.0.0-SNAPSHOT diff --git a/webgoat-lessons/auth-bypass/pom.xml b/webgoat-lessons/auth-bypass/pom.xml index d03a88e71..0cdc9ef49 100644 --- a/webgoat-lessons/auth-bypass/pom.xml +++ b/webgoat-lessons/auth-bypass/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M25 + v8.0.0-SNAPSHOT diff --git a/webgoat-lessons/bypass-restrictions/pom.xml b/webgoat-lessons/bypass-restrictions/pom.xml index 34bc8b80b..c1d0102c0 100755 --- a/webgoat-lessons/bypass-restrictions/pom.xml +++ b/webgoat-lessons/bypass-restrictions/pom.xml @@ -6,6 +6,6 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M25 + v8.0.0-SNAPSHOT diff --git a/webgoat-lessons/challenge/pom.xml b/webgoat-lessons/challenge/pom.xml index 3bfcd8b6d..f4a321fd7 100644 --- a/webgoat-lessons/challenge/pom.xml +++ b/webgoat-lessons/challenge/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M25 + v8.0.0-SNAPSHOT diff --git a/webgoat-lessons/chrome-dev-tools/pom.xml b/webgoat-lessons/chrome-dev-tools/pom.xml index 262cd1e56..52921a6f4 100644 --- a/webgoat-lessons/chrome-dev-tools/pom.xml +++ b/webgoat-lessons/chrome-dev-tools/pom.xml @@ -6,6 +6,6 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M25 + v8.0.0-SNAPSHOT \ No newline at end of file diff --git a/webgoat-lessons/cia/pom.xml b/webgoat-lessons/cia/pom.xml index 14dd15fd5..3e7c95607 100644 --- a/webgoat-lessons/cia/pom.xml +++ b/webgoat-lessons/cia/pom.xml @@ -6,6 +6,6 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M25 + v8.0.0-SNAPSHOT \ No newline at end of file diff --git a/webgoat-lessons/client-side-filtering/pom.xml b/webgoat-lessons/client-side-filtering/pom.xml index c87b8716b..aa1d49872 100644 --- a/webgoat-lessons/client-side-filtering/pom.xml +++ b/webgoat-lessons/client-side-filtering/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M25 + v8.0.0-SNAPSHOT diff --git a/webgoat-lessons/cross-site-scripting/pom.xml b/webgoat-lessons/cross-site-scripting/pom.xml index 109eb2a42..6c99401b6 100644 --- a/webgoat-lessons/cross-site-scripting/pom.xml +++ b/webgoat-lessons/cross-site-scripting/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M25 + v8.0.0-SNAPSHOT diff --git a/webgoat-lessons/csrf/pom.xml b/webgoat-lessons/csrf/pom.xml index 240366a5f..2366e85d3 100644 --- a/webgoat-lessons/csrf/pom.xml +++ b/webgoat-lessons/csrf/pom.xml @@ -6,6 +6,6 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M25 + v8.0.0-SNAPSHOT \ No newline at end of file diff --git a/webgoat-lessons/html-tampering/pom.xml b/webgoat-lessons/html-tampering/pom.xml index da50ea204..2585104ca 100755 --- a/webgoat-lessons/html-tampering/pom.xml +++ b/webgoat-lessons/html-tampering/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M25 + v8.0.0-SNAPSHOT diff --git a/webgoat-lessons/http-basics/pom.xml b/webgoat-lessons/http-basics/pom.xml index 8cd6bcef8..4a2e3959b 100644 --- a/webgoat-lessons/http-basics/pom.xml +++ b/webgoat-lessons/http-basics/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M25 + v8.0.0-SNAPSHOT diff --git a/webgoat-lessons/http-proxies/pom.xml b/webgoat-lessons/http-proxies/pom.xml index 1eaacd02e..23c24a5dd 100644 --- a/webgoat-lessons/http-proxies/pom.xml +++ b/webgoat-lessons/http-proxies/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M25 + v8.0.0-SNAPSHOT diff --git a/webgoat-lessons/idor/pom.xml b/webgoat-lessons/idor/pom.xml index 8f3911b1a..73e18fbaa 100644 --- a/webgoat-lessons/idor/pom.xml +++ b/webgoat-lessons/idor/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M25 + v8.0.0-SNAPSHOT \ No newline at end of file diff --git a/webgoat-lessons/insecure-deserialization/pom.xml b/webgoat-lessons/insecure-deserialization/pom.xml index f4c2d55cb..08de6cf6a 100755 --- a/webgoat-lessons/insecure-deserialization/pom.xml +++ b/webgoat-lessons/insecure-deserialization/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M25 + v8.0.0-SNAPSHOT diff --git a/webgoat-lessons/insecure-login/pom.xml b/webgoat-lessons/insecure-login/pom.xml index 33ffb1fc5..faf241a51 100755 --- a/webgoat-lessons/insecure-login/pom.xml +++ b/webgoat-lessons/insecure-login/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M25 + v8.0.0-SNAPSHOT diff --git a/webgoat-lessons/jwt/pom.xml b/webgoat-lessons/jwt/pom.xml index 3184af5b7..e1856384d 100644 --- a/webgoat-lessons/jwt/pom.xml +++ b/webgoat-lessons/jwt/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M25 + v8.0.0-SNAPSHOT diff --git a/webgoat-lessons/missing-function-ac/pom.xml b/webgoat-lessons/missing-function-ac/pom.xml index e694f064f..7c2359247 100644 --- a/webgoat-lessons/missing-function-ac/pom.xml +++ b/webgoat-lessons/missing-function-ac/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M25 + v8.0.0-SNAPSHOT diff --git a/webgoat-lessons/password-reset/pom.xml b/webgoat-lessons/password-reset/pom.xml index 688648967..37c437ce9 100644 --- a/webgoat-lessons/password-reset/pom.xml +++ b/webgoat-lessons/password-reset/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M25 + v8.0.0-SNAPSHOT diff --git a/webgoat-lessons/pom.xml b/webgoat-lessons/pom.xml index 67254556e..959f701ad 100644 --- a/webgoat-lessons/pom.xml +++ b/webgoat-lessons/pom.xml @@ -5,12 +5,12 @@ org.owasp.webgoat.lesson webgoat-lessons-parent pom - v8.0.0.M25 + v8.0.0-SNAPSHOT org.owasp.webgoat webgoat-parent - v8.0.0.M25 + v8.0.0-SNAPSHOT diff --git a/webgoat-lessons/secure-passwords/pom.xml b/webgoat-lessons/secure-passwords/pom.xml index 98457a832..5cbd50995 100644 --- a/webgoat-lessons/secure-passwords/pom.xml +++ b/webgoat-lessons/secure-passwords/pom.xml @@ -6,6 +6,6 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M25 + v8.0.0-SNAPSHOT \ No newline at end of file diff --git a/webgoat-lessons/sql-injection/pom.xml b/webgoat-lessons/sql-injection/pom.xml index c351e60a4..d2e50488c 100644 --- a/webgoat-lessons/sql-injection/pom.xml +++ b/webgoat-lessons/sql-injection/pom.xml @@ -6,6 +6,6 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M25 + v8.0.0-SNAPSHOT \ No newline at end of file diff --git a/webgoat-lessons/ssrf/pom.xml b/webgoat-lessons/ssrf/pom.xml index d757d8d98..aa514c877 100755 --- a/webgoat-lessons/ssrf/pom.xml +++ b/webgoat-lessons/ssrf/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M25 + v8.0.0-SNAPSHOT diff --git a/webgoat-lessons/vulnerable-components/pom.xml b/webgoat-lessons/vulnerable-components/pom.xml index 74a7c282a..22411f819 100644 --- a/webgoat-lessons/vulnerable-components/pom.xml +++ b/webgoat-lessons/vulnerable-components/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M25 + v8.0.0-SNAPSHOT diff --git a/webgoat-lessons/webgoat-introduction/pom.xml b/webgoat-lessons/webgoat-introduction/pom.xml index 4f551e4ea..5e6d2ce7f 100644 --- a/webgoat-lessons/webgoat-introduction/pom.xml +++ b/webgoat-lessons/webgoat-introduction/pom.xml @@ -6,6 +6,6 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M25 + v8.0.0-SNAPSHOT \ No newline at end of file diff --git a/webgoat-lessons/webwolf-introduction/pom.xml b/webgoat-lessons/webwolf-introduction/pom.xml index dae914c00..a268b0602 100644 --- a/webgoat-lessons/webwolf-introduction/pom.xml +++ b/webgoat-lessons/webwolf-introduction/pom.xml @@ -6,6 +6,6 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M25 + v8.0.0-SNAPSHOT \ No newline at end of file diff --git a/webgoat-lessons/xxe/pom.xml b/webgoat-lessons/xxe/pom.xml index 9129c19a1..6d69be448 100644 --- a/webgoat-lessons/xxe/pom.xml +++ b/webgoat-lessons/xxe/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat.lesson webgoat-lessons-parent - v8.0.0.M25 + v8.0.0-SNAPSHOT diff --git a/webgoat-server/pom.xml b/webgoat-server/pom.xml index 4cbda0052..6317305ed 100644 --- a/webgoat-server/pom.xml +++ b/webgoat-server/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat webgoat-parent - v8.0.0.M25 + v8.0.0-SNAPSHOT diff --git a/webwolf/pom.xml b/webwolf/pom.xml index f461a0fa6..385a0fbc5 100644 --- a/webwolf/pom.xml +++ b/webwolf/pom.xml @@ -6,7 +6,7 @@ org.owasp.webgoat webgoat-parent - v8.0.0.M25 + v8.0.0-SNAPSHOT From 2a5e8dfdacacdc244eae9429be4ae554c603bd96 Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Fri, 3 May 2019 11:20:53 +0200 Subject: [PATCH 006/119] Add missing step necessary to finish the release --- CREATE_RELEASE.MD | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CREATE_RELEASE.MD b/CREATE_RELEASE.MD index b9250f807..b49c71b42 100644 --- a/CREATE_RELEASE.MD +++ b/CREATE_RELEASE.MD @@ -15,6 +15,10 @@ git flow release start mvn versions:set < git commit -am "New release, updating pom.xml" git flow release publish + +<> + +git flow release finish git push origin develop git push origin master git push --tags From 00deb66ad98a385f0867121368398ad93d950029 Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Thu, 9 May 2019 09:17:11 +0200 Subject: [PATCH 007/119] Small update for password reset lesson --- .../password-reset/src/main/resources/html/PasswordReset.html | 4 ++-- .../resources/lessonPlans/en/PasswordReset_host_header.adoc | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/webgoat-lessons/password-reset/src/main/resources/html/PasswordReset.html b/webgoat-lessons/password-reset/src/main/resources/html/PasswordReset.html index 02657b509..90495aee8 100644 --- a/webgoat-lessons/password-reset/src/main/resources/html/PasswordReset.html +++ b/webgoat-lessons/password-reset/src/main/resources/html/PasswordReset.html @@ -109,8 +109,8 @@
- Sign up - Login + Sign up + Login

WebGoat Password Recovery

diff --git a/webgoat-lessons/password-reset/src/main/resources/lessonPlans/en/PasswordReset_host_header.adoc b/webgoat-lessons/password-reset/src/main/resources/lessonPlans/en/PasswordReset_host_header.adoc index 5e1582c14..40a94f6b6 100644 --- a/webgoat-lessons/password-reset/src/main/resources/lessonPlans/en/PasswordReset_host_header.adoc +++ b/webgoat-lessons/password-reset/src/main/resources/lessonPlans/en/PasswordReset_host_header.adoc @@ -13,7 +13,8 @@ The time out is necessary to restrict the attack window, having a link opens up == Assignment Try to reset the password of Tom (tom@webgoat-cloud.org) to your own choice and login as Tom with -that password. Note: it is not possible to use OWASP ZAP for this lesson. +that password. Note: it is not possible to use OWASP ZAP for this lesson, also browsers might not work, command line +tools like `curl` and the like will be more successful for this attack. Tom always resets his password immediately after receiving the email with the link. From 703b6c676ee1762969b24fb22e49bd901ff784df Mon Sep 17 00:00:00 2001 From: Johannes Egger Date: Fri, 14 Jun 2019 15:09:55 +0200 Subject: [PATCH 008/119] Fix typo --- .../src/main/resources/lessonPlans/en/CIA_availability.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webgoat-lessons/cia/src/main/resources/lessonPlans/en/CIA_availability.adoc b/webgoat-lessons/cia/src/main/resources/lessonPlans/en/CIA_availability.adoc index 3dcc201af..f470a62ab 100644 --- a/webgoat-lessons/cia/src/main/resources/lessonPlans/en/CIA_availability.adoc +++ b/webgoat-lessons/cia/src/main/resources/lessonPlans/en/CIA_availability.adoc @@ -1,6 +1,6 @@ == Availability -Confidentiality is "the property of being accessible and usable on demand by an authorized entity." In other words all the information should be available and accessible for authorized persons whenever it is needed. +Availability is "the property of being accessible and usable on demand by an authorized entity." In other words all the information should be available and accessible for authorized persons whenever it is needed. {nbsp} + @@ -19,4 +19,4 @@ Confidentiality is "the property of being accessible and usable on demand by an ** firewalls ** physically and geographically isolated location *** fire- and waterproof -** hardware maintenance \ No newline at end of file +** hardware maintenance From cb667094f2a26c269c27cbd5a87db11485fba3d8 Mon Sep 17 00:00:00 2001 From: Sylvain Juge Date: Wed, 24 Apr 2019 16:28:54 +0200 Subject: [PATCH 009/119] update jar plugin version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index bf6e77a90..cb133b10f 100644 --- a/pom.xml +++ b/pom.xml @@ -147,7 +147,7 @@ 3.8.0 2.22.0 1.6 - 2.6 + 3.1.1 2.10.4 2.5.2 3.0.1 From 1aa98be908c1f79855ba88b443d5c64153f1d109 Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Tue, 9 Jul 2019 20:18:54 +0200 Subject: [PATCH 010/119] Fix issue with maven wrapper using TLS 1.2 as it no longer is supported --- .mvn/wrapper/maven-wrapper.properties | 3 ++- mvnw | 32 +++++++++++++++++++--- mvnw.cmd | 39 ++++++++++++++++++++------- 3 files changed, 60 insertions(+), 14 deletions(-) diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index 717934671..9c96caffb 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -1 +1,2 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.2.1/apache-maven-3.2.1-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar diff --git a/mvnw b/mvnw index 5551fde8e..d2f0ea380 100755 --- a/mvnw +++ b/mvnw @@ -114,7 +114,6 @@ if $mingw ; then M2_HOME="`(cd "$M2_HOME"; pwd)`" [ -n "$JAVA_HOME" ] && JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" - # TODO classpath? fi if [ -z "$JAVA_HOME" ]; then @@ -212,7 +211,11 @@ else if [ "$MVNW_VERBOSE" = true ]; then echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." fi - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" + fi while IFS="=" read key value; do case "$key" in (wrapperUrl) jarUrl="$value"; break ;; esac @@ -221,22 +224,38 @@ else echo "Downloading from: $jarUrl" fi wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi if command -v wget > /dev/null; then if [ "$MVNW_VERBOSE" = true ]; then echo "Found wget ... using wget" fi - wget "$jarUrl" -O "$wrapperJarPath" + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" + fi elif command -v curl > /dev/null; then if [ "$MVNW_VERBOSE" = true ]; then echo "Found curl ... using curl" fi - curl -o "$wrapperJarPath" "$jarUrl" + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + else if [ "$MVNW_VERBOSE" = true ]; then echo "Falling back to using Java to download" fi javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi if [ -e "$javaClass" ]; then if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then if [ "$MVNW_VERBOSE" = true ]; then @@ -277,6 +296,11 @@ if $cygwin; then MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` fi +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain exec "$JAVACMD" \ diff --git a/mvnw.cmd b/mvnw.cmd index e5cfb0ae9..b26ab24f0 100644 --- a/mvnw.cmd +++ b/mvnw.cmd @@ -37,7 +37,7 @@ @echo off @REM set title of command window title %0 -@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% @REM set %HOME% to equivalent of $HOME @@ -120,23 +120,44 @@ SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" -FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" + +FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B ) @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central @REM This allows using the maven wrapper in projects that prohibit checking in binary data. if exist %WRAPPER_JAR% ( - echo Found %WRAPPER_JAR% + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) ) else ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')" - echo Finished downloading %WRAPPER_JAR% + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) ) @REM End of extension +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* if ERRORLEVEL 1 goto error goto end From 27125acd229e072ce881e5c41956760a7230ca4c Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Tue, 9 Jul 2019 20:19:54 +0200 Subject: [PATCH 011/119] Fix issue with maven wrapper using TLS 1.2 as it no longer is supported --- .mvn/wrapper/MavenWrapperDownloader.java | 117 +++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 .mvn/wrapper/MavenWrapperDownloader.java diff --git a/.mvn/wrapper/MavenWrapperDownloader.java b/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 000000000..c32394f14 --- /dev/null +++ b/.mvn/wrapper/MavenWrapperDownloader.java @@ -0,0 +1,117 @@ +/* + * Copyright 2007-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import java.net.*; +import java.io.*; +import java.nio.channels.*; +import java.util.Properties; + +public class MavenWrapperDownloader { + + private static final String WRAPPER_VERSION = "0.5.5"; + /** + * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. + */ + private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" + + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; + + /** + * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to + * use instead of the default one. + */ + private static final String MAVEN_WRAPPER_PROPERTIES_PATH = + ".mvn/wrapper/maven-wrapper.properties"; + + /** + * Path where the maven-wrapper.jar will be saved to. + */ + private static final String MAVEN_WRAPPER_JAR_PATH = + ".mvn/wrapper/maven-wrapper.jar"; + + /** + * Name of the property which should be used to override the default download url for the wrapper. + */ + private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; + + public static void main(String args[]) { + System.out.println("- Downloader started"); + File baseDirectory = new File(args[0]); + System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); + + // If the maven-wrapper.properties exists, read it and check if it contains a custom + // wrapperUrl parameter. + File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); + String url = DEFAULT_DOWNLOAD_URL; + if(mavenWrapperPropertyFile.exists()) { + FileInputStream mavenWrapperPropertyFileInputStream = null; + try { + mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); + Properties mavenWrapperProperties = new Properties(); + mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); + url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); + } catch (IOException e) { + System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); + } finally { + try { + if(mavenWrapperPropertyFileInputStream != null) { + mavenWrapperPropertyFileInputStream.close(); + } + } catch (IOException e) { + // Ignore ... + } + } + } + System.out.println("- Downloading from: " + url); + + File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); + if(!outputFile.getParentFile().exists()) { + if(!outputFile.getParentFile().mkdirs()) { + System.out.println( + "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); + } + } + System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); + try { + downloadFileFromURL(url, outputFile); + System.out.println("Done"); + System.exit(0); + } catch (Throwable e) { + System.out.println("- Error downloading"); + e.printStackTrace(); + System.exit(1); + } + } + + private static void downloadFileFromURL(String urlString, File destination) throws Exception { + if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { + String username = System.getenv("MVNW_USERNAME"); + char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); + Authenticator.setDefault(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(username, password); + } + }); + } + URL website = new URL(urlString); + ReadableByteChannel rbc; + rbc = Channels.newChannel(website.openStream()); + FileOutputStream fos = new FileOutputStream(destination); + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); + fos.close(); + rbc.close(); + } + +} From 97f66545e0bb322abbf14422564f5bf96c6f5791 Mon Sep 17 00:00:00 2001 From: Matthias Grundmann Date: Fri, 12 Jul 2019 17:25:05 +0200 Subject: [PATCH 012/119] In CSRF-3 use POST instead of GET to prevent solving the assignment just by opening the URL in a new tab --- .../src/main/java/org/owasp/webgoat/plugin/CSRFGetFlag.java | 2 +- webgoat-lessons/csrf/src/main/resources/html/CSRF.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/plugin/CSRFGetFlag.java b/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/plugin/CSRFGetFlag.java index ecc486b7f..6ca21cbe5 100644 --- a/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/plugin/CSRFGetFlag.java +++ b/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/plugin/CSRFGetFlag.java @@ -27,7 +27,7 @@ public class CSRFGetFlag extends Endpoint { @Autowired private PluginMessages pluginMessages; - @RequestMapping(produces = {"application/json"}, method = RequestMethod.GET) + @RequestMapping(produces = {"application/json"}, method = RequestMethod.POST) @ResponseBody public Map invoke(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { diff --git a/webgoat-lessons/csrf/src/main/resources/html/CSRF.html b/webgoat-lessons/csrf/src/main/resources/html/CSRF.html index 71d08a816..9b9d79f02 100644 --- a/webgoat-lessons/csrf/src/main/resources/html/CSRF.html +++ b/webgoat-lessons/csrf/src/main/resources/html/CSRF.html @@ -14,7 +14,7 @@
Date: Thu, 9 May 2019 12:24:28 +0100 Subject: [PATCH 013/119] additional environment entries to support https on webgoat --- .../src/main/resources/application.properties | 15 +++++++++++---- .../src/main/resources/goatkeystore.pkcs12 | Bin 0 -> 2563 bytes .../src/main/resources/application.properties | 6 +++--- 3 files changed, 14 insertions(+), 7 deletions(-) create mode 100644 webgoat-container/src/main/resources/goatkeystore.pkcs12 diff --git a/webgoat-container/src/main/resources/application.properties b/webgoat-container/src/main/resources/application.properties index ba8b75afc..281b53230 100644 --- a/webgoat-container/src/main/resources/application.properties +++ b/webgoat-container/src/main/resources/application.properties @@ -2,10 +2,17 @@ server.error.include-stacktrace=always server.error.path=/error.html server.session.timeout=600 server.contextPath=/WebGoat -server.port=8080 -server.address=127.0.0.1 +server.port=${WEBGOAT_PORT:8080} +server.address=${WEBGOAT_HOST:127.0.0.1} -spring.datasource.url=jdbc:hsqldb:hsql://localhost:9001/webgoat +server.ssl.key-store-type=${WEBGOAT_KEYSTORE_TYPE:PKCS12} +server.ssl.key-store=${WEBGOAT_KEYSTORE:classpath:goatkeystore.pkcs12} +server.ssl.key-store-password=${WEBGOAT_KEYSTORE_PASSWORD:password} +server.ssl.key-alias=${WEBGOAT_KEY_ALIAS:goat} +server.ssl.enabled=${WEBGOAT_SSLENABLED:false} +security.require-ssl=${WEBGOAT_SSLENABLED:false} + +spring.datasource.url=jdbc:hsqldb:hsql://${WEBGOAT_HOST:127.0.0.1}:${WEBGOAT_HSQLPORT:9001}/webgoat spring.jpa.hibernate.ddl-auto=update spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.HSQLDialect spring.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver @@ -36,7 +43,7 @@ webgoat.database.driver=org.hsqldb.jdbcDriver webgoat.database.connection.string=jdbc:hsqldb:mem:{USER} webgoat.default.language=en -webwolf.host=${WEBWOLF_HOST:localhost} +webwolf.host=${WEBWOLF_HOST:127.0.0.1} webwolf.port=${WEBWOLF_PORT:9090} webwolf.url=http://${webwolf.host}:${webwolf.port}/WebWolf webwolf.url.landingpage=http://${webwolf.host}:${webwolf.port}/landing diff --git a/webgoat-container/src/main/resources/goatkeystore.pkcs12 b/webgoat-container/src/main/resources/goatkeystore.pkcs12 new file mode 100644 index 0000000000000000000000000000000000000000..c7e335790226c383d469d30421dba2722b9075ba GIT binary patch literal 2563 zcmY+EXE+;*8pneO3Dq8=6|raSRfo_vQN&8kh*^7cXzkLXsjZF~s|amrW6#=qG^$q3 zmRvzgRaFj(gVc5JbMHCN`S3pP^Zfq*_x<=&#DmWm8JHCD;8qY=I$l5i@B#x1LkS*C z0^-4C=eSf6&+Pt>h#3dOGn=1d>XQXt6x@%eK&5L%}E zS!y_-l0$xs+h#>9I$$OAjWZ(?V89fJ2a+cnQKFF5Co?~iES@`{a5=+fu9gK0?7?wz zBCq~@Z{;Hm@^%7gQsqESjVkwb9ivH&V>-93XH0zE7R{@&9vi|;emHwQ9xol^&PLsD zRUZjTTE;S*DH3c)0pW|bzdl1M=jk}s*N`IuFY|-Q&UM=Jl0@AsuP*~pCa>F82fCwu3I!QP zX*#*?$#wDS;USuLzr#qAc_r`A6SkD1Z81ASZivImLfd_GUEUOj2kXcG7I|HUYo z#pI)&cV%wi*7}^Zr$eQ_=LV(Khv!FO0oHktANh@ld9Xp;5Ngry%@1gX(~GB89l0{f zp+Rqzn@KV!QqQxNTAqp$;*yy4wN-YU^NJfVt4?224K>8w*?J+LBu$uS91dTl(H0;s zaR_S25Q~=U#*nXiaZYM!#-_k@#J9=NaWdatsa4++Fy?~WX5@x`oHp2|J!7lSXqp1v z#Mf&)OsA^zvyPNgXs%bLM}*p4S3G7b&1;ZC`<-!DThqM=tBk0aPfPwBf)~pV%!RB= zTu*7rYZE?+jdSzcYRokUUBP!cB2FuCQ>m_g(Pu*7U=%s$Rxj!LjfEi(OKlM%q&wk}wnrsy80WWNR73;`#M{=n;f|o~3?N9a|X6<-pn)}*Bvx3u+7Eun> z$`?-6RzT{?{W;}tL%yN{ zTv=7+@H_Ygqf}QN;zIzDC2c1jX0i&`8JCx$ue`D)LVtI=x4v5&IXU$&z75yeHWwJs z9TIEjEp%66LS!YQw{wTfs!6UTEj)WP7ECJG2c&JY?BIFE^?e$iN7$>iHyt`v!ps{D zgNIIsBN@HqUW~q(!Tg*~X-_&0l=Tt|O#JZk@TLsCmUw+4x6lxLbFY<+BXKd+tqWww z@K(~rVC?HhbCpK>wQ6JXRbN4GzsUY|`dt7xJ8ckWVU=r8yH~%P64O^Wo{W8mh_>Qn zUvJR?k|-U@>o4JwcSY6f-4uG82?t2=WO-SJvaLaU=OP@JZwP1<`v#HBxJd1Oa-6MM zF~H{UUO4P8@ytQ49U=Mf(U@RbdOmo|v*9V|7%4jLVke(RbFD(Ur_zyI;z7ZG_=OzV zG{?E>$lmG+uN7e08h%APFy&~r?q1S$4}aglCtqa_z~H%E*-&%@0dsbP{jKtpHcB4} z)8w^|%?Oi?C(>4yeKq4hgu}+v<9KLGU0K*we1|9dma36}b?n~Wv)Loaf}@{#*v|vf zR$5*$O3!GqrsK7xUtVim8~USLXjn{8h(@b=?o26t&l7qGQbf{gQHjuTcUFP2~PN1xx(Y zQY9Fw1QB2bcme_d&VXP=;lBfJB`A;+>;0R%kdmsZnzD+Tn%b|bN-F2#y!Ka#1$6FG z@pB~1$N)HByniPQ|FA3QKX%pZV)V9*gj$e9cgWK|K_GN!&Mt&7pmoB|D&V4WRp_UqJR>EO;-H(}uyDq)7$8&Nl z*i{9CpnPzv0wgQ2|D~p3Q*Q_&^w+H|jh;*`Wd2bN?2>khGu6T}-8ZlX^VL-uiY_Y4 ze!8R$X}ncn0Ts8q=GS!7HmMu*KyCIRNKGMRg)kzq^y{M!Ys&<02jX>%XmLc4^)s$! zW*YtY%`rZOH!-3#A!E&w1p+O7lq@||-w8?B^vCDHf?(Xyq9qoEZ6NfOOw|=Cs(DVj_& z`PO#Ds#^5^uxV2bRBvc`e*Xqa%K7m-l}~&^{EZ8i*lLQg@^-E8GDQm?%gFxLaUJ1) zR$IMnC1-hN7GQS-MoquJq+?}LhGGAWR{JD=kaG6wXM0q%RK$r%8Cv&%y zsrOfF!aQz|?~UgaP$SjHJp%lVC8FTtXpkfsb#WzamnMxyC}LEG8W9Pg`j)_Ckon2x z9zk!uE%XVMCpA@g5hr4e(CK^O8ash6*XO@b<$_u=;_t*2QafNDi-x~X`Wq_|=UHL! z`cNraq>Qw-mQ&$w281$N6>2gbca%f*Sae;;kq;0Qs~=d?u&d%-OYBm(rzMB7>2mvM z?YKg1%;AWb#l1yNS`3CEv-K3T&R%!%qZil03dZtstY7d!=4lfYi>7VY>elbu9vO80 zoD_GmSSYygDhext zLCi87OpLtD03g&48+B4K&Deq!i2Hp}wc~NtMNu9gRF>NU4c32oUsoL`+@0T`8OGZ~ KVq{{7FZnlqN49 Date: Mon, 13 May 2019 11:25:38 +0200 Subject: [PATCH 014/119] add login&pwd in JDBC url for PostgreSQL I really don't know why exactly spring parameters are not used here, probably for schema creation step. Until changing what the application does on startup this will make it 'just work' without extra changes. --- docker-compose-postgres.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose-postgres.yml b/docker-compose-postgres.yml index 2ff77f0b5..3306c87a1 100644 --- a/docker-compose-postgres.yml +++ b/docker-compose-postgres.yml @@ -7,7 +7,7 @@ services: environment: - WEBWOLF_HOST=webwolf - WEBWOLF_PORT=9090 - - spring.datasource.url=jdbc:postgresql://webgoat_db:5432/webgoat + - spring.datasource.url=jdbc:postgresql://webgoat_db:5432/webgoat?user=webgoat&password=webgoat - spring.datasource.username=webgoat - spring.datasource.password=webgoat - spring.datasource.driver-class-name=org.postgresql.Driver @@ -19,7 +19,7 @@ services: webwolf: image: webgoat/webwolf environment: - - spring.datasource.url=jdbc:postgresql://webgoat_db:5432/webgoat + - spring.datasource.url=jdbc:postgresql://webgoat_db:5432/webgoat?user=webgoat&password=webgoat - spring.datasource.username=webgoat - spring.datasource.password=webgoat - spring.datasource.driver-class-name=org.postgresql.Driver From 63a1097466fa1bec071362dc8f0e5a74dfb29ff4 Mon Sep 17 00:00:00 2001 From: Rene Zubcevic Date: Tue, 2 Apr 2019 18:07:53 +0200 Subject: [PATCH 015/119] owasp categories --- .../org/owasp/webgoat/lessons/Category.java | 25 +++++++++++++------ .../java/org/owasp/webgoat/plugin/XXE.java | 2 +- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Category.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Category.java index bdef4d39e..601bf6ad4 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Category.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Category.java @@ -38,17 +38,26 @@ public enum Category { INTRODUCTION("Introduction", new Integer(5)), GENERAL("General", new Integer(100)), - INJECTION("Injection Flaws", new Integer(200)), - AUTHENTICATION("Authentication Flaws", new Integer(300)), - XSS("Cross-Site Scripting (XSS)", new Integer(400)), + + INJECTION("(A1) Injection", new Integer(300)), + AUTHENTICATION("(A2) Broken Authentication", new Integer(302)), + INSECURE_COMMUNICATION("(A3) Sensitive Data Exposure", new Integer(303)), + XXE("(A4) XML External Entities (XXE)", Integer.valueOf(304)), + ACCESS_CONTROL("(A5) Broken Access Control", new Integer(305)), + + XSS("(A7) Cross-Site Scripting (XSS)", new Integer(307)), + INSECURE_DESERIALIZATION("(A8) Insecure Deserialization", new Integer(308)), + VULNERABLE_COMPONENTS("(A9) Vulnerable Components", new Integer(309)), + + REQUEST_FORGERIES("(A8:2013) Request Forgeries", new Integer(318)), + + REQ_FORGERIES("Request Forgeries", new Integer(450)), - ACCESS_CONTROL("Access Control Flaws", new Integer(500)), + INSECURE_CONFIGURATION("Insecure Configuration", new Integer(600)), - INSECURE_COMMUNICATION("Insecure Communication", new Integer(700)), INSECURE_STORAGE("Insecure Storage", new Integer(800)), - INSECURE_DESERIALIZATION("Insecure Deserialization", new Integer(850)), - REQUEST_FORGERIES("Request Forgeries", new Integer(900)), - VULNERABLE_COMPONENTS("Vulnerable Components - A9", new Integer(950)), + + AJAX_SECURITY("AJAX Security", new Integer(1000)), BUFFER_OVERFLOW("Buffer Overflows", new Integer(1100)), CODE_QUALITY("Code Quality", new Integer(1200)), diff --git a/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/XXE.java b/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/XXE.java index bac04c1f9..258179299 100644 --- a/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/XXE.java +++ b/webgoat-lessons/xxe/src/main/java/org/owasp/webgoat/plugin/XXE.java @@ -39,7 +39,7 @@ public class XXE extends NewLesson { @Override public Category getDefaultCategory() { - return Category.INJECTION; + return Category.XXE; } @Override From 41f252970ba70ac7b472f8a6e4d5cd8ea55f15e6 Mon Sep 17 00:00:00 2001 From: Rene Zubcevic Date: Tue, 21 May 2019 08:30:46 +0200 Subject: [PATCH 016/119] corrected path in pom --- webgoat-lessons/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webgoat-lessons/pom.xml b/webgoat-lessons/pom.xml index 959f701ad..1294595d7 100644 --- a/webgoat-lessons/pom.xml +++ b/webgoat-lessons/pom.xml @@ -136,7 +136,7 @@ ${project.packaging} - ../../webgoat-container/src/main/resources/plugin_lessons + ${project.basedir}/../webgoat-container/src/main/resources/plugin_lessons From 2eaf263e81c5ff236368122a3353a68cfa26cd22 Mon Sep 17 00:00:00 2001 From: Johannes Egger Date: Fri, 14 Jun 2019 14:56:10 +0200 Subject: [PATCH 017/119] Improve task description for HTTP proxy lesson --- .../main/resources/lessonPlans/en/HttpBasics_ProxyIntro5.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webgoat-lessons/http-proxies/src/main/resources/lessonPlans/en/HttpBasics_ProxyIntro5.adoc b/webgoat-lessons/http-proxies/src/main/resources/lessonPlans/en/HttpBasics_ProxyIntro5.adoc index db925accf..f55a64ece 100644 --- a/webgoat-lessons/http-proxies/src/main/resources/lessonPlans/en/HttpBasics_ProxyIntro5.adoc +++ b/webgoat-lessons/http-proxies/src/main/resources/lessonPlans/en/HttpBasics_ProxyIntro5.adoc @@ -19,7 +19,7 @@ modify it as follows. * Change the Method to GET * Add a header 'x-request-intercepted:true' -* Change the input value 'changeMe' to 'Requests are tampered easily' (without the single quotes) +* Remove the request body and instead send 'changeMe' as query string parameter and set the value to 'Requests are tampered easily' (without the single quotes) Then let the request continue through (by hitting the play button). From d81452222335e92723ab8da0760da6b684231e7c Mon Sep 17 00:00:00 2001 From: Johannes Egger Date: Fri, 14 Jun 2019 14:56:33 +0200 Subject: [PATCH 018/119] Fix test for HTTP proxy lesson --- .../owasp/webgoat/plugin/HttpBasicsInterceptRequestTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webgoat-lessons/http-proxies/src/test/java/org/owasp/webgoat/plugin/HttpBasicsInterceptRequestTest.java b/webgoat-lessons/http-proxies/src/test/java/org/owasp/webgoat/plugin/HttpBasicsInterceptRequestTest.java index b213cba1e..3de39b512 100644 --- a/webgoat-lessons/http-proxies/src/test/java/org/owasp/webgoat/plugin/HttpBasicsInterceptRequestTest.java +++ b/webgoat-lessons/http-proxies/src/test/java/org/owasp/webgoat/plugin/HttpBasicsInterceptRequestTest.java @@ -52,7 +52,7 @@ public class HttpBasicsInterceptRequestTest extends AssignmentEndpointTest { @Test public void success() throws Exception { - mockMvc.perform(MockMvcRequestBuilders.get("/challenge/1") + mockMvc.perform(MockMvcRequestBuilders.get("/HttpProxies/intercept-request") .header("x-request-intercepted", "true") .param("changeMe", "Requests are tampered easily")) .andExpect(status().isOk()) From 9471e5381850d71cb07740228375ef7c1966fa55 Mon Sep 17 00:00:00 2001 From: Johannes Egger Date: Fri, 14 Jun 2019 19:35:17 +0200 Subject: [PATCH 019/119] Fix image names for google chrome dev tools lesson --- ...onsole_Clear.JPG => ChromeDev_Console_Clear.jpg} | Bin ...eDev_Console_Ex.JPG => ChromeDev_Console_Ex.jpg} | Bin ...hromeDev_Elements.JPG => ChromeDev_Elements.jpg} | Bin ..._Elements_CSS.JPG => ChromeDev_Elements_CSS.jpg} | Bin ...{ChromeDev_Network.JPG => ChromeDev_Network.jpg} | Bin ...{ChromeDev_Sources.JPG => ChromeDev_Sources.jpg} | Bin 6 files changed, 0 insertions(+), 0 deletions(-) rename webgoat-lessons/chrome-dev-tools/src/main/resources/images/{ChromeDev_Console_Clear.JPG => ChromeDev_Console_Clear.jpg} (100%) rename webgoat-lessons/chrome-dev-tools/src/main/resources/images/{ChromeDev_Console_Ex.JPG => ChromeDev_Console_Ex.jpg} (100%) rename webgoat-lessons/chrome-dev-tools/src/main/resources/images/{ChromeDev_Elements.JPG => ChromeDev_Elements.jpg} (100%) rename webgoat-lessons/chrome-dev-tools/src/main/resources/images/{ChromeDev_Elements_CSS.JPG => ChromeDev_Elements_CSS.jpg} (100%) rename webgoat-lessons/chrome-dev-tools/src/main/resources/images/{ChromeDev_Network.JPG => ChromeDev_Network.jpg} (100%) rename webgoat-lessons/chrome-dev-tools/src/main/resources/images/{ChromeDev_Sources.JPG => ChromeDev_Sources.jpg} (100%) diff --git a/webgoat-lessons/chrome-dev-tools/src/main/resources/images/ChromeDev_Console_Clear.JPG b/webgoat-lessons/chrome-dev-tools/src/main/resources/images/ChromeDev_Console_Clear.jpg similarity index 100% rename from webgoat-lessons/chrome-dev-tools/src/main/resources/images/ChromeDev_Console_Clear.JPG rename to webgoat-lessons/chrome-dev-tools/src/main/resources/images/ChromeDev_Console_Clear.jpg diff --git a/webgoat-lessons/chrome-dev-tools/src/main/resources/images/ChromeDev_Console_Ex.JPG b/webgoat-lessons/chrome-dev-tools/src/main/resources/images/ChromeDev_Console_Ex.jpg similarity index 100% rename from webgoat-lessons/chrome-dev-tools/src/main/resources/images/ChromeDev_Console_Ex.JPG rename to webgoat-lessons/chrome-dev-tools/src/main/resources/images/ChromeDev_Console_Ex.jpg diff --git a/webgoat-lessons/chrome-dev-tools/src/main/resources/images/ChromeDev_Elements.JPG b/webgoat-lessons/chrome-dev-tools/src/main/resources/images/ChromeDev_Elements.jpg similarity index 100% rename from webgoat-lessons/chrome-dev-tools/src/main/resources/images/ChromeDev_Elements.JPG rename to webgoat-lessons/chrome-dev-tools/src/main/resources/images/ChromeDev_Elements.jpg diff --git a/webgoat-lessons/chrome-dev-tools/src/main/resources/images/ChromeDev_Elements_CSS.JPG b/webgoat-lessons/chrome-dev-tools/src/main/resources/images/ChromeDev_Elements_CSS.jpg similarity index 100% rename from webgoat-lessons/chrome-dev-tools/src/main/resources/images/ChromeDev_Elements_CSS.JPG rename to webgoat-lessons/chrome-dev-tools/src/main/resources/images/ChromeDev_Elements_CSS.jpg diff --git a/webgoat-lessons/chrome-dev-tools/src/main/resources/images/ChromeDev_Network.JPG b/webgoat-lessons/chrome-dev-tools/src/main/resources/images/ChromeDev_Network.jpg similarity index 100% rename from webgoat-lessons/chrome-dev-tools/src/main/resources/images/ChromeDev_Network.JPG rename to webgoat-lessons/chrome-dev-tools/src/main/resources/images/ChromeDev_Network.jpg diff --git a/webgoat-lessons/chrome-dev-tools/src/main/resources/images/ChromeDev_Sources.JPG b/webgoat-lessons/chrome-dev-tools/src/main/resources/images/ChromeDev_Sources.jpg similarity index 100% rename from webgoat-lessons/chrome-dev-tools/src/main/resources/images/ChromeDev_Sources.JPG rename to webgoat-lessons/chrome-dev-tools/src/main/resources/images/ChromeDev_Sources.jpg From 99435a107320df6e3cdca06afac813f48b4b86ca Mon Sep 17 00:00:00 2001 From: Rene Zubcevic Date: Fri, 19 Jul 2019 12:16:06 +0200 Subject: [PATCH 020/119] increased sql form fields and fixed chrome progress --- .../owasp/webgoat/plugin/NetworkDummy.java | 14 ++++++- .../owasp/webgoat/plugin/NetworkLesson.java | 10 ++++- .../main/resources/html/ChromeDevTools.html | 41 ++++--------------- .../src/main/resources/html/SqlInjection.html | 8 ++-- 4 files changed, 33 insertions(+), 40 deletions(-) diff --git a/webgoat-lessons/chrome-dev-tools/src/main/java/org/owasp/webgoat/plugin/NetworkDummy.java b/webgoat-lessons/chrome-dev-tools/src/main/java/org/owasp/webgoat/plugin/NetworkDummy.java index 9a462f77a..e5efd285d 100644 --- a/webgoat-lessons/chrome-dev-tools/src/main/java/org/owasp/webgoat/plugin/NetworkDummy.java +++ b/webgoat-lessons/chrome-dev-tools/src/main/java/org/owasp/webgoat/plugin/NetworkDummy.java @@ -3,6 +3,7 @@ package org.owasp.webgoat.plugin; import org.owasp.webgoat.assignments.AssignmentEndpoint; import org.owasp.webgoat.assignments.AssignmentPath; import org.owasp.webgoat.assignments.AttackResult; +import org.owasp.webgoat.session.UserSessionData; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; @@ -21,7 +22,16 @@ public class NetworkDummy extends AssignmentEndpoint { @RequestMapping(method = RequestMethod.POST) public @ResponseBody - AttackResult completed(@RequestParam String networkNum) throws IOException { - return trackProgress(failed().feedback("network.request").build()); + AttackResult completed(@RequestParam String successMessage) throws IOException { + + UserSessionData userSessionData = getUserSessionData(); + String answer = (String) userSessionData.getValue("randValue"); + + if (successMessage!=null && successMessage.equals(answer)) { + return trackProgress(success().feedback("xss-dom-message-success").build()); + } else { + return trackProgress(failed().feedback("xss-dom-message-failure").build()); + } + } } \ No newline at end of file diff --git a/webgoat-lessons/chrome-dev-tools/src/main/java/org/owasp/webgoat/plugin/NetworkLesson.java b/webgoat-lessons/chrome-dev-tools/src/main/java/org/owasp/webgoat/plugin/NetworkLesson.java index 41071eaff..1969e53e9 100644 --- a/webgoat-lessons/chrome-dev-tools/src/main/java/org/owasp/webgoat/plugin/NetworkLesson.java +++ b/webgoat-lessons/chrome-dev-tools/src/main/java/org/owasp/webgoat/plugin/NetworkLesson.java @@ -4,6 +4,7 @@ import org.owasp.webgoat.assignments.AssignmentEndpoint; import org.owasp.webgoat.assignments.AssignmentHints; import org.owasp.webgoat.assignments.AssignmentPath; import org.owasp.webgoat.assignments.AttackResult; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; @@ -21,7 +22,7 @@ import java.io.IOException; @AssignmentHints({"networkHint1", "networkHint2"}) public class NetworkLesson extends AssignmentEndpoint { - @RequestMapping(method = RequestMethod.POST) + @RequestMapping(method = RequestMethod.POST, params= {"network_num","number"}) public @ResponseBody AttackResult completed(@RequestParam String network_num, @RequestParam String number) throws IOException { @@ -31,4 +32,11 @@ public class NetworkLesson extends AssignmentEndpoint { return trackProgress(failed().feedback("network.failed").build()); } } + + @RequestMapping(method = RequestMethod.POST, params="networkNum") + public + @ResponseBody + ResponseEntity ok(@RequestParam String networkNum) throws IOException { + return ResponseEntity.ok().build(); + } } diff --git a/webgoat-lessons/chrome-dev-tools/src/main/resources/html/ChromeDevTools.html b/webgoat-lessons/chrome-dev-tools/src/main/resources/html/ChromeDevTools.html index d8d576bb6..807cc5a4b 100644 --- a/webgoat-lessons/chrome-dev-tools/src/main/resources/html/ChromeDevTools.html +++ b/webgoat-lessons/chrome-dev-tools/src/main/resources/html/ChromeDevTools.html @@ -2,25 +2,29 @@ +
+
+
+
@@ -30,17 +34,19 @@
+
+
@@ -78,7 +78,7 @@
diff --git a/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/mitigation/SqlInjectionLesson12aTest.java b/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/mitigation/SqlInjectionLesson12aTest.java index cee8e8c13..974d48b7f 100644 --- a/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/mitigation/SqlInjectionLesson12aTest.java +++ b/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/mitigation/SqlInjectionLesson12aTest.java @@ -38,7 +38,7 @@ public class SqlInjectionLesson12aTest extends LessonTest { @Test public void knownAccountShouldDisplayData() throws Exception { - mockMvc.perform(MockMvcRequestBuilders.get("/SqlInjection/servers") + mockMvc.perform(MockMvcRequestBuilders.get("/SqlInjectionMitigations/servers") .param("column", "id")) .andExpect(status().isOk()); @@ -46,7 +46,7 @@ public class SqlInjectionLesson12aTest extends LessonTest { @Test public void addressCorrectShouldOrderByHostname() throws Exception { - mockMvc.perform(MockMvcRequestBuilders.get("/SqlInjection/servers") + 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"))); @@ -54,17 +54,17 @@ public class SqlInjectionLesson12aTest extends LessonTest { @Test public void addressCorrectShouldOrderByHostnameUsingSubstr() throws Exception { - mockMvc.perform(MockMvcRequestBuilders.get("/SqlInjection/servers") + 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("/SqlInjection/servers") + 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("/SqlInjection/servers") + 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"))); @@ -72,7 +72,7 @@ public class SqlInjectionLesson12aTest extends LessonTest { @Test public void addressIncorrectShouldOrderByIdUsingSubstr() throws Exception { - mockMvc.perform(MockMvcRequestBuilders.get("/SqlInjection/servers") + 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"))); @@ -80,7 +80,7 @@ public class SqlInjectionLesson12aTest extends LessonTest { @Test public void trueShouldSortByHostname() throws Exception { - mockMvc.perform(MockMvcRequestBuilders.get("/SqlInjection/servers") + mockMvc.perform(MockMvcRequestBuilders.get("/SqlInjectionMitigations/servers") .param("column", "(case when (true) then hostname else id end)")) .andExpect(status().isOk()) @@ -89,7 +89,7 @@ public class SqlInjectionLesson12aTest extends LessonTest { @Test public void falseShouldSortById() throws Exception { - mockMvc.perform(MockMvcRequestBuilders.get("/SqlInjection/servers") + mockMvc.perform(MockMvcRequestBuilders.get("/SqlInjectionMitigations/servers") .param("column", "(case when (true) then hostname else id end)")) .andExpect(status().isOk()) @@ -98,7 +98,7 @@ public class SqlInjectionLesson12aTest extends LessonTest { @Test public void addressIncorrectShouldOrderByHostname() throws Exception { - mockMvc.perform(MockMvcRequestBuilders.get("/SqlInjection/servers") + 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"))); @@ -106,7 +106,7 @@ public class SqlInjectionLesson12aTest extends LessonTest { @Test public void postingCorrectAnswerShouldPassTheLesson() throws Exception { - mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack12a") + mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjectionMitigations/attack12a") .param("ip", "104.130.219.202")) .andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(true))); @@ -114,7 +114,7 @@ public class SqlInjectionLesson12aTest extends LessonTest { @Test public void postingWrongAnswerShouldNotPassTheLesson() throws Exception { - mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack12a") + mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjectionMitigations/attack12a") .param("ip", "192.168.219.202")) .andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(false))); From 7ad3996f2fe1905107d7b24d7f3c369e794e7d76 Mon Sep 17 00:00:00 2001 From: Rene Zubcevic Date: Mon, 22 Jul 2019 15:36:31 +0200 Subject: [PATCH 026/119] fix 6a6b page --- .../owasp/webgoat/plugin/advanced/SqlInjectionLesson6a.java | 2 +- .../src/main/resources/html/SqlInjectionAdvanced.html | 2 +- .../webgoat/plugin/introduction/SqlInjectionLesson6aTest.java | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionLesson6a.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionLesson6a.java index 9bf990d3c..f2affbeee 100644 --- a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionLesson6a.java +++ b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionLesson6a.java @@ -83,7 +83,7 @@ public class SqlInjectionLesson6a extends AssignmentEndpoint { if (output.toString().contains("dave") && output.toString().contains("passW0rD")) { output.append(appendingWhenSucceded); - return trackProgress(informationMessage().feedback("sql-injection.advanced.6a.success").feedbackArgs(output.toString()).output(" Your query was: " + query).build()); + return trackProgress(success().feedback("sql-injection.advanced.6a.success").feedbackArgs(output.toString()).output(" Your query was: " + query).build()); } else { return trackProgress(failed().output(output.toString() + "
Your query was: " + query).build()); } diff --git a/webgoat-lessons/sql-injection/src/main/resources/html/SqlInjectionAdvanced.html b/webgoat-lessons/sql-injection/src/main/resources/html/SqlInjectionAdvanced.html index de3c4dee2..bca28bd63 100644 --- a/webgoat-lessons/sql-injection/src/main/resources/html/SqlInjectionAdvanced.html +++ b/webgoat-lessons/sql-injection/src/main/resources/html/SqlInjectionAdvanced.html @@ -18,7 +18,7 @@
- diff --git a/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson6aTest.java b/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson6aTest.java index be88f4b75..dc65e7eb3 100644 --- a/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson6aTest.java +++ b/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson6aTest.java @@ -62,7 +62,7 @@ public class SqlInjectionLesson6aTest extends LessonTest { mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjectionAdvanced/attack6a") .param("userid_6a", "Smith'; SELECT * from user_system_data; --")) .andExpect(status().isOk()) - .andExpect(jsonPath("$.lessonCompleted", is(false))) + .andExpect(jsonPath("$.lessonCompleted", is(true))) .andExpect(jsonPath("$.feedback", containsString("passW0rD"))); } @@ -82,6 +82,7 @@ public class SqlInjectionLesson6aTest extends LessonTest { .param("userid_6a", "S'; Select * from user_system_data; --")) .andExpect(status().isOk()) + .andExpect(jsonPath("$.lessonCompleted", is(true))) .andExpect(jsonPath("$.feedback", containsString("UNION"))); } } \ No newline at end of file From b395be9bd0c4c0c4591975bd0001c15fa4be187c Mon Sep 17 00:00:00 2001 From: gh-jwhite <45404692+gh-jwhite@users.noreply.github.com> Date: Tue, 23 Jul 2019 10:38:25 -0600 Subject: [PATCH 027/119] Create do-not-merge.md testing a status check/branch protection thing --- do-not-merge.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 do-not-merge.md diff --git a/do-not-merge.md b/do-not-merge.md new file mode 100644 index 000000000..ba2cf2f59 --- /dev/null +++ b/do-not-merge.md @@ -0,0 +1,4 @@ +# DO NOT MERGE + +## Just a Test +... that is all From 67440a6cc8a9e98b1a4b6244bdf3f712e07d3fd9 Mon Sep 17 00:00:00 2001 From: gh-jwhite <45404692+gh-jwhite@users.noreply.github.com> Date: Tue, 23 Jul 2019 14:18:51 -0600 Subject: [PATCH 028/119] Delete do-not-merge.md removing earlier test file --- do-not-merge.md | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 do-not-merge.md diff --git a/do-not-merge.md b/do-not-merge.md deleted file mode 100644 index ba2cf2f59..000000000 --- a/do-not-merge.md +++ /dev/null @@ -1,4 +0,0 @@ -# DO NOT MERGE - -## Just a Test -... that is all From 216b29fca2f61aabecfb1077dd0a319c623de18a Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Fri, 19 Jul 2019 14:30:58 +0200 Subject: [PATCH 029/119] Clean up in pom files --- README.MD | 42 -------- pom.xml | 95 +------------------ webgoat-container/pom.xml | 69 ++++---------- .../webgoat/AsciiDoctorTemplateResolver.java | 4 +- .../main/java/org/owasp/webgoat/WebGoat.java | 21 ---- .../org/owasp/webgoat/WebSecurityConfig.java | 2 - .../webgoat/assignments/AttackResult.java | 1 + .../src/main/resources/application.properties | 1 - .../src/test/scala/Simulation.scala | 27 ------ ...assRestrictionsFrontendValidationTest.java | 2 +- webgoat-lessons/cross-site-scripting/pom.xml | 8 ++ .../owasp/webgoat/plugin/ForgedReviews.java | 4 +- .../webgoat/plugin/JWTFinalEndpoint.java | 2 +- .../webgoat/plugin/JWTFinalEndpointTest.java | 9 ++ webgoat-lessons/pom.xml | 50 ++++------ webgoat-server/pom.xml | 76 --------------- webwolf/pom.xml | 15 ++- 17 files changed, 77 insertions(+), 351 deletions(-) delete mode 100644 webgoat-container/src/test/scala/Simulation.scala diff --git a/README.MD b/README.MD index 099d49aef..654454fd3 100644 --- a/README.MD +++ b/README.MD @@ -97,27 +97,10 @@ To change IP address add the following variable to WebGoat/webgoat-container/src server.address=x.x.x.x ``` -# Vagrant - -We supply a complete environment using Vagrant, to run WebGoat with Vagrant you must first have Vagrant and Virtualbox installed. - -```shell - $ cd WebGoat/webgoat-images/vagrant-training - $ vagrant up -``` - -Once the provisioning is complete login to the Virtualbox with username vagrant and password vagrant. -WebGoat and WebWolf will automatically start when you login to this image. - - # Building a new Docker image NOTE: Travis will create a new Docker image automatically when making a new release. -WebGoat now has Docker support for x86 and ARM (raspberry pi). -### Docker on x86 -On x86 you can build a container with the following commands: - ```Shell cd WebGoat/ mvn install @@ -128,31 +111,6 @@ docker login docker push webgoat/webgoat-8.0 ``` -### Docker on ARM (Raspberry Pi) -On a Raspberry Pi (it has yet been tested with a Raspberry Pi 3 and the hypriot Docker image) you need to build JFFI for -ARM first. This is needed by the docker-maven-plugin ([see here](https://github.com/spotify/docker-maven-plugin/issues/233)): - -```Shell -sudo apt-get install build-essential -git clone https://github.com/jnr/jffi.git -cd jffi -ant jar -cd build/jni -sudo cp libjffi-1.2.so /usr/lib -``` - -When you have done this you can build the Docker container using the following commands: - -```Shell -cd WebGoat/ -mvn install -cd webgoat-server -mvn docker:build -Drpi=true -docker tag webgoat/webgoat-8.0 webgoat/webgoat-8.0:8.0 -docker login -docker push webgoat/webgoat-8.0 -``` - # Run Instructions: Once installed connect to http://localhost:8080/WebGoat and http://localhost:9090/WebWolf diff --git a/pom.xml b/pom.xml index cb133b10f..36b9913c0 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ org.springframework.boot spring-boot-starter-parent - 1.5.18.RELEASE + 1.5.21.RELEASE @@ -116,46 +116,19 @@ 1.1.1 - 1.4 - 1.4 - 1.4 - 1.4 - 1.9.1 - 2.7 3.2.1 - 2.1 - 0.5 - 1.3.1 - 2.6 3.4 - 4.0.0 - 2.2.5 - 2.2.4 + 2.6 18.0 - 1.4.190 2.3.4 - 1.3.1 - 2.6.3 - 2.6.3 - 6.0 - 1.3 - 1.7.12 - 1.3.1 4.12 1.18.4 - 1.5.4 3.8.0 2.22.0 - 1.6 - 3.1.1 - 2.10.4 - 2.5.2 - 3.0.1 + 3.1.2 + 3.1.1 + 3.1.0 2.22.0 - 1.6.6 - 2.11.7 - 2.1.20 - 2.48.2 3.2.4.RELEASE @@ -166,32 +139,6 @@ webwolf - - - ossrh - https://oss.sonatype.org/content/repositories/snapshots - - - ossrh - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - - - - - apache.snapshots - http://repository.apache.org/snapshots/ - - - daily - - - daily - - - - org.projectlombok @@ -224,38 +171,6 @@ UTF-8 - - org.apache.maven.plugins - maven-release-plugin - ${maven-release-plugin.version} - - true - false - release - @{project.version} - deploy - - - - org.eluder.coveralls - coveralls-maven-plugin - ${coveralls-maven-plugin.version} - - - - - - org.codehaus.mojo - cobertura-maven-plugin - ${cobertura-maven-plugin.version} - - - xml - 256m - - true - - diff --git a/webgoat-container/pom.xml b/webgoat-container/pom.xml index 2f766037a..cf324686b 100644 --- a/webgoat-container/pom.xml +++ b/webgoat-container/pom.xml @@ -13,29 +13,6 @@ v8.0.0-SNAPSHOT - - - performance - - - - io.gatling - gatling-maven-plugin - ${gatling-plugin.version} - - - - execute - - - - - - - - - - @@ -69,7 +46,11 @@ maven-surefire-plugin ${maven-surefire-plugin.version} - never + 0 + true + + --illegal-access=permit + @@ -89,12 +70,23 @@ - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 + org.springframework.boot + spring-boot-starter-undertow org.springframework.boot spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-tomcat + + + + + javax.activation + activation + ${activation.version} org.springframework.boot @@ -119,14 +111,6 @@ guava ${guava.version} - - - - io.gatling.highcharts - gatling-charts-highcharts - ${gatling.version} - test - org.springframework.boot spring-boot-starter-security @@ -140,28 +124,11 @@ thymeleaf-extras-springsecurity4 2.1.2.RELEASE - - javax.activation - activation - ${activation.version} - org.hsqldb hsqldb ${hsqldb.version} - - javax.transaction - javax.transaction-api - ${javax.transaction-api.version} - - - org.scala-lang - scala-compiler - ${scala.version} - test - - diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/AsciiDoctorTemplateResolver.java b/webgoat-container/src/main/java/org/owasp/webgoat/AsciiDoctorTemplateResolver.java index df4c11e0b..e5a4c7da9 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/AsciiDoctorTemplateResolver.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/AsciiDoctorTemplateResolver.java @@ -44,9 +44,9 @@ import org.thymeleaf.resourceresolver.IResourceResolver; import org.thymeleaf.templateresolver.TemplateResolver; import java.io.*; +import java.nio.charset.StandardCharsets; import java.util.Map; -import static org.apache.commons.lang3.CharEncoding.UTF_8; import static org.asciidoctor.Asciidoctor.Factory.create; /** @@ -92,7 +92,7 @@ public class AsciiDoctorTemplateResolver extends TemplateResolver { extensionRegistry.inlineMacro("webGoatVersion", WebGoatVersionMacro.class); asciidoctor.convert(new InputStreamReader(is), writer, createAttributes()); - return new ByteArrayInputStream(writer.getBuffer().toString().getBytes(UTF_8)); + return new ByteArrayInputStream(writer.getBuffer().toString().getBytes(StandardCharsets.UTF_8)); } } catch (IOException e) { //no html yet diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java b/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java index d78e248d7..e18374c23 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java @@ -31,7 +31,6 @@ package org.owasp.webgoat; import lombok.extern.slf4j.Slf4j; -import org.apache.catalina.Context; import org.owasp.webgoat.plugins.PluginEndpointPublisher; import org.owasp.webgoat.plugins.PluginsLoader; import org.owasp.webgoat.session.Course; @@ -42,9 +41,6 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; -import org.springframework.boot.context.embedded.tomcat.TomcatContextCustomizer; -import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; import org.springframework.boot.web.support.SpringBootServletInitializer; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; @@ -53,7 +49,6 @@ import org.springframework.context.annotation.ScopedProxyMode; import org.springframework.web.client.RestTemplate; import java.io.File; -import java.util.Arrays; @SpringBootApplication @Slf4j @@ -99,20 +94,4 @@ public class WebGoat extends SpringBootServletInitializer { public RestTemplate restTemplate() { return new RestTemplate(); } - - @Bean - public EmbeddedServletContainerFactory servletContainer() { - TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory(); - factory.setTomcatContextCustomizers(Arrays.asList(new CustomCustomizer())); - return factory; - } - - static class CustomCustomizer implements TomcatContextCustomizer { - @Override - public void customize(Context context) { - context.setUseHttpOnly(false); - } - } - - } diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/WebSecurityConfig.java b/webgoat-container/src/main/java/org/owasp/webgoat/WebSecurityConfig.java index 05f185927..b8b526af8 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/WebSecurityConfig.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/WebSecurityConfig.java @@ -58,8 +58,6 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry security = http .authorizeRequests() .antMatchers("/css/**", "/images/**", "/js/**", "fonts/**", "/plugins/**", "/registration", "/register.mvc").permitAll() - .antMatchers("/servlet/AdminServlet/**").hasAnyRole("WEBGOAT_ADMIN", "SERVER_ADMIN") // - .antMatchers("/JavaSource/**").hasRole("SERVER_ADMIN") // .anyRequest().authenticated(); security.and() .formLogin() diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/assignments/AttackResult.java b/webgoat-container/src/main/java/org/owasp/webgoat/assignments/AttackResult.java index e78d46338..573f488a1 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/assignments/AttackResult.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/assignments/AttackResult.java @@ -25,6 +25,7 @@ package org.owasp.webgoat.assignments; +import com.google.common.base.Strings; import lombok.Getter; import org.apache.commons.lang3.StringEscapeUtils; import org.owasp.webgoat.i18n.PluginMessages; diff --git a/webgoat-container/src/main/resources/application.properties b/webgoat-container/src/main/resources/application.properties index 281b53230..2346f3f30 100644 --- a/webgoat-container/src/main/resources/application.properties +++ b/webgoat-container/src/main/resources/application.properties @@ -17,7 +17,6 @@ spring.jpa.hibernate.ddl-auto=update spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.HSQLDialect spring.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver - logging.level.org.springframework=INFO logging.level.org.springframework.boot.devtools=INFO logging.level.org.owasp=DEBUG diff --git a/webgoat-container/src/test/scala/Simulation.scala b/webgoat-container/src/test/scala/Simulation.scala deleted file mode 100644 index 4e8fe9b42..000000000 --- a/webgoat-container/src/test/scala/Simulation.scala +++ /dev/null @@ -1,27 +0,0 @@ -import io.gatling.core.Predef._ -import io.gatling.http.Predef._ -import org.apache.commons.lang3.RandomStringUtils - -import scala.concurrent.duration._ - -class BasicSimulation extends Simulation { - - val httpConf = http - .baseURL("http://localhost:8080/WebGoat/") // Here is the root for all relative URLs - .userAgentHeader("Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20100101 Firefox/16.0") - - val scn = scenario("Register and automatic login"). - exec(session => - session.setAll(("username", RandomStringUtils.randomAlphabetic(10))) - ) - .exec( - http("Test") - .post("register.mvc") - .formParam("username", "${username}") - .formParam("password", "${username}") - .formParam("matchingPassword", "${username}") - .formParam("agree", "agree") - ) - - setUp(scn.inject(atOnceUsers(100)).protocols(httpConf)) -} \ No newline at end of file diff --git a/webgoat-lessons/bypass-restrictions/src/test/java/org/owasp/webgoat/plugin/BypassRestrictionsFrontendValidationTest.java b/webgoat-lessons/bypass-restrictions/src/test/java/org/owasp/webgoat/plugin/BypassRestrictionsFrontendValidationTest.java index 34bb4dd54..4c7d630c5 100644 --- a/webgoat-lessons/bypass-restrictions/src/test/java/org/owasp/webgoat/plugin/BypassRestrictionsFrontendValidationTest.java +++ b/webgoat-lessons/bypass-restrictions/src/test/java/org/owasp/webgoat/plugin/BypassRestrictionsFrontendValidationTest.java @@ -21,7 +21,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. public class BypassRestrictionsFrontendValidationTest extends LessonTest { @Before - public void setup() throws Exception { + public void setup() { when(webSession.getCurrentLesson()).thenReturn(new BypassRestrictions()); this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); } diff --git a/webgoat-lessons/cross-site-scripting/pom.xml b/webgoat-lessons/cross-site-scripting/pom.xml index 6c99401b6..9deca9f21 100644 --- a/webgoat-lessons/cross-site-scripting/pom.xml +++ b/webgoat-lessons/cross-site-scripting/pom.xml @@ -8,6 +8,14 @@ webgoat-lessons-parent v8.0.0-SNAPSHOT + + + + org.jsoup + jsoup + 1.11.3 + + diff --git a/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/plugin/ForgedReviews.java b/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/plugin/ForgedReviews.java index f27684843..12d8cf1ce 100644 --- a/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/plugin/ForgedReviews.java +++ b/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/plugin/ForgedReviews.java @@ -32,10 +32,8 @@ package org.owasp.webgoat.plugin; import com.beust.jcommander.internal.Lists; -import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.EvictingQueue; import com.google.common.collect.Maps; -import org.apache.catalina.servlet4preview.http.HttpServletRequest; import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; @@ -46,11 +44,11 @@ import org.owasp.webgoat.assignments.AttackResult; import org.owasp.webgoat.session.WebSession; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; -import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; +import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.util.Collection; import java.util.Map; diff --git a/webgoat-lessons/jwt/src/main/java/org/owasp/webgoat/plugin/JWTFinalEndpoint.java b/webgoat-lessons/jwt/src/main/java/org/owasp/webgoat/plugin/JWTFinalEndpoint.java index cec9fd62c..6efba6025 100644 --- a/webgoat-lessons/jwt/src/main/java/org/owasp/webgoat/plugin/JWTFinalEndpoint.java +++ b/webgoat-lessons/jwt/src/main/java/org/owasp/webgoat/plugin/JWTFinalEndpoint.java @@ -84,7 +84,7 @@ public class JWTFinalEndpoint extends AssignmentEndpoint { } return null; } - }).parse(token); + }).parseClaimsJws(token); if (errorMessage[0] != null) { return trackProgress(failed().output(errorMessage[0]).build()); } diff --git a/webgoat-lessons/jwt/src/test/java/org/owasp/webgoat/plugin/JWTFinalEndpointTest.java b/webgoat-lessons/jwt/src/test/java/org/owasp/webgoat/plugin/JWTFinalEndpointTest.java index fefdbe8f0..bc90c4534 100644 --- a/webgoat-lessons/jwt/src/test/java/org/owasp/webgoat/plugin/JWTFinalEndpointTest.java +++ b/webgoat-lessons/jwt/src/test/java/org/owasp/webgoat/plugin/JWTFinalEndpointTest.java @@ -59,4 +59,13 @@ public class JWTFinalEndpointTest extends LessonTest { .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")))); + } } \ No newline at end of file diff --git a/webgoat-lessons/pom.xml b/webgoat-lessons/pom.xml index 1294595d7..6f28f4954 100644 --- a/webgoat-lessons/pom.xml +++ b/webgoat-lessons/pom.xml @@ -32,7 +32,7 @@ vulnerable-components webgoat-introduction webwolf-introduction - auth-bypass + auth-bypass missing-function-ac csrf password-reset @@ -67,7 +67,6 @@ org.mockito mockito-core - 1.10.19 test @@ -97,12 +96,6 @@ xstream 1.4.7 - - - org.jsoup - jsoup - 1.11.3 - @@ -118,28 +111,25 @@ org.apache.maven.plugins - maven-dependency-plugin - - - copy-artifact-src - package - - copy - - - true - - - ${project.groupId} - ${project.artifactId} - ${project.version} - ${project.packaging} - - - ${project.basedir}/../webgoat-container/src/main/resources/plugin_lessons - - - + maven-surefire-plugin + ${maven-surefire-plugin.version} + + 0 + true + + --illegal-access=permit + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 11 + 11 + UTF-8 + diff --git a/webgoat-server/pom.xml b/webgoat-server/pom.xml index 6317305ed..95bb65f69 100644 --- a/webgoat-server/pom.xml +++ b/webgoat-server/pom.xml @@ -13,83 +13,7 @@ org.owasp.webgoat.StartWebGoat - - - raspberry-pi-3 - - - rpi - - - - - - com.spotify - docker-maven-plugin - 0.4.10 - - webgoat/webgoat-8.0 - src/main/docker_rpi3 - - - / - ${project.build.directory} - ${project.build.finalName}.jar - - - / - ${project.basedir}/../webwolf/target - webwolf-${project.version}.jar - - - - - - - - - default - - - !rpi - - - - - - com.spotify - docker-maven-plugin - 0.4.10 - - webgoat/webgoat-8.0 - ${project.basedir} - - - / - ${project.build.directory} - ${project.build.finalName}.jar - - - / - ${project.basedir}/../webwolf/target - webwolf-${project.version}.jar - - - - - - - - - - - com.spotify - docker-maven-plugin - 0.4.10 - test - true - org.owasp.webgoat webgoat-container diff --git a/webwolf/pom.xml b/webwolf/pom.xml index 385a0fbc5..c0126b712 100644 --- a/webwolf/pom.xml +++ b/webwolf/pom.xml @@ -28,10 +28,6 @@ commons-io ${commons-io.version} - - org.springframework.boot - spring-boot-starter-cache - org.springframework.boot spring-boot-starter-security @@ -114,6 +110,17 @@ org.springframework.boot spring-boot-maven-plugin + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + never + + --illegal-access=permit + + + From 33c73a7dca475b877f61d8d93d6cf48ae8c28d70 Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Fri, 19 Jul 2019 15:07:18 +0200 Subject: [PATCH 030/119] Adding new developer --- pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pom.xml b/pom.xml index 36b9913c0..e000e6e90 100644 --- a/pom.xml +++ b/pom.xml @@ -51,6 +51,11 @@ Jason White jason.white@owasp.org + + zubcevic + René Zubcevic + rene.zubcevic@owasp.org + jwayman Jeff Wayman From ffbc808e266bc6684d994a29a35fa5f264d5f81d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Zubcevic?= Date: Thu, 25 Jul 2019 10:49:25 +0200 Subject: [PATCH 031/119] Integration test support --- webgoat-server/pom.xml | 12 +- .../org/owasp/webgoat/General_TestHelper.java | 133 ++++++++++++++ .../SqlInjectionAdvanced_TestHelper.java | 36 ++++ .../SqlInjectionMitigation_TestHelper.java | 37 ++++ .../webgoat/SqlInjection_TestHelper.java | 80 +++++++++ .../java/org/owasp/webgoat/TestHelper.java | 95 ++++++++++ .../owasp/webgoat/WebGoatIntegrationTest.java | 162 ++++++++++++++++++ 7 files changed, 554 insertions(+), 1 deletion(-) create mode 100644 webgoat-server/src/test/java/org/owasp/webgoat/General_TestHelper.java create mode 100644 webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionAdvanced_TestHelper.java create mode 100644 webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionMitigation_TestHelper.java create mode 100644 webgoat-server/src/test/java/org/owasp/webgoat/SqlInjection_TestHelper.java create mode 100644 webgoat-server/src/test/java/org/owasp/webgoat/TestHelper.java create mode 100644 webgoat-server/src/test/java/org/owasp/webgoat/WebGoatIntegrationTest.java diff --git a/webgoat-server/pom.xml b/webgoat-server/pom.xml index 95bb65f69..5c0ae93b2 100644 --- a/webgoat-server/pom.xml +++ b/webgoat-server/pom.xml @@ -139,7 +139,17 @@ secure-passwords ${project.version} - + + org.springframework.boot + spring-boot-starter-test + test + + + io.rest-assured + rest-assured + 4.0.0 + test + diff --git a/webgoat-server/src/test/java/org/owasp/webgoat/General_TestHelper.java b/webgoat-server/src/test/java/org/owasp/webgoat/General_TestHelper.java new file mode 100644 index 000000000..adce19bb5 --- /dev/null +++ b/webgoat-server/src/test/java/org/owasp/webgoat/General_TestHelper.java @@ -0,0 +1,133 @@ +package org.owasp.webgoat; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import java.util.HashMap; +import java.util.Map; + +import io.restassured.http.ContentType; + + +public class General_TestHelper extends TestHelper { + + + public void httpBasics(String webgoatURL, String cookie) { + + startLesson(cookie, webgoatURL, "HttpBasics"); + Map params = new HashMap<>(); + params.clear(); + params.put("person", "goatuser"); + checkAssignment(cookie, webgoatURL+"/WebGoat/HttpBasics/attack1", params, true); + + params.clear(); + params.put("answer", "POST"); + params.put("magic_answer", "33"); + params.put("magic_num", "4"); + checkAssignment(cookie, webgoatURL+"/WebGoat/HttpBasics/attack2", params, false); + + params.clear(); + params.put("answer", "POST"); + params.put("magic_answer", "33"); + params.put("magic_num", "33"); + checkAssignment(cookie, webgoatURL+"/WebGoat/HttpBasics/attack2", params, true); + + checkResults(cookie, webgoatURL, "/HttpBasics/"); + + } + + public void httpProxies(String webgoatURL, String cookie) { + + startLesson(cookie, webgoatURL, "HttpProxies"); + assertThat(given() + .when().config(restConfig).cookie("JSESSIONID", cookie).header("x-request-intercepted", "true") + .contentType(ContentType.JSON).log().all() + .get(webgoatURL + "/WebGoat/HttpProxies/intercept-request?changeMe=Requests are tampered easily").then() + .log().all().statusCode(200).extract().path("lessonCompleted"), is(true)); + + checkResults(cookie, webgoatURL, "/HttpProxies/"); + + } + + public void cia(String webgoatURL, String cookie) { + + startLesson(cookie, webgoatURL, "CIA"); + Map params = new HashMap<>(); + params.clear(); + params.put("question_0_solution", "Solution 3: By stealing a database where names and emails are stored and uploading it to a website."); + params.put("question_1_solution", "Solution 1: By changing the names and emails of one or more users stored in a database."); + params.put("question_2_solution", "Solution 4: By launching a denial of service attack on the servers."); + params.put("question_3_solution", "Solution 2: The systems security is compromised even if only one goal is harmed."); + checkAssignment(cookie, webgoatURL+"/WebGoat/cia/quiz", params, true); + checkResults(cookie, webgoatURL, "/cia/"); + + } + + public void securePasswords(String webgoatURL, String cookie) { + + startLesson(cookie, webgoatURL, "SecurePasswords"); + Map params = new HashMap<>(); + params.clear(); + params.put("password", "ajnaeliclm^&&@kjn."); + checkAssignment(cookie, webgoatURL+"/WebGoat/SecurePasswords/assignment", params, true); + checkResults(cookie, webgoatURL, "SecurePasswords/"); + + startLesson(cookie, webgoatURL, "AuthBypass"); + params.clear(); + params.put("secQuestion2", "John"); + params.put("secQuestion3", "Main"); + params.put("jsEnabled", "1"); + params.put("verifyMethod", "SEC_QUESTIONS"); + params.put("userId", "12309746"); + checkAssignment(cookie, webgoatURL + "/WebGoat/auth-bypass/verify-account", params, true); + checkResults(cookie, webgoatURL, "/auth-bypass/"); + + startLesson(cookie, webgoatURL, "HttpProxies"); + assertThat(given().when().config(restConfig).cookie("JSESSIONID", cookie).header("x-request-intercepted", "true") + .contentType(ContentType.JSON).log().all() + .get(webgoatURL + "/WebGoat/HttpProxies/intercept-request?changeMe=Requests are tampered easily").then() + .log().all().statusCode(200).extract().path("lessonCompleted"), is(true)); + checkResults(cookie, webgoatURL, "/HttpProxies/"); + + } + + public void chrome(String webgoatURL, String cookie) { + + startLesson(cookie, webgoatURL, "ChromeDevTools"); + + Map params = new HashMap<>(); + params.clear(); + params.put("param1", "42"); + params.put("param2", "24"); + + String result = + given() + .when() + .config(restConfig) + .cookie("JSESSIONID", cookie) + .header("webgoat-requested-by","dom-xss-vuln") + .header("X-Requested-With", "XMLHttpRequest") + .formParams(params) + .post(webgoatURL+"/WebGoat/CrossSiteScripting/phone-home-xss") + .then() + //.log().all() + .statusCode(200) + .extract().path("output"); + String secretNumber = result.substring("phoneHome Response is ".length()); + + params.clear(); + params.put("successMessage", secretNumber); + checkAssignment(cookie, webgoatURL+"/WebGoat/ChromeDevTools/dummy", params, true); + + params.clear(); + params.put("number", "24"); + params.put("network_num", "24"); + checkAssignment(cookie, webgoatURL+"/WebGoat/ChromeDevTools/network", params, true); + + checkResults(cookie, webgoatURL, "/ChromeDevTools/"); + + } + + +} diff --git a/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionAdvanced_TestHelper.java b/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionAdvanced_TestHelper.java new file mode 100644 index 000000000..13673a352 --- /dev/null +++ b/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionAdvanced_TestHelper.java @@ -0,0 +1,36 @@ +package org.owasp.webgoat; + +import java.util.HashMap; +import java.util.Map; + +public class SqlInjectionAdvanced_TestHelper extends TestHelper { + + public void runTests(String webgoatURL, String cookie) { + + startLesson(cookie, webgoatURL, "SqlInjectionAdvanced"); + + Map params = new HashMap<>(); + params.clear(); + params.put("userid_6a", "'; SELECT * FROM user_system_data;--"); + checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjectionAdvanced/attack6a", params, true); + + params.clear(); + params.put("userid_6a", "Smith' union select userid,user_name, user_name,user_name,password,cookie,userid from user_system_data --"); + checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjectionAdvanced/attack6a", params, true); + + params.clear(); + params.put("userid_6b", "passW0rD"); + checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjectionAdvanced/attack6b", params, true); + + params.clear(); + params.put("question_0_solution", "Solution 4: A statement has got values instead of a prepared statement"); + params.put("question_1_solution", "Solution 3: ?"); + params.put("question_2_solution", "Solution 2: Prepared statements are compiled once by the database management system waiting for input and are pre-compiled this way."); + params.put("question_3_solution", "Solution 3: Placeholders can prevent that the users input gets attached to the SQL query resulting in a seperation of code and data."); + params.put("question_4_solution", "Solution 4: The database registers 'Robert' ); DROP TABLE Students;--'."); + checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjectionAdvanced/quiz", params, true); + + //checkResults(cookie, webgoatURL, "/SqlInjectionAdvanced/"); + + } +} diff --git a/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionMitigation_TestHelper.java b/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionMitigation_TestHelper.java new file mode 100644 index 000000000..70389dee2 --- /dev/null +++ b/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionMitigation_TestHelper.java @@ -0,0 +1,37 @@ +package org.owasp.webgoat; + +import java.util.HashMap; +import java.util.Map; + +public class SqlInjectionMitigation_TestHelper extends TestHelper { + + public void runTests(String webgoatURL, String cookie) { + + startLesson(cookie, webgoatURL, "SqlInjectionMitigations"); + + Map params = new HashMap<>(); + params.clear(); + params.put("field1", "getConnection"); + params.put("field2", "PreparedStatement prep"); + params.put("field3", "prepareStatement"); + params.put("field4", "?"); + params.put("field5", "?"); + params.put("field6", "prep.setString(1,\"\")"); + params.put("field7", "prep.setString(2,\\\"\\\")"); + checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjectionMitigations/attack10a", params, true); + + params.put("editor", "try {\r\n" + + " Connection conn = DriverManager.getConnection(DBURL,DBUSER,DBPW);\r\n" + + " PreparedStatement prep = conn.prepareStatement(\"select id from users where name = ?\");\r\n" + + " prep.setString(1,\"me\");\r\n" + + " prep.execute();\r\n" + + " System.out.println(conn); //should output 'null'\r\n" + + "} catch (Exception e) {\r\n" + + " System.out.println(\"Oops. Something went wrong!\");\r\n" + + "}"); + checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjectionMitigations/attack10b", params, true); + + //checkResults(cookie, webgoatURL, "/SqlInjectionMitigations/"); + + } +} diff --git a/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjection_TestHelper.java b/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjection_TestHelper.java new file mode 100644 index 000000000..1f1db2ab4 --- /dev/null +++ b/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjection_TestHelper.java @@ -0,0 +1,80 @@ +package org.owasp.webgoat; + +import java.util.HashMap; +import java.util.Map; + +public class SqlInjection_TestHelper extends TestHelper { + + private static final String sql_2 = "select department from employees where last_name='Franco'"; + private static final String sql_3 = "update employees set department='Sales' where last_name='Barnett'"; + private static final String sql_4_drop = "alter table employees drop column phone"; + private static final String sql_4_add = "alter table employees add column phone varchar(20)"; + private static final String sql_5 = "grant alter table to UnauthorizedUser"; + private static final String sql_9_account = " ' "; + private static final String sql_9_operator = "or"; + private static final String sql_9_injection = "'1'='1"; + private static final String sql_10_login_count = "2"; + private static final String sql_10_userid = "1 or 1=1"; + + private static final String sql_11_a = "Smith' or '1' = '1"; + private static final String sql_11_b = "3SL99A' or '1'='1"; + + private static final String sql_12_a = "Smith"; + private static final String sql_12_b = "3SL99A' ; update employees set salary= '100000' where last_name='Smith"; + + private static final String sql_13 = "%update% '; drop table access_log ; --'"; + + public void runTests(String webgoatURL, String cookie) { + + startLesson(cookie, webgoatURL, "SqlInjection"); + + Map params = new HashMap<>(); + params.clear(); + params.put("query", sql_2); + checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack2", params, true); + + params.clear(); + params.put("query", sql_3); + checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack3", params, true); + + params.clear(); + params.put("query", sql_4_drop); + checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack4", params, false); + + params.clear(); + params.put("query", sql_4_add); + checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack4", params, true); + + params.clear(); + params.put("query", sql_5); + checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack5", params, true); + + params.clear(); + params.put("operator", sql_9_operator); + params.put("account", sql_9_account); + params.put("injection", sql_9_injection); + checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/assignment5a", params, true); + + params.clear(); + params.put("login_count", sql_10_login_count); + params.put("userid", sql_10_userid); + checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/assignment5b", params, true); + + params.clear(); + params.put("name", sql_11_a); + params.put("auth_tan", sql_11_b); + checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack8", params, true); + + params.clear(); + params.put("name", sql_12_a); + params.put("auth_tan", sql_12_b); + checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack9", params, true); + + params.clear(); + params.put("action_string", sql_13); + checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack10", params, true); + + checkResults(cookie, webgoatURL, "/SqlInjection/"); + + } +} diff --git a/webgoat-server/src/test/java/org/owasp/webgoat/TestHelper.java b/webgoat-server/src/test/java/org/owasp/webgoat/TestHelper.java new file mode 100644 index 000000000..dfad6d538 --- /dev/null +++ b/webgoat-server/src/test/java/org/owasp/webgoat/TestHelper.java @@ -0,0 +1,95 @@ +package org.owasp.webgoat; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.CoreMatchers.everyItem; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.startsWith; + +import static org.junit.Assert.assertThat; + +import java.util.Map; + +import io.restassured.config.RestAssuredConfig; +import io.restassured.config.SSLConfig; + +public class TestHelper { + + //This also allows to test the application with HTTPS when outside testing option is used + protected RestAssuredConfig restConfig = RestAssuredConfig.newConfig().sslConfig(new SSLConfig().relaxedHTTPSValidation()); + + /** + * At start of a lesson. The .lesson.lesson is visited and the lesson is reset. + * @param cookie + * @param url + * @param lessonName + */ + public void startLesson(String cookie, String url, String lessonName) { + given() + .when() + .config(restConfig) + .cookie("JSESSIONID", cookie) + .get(url+"/WebGoat/"+lessonName+".lesson.lesson") + .then() + .statusCode(200); + + given() + .when() + .config(restConfig) + .cookie("JSESSIONID", cookie) + .get(url+"/WebGoat/service/restartlesson.mvc") + .then() + .statusCode(200); + } + + /** + * Helper method for most common type of test. + * POST with parameters. + * Checks for 200 and lessonCompleted as indicated by expectedResult + * @param webgoatCookie + * @param url + * @param params + * @param expectedResult + */ + public void checkAssignment(String webgoatCookie, String url, Map params, boolean expectedResult) { + assertThat( + given() + .when() + .config(restConfig) + .cookie("JSESSIONID", webgoatCookie) + .formParams(params) + .post(url) + .then() + //.log().all() + .statusCode(200) + .extract().path("lessonCompleted"), is(expectedResult)); + } + + /** + * Helper method at the end of a lesson. + * Check if all path paramters are correct for the progress. + * Check if all are solved. + * @param webgoatCookie + * @param webgoatURL + * @param prefix + */ + public void checkResults(String webgoatCookie, String webgoatURL, String prefix) { + assertThat(given() + .when() + .config(restConfig) + .cookie("JSESSIONID", webgoatCookie) + .get(webgoatURL+"/WebGoat/service/lessonoverview.mvc") + .then() + //.log().all() + .statusCode(200).extract().jsonPath().getList("solved"),everyItem(is(true))); + + assertThat(given() + .when() + .config(restConfig) + .cookie("JSESSIONID", webgoatCookie) + .get(webgoatURL+"/WebGoat/service/lessonoverview.mvc") + .then() + //.log().all() + .statusCode(200).extract().jsonPath().getList("assignment.path"),everyItem(startsWith(prefix))); + + } +} diff --git a/webgoat-server/src/test/java/org/owasp/webgoat/WebGoatIntegrationTest.java b/webgoat-server/src/test/java/org/owasp/webgoat/WebGoatIntegrationTest.java new file mode 100644 index 000000000..12967099e --- /dev/null +++ b/webgoat-server/src/test/java/org/owasp/webgoat/WebGoatIntegrationTest.java @@ -0,0 +1,162 @@ +package org.owasp.webgoat; + +import static io.restassured.RestAssured.given; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.context.embedded.LocalServerPort; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes=WebGoat.class, webEnvironment = WebEnvironment.RANDOM_PORT) +@EnableAutoConfiguration +public class WebGoatIntegrationTest extends TestHelper { + + /* + * Unique port for http server. Database port is not yet overruled. But this is + * not a problem for the integration test. + */ + @LocalServerPort + int randomServerPort; + + private General_TestHelper generalTestHelper = new General_TestHelper(); + private SqlInjection_TestHelper sqlInjectionHelper = new SqlInjection_TestHelper(); + private SqlInjectionAdvanced_TestHelper sqlInjectionAdvancedHelper = new SqlInjectionAdvanced_TestHelper(); + private SqlInjectionMitigation_TestHelper sqlInjectionMitigationHelper = new SqlInjectionMitigation_TestHelper(); + + String webgoatURL = System.getProperty("WEBGOAT_URL",""); + String webgoatUser = System.getProperty("WEBGOAT_USER",""); + String webgoatPassword = System.getProperty("WEBGOAT_PASSWORD","password"); + String cookie = ""; + + @Before + public void init() { + + /* + * If no system properties are set, the test runs against the random port + * of the webgoat application that starts with this test. + * If set you can use it to test an oustide running application. If testing + * against outside running applications, the tests that require WebWolf can be tested as well. + */ + //TODO add support for testing the lessons that require WebWolf as well. + if (webgoatURL.equals("")) { + webgoatURL = "http://127.0.0.1:"+randomServerPort; + } + + /* + * If not defined a random user will be registered and used in the test. + * If you run against an outside application and want to visually see the results, + * you can set a username. + */ + if (webgoatUser.equals("")) { + webgoatUser = "tester"+Math.round(Math.random()*1000); + } + + //check if user exists + String location = given() + .when() + .config(restConfig) + .formParam("username", webgoatUser) + .formParam("password", "password") + .post(webgoatURL+"/WebGoat/login") + .then() + //.log().all() + .cookie("JSESSIONID") + .statusCode(302) + .extract().header("Location"); + + //register when not existing, otherwise log in and save the cookie + if (location.endsWith("error")) { + + cookie = given() + .when() + .config(restConfig) + .formParam("username", webgoatUser) + .formParam("password", "password") + .formParam("matchingPassword", "password") + .formParam("agree", "agree") + .post(webgoatURL+"/WebGoat/register.mvc") + .then() + .cookie("JSESSIONID") + .statusCode(302) + .extract() + .cookie("JSESSIONID"); + + } else { + + cookie = given() + .when() + .config(restConfig) + .formParam("username", webgoatUser) + .formParam("password", "password") + .post(webgoatURL+"/WebGoat/login") + .then() + //.log().all() + .cookie("JSESSIONID") + .statusCode(302) + .extract().cookie("JSESSIONID"); + } + } + + @Test + public void testGeneral_HttpBasics() { + + generalTestHelper.httpBasics(webgoatURL, cookie); + + } + + @Test + public void testGeneral_HttpProxies() { + + generalTestHelper.httpProxies(webgoatURL, cookie); + + } + + @Test + public void testGeneral_CIA() { + + generalTestHelper.cia(webgoatURL, cookie); + + } + + @Test + public void testGeneral_Chrome() { + + generalTestHelper.chrome(webgoatURL, cookie); + + } + + @Test + public void testSecurePassords() { + + generalTestHelper.securePasswords(webgoatURL, cookie); + + } + + @Test + public void testSQLInjection() { + + sqlInjectionHelper.runTests(webgoatURL, cookie); + + } + + @Test + public void testSQLInjectionAdvanced() { + + sqlInjectionAdvancedHelper.runTests(webgoatURL, cookie); + + } + + @Test + public void testSQLInjectionMitigation() { + + sqlInjectionMitigationHelper.runTests(webgoatURL, cookie); + + } + + +} From d2e23f6b8e9b30d794152e2e66ae21bde644d08f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Zubcevic?= Date: Thu, 25 Jul 2019 10:59:37 +0200 Subject: [PATCH 032/119] reduce logging --- .../java/org/owasp/webgoat/General_TestHelper.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/webgoat-server/src/test/java/org/owasp/webgoat/General_TestHelper.java b/webgoat-server/src/test/java/org/owasp/webgoat/General_TestHelper.java index adce19bb5..694084f50 100644 --- a/webgoat-server/src/test/java/org/owasp/webgoat/General_TestHelper.java +++ b/webgoat-server/src/test/java/org/owasp/webgoat/General_TestHelper.java @@ -42,9 +42,11 @@ public class General_TestHelper extends TestHelper { startLesson(cookie, webgoatURL, "HttpProxies"); assertThat(given() .when().config(restConfig).cookie("JSESSIONID", cookie).header("x-request-intercepted", "true") - .contentType(ContentType.JSON).log().all() + .contentType(ContentType.JSON) + //.log().all() .get(webgoatURL + "/WebGoat/HttpProxies/intercept-request?changeMe=Requests are tampered easily").then() - .log().all().statusCode(200).extract().path("lessonCompleted"), is(true)); + //.log().all() + .statusCode(200).extract().path("lessonCompleted"), is(true)); checkResults(cookie, webgoatURL, "/HttpProxies/"); @@ -85,9 +87,11 @@ public class General_TestHelper extends TestHelper { startLesson(cookie, webgoatURL, "HttpProxies"); assertThat(given().when().config(restConfig).cookie("JSESSIONID", cookie).header("x-request-intercepted", "true") - .contentType(ContentType.JSON).log().all() + .contentType(ContentType.JSON) + //.log().all() .get(webgoatURL + "/WebGoat/HttpProxies/intercept-request?changeMe=Requests are tampered easily").then() - .log().all().statusCode(200).extract().path("lessonCompleted"), is(true)); + //.log().all() + .statusCode(200).extract().path("lessonCompleted"), is(true)); checkResults(cookie, webgoatURL, "/HttpProxies/"); } From e61c943f9769a7f899b6a296a2ef878f1bc114d5 Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Sun, 28 Jul 2019 20:48:20 +0200 Subject: [PATCH 033/119] #601 bug: username is case sensitive, but email in general is not Opted for completing remove support for uppercase letters in username this way we never come across issued with casing in WebGoat --- .../src/main/java/org/owasp/webgoat/users/UserForm.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/users/UserForm.java b/webgoat-container/src/main/java/org/owasp/webgoat/users/UserForm.java index e2062cbdd..1e0c44000 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/users/UserForm.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/users/UserForm.java @@ -17,7 +17,7 @@ public class UserForm { @NotNull @Size(min=6, max=20) - @Pattern(regexp = "[a-zA-Z0-9-]*", message = "can only contain letters, digits, and -") + @Pattern(regexp = "[a-z0-9-]*", message = "can only contain lowercase letters, digits, and -") private String username; @NotNull @Size(min=6, max=10) From 18eee4df587453862bf35e967ea5bbf6cb9768b7 Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Sun, 28 Jul 2019 20:50:19 +0200 Subject: [PATCH 034/119] Fix for issue with timestamp not being parsed when sending to WebWolf timestamp was already fixed at LocalDateTime.now() however WebGoat still send the timestamp along, removed it --- .../src/main/java/org/owasp/webgoat/plugin/Email.java | 1 - .../src/main/java/org/owasp/webgoat/plugin/MailAssignment.java | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/webgoat-lessons/webwolf-introduction/src/main/java/org/owasp/webgoat/plugin/Email.java b/webgoat-lessons/webwolf-introduction/src/main/java/org/owasp/webgoat/plugin/Email.java index 08b242598..d7c228a8a 100644 --- a/webgoat-lessons/webwolf-introduction/src/main/java/org/owasp/webgoat/plugin/Email.java +++ b/webgoat-lessons/webwolf-introduction/src/main/java/org/owasp/webgoat/plugin/Email.java @@ -10,7 +10,6 @@ import java.time.LocalDateTime; @Data public class Email implements Serializable { - private LocalDateTime time; private String contents; private String sender; private String title; diff --git a/webgoat-lessons/webwolf-introduction/src/main/java/org/owasp/webgoat/plugin/MailAssignment.java b/webgoat-lessons/webwolf-introduction/src/main/java/org/owasp/webgoat/plugin/MailAssignment.java index c10321e74..11615554d 100644 --- a/webgoat-lessons/webwolf-introduction/src/main/java/org/owasp/webgoat/plugin/MailAssignment.java +++ b/webgoat-lessons/webwolf-introduction/src/main/java/org/owasp/webgoat/plugin/MailAssignment.java @@ -32,11 +32,10 @@ public class MailAssignment extends AssignmentEndpoint { @ResponseBody public AttackResult sendEmail(@RequestParam String email) { String username = email.substring(0, email.indexOf("@")); - if (username.equals(getWebSession().getUserName())) { + if (username.equalsIgnoreCase(getWebSession().getUserName())) { Email mailEvent = Email.builder() .recipient(username) .title("Test messages from WebWolf") - .time(LocalDateTime.now()) .contents("This is a test message from WebWolf, your unique code is: " + StringUtils.reverse(username)) .sender("webgoat@owasp.org") .build(); From 7d9f24c86b61dba206b9d29b62bc0d9932f079db Mon Sep 17 00:00:00 2001 From: Jacob Skiba Date: Tue, 6 Aug 2019 05:26:05 -0400 Subject: [PATCH 035/119] Update CrossSiteScripting_content9.adoc Fix broken resource link --- .../resources/lessonPlans/en/CrossSiteScripting_content9.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webgoat-lessons/cross-site-scripting/src/main/resources/lessonPlans/en/CrossSiteScripting_content9.adoc b/webgoat-lessons/cross-site-scripting/src/main/resources/lessonPlans/en/CrossSiteScripting_content9.adoc index a833e819f..7489c72e1 100644 --- a/webgoat-lessons/cross-site-scripting/src/main/resources/lessonPlans/en/CrossSiteScripting_content9.adoc +++ b/webgoat-lessons/cross-site-scripting/src/main/resources/lessonPlans/en/CrossSiteScripting_content9.adoc @@ -39,8 +39,8 @@ _$selector.*text*(someEncodeHtmlMethod(userInputHere))_ http://underscorejs.org/#template -https://nvisium.com/blog/2015/05/21/dont-break-your-backbone-xss-mitigation/ +https://nvisium.com/blog/2015/05/21/dont-break-your-backbone-xss-mitigation.html ==== Angular Angular has sought to escape by default, but the expression language has proven to have 'sandbox' escapes. Best to check -details of the version you are using and consult starting here: https://docs.angularjs.org/guide/security \ No newline at end of file +details of the version you are using and consult starting here: https://docs.angularjs.org/guide/security From e01c2a35ce8de209ac2628ae5b8472954614fe26 Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Tue, 6 Aug 2019 19:03:40 +0200 Subject: [PATCH 036/119] Add test case for security question assignment and the tracking is now done with a session scoped bean --- .../plugin/SecurityQuestionAssignment.java | 70 +++++++++------- .../owasp/webgoat/plugin/TriedQuestions.java | 22 +++++ .../resources/i18n/WebGoatLabels.properties | 1 + .../SecurityQuestionAssignmentTest.java | 82 +++++++++++++++++++ 4 files changed, 145 insertions(+), 30 deletions(-) create mode 100644 webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/plugin/TriedQuestions.java create mode 100644 webgoat-lessons/password-reset/src/main/test/java/org/owasp/webgoat/plugin/SecurityQuestionAssignmentTest.java diff --git a/webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/plugin/SecurityQuestionAssignment.java b/webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/plugin/SecurityQuestionAssignment.java index cc823f45a..0210f8dee 100644 --- a/webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/plugin/SecurityQuestionAssignment.java +++ b/webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/plugin/SecurityQuestionAssignment.java @@ -3,6 +3,7 @@ package org.owasp.webgoat.plugin; import org.owasp.webgoat.assignments.AssignmentEndpoint; import org.owasp.webgoat.assignments.AssignmentPath; import org.owasp.webgoat.assignments.AttackResult; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; @@ -11,44 +12,53 @@ import org.springframework.web.bind.annotation.ResponseBody; import java.util.HashMap; import java.util.Map; +import static java.util.Optional.of; + /** * Assignment for picking a good security question. + * * @author Tobias Melzer * @since 11.12.18 */ @AssignmentPath("/PasswordReset/SecurityQuestions") public class SecurityQuestionAssignment extends AssignmentEndpoint { - private static int triedQuestions = 0; + @Autowired + private TriedQuestions triedQuestions; - private static Map questions; + private static Map questions; - static { - questions = new HashMap<>(); - questions.put("What is your favorite animal?", "The answer can easily be guessed and figured out through social media."); - questions.put("In what year was your mother born?", "Can be easily guessed."); - questions.put("What was the time you were born?", "This may first seem like a good question, but you most likely dont know the exact time, so it might be hard to remember."); - questions.put("What is the name of the person you first kissed?", "Can be figured out through social media, or even guessed by trying the most common names."); - questions.put("What was the house number and street name you lived in as a child?", "Answer can be figured out through social media, or worse it might be your current address."); - questions.put("In what town or city was your first full time job?", "In times of LinkedIn and Facebook, the answer can be figured out quite easily."); - questions.put("In what city were you born?", "Easy to figure out through social media."); - questions.put("What was the last name of your favorite teacher in grade three?", "Most people would probably not know the answer to that."); - questions.put("What is the name of a college/job you applied to but didn't attend?", "It might not be easy to remember and an hacker could just try some company's/colleges in your area."); - questions.put("What are the last 5 digits of your drivers license?", "Is subject to change, and the last digit of your driver license might follow a specific pattern. (For example your birthday)."); - questions.put("What was your childhood nickname?", "Not all people had a nickname."); - questions.put("Who was your childhood hero?", "Most Heroes we had as a child where quite obvious ones, like Superman for example."); - questions.put("On which wrist do you were your watch?", "There are only to possible real answers, so really easy to guess."); - questions.put("What is your favorite color?", "Can easily be guessed."); - } - @RequestMapping(method = RequestMethod.POST) - public - @ResponseBody - AttackResult completed(@RequestParam String question) { - triedQuestions+=1; - String answer = questions.get(question); - answer = "" + answer + ""; - if(triedQuestions > 1) - return trackProgress(success().output(answer).build()); - return failed().output(answer).build(); - } + static { + questions = new HashMap<>(); + questions.put("What is your favorite animal?", "The answer can easily be guessed and figured out through social media."); + questions.put("In what year was your mother born?", "Can be easily guessed."); + questions.put("What was the time you were born?", "This may first seem like a good question, but you most likely dont know the exact time, so it might be hard to remember."); + questions.put("What is the name of the person you first kissed?", "Can be figured out through social media, or even guessed by trying the most common names."); + questions.put("What was the house number and street name you lived in as a child?", "Answer can be figured out through social media, or worse it might be your current address."); + questions.put("In what town or city was your first full time job?", "In times of LinkedIn and Facebook, the answer can be figured out quite easily."); + questions.put("In what city were you born?", "Easy to figure out through social media."); + questions.put("What was the last name of your favorite teacher in grade three?", "Most people would probably not know the answer to that."); + questions.put("What is the name of a college/job you applied to but didn't attend?", "It might not be easy to remember and an hacker could just try some company's/colleges in your area."); + questions.put("What are the last 5 digits of your drivers license?", "Is subject to change, and the last digit of your driver license might follow a specific pattern. (For example your birthday)."); + questions.put("What was your childhood nickname?", "Not all people had a nickname."); + questions.put("Who was your childhood hero?", "Most Heroes we had as a child where quite obvious ones, like Superman for example."); + questions.put("On which wrist do you were your watch?", "There are only to possible real answers, so really easy to guess."); + questions.put("What is your favorite color?", "Can easily be guessed."); + } + + @RequestMapping(method = RequestMethod.POST) + @ResponseBody + public AttackResult completed(@RequestParam String question) { + var answer = of(questions.get(question)); + if (answer.isPresent()) { + triedQuestions.incr(question); + if (triedQuestions.isComplete()) { + return trackProgress(success().output("" + answer + "").build()); + } + } + return informationMessage() + .feedback("password-questions-one-successful") + .output(answer.orElse("Unknown question, please try again...")) + .build(); + } } diff --git a/webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/plugin/TriedQuestions.java b/webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/plugin/TriedQuestions.java new file mode 100644 index 000000000..92bcd38c8 --- /dev/null +++ b/webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/plugin/TriedQuestions.java @@ -0,0 +1,22 @@ +package org.owasp.webgoat.plugin; + +import com.google.common.collect.Sets; +import org.springframework.stereotype.Component; +import org.springframework.web.context.annotation.SessionScope; + +import java.util.Set; + +@Component +@SessionScope +public class TriedQuestions { + + private Set answeredQuestions = Sets.newHashSet(); + + public void incr(String question) { + answeredQuestions.add(question); + } + + public boolean isComplete() { + return answeredQuestions.size() > 1; + } +} diff --git a/webgoat-lessons/password-reset/src/main/resources/i18n/WebGoatLabels.properties b/webgoat-lessons/password-reset/src/main/resources/i18n/WebGoatLabels.properties index be4edc2b1..283ab18b4 100644 --- a/webgoat-lessons/password-reset/src/main/resources/i18n/WebGoatLabels.properties +++ b/webgoat-lessons/password-reset/src/main/resources/i18n/WebGoatLabels.properties @@ -7,6 +7,7 @@ password-reset-simple.email_mismatch=Of course you can send mail to user {0} how password-questions-wrong-user=You need to find a different user you are logging in with 'webgoat'. password-questions-unknown-user=User {0} is not a valid user. +password-questions-one-successful=You answered one question successfully please try another one. password-reset-no-user=Please supply a valid e-mail address. password-reset-solved=Congratulations you solved the assignment, please type in the following code in the e-mail field: {0} diff --git a/webgoat-lessons/password-reset/src/main/test/java/org/owasp/webgoat/plugin/SecurityQuestionAssignmentTest.java b/webgoat-lessons/password-reset/src/main/test/java/org/owasp/webgoat/plugin/SecurityQuestionAssignmentTest.java new file mode 100644 index 000000000..2ce1b1711 --- /dev/null +++ b/webgoat-lessons/password-reset/src/main/test/java/org/owasp/webgoat/plugin/SecurityQuestionAssignmentTest.java @@ -0,0 +1,82 @@ +package org.owasp.webgoat.plugin; + +import org.hamcrest.CoreMatchers; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.owasp.webgoat.plugins.LessonTest; +import org.springframework.mock.web.MockHttpSession; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringJUnit4ClassRunner.class) +public class SecurityQuestionAssignmentTest extends LessonTest { + + @Before + public void setup() { + PasswordReset assignment = new PasswordReset(); + Mockito.when(webSession.getCurrentLesson()).thenReturn(assignment); + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + Mockito.when(webSession.getUserName()).thenReturn("unit-test"); + } + + @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))); + } +} \ No newline at end of file From 6d36e7db744d8342e5f29fc33b07019e7b008420 Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Sat, 17 Aug 2019 13:52:59 +0200 Subject: [PATCH 037/119] Added new endpoint for POST so it will give feedback to the UI. It now ended up in a HTTP/405 which does not give any feedback to the UI --- .../plugin/HttpBasicsInterceptRequest.java | 55 ++++++++++--------- .../HttpBasicsInterceptRequestTest.java | 28 ++++++++++ 2 files changed, 57 insertions(+), 26 deletions(-) diff --git a/webgoat-lessons/http-proxies/src/main/java/org/owasp/webgoat/plugin/HttpBasicsInterceptRequest.java b/webgoat-lessons/http-proxies/src/main/java/org/owasp/webgoat/plugin/HttpBasicsInterceptRequest.java index 3c7d42f44..78100bc59 100644 --- a/webgoat-lessons/http-proxies/src/main/java/org/owasp/webgoat/plugin/HttpBasicsInterceptRequest.java +++ b/webgoat-lessons/http-proxies/src/main/java/org/owasp/webgoat/plugin/HttpBasicsInterceptRequest.java @@ -3,41 +3,37 @@ package org.owasp.webgoat.plugin; import org.owasp.webgoat.assignments.AssignmentEndpoint; import org.owasp.webgoat.assignments.AssignmentPath; import org.owasp.webgoat.assignments.AttackResult; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.ResponseBody; - -import javax.servlet.http.HttpServletRequest; -import java.io.IOException; +import org.springframework.web.bind.MissingServletRequestParameterException; +import org.springframework.web.bind.annotation.*; /** * ************************************************************************************************* - * - * + *

+ *

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

* Copyright (c) 2002 - 20014 Bruce Mayhew - * + *

* This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) any later * version. - * + *

* This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. - * + *

* You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place - Suite 330, Boston, MA 02111-1307, USA. - * + *

* Getting Source ============== - * + *

* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository * for free software projects. - * + *

* For details, please see http://webgoat.github.io * * @author Bruce Mayhew WebGoat @@ -46,18 +42,25 @@ import java.io.IOException; @AssignmentPath("/HttpProxies/intercept-request") public class HttpBasicsInterceptRequest extends AssignmentEndpoint { - @RequestMapping(method = RequestMethod.GET) - public @ResponseBody - AttackResult completed(HttpServletRequest request) { - String header = null; - String param = null; - if (request != null && (header = request.getHeader("x-request-intercepted")) != null - && header.toLowerCase().equals("true") - && (param = request.getParameter("changeMe")) != null - && param.equals("Requests are tampered easily")) { + @GetMapping + @ResponseBody + public AttackResult completed(@RequestHeader(value = "x-request-intercepted", required = false) Boolean headerValue, + @RequestParam(value = "changeMe", required = false) String paramValue) { + if (headerValue != null && paramValue != null && headerValue && "Requests are tampered easily".equalsIgnoreCase(paramValue)) { return trackProgress(success().feedback("http-proxies.intercept.success").build()); - } else { + } else { return trackProgress(failed().feedback("http-proxies.intercept.failure").build()); } - } + } + + @PostMapping + @ResponseBody + public AttackResult post() { + return trackProgress(failed().feedback("http-proxies.intercept.failure").build()); + } + + @ExceptionHandler(MissingServletRequestParameterException.class) + public AttackResult handleMissingParams() { + return trackProgress(failed().feedback("http-proxies.intercept.failure").build()); + } } diff --git a/webgoat-lessons/http-proxies/src/test/java/org/owasp/webgoat/plugin/HttpBasicsInterceptRequestTest.java b/webgoat-lessons/http-proxies/src/test/java/org/owasp/webgoat/plugin/HttpBasicsInterceptRequestTest.java index 3de39b512..c6e8cc294 100644 --- a/webgoat-lessons/http-proxies/src/test/java/org/owasp/webgoat/plugin/HttpBasicsInterceptRequestTest.java +++ b/webgoat-lessons/http-proxies/src/test/java/org/owasp/webgoat/plugin/HttpBasicsInterceptRequestTest.java @@ -69,4 +69,32 @@ public class HttpBasicsInterceptRequestTest extends AssignmentEndpointTest { .andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.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(messages.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(messages.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(messages.getMessage("http-proxies.intercept.failure")))) + .andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(false))); + } } \ No newline at end of file From f0d1555a09028a15ce827bfd89ab7018703ae82c Mon Sep 17 00:00:00 2001 From: TortugaAttack Date: Wed, 21 Aug 2019 23:38:27 +0200 Subject: [PATCH 038/119] Fixed #45 - multiple tracker for one user fixed --- .../org/owasp/webgoat/users/UserService.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/users/UserService.java b/webgoat-container/src/main/java/org/owasp/webgoat/users/UserService.java index 932dc6e98..4a203fb68 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/users/UserService.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/users/UserService.java @@ -30,13 +30,25 @@ public class UserService implements UserDetailsService { } public void addUser(String username, String password) { + //get user if there exists one by the name + WebGoatUser webGoatUser = userRepository.findByUsername(username); + //if user exists it will be updated, otherwise created userRepository.save(new WebGoatUser(username, password)); - userTrackerRepository.save(new UserTracker(username)); + //if user previously existed it will not get another tracker + if (webGoatUser == null) { + userTrackerRepository.save(new UserTracker(username)); + } } public void addUser(String username, String password, String role) { + //get user if there exists one by the name + WebGoatUser webGoatUser = userRepository.findByUsername(username); + //if user exists it will be updated, otherwise created userRepository.save(new WebGoatUser(username,password,role)); - userTrackerRepository.save(new UserTracker(username)); + //if user previously existed it will not get another tracker + if (webGoatUser == null) { + userTrackerRepository.save(new UserTracker(username)); + } } public List getAllUsers () { From 924a53c22ae1e0762e1bc6b19bb83682e486b15c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Zubcevic?= Date: Thu, 22 Aug 2019 13:48:48 +0200 Subject: [PATCH 039/119] fixed sql adv 5 progress and added prove in integration test --- .../advanced/SqlInjectionChallenge.java | 6 ++++- .../advanced/SqlInjectionChallengeLogin.java | 8 ++----- .../SqlInjectionAdvanced_TestHelper.java | 14 ++++++++++- .../java/org/owasp/webgoat/TestHelper.java | 23 +++++++++++++++++++ 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionChallenge.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionChallenge.java index 3f13d819f..88368f96c 100644 --- a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionChallenge.java +++ b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionChallenge.java @@ -51,7 +51,11 @@ public class SqlInjectionChallenge extends AssignmentEndpoint { ResultSet resultSet = statement.executeQuery(checkUserQuery); if (resultSet.next()) { - attackResult = failed().feedback("user.exists").feedbackArgs(username_reg).build(); + if (username_reg.contains("tom'")) { + attackResult = trackProgress(success().feedback("user.exists").build()); + } else { + attackResult = failed().feedback("user.exists").feedbackArgs(username_reg).build(); + } } else { PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO " + USERS_TABLE_NAME + " VALUES (?, ?, ?)"); preparedStatement.setString(1, username_reg); diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionChallengeLogin.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionChallengeLogin.java index 4ca99b883..29095667b 100644 --- a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionChallengeLogin.java +++ b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionChallengeLogin.java @@ -1,7 +1,5 @@ package org.owasp.webgoat.plugin.advanced; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.RandomStringUtils; import org.owasp.webgoat.assignments.AssignmentEndpoint; import org.owasp.webgoat.assignments.AssignmentHints; import org.owasp.webgoat.assignments.AssignmentPath; @@ -18,7 +16,6 @@ import java.sql.*; import static org.springframework.web.bind.annotation.RequestMethod.POST; @AssignmentPath("/SqlInjectionAdvanced/challenge_Login") -@Slf4j @AssignmentHints(value ={"SqlInjectionChallengeHint1", "SqlInjectionChallengeHint2", "SqlInjectionChallengeHint3", "SqlInjectionChallengeHint4"}) public class SqlInjectionChallengeLogin extends AssignmentEndpoint { @@ -29,7 +26,6 @@ public class SqlInjectionChallengeLogin extends AssignmentEndpoint { @RequestMapping(method = POST) @ResponseBody public AttackResult login(@RequestParam String username_login, @RequestParam String password_login) throws Exception { - System.out.println("right Method"); Connection connection = DatabaseUtilities.getConnection(webSession); SqlInjectionChallenge.checkDatabase(connection); @@ -39,8 +35,8 @@ public class SqlInjectionChallengeLogin extends AssignmentEndpoint { ResultSet resultSet = statement.executeQuery(); if (resultSet.next()) { - return ("tom".equals(username_login)) ? success().build() - : success().feedback("ResultsButNotTom").build(); + return ("tom".equals(username_login)) ? trackProgress(success().build()) + : success().feedback("ResultsButNotTom").build(); } else { return failed().feedback("NoResultsMatched").build(); } diff --git a/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionAdvanced_TestHelper.java b/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionAdvanced_TestHelper.java index 13673a352..7328475f2 100644 --- a/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionAdvanced_TestHelper.java +++ b/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionAdvanced_TestHelper.java @@ -10,6 +10,18 @@ public class SqlInjectionAdvanced_TestHelper extends TestHelper { startLesson(cookie, webgoatURL, "SqlInjectionAdvanced"); Map params = new HashMap<>(); + params.clear(); + params.put("username_reg", "tom' AND substring(password,1,1)='t"); + params.put("password_reg", "password"); + params.put("email_reg", "someone@microsoft.com"); + params.put("confirm_password", "password"); + checkAssignmentWithPUT(cookie, webgoatURL+"/WebGoat/SqlInjectionAdvanced/challenge", params, true); + + params.clear(); + params.put("username_login", "tom"); + params.put("password_login", "thisisasecretfortomonly"); + checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjectionAdvanced/challenge_Login", params, true); + params.clear(); params.put("userid_6a", "'; SELECT * FROM user_system_data;--"); checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjectionAdvanced/attack6a", params, true); @@ -30,7 +42,7 @@ public class SqlInjectionAdvanced_TestHelper extends TestHelper { params.put("question_4_solution", "Solution 4: The database registers 'Robert' ); DROP TABLE Students;--'."); checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjectionAdvanced/quiz", params, true); - //checkResults(cookie, webgoatURL, "/SqlInjectionAdvanced/"); + checkResults(cookie, webgoatURL, "/SqlInjectionAdvanced/"); } } diff --git a/webgoat-server/src/test/java/org/owasp/webgoat/TestHelper.java b/webgoat-server/src/test/java/org/owasp/webgoat/TestHelper.java index dfad6d538..fd2b67141 100644 --- a/webgoat-server/src/test/java/org/owasp/webgoat/TestHelper.java +++ b/webgoat-server/src/test/java/org/owasp/webgoat/TestHelper.java @@ -64,6 +64,29 @@ public class TestHelper { .extract().path("lessonCompleted"), is(expectedResult)); } + /** + * Helper method for most common type of test. + * PUT with parameters. + * Checks for 200 and lessonCompleted as indicated by expectedResult + * @param webgoatCookie + * @param url + * @param params + * @param expectedResult + */ + public void checkAssignmentWithPUT(String webgoatCookie, String url, Map params, boolean expectedResult) { + assertThat( + given() + .when() + .config(restConfig) + .cookie("JSESSIONID", webgoatCookie) + .formParams(params) + .put(url) + .then() + //.log().all() + .statusCode(200) + .extract().path("lessonCompleted"), is(expectedResult)); + } + /** * Helper method at the end of a lesson. * Check if all path paramters are correct for the progress. From 139651615ed77f75ac50983503d4d64e255b0f3c Mon Sep 17 00:00:00 2001 From: Matthias Grundmann Date: Fri, 12 Jul 2019 16:49:57 +0200 Subject: [PATCH 040/119] Make lesson csrf-7 stricter (do not allow invalid JSON, e.g. trailing =) --- pom.xml | 1 + .../main/java/org/owasp/webgoat/plugin/CSRFFeedback.java | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/pom.xml b/pom.xml index e000e6e90..c82018731 100644 --- a/pom.xml +++ b/pom.xml @@ -126,6 +126,7 @@ 2.6 18.0 2.3.4 + 2.9.9 4.12 1.18.4 3.8.0 diff --git a/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/plugin/CSRFFeedback.java b/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/plugin/CSRFFeedback.java index 501da489b..c99dbee70 100644 --- a/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/plugin/CSRFFeedback.java +++ b/webgoat-lessons/csrf/src/main/java/org/owasp/webgoat/plugin/CSRFFeedback.java @@ -1,5 +1,6 @@ package org.owasp.webgoat.plugin; +import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; @@ -38,6 +39,12 @@ public class CSRFFeedback extends AssignmentEndpoint { @ResponseBody public AttackResult completed(HttpServletRequest request, @RequestBody String feedback) { try { + objectMapper.enable(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES); + objectMapper.enable(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES); + objectMapper.enable(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS); + objectMapper.enable(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY); + objectMapper.enable(DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES); + objectMapper.enable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS); objectMapper.readValue(feedback.getBytes(), Map.class); } catch (IOException e) { return failed().feedback(ExceptionUtils.getStackTrace(e)).build(); From ff530e926e5c81eb26c114bced9614bdd886c26d Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Sun, 25 Aug 2019 17:43:14 +0200 Subject: [PATCH 041/119] Use separate project for integration tests so we can start WebGoat and WebWolf --- pom.xml | 1 + .../main/java/org/owasp/webgoat/WebGoat.java | 20 +- .../owasp/webgoat/lessons/AbstractLesson.java | 2 +- .../org/owasp/webgoat/lessons/Category.java | 52 ++--- .../owasp/webgoat/lessons/LessonAdapter.java | 2 +- .../org/owasp/webgoat/users/UserForm.java | 2 +- ...perties => application-webgoat.properties} | 0 .../org/owasp/webgoat/plugins/LessonTest.java | 2 +- webgoat-integration-tests/pom.xml | 66 ++++++ .../org/owasp/webgoat/GeneralLessonTest.java | 127 +++++++++++ .../org/owasp/webgoat/IntegrationTest.java | 200 ++++++++++++++++++ .../webgoat/PasswordResetLessonTest.java | 76 +++++++ .../webgoat/SqlInjectionAdvancedTest.java | 49 +++++ .../owasp/webgoat/SqlInjectionLessonTest.java | 82 +++++++ .../webgoat/SqlInjectionMitigationTest.java | 76 +++---- .../src/test/resources/logback-test.xml | 15 ++ .../ResetLinkAssignmentForgotPassword.java | 99 +++++---- .../resources/i18n/WebGoatLabels.properties | 2 + webgoat-server/pom.xml | 27 ++- .../java/org/owasp/webgoat/StartWebGoat.java | 10 +- .../org/owasp/webgoat/General_TestHelper.java | 137 ------------ .../SqlInjectionAdvanced_TestHelper.java | 48 ----- .../webgoat/SqlInjection_TestHelper.java | 80 ------- .../java/org/owasp/webgoat/TestHelper.java | 118 ----------- .../owasp/webgoat/WebGoatIntegrationTest.java | 162 -------------- webwolf/pom.xml | 16 ++ .../main/java/org/owasp/webwolf/WebWolf.java | 15 +- .../java/org/owasp/webwolf/mailbox/Email.java | 1 + .../org/owasp/webwolf/requests/Requests.java | 2 +- .../requests/WebWolfTraceRepository.java | 21 +- .../java/org/owasp/webwolf/user/UserForm.java | 2 +- .../owasp/webwolf/user/WebGoatUserCookie.java | 22 -- ...perties => application-webwolf.properties} | 1 + 33 files changed, 793 insertions(+), 742 deletions(-) rename webgoat-container/src/main/resources/{application.properties => application-webgoat.properties} (100%) create mode 100644 webgoat-integration-tests/pom.xml create mode 100644 webgoat-integration-tests/src/test/java/org/owasp/webgoat/GeneralLessonTest.java create mode 100644 webgoat-integration-tests/src/test/java/org/owasp/webgoat/IntegrationTest.java create mode 100644 webgoat-integration-tests/src/test/java/org/owasp/webgoat/PasswordResetLessonTest.java create mode 100644 webgoat-integration-tests/src/test/java/org/owasp/webgoat/SqlInjectionAdvancedTest.java create mode 100644 webgoat-integration-tests/src/test/java/org/owasp/webgoat/SqlInjectionLessonTest.java rename webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionMitigation_TestHelper.java => webgoat-integration-tests/src/test/java/org/owasp/webgoat/SqlInjectionMitigationTest.java (65%) create mode 100644 webgoat-integration-tests/src/test/resources/logback-test.xml delete mode 100644 webgoat-server/src/test/java/org/owasp/webgoat/General_TestHelper.java delete mode 100644 webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionAdvanced_TestHelper.java delete mode 100644 webgoat-server/src/test/java/org/owasp/webgoat/SqlInjection_TestHelper.java delete mode 100644 webgoat-server/src/test/java/org/owasp/webgoat/TestHelper.java delete mode 100644 webgoat-server/src/test/java/org/owasp/webgoat/WebGoatIntegrationTest.java delete mode 100644 webwolf/src/main/java/org/owasp/webwolf/user/WebGoatUserCookie.java rename webwolf/src/main/resources/{application.properties => application-webwolf.properties} (98%) diff --git a/pom.xml b/pom.xml index c82018731..7036fabab 100644 --- a/pom.xml +++ b/pom.xml @@ -143,6 +143,7 @@ webgoat-lessons webgoat-server webwolf + webgoat-integration-tests diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java b/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java index e18374c23..131c482ab 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java @@ -30,7 +30,6 @@ */ package org.owasp.webgoat; -import lombok.extern.slf4j.Slf4j; import org.owasp.webgoat.plugins.PluginEndpointPublisher; import org.owasp.webgoat.plugins.PluginsLoader; import org.owasp.webgoat.session.Course; @@ -38,30 +37,17 @@ import org.owasp.webgoat.session.UserSessionData; import org.owasp.webgoat.session.WebSession; import org.owasp.webgoat.session.WebgoatContext; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.boot.web.support.SpringBootServletInitializer; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.ScopedProxyMode; import org.springframework.web.client.RestTemplate; import java.io.File; -@SpringBootApplication -@Slf4j -public class WebGoat extends SpringBootServletInitializer { - - @Override - protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { - return application.sources(WebGoat.class); - } - - public static void main(String[] args) throws Exception { - SpringApplication.run(WebGoat.class, args); - } +@Configuration +public class WebGoat { @Bean(name = "pluginTargetDirectory") public File pluginTargetDirectory(@Value("${webgoat.user.directory}") final String webgoatHome) { diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java index 1336fa326..16eca3f45 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java @@ -58,7 +58,7 @@ public abstract class AbstractLesson extends Screen implements ComparablegetDefaultRanking.

diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/users/UserForm.java b/webgoat-container/src/main/java/org/owasp/webgoat/users/UserForm.java index 1e0c44000..38d6b3947 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/users/UserForm.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/users/UserForm.java @@ -16,7 +16,7 @@ import javax.validation.constraints.Size; public class UserForm { @NotNull - @Size(min=6, max=20) + @Size(min=6, max=40) @Pattern(regexp = "[a-z0-9-]*", message = "can only contain lowercase letters, digits, and -") private String username; @NotNull diff --git a/webgoat-container/src/main/resources/application.properties b/webgoat-container/src/main/resources/application-webgoat.properties similarity index 100% rename from webgoat-container/src/main/resources/application.properties rename to webgoat-container/src/main/resources/application-webgoat.properties diff --git a/webgoat-container/src/test/java/org/owasp/webgoat/plugins/LessonTest.java b/webgoat-container/src/test/java/org/owasp/webgoat/plugins/LessonTest.java index 3e6dffe9e..cd59ab8d9 100644 --- a/webgoat-container/src/test/java/org/owasp/webgoat/plugins/LessonTest.java +++ b/webgoat-container/src/test/java/org/owasp/webgoat/plugins/LessonTest.java @@ -22,7 +22,7 @@ import static org.mockito.Mockito.when; * @since 5/20/17. */ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@TestPropertySource(locations = "classpath:/application-test.properties") +@TestPropertySource(locations = {"classpath:/application-webgoat.properties", "classpath:/application-test.properties"}) public abstract class LessonTest { @LocalServerPort diff --git a/webgoat-integration-tests/pom.xml b/webgoat-integration-tests/pom.xml new file mode 100644 index 000000000..de8e86b47 --- /dev/null +++ b/webgoat-integration-tests/pom.xml @@ -0,0 +1,66 @@ + + 4.0.0 + webgoat-integration-tests + jar + + org.owasp.webgoat + webgoat-parent + v8.0.0-SNAPSHOT + + + + + org.owasp.webgoat + webgoat-server + ${project.version} + + + org.owasp.webgoat + webgoat-server + ${project.version} + internal + + + org.owasp.webgoat + webwolf + ${project.version} + internal + + + org.owasp.webgoat + webwolf + ${project.version} + + + org.springframework.boot + spring-boot-starter-test + test + + + io.rest-assured + rest-assured + 4.0.0 + test + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + 0 + true + + --illegal-access=permit + + + + + + + diff --git a/webgoat-integration-tests/src/test/java/org/owasp/webgoat/GeneralLessonTest.java b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/GeneralLessonTest.java new file mode 100644 index 000000000..80dfbc496 --- /dev/null +++ b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/GeneralLessonTest.java @@ -0,0 +1,127 @@ +package org.owasp.webgoat; + +import io.restassured.RestAssured; +import io.restassured.http.ContentType; +import org.hamcrest.CoreMatchers; +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + + +public class GeneralLessonTest extends IntegrationTest { + + @Test + public void httpBasics() { + startLesson("HttpBasics"); + Map params = new HashMap<>(); + params.clear(); + params.put("person", "goatuser"); + checkAssignment(url("HttpBasics/attack1"), params, true); + + params.clear(); + params.put("answer", "POST"); + params.put("magic_answer", "33"); + params.put("magic_num", "4"); + checkAssignment(url("HttpBasics/attack2"), params, false); + + params.clear(); + params.put("answer", "POST"); + params.put("magic_answer", "33"); + params.put("magic_num", "33"); + checkAssignment(url("HttpBasics/attack2"), params, true); + + checkResults("/HttpBasics/"); + } + + @Test + public void httpProxies() { + startLesson("HttpProxies"); + Assert.assertThat(RestAssured.given() + .when().config(restConfig).cookie("JSESSIONID", getWebGoatCookie()).header("x-request-intercepted", "true") + .contentType(ContentType.JSON) + .get(url("HttpProxies/intercept-request?changeMe=Requests are tampered easily")) + .then() + .statusCode(200).extract().path("lessonCompleted"), CoreMatchers.is(true)); + + checkResults("/HttpProxies/"); + } + + @Test + public void cia() { + startLesson("CIA"); + Map params = new HashMap<>(); + params.clear(); + params.put("question_0_solution", "Solution 3: By stealing a database where names and emails are stored and uploading it to a website."); + params.put("question_1_solution", "Solution 1: By changing the names and emails of one or more users stored in a database."); + params.put("question_2_solution", "Solution 4: By launching a denial of service attack on the servers."); + params.put("question_3_solution", "Solution 2: The systems security is compromised even if only one goal is harmed."); + checkAssignment(url("/WebGoat/cia/quiz"), params, true); + checkResults("/cia/"); + + } + + @Test + public void securePasswords() { + startLesson("SecurePasswords"); + Map params = new HashMap<>(); + params.clear(); + params.put("password", "ajnaeliclm^&&@kjn."); + checkAssignment(url("/WebGoat/SecurePasswords/assignment"), params, true); + checkResults("SecurePasswords/"); + + startLesson("AuthBypass"); + params.clear(); + params.put("secQuestion2", "John"); + params.put("secQuestion3", "Main"); + params.put("jsEnabled", "1"); + params.put("verifyMethod", "SEC_QUESTIONS"); + params.put("userId", "12309746"); + checkAssignment(url("/WebGoat/auth-bypass/verify-account"), params, true); + checkResults("/auth-bypass/"); + + startLesson("HttpProxies"); + Assert.assertThat(RestAssured.given().when().config(restConfig).cookie("JSESSIONID", getWebGoatCookie()).header("x-request-intercepted", "true") + .contentType(ContentType.JSON) + .get(url("/WebGoat/HttpProxies/intercept-request?changeMe=Requests are tampered easily")).then() + .statusCode(200).extract().path("lessonCompleted"), CoreMatchers.is(true)); + checkResults("/HttpProxies/"); + + } + + @Test + public void chrome() { + startLesson("ChromeDevTools"); + + Map params = new HashMap<>(); + params.clear(); + params.put("param1", "42"); + params.put("param2", "24"); + + String result = + RestAssured.given() + .when() + .config(restConfig) + .cookie("JSESSIONID", getWebGoatCookie()) + .header("webgoat-requested-by", "dom-xss-vuln") + .header("X-Requested-With", "XMLHttpRequest") + .formParams(params) + .post(url("/WebGoat/CrossSiteScripting/phone-home-xss")) + .then() + .statusCode(200) + .extract().path("output"); + String secretNumber = result.substring("phoneHome Response is ".length()); + + params.clear(); + params.put("successMessage", secretNumber); + checkAssignment(url("/WebGoat/ChromeDevTools/dummy"), params, true); + + params.clear(); + params.put("number", "24"); + params.put("network_num", "24"); + checkAssignment(url("/WebGoat/ChromeDevTools/network"), params, true); + + checkResults("/ChromeDevTools/"); + } +} diff --git a/webgoat-integration-tests/src/test/java/org/owasp/webgoat/IntegrationTest.java b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/IntegrationTest.java new file mode 100644 index 000000000..f26dec4f3 --- /dev/null +++ b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/IntegrationTest.java @@ -0,0 +1,200 @@ +package org.owasp.webgoat; + +import io.restassured.RestAssured; +import io.restassured.config.RestAssuredConfig; +import io.restassured.config.SSLConfig; +import lombok.Getter; +import org.hamcrest.CoreMatchers; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.owasp.webwolf.WebWolf; +import org.springframework.boot.builder.SpringApplicationBuilder; + +import java.io.IOException; +import java.net.ServerSocket; +import java.util.Map; +import java.util.UUID; + +public abstract class IntegrationTest { + + private static String WEBGOAT_URL = "http://localhost:8080/WebGoat/"; + private static String WEBWOLF_URL = "http://localhost:9090/"; + + //This also allows to test the application with HTTPS when outside testing option is used + protected static RestAssuredConfig restConfig = RestAssuredConfig.newConfig().sslConfig(new SSLConfig().relaxedHTTPSValidation()); + + @Getter + private String webGoatCookie; + @Getter + private String webWolfCookie; + @Getter + private String webgoatUser = UUID.randomUUID().toString(); + + private static boolean started = false; + + @BeforeClass + public static void beforeAll() { + if (!started) { + started = true; + if (!areAlreadyRunning()) { + SpringApplicationBuilder wgs = new SpringApplicationBuilder(StartWebGoat.class) + .properties(Map.of("spring.config.name", "application-webgoat")); + wgs.run(); + SpringApplicationBuilder wws = new SpringApplicationBuilder(WebWolf.class) + .properties(Map.of("spring.config.name", "application-webwolf")); + wws.run(); + } + } + } + + private static boolean areAlreadyRunning() { + return checkIfServerIsRunnningOn(9090) && checkIfServerIsRunnningOn(8080); + } + + private static boolean checkIfServerIsRunnningOn(int port) { + try (var ignored = new ServerSocket(port)) { + return false; + } catch (IOException e) { + return true; + } + } + + protected String url(String url) { + url = url.replaceFirst("/WebGoat/", ""); + url = url.replaceFirst("/WebGoat", ""); + url = url.startsWith("/") ? url.replaceFirst("/", "") : url; + return WEBGOAT_URL + url; + } + + protected String webWolfUrl(String url) { + url = url.startsWith("/") ? url.replaceFirst("/", "") : url; + return WEBWOLF_URL + url; + } + + @Before + public void login() { + webGoatCookie = RestAssured.given() + .when() + .config(restConfig) + .formParam("username", webgoatUser) + .formParam("password", "password") + .formParam("matchingPassword", "password") + .formParam("agree", "agree") + .post(url("register.mvc")) + .then() + .cookie("JSESSIONID") + .statusCode(302) + .extract() + .cookie("JSESSIONID"); + + webWolfCookie = RestAssured.given() + .when() + .config(restConfig) + .formParam("username", webgoatUser) + .formParam("password", "password") + .post(WEBWOLF_URL + "login") + .then() + .cookie("WEBWOLFSESSION") + .statusCode(302) + .extract() + .cookie("WEBWOLFSESSION"); + } + + @After + public void logout() { + RestAssured.given() + .when() + .config(restConfig) + .get(WEBGOAT_URL + "logout") + .then() + .statusCode(200); + } + + /** + * At start of a lesson. The .lesson.lesson is visited and the lesson is reset. + * + * @param lessonName + */ + public void startLesson(String lessonName) { + RestAssured.given() + .when() + .config(restConfig) + .cookie("JSESSIONID", getWebGoatCookie()) + .get(url(lessonName + ".lesson.lesson")) + .then() + .statusCode(200); + + RestAssured.given() + .when() + .config(restConfig) + .cookie("JSESSIONID", getWebGoatCookie()) + .get(url("service/restartlesson.mvc")) + .then() + .statusCode(200); + } + + /** + * Helper method for most common type of test. + * POST with parameters. + * Checks for 200 and lessonCompleted as indicated by expectedResult + * + * @param url + * @param params + * @param expectedResult + */ + public void checkAssignment(String url, Map params, boolean expectedResult) { + Assert.assertThat( + RestAssured.given() + .when() + .config(restConfig) + .cookie("JSESSIONID", getWebGoatCookie()) + .formParams(params) + .post(url) + .then() + .statusCode(200) + .extract().path("lessonCompleted"), CoreMatchers.is(expectedResult)); + } + + /** + * Helper method for most common type of test. + * PUT with parameters. + * Checks for 200 and lessonCompleted as indicated by expectedResult + * + * @param url + * @param params + * @param expectedResult + */ + public void checkAssignmentWithPUT(String url, Map params, boolean expectedResult) { + Assert.assertThat( + RestAssured.given() + .when() + .config(restConfig) + .cookie("JSESSIONID", getWebGoatCookie()) + .formParams(params) + .put(url) + .then() + .statusCode(200) + .extract().path("lessonCompleted"), CoreMatchers.is(expectedResult)); + } + + public void checkResults(String prefix) { + Assert.assertThat(RestAssured.given() + .when() + .config(restConfig) + .cookie("JSESSIONID", getWebGoatCookie()) + .get(url("service/lessonoverview.mvc")) + .then() + .statusCode(200).extract().jsonPath().getList("solved"), CoreMatchers.everyItem(CoreMatchers.is(true))); + + Assert.assertThat(RestAssured.given() + .when() + .config(restConfig) + .cookie("JSESSIONID", getWebGoatCookie()) + .get(url("service/lessonoverview.mvc")) + .then() + .statusCode(200).extract().jsonPath().getList("assignment.path"), CoreMatchers.everyItem(CoreMatchers.startsWith(prefix))); + + } +} diff --git a/webgoat-integration-tests/src/test/java/org/owasp/webgoat/PasswordResetLessonTest.java b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/PasswordResetLessonTest.java new file mode 100644 index 000000000..ebe2b210a --- /dev/null +++ b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/PasswordResetLessonTest.java @@ -0,0 +1,76 @@ +package org.owasp.webgoat; + +import io.restassured.RestAssured; +import org.assertj.core.api.Assertions; +import org.junit.Test; + +import java.util.Map; + +public class PasswordResetLessonTest extends IntegrationTest { + + @Test + public void solveAssignment() { + //WebGoat + startLesson("PasswordReset"); + clickForgotEmailLink("tom@webgoat-cloud.org"); + + //WebWolf + var link = getPasswordResetLinkFromLandingPage(); + + //WebGoat + changePassword(link); + checkAssignment(url("PasswordReset/reset/login"), Map.of("email", "tom@webgoat-cloud.org", "password", "123456"), true); + } + + @Test + public void sendEmailShouldBeAvailabeInWebWolf() { + startLesson("PasswordReset"); + clickForgotEmailLink(getWebgoatUser() + "@webgoat.org"); + + var responseBody = RestAssured.given() + .when() + .config(restConfig) + .cookie("WEBWOLFSESSION", getWebWolfCookie()) + .get(webWolfUrl("/WebWolf/mail")) + .then() + .extract().response().getBody().asString(); + + Assertions.assertThat(responseBody).contains("Hi, you requested a password reset link"); + } + + private void changePassword(String link) { + RestAssured.given() + .when() + .config(restConfig) + .cookie("JSESSIONID", getWebGoatCookie()) + .formParams("resetLink", link, "password", "123456") + .post(url("PasswordReset/reset/change-password")) + .then() + .statusCode(200); + } + + private String getPasswordResetLinkFromLandingPage() { + var responseBody = RestAssured.given() + .when() + .config(restConfig) + .cookie("WEBWOLFSESSION", getWebWolfCookie()) + .get(webWolfUrl("WebWolf/requests")) + .then() + .extract().response().getBody().asString(); + int startIndex = responseBody.lastIndexOf("\"path\" : \"/PasswordReset/reset/reset-password/"); + var link = responseBody.substring(startIndex + "\"path\" : \"/PasswordReset/reset/reset-password/".length(), responseBody.indexOf(",", startIndex) - 1); + return link; + } + + private void clickForgotEmailLink(String user) { + RestAssured.given() + .when() + .header("host", "localhost:9090") + .config(restConfig) + .cookie("JSESSIONID", getWebGoatCookie()) + .formParams("email", user) + .post(url("PasswordReset/ForgotPassword/create-password-reset-link")) + .then() + .statusCode(200); + } +} diff --git a/webgoat-integration-tests/src/test/java/org/owasp/webgoat/SqlInjectionAdvancedTest.java b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/SqlInjectionAdvancedTest.java new file mode 100644 index 000000000..5bb9b5bcf --- /dev/null +++ b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/SqlInjectionAdvancedTest.java @@ -0,0 +1,49 @@ +package org.owasp.webgoat; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +public class SqlInjectionAdvancedTest extends IntegrationTest { + + @Test + public void runTests() { + startLesson("SqlInjectionAdvanced"); + + Map params = new HashMap<>(); + params.clear(); + params.put("username_reg", "tom' AND substring(password,1,1)='t"); + params.put("password_reg", "password"); + params.put("email_reg", "someone@microsoft.com"); + params.put("confirm_password", "password"); + checkAssignmentWithPUT(url("/WebGoat/SqlInjectionAdvanced/challenge"), params, true); + + params.clear(); + params.put("username_login", "tom"); + params.put("password_login", "thisisasecretfortomonly"); + checkAssignment(url("/WebGoat/SqlInjectionAdvanced/challenge_Login"), params, true); + + params.clear(); + params.put("userid_6a", "'; SELECT * FROM user_system_data;--"); + checkAssignment(url("/WebGoat/SqlInjectionAdvanced/attack6a"), params, true); + + params.clear(); + params.put("userid_6a", "Smith' union select userid,user_name, user_name,user_name,password,cookie,userid from user_system_data --"); + checkAssignment(url("/WebGoat/SqlInjectionAdvanced/attack6a"), params, true); + + params.clear(); + params.put("userid_6b", "passW0rD"); + checkAssignment(url("/WebGoat/SqlInjectionAdvanced/attack6b"), params, true); + + params.clear(); + params.put("question_0_solution", "Solution 4: A statement has got values instead of a prepared statement"); + params.put("question_1_solution", "Solution 3: ?"); + params.put("question_2_solution", "Solution 2: Prepared statements are compiled once by the database management system waiting for input and are pre-compiled this way."); + params.put("question_3_solution", "Solution 3: Placeholders can prevent that the users input gets attached to the SQL query resulting in a seperation of code and data."); + params.put("question_4_solution", "Solution 4: The database registers 'Robert' ); DROP TABLE Students;--'."); + checkAssignment(url("/WebGoat/SqlInjectionAdvanced/quiz"), params, true); + + checkResults("/SqlInjectionAdvanced/"); + } +} diff --git a/webgoat-integration-tests/src/test/java/org/owasp/webgoat/SqlInjectionLessonTest.java b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/SqlInjectionLessonTest.java new file mode 100644 index 000000000..941b088e6 --- /dev/null +++ b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/SqlInjectionLessonTest.java @@ -0,0 +1,82 @@ +package org.owasp.webgoat; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +public class SqlInjectionLessonTest extends IntegrationTest { + + private static final String sql_2 = "select department from employees where last_name='Franco'"; + private static final String sql_3 = "update employees set department='Sales' where last_name='Barnett'"; + private static final String sql_4_drop = "alter table employees drop column phone"; + private static final String sql_4_add = "alter table employees add column phone varchar(20)"; + private static final String sql_5 = "grant alter table to UnauthorizedUser"; + private static final String sql_9_account = " ' "; + private static final String sql_9_operator = "or"; + private static final String sql_9_injection = "'1'='1"; + private static final String sql_10_login_count = "2"; + private static final String sql_10_userid = "1 or 1=1"; + + private static final String sql_11_a = "Smith' or '1' = '1"; + private static final String sql_11_b = "3SL99A' or '1'='1"; + + private static final String sql_12_a = "Smith"; + private static final String sql_12_b = "3SL99A' ; update employees set salary= '100000' where last_name='Smith"; + + private static final String sql_13 = "%update% '; drop table access_log ; --'"; + + @Test + public void runTests() { + startLesson("SqlInjection"); + + Map params = new HashMap<>(); + params.clear(); + params.put("query", sql_2); + checkAssignment(url("/WebGoat/SqlInjection/attack2"), params, true); + + params.clear(); + params.put("query", sql_3); + checkAssignment(url("/WebGoat/SqlInjection/attack3"), params, true); + + params.clear(); + params.put("query", sql_4_drop); + checkAssignment(url("/WebGoat/SqlInjection/attack4"), params, false); + + params.clear(); + params.put("query", sql_4_add); + checkAssignment(url("/WebGoat/SqlInjection/attack4"), params, true); + + params.clear(); + params.put("query", sql_5); + checkAssignment(url("/WebGoat/SqlInjection/attack5"), params, true); + + params.clear(); + params.put("operator", sql_9_operator); + params.put("account", sql_9_account); + params.put("injection", sql_9_injection); + checkAssignment(url("/WebGoat/SqlInjection/assignment5a"), params, true); + + params.clear(); + params.put("login_count", sql_10_login_count); + params.put("userid", sql_10_userid); + checkAssignment(url("/WebGoat/SqlInjection/assignment5b"), params, true); + + params.clear(); + params.put("name", sql_11_a); + params.put("auth_tan", sql_11_b); + checkAssignment(url("/WebGoat/SqlInjection/attack8"), params, true); + + params.clear(); + params.put("name", sql_12_a); + params.put("auth_tan", sql_12_b); + checkAssignment(url("/WebGoat/SqlInjection/attack9"), params, true); + + params.clear(); + params.put("action_string", sql_13); + checkAssignment(url("/WebGoat/SqlInjection/attack10"), params, true); + + checkResults("/SqlInjection/"); + + } +} diff --git a/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionMitigation_TestHelper.java b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/SqlInjectionMitigationTest.java similarity index 65% rename from webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionMitigation_TestHelper.java rename to webgoat-integration-tests/src/test/java/org/owasp/webgoat/SqlInjectionMitigationTest.java index 70389dee2..d51af280c 100644 --- a/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionMitigation_TestHelper.java +++ b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/SqlInjectionMitigationTest.java @@ -1,37 +1,39 @@ -package org.owasp.webgoat; - -import java.util.HashMap; -import java.util.Map; - -public class SqlInjectionMitigation_TestHelper extends TestHelper { - - public void runTests(String webgoatURL, String cookie) { - - startLesson(cookie, webgoatURL, "SqlInjectionMitigations"); - - Map params = new HashMap<>(); - params.clear(); - params.put("field1", "getConnection"); - params.put("field2", "PreparedStatement prep"); - params.put("field3", "prepareStatement"); - params.put("field4", "?"); - params.put("field5", "?"); - params.put("field6", "prep.setString(1,\"\")"); - params.put("field7", "prep.setString(2,\\\"\\\")"); - checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjectionMitigations/attack10a", params, true); - - params.put("editor", "try {\r\n" + - " Connection conn = DriverManager.getConnection(DBURL,DBUSER,DBPW);\r\n" + - " PreparedStatement prep = conn.prepareStatement(\"select id from users where name = ?\");\r\n" + - " prep.setString(1,\"me\");\r\n" + - " prep.execute();\r\n" + - " System.out.println(conn); //should output 'null'\r\n" + - "} catch (Exception e) {\r\n" + - " System.out.println(\"Oops. Something went wrong!\");\r\n" + - "}"); - checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjectionMitigations/attack10b", params, true); - - //checkResults(cookie, webgoatURL, "/SqlInjectionMitigations/"); - - } -} +package org.owasp.webgoat; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +public class SqlInjectionMitigationTest extends IntegrationTest { + + @Test + public void runTests() { + startLesson("SqlInjectionMitigations"); + + Map params = new HashMap<>(); + params.clear(); + params.put("field1", "getConnection"); + params.put("field2", "PreparedStatement prep"); + params.put("field3", "prepareStatement"); + params.put("field4", "?"); + params.put("field5", "?"); + params.put("field6", "prep.setString(1,\"\")"); + params.put("field7", "prep.setString(2,\\\"\\\")"); + checkAssignment(url("/WebGoat/SqlInjectionMitigations/attack10a"), params, true); + + params.put("editor", "try {\r\n" + + " Connection conn = DriverManager.getConnection(DBURL,DBUSER,DBPW);\r\n" + + " PreparedStatement prep = conn.prepareStatement(\"select id from users where name = ?\");\r\n" + + " prep.setString(1,\"me\");\r\n" + + " prep.execute();\r\n" + + " System.out.println(conn); //should output 'null'\r\n" + + "} catch (Exception e) {\r\n" + + " System.out.println(\"Oops. Something went wrong!\");\r\n" + + "}"); + checkAssignment(url("/WebGoat/SqlInjectionMitigations/attack10b"), params, true); + + //checkResults(webGoatCookie, webgoatURL, "/SqlInjectionMitigations/"); + + } +} diff --git a/webgoat-integration-tests/src/test/resources/logback-test.xml b/webgoat-integration-tests/src/test/resources/logback-test.xml new file mode 100644 index 000000000..2ee84585a --- /dev/null +++ b/webgoat-integration-tests/src/test/resources/logback-test.xml @@ -0,0 +1,15 @@ + + + + + \ No newline at end of file diff --git a/webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/plugin/ResetLinkAssignmentForgotPassword.java b/webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/plugin/ResetLinkAssignmentForgotPassword.java index daceaa377..88bb7cd24 100644 --- a/webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/plugin/ResetLinkAssignmentForgotPassword.java +++ b/webgoat-lessons/password-reset/src/main/java/org/owasp/webgoat/plugin/ResetLinkAssignmentForgotPassword.java @@ -7,7 +7,6 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; -import org.springframework.web.bind.annotation.CookieValue; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; @@ -17,69 +16,67 @@ import javax.servlet.http.HttpServletRequest; import java.time.LocalDateTime; import java.util.UUID; +import static org.springframework.util.StringUtils.*; import static org.springframework.web.bind.annotation.RequestMethod.POST; /** * Part of the password reset assignment. Used to send the e-mail. + * * @author nbaars * @since 8/20/17. */ @AssignmentPath("/PasswordReset/ForgotPassword") public class ResetLinkAssignmentForgotPassword extends AssignmentEndpoint { - private final RestTemplate restTemplate; - private final String webWolfMailURL; + private final RestTemplate restTemplate; + private final String webWolfMailURL; - public ResetLinkAssignmentForgotPassword(RestTemplate restTemplate, - @Value("${webwolf.url.mail}") String webWolfMailURL) { - this.restTemplate = restTemplate; - this.webWolfMailURL = webWolfMailURL; - } + public ResetLinkAssignmentForgotPassword(RestTemplate restTemplate, + @Value("${webwolf.url.mail}") String webWolfMailURL) { + this.restTemplate = restTemplate; + this.webWolfMailURL = webWolfMailURL; + } - @RequestMapping(method = POST, value = "/create-password-reset-link") - @ResponseBody - public AttackResult sendPasswordResetLink(@RequestParam String email, HttpServletRequest request, @CookieValue("JSESSIONID") String cookie) { - String resetLink = UUID.randomUUID().toString(); - ResetLinkAssignment.resetLinks.add(resetLink); - String host = request.getHeader("host"); - if (org.springframework.util.StringUtils.hasText(email)) { - if (email.equals(ResetLinkAssignment.TOM_EMAIL) && host.contains("9090")) { //User indeed changed the host header. - ResetLinkAssignment.userToTomResetLink.put(getWebSession().getUserName(), resetLink); - fakeClickingLinkEmail(host, resetLink); - } else { + @RequestMapping(method = POST, value = "/create-password-reset-link") + @ResponseBody + public AttackResult sendPasswordResetLink(@RequestParam String email, HttpServletRequest request) { + String resetLink = UUID.randomUUID().toString(); + ResetLinkAssignment.resetLinks.add(resetLink); + String host = request.getHeader("host"); + if (hasText(email)) { + if (email.equals(ResetLinkAssignment.TOM_EMAIL) && host.contains("9090")) { //User indeed changed the host header. + ResetLinkAssignment.userToTomResetLink.put(getWebSession().getUserName(), resetLink); + fakeClickingLinkEmail(host, resetLink); + } else { + try { + sendMailToUser(email, host, resetLink); + } catch (Exception e) { + return failed().output("E-mail can't be send. please try again.").build(); + } + } + } + return success().feedback("email.send").feedbackArgs(email).build(); + } + + private void sendMailToUser(@RequestParam String email, String host, String resetLink) { + int index = email.indexOf("@"); + String username = email.substring(0, index == -1 ? email.length() : index); + PasswordResetEmail mail = PasswordResetEmail.builder() + .title("Your password reset link") + .contents(String.format(ResetLinkAssignment.TEMPLATE, host, resetLink)) + .sender("password-reset@webgoat-cloud.net") + .recipient(username).build(); + this.restTemplate.postForEntity(webWolfMailURL, mail, Object.class); + } + + private void fakeClickingLinkEmail(String host, String resetLink) { try { - sendMailToUser(email, host, resetLink); - } catch(Exception e) { return failed().output("E-mail can't be send. please try again.").build(); } - } + HttpHeaders httpHeaders = new HttpHeaders(); + HttpEntity httpEntity = new HttpEntity(httpHeaders); + new RestTemplate().exchange(String.format("http://%s/PasswordReset/reset/reset-password/%s", host, resetLink), HttpMethod.GET, httpEntity, Void.class); + } catch (Exception e) { + //don't care + } } - return success().feedback("email.send").feedbackArgs(email).build(); - } - - private void sendMailToUser(@RequestParam String email, String host, String resetLink) { - int index = email.indexOf("@"); - String username = email.substring(0, index == -1 ? email.length() : index); - PasswordResetEmail mail = PasswordResetEmail.builder() - .title("Your password reset link") - .contents(String.format(ResetLinkAssignment.TEMPLATE, host, resetLink)) - .sender("password-reset@webgoat-cloud.net") - .recipient(username) - .time(LocalDateTime.now()).build(); - this.restTemplate.postForEntity(webWolfMailURL, mail, Object.class); - } - - /** - * We need to add the current cookie of the user otherwise we cannot distinguish in WebWolf for - * which user we need to trace the incoming request. In normal situation this HOST will be in your - * full control so every incoming request would be valid. - */ - private void fakeClickingLinkEmail(String host, String resetLink) { - try { - HttpHeaders httpHeaders = new HttpHeaders(); - HttpEntity httpEntity = new HttpEntity(httpHeaders); - new RestTemplate().exchange(String.format("http://%s/PasswordReset/reset/reset-password/%s", host, resetLink), HttpMethod.GET, httpEntity, Void.class); - } catch (Exception e) { - //don't care - } - } } diff --git a/webgoat-lessons/password-reset/src/main/resources/i18n/WebGoatLabels.properties b/webgoat-lessons/password-reset/src/main/resources/i18n/WebGoatLabels.properties index 283ab18b4..2b88df6a4 100644 --- a/webgoat-lessons/password-reset/src/main/resources/i18n/WebGoatLabels.properties +++ b/webgoat-lessons/password-reset/src/main/resources/i18n/WebGoatLabels.properties @@ -9,6 +9,8 @@ password-questions-wrong-user=You need to find a different user you are logging password-questions-unknown-user=User {0} is not a valid user. password-questions-one-successful=You answered one question successfully please try another one. +email.send=An e-mail has been send to {0} + password-reset-no-user=Please supply a valid e-mail address. password-reset-solved=Congratulations you solved the assignment, please type in the following code in the e-mail field: {0} password-reset-not-solved=Sorry but you did not redirect the reset link to WebWolf diff --git a/webgoat-server/pom.xml b/webgoat-server/pom.xml index 5c0ae93b2..312887d4c 100644 --- a/webgoat-server/pom.xml +++ b/webgoat-server/pom.xml @@ -139,17 +139,6 @@ secure-passwords ${project.version} - - org.springframework.boot - spring-boot-starter-test - test - - - io.rest-assured - rest-assured - 4.0.0 - test - @@ -199,6 +188,22 @@ true + + org.apache.maven.plugins + maven-jar-plugin + 3.1.2 + + + test-compile + + jar + + + internal + + + + diff --git a/webgoat-server/src/main/java/org/owasp/webgoat/StartWebGoat.java b/webgoat-server/src/main/java/org/owasp/webgoat/StartWebGoat.java index 473114c0e..bf7b8a223 100644 --- a/webgoat-server/src/main/java/org/owasp/webgoat/StartWebGoat.java +++ b/webgoat-server/src/main/java/org/owasp/webgoat/StartWebGoat.java @@ -27,6 +27,11 @@ package org.owasp.webgoat; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.support.SpringBootServletInitializer; +import org.springframework.context.annotation.Import; + +import java.util.Map; /** * Main entry point, this project is here to get all the lesson jars included to the final jar file @@ -36,10 +41,11 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; */ @SpringBootApplication @Slf4j -public class StartWebGoat { +public class StartWebGoat extends SpringBootServletInitializer { public static void main(String[] args) { log.info("Starting WebGoat with args: {}", args); - SpringApplication.run(WebGoat.class, args); + System.setProperty("spring.config.name", "application-webgoat"); + SpringApplication.run(StartWebGoat.class, args); } } diff --git a/webgoat-server/src/test/java/org/owasp/webgoat/General_TestHelper.java b/webgoat-server/src/test/java/org/owasp/webgoat/General_TestHelper.java deleted file mode 100644 index 694084f50..000000000 --- a/webgoat-server/src/test/java/org/owasp/webgoat/General_TestHelper.java +++ /dev/null @@ -1,137 +0,0 @@ -package org.owasp.webgoat; - -import static io.restassured.RestAssured.given; -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; - -import java.util.HashMap; -import java.util.Map; - -import io.restassured.http.ContentType; - - -public class General_TestHelper extends TestHelper { - - - public void httpBasics(String webgoatURL, String cookie) { - - startLesson(cookie, webgoatURL, "HttpBasics"); - Map params = new HashMap<>(); - params.clear(); - params.put("person", "goatuser"); - checkAssignment(cookie, webgoatURL+"/WebGoat/HttpBasics/attack1", params, true); - - params.clear(); - params.put("answer", "POST"); - params.put("magic_answer", "33"); - params.put("magic_num", "4"); - checkAssignment(cookie, webgoatURL+"/WebGoat/HttpBasics/attack2", params, false); - - params.clear(); - params.put("answer", "POST"); - params.put("magic_answer", "33"); - params.put("magic_num", "33"); - checkAssignment(cookie, webgoatURL+"/WebGoat/HttpBasics/attack2", params, true); - - checkResults(cookie, webgoatURL, "/HttpBasics/"); - - } - - public void httpProxies(String webgoatURL, String cookie) { - - startLesson(cookie, webgoatURL, "HttpProxies"); - assertThat(given() - .when().config(restConfig).cookie("JSESSIONID", cookie).header("x-request-intercepted", "true") - .contentType(ContentType.JSON) - //.log().all() - .get(webgoatURL + "/WebGoat/HttpProxies/intercept-request?changeMe=Requests are tampered easily").then() - //.log().all() - .statusCode(200).extract().path("lessonCompleted"), is(true)); - - checkResults(cookie, webgoatURL, "/HttpProxies/"); - - } - - public void cia(String webgoatURL, String cookie) { - - startLesson(cookie, webgoatURL, "CIA"); - Map params = new HashMap<>(); - params.clear(); - params.put("question_0_solution", "Solution 3: By stealing a database where names and emails are stored and uploading it to a website."); - params.put("question_1_solution", "Solution 1: By changing the names and emails of one or more users stored in a database."); - params.put("question_2_solution", "Solution 4: By launching a denial of service attack on the servers."); - params.put("question_3_solution", "Solution 2: The systems security is compromised even if only one goal is harmed."); - checkAssignment(cookie, webgoatURL+"/WebGoat/cia/quiz", params, true); - checkResults(cookie, webgoatURL, "/cia/"); - - } - - public void securePasswords(String webgoatURL, String cookie) { - - startLesson(cookie, webgoatURL, "SecurePasswords"); - Map params = new HashMap<>(); - params.clear(); - params.put("password", "ajnaeliclm^&&@kjn."); - checkAssignment(cookie, webgoatURL+"/WebGoat/SecurePasswords/assignment", params, true); - checkResults(cookie, webgoatURL, "SecurePasswords/"); - - startLesson(cookie, webgoatURL, "AuthBypass"); - params.clear(); - params.put("secQuestion2", "John"); - params.put("secQuestion3", "Main"); - params.put("jsEnabled", "1"); - params.put("verifyMethod", "SEC_QUESTIONS"); - params.put("userId", "12309746"); - checkAssignment(cookie, webgoatURL + "/WebGoat/auth-bypass/verify-account", params, true); - checkResults(cookie, webgoatURL, "/auth-bypass/"); - - startLesson(cookie, webgoatURL, "HttpProxies"); - assertThat(given().when().config(restConfig).cookie("JSESSIONID", cookie).header("x-request-intercepted", "true") - .contentType(ContentType.JSON) - //.log().all() - .get(webgoatURL + "/WebGoat/HttpProxies/intercept-request?changeMe=Requests are tampered easily").then() - //.log().all() - .statusCode(200).extract().path("lessonCompleted"), is(true)); - checkResults(cookie, webgoatURL, "/HttpProxies/"); - - } - - public void chrome(String webgoatURL, String cookie) { - - startLesson(cookie, webgoatURL, "ChromeDevTools"); - - Map params = new HashMap<>(); - params.clear(); - params.put("param1", "42"); - params.put("param2", "24"); - - String result = - given() - .when() - .config(restConfig) - .cookie("JSESSIONID", cookie) - .header("webgoat-requested-by","dom-xss-vuln") - .header("X-Requested-With", "XMLHttpRequest") - .formParams(params) - .post(webgoatURL+"/WebGoat/CrossSiteScripting/phone-home-xss") - .then() - //.log().all() - .statusCode(200) - .extract().path("output"); - String secretNumber = result.substring("phoneHome Response is ".length()); - - params.clear(); - params.put("successMessage", secretNumber); - checkAssignment(cookie, webgoatURL+"/WebGoat/ChromeDevTools/dummy", params, true); - - params.clear(); - params.put("number", "24"); - params.put("network_num", "24"); - checkAssignment(cookie, webgoatURL+"/WebGoat/ChromeDevTools/network", params, true); - - checkResults(cookie, webgoatURL, "/ChromeDevTools/"); - - } - - -} diff --git a/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionAdvanced_TestHelper.java b/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionAdvanced_TestHelper.java deleted file mode 100644 index 7328475f2..000000000 --- a/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjectionAdvanced_TestHelper.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.owasp.webgoat; - -import java.util.HashMap; -import java.util.Map; - -public class SqlInjectionAdvanced_TestHelper extends TestHelper { - - public void runTests(String webgoatURL, String cookie) { - - startLesson(cookie, webgoatURL, "SqlInjectionAdvanced"); - - Map params = new HashMap<>(); - params.clear(); - params.put("username_reg", "tom' AND substring(password,1,1)='t"); - params.put("password_reg", "password"); - params.put("email_reg", "someone@microsoft.com"); - params.put("confirm_password", "password"); - checkAssignmentWithPUT(cookie, webgoatURL+"/WebGoat/SqlInjectionAdvanced/challenge", params, true); - - params.clear(); - params.put("username_login", "tom"); - params.put("password_login", "thisisasecretfortomonly"); - checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjectionAdvanced/challenge_Login", params, true); - - params.clear(); - params.put("userid_6a", "'; SELECT * FROM user_system_data;--"); - checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjectionAdvanced/attack6a", params, true); - - params.clear(); - params.put("userid_6a", "Smith' union select userid,user_name, user_name,user_name,password,cookie,userid from user_system_data --"); - checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjectionAdvanced/attack6a", params, true); - - params.clear(); - params.put("userid_6b", "passW0rD"); - checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjectionAdvanced/attack6b", params, true); - - params.clear(); - params.put("question_0_solution", "Solution 4: A statement has got values instead of a prepared statement"); - params.put("question_1_solution", "Solution 3: ?"); - params.put("question_2_solution", "Solution 2: Prepared statements are compiled once by the database management system waiting for input and are pre-compiled this way."); - params.put("question_3_solution", "Solution 3: Placeholders can prevent that the users input gets attached to the SQL query resulting in a seperation of code and data."); - params.put("question_4_solution", "Solution 4: The database registers 'Robert' ); DROP TABLE Students;--'."); - checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjectionAdvanced/quiz", params, true); - - checkResults(cookie, webgoatURL, "/SqlInjectionAdvanced/"); - - } -} diff --git a/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjection_TestHelper.java b/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjection_TestHelper.java deleted file mode 100644 index 1f1db2ab4..000000000 --- a/webgoat-server/src/test/java/org/owasp/webgoat/SqlInjection_TestHelper.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.owasp.webgoat; - -import java.util.HashMap; -import java.util.Map; - -public class SqlInjection_TestHelper extends TestHelper { - - private static final String sql_2 = "select department from employees where last_name='Franco'"; - private static final String sql_3 = "update employees set department='Sales' where last_name='Barnett'"; - private static final String sql_4_drop = "alter table employees drop column phone"; - private static final String sql_4_add = "alter table employees add column phone varchar(20)"; - private static final String sql_5 = "grant alter table to UnauthorizedUser"; - private static final String sql_9_account = " ' "; - private static final String sql_9_operator = "or"; - private static final String sql_9_injection = "'1'='1"; - private static final String sql_10_login_count = "2"; - private static final String sql_10_userid = "1 or 1=1"; - - private static final String sql_11_a = "Smith' or '1' = '1"; - private static final String sql_11_b = "3SL99A' or '1'='1"; - - private static final String sql_12_a = "Smith"; - private static final String sql_12_b = "3SL99A' ; update employees set salary= '100000' where last_name='Smith"; - - private static final String sql_13 = "%update% '; drop table access_log ; --'"; - - public void runTests(String webgoatURL, String cookie) { - - startLesson(cookie, webgoatURL, "SqlInjection"); - - Map params = new HashMap<>(); - params.clear(); - params.put("query", sql_2); - checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack2", params, true); - - params.clear(); - params.put("query", sql_3); - checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack3", params, true); - - params.clear(); - params.put("query", sql_4_drop); - checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack4", params, false); - - params.clear(); - params.put("query", sql_4_add); - checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack4", params, true); - - params.clear(); - params.put("query", sql_5); - checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack5", params, true); - - params.clear(); - params.put("operator", sql_9_operator); - params.put("account", sql_9_account); - params.put("injection", sql_9_injection); - checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/assignment5a", params, true); - - params.clear(); - params.put("login_count", sql_10_login_count); - params.put("userid", sql_10_userid); - checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/assignment5b", params, true); - - params.clear(); - params.put("name", sql_11_a); - params.put("auth_tan", sql_11_b); - checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack8", params, true); - - params.clear(); - params.put("name", sql_12_a); - params.put("auth_tan", sql_12_b); - checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack9", params, true); - - params.clear(); - params.put("action_string", sql_13); - checkAssignment(cookie, webgoatURL+"/WebGoat/SqlInjection/attack10", params, true); - - checkResults(cookie, webgoatURL, "/SqlInjection/"); - - } -} diff --git a/webgoat-server/src/test/java/org/owasp/webgoat/TestHelper.java b/webgoat-server/src/test/java/org/owasp/webgoat/TestHelper.java deleted file mode 100644 index fd2b67141..000000000 --- a/webgoat-server/src/test/java/org/owasp/webgoat/TestHelper.java +++ /dev/null @@ -1,118 +0,0 @@ -package org.owasp.webgoat; - -import static io.restassured.RestAssured.given; -import static org.hamcrest.CoreMatchers.everyItem; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.startsWith; - -import static org.junit.Assert.assertThat; - -import java.util.Map; - -import io.restassured.config.RestAssuredConfig; -import io.restassured.config.SSLConfig; - -public class TestHelper { - - //This also allows to test the application with HTTPS when outside testing option is used - protected RestAssuredConfig restConfig = RestAssuredConfig.newConfig().sslConfig(new SSLConfig().relaxedHTTPSValidation()); - - /** - * At start of a lesson. The .lesson.lesson is visited and the lesson is reset. - * @param cookie - * @param url - * @param lessonName - */ - public void startLesson(String cookie, String url, String lessonName) { - given() - .when() - .config(restConfig) - .cookie("JSESSIONID", cookie) - .get(url+"/WebGoat/"+lessonName+".lesson.lesson") - .then() - .statusCode(200); - - given() - .when() - .config(restConfig) - .cookie("JSESSIONID", cookie) - .get(url+"/WebGoat/service/restartlesson.mvc") - .then() - .statusCode(200); - } - - /** - * Helper method for most common type of test. - * POST with parameters. - * Checks for 200 and lessonCompleted as indicated by expectedResult - * @param webgoatCookie - * @param url - * @param params - * @param expectedResult - */ - public void checkAssignment(String webgoatCookie, String url, Map params, boolean expectedResult) { - assertThat( - given() - .when() - .config(restConfig) - .cookie("JSESSIONID", webgoatCookie) - .formParams(params) - .post(url) - .then() - //.log().all() - .statusCode(200) - .extract().path("lessonCompleted"), is(expectedResult)); - } - - /** - * Helper method for most common type of test. - * PUT with parameters. - * Checks for 200 and lessonCompleted as indicated by expectedResult - * @param webgoatCookie - * @param url - * @param params - * @param expectedResult - */ - public void checkAssignmentWithPUT(String webgoatCookie, String url, Map params, boolean expectedResult) { - assertThat( - given() - .when() - .config(restConfig) - .cookie("JSESSIONID", webgoatCookie) - .formParams(params) - .put(url) - .then() - //.log().all() - .statusCode(200) - .extract().path("lessonCompleted"), is(expectedResult)); - } - - /** - * Helper method at the end of a lesson. - * Check if all path paramters are correct for the progress. - * Check if all are solved. - * @param webgoatCookie - * @param webgoatURL - * @param prefix - */ - public void checkResults(String webgoatCookie, String webgoatURL, String prefix) { - assertThat(given() - .when() - .config(restConfig) - .cookie("JSESSIONID", webgoatCookie) - .get(webgoatURL+"/WebGoat/service/lessonoverview.mvc") - .then() - //.log().all() - .statusCode(200).extract().jsonPath().getList("solved"),everyItem(is(true))); - - assertThat(given() - .when() - .config(restConfig) - .cookie("JSESSIONID", webgoatCookie) - .get(webgoatURL+"/WebGoat/service/lessonoverview.mvc") - .then() - //.log().all() - .statusCode(200).extract().jsonPath().getList("assignment.path"),everyItem(startsWith(prefix))); - - } -} diff --git a/webgoat-server/src/test/java/org/owasp/webgoat/WebGoatIntegrationTest.java b/webgoat-server/src/test/java/org/owasp/webgoat/WebGoatIntegrationTest.java deleted file mode 100644 index 12967099e..000000000 --- a/webgoat-server/src/test/java/org/owasp/webgoat/WebGoatIntegrationTest.java +++ /dev/null @@ -1,162 +0,0 @@ -package org.owasp.webgoat; - -import static io.restassured.RestAssured.given; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.context.embedded.LocalServerPort; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest(classes=WebGoat.class, webEnvironment = WebEnvironment.RANDOM_PORT) -@EnableAutoConfiguration -public class WebGoatIntegrationTest extends TestHelper { - - /* - * Unique port for http server. Database port is not yet overruled. But this is - * not a problem for the integration test. - */ - @LocalServerPort - int randomServerPort; - - private General_TestHelper generalTestHelper = new General_TestHelper(); - private SqlInjection_TestHelper sqlInjectionHelper = new SqlInjection_TestHelper(); - private SqlInjectionAdvanced_TestHelper sqlInjectionAdvancedHelper = new SqlInjectionAdvanced_TestHelper(); - private SqlInjectionMitigation_TestHelper sqlInjectionMitigationHelper = new SqlInjectionMitigation_TestHelper(); - - String webgoatURL = System.getProperty("WEBGOAT_URL",""); - String webgoatUser = System.getProperty("WEBGOAT_USER",""); - String webgoatPassword = System.getProperty("WEBGOAT_PASSWORD","password"); - String cookie = ""; - - @Before - public void init() { - - /* - * If no system properties are set, the test runs against the random port - * of the webgoat application that starts with this test. - * If set you can use it to test an oustide running application. If testing - * against outside running applications, the tests that require WebWolf can be tested as well. - */ - //TODO add support for testing the lessons that require WebWolf as well. - if (webgoatURL.equals("")) { - webgoatURL = "http://127.0.0.1:"+randomServerPort; - } - - /* - * If not defined a random user will be registered and used in the test. - * If you run against an outside application and want to visually see the results, - * you can set a username. - */ - if (webgoatUser.equals("")) { - webgoatUser = "tester"+Math.round(Math.random()*1000); - } - - //check if user exists - String location = given() - .when() - .config(restConfig) - .formParam("username", webgoatUser) - .formParam("password", "password") - .post(webgoatURL+"/WebGoat/login") - .then() - //.log().all() - .cookie("JSESSIONID") - .statusCode(302) - .extract().header("Location"); - - //register when not existing, otherwise log in and save the cookie - if (location.endsWith("error")) { - - cookie = given() - .when() - .config(restConfig) - .formParam("username", webgoatUser) - .formParam("password", "password") - .formParam("matchingPassword", "password") - .formParam("agree", "agree") - .post(webgoatURL+"/WebGoat/register.mvc") - .then() - .cookie("JSESSIONID") - .statusCode(302) - .extract() - .cookie("JSESSIONID"); - - } else { - - cookie = given() - .when() - .config(restConfig) - .formParam("username", webgoatUser) - .formParam("password", "password") - .post(webgoatURL+"/WebGoat/login") - .then() - //.log().all() - .cookie("JSESSIONID") - .statusCode(302) - .extract().cookie("JSESSIONID"); - } - } - - @Test - public void testGeneral_HttpBasics() { - - generalTestHelper.httpBasics(webgoatURL, cookie); - - } - - @Test - public void testGeneral_HttpProxies() { - - generalTestHelper.httpProxies(webgoatURL, cookie); - - } - - @Test - public void testGeneral_CIA() { - - generalTestHelper.cia(webgoatURL, cookie); - - } - - @Test - public void testGeneral_Chrome() { - - generalTestHelper.chrome(webgoatURL, cookie); - - } - - @Test - public void testSecurePassords() { - - generalTestHelper.securePasswords(webgoatURL, cookie); - - } - - @Test - public void testSQLInjection() { - - sqlInjectionHelper.runTests(webgoatURL, cookie); - - } - - @Test - public void testSQLInjectionAdvanced() { - - sqlInjectionAdvancedHelper.runTests(webgoatURL, cookie); - - } - - @Test - public void testSQLInjectionMitigation() { - - sqlInjectionMitigationHelper.runTests(webgoatURL, cookie); - - } - - -} diff --git a/webwolf/pom.xml b/webwolf/pom.xml index c0126b712..54c0eb81f 100644 --- a/webwolf/pom.xml +++ b/webwolf/pom.xml @@ -110,6 +110,22 @@ org.springframework.boot spring-boot-maven-plugin + + org.apache.maven.plugins + maven-jar-plugin + 3.1.2 + + + test-compile + + jar + + + internal + + + + org.apache.maven.plugins maven-surefire-plugin diff --git a/webwolf/src/main/java/org/owasp/webwolf/WebWolf.java b/webwolf/src/main/java/org/owasp/webwolf/WebWolf.java index 768b78347..1153f14cb 100644 --- a/webwolf/src/main/java/org/owasp/webwolf/WebWolf.java +++ b/webwolf/src/main/java/org/owasp/webwolf/WebWolf.java @@ -1,29 +1,24 @@ package org.owasp.webwolf; -import lombok.extern.slf4j.Slf4j; import org.owasp.webwolf.requests.WebWolfTraceRepository; import org.springframework.boot.SpringApplication; import org.springframework.boot.actuate.trace.TraceRepository; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.boot.web.support.SpringBootServletInitializer; import org.springframework.context.annotation.Bean; +import java.util.Map; + @SpringBootApplication -@Slf4j -public class WebWolf extends SpringBootServletInitializer { +public class WebWolf { @Bean public TraceRepository traceRepository() { return new WebWolfTraceRepository(); } - @Override - protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { - return application.sources(WebWolf.class); - } - - public static void main(String[] args) throws Exception { + public static void main(String[] args) { + System.setProperty("spring.config.name", "application-webwolf"); SpringApplication.run(WebWolf.class, args); } } diff --git a/webwolf/src/main/java/org/owasp/webwolf/mailbox/Email.java b/webwolf/src/main/java/org/owasp/webwolf/mailbox/Email.java index c97e0ba4e..aa31da1f7 100644 --- a/webwolf/src/main/java/org/owasp/webwolf/mailbox/Email.java +++ b/webwolf/src/main/java/org/owasp/webwolf/mailbox/Email.java @@ -25,6 +25,7 @@ public class Email implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @JsonIgnore private LocalDateTime time = LocalDateTime.now(); @Column(length = 1024) private String contents; diff --git a/webwolf/src/main/java/org/owasp/webwolf/requests/Requests.java b/webwolf/src/main/java/org/owasp/webwolf/requests/Requests.java index d92bb4bf1..7bf9bd162 100644 --- a/webwolf/src/main/java/org/owasp/webwolf/requests/Requests.java +++ b/webwolf/src/main/java/org/owasp/webwolf/requests/Requests.java @@ -42,7 +42,7 @@ public class Requests { } @GetMapping - public ModelAndView get(HttpServletRequest request) { + public ModelAndView get() { ModelAndView m = new ModelAndView("requests"); List traces = traceRepository.findAllTraces().stream() .map(t -> new Tracert(t.getTimestamp(), path(t), toJsonString(t))).collect(toList()); diff --git a/webwolf/src/main/java/org/owasp/webwolf/requests/WebWolfTraceRepository.java b/webwolf/src/main/java/org/owasp/webwolf/requests/WebWolfTraceRepository.java index 23e95ba02..d08ed00f6 100644 --- a/webwolf/src/main/java/org/owasp/webwolf/requests/WebWolfTraceRepository.java +++ b/webwolf/src/main/java/org/owasp/webwolf/requests/WebWolfTraceRepository.java @@ -7,7 +7,10 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.boot.actuate.trace.Trace; import org.springframework.boot.actuate.trace.TraceRepository; -import java.util.*; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * Keep track of all the incoming requests, we are only keeping track of request originating from @@ -20,7 +23,7 @@ import java.util.*; public class WebWolfTraceRepository implements TraceRepository { private final EvictingQueue traces = EvictingQueue.create(10000); - private List exclusionList = Lists.newArrayList("/WebWolf/home", "/WebWolf/mail","/WebWolf/files", "/images/", "/login", "/favicon.ico", "/js/", "/webjars/", "/WebWolf/requests", "/css/", "/mail"); + private List exclusionList = Lists.newArrayList("/WebWolf/home", "/WebWolf/mail", "/WebWolf/files", "/images/", "/login", "/favicon.ico", "/js/", "/webjars/", "/WebWolf/requests", "/css/", "/mail"); @Override public List findAll() { @@ -40,21 +43,9 @@ public class WebWolfTraceRepository implements TraceRepository { @Override public void add(Map map) { - Optional host = getFromHeaders("host", map); String path = (String) map.getOrDefault("path", ""); - if (host.isPresent() && !isInExclusionList(path)) { + if (!isInExclusionList(path)) { traces.add(new Trace(new Date(), map)); } } - - private Optional getFromHeaders(String header, Map map) { - Map headers = (Map) map.get("headers"); - if (headers != null) { - Map request = (Map) headers.get("request"); - if (request != null) { - return Optional.ofNullable((String) request.get(header)); - } - } - return Optional.empty(); - } } diff --git a/webwolf/src/main/java/org/owasp/webwolf/user/UserForm.java b/webwolf/src/main/java/org/owasp/webwolf/user/UserForm.java index 7e9d82a82..bb983126e 100644 --- a/webwolf/src/main/java/org/owasp/webwolf/user/UserForm.java +++ b/webwolf/src/main/java/org/owasp/webwolf/user/UserForm.java @@ -15,7 +15,7 @@ import javax.validation.constraints.Size; public class UserForm { @NotNull - @Size(min=6, max=20) + @Size(min=6, max=40) private String username; @NotNull @Size(min=6, max=10) diff --git a/webwolf/src/main/java/org/owasp/webwolf/user/WebGoatUserCookie.java b/webwolf/src/main/java/org/owasp/webwolf/user/WebGoatUserCookie.java deleted file mode 100644 index 618d6df25..000000000 --- a/webwolf/src/main/java/org/owasp/webwolf/user/WebGoatUserCookie.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.owasp.webwolf.user; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.springframework.data.annotation.Id; - -import java.io.Serializable; - -/** - * @author nbaars - * @since 8/20/17. - */ -@Getter -@NoArgsConstructor -@AllArgsConstructor -public class WebGoatUserCookie implements Serializable { - - @Id - private String username; - private String cookie; -} diff --git a/webwolf/src/main/resources/application.properties b/webwolf/src/main/resources/application-webwolf.properties similarity index 98% rename from webwolf/src/main/resources/application.properties rename to webwolf/src/main/resources/application-webwolf.properties index 981ce87aa..cb3c0f617 100644 --- a/webwolf/src/main/resources/application.properties +++ b/webwolf/src/main/resources/application-webwolf.properties @@ -10,6 +10,7 @@ spring.datasource.url=jdbc:hsqldb:hsql://${WEBGOAT_HOST:127.0.0.1}:${WEBGOAT_HSQ spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.HSQLDialect spring.jpa.hibernate.ddl-auto=update spring.messages.basename=i18n/messages +spring.jmx.enabled=false logging.level.org.springframework=INFO logging.level.org.springframework.boot.devtools=WARN From 2283f945a97a9875867dcf8c228cd659b77929db Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Sun, 25 Aug 2019 17:53:36 +0200 Subject: [PATCH 042/119] Fix failing configuration --- .../src/main/java/org/owasp/webgoat/WebGoat.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java b/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java index 131c482ab..21838d192 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java @@ -37,16 +37,16 @@ import org.owasp.webgoat.session.UserSessionData; import org.owasp.webgoat.session.WebSession; import org.owasp.webgoat.session.WebgoatContext; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.ScopedProxyMode; import org.springframework.web.client.RestTemplate; import java.io.File; -@Configuration +@SpringBootApplication public class WebGoat { @Bean(name = "pluginTargetDirectory") From 75a174ff7bb9512357b21a49aa278e2f95c21125 Mon Sep 17 00:00:00 2001 From: Jeffrey Wagner Date: Fri, 6 Sep 2019 21:12:55 -0400 Subject: [PATCH 043/119] Fixed description and grammer --- .../SqlInjection_introduction_content8.adoc | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_introduction_content8.adoc b/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_introduction_content8.adoc index 9903db79d..a9be7fce0 100644 --- a/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_introduction_content8.adoc +++ b/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_introduction_content8.adoc @@ -1,26 +1,26 @@ == Compromising confidentiality with String SQL injection -If a system is vulnerable to SQL injections it is also easy to compromise aspects of the CIA triad _(if you are unfamiliar with the CIA triad check out the CIA triad lesson in the general category)_. -In the following three lessons, you will learn how to use simple SQL injection attacks to compromise each of the three. Per example by using _SQL string injections_ or _query chaining_. +If a system is vulnerable to SQL injections, aspets of that system's CIA triad can be easily compromoised _(if you are unfamiliar with the CIA triad, check out the CIA triad lesson in the general category)_. +In the following three lessons you will learn how to compromise each aspect of the CIA triad using teachniques like _SQL string injections_ or _query chaining_. -This lesson, we will take a look at *confidentiality*. -Confidentiality can easily be compromised if an attacker uses SQL injection to read sensitive data from the database. For example reading credit card numbers or passwords. +In this lesson we will look at *confidentiality*. +Confidentiality can be easily compromised by an attacker using SQL injection to read sensitive data like credit card numbers from a database. === What is String SQL injection? -If queries are build dynamically in the application by concatenating strings to it, this makes it very susceptible to String SQL injection. + -If the input takes a string and that one gets inserted into the query as a string parameter, then you can easily manipulate the build query by using quotation marks to form the string to your specific needs. -You could per example end the string parameter with it and input your own SQL after that. +If queries are built dynamically in the application by concatenating strings to it, this makes it very susceptible to String SQL injection. + +If the input takes a string that gets inserted into a query as a string parameter, then you can easily manipulate the build query using quotation marks to form the string to your specific needs. +For example, you could end the string parameter with quotation marks and input your own SQL after that. === It is your turn! You are an employee named John *Smith* working for a big company. -The company has an internal system that allows all employees to see their own internal data, like the department they work in and their salary. +The company has an internal system that allows all employees to see their own internal data - like the department they work in and their salary. The system requires the employees to use a unique _authentication TAN_ to view their data. + Your current TAN is *3SL99A*. -Since you always have the urge to be the most earning employee you want to exploit the system and instead of viewing your own internal data _take a look at the data of all your colleagues_ to check their current salaries. +Since you always have the urge to be the most earning employee, you want to exploit the system and instead of viewing your own internal data, _ you want to take a look at the data of all your colleagues_ to check their current salaries. -Use the form below and try to retrieve all the employee data from the *employees* table. You should not need to know any specific names or TANs to get the information you need. + -You already found out that the query performing your request looks like that: +Use the form below and try to retrieve all employee data from the *employees* table. You should not need to know any specific names or TANs to get the information you need. + +You already found out that the query performing your request looks like this: ------------------------------------------------------------ "SELECT * FROM employees WHERE last_name = '" + name + "' AND auth_tan = '" + auth_tan + "'; ------------------------------------------------------------- \ No newline at end of file +------------------------------------------------------------ From 0982bd982c2ad8a827da2abdb97c630117aea62a Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Sun, 8 Sep 2019 18:52:12 +0200 Subject: [PATCH 044/119] Review comments processed: - Ports can now be changed - User is now a default user making it easier to login and look around after a failure --- .../org/owasp/webgoat/IntegrationTest.java | 60 +++++++++++++------ 1 file changed, 41 insertions(+), 19 deletions(-) diff --git a/webgoat-integration-tests/src/test/java/org/owasp/webgoat/IntegrationTest.java b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/IntegrationTest.java index f26dec4f3..6d41a6b34 100644 --- a/webgoat-integration-tests/src/test/java/org/owasp/webgoat/IntegrationTest.java +++ b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/IntegrationTest.java @@ -17,10 +17,15 @@ import java.net.ServerSocket; import java.util.Map; import java.util.UUID; +import static io.restassured.RestAssured.given; + public abstract class IntegrationTest { - private static String WEBGOAT_URL = "http://localhost:8080/WebGoat/"; - private static String WEBWOLF_URL = "http://localhost:9090/"; + protected static int WG_PORT = 8080; + protected static int WW_PORT = 9090; + private static String WEBGOAT_URL = "http://127.0.0.1:" + WG_PORT + "/WebGoat/"; + private static String WEBWOLF_URL = "http://127.0.0.1:" + WW_PORT + "/"; + //This also allows to test the application with HTTPS when outside testing option is used protected static RestAssuredConfig restConfig = RestAssuredConfig.newConfig().sslConfig(new SSLConfig().relaxedHTTPSValidation()); @@ -38,23 +43,19 @@ public abstract class IntegrationTest { public static void beforeAll() { if (!started) { started = true; - if (!areAlreadyRunning()) { + if (!isAlreadyRunning()) { SpringApplicationBuilder wgs = new SpringApplicationBuilder(StartWebGoat.class) - .properties(Map.of("spring.config.name", "application-webgoat")); + .properties(Map.of("spring.config.name", "application-webgoat", "WEBGOAT_PORT", WG_PORT)); wgs.run(); SpringApplicationBuilder wws = new SpringApplicationBuilder(WebWolf.class) - .properties(Map.of("spring.config.name", "application-webwolf")); + .properties(Map.of("spring.config.name", "application-webwolf", "WEBWOLF_PORT", WW_PORT)); wws.run(); } } } - private static boolean areAlreadyRunning() { - return checkIfServerIsRunnningOn(9090) && checkIfServerIsRunnningOn(8080); - } - - private static boolean checkIfServerIsRunnningOn(int port) { - try (var ignored = new ServerSocket(port)) { + private static boolean isAlreadyRunning() { + try (var ignored = new ServerSocket(WG_PORT)) { return false; } catch (IOException e) { return true; @@ -75,19 +76,40 @@ public abstract class IntegrationTest { @Before public void login() { - webGoatCookie = RestAssured.given() + String location = given() .when() .config(restConfig) .formParam("username", webgoatUser) .formParam("password", "password") - .formParam("matchingPassword", "password") - .formParam("agree", "agree") - .post(url("register.mvc")) - .then() + .post(url("login")).then() .cookie("JSESSIONID") .statusCode(302) - .extract() - .cookie("JSESSIONID"); + .extract().header("Location"); + if (location.endsWith("?error")) { + webGoatCookie = RestAssured.given() + .when() + .config(restConfig) + .formParam("username", webgoatUser) + .formParam("password", "password") + .formParam("matchingPassword", "password") + .formParam("agree", "agree") + .post(url("register.mvc")) + .then() + .cookie("JSESSIONID") + .statusCode(302) + .extract() + .cookie("JSESSIONID"); + } else { + webGoatCookie = given() + .when() + .config(restConfig) + .formParam("username", webgoatUser) + .formParam("password", "password") + .post(url("login")).then() + .cookie("JSESSIONID") + .statusCode(302) + .extract().cookie("JSESSIONID"); + } webWolfCookie = RestAssured.given() .when() @@ -107,7 +129,7 @@ public abstract class IntegrationTest { RestAssured.given() .when() .config(restConfig) - .get(WEBGOAT_URL + "logout") + .get(url("logout")) .then() .statusCode(200); } From bf52e7a99229d12f6ea9dcbabe59902d41670e69 Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Mon, 9 Sep 2019 11:37:26 +0200 Subject: [PATCH 045/119] Fixed checking of server already running --- .../java/org/owasp/webgoat/IntegrationTest.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/webgoat-integration-tests/src/test/java/org/owasp/webgoat/IntegrationTest.java b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/IntegrationTest.java index 6d41a6b34..9114fcad1 100644 --- a/webgoat-integration-tests/src/test/java/org/owasp/webgoat/IntegrationTest.java +++ b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/IntegrationTest.java @@ -13,7 +13,7 @@ import org.owasp.webwolf.WebWolf; import org.springframework.boot.builder.SpringApplicationBuilder; import java.io.IOException; -import java.net.ServerSocket; +import java.net.Socket; import java.util.Map; import java.util.UUID; @@ -43,10 +43,12 @@ public abstract class IntegrationTest { public static void beforeAll() { if (!started) { started = true; - if (!isAlreadyRunning()) { + if (!isAlreadyRunning(WG_PORT)) { SpringApplicationBuilder wgs = new SpringApplicationBuilder(StartWebGoat.class) .properties(Map.of("spring.config.name", "application-webgoat", "WEBGOAT_PORT", WG_PORT)); wgs.run(); + } + if (!isAlreadyRunning(WW_PORT)) { SpringApplicationBuilder wws = new SpringApplicationBuilder(WebWolf.class) .properties(Map.of("spring.config.name", "application-webwolf", "WEBWOLF_PORT", WW_PORT)); wws.run(); @@ -54,11 +56,11 @@ public abstract class IntegrationTest { } } - private static boolean isAlreadyRunning() { - try (var ignored = new ServerSocket(WG_PORT)) { - return false; - } catch (IOException e) { + private static boolean isAlreadyRunning(int port) { + try (var ignored = new Socket("127.0.0.1", port)) { return true; + } catch (IOException e) { + return false; } } From aec051a9f12f97a444833461a76220f6ee18801c Mon Sep 17 00:00:00 2001 From: ephemeralwaves Date: Fri, 6 Sep 2019 12:05:50 -0400 Subject: [PATCH 046/119] Fixed minor spelling mistake --- .../lessonPlans/en/SqlInjection_introduction_content7.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_introduction_content7.adoc b/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_introduction_content7.adoc index 13095e8f0..c6275765e 100644 --- a/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_introduction_content7.adoc +++ b/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_introduction_content7.adoc @@ -19,4 +19,4 @@ === Not all databases are equal (SQL Server) * Command shell: `master.dbo.xp_cmdshell 'cmd.exe dir c:'` -* Reqistry commands: `xp_regread`, `xp_regdeletekey`, … \ No newline at end of file +* Registry commands: `xp_regread`, `xp_regdeletekey`, … From f7c8a271aa5309b3c990975c89e5b5312072690b Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Mon, 9 Sep 2019 13:55:24 +0200 Subject: [PATCH 047/119] Fixed small typos --- .../lessonPlans/en/SqlInjection_introduction_content8.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_introduction_content8.adoc b/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_introduction_content8.adoc index a9be7fce0..4ae9d690c 100644 --- a/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_introduction_content8.adoc +++ b/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_introduction_content8.adoc @@ -1,6 +1,6 @@ == Compromising confidentiality with String SQL injection -If a system is vulnerable to SQL injections, aspets of that system's CIA triad can be easily compromoised _(if you are unfamiliar with the CIA triad, check out the CIA triad lesson in the general category)_. -In the following three lessons you will learn how to compromise each aspect of the CIA triad using teachniques like _SQL string injections_ or _query chaining_. +If a system is vulnerable to SQL injections, aspects of that system's CIA triad can be easily compromised _(if you are unfamiliar with the CIA triad, check out the CIA triad lesson in the general category)_. +In the following three lessons you will learn how to compromise each aspect of the CIA triad using techniques like _SQL string injections_ or _query chaining_. In this lesson we will look at *confidentiality*. Confidentiality can be easily compromised by an attacker using SQL injection to read sensitive data like credit card numbers from a database. From 43c25dc3bb321b2acd582df837c696aabe386cbb Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Tue, 10 Sep 2019 13:53:30 +0200 Subject: [PATCH 048/119] Modified PR to reflect coding style --- .../org/owasp/webwolf/user/UserService.java | 5 ++- .../owasp/webwolf/user/UserServiceTest.java | 39 ++++++----------- .../owasp/webwolf/user/UserValidatorTest.java | 42 ++++++++----------- 3 files changed, 33 insertions(+), 53 deletions(-) diff --git a/webwolf/src/main/java/org/owasp/webwolf/user/UserService.java b/webwolf/src/main/java/org/owasp/webwolf/user/UserService.java index 5acc52f92..b8cd0c9c3 100644 --- a/webwolf/src/main/java/org/owasp/webwolf/user/UserService.java +++ b/webwolf/src/main/java/org/owasp/webwolf/user/UserService.java @@ -14,9 +14,12 @@ import org.springframework.stereotype.Service; @Service public class UserService implements UserDetailsService { - @Autowired private UserRepository userRepository; + public UserService(UserRepository userRepository) { + this.userRepository = userRepository; + } + @Override public WebGoatUser loadUserByUsername(final String username) throws UsernameNotFoundException { WebGoatUser webGoatUser = userRepository.findByUsername(username); diff --git a/webwolf/src/test/java/org/owasp/webwolf/user/UserServiceTest.java b/webwolf/src/test/java/org/owasp/webwolf/user/UserServiceTest.java index 3d611c30a..e05048841 100644 --- a/webwolf/src/test/java/org/owasp/webwolf/user/UserServiceTest.java +++ b/webwolf/src/test/java/org/owasp/webwolf/user/UserServiceTest.java @@ -1,8 +1,6 @@ package org.owasp.webwolf.user; - -import org.junit.Assert; -import org.junit.Before; +import org.assertj.core.api.Assertions; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; @@ -12,10 +10,6 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import static org.mockito.Mockito.*; -/** - * @author rjclancy - * @since 3/26/19. - */ @RunWith(SpringJUnit4ClassRunner.class) public class UserServiceTest { @@ -23,45 +17,36 @@ public class UserServiceTest { private UserRepository mockUserRepository; @InjectMocks - private UserService cut; + private UserService sut; @Test public void testLoadUserByUsername(){ - // setup - final String username = "guest"; - final String password = "123"; - + var username = "guest"; + var password = "123"; WebGoatUser user = new WebGoatUser(username, password); when(mockUserRepository.findByUsername(username)).thenReturn(user); - // execute - final WebGoatUser webGoatUser = cut.loadUserByUsername(username); + var webGoatUser = sut.loadUserByUsername(username); - // verify - Assert.assertEquals(username, webGoatUser.getUsername()); - Assert.assertEquals(password, webGoatUser.getPassword()); + Assertions.assertThat(username).isEqualTo(webGoatUser.getUsername()); + Assertions.assertThat(password).isEqualTo(webGoatUser.getPassword()); } @Test(expected = UsernameNotFoundException.class) public void testLoadUserByUsername_NULL(){ - // setup - final String username = "guest"; + var username = "guest"; when(mockUserRepository.findByUsername(username)).thenReturn(null); - // execute - cut.loadUserByUsername(username); + sut.loadUserByUsername(username); } @Test public void testAddUser(){ - // setup - final String username = "guest"; - final String password = "guest"; + var username = "guest"; + var password = "guest"; - // execute - cut.addUser(username, password); + sut.addUser(username, password); - // verify verify(mockUserRepository, times(1)).save(any(WebGoatUser.class)); } } diff --git a/webwolf/src/test/java/org/owasp/webwolf/user/UserValidatorTest.java b/webwolf/src/test/java/org/owasp/webwolf/user/UserValidatorTest.java index 60e614a58..5c160f5e1 100644 --- a/webwolf/src/test/java/org/owasp/webwolf/user/UserValidatorTest.java +++ b/webwolf/src/test/java/org/owasp/webwolf/user/UserValidatorTest.java @@ -1,5 +1,6 @@ package org.owasp.webwolf.user; +import org.assertj.core.api.Assertions; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -12,10 +13,6 @@ import static junit.framework.TestCase.assertTrue; import static org.junit.Assert.assertFalse; import static org.mockito.Mockito.when; -/** - * @author rjclancy - * @since 3/26/19. - */ @RunWith(SpringJUnit4ClassRunner.class) public class UserValidatorTest { @@ -26,8 +23,8 @@ public class UserValidatorTest { private UserValidator userValidator; @Test - public void testValidUserForm() { - UserForm validUserForm = new UserForm(); + public void validUserFormShouldNotHaveErrors() { + var validUserForm = new UserForm(); validUserForm.setUsername("guest"); validUserForm.setMatchingPassword("123"); validUserForm.setPassword("123"); @@ -35,12 +32,12 @@ public class UserValidatorTest { userValidator.validate(validUserForm, errors); - assertFalse(errors.hasErrors()); + Assertions.assertThat(errors.hasErrors()).isFalse(); } @Test - public void testValidUserForm_INVALID_PASSWORD() { - UserForm validUserForm = new UserForm(); + public void whenPasswordDoNotMatchShouldFail() { + var validUserForm = new UserForm(); validUserForm.setUsername("guest"); validUserForm.setMatchingPassword("123"); validUserForm.setPassword("124"); @@ -48,38 +45,33 @@ public class UserValidatorTest { userValidator.validate(validUserForm, errors); - assertTrue(errors.hasErrors()); + Assertions.assertThat(errors.hasErrors()).isTrue(); } @Test - public void testValidUserForm_DUPLICATE_USER() { - // setup - final String username = "guest"; - final String password = "123"; - - UserForm validUserForm = new UserForm(); + public void registerExistingUserAgainShouldFail() { + var username = "guest"; + var password = "123"; + var validUserForm = new UserForm(); validUserForm.setUsername(username); validUserForm.setMatchingPassword(password); validUserForm.setPassword("124"); BindException errors = new BindException(validUserForm, "validUserForm"); - - WebGoatUser webGoatUser = new WebGoatUser(username, password); + var webGoatUser = new WebGoatUser(username, password); when(mockUserRepository.findByUsername(validUserForm.getUsername())).thenReturn(webGoatUser); - // execute userValidator.validate(validUserForm, errors); - // verify - assertTrue(errors.hasErrors()); + Assertions.assertThat(errors.hasErrors()).isTrue(); } @Test - public void testSupports(){ - Assert.assertTrue(userValidator.supports(UserForm.class)); + public void testSupports() { + Assertions.assertThat(userValidator.supports(UserForm.class)).isTrue(); } @Test - public void testSupports_false(){ - Assert.assertFalse(userValidator.supports(UserService.class)); + public void testSupports_false() { + Assertions.assertThat(userValidator.supports(UserService.class)).isFalse(); } } \ No newline at end of file From fb2e11fe11fd0ede4e0943518223ef116c6ea69a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Zubcevic?= Date: Tue, 10 Sep 2019 09:00:13 +0200 Subject: [PATCH 049/119] fix for complete progress of sql mitigations and integration test --- .../webgoat/SqlInjectionMitigationTest.java | 16 +++++++++++++++- .../plugin/mitigation/SqlInjectionLesson10a.java | 2 +- .../plugin/mitigation/SqlInjectionLesson10b.java | 2 +- .../plugin/mitigation/SqlInjectionLesson12a.java | 2 +- .../resources/html/SqlInjectionMitigations.html | 2 +- 5 files changed, 19 insertions(+), 5 deletions(-) diff --git a/webgoat-integration-tests/src/test/java/org/owasp/webgoat/SqlInjectionMitigationTest.java b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/SqlInjectionMitigationTest.java index d51af280c..d73f9128c 100644 --- a/webgoat-integration-tests/src/test/java/org/owasp/webgoat/SqlInjectionMitigationTest.java +++ b/webgoat-integration-tests/src/test/java/org/owasp/webgoat/SqlInjectionMitigationTest.java @@ -2,6 +2,9 @@ package org.owasp.webgoat; import org.junit.Test; +import io.restassured.RestAssured; +import io.restassured.http.ContentType; + import java.util.HashMap; import java.util.Map; @@ -33,7 +36,18 @@ public class SqlInjectionMitigationTest extends IntegrationTest { "}"); checkAssignment(url("/WebGoat/SqlInjectionMitigations/attack10b"), params, true); - //checkResults(webGoatCookie, webgoatURL, "/SqlInjectionMitigations/"); + RestAssured.given() + .when().config(restConfig).cookie("JSESSIONID", getWebGoatCookie()) + .contentType(ContentType.JSON) + .get(url("/WebGoat/SqlInjectionMitigations/servers?column=(case when (true) then hostname else id end)")) + .then() + .statusCode(200); + + params.clear(); + params.put("ip", "104.130.219.202"); + checkAssignment(url("/WebGoat/SqlInjectionMitigations/attack12a"), params, true); + + checkResults("/SqlInjectionMitigations/"); } } diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/mitigation/SqlInjectionLesson10a.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/mitigation/SqlInjectionLesson10a.java index 1c531e2df..13e3c65d8 100644 --- a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/mitigation/SqlInjectionLesson10a.java +++ b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/mitigation/SqlInjectionLesson10a.java @@ -13,7 +13,7 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; -@AssignmentPath("SqlInjectionMitigations/attack10a") +@AssignmentPath("/SqlInjectionMitigations/attack10a") @Slf4j @AssignmentHints(value = {"SqlStringInjectionHint-mitigation-10a-1", "SqlStringInjectionHint-mitigation-10a-10a2"}) public class SqlInjectionLesson10a extends AssignmentEndpoint { diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/mitigation/SqlInjectionLesson10b.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/mitigation/SqlInjectionLesson10b.java index b47c7580c..3467ac521 100644 --- a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/mitigation/SqlInjectionLesson10b.java +++ b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/mitigation/SqlInjectionLesson10b.java @@ -18,7 +18,7 @@ import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; -@AssignmentPath("SqlInjectionMitigations/attack10b") +@AssignmentPath("/SqlInjectionMitigations/attack10b") @AssignmentHints(value = {"SqlStringInjectionHint-mitigation-10b-1", "SqlStringInjectionHint-mitigation-10b-2", "SqlStringInjectionHint-mitigation-10b-3", "SqlStringInjectionHint-mitigation-10b-4", "SqlStringInjectionHint-mitigation-10b-5"}) public class SqlInjectionLesson10b extends AssignmentEndpoint { diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/mitigation/SqlInjectionLesson12a.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/mitigation/SqlInjectionLesson12a.java index d99be9505..591576fde 100644 --- a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/mitigation/SqlInjectionLesson12a.java +++ b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/mitigation/SqlInjectionLesson12a.java @@ -20,7 +20,7 @@ import java.sql.*; * @author nbaars * @since 6/13/17. */ -@AssignmentPath("SqlInjectionMitigations/attack12a") +@AssignmentPath("/SqlInjectionMitigations/attack12a") @AssignmentHints(value = {"SqlStringInjectionHint-mitigation-12a-1", "SqlStringInjectionHint-mitigation-12a-2", "SqlStringInjectionHint-mitigation-12a-3", "SqlStringInjectionHint-mitigation-12a-4"}) @Slf4j public class SqlInjectionLesson12a extends AssignmentEndpoint { diff --git a/webgoat-lessons/sql-injection/src/main/resources/html/SqlInjectionMitigations.html b/webgoat-lessons/sql-injection/src/main/resources/html/SqlInjectionMitigations.html index 92cc1eca7..577e58996 100644 --- a/webgoat-lessons/sql-injection/src/main/resources/html/SqlInjectionMitigations.html +++ b/webgoat-lessons/sql-injection/src/main/resources/html/SqlInjectionMitigations.html @@ -128,7 +128,7 @@
-
+
IP address webgoat-prd server:
From 361249c666af225db18cd713f2e2a5bae3bb7bdb Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Thu, 12 Sep 2019 17:22:03 +0200 Subject: [PATCH 050/119] First attempt at moving to Spring Boot 2 --- pom.xml | 2 +- webgoat-container/pom.xml | 3 +- .../webgoat/AsciiDoctorTemplateResolver.java | 117 ++++++++---------- .../owasp/webgoat/LessonTemplateResolver.java | 72 +++++------ .../org/owasp/webgoat/MvcConfiguration.java | 50 ++++---- .../main/java/org/owasp/webgoat/WebGoat.java | 14 --- .../org/owasp/webgoat/WebSecurityConfig.java | 14 +++ .../assignments/AssignmentEndpoint.java | 8 +- .../webgoat/assignments/AssignmentPath.java | 14 ++- .../owasp/webgoat/assignments/Endpoint.java | 41 ------ .../org/owasp/webgoat/lessons/Assignment.java | 4 +- .../plugins/PluginEndpointPublisher.java | 66 ---------- .../owasp/webgoat/plugins/PluginResource.java | 14 --- .../owasp/webgoat/plugins/PluginsLoader.java | 42 +++++-- .../service/LessonProgressService.java | 2 +- .../resources/application-webgoat.properties | 8 +- .../main/resources/templates/main_new.html | 17 ++- .../org/owasp/webgoat/plugins/LessonTest.java | 2 +- .../service/LessonProgressServiceTest.java | 4 +- .../webgoat/session/LessonTrackerTest.java | 8 +- .../java/org/owasp/webgoat/plugin/Flag.java | 11 +- .../plugin/challenge1/Assignment1.java | 1 - .../org/owasp/webgoat/plugin/Salaries.java | 11 +- .../org/owasp/webgoat/plugin/CSRFGetFlag.java | 13 +- .../webgoat/plugin/HttpBasicsLesson.java | 14 +-- .../owasp/webgoat/plugin/HttpBasicsQuiz.java | 45 ++++--- .../webgoat/plugin/IDORViewOwnProfile.java | 12 +- .../java/org/owasp/webgoat/plugin/Users.java | 11 +- .../java/org/owasp/webgoat/plugin/Ping.java | 11 +- webgoat-server/pom.xml | 13 +- .../owasp/webgoat/HSQLDBDatabaseConfig.java | 2 +- .../java/org/owasp/webgoat/StartWebGoat.java | 8 +- webwolf/pom.xml | 15 +-- 33 files changed, 271 insertions(+), 398 deletions(-) delete mode 100644 webgoat-container/src/main/java/org/owasp/webgoat/assignments/Endpoint.java delete mode 100644 webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginEndpointPublisher.java diff --git a/pom.xml b/pom.xml index 7036fabab..9023349dc 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ org.springframework.boot spring-boot-starter-parent - 1.5.21.RELEASE + 2.1.8.RELEASE diff --git a/webgoat-container/pom.xml b/webgoat-container/pom.xml index cf324686b..3067eca8b 100644 --- a/webgoat-container/pom.xml +++ b/webgoat-container/pom.xml @@ -121,8 +121,7 @@ org.thymeleaf.extras - thymeleaf-extras-springsecurity4 - 2.1.2.RELEASE + thymeleaf-extras-springsecurity5 org.hsqldb diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/AsciiDoctorTemplateResolver.java b/webgoat-container/src/main/java/org/owasp/webgoat/AsciiDoctorTemplateResolver.java index e5a4c7da9..8fcaf5635 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/AsciiDoctorTemplateResolver.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/AsciiDoctorTemplateResolver.java @@ -39,12 +39,15 @@ import org.owasp.webgoat.asciidoc.WebGoatVersionMacro; import org.owasp.webgoat.asciidoc.WebWolfMacro; import org.owasp.webgoat.asciidoc.WebWolfRootMacro; import org.owasp.webgoat.i18n.Language; -import org.thymeleaf.TemplateProcessingParameters; -import org.thymeleaf.resourceresolver.IResourceResolver; -import org.thymeleaf.templateresolver.TemplateResolver; +import org.thymeleaf.IEngineConfiguration; +import org.thymeleaf.templateresolver.FileTemplateResolver; +import org.thymeleaf.templateresource.ITemplateResource; +import org.thymeleaf.templateresource.StringTemplateResource; -import java.io.*; -import java.nio.charset.StandardCharsets; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringWriter; import java.util.Map; import static org.asciidoctor.Asciidoctor.Factory.create; @@ -57,7 +60,7 @@ import static org.asciidoctor.Asciidoctor.Factory.create; * */ @Slf4j -public class AsciiDoctorTemplateResolver extends TemplateResolver { +public class AsciiDoctorTemplateResolver extends FileTemplateResolver { private static final Asciidoctor asciidoctor = create(); private static final String PREFIX = "doc:"; @@ -65,72 +68,56 @@ public class AsciiDoctorTemplateResolver extends TemplateResolver { public AsciiDoctorTemplateResolver(Language language) { this.language = language; - - setResourceResolver(new AdocResourceResolver()); setResolvablePatterns(Sets.newHashSet(PREFIX + "*")); } @Override - protected String computeResourceName(TemplateProcessingParameters params) { - String templateName = params.getTemplateName(); - return templateName.substring(PREFIX.length()); - } - - private class AdocResourceResolver implements IResourceResolver { - - @Override - public InputStream getResourceAsStream(TemplateProcessingParameters params, String resourceName) { - try (InputStream is = readInputStreamOrFallbackToEnglish(resourceName, language)) { - if (is == null) { - log.warn("Resource name: {} not found, did you add the adoc file?", resourceName); - return new ByteArrayInputStream(new byte[0]); - } else { - StringWriter writer = new StringWriter(); - JavaExtensionRegistry extensionRegistry = asciidoctor.javaExtensionRegistry(); - extensionRegistry.inlineMacro("webWolfLink", WebWolfMacro.class); - extensionRegistry.inlineMacro("webWolfRootLink", WebWolfRootMacro.class); - extensionRegistry.inlineMacro("webGoatVersion", WebGoatVersionMacro.class); - - asciidoctor.convert(new InputStreamReader(is), writer, createAttributes()); - return new ByteArrayInputStream(writer.getBuffer().toString().getBytes(StandardCharsets.UTF_8)); - } - } catch (IOException e) { - //no html yet - return new ByteArrayInputStream(new byte[0]); - } - } - - /** - * The resource name is for example HttpBasics_content1.adoc. This is always located in the following directory: - * plugin/HttpBasics/lessonPlans/en/HttpBasics_content1.adoc - */ - private String computeResourceName(String resourceName, String language) { - return String.format("lessonPlans/%s/%s", language, resourceName); - } - - private InputStream readInputStreamOrFallbackToEnglish(String resourceName, Language language) { - InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(computeResourceName(resourceName, language.getLocale().getLanguage())); + protected ITemplateResource computeTemplateResource(IEngineConfiguration configuration, String ownerTemplate, String template, String resourceName, String characterEncoding, Map templateResolutionAttributes) { + var templateName = resourceName.substring(PREFIX.length()); + try (InputStream is = readInputStreamOrFallbackToEnglish(templateName, language)) { if (is == null) { - is = Thread.currentThread().getContextClassLoader().getResourceAsStream(computeResourceName(resourceName, "en")); + log.warn("Resource name: {} not found, did you add the adoc file?", templateName); + return new StringTemplateResource(""); + } else { + StringWriter writer = new StringWriter(); + JavaExtensionRegistry extensionRegistry = asciidoctor.javaExtensionRegistry(); + extensionRegistry.inlineMacro("webWolfLink", WebWolfMacro.class); + extensionRegistry.inlineMacro("webWolfRootLink", WebWolfRootMacro.class); + extensionRegistry.inlineMacro("webGoatVersion", WebGoatVersionMacro.class); + + asciidoctor.convert(new InputStreamReader(is), writer, createAttributes()); + return new StringTemplateResource(writer.getBuffer().toString()); } - return is; - } - - private Map createAttributes() { - Map attributes = Maps.newHashMap(); - attributes.put("source-highlighter", "coderay"); - attributes.put("backend", "xhtml"); - - Map options = Maps.newHashMap(); - options.put("attributes", attributes); - - return options; - } - - @Override - public String getName() { - return "adocResourceResolver"; + } catch (IOException e) { + //no html yet + return new StringTemplateResource(""); } } + /** + * The resource name is for example HttpBasics_content1.adoc. This is always located in the following directory: + * plugin/HttpBasics/lessonPlans/en/HttpBasics_content1.adoc + */ + private String computeResourceName(String resourceName, String language) { + return String.format("lessonPlans/%s/%s", language, resourceName); + } + + private InputStream readInputStreamOrFallbackToEnglish(String resourceName, Language language) { + InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(computeResourceName(resourceName, language.getLocale().getLanguage())); + if (is == null) { + is = Thread.currentThread().getContextClassLoader().getResourceAsStream(computeResourceName(resourceName, "en")); + } + return is; + } + + private Map createAttributes() { + Map attributes = Maps.newHashMap(); + attributes.put("source-highlighter", "coderay"); + attributes.put("backend", "xhtml"); + + Map options = Maps.newHashMap(); + options.put("attributes", attributes); + + return options; + } } diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/LessonTemplateResolver.java b/webgoat-container/src/main/java/org/owasp/webgoat/LessonTemplateResolver.java index 14e983a81..c035c58a3 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/LessonTemplateResolver.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/LessonTemplateResolver.java @@ -1,47 +1,46 @@ /** - ************************************************************************************************* - * - * + * ************************************************************************************************ + *

+ *

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

* Copyright (c) 2002 - 20014 Bruce Mayhew - * + *

* This program is free software; you can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. - * + *

* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. - * + *

* You should have received a copy of the GNU General Public License along with this program; if * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. - * + *

* Getting Source ============== - * + *

* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software * projects. * * @author WebGoat - * @since October 28, 2003 * @version $Id: $Id + * @since October 28, 2003 */ package org.owasp.webgoat; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.google.common.io.ByteStreams; -import lombok.SneakyThrows; import org.springframework.core.io.ResourceLoader; -import org.thymeleaf.TemplateProcessingParameters; -import org.thymeleaf.resourceresolver.IResourceResolver; -import org.thymeleaf.templateresolver.TemplateResolver; +import org.thymeleaf.IEngineConfiguration; +import org.thymeleaf.templateresolver.FileTemplateResolver; +import org.thymeleaf.templateresource.ITemplateResource; +import org.thymeleaf.templateresource.StringTemplateResource; -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.InputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.Map; /** @@ -53,42 +52,29 @@ import java.util.Map; * * Thymeleaf will invoke this resolver based on the prefix and this implementation will resolve the html in the plugins directory */ -public class LessonTemplateResolver extends TemplateResolver { +public class LessonTemplateResolver extends FileTemplateResolver { private final static String PREFIX = "lesson:"; - private final File pluginTargetDirectory; private ResourceLoader resourceLoader; private Map resources = Maps.newHashMap(); - public LessonTemplateResolver(File pluginTargetDirectory, ResourceLoader resourceLoader) { - this.pluginTargetDirectory = pluginTargetDirectory; + public LessonTemplateResolver(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; - setResourceResolver(new LessonResourceResolver()); setResolvablePatterns(Sets.newHashSet(PREFIX + "*")); } @Override - protected String computeResourceName(TemplateProcessingParameters params) { - String templateName = params.getTemplateName(); - return templateName.substring(PREFIX.length()); - } - - private class LessonResourceResolver implements IResourceResolver { - - @Override - @SneakyThrows - public InputStream getResourceAsStream(TemplateProcessingParameters params, String resourceName) { - byte[] resource = resources.get(resourceName); - if (resource == null) { - resource = ByteStreams.toByteArray(resourceLoader.getResource("classpath:/html/" + resourceName + ".html").getInputStream()); - resources.put(resourceName, resource); + protected ITemplateResource computeTemplateResource(IEngineConfiguration configuration, String ownerTemplate, String template, String resourceName, String characterEncoding, Map templateResolutionAttributes) { + var templateName = resourceName.substring(PREFIX.length());; + byte[] resource = resources.get(templateName); + if (resource == null) { + try { + resource = ByteStreams.toByteArray(resourceLoader.getResource("classpath:/html/" + templateName + ".html").getInputStream()); + } catch (IOException e) { + e.printStackTrace(); } - return new ByteArrayInputStream(resource); - } - - @Override - public String getName() { - return "lessonResourceResolver"; + resources.put(resourceName, resource); } + return new StringTemplateResource(new String(resource, StandardCharsets.UTF_8)); } -} +} \ No newline at end of file diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/MvcConfiguration.java b/webgoat-container/src/main/java/org/owasp/webgoat/MvcConfiguration.java index e26aa0b5e..0e2aac9f6 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/MvcConfiguration.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/MvcConfiguration.java @@ -30,41 +30,38 @@ */ package org.owasp.webgoat; -import com.google.common.collect.Sets; import org.owasp.webgoat.i18n.Language; import org.owasp.webgoat.i18n.Messages; import org.owasp.webgoat.i18n.PluginMessages; import org.owasp.webgoat.session.LabelDebugger; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ResourceLoader; import org.springframework.web.servlet.LocaleResolver; +import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.i18n.SessionLocaleResolver; -import org.thymeleaf.extras.springsecurity4.dialect.SpringSecurityDialect; -import org.thymeleaf.spring4.SpringTemplateEngine; -import org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver; -import org.thymeleaf.templateresolver.TemplateResolver; +import org.thymeleaf.TemplateEngine; +import org.thymeleaf.extras.springsecurity5.dialect.SpringSecurityDialect; +import org.thymeleaf.spring5.SpringTemplateEngine; +import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver; +import org.thymeleaf.spring5.view.ThymeleafViewResolver; +import org.thymeleaf.templatemode.TemplateMode; +import org.thymeleaf.templateresolver.ITemplateResolver; -import java.io.File; +import java.util.Set; /** * Configuration for Spring MVC */ @Configuration -public class MvcConfiguration extends WebMvcConfigurerAdapter { +public class MvcConfiguration implements WebMvcConfigurer { private static final String UTF8 = "UTF-8"; - @Autowired - @Qualifier("pluginTargetDirectory") - private File pluginTargetDirectory; - @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/login").setViewName("login"); @@ -74,13 +71,21 @@ public class MvcConfiguration extends WebMvcConfigurerAdapter { //registry.addViewController("/list_users").setViewName("list_users"); } + @Bean + public ViewResolver viewResolver(SpringTemplateEngine thymeleafTemplateEngine) { + ThymeleafViewResolver resolver = new ThymeleafViewResolver(); + resolver.setTemplateEngine(thymeleafTemplateEngine); + resolver.setCharacterEncoding("UTF-8"); + return resolver; + } @Bean - public TemplateResolver springThymeleafTemplateResolver(ApplicationContext applicationContext) { + public ITemplateResolver springThymeleafTemplateResolver(ApplicationContext applicationContext) { SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver(); resolver.setPrefix("classpath:/templates/"); resolver.setSuffix(".html"); - resolver.setOrder(1); + resolver.setTemplateMode(TemplateMode.HTML); + resolver.setOrder(2); resolver.setCacheable(false); resolver.setCharacterEncoding(UTF8); resolver.setApplicationContext(applicationContext); @@ -89,8 +94,8 @@ public class MvcConfiguration extends WebMvcConfigurerAdapter { @Bean public LessonTemplateResolver lessonTemplateResolver(ResourceLoader resourceLoader) { - LessonTemplateResolver resolver = new LessonTemplateResolver(pluginTargetDirectory, resourceLoader); - resolver.setOrder(2); + LessonTemplateResolver resolver = new LessonTemplateResolver(resourceLoader); + resolver.setOrder(0); resolver.setCacheable(false); resolver.setCharacterEncoding(UTF8); return resolver; @@ -100,19 +105,20 @@ public class MvcConfiguration extends WebMvcConfigurerAdapter { public AsciiDoctorTemplateResolver asciiDoctorTemplateResolver(Language language) { AsciiDoctorTemplateResolver resolver = new AsciiDoctorTemplateResolver(language); resolver.setCacheable(false); - resolver.setOrder(3); + resolver.setOrder(1); resolver.setCharacterEncoding(UTF8); return resolver; } @Bean - public SpringTemplateEngine thymeleafTemplateEngine(TemplateResolver springThymeleafTemplateResolver, + public SpringTemplateEngine thymeleafTemplateEngine(ITemplateResolver springThymeleafTemplateResolver, LessonTemplateResolver lessonTemplateResolver, AsciiDoctorTemplateResolver asciiDoctorTemplateResolver) { SpringTemplateEngine engine = new SpringTemplateEngine(); + engine.setEnableSpringELCompiler(true); engine.addDialect(new SpringSecurityDialect()); engine.setTemplateResolvers( - Sets.newHashSet(springThymeleafTemplateResolver, lessonTemplateResolver, asciiDoctorTemplateResolver)); + Set.of(lessonTemplateResolver, asciiDoctorTemplateResolver, springThymeleafTemplateResolver)); return engine; } @@ -123,12 +129,10 @@ public class MvcConfiguration extends WebMvcConfigurerAdapter { */ @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { - registry.addResourceHandler("/plugin_lessons/**").addResourceLocations("file:///" + pluginTargetDirectory.toString() + "/"); registry.addResourceHandler("/images/**").addResourceLocations("classpath:/images/"); registry.addResourceHandler("/lesson_js/**").addResourceLocations("classpath:/js/"); registry.addResourceHandler("/lesson_css/**").addResourceLocations("classpath:/css/"); registry.addResourceHandler("/video/**").addResourceLocations("classpath:/video/"); - super.addResourceHandlers(registry); } @Bean diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java b/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java index 21838d192..dc0f8bb69 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java @@ -30,15 +30,11 @@ */ package org.owasp.webgoat; -import org.owasp.webgoat.plugins.PluginEndpointPublisher; -import org.owasp.webgoat.plugins.PluginsLoader; -import org.owasp.webgoat.session.Course; import org.owasp.webgoat.session.UserSessionData; import org.owasp.webgoat.session.WebSession; import org.owasp.webgoat.session.WebgoatContext; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.ScopedProxyMode; @@ -66,16 +62,6 @@ public class WebGoat { return new UserSessionData("test", "data"); } - @Bean - public PluginEndpointPublisher pluginEndpointPublisher(ApplicationContext applicationContext) { - return new PluginEndpointPublisher(applicationContext); - } - - @Bean - public Course course(PluginEndpointPublisher pluginEndpointPublisher) { - return new PluginsLoader(pluginEndpointPublisher).loadPlugins(); - } - @Bean public RestTemplate restTemplate() { return new RestTemplate(); diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/WebSecurityConfig.java b/webgoat-container/src/main/java/org/owasp/webgoat/WebSecurityConfig.java index b8b526af8..07ea29f1e 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/WebSecurityConfig.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/WebSecurityConfig.java @@ -35,6 +35,7 @@ import org.owasp.webgoat.users.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; @@ -42,6 +43,7 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.password.NoOpPasswordEncoder; /** * Security configuration for WebGoat. @@ -90,4 +92,16 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { public UserDetailsService userDetailsServiceBean() throws Exception { return userDetailsService; } + + @Override + @Bean + protected AuthenticationManager authenticationManager() throws Exception { + return super.authenticationManager(); + } + + @SuppressWarnings("deprecation") + @Bean + public NoOpPasswordEncoder passwordEncoder() { + return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance(); + } } \ No newline at end of file diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/assignments/AssignmentEndpoint.java b/webgoat-container/src/main/java/org/owasp/webgoat/assignments/AssignmentEndpoint.java index 3b02b6129..b316f40ee 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/assignments/AssignmentEndpoint.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/assignments/AssignmentEndpoint.java @@ -41,7 +41,8 @@ import org.springframework.beans.factory.annotation.Autowired; *

* Note: each subclass should declare this annotation otherwise the WebGoat framework cannot find your endpoint. */ -public abstract class AssignmentEndpoint extends Endpoint { +//TODO: rename to assignment +public abstract class AssignmentEndpoint { @Autowired private UserTrackerRepository userTrackerRepository; @@ -76,11 +77,6 @@ public abstract class AssignmentEndpoint extends Endpoint { return userSessionData; } - @Override - public final String getPath() { - return this.getClass().getAnnotationsByType(AssignmentPath.class)[0].value(); - } - /** * Convenience method for create a successful result: * diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/assignments/AssignmentPath.java b/webgoat-container/src/main/java/org/owasp/webgoat/assignments/AssignmentPath.java index 9147a1820..25336aa44 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/assignments/AssignmentPath.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/assignments/AssignmentPath.java @@ -1,5 +1,9 @@ package org.owasp.webgoat.assignments; +import org.springframework.core.annotation.AliasFor; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -10,7 +14,15 @@ import java.lang.annotation.Target; */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) +//@RequestMapping public @interface AssignmentPath { - String value(); + // @AliasFor(annotation = RequestMapping.class) + String[] path() default {}; + + // @AliasFor(annotation = RequestMapping.class) + RequestMethod[] method() default {}; + + // @AliasFor("path") + String value() default ""; } diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/assignments/Endpoint.java b/webgoat-container/src/main/java/org/owasp/webgoat/assignments/Endpoint.java deleted file mode 100644 index 746ac412d..000000000 --- a/webgoat-container/src/main/java/org/owasp/webgoat/assignments/Endpoint.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * This file is part of WebGoat, an Open Web Application Security Project utility. For details, - * please see http://www.owasp.org/ - *

- * Copyright (c) 2002 - 2017 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.assignments; - -import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint; - -public abstract class Endpoint implements MvcEndpoint { - - @Override - public final boolean isSensitive() { - return false; - } - - @Override - public final Class getEndpointType() { - return null; - } -} diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Assignment.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Assignment.java index d9b1f3470..7587436a9 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Assignment.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Assignment.java @@ -52,8 +52,8 @@ public class Assignment { //Hibernate } - public Assignment(String name, String path) { - this(name, path, Lists.newArrayList()); + public Assignment(String name) { + this(name, name, Lists.newArrayList()); } public Assignment(String name, String path, List hints) { diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginEndpointPublisher.java b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginEndpointPublisher.java deleted file mode 100644 index d3a2a333e..000000000 --- a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginEndpointPublisher.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.owasp.webgoat.plugins; - -import lombok.extern.slf4j.Slf4j; -import org.owasp.webgoat.assignments.Endpoint; -import org.springframework.beans.factory.annotation.Autowire; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.support.DefaultListableBeanFactory; -import org.springframework.beans.factory.support.RootBeanDefinition; -import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint; -import org.springframework.context.ApplicationContext; -import org.springframework.context.support.AbstractApplicationContext; - -import java.util.List; - -/** - * ************************************************************************************************ - * This file is part of WebGoat, an Open Web Application Security Project utility. For details, - * please see http://www.owasp.org/ - *

- * Copyright (c) 2002 - 20014 Bruce Mayhew - *

- * This program is free software; you can redistribute it and/or modify it under the terms of the - * GNU General Public License as published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - *

- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - *

- * You should have received a copy of the GNU General Public License along with this program; if - * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - *

- * Getting Source ============== - *

- * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software - * projects. - *

- * - * @author nbaars - * @version $Id: $Id - * @since October 16, 2016 - */ -@Slf4j -public class PluginEndpointPublisher { - - private AbstractApplicationContext applicationContext; - - public PluginEndpointPublisher(ApplicationContext applicationContext) { - this.applicationContext = (AbstractApplicationContext) applicationContext; - } - - public void publish(List> endpoints) { - endpoints.forEach(e -> publishEndpoint(e)); - } - - private void publishEndpoint(Class e) { - try { - BeanDefinition beanDefinition = new RootBeanDefinition(e, Autowire.BY_TYPE.value(), true); - DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getBeanFactory(); - beanFactory.registerBeanDefinition(beanDefinition.getBeanClassName(), beanDefinition); - } catch (Exception ex) { - log.error("Failed to register " + e.getSimpleName() + " as endpoint with Spring, skipping..."); - } - } -} diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginResource.java b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginResource.java index 172b7b965..1acdd6097 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginResource.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginResource.java @@ -3,19 +3,12 @@ package org.owasp.webgoat.plugins; import lombok.AllArgsConstructor; import lombok.Getter; import org.owasp.webgoat.assignments.AssignmentEndpoint; -import org.owasp.webgoat.assignments.Endpoint; import org.owasp.webgoat.lessons.NewLesson; import java.net.URL; import java.util.List; import java.util.stream.Collectors; -/** - * Plugin resource - * - * @author nbaars - * @since 3/4/17. - */ @AllArgsConstructor @Getter public class PluginResource { @@ -27,13 +20,6 @@ public class PluginResource { return classes.stream().filter(c -> c.getSuperclass() == NewLesson.class).collect(Collectors.toList()); } - public List> getEndpoints() { - return classes.stream(). - filter(c -> c.getSuperclass() == AssignmentEndpoint.class || c.getSuperclass() == Endpoint.class). - map(c -> (Class) c). - collect(Collectors.toList()); - } - public List> getAssignments(Class lesson) { return classes.stream(). filter(c -> c.getSuperclass() == AssignmentEndpoint.class). diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginsLoader.java b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginsLoader.java index 28437e786..4820453e6 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginsLoader.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginsLoader.java @@ -8,14 +8,22 @@ import lombok.extern.slf4j.Slf4j; import org.owasp.webgoat.assignments.AssignmentEndpoint; import org.owasp.webgoat.assignments.AssignmentHints; import org.owasp.webgoat.assignments.AssignmentPath; +import org.owasp.webgoat.assignments.AttackResult; import org.owasp.webgoat.lessons.AbstractLesson; import org.owasp.webgoat.lessons.Assignment; import org.owasp.webgoat.lessons.NewLesson; import org.owasp.webgoat.session.Course; import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; +import org.springframework.context.annotation.Configuration; import org.springframework.core.type.filter.RegexPatternTypeFilter; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; import java.net.URL; import java.util.List; import java.util.Map; @@ -56,13 +64,12 @@ import static java.util.stream.Collectors.toList; */ @AllArgsConstructor @Slf4j +@Configuration public class PluginsLoader { - - private final PluginEndpointPublisher pluginEndpointPublisher; - /** *

createLessonsFromPlugins.

*/ + @Bean public Course loadPlugins() { List lessons = Lists.newArrayList(); for (PluginResource plugin : findPluginResources()) { @@ -70,7 +77,7 @@ public class PluginsLoader { plugin.getLessons().forEach(c -> { NewLesson lesson = null; try { - lesson = (NewLesson) c.newInstance(); + lesson = (NewLesson) c.getConstructor().newInstance(); log.trace("Lesson loaded: {}", lesson.getId()); } catch (Exception e) { log.error("Error while loading:" + c, e); @@ -78,7 +85,6 @@ public class PluginsLoader { List> assignments = plugin.getAssignments(c); lesson.setAssignments(createAssignment(assignments)); lessons.add(lesson); - pluginEndpointPublisher.publish(plugin.getEndpoints()); }); } catch (Exception e) { log.error("Error in loadLessons: ", e); @@ -97,7 +103,29 @@ public class PluginsLoader { } private String getPath(Class e) { - return e.getAnnotationsByType(AssignmentPath.class)[0].value(); + for (Method m : e.getMethods()) { + if (m.getReturnType() == AttackResult.class) { + var mapping = m.getAnnotation(RequestMapping.class); + if (mapping == null) { + log.error("AttackResult method found without mapping in: {}", e.getSimpleName()); + } else { + return getMapping(m); + } + } + } + return ""; + } + + private String getMapping(Method m) { + String[] path = null; + if (m.getAnnotation(RequestMapping.class) != null) { + path = m.getAnnotation(RequestMapping.class).path(); + } else if (m.getAnnotation(PostMapping.class) != null) { + path = m.getAnnotation(PostMapping.class).path(); + } else if (m.getAnnotation(GetMapping.class) != null) { + path = m.getAnnotation(GetMapping.class).value(); + } + return path != null && path.length > 0 ? path[0] : ""; } private List getHints(Class e) { @@ -107,8 +135,6 @@ public class PluginsLoader { return Lists.newArrayList(); } - - @SneakyThrows public List findPluginResources() { final ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false); diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonProgressService.java b/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonProgressService.java index 76e6187a5..cba3a1017 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonProgressService.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonProgressService.java @@ -76,7 +76,7 @@ public class LessonProgressService { } private List toJson(Map map) { - ArrayList result = Lists.newArrayList(); + List result = new ArrayList(); for (Map.Entry entry : map.entrySet()) { result.add(new LessonOverview(entry.getKey(), entry.getValue())); } diff --git a/webgoat-container/src/main/resources/application-webgoat.properties b/webgoat-container/src/main/resources/application-webgoat.properties index 2346f3f30..ad5f3cbbb 100644 --- a/webgoat-container/src/main/resources/application-webgoat.properties +++ b/webgoat-container/src/main/resources/application-webgoat.properties @@ -1,7 +1,7 @@ server.error.include-stacktrace=always server.error.path=/error.html server.session.timeout=600 -server.contextPath=/WebGoat +server.servlet.context-path=/WebGoat server.port=${WEBGOAT_PORT:8080} server.address=${WEBGOAT_HOST:127.0.0.1} @@ -17,6 +17,11 @@ spring.jpa.hibernate.ddl-auto=update spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.HSQLDialect spring.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver +logging.level.org.thymeleaf=DEBUG +logging.level.org.thymeleaf.TemplateEngine.CONFIG=TRACE +logging.level.org.thymeleaf.TemplateEngine.TIMER=TRACE +logging.level.org.thymeleaf.TemplateEngine.cache.TEMPLATE_CACHE=TRACE +logging.level.org.springframework.web=TRACE logging.level.org.springframework=INFO logging.level.org.springframework.boot.devtools=INFO logging.level.org.owasp=DEBUG @@ -25,7 +30,6 @@ logging.level.org.owasp.webgoat=TRACE # Needed for creating a vulnerable web application security.enable-csrf=false -spring.resources.cache-period=0 spring.thymeleaf.cache=false webgoat.start.hsqldb=true diff --git a/webgoat-container/src/main/resources/templates/main_new.html b/webgoat-container/src/main/resources/templates/main_new.html index eadb722c3..edde993ab 100644 --- a/webgoat-container/src/main/resources/templates/main_new.html +++ b/webgoat-container/src/main/resources/templates/main_new.html @@ -28,15 +28,15 @@ - - WebGoat @@ -67,8 +67,7 @@
  • Logout
  • -