diff --git a/platformQuickStarts/GCP/GKE-Docker/deploy.cfg b/platformQuickStarts/GCP/GKE-Docker/deploy.cfg new file mode 100644 index 000000000..460110cc2 --- /dev/null +++ b/platformQuickStarts/GCP/GKE-Docker/deploy.cfg @@ -0,0 +1,4 @@ +CURTAG=webgoat/webgoat-8.0 +DEST_TAG=gcr.io/astech-training/raging-wire-webgoat +CLUSTER_NAME=raging-wire-webgoat +PORT_NUM=8080 \ No newline at end of file diff --git a/platformQuickStarts/GCP/GKE-Docker/gke-deploy-config.sh b/platformQuickStarts/GCP/GKE-Docker/gke-deploy-config.sh new file mode 100644 index 000000000..87a076730 --- /dev/null +++ b/platformQuickStarts/GCP/GKE-Docker/gke-deploy-config.sh @@ -0,0 +1,4 @@ +CURTAG=webgoat/webgoat-8.0 +DEST_TAG=gcr.io/your-gke-project/your-webgoat-tag +CLUSTER_NAME=your-cluster-name +PORT_NUM=8080 \ No newline at end of file diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/CreateDB.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/CreateDB.java index 1805bd161..d658b072a 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/session/CreateDB.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/session/CreateDB.java @@ -232,7 +232,7 @@ public class CreateDB { // Create the new table try { - String createTableStatement = "CREATE TABLE user_system_data (" + "userid varchar(5) not null primary key," + String createTableStatement = "CREATE TABLE user_system_data (" + "userid int not null primary key," + "user_name varchar(12)," + "password varchar(10)," + "cookie varchar(30)" + ")"; statement.executeUpdate(createTableStatement); } catch (SQLException e) { @@ -240,11 +240,11 @@ public class CreateDB { } // Populate - String insertData1 = "INSERT INTO user_system_data VALUES ('101','jsnow','passwd1', '')"; - String insertData2 = "INSERT INTO user_system_data VALUES ('102','jdoe','passwd2', '')"; - String insertData3 = "INSERT INTO user_system_data VALUES ('103','jplane','passwd3', '')"; - String insertData4 = "INSERT INTO user_system_data VALUES ('104','jeff','jeff', '')"; - String insertData5 = "INSERT INTO user_system_data VALUES ('105','dave','dave', '')"; + String insertData1 = "INSERT INTO user_system_data VALUES (101,'jsnow','passwd1', '')"; + String insertData2 = "INSERT INTO user_system_data VALUES (102,'jdoe','passwd2', '')"; + String insertData3 = "INSERT INTO user_system_data VALUES (103,'jplane','passwd3', '')"; + String insertData4 = "INSERT INTO user_system_data VALUES (104,'jeff','jeff', '')"; + String insertData5 = "INSERT INTO user_system_data VALUES (105,'dave','passW0rD', '')"; statement.executeUpdate(insertData1); statement.executeUpdate(insertData2); statement.executeUpdate(insertData3); 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 c9e3b7d70..e2062cbdd 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 and digits") + @Pattern(regexp = "[a-zA-Z0-9-]*", message = "can only contain letters, digits, and -") private String username; @NotNull @Size(min=6, max=10) diff --git a/webgoat-container/src/main/resources/static/js/goatApp/controller/LessonController.js b/webgoat-container/src/main/resources/static/js/goatApp/controller/LessonController.js index 11b8279cf..f9bfadf6e 100644 --- a/webgoat-container/src/main/resources/static/js/goatApp/controller/LessonController.js +++ b/webgoat-container/src/main/resources/static/js/goatApp/controller/LessonController.js @@ -79,6 +79,7 @@ define(['jquery', this.listenTo(this.lessonHintView, 'hints:hideButton', this.onHideHintsButton); this.lessonContentView.navToPage(pageNum); this.lessonHintView.hideHints(); + this.lessonHintView.showFirstHint(); //this.lessonHintView.selectHints(); this.titleView.render(this.lessonInfoModel.get('lessonTitle')); return; @@ -160,7 +161,7 @@ define(['jquery', } // this.lessonHintView.render(); - if (this.lessonHintView.getHintsCount > 0) { + if (this.lessonHintView.getHintsCount() > 0) { this.helpControlsView.showHintsButton(); } else { this.helpControlsView.hideHintsButton(); diff --git a/webgoat-container/src/main/resources/static/js/goatApp/model/LessonContentModel.js b/webgoat-container/src/main/resources/static/js/goatApp/model/LessonContentModel.js index f26aad564..ee463fbab 100644 --- a/webgoat-container/src/main/resources/static/js/goatApp/model/LessonContentModel.js +++ b/webgoat-container/src/main/resources/static/js/goatApp/model/LessonContentModel.js @@ -32,7 +32,11 @@ define(['jquery', } this.set('content',content); this.set('lessonUrl',document.URL.replace(/\.lesson.*/,'.lesson')); - this.set('pageNum',document.URL.replace(/.*\.lesson\/(\d{1,4})$/,'$1')); + if (/.*\.lesson\/(\d{1,4})$/.test(document.URL)) { + this.set('pageNum',document.URL.replace(/.*\.lesson\/(\d{1,4})$/,'$1')); + } else { + this.set('pageNum',0); + } this.trigger('content:loaded',this,loadHelps); }, diff --git a/webgoat-container/src/main/resources/static/js/goatApp/view/HintView.js b/webgoat-container/src/main/resources/static/js/goatApp/view/HintView.js index f8b4a2159..a1d83ef89 100644 --- a/webgoat-container/src/main/resources/static/js/goatApp/view/HintView.js +++ b/webgoat-container/src/main/resources/static/js/goatApp/view/HintView.js @@ -32,21 +32,19 @@ function($, toggleLabel: function() { if (this.isVisible()) { - $('show-hints-button').text('Hide hints'); + $('#show-hints-button').text('Hide hints'); } else { - $('show-hints-button').text('Show hints'); + $('#show-hints-button').text('Show hints'); } }, render:function() { if (this.isVisible()) { - this.$el.hide(350); + this.$el.hide(350, this.toggleLabel.bind(this)); } else if (this.hintsToShow.length > 0) { - this.$el.show(350); + this.$el.show(350, this.toggleLabel.bind(this)); } - this.toggleLabel() - if (this.hintsToShow.length > 0) { this.hideShowPrevNextButtons(); } @@ -90,9 +88,9 @@ function($, hideHints: function() { if (this.$el.is(':visible')) { - this.$el.hide(350); + this.$el.hide(350, this.toggleLabel.bind(this)); } - }, + }, showNextHint: function() { this.curHint = (this.curHint < this.hintsToShow.length -1) ? this.curHint+1 : this.curHint; @@ -106,6 +104,12 @@ function($, this.displayHint(this.curHint); }, + showFirstHint: function() { + this.curHint = 0; + this.hideShowPrevNextButtons(); + this.displayHint(this.curHint); + }, + displayHint: function(curHint) { if(this.hintsToShow.length == 0) { // this.hideHints(); diff --git a/webgoat-container/src/main/resources/templates/list_users.html b/webgoat-container/src/main/resources/templates/list_users.html index 5e2b3045b..050c85dc7 100644 --- a/webgoat-container/src/main/resources/templates/list_users.html +++ b/webgoat-container/src/main/resources/templates/list_users.html @@ -123,8 +123,9 @@
- Users in WebGoat - su + + Users in WebGoat +

WebGoat Users

diff --git a/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/StoredXssComments.java b/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/StoredXssComments.java index 022abc883..8fbff0518 100644 --- a/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/StoredXssComments.java +++ b/webgoat-lessons/cross-site-scripting/src/main/java/org/owasp/webgoat/plugin/StoredXssComments.java @@ -49,10 +49,7 @@ import org.owasp.encoder.*; import static org.springframework.http.MediaType.ALL_VALUE; import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; +import java.util.*; import static org.springframework.web.bind.annotation.RequestMethod.GET; @@ -72,20 +69,19 @@ public class StoredXssComments extends AssignmentEndpoint { comments.add(new Comment("secUriTy", DateTime.now().toString(fmt), "Comment for Unit Testing")); comments.add(new Comment("webgoat", DateTime.now().toString(fmt), "This comment is safe")); comments.add(new Comment("guest", DateTime.now().toString(fmt), "This one is safe too.")); - comments.add(new Comment("guest", DateTime.now().toString(fmt), "Can you post a comment, calling webgoat.customjs.phoneHome() ?")); + comments.add(new Comment("guest", DateTime.now().toString(fmt), "Can you post a comment, calling webgoat.customjs.phoneHome() ?")); } @RequestMapping(method = GET, produces = MediaType.APPLICATION_JSON_VALUE,consumes = ALL_VALUE) @ResponseBody public Collection retrieveComments() { - Collection allComments = Lists.newArrayList(); + List allComments = Lists.newArrayList(); Collection newComments = userComments.get(webSession.getUserName()); + allComments.addAll(comments); if (newComments != null) { allComments.addAll(newComments); } - - allComments.addAll(comments); - + Collections.reverse(allComments); return allComments; } diff --git a/webgoat-lessons/cross-site-scripting/src/main/resources/i18n/WebGoatLabels.properties b/webgoat-lessons/cross-site-scripting/src/main/resources/i18n/WebGoatLabels.properties index 3f6a96ee2..880258b1d 100644 --- a/webgoat-lessons/cross-site-scripting/src/main/resources/i18n/WebGoatLabels.properties +++ b/webgoat-lessons/cross-site-scripting/src/main/resources/i18n/WebGoatLabels.properties @@ -5,7 +5,7 @@ xss-reflected-5a-failure=Try again. We do want to see this specific javascript ( xss-reflected-5b-success=Correct ... because
  • The script was not triggered by the URL/QueryString
  • Even if you use the attack URL in a new tab, it won't execute (becuase of response type). Try it if you like.
xss-reflected-5b-failure=Nope, pretty easy to guess now though. xss-reflected-6a-success=Correct! Now, see if you can send in an exploit to that route in the next assignment. -xss-reflected-6a-failure=No, look at the example. Check the GoatRouter.js file. It should be pretty easy to determine. +xss-reflected-6a-failure=No, look at the example. Check the GoatRouter.js file. It should be pretty easy to determine. xss.lesson1.failure=Are you sure? Try using a tab from a different site. xss-dom-message-success=Correct, I hope you didn't cheat, using the console! xss-dom-message-failure=Incorrect, keep trying. It should be obvious in the log when you are successful. diff --git a/webgoat-lessons/cross-site-scripting/src/main/resources/lessonPlans/en/CrossSiteScripting_content5b.adoc b/webgoat-lessons/cross-site-scripting/src/main/resources/lessonPlans/en/CrossSiteScripting_content5b.adoc index e0cf6f949..850f0d09e 100644 --- a/webgoat-lessons/cross-site-scripting/src/main/resources/lessonPlans/en/CrossSiteScripting_content5b.adoc +++ b/webgoat-lessons/cross-site-scripting/src/main/resources/lessonPlans/en/CrossSiteScripting_content5b.adoc @@ -4,7 +4,7 @@ You should have been able to execute script with the last example. At this point Why is that? -That is because there is no link that would tigger that XSS. +That is because there is no link that would trigger that XSS. You can try it yourself to see what happens ... go to (substitute localhost with your server's name or IP if you need to): -link: http://localhost:8080/WebGoat/CrossSiteScripting/attack5a?QTY1=1&QTY2=1&QTY3=1&QTY4=1&field1=4128+3214+0002+1999&field2=111 +link: http://localhost:8080/WebGoat/CrossSiteScripting/attack5a?QTY1=1&QTY2=1&QTY3=1&QTY4=1&field1=4128+3214+0002+1999&field2=111 diff --git a/webgoat-lessons/cross-site-scripting/src/main/resources/lessonPlans/en/CrossSiteScripting_content6a.adoc b/webgoat-lessons/cross-site-scripting/src/main/resources/lessonPlans/en/CrossSiteScripting_content6a.adoc index 656d9f4de..c1a3ab6a7 100644 --- a/webgoat-lessons/cross-site-scripting/src/main/resources/lessonPlans/en/CrossSiteScripting_content6a.adoc +++ b/webgoat-lessons/cross-site-scripting/src/main/resources/lessonPlans/en/CrossSiteScripting_content6a.adoc @@ -1,15 +1,15 @@ -== Ientify Potential for DOM-Based XSS +== Identify Potential for DOM-Based XSS DOM-Based XSS can usually be found by looking for the route configurations in the client-side code. -Look for a route that takes inputs that you can ID being 'reflected' to the page. +Look for a route that takes inputs that are being 'reflected' to the page. For this example, you'll want to look for some 'test' code in the route handlers (WebGoat uses backbone as its primary javascript library). Sometimes, test code gets left in production (and often times test code is very simple and lacks security or any quality controls!). Your objective is to find the route and exploit it. First though ... what is the base route? As an example, look at the URL for this lesson ... -it should look something like /WebGoat/start.mvc#lesson/CrossSiteScripting.lesson/5 (although maybe slightly different). The 'base route' in this case is: +it should look something like /WebGoat/start.mvc#lesson/CrossSiteScripting.lesson/9. The 'base route' in this case is: *start.mvc#lesson/* +The *CrossSiteScripting.lesson/9* after that are parameters that are processed by the javascript route handler. -The *CrossSiteScripting.lesson/#* after that are parameters that are processed by javascript route handler. - -So, what is test route for this test code? +So, what is the route for the test code that stayed in the app during production? +To answer this question, you have to check the javascript source. \ No newline at end of file diff --git a/webgoat-lessons/cross-site-scripting/src/main/resources/lessonPlans/en/CrossSiteScripting_content6b.adoc b/webgoat-lessons/cross-site-scripting/src/main/resources/lessonPlans/en/CrossSiteScripting_content6b.adoc index 3fd67b860..4b35ae2a2 100644 --- a/webgoat-lessons/cross-site-scripting/src/main/resources/lessonPlans/en/CrossSiteScripting_content6b.adoc +++ b/webgoat-lessons/cross-site-scripting/src/main/resources/lessonPlans/en/CrossSiteScripting_content6b.adoc @@ -8,4 +8,4 @@ The function you want to execute is ... Sure, you could just use console/debug to trigger it, but you need to trigger it via a URL in a new tab. -Once you do trigger it, a subsequent response will come to the browser with a random number. Put that random number in below. +Once you do trigger it, a subsequent response will come to your browser's console with a random number. Put that random number in below. 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 0acd8bbfe..501da489b 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 @@ -64,11 +64,11 @@ public class CSRFFeedback extends AssignmentEndpoint { private boolean hostOrRefererDifferentHost(HttpServletRequest request) { String referer = request.getHeader("referer"); - String origin = request.getHeader("origin"); + String host = request.getHeader("host"); if (referer != null) { - return !referer.contains(origin); + return !referer.contains(host); } else { - return true; //this case referer is null or origin does not matter we cannot compare so we return true which should of course be false + return true; } } diff --git a/webgoat-lessons/csrf/src/main/resources/html/CSRF.html b/webgoat-lessons/csrf/src/main/resources/html/CSRF.html index fc7463461..71d08a816 100644 --- a/webgoat-lessons/csrf/src/main/resources/html/CSRF.html +++ b/webgoat-lessons/csrf/src/main/resources/html/CSRF.html @@ -20,7 +20,7 @@ action="/WebGoat/csrf/basic-get-flag" enctype="application/json;charset=UTF-8"> - + diff --git a/webgoat-lessons/csrf/src/main/resources/lessonPlans/en/CSRF_Login.adoc b/webgoat-lessons/csrf/src/main/resources/lessonPlans/en/CSRF_Login.adoc index ea480f495..dfc8ec854 100644 --- a/webgoat-lessons/csrf/src/main/resources/lessonPlans/en/CSRF_Login.adoc +++ b/webgoat-lessons/csrf/src/main/resources/lessonPlans/en/CSRF_Login.adoc @@ -16,9 +16,11 @@ the activities of the user. image::images/login-csrf.png[caption="Figure: ", title="Login CSRF from Robust Defenses for Cross-Site Request Forgery", width="800", height="500", style="lesson-image" link="http://seclab.stanford.edu/websec/csrf/csrf.pdf"] {blank} -For more information read the following http://seclab.stanford.edu/websec/csrf/csrf.pdf[paper] +For more information read the following http://seclab.stanford.edu/websec/csrf/csrf.pdf[paper]. -In this assignment try to see if WebGoat is also vulnerable for a login CSRF attack. First create a user -based on your own username prefixed with csrf. So if your username is `tom` you must create -a new user called `csrf-tom` +In this assignment try to see if WebGoat is also vulnerable for a login CSRF attack. +Leave this tab open and in another tab create a user based on your own username prefixed with `csrf-`. +So if your username is `tom` you must create a new user called `csrf-tom`. +Login as the new user. This is what an attacker would do using CSRF. Then click the button in the original tab. +Because you are logged in as a different user, the attacker learns that you clicked the button. diff --git a/webgoat-lessons/csrf/src/test/java/org/owasp/webgoat/plugin/CSRFFeedbackTest.java b/webgoat-lessons/csrf/src/test/java/org/owasp/webgoat/plugin/CSRFFeedbackTest.java index 495a2cf9b..cb5edba91 100644 --- a/webgoat-lessons/csrf/src/test/java/org/owasp/webgoat/plugin/CSRFFeedbackTest.java +++ b/webgoat-lessons/csrf/src/test/java/org/owasp/webgoat/plugin/CSRFFeedbackTest.java @@ -46,7 +46,7 @@ public class CSRFFeedbackTest extends LessonTest { mockMvc.perform(post("/csrf/feedback/message") .contentType(MediaType.TEXT_PLAIN) .cookie(new Cookie("JSESSIONID", "test")) - .header("origin", "localhost:8080") + .header("host", "localhost:8080") .header("referer", "webgoat.org") .content("{\"name\": \"Test\", \"email\": \"test1233@dfssdf.de\", \"subject\": \"service\", \"message\":\"dsaffd\"}")) .andExpect(jsonPath("lessonCompleted", is(true))) diff --git a/webgoat-lessons/jwt/src/main/java/org/owasp/webgoat/plugin/JWTSecretKeyEndpoint.java b/webgoat-lessons/jwt/src/main/java/org/owasp/webgoat/plugin/JWTSecretKeyEndpoint.java index 5748681f5..f3f2ab8b7 100644 --- a/webgoat-lessons/jwt/src/main/java/org/owasp/webgoat/plugin/JWTSecretKeyEndpoint.java +++ b/webgoat-lessons/jwt/src/main/java/org/owasp/webgoat/plugin/JWTSecretKeyEndpoint.java @@ -1,6 +1,7 @@ package org.owasp.webgoat.plugin; import com.google.common.collect.Lists; +import io.jsonwebtoken.impl.TextCodec; import org.owasp.webgoat.assignments.AssignmentEndpoint; import org.owasp.webgoat.assignments.AssignmentHints; import org.owasp.webgoat.assignments.AssignmentPath; @@ -23,7 +24,7 @@ import java.util.List; @AssignmentHints({"jwt-secret-hint1", "jwt-secret-hint2", "jwt-secret-hint3"}) public class JWTSecretKeyEndpoint extends AssignmentEndpoint { - public static final String JWT_SECRET = "victory"; + public static final String JWT_SECRET = TextCodec.BASE64.encode("victory"); private static final String WEBGOAT_USER = "WebGoat"; private static final List expectedClaims = Lists.newArrayList("iss", "iat", "exp", "aud", "sub", "username", "Email", "Role"); diff --git a/webgoat-lessons/jwt/src/main/java/org/owasp/webgoat/plugin/JWTVotesEndpoint.java b/webgoat-lessons/jwt/src/main/java/org/owasp/webgoat/plugin/JWTVotesEndpoint.java index c963212ee..49363b3b1 100644 --- a/webgoat-lessons/jwt/src/main/java/org/owasp/webgoat/plugin/JWTVotesEndpoint.java +++ b/webgoat-lessons/jwt/src/main/java/org/owasp/webgoat/plugin/JWTVotesEndpoint.java @@ -5,6 +5,7 @@ import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwt; import io.jsonwebtoken.JwtException; import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.impl.TextCodec; import org.apache.commons.lang3.StringUtils; import org.owasp.webgoat.assignments.AssignmentEndpoint; import org.owasp.webgoat.assignments.AssignmentHints; @@ -25,7 +26,6 @@ import java.time.Duration; import java.time.Instant; import java.util.Date; import java.util.Map; -import java.util.concurrent.TimeUnit; import static java.util.Comparator.comparingLong; import static java.util.Optional.ofNullable; @@ -39,7 +39,7 @@ import static java.util.stream.Collectors.toList; @AssignmentHints({"jwt-change-token-hint1", "jwt-change-token-hint2", "jwt-change-token-hint3", "jwt-change-token-hint4", "jwt-change-token-hint5"}) public class JWTVotesEndpoint extends AssignmentEndpoint { - public static final String JWT_PASSWORD = "victory"; + public static final String JWT_PASSWORD = TextCodec.BASE64.encode("victory"); private static String validUsers = "TomJerrySylvester"; private static int totalVotes = 38929; diff --git a/webgoat-lessons/jwt/src/main/resources/lessonPlans/en/JWT_refresh.adoc b/webgoat-lessons/jwt/src/main/resources/lessonPlans/en/JWT_refresh.adoc index 3b91e0bfa..571bfcc21 100644 --- a/webgoat-lessons/jwt/src/main/resources/lessonPlans/en/JWT_refresh.adoc +++ b/webgoat-lessons/jwt/src/main/resources/lessonPlans/en/JWT_refresh.adoc @@ -63,15 +63,15 @@ whether the location is still the same if not revoke all the tokens and let the === Need for refresh tokens Does it make sense to use a refresh token in a modern single page application (SPA)? As we have seen in the section -about storing tokens there are two option: web storage or a cookie which mean a refresh token is right beside an -access token, so if the access token is leaked changes are the refresh token will also be compromised. Most of the time -there is a difference of course, the access token is send when you make an API call, the refresh token is only send +about storing tokens there are two options: web storage or a cookie which mean a refresh token is right beside an +access token, so if the access token is leaked chances are the refresh token will also be compromised. Most of the time +there is a difference of course. The access token is sent when you make an API call, the refresh token is only sent when a new access token should be obtained, which in most cases is a different endpoint. If you end up on the same -server you can chose to only use the access token. +server you can choose to only use the access token. As stated above using an access token and a separate refresh token gives some leverage for the server not to check the access token over and over. Only perform the check when the user needs a new access token. -It is certainly possible to only use an access token, at the server you store the exact same information you would +It is certainly possible to only use an access token. At the server you store the exact same information you would store for a refresh token, see previous paragraph. This way you need to check the token each time but this might be suitable depending on the application. In the case the refresh tokens are stored for validation it is important to protect these tokens as well (at least use a hash function to store them in your database). diff --git a/webgoat-lessons/jwt/src/main/resources/lessonPlans/en/JWT_weak_keys b/webgoat-lessons/jwt/src/main/resources/lessonPlans/en/JWT_weak_keys index b8da3bf02..d57483f2e 100644 --- a/webgoat-lessons/jwt/src/main/resources/lessonPlans/en/JWT_weak_keys +++ b/webgoat-lessons/jwt/src/main/resources/lessonPlans/en/JWT_weak_keys @@ -9,5 +9,5 @@ dictionary attack is not feasible. Once you have a token you can start an offlin Given we have the following token try to find out secret key and submit a new key with the userId changed to WebGoat. ``` -eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJXZWJHb2F0IFRva2VuIEJ1aWxkZXIiLCJpYXQiOjE1MjQyMTA5MDQsImV4cCI6MTYxODkwNTMwNCwiYXVkIjoid2ViZ29hdC5vcmciLCJzdWIiOiJ0b21Ad2ViZ29hdC5jb20iLCJ1c2VybmFtZSI6IlRvbSIsIkVtYWlsIjoidG9tQHdlYmdvYXQuY29tIiwiUm9sZSI6WyJNYW5hZ2VyIiwiUHJvamVjdCBBZG1pbmlzdHJhdG9yIl19.m-jSyfYEsVzD3CBI6N39wZ7AcdKdp_GiO7F_Ym12u-0 +eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJXZWJHb2F0IFRva2VuIEJ1aWxkZXIiLCJpYXQiOjE1MjQyMTA5MDQsImV4cCI6MTYxODkwNTMwNCwiYXVkIjoid2ViZ29hdC5vcmciLCJzdWIiOiJ0b21Ad2ViZ29hdC5jb20iLCJ1c2VybmFtZSI6IlRvbSIsIkVtYWlsIjoidG9tQHdlYmdvYXQuY29tIiwiUm9sZSI6WyJNYW5hZ2VyIiwiUHJvamVjdCBBZG1pbmlzdHJhdG9yIl19.vPe-qQPOt78zK8wrbN1TjNJj3LeX9Qbch6oo23RUJgM ``` \ No newline at end of file diff --git a/webgoat-lessons/missing-function-ac/src/main/java/org/owasp/webgoat/plugin/MissingFunctionACYourHash.java b/webgoat-lessons/missing-function-ac/src/main/java/org/owasp/webgoat/plugin/MissingFunctionACYourHash.java index 97770e635..d830ac7a1 100644 --- a/webgoat-lessons/missing-function-ac/src/main/java/org/owasp/webgoat/plugin/MissingFunctionACYourHash.java +++ b/webgoat-lessons/missing-function-ac/src/main/java/org/owasp/webgoat/plugin/MissingFunctionACYourHash.java @@ -13,7 +13,7 @@ import org.springframework.web.bind.annotation.ResponseBody; @AssignmentPath("/access-control/user-hash") @AssignmentHints({"access-control.hash.hint1","access-control.hash.hint2","access-control.hash.hint3", "access-control.hash.hint4","access-control.hash.hint5","access-control.hash.hint6","access-control.hash.hint7", - "access-control.hash.hint8","access-control.hash.hint9"}) + "access-control.hash.hint8","access-control.hash.hint9","access-control.hash.hint10","access-control.hash.hint11","access-control.hash.hint12"}) public class MissingFunctionACYourHash extends AssignmentEndpoint { @Autowired diff --git a/webgoat-lessons/missing-function-ac/src/main/java/org/owasp/webgoat/plugin/Users.java b/webgoat-lessons/missing-function-ac/src/main/java/org/owasp/webgoat/plugin/Users.java index 26e48709d..9b01ac3d5 100644 --- a/webgoat-lessons/missing-function-ac/src/main/java/org/owasp/webgoat/plugin/Users.java +++ b/webgoat-lessons/missing-function-ac/src/main/java/org/owasp/webgoat/plugin/Users.java @@ -51,7 +51,7 @@ public class Users extends Endpoint{ userMap.put("cc", results.getString(3)); userMap.put("ccType", results.getString(4)); userMap.put("cookie", results.getString(5)); - userMap.put("loginCOunt",Integer.toString(results.getInt(6))); + userMap.put("loginCount",Integer.toString(results.getInt(6))); allUsersMap.put(id,userMap); } userSessionData.setValue("allUsers",allUsersMap); diff --git a/webgoat-lessons/missing-function-ac/src/main/resources/i18n/WebGoatLabels.properties b/webgoat-lessons/missing-function-ac/src/main/resources/i18n/WebGoatLabels.properties index 876cff6de..4533fe073 100644 --- a/webgoat-lessons/missing-function-ac/src/main/resources/i18n/WebGoatLabels.properties +++ b/webgoat-lessons/missing-function-ac/src/main/resources/i18n/WebGoatLabels.properties @@ -11,12 +11,15 @@ access-control.hidden-menus.hint3=Look for something a super-user or administato access-control.hash.success=Congrats! You really succeeded when you added the user. access-control.hash.close=Keep trying, this one may take several attempts & steps to achieve. See the hints for help. -access-control.hash.hint1=If you haven't found the hidden menus from the earlier exercise, go do that now. -access-control.hash.hint2=When you look at the users page, there is a hint that more info is viewable by a given role of user. -access-control.hash.hint3=Have you tried tampering the GET request? Can you find supported or unsupported methods? Can you trigger 500 errors? -access-control.hash.hint4=There are actually two ways to solve this one. The first involves just changing a request header. -access-control.hash.hint5=If the request to view users, were a 'service' or 'RESTful' endpoint, what would be different about it? -access-control.hash.hint6=If you're still looking for hints ... try changing the Content-type header in the GET request. -access-control.hash.hint7=The harder way involves changing the Content-type AND the method ... As well as a proper payload for the request. Look at how registration works first and extrapolate out from there. -access-control.hash.hint8=See if you can add a user with a webgoat admin role, and if more is visible once you log in as that user. -access-control.hash.hint9=If you create a new user with the admin role ... The role should include 'WEBGOAT' and 'ADMIN' in the role name. You'll have to do some guessing beyond that. \ No newline at end of file +access-control.hash.hint1=There is an easier way and a 'harder' way to achieve this, the easier way involves one simple change in a GET request. +access-control.hash.hint2= If you haven't found the hidden menus from the earlier exercise, go do that first. +access-control.hash.hint3=When you look at the users page, there is a hint that more info is viewable by a given role. +access-control.hash.hint4=For the easy way, have you tried tampering the GET request? Different content-types? +access-control.hash.hint5=For the 'easy' way, modify the GET request to /users to include 'Content-Type: application/json' +access-control.hash.hint6=Now for the harder way ... it builds on the easier way +access-control.hash.hint7=If the request to view users, were a 'service' or 'RESTful' endpoint, what would be different about it? +access-control.hash.hint8=If you're still looking for hints ... try changing the Content-type header as in the GET request. +access-control.hash.hint9=You also need to deliver a proper payload for the request (look at how registration works). This should be formatted in line with the content-type you just defined. +access-control.hash.hint10=You will want to add WEBGOAT_ADMIN for the user's role. Yes, you'd have to guess/fuzz this in a real-world setting. +access-control.hash.hint11=OK, here it is. First, create an admin user ... Change the method to POST, change the content-type to "application/json". And your payload should look something like: {"username":"newUser2","password":"newUser12","matchingPassword":"newUser12","role":"WEBGOAT_ADMIN"} +access-control.hash.hint12=Now log in as that user and bring up WebGoat/users. Copy your hash and log back in to your original account and input it there to get credit. diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson6a.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionLesson6a.java similarity index 97% rename from webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson6a.java rename to webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionLesson6a.java index 136723f8d..dd31c61cc 100644 --- a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson6a.java +++ b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionLesson6a.java @@ -1,10 +1,11 @@ -package org.owasp.webgoat.plugin.introduction; +package org.owasp.webgoat.plugin.advanced; 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.plugin.introduction.SqlInjectionLesson5a; import org.owasp.webgoat.session.DatabaseUtilities; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -55,7 +56,6 @@ public class SqlInjectionLesson6a extends AssignmentEndpoint { AttackResult completed(@RequestParam String userid_6a) throws IOException { return injectableQuery(userid_6a); // The answer: Smith' union select userid,user_name, password,cookie,cookie, cookie,userid from user_system_data -- - } protected AttackResult injectableQuery(String accountName) { diff --git a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson6b.java b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionLesson6b.java similarity index 98% rename from webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson6b.java rename to webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionLesson6b.java index 77bd7b66e..74fc5d2ad 100644 --- a/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson6b.java +++ b/webgoat-lessons/sql-injection/src/main/java/org/owasp/webgoat/plugin/advanced/SqlInjectionLesson6b.java @@ -1,5 +1,5 @@ -package org.owasp.webgoat.plugin.introduction; +package org.owasp.webgoat.plugin.advanced; import org.owasp.webgoat.assignments.AssignmentEndpoint; import org.owasp.webgoat.assignments.AssignmentPath; diff --git a/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_content6a.adoc b/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_content6a.adoc index 17e5a279d..fde2040a3 100644 --- a/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_content6a.adoc +++ b/webgoat-lessons/sql-injection/src/main/resources/lessonPlans/en/SqlInjection_content6a.adoc @@ -3,7 +3,7 @@ Lets try to exploit a join to another table. One of the tables in the WebGoat database is: ------------------------------------------------------- -CREATE TABLE user_system_data (userid varchar(5) not null primary key, +CREATE TABLE user_system_data (userid int not null primary key, user_name varchar(12), password varchar(10), cookie varchar(30)); 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 3500b8efa..344db1dbe 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 @@ -64,7 +64,7 @@ public class SqlInjectionLesson6aTest extends LessonTest { .andExpect(status().isOk()) .andExpect(jsonPath("$.lessonCompleted", is(true))) - .andExpect(jsonPath("$.feedback", containsString("dave"))); + .andExpect(jsonPath("$.feedback", containsString("passW0rD"))); } @Test diff --git a/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson6bTest.java b/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson6bTest.java index a7abd0d61..7341a6d3a 100644 --- a/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson6bTest.java +++ b/webgoat-lessons/sql-injection/src/test/java/org/owasp/webgoat/plugin/introduction/SqlInjectionLesson6bTest.java @@ -30,7 +30,7 @@ public class SqlInjectionLesson6bTest extends LessonTest { @Test public void submitCorrectPassword() throws Exception { mockMvc.perform(MockMvcRequestBuilders.post("/SqlInjection/attack6b") - .param("userid_6b", "dave")) + .param("userid_6b", "passW0rD")) .andExpect(status().isOk()).andExpect(jsonPath("$.lessonCompleted", is(true))); }