diff --git a/webgoat-lessons/pom.xml b/webgoat-lessons/pom.xml
index 1d97b0118..4aad7f093 100644
--- a/webgoat-lessons/pom.xml
+++ b/webgoat-lessons/pom.xml
@@ -30,10 +30,11 @@
vulnerable-components
webgoat-introduction
webwolf-introduction
- auth-bypass
+ auth-bypass
missing-function-ac
csrf
password-reset
+ ssrf
diff --git a/webgoat-lessons/ssrf/pom.xml b/webgoat-lessons/ssrf/pom.xml
new file mode 100755
index 000000000..fb281fcd9
--- /dev/null
+++ b/webgoat-lessons/ssrf/pom.xml
@@ -0,0 +1,34 @@
+
+ 4.0.0
+ ssrf
+ jar
+
+ org.owasp.webgoat.lesson
+ webgoat-lessons-parent
+ v8.0.0.SNAPSHOT
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.security
+ spring-security-test
+ 4.1.3.RELEASE
+ test
+
+
+ junit
+ junit
+ ${junit.version}
+ jar
+ test
+
+
+
+
+
diff --git a/webgoat-lessons/ssrf/src/main/java/org/owasp/webgoat/plugin/SSRF.java b/webgoat-lessons/ssrf/src/main/java/org/owasp/webgoat/plugin/SSRF.java
new file mode 100755
index 000000000..b4da9d97f
--- /dev/null
+++ b/webgoat-lessons/ssrf/src/main/java/org/owasp/webgoat/plugin/SSRF.java
@@ -0,0 +1,63 @@
+package org.owasp.webgoat.plugin;
+
+import com.beust.jcommander.internal.Lists;
+import org.owasp.webgoat.lessons.Category;
+import org.owasp.webgoat.lessons.NewLesson;
+
+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 WebGoat
+ * @version $Id: $Id
+ * @since October 12, 2016
+ */
+public class SSRF extends NewLesson {
+ @Override
+ public Category getDefaultCategory() {
+ return Category.REQUEST_FORGERIES;
+ }
+
+ @Override
+ public List getHints() {
+ return Lists.newArrayList();
+ }
+
+ @Override
+ public Integer getDefaultRanking() {
+ return 2;
+ }
+
+ @Override
+ public String getTitle() {
+ return "ssrf.title";
+ }
+
+ @Override
+ public String getId() {
+ return "SSRF";
+ }
+}
diff --git a/webgoat-lessons/ssrf/src/main/java/org/owasp/webgoat/plugin/SSRFTask1.java b/webgoat-lessons/ssrf/src/main/java/org/owasp/webgoat/plugin/SSRFTask1.java
new file mode 100755
index 000000000..2e351b5eb
--- /dev/null
+++ b/webgoat-lessons/ssrf/src/main/java/org/owasp/webgoat/plugin/SSRFTask1.java
@@ -0,0 +1,98 @@
+package org.owasp.webgoat.plugin;
+
+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.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.sun.net.httpserver.Authenticator.Success;
+
+import java.io.*;
+import java.net.URL;
+import java.net.URLConnection;
+
+
+/**
+ * *************************************************************************************************
+ *
+ *
+ * This file is part of WebGoat, an Open Web Application Security Project
+ * utility. For details, please see http://www.owasp.org/
+ *
+ * Copyright (c) 2002 - 2014 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 Alex Fry WebGoat
+ * @created December 26, 2018
+ */
+@AssignmentPath("/SSRF/task1")
+@AssignmentHints({"ssrf.hint1","ssrf.hint2"})
+public class SSRFTask1 extends AssignmentEndpoint {
+
+ @RequestMapping(method = RequestMethod.POST)
+ public @ResponseBody
+
+ AttackResult completed(@RequestParam String url) throws IOException {
+ return stealTheCheese(url);
+ }
+
+ protected AttackResult stealTheCheese(String url) {
+ try {
+ StringBuffer html = new StringBuffer();
+
+ if (url.matches("images/tom.png")) {
+ html.append("
");
+ return trackProgress(failed()
+ .feedback("ssrf.tom")
+ .output(html.toString())
+ .build());
+ }else if (url.matches("images/jerry.png")){
+ html.append("
");
+ return trackProgress(success()
+ .feedback("ssrf.success")
+ .output(html.toString())
+ .build());
+ }else{
+ html.append("
");
+ return trackProgress(failed()
+ .feedback("ssrf.failure")
+ .output(html.toString())
+ .build());
+ }
+
+ }catch(Exception e) {
+ e.printStackTrace();
+ return trackProgress(failed()
+ .output(e.getMessage())
+ .build());
+ }
+ }
+}
diff --git a/webgoat-lessons/ssrf/src/main/java/org/owasp/webgoat/plugin/SSRFTask2.java b/webgoat-lessons/ssrf/src/main/java/org/owasp/webgoat/plugin/SSRFTask2.java
new file mode 100755
index 000000000..fa0c8f03f
--- /dev/null
+++ b/webgoat-lessons/ssrf/src/main/java/org/owasp/webgoat/plugin/SSRFTask2.java
@@ -0,0 +1,101 @@
+package org.owasp.webgoat.plugin;
+
+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.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.sun.net.httpserver.Authenticator.Success;
+
+import java.io.*;
+import java.net.URL;
+import java.net.URLConnection;
+
+
+/**
+ * *************************************************************************************************
+ *
+ *
+ * This file is part of WebGoat, an Open Web Application Security Project
+ * utility. For details, please see http://www.owasp.org/
+ *
+ * Copyright (c) 2002 - 2014 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 Alex Fry WebGoat
+ * @created December 26, 2018
+ */
+@AssignmentPath("/SSRF/task2")
+@AssignmentHints({"ssrf.hint3"})
+public class SSRFTask2 extends AssignmentEndpoint {
+
+ @RequestMapping(method = RequestMethod.POST)
+ public @ResponseBody
+
+ AttackResult completed(@RequestParam String url) throws IOException {
+ return furBall(url);
+ }
+
+ protected AttackResult furBall(String url) {
+ try {
+ StringBuffer html = new StringBuffer();
+
+ if (url.matches("http://ifconfig.pro")){
+ URL u = new URL(url);
+ URLConnection urlConnection = u.openConnection();
+ BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
+ String inputLine;
+
+ while ((inputLine = in.readLine()) != null) {
+ html.append(inputLine);
+ }
+ in.close();
+
+ return trackProgress(success()
+ .feedback("ssrf.success")
+ .output(html.toString())
+ .build());
+ }else{
+ html.append("
");
+ return trackProgress(failed()
+ .feedback("ssrf.failure")
+ .output(html.toString())
+ .build());
+ }
+
+ }catch(Exception e) {
+ e.printStackTrace();
+ return trackProgress(failed()
+ .output(e.getMessage())
+ .build());
+ }
+ }
+}
diff --git a/webgoat-lessons/ssrf/src/main/resources/html/SSRF.html b/webgoat-lessons/ssrf/src/main/resources/html/SSRF.html
new file mode 100755
index 000000000..241b410b3
--- /dev/null
+++ b/webgoat-lessons/ssrf/src/main/resources/html/SSRF.html
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/webgoat-lessons/ssrf/src/main/resources/i18n/WebGoatLabels.properties b/webgoat-lessons/ssrf/src/main/resources/i18n/WebGoatLabels.properties
new file mode 100755
index 000000000..4b4825ebc
--- /dev/null
+++ b/webgoat-lessons/ssrf/src/main/resources/i18n/WebGoatLabels.properties
@@ -0,0 +1,9 @@
+ssrf.title=Server-Side Request Forgery
+
+ssrf.tom=You failed to steal the cheese!
+ssrf.success=You rocked the SSRF!
+ssrf.failure=You need to stick to the game plan!
+
+ssrf.hint1=You should use an HTTP proxy to intercept the request and change the URL.
+ssrf.hint2=If Tom is images/tom.png, Jerry would be images/jerry.png.
+ssrf.hint3=You need to put the protocol, "http://" in front of ifconfig.pro.
\ No newline at end of file
diff --git a/webgoat-lessons/ssrf/src/main/resources/images/cat.jpg b/webgoat-lessons/ssrf/src/main/resources/images/cat.jpg
new file mode 100644
index 000000000..e0e1fb983
Binary files /dev/null and b/webgoat-lessons/ssrf/src/main/resources/images/cat.jpg differ
diff --git a/webgoat-lessons/ssrf/src/main/resources/images/jerry.png b/webgoat-lessons/ssrf/src/main/resources/images/jerry.png
new file mode 100644
index 000000000..5ed492711
Binary files /dev/null and b/webgoat-lessons/ssrf/src/main/resources/images/jerry.png differ
diff --git a/webgoat-lessons/ssrf/src/main/resources/images/tom.png b/webgoat-lessons/ssrf/src/main/resources/images/tom.png
new file mode 100644
index 000000000..d8e50d91a
Binary files /dev/null and b/webgoat-lessons/ssrf/src/main/resources/images/tom.png differ
diff --git a/webgoat-lessons/ssrf/src/main/resources/js/credentials.js b/webgoat-lessons/ssrf/src/main/resources/js/credentials.js
new file mode 100755
index 000000000..b7387c623
--- /dev/null
+++ b/webgoat-lessons/ssrf/src/main/resources/js/credentials.js
@@ -0,0 +1,6 @@
+function submit_secret_credentials() {
+ var xhttp = new XMLHttpRequest();
+ xhttp['open']('POST', '#attack/307/100', true);
+ //sending the request is obfuscated, to descourage js reading
+ var _0xb7f9=["\x43\x61\x70\x74\x61\x69\x6E\x4A\x61\x63\x6B","\x42\x6C\x61\x63\x6B\x50\x65\x61\x72\x6C","\x73\x74\x72\x69\x6E\x67\x69\x66\x79","\x73\x65\x6E\x64"];xhttp[_0xb7f9[3]](JSON[_0xb7f9[2]]({username:_0xb7f9[0],password:_0xb7f9[1]}))
+}
\ No newline at end of file
diff --git a/webgoat-lessons/ssrf/src/main/resources/lessonPlans/en/SSRF_Intro.adoc b/webgoat-lessons/ssrf/src/main/resources/lessonPlans/en/SSRF_Intro.adoc
new file mode 100755
index 000000000..03b06fdac
--- /dev/null
+++ b/webgoat-lessons/ssrf/src/main/resources/lessonPlans/en/SSRF_Intro.adoc
@@ -0,0 +1,12 @@
+
+== Concept
+In a Server-Side Request Forgery (SSRF) attack, the attacker can abuse functionality on the server to read or update internal resources. The attacker can supply or a modify a URL which the code running on the server will read or submit data to, and by carefully selecting the URLs, the attacker may be able to read server configuration such as AWS metadata, connect to internal services like http enabled databases or perform post requests towards internal services which are not intended to be exposed.
+
+== Goals
+* The user will need to modify the URL.
+
+== SSRF How-To
+* https://www.hackerone.com/blog-How-To-Server-Side-Request-Forgery-SSRF
+
+== A New Era of SSRF by Orange Tsai
+* https://www.youtube.com/watch?v=D1S-G8rJrEk
\ No newline at end of file
diff --git a/webgoat-lessons/ssrf/src/main/resources/lessonPlans/en/SSRF_Prevent.adoc b/webgoat-lessons/ssrf/src/main/resources/lessonPlans/en/SSRF_Prevent.adoc
new file mode 100755
index 000000000..bc088bb92
--- /dev/null
+++ b/webgoat-lessons/ssrf/src/main/resources/lessonPlans/en/SSRF_Prevent.adoc
@@ -0,0 +1,10 @@
+
+== Prevent
+To prevent SSRF vulnerabilities in web applications, it is recommended to adhere to the following guidelines:
+
+* Use a whitelist of allowed domains, resources and protocols from where the web server can fetch resources.
+* Any input accepted from the user should be validated and rejected if it does not match the positive specification expected.
+* If possible, do not accept user input in functions that control where the web server can fetch resources.
+
+== References
+* https://www.owasp.org/index.php/Server_Side_Request_Forgery
\ No newline at end of file
diff --git a/webgoat-lessons/ssrf/src/main/resources/lessonPlans/en/SSRF_Task1.adoc b/webgoat-lessons/ssrf/src/main/resources/lessonPlans/en/SSRF_Task1.adoc
new file mode 100755
index 000000000..bedc3f879
--- /dev/null
+++ b/webgoat-lessons/ssrf/src/main/resources/lessonPlans/en/SSRF_Task1.adoc
@@ -0,0 +1,2 @@
+=== Change the URL to display Jerry
+
diff --git a/webgoat-lessons/ssrf/src/main/resources/lessonPlans/en/SSRF_Task2.adoc b/webgoat-lessons/ssrf/src/main/resources/lessonPlans/en/SSRF_Task2.adoc
new file mode 100755
index 000000000..b8a457a52
--- /dev/null
+++ b/webgoat-lessons/ssrf/src/main/resources/lessonPlans/en/SSRF_Task2.adoc
@@ -0,0 +1,2 @@
+=== Change the URL to display the Interface Configuration with ifconfig.pro
+
diff --git a/webgoat-lessons/ssrf/src/test/java/org/owasp/webgoat/plugin/SSRFTest1.java b/webgoat-lessons/ssrf/src/test/java/org/owasp/webgoat/plugin/SSRFTest1.java
new file mode 100644
index 000000000..f92860fa6
--- /dev/null
+++ b/webgoat-lessons/ssrf/src/test/java/org/owasp/webgoat/plugin/SSRFTest1.java
@@ -0,0 +1,52 @@
+package org.owasp.webgoat.plugin;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.owasp.webgoat.plugins.LessonTest;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+
+import static org.hamcrest.Matchers.is;
+import static org.mockito.Mockito.when;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+/**
+ * @author afry
+ * @since 12/28/18.
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+public class SSRFTest1 extends LessonTest {
+
+
+ @Before
+ public void setup() throws Exception {
+ SSRF ssrf = new SSRF();
+ when(webSession.getCurrentLesson()).thenReturn(ssrf);
+ this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
+ }
+
+ @Test
+ public void modifyUrlTom() throws Exception {
+ mockMvc.perform(MockMvcRequestBuilders.post("/SSRF/task1")
+ .param("url", "images/tom.png"))
+ .andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(false)));
+ }
+
+ @Test
+ public void modifyUrlJerry() throws Exception {
+ mockMvc.perform(MockMvcRequestBuilders.post("/SSRF/task1")
+ .param("url", "images/jerry.png"))
+ .andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(true)));
+ }
+
+ @Test
+ public void modifyUrlCat() throws Exception {
+ mockMvc.perform(MockMvcRequestBuilders.post("/SSRF/task1")
+ .param("url", "images/cat.jpg"))
+ .andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(false)));
+ }
+}
diff --git a/webgoat-lessons/ssrf/src/test/java/org/owasp/webgoat/plugin/SSRFTest2.java b/webgoat-lessons/ssrf/src/test/java/org/owasp/webgoat/plugin/SSRFTest2.java
new file mode 100644
index 000000000..4653af8c3
--- /dev/null
+++ b/webgoat-lessons/ssrf/src/test/java/org/owasp/webgoat/plugin/SSRFTest2.java
@@ -0,0 +1,45 @@
+package org.owasp.webgoat.plugin;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.owasp.webgoat.plugins.LessonTest;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+
+import static org.hamcrest.Matchers.is;
+import static org.mockito.Mockito.when;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+/**
+ * @author afry
+ * @since 12/28/18.
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+public class SSRFTest2 extends LessonTest {
+
+
+ @Before
+ public void setup() throws Exception {
+ SSRF ssrf = new SSRF();
+ when(webSession.getCurrentLesson()).thenReturn(ssrf);
+ this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
+ }
+
+ @Test
+ public void modifyUrlIfconfigPro() throws Exception {
+ mockMvc.perform(MockMvcRequestBuilders.post("/SSRF/task2")
+ .param("url", "http://ifconfig.pro"))
+ .andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(true)));
+ }
+
+ @Test
+ public void modifyUrlCat() throws Exception {
+ mockMvc.perform(MockMvcRequestBuilders.post("/SSRF/task2")
+ .param("url", "images/cat.jpg"))
+ .andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(false)));
+ }
+}